chore: formatting pass on kadabra [ci skip]

This commit is contained in:
decentral1se 2023-02-08 23:19:14 +01:00
parent 3d2b8fa446
commit f6b139dfea
Signed by: decentral1se
GPG Key ID: 03789458B3D0C410
2 changed files with 90 additions and 29 deletions

View File

@ -189,6 +189,7 @@ func newAbraApp(version, commit string) *cli.App {
return nil return nil
} }
return app return app
} }

View File

@ -40,7 +40,7 @@ var allFlag = &cli.BoolFlag{
Destination: &updateAll, Destination: &updateAll,
} }
// Check for available upgrades // Notify checks for available upgrades
var Notify = cli.Command{ var Notify = cli.Command{
Name: "notify", Name: "notify",
Aliases: []string{"n"}, Aliases: []string{"n"},
@ -49,24 +49,31 @@ var Notify = cli.Command{
internal.DebugFlag, internal.DebugFlag,
majorFlag, majorFlag,
}, },
Before: internal.SubCommandBefore, 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.`, 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 { Action: func(c *cli.Context) error {
cl, err := client.New("default") cl, err := client.New("default")
if err != nil { if err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
stacks, err := stack.GetStacks(cl) stacks, err := stack.GetStacks(cl)
if err != nil { if err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
for _, stackInfo := range stacks { for _, stackInfo := range stacks {
stackName := stackInfo.Name stackName := stackInfo.Name
recipeName, err := getLabel(cl, stackName, "recipe") recipeName, err := getLabel(cl, stackName, "recipe")
if err != nil { if err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
if recipeName != "" { if recipeName != "" {
_, err = getLatestUpgrade(cl, stackName, recipeName) _, err = getLatestUpgrade(cl, stackName, recipeName)
if err != nil { if err != nil {
@ -74,24 +81,33 @@ var Notify = cli.Command{
} }
} }
} }
return nil return nil
}, },
} }
// Upgrade apps // UpgradeApp upgrades apps.
var UpgradeApp = cli.Command{ var UpgradeApp = cli.Command{
Name: "upgrade", Name: "upgrade",
Aliases: []string{"u"}, Aliases: []string{"u"},
Usage: "Upgrade apps", Usage: "Upgrade apps",
ArgsUsage: "<stack_name> <recipe>", ArgsUsage: "<stack-name> <recipe>",
Flags: []cli.Flag{ Flags: []cli.Flag{
internal.DebugFlag, internal.DebugFlag,
internal.ChaosFlag, internal.ChaosFlag,
majorFlag, majorFlag,
allFlag, allFlag,
}, },
Before: internal.SubCommandBefore, 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.`, 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 { Action: func(c *cli.Context) error {
cl, err := client.New("default") cl, err := client.New("default")
if err != nil { if err != nil {
@ -105,6 +121,7 @@ var UpgradeApp = cli.Command{
if err != nil { if err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
return nil return nil
} }
@ -112,22 +129,25 @@ var UpgradeApp = cli.Command{
if err != nil { if err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
for _, stackInfo := range stacks { for _, stackInfo := range stacks {
stackName := stackInfo.Name stackName := stackInfo.Name
recipeName, err := getLabel(cl, stackName, "recipe") recipeName, err := getLabel(cl, stackName, "recipe")
if err != nil { if err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
err = tryUpgrade(cl, stackName, recipeName) err = tryUpgrade(cl, stackName, recipeName)
if err != nil { if err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
} }
return nil 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) { func getLabel(cl *dockerclient.Client, stackName string, label string) (string, error) {
filter := filters.NewArgs() filter := filters.NewArgs()
filter.Add("label", fmt.Sprintf("%s=%s", convert.LabelNamespace, stackName)) 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 { if err != nil {
return "", err return "", err
} }
for _, service := range services { for _, service := range services {
labelKey := fmt.Sprintf("coop-cloud.%s.%s", stackName, label) labelKey := fmt.Sprintf("coop-cloud.%s.%s", stackName, label)
if labelValue, ok := service.Spec.Labels[labelKey]; ok { if labelValue, ok := service.Spec.Labels[labelKey]; ok {
return labelValue, nil return labelValue, nil
} }
} }
logrus.Debugf("no %s label found for %s", label, stackName) logrus.Debugf("no %s label found for %s", label, stackName)
return "", nil 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) { func getBoolLabel(cl *dockerclient.Client, stackName string, label string) (bool, error) {
lableValue, err := getLabel(cl, stackName, label) lableValue, err := getLabel(cl, stackName, label)
if err != nil { if err != nil {
return false, err return false, err
} }
if lableValue != "" { if lableValue != "" {
value, err := strconv.ParseBool(lableValue) value, err := strconv.ParseBool(lableValue)
if err != nil { if err != nil {
return false, err return false, err
} }
return value, nil return value, nil
} }
logrus.Debugf("Boolean label %s could not be found for %s, set default to false.", label, stackName) logrus.Debugf("Boolean label %s could not be found for %s, set default to false.", label, stackName)
return false, nil 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) { func getEnv(cl *dockerclient.Client, stackName string) (config.AppEnv, error) {
envMap := make(map[string]string) envMap := make(map[string]string)
filter := filters.NewArgs() filter := filters.NewArgs()
@ -173,6 +200,7 @@ func getEnv(cl *dockerclient.Client, stackName string) (config.AppEnv, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, service := range services { for _, service := range services {
envList := service.Spec.TaskTemplate.ContainerSpec.Env envList := service.Spec.TaskTemplate.ContainerSpec.Env
for _, envString := range envList { for _, envString := range envList {
@ -187,53 +215,60 @@ func getEnv(cl *dockerclient.Client, stackName string) (config.AppEnv, error) {
envMap[k] = v envMap[k] = v
} }
} }
return envMap, nil return envMap, nil
} }
// getLatestUpgrade returns the latest available version for an app regarding to the --major flag // getLatestUpgrade returns the latest available version for an app respecting
// if it is newer than the currently deployed version // the "--major" flag if it is newer than the currently deployed version.
func getLatestUpgrade(cl *dockerclient.Client, stackName string, recipeName string) (string, error) { func getLatestUpgrade(cl *dockerclient.Client, stackName string, recipeName string) (string, error) {
deployedVersion, err := getDeployedVersion(cl, stackName, recipeName) deployedVersion, err := getDeployedVersion(cl, stackName, recipeName)
if err != nil { if err != nil {
return "", err return "", err
} }
availableUpgrades, err := getAvailableUpgrades(cl, stackName, recipeName, deployedVersion) availableUpgrades, err := getAvailableUpgrades(cl, stackName, recipeName, deployedVersion)
if err != nil { if err != nil {
return "", err return "", err
} }
if len(availableUpgrades) == 0 { if len(availableUpgrades) == 0 {
logrus.Debugf("no available upgrades for %s", stackName) logrus.Debugf("no available upgrades for %s", stackName)
return "", nil return "", nil
} }
// Uncomment to select the next version instead of the last version
// availableUpgrades = internal.ReverseStringList(availableUpgrades)
var chosenUpgrade string var chosenUpgrade string
if len(availableUpgrades) > 0 { if len(availableUpgrades) > 0 {
chosenUpgrade = availableUpgrades[len(availableUpgrades)-1] chosenUpgrade = availableUpgrades[len(availableUpgrades)-1]
logrus.Infof("%s (%s) can be upgraded from version %s to %s", stackName, recipeName, deployedVersion, chosenUpgrade) 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) { func getDeployedVersion(cl *dockerclient.Client, stackName string, recipeName string) (string, error) {
logrus.Debugf("Retrieve deployed version whether %s is already deployed", stackName) logrus.Debugf("Retrieve deployed version whether %s is already deployed", stackName)
isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, stackName) isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, stackName)
if err != nil { if err != nil {
return "", err return "", err
} }
if !isDeployed { if !isDeployed {
return "", fmt.Errorf("%s is not deployed?", stackName) return "", fmt.Errorf("%s is not deployed?", stackName)
} }
if deployedVersion == "unknown" { if deployedVersion == "unknown" {
return "", fmt.Errorf("failed to determine deployed version of %s", stackName) return "", fmt.Errorf("failed to determine deployed version of %s", stackName)
} }
return deployedVersion, nil return deployedVersion, nil
} }
// getAvailableUpgrades returns all available versions of an app that are newer than // getAvailableUpgrades returns all available versions of an app that are newer
// the deployed version. It only includes major steps if the --major flag is set. // than the deployed version. It only includes major upgrades if the "--major"
// flag is set.
func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName string, func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName string,
deployedVersion string) ([]string, error) { deployedVersion string) ([]string, error) {
catl, err := recipe.ReadRecipeCatalogue() catl, err := recipe.ReadRecipeCatalogue()
@ -251,64 +286,73 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName
} }
var availableUpgrades []string var availableUpgrades []string
for _, version := range versions { for _, version := range versions {
parsedDeployedVersion, err := tagcmp.Parse(deployedVersion) parsedDeployedVersion, err := tagcmp.Parse(deployedVersion)
if err != nil { if err != nil {
return nil, err return nil, err
} }
parsedVersion, err := tagcmp.Parse(version) parsedVersion, err := tagcmp.Parse(version)
if err != nil { if err != nil {
return nil, err return nil, err
} }
versionDelta, err := parsedDeployedVersion.UpgradeDelta(parsedVersion) versionDelta, err := parsedDeployedVersion.UpgradeDelta(parsedVersion)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if 0 < versionDelta.UpgradeType() && (versionDelta.UpgradeType() < 4 || majorUpdate) { if 0 < versionDelta.UpgradeType() && (versionDelta.UpgradeType() < 4 || majorUpdate) {
availableUpgrades = append(availableUpgrades, version) availableUpgrades = append(availableUpgrades, version)
} }
} }
logrus.Debugf("Available updates for %s: %s", stackName, availableUpgrades) logrus.Debugf("Available updates for %s: %s", stackName, availableUpgrades)
return availableUpgrades, nil 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 { func processRecipeRepoVersion(recipeName string, version string) error {
if err := recipe.EnsureExists(recipeName); err != nil { if err := recipe.EnsureExists(recipeName); err != nil {
return err return err
} }
if err := recipe.EnsureUpToDate(recipeName); err != nil { if err := recipe.EnsureUpToDate(recipeName); err != nil {
return err return err
} }
if err := recipe.EnsureVersion(recipeName, version); err != nil { if err := recipe.EnsureVersion(recipeName, version); err != nil {
return err return err
} }
if r, err := recipe.Get(recipeName); err != nil { if r, err := recipe.Get(recipeName); err != nil {
return err return err
} else if err := lint.LintForErrors(r); err != nil { } else if err := lint.LintForErrors(r); err != nil {
return err return err
} }
return nil 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 { func mergeAbraShEnv(recipeName string, env config.AppEnv) error {
abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, recipeName, "abra.sh") abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, recipeName, "abra.sh")
abraShEnv, err := config.ReadAbraShEnvVars(abraShPath) abraShEnv, err := config.ReadAbraShEnvVars(abraShPath)
if err != nil { if err != nil {
return err return err
} }
for k, v := range abraShEnv { for k, v := range abraShEnv {
logrus.Debugf("read v:%s k: %s", v, k) logrus.Debugf("read v:%s k: %s", v, k)
env[k] = v env[k] = v
} }
return nil 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) { func createDeployConfig(recipeName string, stackName string, env config.AppEnv) (*composetypes.Config, stack.Deploy, error) {
env["STACK_NAME"] = stackName env["STACK_NAME"] = stackName
@ -317,64 +361,77 @@ func createDeployConfig(recipeName string, stackName string, env config.AppEnv)
Prune: false, Prune: false,
ResolveImage: stack.ResolveImageAlways, ResolveImage: stack.ResolveImageAlways,
} }
composeFiles, err := config.GetAppComposeFiles(recipeName, env) composeFiles, err := config.GetAppComposeFiles(recipeName, env)
if err != nil { if err != nil {
return nil, deployOpts, err return nil, deployOpts, err
} }
deployOpts.Composefiles = composeFiles deployOpts.Composefiles = composeFiles
compose, err := config.GetAppComposeConfig(stackName, deployOpts, env) compose, err := config.GetAppComposeConfig(stackName, deployOpts, env)
if err != nil { if err != nil {
return nil, deployOpts, err return nil, deployOpts, err
} }
config.ExposeAllEnv(stackName, compose, env) config.ExposeAllEnv(stackName, compose, env)
// after the upgrade the deployment won't be in chaos state anymore // after the upgrade the deployment won't be in chaos state anymore
config.SetChaosLabel(compose, stackName, false) config.SetChaosLabel(compose, stackName, false)
config.SetRecipeLabel(compose, stackName, recipeName) config.SetRecipeLabel(compose, stackName, recipeName)
config.SetUpdateLabel(compose, stackName, env) config.SetUpdateLabel(compose, stackName, env)
return compose, deployOpts, nil 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 { func tryUpgrade(cl *dockerclient.Client, stackName string, recipeName string) error {
if recipeName == "" { if recipeName == "" {
logrus.Debugf("Don't update %s due to missing recipe name", stackName) logrus.Debugf("Don't update %s due to missing recipe name", stackName)
return nil return nil
} }
chaos, err := getBoolLabel(cl, stackName, "chaos") chaos, err := getBoolLabel(cl, stackName, "chaos")
if err != nil { if err != nil {
return err return err
} }
if chaos && !internal.Chaos { if chaos && !internal.Chaos {
logrus.Debugf("Don't update %s due to chaos deployment.", stackName) logrus.Debugf("Don't update %s due to chaos deployment.", stackName)
return nil return nil
} }
updatesEnabled, err := getBoolLabel(cl, stackName, "autoupdate") updatesEnabled, err := getBoolLabel(cl, stackName, "autoupdate")
if err != nil { if err != nil {
return err return err
} }
if !updatesEnabled { if !updatesEnabled {
logrus.Debugf("Don't update %s due to disabling auto updates or missing ENABLE_AUTOUPDATE env.", stackName) logrus.Debugf("Don't update %s due to disabling auto updates or missing ENABLE_AUTOUPDATE env.", stackName)
return nil return nil
} }
upgradeVersion, err := getLatestUpgrade(cl, stackName, recipeName) upgradeVersion, err := getLatestUpgrade(cl, stackName, recipeName)
if err != nil { if err != nil {
return err return err
} }
if upgradeVersion == "" { if upgradeVersion == "" {
logrus.Debugf("Don't update %s due to no new version.", stackName) logrus.Debugf("Don't update %s due to no new version.", stackName)
return nil 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 { func upgrade(cl *dockerclient.Client, stackName string, recipeName string, upgradeVersion string) error {
env, err := getEnv(cl, stackName) env, err := getEnv(cl, stackName)
if err != nil { if err != nil {
return err return err
} }
app := config.App{ app := config.App{
Name: stackName, Name: stackName,
Recipe: recipeName, 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) logrus.Infof("Upgrade %s (%s) to version %s", stackName, recipeName, upgradeVersion)
err = stack.RunDeploy(cl, deployOpts, compose, stackName, true) err = stack.RunDeploy(cl, deployOpts, compose, stackName, true)
return err return err
} }
func newAbraApp(version, commit string) *cli.App { func newAbraApp(version, commit string) *cli.App {
app := &cli.App{ app := &cli.App{
Name: "kadabra", 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 { 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 nil
} }
return app return app
} }