From 193091f4d08e6945f863fe990280a5e25721dce4 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 1 Feb 2023 15:29:47 +0100 Subject: [PATCH] add notify command and --major flag --- cli/updater/updater.go | 148 +++++++++++++++++++++++++++-------------- 1 file changed, 99 insertions(+), 49 deletions(-) diff --git a/cli/updater/updater.go b/cli/updater/updater.go index 58f1a287..2e5c47f6 100644 --- a/cli/updater/updater.go +++ b/cli/updater/updater.go @@ -25,6 +25,47 @@ import ( "github.com/urfave/cli" ) +var majorUpdate bool +var majorFlag = &cli.BoolFlag{ + Name: "major, m", + Usage: "Also check for major updates", + Destination: &majorUpdate, +} + +// Check for available upgrades +var Notify = cli.Command{ + Name: "notify", + Aliases: []string{"n"}, + Usage: "Check for available upgrades", + Flags: []cli.Flag{ + internal.DebugFlag, + majorFlag, + }, + Before: internal.SubCommandBefore, + Description: `Check for available upgrades`, + Action: func(c *cli.Context) error { + + cl, err := client.New("default") + if err != nil { + logrus.Fatal(err) + } + // can't import this lib: + // stacks := swarm.GetStacks(cl) + stacks, err := stack.GetStacks(cl) + if err != nil { + logrus.Fatal(err) + } + for _, stackInfo := range stacks { + stackName := stackInfo.Name + recipeName := getLabel(cl, stackName, "recipe") + if recipeName != "" { + getLatestUpgrade(cl, stackName, recipeName) + } + } + return nil + }, +} + // Upgrade a specific app var UpgradeApp = cli.Command{ Name: "appupgrade", @@ -34,6 +75,7 @@ var UpgradeApp = cli.Command{ Flags: []cli.Flag{ internal.DebugFlag, internal.ForceFlag, + majorFlag, }, Before: internal.SubCommandBefore, Description: `Upgrade an app`, @@ -44,12 +86,15 @@ var UpgradeApp = cli.Command{ if err != nil { logrus.Fatal(err) } - upgrade(cl, stackName, recipeName) + upgradeVersion := getLatestUpgrade(cl, stackName, recipeName) + if upgradeVersion != "" { + upgrade(cl, stackName, recipeName, upgradeVersion) + } return nil }, } -// Upgrade all appS +// Upgrade all apps var UpgradeAll = cli.Command{ Name: "upgrade", Aliases: []string{"u"}, @@ -57,7 +102,7 @@ var UpgradeAll = cli.Command{ Flags: []cli.Flag{ internal.DebugFlag, internal.ForceFlag, - internal.DontWaitConvergeFlag, + majorFlag, }, Before: internal.SubCommandBefore, Description: `Upgrade all deployed apps`, @@ -79,9 +124,12 @@ var UpgradeAll = cli.Command{ chaos := getBoolLabel(cl, stackName, "chaos") updatesEnabled := getBoolLabel(cl, stackName, "autoupdate") if recipeName != "" && updatesEnabled && (!chaos || internal.Force) { - upgrade(cl, stackName, recipeName) + upgradeVersion := getLatestUpgrade(cl, stackName, recipeName) + if upgradeVersion != "" { + upgrade(cl, stackName, recipeName, upgradeVersion) + } } else { - logrus.Infof("Don't update %s due to missing recipe name, disabled updates or chaos deployment", stackName) + logrus.Debugf("Don't update %s due to missing recipe name, disabled updates or chaos deployment", stackName) } } return nil @@ -140,24 +188,47 @@ func getEnv(cl *dockerclient.Client, stackName string) config.AppEnv { } k := splitString[0] v := splitString[1] - logrus.Debugf("Env Key: %s Value: %s", k, v) + logrus.Debugf("For %s read env %s with value: %s from docker service", stackName, k, v) envMap[k] = v } } return envMap } -func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName string) []string { +func getLatestUpgrade(cl *dockerclient.Client, stackName string, recipeName string) string { + deployedVersion := getDeployedVersion(cl, stackName, recipeName) + availableUpgrades := getAvailableUpgrades(cl, stackName, recipeName, deployedVersion) + if len(availableUpgrades) == 0 { + logrus.Debugf("no available upgrades for %s", stackName) + return "" + } + 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 + +} + +func getDeployedVersion(cl *dockerclient.Client, stackName string, recipeName string) string { logrus.Debugf("Retrieve deployed version whether %s is already deployed", stackName) isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, stackName) if err != nil { logrus.Fatal(err) } - if !isDeployed { logrus.Fatalf("%s is not deployed?", stackName) } + if deployedVersion == "unknown" { + logrus.Fatalf("failed to determine deployed version of %s", stackName) + } + return deployedVersion +} +func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName string, + deployedVersion string) []string { catl, err := recipe.ReadRecipeCatalogue() if err != nil { logrus.Fatal(err) @@ -173,35 +244,25 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName } var availableUpgrades []string - if deployedVersion == "unknown" { - availableUpgrades = versions - logrus.Fatalf("failed to determine deployed version of %s", stackName) - } - if deployedVersion != "unknown" { - logrus.Infof("%s is deployed on %s with version %s", recipeName, stackName, deployedVersion) - for _, version := range versions { - parsedDeployedVersion, err := tagcmp.Parse(deployedVersion) - if err != nil { - logrus.Fatal(err) - } - parsedVersion, err := tagcmp.Parse(version) - if err != nil { - logrus.Fatal(err) - } - versionDelta, err := parsedDeployedVersion.UpgradeDelta(parsedVersion) - if err != nil { - logrus.Fatal(err) - } - // Only update Patch/Minor updates - if 0 < versionDelta.UpgradeType() && versionDelta.UpgradeType() < 4 { - availableUpgrades = append(availableUpgrades, version) - } + for _, version := range versions { + parsedDeployedVersion, err := tagcmp.Parse(deployedVersion) + if err != nil { + logrus.Fatal(err) + } + parsedVersion, err := tagcmp.Parse(version) + if err != nil { + logrus.Fatal(err) + } + versionDelta, err := parsedDeployedVersion.UpgradeDelta(parsedVersion) + if err != nil { + logrus.Fatal(err) + } + if 0 < versionDelta.UpgradeType() && (versionDelta.UpgradeType() < 4 || majorUpdate) { + availableUpgrades = append(availableUpgrades, version) } - - } else { - logrus.Warnf("Could not determine the deployed version for %s", stackName) } + return availableUpgrades } @@ -262,8 +323,7 @@ func createDeployConfig(recipeName string, stackName string, env config.AppEnv) return compose, deployOpts } -func upgrade(cl *dockerclient.Client, stackName string, recipeName string) { - logrus.Debugf("Upgrade StackName: %s \n Recipe: %s", stackName, recipeName) +func upgrade(cl *dockerclient.Client, stackName string, recipeName string, upgradeVersion string) { app := config.App{ Name: stackName, Recipe: recipeName, @@ -271,24 +331,13 @@ func upgrade(cl *dockerclient.Client, stackName string, recipeName string) { Env: getEnv(cl, stackName), } - availableUpgrades := getAvailableUpgrades(cl, stackName, recipeName) - if len(availableUpgrades) == 0 { - logrus.Infof("no available upgrades for %s", stackName) - return - } - availableUpgrades = internal.ReverseStringList(availableUpgrades) - var chosenUpgrade string - if len(availableUpgrades) > 0 { - chosenUpgrade = availableUpgrades[len(availableUpgrades)-1] - logrus.Infof("choosing %s as version to upgrade to", chosenUpgrade) - } - - processRecipeRepoVersion(recipeName, chosenUpgrade) + processRecipeRepoVersion(recipeName, upgradeVersion) mergeAbraShEnv(recipeName, app.Env) compose, deployOpts := createDeployConfig(recipeName, stackName, app.Env) + logrus.Infof("Upgrade %s (%s) to version %s", stackName, recipeName, upgradeVersion) if err := stack.RunDeploy(cl, deployOpts, compose, stackName, true); err != nil { logrus.Fatal(err) } @@ -307,6 +356,7 @@ func newAbraApp(version, commit string) *cli.App { `, Version: fmt.Sprintf("%s-%s", version, commit[:7]), Commands: []cli.Command{ + Notify, UpgradeApp, UpgradeAll, },