Skip to content

Commit

Permalink
feat: allow deploy env to skip stopped services
Browse files Browse the repository at this point in the history
Adding `--skip-paused-services` flag to `environment deploy` command
allowing to deploy all services from an environment but skip paused
services.

Ticket: ENG-1708
  • Loading branch information
benjaminch committed Mar 19, 2024
1 parent cbbb271 commit a14c22b
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 7 deletions.
109 changes: 103 additions & 6 deletions cmd/environment_deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import (
"fmt"
"github.com/pterm/pterm"
"os"
"slices"
"time"

"github.com/qovery/qovery-cli/utils"
"github.com/qovery/qovery-client-go"
"github.com/spf13/cobra"
)

var skipPausedServicesFlag bool

var environmentDeployCmd = &cobra.Command{
Use: "deploy",
Short: "Deploy an environment",
Expand Down Expand Up @@ -44,26 +47,120 @@ var environmentDeployCmd = &cobra.Command{
time.Sleep(5 * time.Second)
}

_, _, err = client.EnvironmentActionsAPI.DeployEnvironment(context.Background(), envId).Execute()
if skipPausedServicesFlag {
// Paused services shouldn't be deployed, let's gather services status
servicesIDsToDeploy, err := getEnvironmentServices(client, envId, []qovery.StateEnum{qovery.STATEENUM_STOPPED})
if err != nil {
utils.PrintlnError(err)
os.Exit(1)
panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011
}

if err != nil {
utils.PrintlnError(err)
os.Exit(1)
panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011
// Deploy the non stopped services from the env
request := qovery.DeployAllRequest{}
// Adding services to be deployed
for _, applicationID := range servicesIDsToDeploy.ApplicationsIDs {
request.Applications = append(request.Applications, qovery.DeployAllRequestApplicationsInner {ApplicationId: applicationID})
utils.Println(fmt.Sprintf("Application %s is deploying!", applicationID))
}
for _, containerID := range servicesIDsToDeploy.ContainersIDs {
request.Containers = append(request.Containers, qovery.DeployAllRequestContainersInner {Id: containerID})
utils.Println(fmt.Sprintf("Container %s is deploying!", containerID))
}
for _, helmID := range servicesIDsToDeploy.HelmsIDs {
request.Helms = append(request.Helms, qovery.DeployAllRequestHelmsInner{Id: &helmID})
utils.Println(fmt.Sprintf("Helm %s is deploying!", helmID))
}
for _, jobID := range servicesIDsToDeploy.JobsIDs {
request.Jobs = append(request.Jobs, qovery.DeployAllRequestJobsInner{Id: &jobID})
utils.Println(fmt.Sprintf("Job %s is deploying!", jobID))
}
for _, databaseID := range servicesIDsToDeploy.DatabasesIDs {
request.Databases = append(request.Databases, databaseID)
utils.Println(fmt.Sprintf("Database %s is deploying!", databaseID))
}

_, _, err = client.EnvironmentActionsAPI.DeployAllServices(context.Background(), envId).DeployAllRequest(request).Execute()
if err != nil {
utils.PrintlnError(err)
os.Exit(1)
panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011
}

} else {
// Deploy the whole env
_, _, err = client.EnvironmentActionsAPI.DeployEnvironment(context.Background(), envId).Execute()
if err != nil {
utils.PrintlnError(err)
os.Exit(1)
panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011
}
utils.Println("Environment is deploying!")
}

utils.Println("Environment is deploying!")

if watchFlag {
utils.WatchEnvironment(envId, qovery.STATEENUM_DEPLOYED, client)
}
},
}

type Services struct {
ApplicationsIDs []string
ContainersIDs []string
HelmsIDs []string
JobsIDs []string
DatabasesIDs []string
}

func getEnvironmentServices(client *qovery.APIClient, envId string, servicesStatusesToExclude []qovery.StateEnum) (Services, error) {
nonStoppedServices := Services {
ApplicationsIDs: make([]string, 0),
ContainersIDs: make([]string, 0),
HelmsIDs: make([]string, 0),
JobsIDs: make([]string, 0),
DatabasesIDs: make([]string, 0),
}
envStatuses, _, err := client.EnvironmentMainCallsAPI.GetEnvironmentStatuses(context.Background(), envId).Execute()
if err != nil {
return nonStoppedServices, err
}

// Gather all non stopped services
for _, serviceStatus := range envStatuses.Applications {
if !slices.Contains(servicesStatusesToExclude, serviceStatus.GetState()) {
nonStoppedServices.ApplicationsIDs = append(nonStoppedServices.ApplicationsIDs, serviceStatus.Id)
}
}
for _, serviceStatus := range envStatuses.Containers {
if !slices.Contains(servicesStatusesToExclude, serviceStatus.GetState()) {
nonStoppedServices.ContainersIDs = append(nonStoppedServices.ContainersIDs, serviceStatus.Id)
}
}
for _, serviceStatus := range envStatuses.Helms {
if !slices.Contains(servicesStatusesToExclude, serviceStatus.GetState()) {
nonStoppedServices.HelmsIDs = append(nonStoppedServices.HelmsIDs, serviceStatus.Id)
}
}
for _, serviceStatus := range envStatuses.Jobs {
if !slices.Contains(servicesStatusesToExclude, serviceStatus.GetState()) {
nonStoppedServices.JobsIDs = append(nonStoppedServices.JobsIDs, serviceStatus.Id)
}
}
for _, serviceStatus := range envStatuses.Databases {
if !slices.Contains(servicesStatusesToExclude, serviceStatus.GetState()) {
nonStoppedServices.DatabasesIDs = append(nonStoppedServices.DatabasesIDs, serviceStatus.Id)
}
}

return nonStoppedServices, nil
}

func init() {
environmentCmd.AddCommand(environmentDeployCmd)
environmentDeployCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name")
environmentDeployCmd.Flags().StringVarP(&projectName, "project", "", "", "Project Name")
environmentDeployCmd.Flags().StringVarP(&environmentName, "environment", "", "", "Environment Name")
environmentDeployCmd.Flags().BoolVarP(&watchFlag, "watch", "w", false, "Watch environment status until it's ready or an error occurs")
environmentDeployCmd.Flags().BoolVarP(&skipPausedServicesFlag, "skip-paused-services", "", false, "Skip paused services: paused services won't be started / deployed")
}
119 changes: 119 additions & 0 deletions cmd/environment_statuses.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package cmd

import (
"context"
"encoding/json"
"fmt"
"github.com/qovery/qovery-cli/utils"
"github.com/spf13/cobra"
"os"
)

var environmentServicesStatusesCmd = &cobra.Command{
Use: "statuses",
Short: "Get environment services statuses",
Run: func(cmd *cobra.Command, args []string) {
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
}

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
}

// Get env and services statuses
statuses, _, err := client.EnvironmentMainCallsAPI.GetEnvironmentStatuses(context.Background(), envId).Execute()

if err != nil {
utils.PrintlnError(err)
os.Exit(1)
panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011
}

if jsonFlag {
j, err := json.Marshal(statuses)

if err != nil {
utils.PrintlnError(err)
os.Exit(1)
panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011
}
utils.Println(string(j))
return
}

if statuses.Environment == nil {
utils.PrintlnError(fmt.Errorf("environment status not found for `%s`", envId))
os.Exit(1)
panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011
}

var data [][]string
for _, status := range statuses.Applications{
data = append(data, []string{
"application",
status.Id,
string(status.GetState()),
})
}
for _, status := range statuses.Containers{
data = append(data, []string{
"container",
status.Id,
string(status.GetState()),
})
}
for _, status := range statuses.Helms{
data = append(data, []string{
"helm",
status.Id,
string(status.GetState()),
})
}
for _, status := range statuses.Jobs{
data = append(data, []string{
"job",
status.Id,
string(status.GetState()),
})
}
for _, status := range statuses.Databases{
data = append(data, []string{
"database",
status.Id,
string(status.GetState()),
})
}

utils.Println(fmt.Sprintf("\nEnvironment status: %s \n", statuses.Environment.GetState()))
err = utils.PrintTable([]string{
"Type",
"ID",
"Status",
}, data)

if err != nil {
utils.PrintlnError(fmt.Errorf("cannot print services statuses", err))
os.Exit(1)
panic("unreachable") // staticcheck false positive: https://staticcheck.io/docs/checks#SA5011
}
},
}

func init() {
environmentCmd.AddCommand(environmentServicesStatusesCmd)
environmentServicesStatusesCmd.Flags().StringVarP(&organizationName, "organization", "", "", "Organization Name")
environmentServicesStatusesCmd.Flags().StringVarP(&projectName, "project", "", "", "Project Name")
environmentServicesStatusesCmd.Flags().StringVarP(&environmentName, "environment", "", "", "Environment Name")
environmentServicesStatusesCmd.Flags().BoolVarP(&jsonFlag, "json", "", false, "JSON output")
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.19

require (
github.com/AlecAivazis/survey/v2 v2.3.6
github.com/appscode/go-querystring v0.0.0-20170504095604-0126cfb3f1dc
github.com/containerd/console v1.0.3
github.com/fatih/color v1.14.1
github.com/getsentry/sentry-go v0.19.0
Expand Down Expand Up @@ -32,7 +33,6 @@ require (
atomicgo.dev/cursor v0.1.1 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/appscode/go-querystring v0.0.0-20170504095604-0126cfb3f1dc // indirect
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
Expand Down

0 comments on commit a14c22b

Please sign in to comment.