From f6b139dfea3c0bb8434d678deb9add7a38c6558b Mon Sep 17 00:00:00 2001 From: decentral1se Date: Wed, 8 Feb 2023 23:19:14 +0100 Subject: [PATCH] chore: formatting pass on kadabra [ci skip] --- cli/cli.go | 1 + cli/updater/updater.go | 118 +++++++++++++++++++++++++++++++---------- 2 files changed, 90 insertions(+), 29 deletions(-) diff --git a/cli/cli.go b/cli/cli.go index 5d63b471..51c2342c 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -189,6 +189,7 @@ func newAbraApp(version, commit string) *cli.App { return nil } + return app } diff --git a/cli/updater/updater.go b/cli/updater/updater.go index bbd31862..1692898e 100644 --- a/cli/updater/updater.go +++ b/cli/updater/updater.go @@ -40,7 +40,7 @@ var allFlag = &cli.BoolFlag{ Destination: &updateAll, } -// Check for available upgrades +// Notify checks for available upgrades var Notify = cli.Command{ Name: "notify", Aliases: []string{"n"}, @@ -49,24 +49,31 @@ var Notify = cli.Command{ internal.DebugFlag, majorFlag, }, - Before: internal.SubCommandBefore, - Description: `It reads the deployed app versions and looks for new versions in the recipe catalogue. If a new patch/minor version is available, a notification is printed. To include major versions use the --major flag.`, + Before: internal.SubCommandBefore, + Description: ` +It reads the deployed app versions and looks for new versions in the recipe +catalogue. If a new patch/minor version is available, a notification is +printed. To include major versions use the --major flag. +`, Action: func(c *cli.Context) error { cl, err := client.New("default") if err != nil { logrus.Fatal(err) } + stacks, err := stack.GetStacks(cl) if err != nil { logrus.Fatal(err) } + for _, stackInfo := range stacks { stackName := stackInfo.Name recipeName, err := getLabel(cl, stackName, "recipe") if err != nil { logrus.Fatal(err) } + if recipeName != "" { _, err = getLatestUpgrade(cl, stackName, recipeName) if err != nil { @@ -74,24 +81,33 @@ var Notify = cli.Command{ } } } + return nil }, } -// Upgrade apps +// UpgradeApp upgrades apps. var UpgradeApp = cli.Command{ Name: "upgrade", Aliases: []string{"u"}, Usage: "Upgrade apps", - ArgsUsage: " ", + ArgsUsage: " ", Flags: []cli.Flag{ internal.DebugFlag, internal.ChaosFlag, majorFlag, allFlag, }, - Before: internal.SubCommandBefore, - Description: `Upgrade an app by specifying its stack name and recipe. By passing --all instead every deployed app is upgraded. For each apps with enabled auto updates the deployed version is compared with the current recipe catalogue version. If a new patch/minor version is available the app is upgraded. To include major versions use the --major flag. Don't do that, it will probably break things. Only apps that are not deployed with --chaos are upgraded, to update chaos deployments use the --chaos flag. Use it with care.`, + Before: internal.SubCommandBefore, + Description: ` +Upgrade an app by specifying its stack name and recipe. By passing "--all" +instead, every deployed app is upgraded. For each apps with enabled auto +updates the deployed version is compared with the current recipe catalogue +version. If a new patch/minor version is available, the app is upgraded. To +include major versions use the "--major" flag. Don't do that, it will probably +break things. Only apps that are not deployed with "--chaos" are upgraded, to +update chaos deployments use the "--chaos" flag. Use it with care. +`, Action: func(c *cli.Context) error { cl, err := client.New("default") if err != nil { @@ -105,6 +121,7 @@ var UpgradeApp = cli.Command{ if err != nil { logrus.Fatal(err) } + return nil } @@ -112,22 +129,25 @@ var UpgradeApp = cli.Command{ if err != nil { logrus.Fatal(err) } + for _, stackInfo := range stacks { stackName := stackInfo.Name recipeName, err := getLabel(cl, stackName, "recipe") if err != nil { logrus.Fatal(err) } + err = tryUpgrade(cl, stackName, recipeName) if err != nil { logrus.Fatal(err) } } + return nil }, } -// getLabel reads docker label in the format coop-cloud.${STACK_NAME}.${LABEL} +// getLabel reads docker labels in the format of "coop-cloud.${STACK_NAME}.${LABEL}". func getLabel(cl *dockerclient.Client, stackName string, label string) (string, error) { filter := filters.NewArgs() filter.Add("label", fmt.Sprintf("%s=%s", convert.LabelNamespace, stackName)) @@ -136,34 +156,41 @@ func getLabel(cl *dockerclient.Client, stackName string, label string) (string, if err != nil { return "", err } + for _, service := range services { labelKey := fmt.Sprintf("coop-cloud.%s.%s", stackName, label) if labelValue, ok := service.Spec.Labels[labelKey]; ok { return labelValue, nil } } + logrus.Debugf("no %s label found for %s", label, stackName) + return "", nil } -// getBoolLabel reads a boolean docker label +// getBoolLabel reads a boolean docker label. func getBoolLabel(cl *dockerclient.Client, stackName string, label string) (bool, error) { lableValue, err := getLabel(cl, stackName, label) if err != nil { return false, err } + if lableValue != "" { value, err := strconv.ParseBool(lableValue) if err != nil { return false, err } + return value, nil } + logrus.Debugf("Boolean label %s could not be found for %s, set default to false.", label, stackName) + return false, nil } -// getEnv reads Env variables from docker services +// getEnv reads env variables from docker services. func getEnv(cl *dockerclient.Client, stackName string) (config.AppEnv, error) { envMap := make(map[string]string) filter := filters.NewArgs() @@ -173,6 +200,7 @@ func getEnv(cl *dockerclient.Client, stackName string) (config.AppEnv, error) { if err != nil { return nil, err } + for _, service := range services { envList := service.Spec.TaskTemplate.ContainerSpec.Env for _, envString := range envList { @@ -187,53 +215,60 @@ func getEnv(cl *dockerclient.Client, stackName string) (config.AppEnv, error) { envMap[k] = v } } + return envMap, nil } -// getLatestUpgrade returns the latest available version for an app regarding to the --major flag -// if it is newer than the currently deployed version +// getLatestUpgrade returns the latest available version for an app respecting +// the "--major" flag if it is newer than the currently deployed version. func getLatestUpgrade(cl *dockerclient.Client, stackName string, recipeName string) (string, error) { deployedVersion, err := getDeployedVersion(cl, stackName, recipeName) if err != nil { return "", err } + availableUpgrades, err := getAvailableUpgrades(cl, stackName, recipeName, deployedVersion) if err != nil { return "", err } + if len(availableUpgrades) == 0 { logrus.Debugf("no available upgrades for %s", stackName) return "", nil } - // Uncomment to select the next version instead of the last version - // availableUpgrades = internal.ReverseStringList(availableUpgrades) + var chosenUpgrade string if len(availableUpgrades) > 0 { chosenUpgrade = availableUpgrades[len(availableUpgrades)-1] logrus.Infof("%s (%s) can be upgraded from version %s to %s", stackName, recipeName, deployedVersion, chosenUpgrade) } - return chosenUpgrade, nil + return chosenUpgrade, nil } -// getDeployedVersion returns the currently deployed version of an app +// getDeployedVersion returns the currently deployed version of an app. func getDeployedVersion(cl *dockerclient.Client, stackName string, recipeName string) (string, error) { logrus.Debugf("Retrieve deployed version whether %s is already deployed", stackName) + isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, stackName) if err != nil { return "", err } + if !isDeployed { return "", fmt.Errorf("%s is not deployed?", stackName) } + if deployedVersion == "unknown" { return "", fmt.Errorf("failed to determine deployed version of %s", stackName) } + return deployedVersion, nil } -// getAvailableUpgrades returns all available versions of an app that are newer than -// the deployed version. It only includes major steps if the --major flag is set. +// getAvailableUpgrades returns all available versions of an app that are newer +// than the deployed version. It only includes major upgrades if the "--major" +// flag is set. func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName string, deployedVersion string) ([]string, error) { catl, err := recipe.ReadRecipeCatalogue() @@ -251,64 +286,73 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName } var availableUpgrades []string - for _, version := range versions { parsedDeployedVersion, err := tagcmp.Parse(deployedVersion) if err != nil { return nil, err } + parsedVersion, err := tagcmp.Parse(version) if err != nil { return nil, err } + versionDelta, err := parsedDeployedVersion.UpgradeDelta(parsedVersion) if err != nil { return nil, err } + if 0 < versionDelta.UpgradeType() && (versionDelta.UpgradeType() < 4 || majorUpdate) { availableUpgrades = append(availableUpgrades, version) } } + logrus.Debugf("Available updates for %s: %s", stackName, availableUpgrades) return availableUpgrades, nil - } -// processRecipeRepoVersion clones, pulls, checks out the version and lints the recipe repository +// processRecipeRepoVersion clones, pulls, checks out the version and lints the +// recipe repository. func processRecipeRepoVersion(recipeName string, version string) error { if err := recipe.EnsureExists(recipeName); err != nil { return err } + if err := recipe.EnsureUpToDate(recipeName); err != nil { return err } + if err := recipe.EnsureVersion(recipeName, version); err != nil { return err } + if r, err := recipe.Get(recipeName); err != nil { return err } else if err := lint.LintForErrors(r); err != nil { return err } + return nil } -// mergeAbraShEnv merges abra.sh env's into the app env's +// mergeAbraShEnv merges abra.sh env vars into the app env vars. func mergeAbraShEnv(recipeName string, env config.AppEnv) error { abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, recipeName, "abra.sh") abraShEnv, err := config.ReadAbraShEnvVars(abraShPath) if err != nil { return err } + for k, v := range abraShEnv { logrus.Debugf("read v:%s k: %s", v, k) env[k] = v } + return nil } -// createDeployConfig merges and enriches the compose config for the deployment +// createDeployConfig merges and enriches the compose config for the deployment. func createDeployConfig(recipeName string, stackName string, env config.AppEnv) (*composetypes.Config, stack.Deploy, error) { env["STACK_NAME"] = stackName @@ -317,64 +361,77 @@ func createDeployConfig(recipeName string, stackName string, env config.AppEnv) Prune: false, ResolveImage: stack.ResolveImageAlways, } + composeFiles, err := config.GetAppComposeFiles(recipeName, env) if err != nil { return nil, deployOpts, err } + deployOpts.Composefiles = composeFiles compose, err := config.GetAppComposeConfig(stackName, deployOpts, env) if err != nil { return nil, deployOpts, err } + config.ExposeAllEnv(stackName, compose, env) + // after the upgrade the deployment won't be in chaos state anymore config.SetChaosLabel(compose, stackName, false) config.SetRecipeLabel(compose, stackName, recipeName) config.SetUpdateLabel(compose, stackName, env) + return compose, deployOpts, nil } -// tryUpgrade performs the upgrade if all the requirements are fulfilled +// tryUpgrade performs the upgrade if all the requirements are fulfilled. func tryUpgrade(cl *dockerclient.Client, stackName string, recipeName string) error { if recipeName == "" { logrus.Debugf("Don't update %s due to missing recipe name", stackName) return nil } + chaos, err := getBoolLabel(cl, stackName, "chaos") if err != nil { return err } + if chaos && !internal.Chaos { logrus.Debugf("Don't update %s due to chaos deployment.", stackName) return nil } + updatesEnabled, err := getBoolLabel(cl, stackName, "autoupdate") if err != nil { return err } + if !updatesEnabled { logrus.Debugf("Don't update %s due to disabling auto updates or missing ENABLE_AUTOUPDATE env.", stackName) return nil } + upgradeVersion, err := getLatestUpgrade(cl, stackName, recipeName) if err != nil { return err } + if upgradeVersion == "" { logrus.Debugf("Don't update %s due to no new version.", stackName) return nil } - err = upgrade(cl, stackName, recipeName, upgradeVersion) - return err + err = upgrade(cl, stackName, recipeName, upgradeVersion) + + return err } -// upgrade performs all necessary steps to upgrade an app +// upgrade performs all necessary steps to upgrade an app. func upgrade(cl *dockerclient.Client, stackName string, recipeName string, upgradeVersion string) error { env, err := getEnv(cl, stackName) if err != nil { return err } + app := config.App{ Name: stackName, Recipe: recipeName, @@ -396,14 +453,16 @@ func upgrade(cl *dockerclient.Client, stackName string, recipeName string, upgra } logrus.Infof("Upgrade %s (%s) to version %s", stackName, recipeName, upgradeVersion) + err = stack.RunDeploy(cl, deployOpts, compose, stackName, true) + return err } func newAbraApp(version, commit string) *cli.App { app := &cli.App{ Name: "kadabra", - Usage: `The Co-op Cloud autoupdater + Usage: `The Co-op Cloud auto-updater ____ ____ _ _ / ___|___ ___ _ __ / ___| | ___ _ _ __| | | | / _ \ _____ / _ \| '_ \ | | | |/ _ \| | | |/ _' | @@ -419,9 +478,10 @@ func newAbraApp(version, commit string) *cli.App { } app.Before = func(c *cli.Context) error { - logrus.Debugf("abra version %s, commit %s", version, commit) + logrus.Debugf("kadabra version %s, commit %s", version, commit) return nil } + return app }