From 0af344342d5640b17ff072ca03b74e2de1d7634e Mon Sep 17 00:00:00 2001 From: Fabien FLEUREAU Date: Wed, 22 Jan 2025 16:31:59 +0100 Subject: [PATCH] feat(ENG-1883): allow to queue stop deployment request for services and env --- cmd/application_stop.go | 146 ++++++++++++++++++++++++++-------------- cmd/container_stop.go | 99 ++++++++++++++++++++------- cmd/cronjob_stop.go | 101 ++++++++++++++++++++------- cmd/database_stop.go | 101 +++++++++++++++++++++------ cmd/environment_stop.go | 25 ++++--- cmd/helm_stop.go | 98 +++++++++++++++++++++------ cmd/lifecycle_stop.go | 101 +++++++++++++++++++++------ 7 files changed, 499 insertions(+), 172 deletions(-) diff --git a/cmd/application_stop.go b/cmd/application_stop.go index 093abf87..7c640c7e 100644 --- a/cmd/application_stop.go +++ b/cmd/application_stop.go @@ -3,6 +3,7 @@ package cmd import ( "context" "fmt" + "github.com/qovery/qovery-client-go" "os" "strings" "time" @@ -20,35 +21,41 @@ var applicationStopCmd = &cobra.Command{ utils.Capture(cmd) tokenType, token, err := utils.GetAccessToken() - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - - if applicationName == "" && applicationNames == "" { - utils.PrintlnError(fmt.Errorf("use either --application \"\" or --applications \", \" but not both at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - - if applicationName != "" && applicationNames != "" { - utils.PrintlnError(fmt.Errorf("you can't use --application and --applications at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } + checkError(err) + validateApplicationArguments(applicationName, applicationNames) client := utils.GetQoveryClient(tokenType, token) - _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) - - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + organizationId, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + checkError(err) + + if isDeploymentQueueEnabledForOrganization(organizationId) { + serviceIds := buildServiceIdsFromApplicationNames(client, envId, applicationName, applicationNames) + _, err := client.EnvironmentActionsAPI. + StopSelectedServices(context.Background(), envId). + EnvironmentServiceIdsAllRequest(qovery.EnvironmentServiceIdsAllRequest{ + ApplicationIds: serviceIds, + }). + Execute() + checkError(err) + if watchFlag { + utils.WatchEnvironment(envId, "unused", client) + } else { + if applicationName != "" { + utils.Println(fmt.Sprintf("Request to stop application %s has been queued...", pterm.FgBlue.Sprintf("%s", applicationName))) + } else { + utils.Println(fmt.Sprintf("Request to stop applications %s has been queued...", pterm.FgBlue.Sprintf("%s", applicationNames))) + } + } + return } + // TODO once deployment queue is enabled for all organizations, remove the following code block + applications, _, err := client.ApplicationsAPI.ListApplication(context.Background(), envId).Execute() + checkError(err) + if applicationNames != "" { // wait until service is ready + // TODO: this is not needed since we can put the deployment request in queue for { if utils.IsEnvironmentInATerminalState(envId, client) { break @@ -58,14 +65,6 @@ var applicationStopCmd = &cobra.Command{ time.Sleep(5 * time.Second) } - applications, _, err := client.ApplicationsAPI.ListApplication(context.Background(), envId).Execute() - - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - var serviceIds []string for _, applicationName := range strings.Split(applicationNames, ",") { trimmedApplicationName := strings.TrimSpace(applicationName) @@ -81,23 +80,10 @@ var applicationStopCmd = &cobra.Command{ utils.Println(fmt.Sprintf("Stopping applications %s in progress..", pterm.FgBlue.Sprintf("%s", applicationNames))) } - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - + checkError(err) return } - applications, _, err := client.ApplicationsAPI.ListApplication(context.Background(), envId).Execute() - - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - application := utils.FindByApplicationName(applications.GetResults(), applicationName) if application == nil { @@ -109,11 +95,7 @@ var applicationStopCmd = &cobra.Command{ msg, err := utils.StopService(client, envId, application.Id, utils.ApplicationType, watchFlag) - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } + checkError(err) if msg != "" { utils.PrintlnInfo(msg) @@ -128,6 +110,70 @@ var applicationStopCmd = &cobra.Command{ }, } +func buildServiceIdsFromApplicationNames( + client *qovery.APIClient, + environmentId string, + applicationName string, + applicationNames string, +) []string { + var serviceIds []string + applications, _, err := client.ApplicationsAPI.ListApplication(context.Background(), environmentId).Execute() + checkError(err) + + if applicationName != "" { + application := utils.FindByApplicationName(applications.GetResults(), applicationName) + if application == nil { + utils.PrintlnError(fmt.Errorf("application %s not found", applicationName)) + utils.PrintlnInfo("You can list all applications with: qovery application list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, application.Id) + } + if applicationNames != "" { + for _, applicationName := range strings.Split(applicationNames, ",") { + trimmedApplicationName := strings.TrimSpace(applicationName) + application := utils.FindByApplicationName(applications.GetResults(), trimmedApplicationName) + if application == nil { + utils.PrintlnError(fmt.Errorf("application %s not found", applicationName)) + utils.PrintlnInfo("You can list all applications with: qovery application list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, application.Id) + } + } + + return serviceIds +} + +func isDeploymentQueueEnabledForOrganization(organizationId string) bool { + return organizationId == "3f421018-8edf-4a41-bb86-bec62791b6dc" || // backdev + organizationId == "3d542888-3d2c-474a-b1ad-712556db66da" // QSandbox +} + +func validateApplicationArguments(applicationName string, applicationNames string) { + if applicationName == "" && applicationNames == "" { + utils.PrintlnError(fmt.Errorf("use either --application \"\" or --applications \", \" but not both at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + if applicationName != "" && applicationNames != "" { + utils.PrintlnError(fmt.Errorf("you can't use --application and --applications at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } +} + +func checkError(err error) { + if err != nil { + utils.PrintlnError(err) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } +} + func init() { applicationCmd.AddCommand(applicationStopCmd) applicationStopCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name") diff --git a/cmd/container_stop.go b/cmd/container_stop.go index 0196031a..386c545b 100644 --- a/cmd/container_stop.go +++ b/cmd/container_stop.go @@ -3,6 +3,7 @@ package cmd import ( "context" "fmt" + "github.com/qovery/qovery-client-go" "os" "strings" "time" @@ -20,31 +21,32 @@ var containerStopCmd = &cobra.Command{ utils.Capture(cmd) tokenType, token, err := utils.GetAccessToken() - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - - if containerName == "" && containerNames == "" { - utils.PrintlnError(fmt.Errorf("use either --container \"\" or --containers \", \" but not both at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - - if containerName != "" && containerNames != "" { - utils.PrintlnError(fmt.Errorf("you can't use --container and --containers at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } + checkError(err) + validateContainerArguments(containerName, containerNames) client := utils.GetQoveryClient(tokenType, token) - _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) - - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + organizationId, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + checkError(err) + + if isDeploymentQueueEnabledForOrganization(organizationId) { + serviceIds := buildServiceIdsFromContainerNames(client, envId, containerName, containerNames) + _, err := client.EnvironmentActionsAPI. + StopSelectedServices(context.Background(), envId). + EnvironmentServiceIdsAllRequest(qovery.EnvironmentServiceIdsAllRequest{ + ContainerIds: serviceIds, + }). + Execute() + checkError(err) + if watchFlag { + utils.WatchEnvironment(envId, "unused", client) + } else { + if containerName != "" { + utils.Println(fmt.Sprintf("Request to stop container %s has been queued...", pterm.FgBlue.Sprintf("%s", containerName))) + } else { + utils.Println(fmt.Sprintf("Request to stop containers %s has been queued...", pterm.FgBlue.Sprintf("%s", containerNames))) + } + } + return } if containerNames != "" { @@ -128,6 +130,57 @@ var containerStopCmd = &cobra.Command{ }, } +func buildServiceIdsFromContainerNames( + client *qovery.APIClient, + environmentId string, + containerName string, + containerNames string, +) []string { + var serviceIds []string + containers, _, err := client.ContainersAPI.ListContainer(context.Background(), environmentId).Execute() + checkError(err) + + if containerName != "" { + container := utils.FindByContainerName(containers.GetResults(), containerName) + if container == nil { + utils.PrintlnError(fmt.Errorf("container %s not found", containerName)) + utils.PrintlnInfo("You can list all containers with: qovery container list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, container.Id) + } + if containerNames != "" { + for _, containerName := range strings.Split(containerNames, ",") { + trimmedContainerName := strings.TrimSpace(containerName) + container := utils.FindByContainerName(containers.GetResults(), trimmedContainerName) + if container == nil { + utils.PrintlnError(fmt.Errorf("container %s not found", containerName)) + utils.PrintlnInfo("You can list all containers with: qovery container list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, container.Id) + } + } + + return serviceIds +} + +func validateContainerArguments(containerName string, containerNames string) { + if containerName == "" && containerNames == "" { + utils.PrintlnError(fmt.Errorf("use either --container \"\" or --containers \", \" but not both at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + if containerName != "" && containerNames != "" { + utils.PrintlnError(fmt.Errorf("you can't use --container and --containers at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } +} + func init() { containerCmd.AddCommand(containerStopCmd) containerStopCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name") diff --git a/cmd/cronjob_stop.go b/cmd/cronjob_stop.go index 23e521ea..b88120e5 100644 --- a/cmd/cronjob_stop.go +++ b/cmd/cronjob_stop.go @@ -1,7 +1,9 @@ package cmd import ( + "context" "fmt" + "github.com/qovery/qovery-client-go" "os" "strings" "time" @@ -20,32 +22,34 @@ var cronjobStopCmd = &cobra.Command{ utils.Capture(cmd) tokenType, token, err := utils.GetAccessToken() - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - - if cronjobName == "" && cronjobNames == "" { - utils.PrintlnError(fmt.Errorf("use either --cronjob \"\" or --cronjobs \", \" but not both at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - - if cronjobName != "" && cronjobNames != "" { - utils.PrintlnError(fmt.Errorf("you can't use --cronjob and --cronjobs at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } + checkError(err) + validateCronjobArguments(cronjobName, cronjobNames) client := utils.GetQoveryClient(tokenType, token) - _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) - - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + organizationId, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + checkError(err) + + if isDeploymentQueueEnabledForOrganization(organizationId) { + serviceIds := buildServiceIdsFromCronjobNames(client, envId, cronjobName, cronjobNames) + _, err := client.EnvironmentActionsAPI. + StopSelectedServices(context.Background(), envId). + EnvironmentServiceIdsAllRequest(qovery.EnvironmentServiceIdsAllRequest{ + JobIds: serviceIds, + }). + Execute() + checkError(err) + if watchFlag { + utils.WatchEnvironment(envId, "unused", client) + } else { + if cronjobName != "" { + utils.Println(fmt.Sprintf("Request to stop cronjob %s has been queued...", pterm.FgBlue.Sprintf("%s", cronjobName))) + } else { + utils.Println(fmt.Sprintf("Request to stop cronjobs %s has been queued...", pterm.FgBlue.Sprintf("%s", cronjobNames))) + } + } + return } + // TODO once deployment queue is enabled for all organizations, remove the following code block if cronjobNames != "" { // wait until service is ready @@ -128,6 +132,57 @@ var cronjobStopCmd = &cobra.Command{ }, } +func buildServiceIdsFromCronjobNames( + client *qovery.APIClient, + environmentId string, + cronjobName string, + cronjobNames string, +) []string { + var serviceIds []string + cronjobs, _, err := client.JobsAPI.ListJobs(context.Background(), environmentId).Execute() + checkError(err) + + if cronjobName != "" { + cronjob := utils.FindByJobName(cronjobs.GetResults(), cronjobName) + if cronjob == nil || cronjob.CronJobResponse == nil { + utils.PrintlnError(fmt.Errorf("cronjob %s not found", cronjobName)) + utils.PrintlnInfo("You can list all cronjobs with: qovery cronjob list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, cronjob.CronJobResponse.Id) + } + if cronjobNames != "" { + for _, cronjobName := range strings.Split(cronjobNames, ",") { + trimmedCronjobName := strings.TrimSpace(cronjobName) + cronjob := utils.FindByJobName(cronjobs.GetResults(), trimmedCronjobName) + if cronjob == nil || cronjob.CronJobResponse == nil { + utils.PrintlnError(fmt.Errorf("cronjob %s not found", cronjobName)) + utils.PrintlnInfo("You can list all cronjobs with: qovery cronjob list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, cronjob.CronJobResponse.Id) + } + } + + return serviceIds +} + +func validateCronjobArguments(cronJobName string, cronJobNames string) { + if cronJobName == "" && cronJobNames == "" { + utils.PrintlnError(fmt.Errorf("use either --cronjob \"\" or --cronjobs \", \" but not both at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + if cronJobName != "" && cronJobNames != "" { + utils.PrintlnError(fmt.Errorf("you can't use --cronjob and --cronjobs at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } +} + func init() { cronjobCmd.AddCommand(cronjobStopCmd) cronjobStopCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name") diff --git a/cmd/database_stop.go b/cmd/database_stop.go index fa3da3b0..9f6443af 100644 --- a/cmd/database_stop.go +++ b/cmd/database_stop.go @@ -3,6 +3,7 @@ package cmd import ( "context" "fmt" + "github.com/qovery/qovery-client-go" "os" "strings" "time" @@ -20,33 +21,38 @@ var databaseStopCmd = &cobra.Command{ utils.Capture(cmd) tokenType, token, err := utils.GetAccessToken() - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } + checkError(err) - if databaseName == "" && databaseNames == "" { - utils.PrintlnError(fmt.Errorf("use either --database \"\" or --databases \", \" but not both at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - - if databaseName != "" && databaseNames != "" { - utils.PrintlnError(fmt.Errorf("you can't use --database and --databases at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } + validateDatabaseArguments(databaseName, databaseNames) client := utils.GetQoveryClient(tokenType, token) - _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) - - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + organizationId, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + + checkError(err) + + if isDeploymentQueueEnabledForOrganization(organizationId) { + serviceIds := buildServiceIdsFromDatabaseNames(client, envId, databaseName, databaseNames) + _, err := client.EnvironmentActionsAPI. + StopSelectedServices(context.Background(), envId). + EnvironmentServiceIdsAllRequest(qovery.EnvironmentServiceIdsAllRequest{ + DatabaseIds: serviceIds, + }). + Execute() + checkError(err) + if watchFlag { + utils.WatchEnvironment(envId, "unused", client) + } else { + if databaseName != "" { + utils.Println(fmt.Sprintf("Request to stop database %s has been queued...", pterm.FgBlue.Sprintf("%s", databaseName))) + } else { + utils.Println(fmt.Sprintf("Request to stop databases %s has been queued...", pterm.FgBlue.Sprintf("%s", databaseNames))) + } + } + return } + // TODO once deployment queue is enabled for all organizations, remove the following code block + if databaseNames != "" { // wait until service is ready for { @@ -128,6 +134,57 @@ var databaseStopCmd = &cobra.Command{ }, } +func buildServiceIdsFromDatabaseNames( + client *qovery.APIClient, + environmentId string, + databaseName string, + databaseNames string, +) []string { + var serviceIds []string + databases, _, err := client.DatabasesAPI.ListDatabase(context.Background(), environmentId).Execute() + checkError(err) + + if databaseName != "" { + database := utils.FindByDatabaseName(databases.GetResults(), databaseName) + if database == nil { + utils.PrintlnError(fmt.Errorf("database %s not found", databaseName)) + utils.PrintlnInfo("You can list all databases with: qovery database list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, database.Id) + } + if databaseNames != "" { + for _, databaseName := range strings.Split(databaseNames, ",") { + trimmedDatabaseName := strings.TrimSpace(databaseName) + database := utils.FindByDatabaseName(databases.GetResults(), trimmedDatabaseName) + if database == nil { + utils.PrintlnError(fmt.Errorf("database %s not found", databaseName)) + utils.PrintlnInfo("You can list all databases with: qovery database list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, database.Id) + } + } + + return serviceIds +} + +func validateDatabaseArguments(databaseName string, databaseNames string) { + if databaseName == "" && databaseNames == "" { + utils.PrintlnError(fmt.Errorf("use either --database \"\" or --databases \", \" but not both at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + if databaseName != "" && databaseNames != "" { + utils.PrintlnError(fmt.Errorf("you can't use --database and --databases at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } +} + func init() { databaseCmd.AddCommand(databaseStopCmd) databaseStopCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name") diff --git a/cmd/environment_stop.go b/cmd/environment_stop.go index baf99f7e..420ffbb8 100644 --- a/cmd/environment_stop.go +++ b/cmd/environment_stop.go @@ -20,21 +20,26 @@ var environmentStopCmd = &cobra.Command{ utils.Capture(cmd) tokenType, token, err := utils.GetAccessToken() - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } + checkError(err) client := utils.GetQoveryClient(tokenType, token) - _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + organizationId, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + checkError(err) - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + if isDeploymentQueueEnabledForOrganization(organizationId) { + + _, _, err = client.EnvironmentActionsAPI.StopEnvironment(context.Background(), envId).Execute() + checkError(err) + utils.Println("Environment stop request has been queued.") + + if watchFlag { + utils.WatchEnvironment(envId, "unused", client) + } + return } + // TODO once deployment queue is enabled for all organizations, remove the following code block + // wait until service is ready for { if utils.IsEnvironmentInATerminalState(envId, client) { diff --git a/cmd/helm_stop.go b/cmd/helm_stop.go index c854d5b7..511c857f 100644 --- a/cmd/helm_stop.go +++ b/cmd/helm_stop.go @@ -21,33 +21,36 @@ var helmStopCmd = &cobra.Command{ utils.Capture(cmd) tokenType, token, err := utils.GetAccessToken() - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } + checkError(err) - if helmName == "" && helmNames == "" { - utils.PrintlnError(fmt.Errorf("use either --helm \"\" or --helms \", \" but not both at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - - if helmName != "" && helmNames != "" { - utils.PrintlnError(fmt.Errorf("you can't use --helm and --helms at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } + validateHelmArguments(helmName, helmNames) client := utils.GetQoveryClient(tokenType, token) - _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) - - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + organizationId, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + checkError(err) + + if isDeploymentQueueEnabledForOrganization(organizationId) { + serviceIds := buildServiceIdsFromHelmNames(client, envId, helmName, helmNames) + _, err := client.EnvironmentActionsAPI. + StopSelectedServices(context.Background(), envId). + EnvironmentServiceIdsAllRequest(qovery.EnvironmentServiceIdsAllRequest{ + HelmIds: serviceIds, + }). + Execute() + checkError(err) + if watchFlag { + utils.WatchEnvironment(envId, "unused", client) + } else { + if helmName != "" { + utils.Println(fmt.Sprintf("Request to stop helm %s has been queued...", pterm.FgBlue.Sprintf("%s", helmName))) + } else { + utils.Println(fmt.Sprintf("Request to stop helms %s has been queued...", pterm.FgBlue.Sprintf("%s", helmNames))) + } + } + return } + // TODO once deployment queue is enabled for all organizations, remove the following code block if helmNames != "" { // wait until service is ready for { @@ -137,6 +140,57 @@ var helmStopCmd = &cobra.Command{ }, } +func buildServiceIdsFromHelmNames( + client *qovery.APIClient, + environmentId string, + helmName string, + helmNames string, +) []string { + var serviceIds []string + helms, _, err := client.HelmsAPI.ListHelms(context.Background(), environmentId).Execute() + checkError(err) + + if helmName != "" { + helm := utils.FindByHelmName(helms.GetResults(), helmName) + if helm == nil { + utils.PrintlnError(fmt.Errorf("helm %s not found", helmName)) + utils.PrintlnInfo("You can list all helms with: qovery helm list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, helm.Id) + } + if helmNames != "" { + for _, helmName := range strings.Split(helmNames, ",") { + trimmedHelmName := strings.TrimSpace(helmName) + helm := utils.FindByHelmName(helms.GetResults(), trimmedHelmName) + if helm == nil { + utils.PrintlnError(fmt.Errorf("helm %s not found", helmName)) + utils.PrintlnInfo("You can list all helms with: qovery helm list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, helm.Id) + } + } + + return serviceIds +} + +func validateHelmArguments(helmName string, helmNames string) { + if helmName == "" && helmNames == "" { + utils.PrintlnError(fmt.Errorf("use either --helm \"\" or --helms \", \" but not both at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + if helmName != "" && helmNames != "" { + utils.PrintlnError(fmt.Errorf("you can't use --helm and --helms at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } +} + func init() { helmCmd.AddCommand(helmStopCmd) helmStopCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name") diff --git a/cmd/lifecycle_stop.go b/cmd/lifecycle_stop.go index da676b45..82f47a91 100644 --- a/cmd/lifecycle_stop.go +++ b/cmd/lifecycle_stop.go @@ -1,7 +1,9 @@ package cmd import ( + "context" "fmt" + "github.com/qovery/qovery-client-go" "os" "strings" "time" @@ -20,33 +22,37 @@ var lifecycleStopCmd = &cobra.Command{ utils.Capture(cmd) tokenType, token, err := utils.GetAccessToken() - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } + checkError(err) - if lifecycleName == "" && lifecycleNames == "" { - utils.PrintlnError(fmt.Errorf("use either --lifecycle \"\" or --lifecycles \", \" but not both at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } - - if lifecycleName != "" && lifecycleNames != "" { - utils.PrintlnError(fmt.Errorf("you can't use --lifecycle and --lifecycles at the same time")) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 - } + validateLifecycleArguments(lifecycleName, lifecycleNames) client := utils.GetQoveryClient(tokenType, token) - _, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) - - if err != nil { - utils.PrintlnError(err) - os.Exit(1) - panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + organizationId, _, envId, err := getOrganizationProjectEnvironmentContextResourcesIds(client) + checkError(err) + + if isDeploymentQueueEnabledForOrganization(organizationId) { + serviceIds := buildServiceIdsFromLifecycleNames(client, envId, lifecycleName, lifecycleNames) + _, err := client.EnvironmentActionsAPI. + StopSelectedServices(context.Background(), envId). + EnvironmentServiceIdsAllRequest(qovery.EnvironmentServiceIdsAllRequest{ + JobIds: serviceIds, + }). + Execute() + checkError(err) + if watchFlag { + utils.WatchEnvironment(envId, "unused", client) + } else { + if lifecycleName != "" { + utils.Println(fmt.Sprintf("Request to stop lifecyclejob %s has been queued...", pterm.FgBlue.Sprintf("%s", lifecycleName))) + } else { + utils.Println(fmt.Sprintf("Request to stop lifecyclejobs %s has been queued...", pterm.FgBlue.Sprintf("%s", lifecycleNames))) + } + } + return } + // TODO once deployment queue is enabled for all organizations, remove the following code block + if lifecycleNames != "" { // wait until service is ready for { @@ -128,6 +134,57 @@ var lifecycleStopCmd = &cobra.Command{ }, } +func buildServiceIdsFromLifecycleNames( + client *qovery.APIClient, + environmentId string, + lifecycleName string, + lifecycleNames string, +) []string { + var serviceIds []string + lifecycles, _, err := client.JobsAPI.ListJobs(context.Background(), environmentId).Execute() + checkError(err) + + if lifecycleName != "" { + lifecycle := utils.FindByJobName(lifecycles.GetResults(), lifecycleName) + if lifecycle == nil || lifecycle.LifecycleJobResponse == nil { + utils.PrintlnError(fmt.Errorf("lifecycle %s not found", lifecycleName)) + utils.PrintlnInfo("You can list all lifecycles with: qovery lifecycle list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, lifecycle.LifecycleJobResponse.Id) + } + if lifecycleNames != "" { + for _, lifecycleName := range strings.Split(lifecycleNames, ",") { + trimmedLifecycleName := strings.TrimSpace(lifecycleName) + lifecycle := utils.FindByJobName(lifecycles.GetResults(), trimmedLifecycleName) + if lifecycle == nil || lifecycle.LifecycleJobResponse == nil { + utils.PrintlnError(fmt.Errorf("lifecycle %s not found", lifecycleName)) + utils.PrintlnInfo("You can list all lifecycles with: qovery lifecycle list") + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + serviceIds = append(serviceIds, lifecycle.LifecycleJobResponse.Id) + } + } + + return serviceIds +} + +func validateLifecycleArguments(lifecycleName string, lifecycleNames string) { + if lifecycleName == "" && lifecycleNames == "" { + utils.PrintlnError(fmt.Errorf("use either --lifecycle \"\" or --lifecycles \", \" but not both at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } + + if lifecycleName != "" && lifecycleNames != "" { + utils.PrintlnError(fmt.Errorf("you can't use --lifecycle and --lifecycles at the same time")) + os.Exit(1) + panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011 + } +} + func init() { lifecycleCmd.AddCommand(lifecycleStopCmd) lifecycleStopCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name")