From 628a9a4b3f171c1da7d352cd6c9f2f6f7db9a30e Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 30 Dec 2024 16:39:20 +0100 Subject: [PATCH] feat: Relaxes --force enforcement on deploy an instead error in some cases --- cli/app/deploy.go | 39 ++++++++++++++++++++++++++++++--------- pkg/app/app.go | 43 +++++++++++++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/cli/app/deploy.go b/cli/app/deploy.go index e9473c51..daf0f518 100644 --- a/cli/app/deploy.go +++ b/cli/app/deploy.go @@ -10,6 +10,7 @@ import ( "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/secret" + "coopcloud.tech/tagcmp" appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/client" @@ -45,7 +46,8 @@ Please note, "upgrade"/"rollback" do not support chaos operations.`, ValidArgsFunction: func( cmd *cobra.Command, args []string, - toComplete string) ([]string, cobra.ShellCompDirective) { + toComplete string, + ) ([]string, cobra.ShellCompDirective) { switch l := len(args); l { case 0: return autocomplete.AppNameComplete() @@ -138,14 +140,6 @@ Please note, "upgrade"/"rollback" do not support chaos operations.`, } } - if deployMeta.IsDeployed { - if internal.Force || internal.Chaos { - warnMessages = append(warnMessages, fmt.Sprintf("%s is already deployed", app.Name)) - } else { - log.Fatalf("%s is already deployed", app.Name) - } - } - if !internal.Chaos && specificVersion == "" { versions, err := app.Recipe.Tags() if err != nil { @@ -188,6 +182,33 @@ Please note, "upgrade"/"rollback" do not support chaos operations.`, } } + if deployMeta.IsDeployed { + if !internal.Force { + appStatus, err := app.Status() + if err != nil { + log.Fatal(err) + } + if appStatus.Chaos && !internal.Chaos { + log.Fatalf("%s is deployed from a chaos version. Are you sure the local changes are in the current version (%s)?", app.Name, version) + } + + if version != "" && appStatus.Version != "" { + localVersion, err := tagcmp.Parse(version) + if err != nil { + log.Fatal(err) + } + remoteVersion, err := tagcmp.Parse(appStatus.Version) + if err != nil { + log.Fatal(err) + } + + if localVersion.IsLessThan(remoteVersion) { + log.Fatalf("%s is deployed at %s. Are you sure you want to downgrade to %s?", app.Name, appStatus.Version, version) + } + } + } + } + abraShEnv, err := envfile.ReadAbraShEnvVars(app.Recipe.AbraShPath) if err != nil { log.Fatal(err) diff --git a/pkg/app/app.go b/pkg/app/app.go index 25c00a99..e0b7eb36 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -89,6 +89,8 @@ type App struct { Env envfile.AppEnv Server string Path string + + status *Status } // Type aliases to make code hints easier to understand @@ -132,6 +134,19 @@ func StackName(appName string) string { return stackName } +func (a App) Status() (Status, error) { + if a.status != nil { + return *a.status, nil + } + appStatuses, err := GetAppStatuses([]App{a}, true) + if err != nil { + return Status{}, err + } + appStatus := appStatuses[a.StackName()] + a.status = &appStatus + return appStatus, nil +} + // Filters retrieves app filters for querying the container runtime. By default // it filters on all services in the app. It is also possible to pass an // otional list of service names, which get filtered instead. @@ -397,9 +412,17 @@ func SanitiseAppName(name string) string { return strings.ReplaceAll(name, ".", "_") } +type Status struct { + Status string + Version string + Chaos bool + ChaosVersion string + AutoUpdate bool +} + // GetAppStatuses queries servers to check the deployment status of given apps. -func GetAppStatuses(apps []App, MachineReadable bool) (map[string]map[string]string, error) { - statuses := make(map[string]map[string]string) +func GetAppStatuses(apps []App, MachineReadable bool) (map[string]Status, error) { + statuses := make(map[string]Status) servers := make(map[string]struct{}) for _, app := range apps { @@ -435,36 +458,32 @@ func GetAppStatuses(apps []App, MachineReadable bool) (map[string]map[string]str } for _, service := range status.Services { - result := make(map[string]string) + result := Status{} name := service.Spec.Labels[convert.LabelNamespace] if _, ok := statuses[name]; !ok { - result["status"] = "deployed" + result.Status = "deployed" } labelKey := fmt.Sprintf("coop-cloud.%s.chaos", name) chaos, ok := service.Spec.Labels[labelKey] if ok { - result["chaos"] = chaos + result.Chaos = chaos == "true" } labelKey = fmt.Sprintf("coop-cloud.%s.chaos-version", name) if chaosVersion, ok := service.Spec.Labels[labelKey]; ok { - result["chaosVersion"] = chaosVersion + result.ChaosVersion = chaosVersion } labelKey = fmt.Sprintf("coop-cloud.%s.autoupdate", name) if autoUpdate, ok := service.Spec.Labels[labelKey]; ok { - result["autoUpdate"] = autoUpdate - } else { - result["autoUpdate"] = "false" + result.AutoUpdate = autoUpdate == "true" } labelKey = fmt.Sprintf("coop-cloud.%s.version", name) if version, ok := service.Spec.Labels[labelKey]; ok { - result["version"] = version - } else { - continue + result.Version = version } statuses[name] = result -- 2.47.2