forked from toolshed/abra
		
	fix!: chaos consistency (deploy/undeploy/rollback/upgrade)
See coop-cloud/organising#559 --chaos for rollback/upgrade goes away.
This commit is contained in:
		@ -71,7 +71,7 @@ recipes.
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
		deployMeta, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
@ -80,7 +80,7 @@ recipes.
 | 
			
		||||
		// is because we need to deal with GetComposeFiles under the hood and these
 | 
			
		||||
		// files change from version to version which therefore affects which
 | 
			
		||||
		// secrets might be generated
 | 
			
		||||
		version := deployedVersion
 | 
			
		||||
		version := deployMeta.Version
 | 
			
		||||
		if specificVersion != "" {
 | 
			
		||||
			version = specificVersion
 | 
			
		||||
			log.Debugf("choosing %s as version to deploy", version)
 | 
			
		||||
@ -100,7 +100,7 @@ recipes.
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if isDeployed {
 | 
			
		||||
		if deployMeta.IsDeployed {
 | 
			
		||||
			if internal.Force || internal.Chaos {
 | 
			
		||||
				log.Warnf("%s is already deployed but continuing (--force/--chaos)", app.Name)
 | 
			
		||||
			} else {
 | 
			
		||||
@ -147,10 +147,11 @@ recipes.
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		chaosVersion := "false"
 | 
			
		||||
		if internal.Chaos {
 | 
			
		||||
			log.Warnf("chaos mode engaged")
 | 
			
		||||
			var err error
 | 
			
		||||
			version, err = app.Recipe.ChaosVersion()
 | 
			
		||||
			chaosVersion, err = app.Recipe.ChaosVersion()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
@ -184,7 +185,7 @@ recipes.
 | 
			
		||||
		appPkg.ExposeAllEnv(stackName, compose, app.Env)
 | 
			
		||||
		appPkg.SetRecipeLabel(compose, stackName, app.Recipe.Name)
 | 
			
		||||
		appPkg.SetChaosLabel(compose, stackName, internal.Chaos)
 | 
			
		||||
		appPkg.SetChaosVersionLabel(compose, stackName, version)
 | 
			
		||||
		appPkg.SetChaosVersionLabel(compose, stackName, chaosVersion)
 | 
			
		||||
		appPkg.SetUpdateLabel(compose, stackName, app.Env)
 | 
			
		||||
 | 
			
		||||
		envVars, err := appPkg.CheckEnv(app)
 | 
			
		||||
@ -198,7 +199,7 @@ recipes.
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := internal.DeployOverview(app, version, "continue with deployment?"); err != nil {
 | 
			
		||||
		if err := internal.DeployOverview(app, version, chaosVersion, "continue with deployment?"); err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -47,12 +47,12 @@ var appLogsCommand = cli.Command{
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isDeployed, _, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
		deployMeta, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !isDeployed {
 | 
			
		||||
		if !deployMeta.IsDeployed {
 | 
			
		||||
			log.Fatalf("%s is not deployed?", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -41,12 +41,12 @@ var appPsCommand = cli.Command{
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, app.StackName())
 | 
			
		||||
		deployMeta, err := stack.IsDeployed(context.Background(), cl, app.StackName())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !isDeployed {
 | 
			
		||||
		if !deployMeta.IsDeployed {
 | 
			
		||||
			log.Fatalf("%s is not deployed?", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -55,7 +55,7 @@ var appPsCommand = cli.Command{
 | 
			
		||||
		if statusMeta, ok := statuses[app.StackName()]; ok {
 | 
			
		||||
			isChaos, exists := statusMeta["chaos"]
 | 
			
		||||
			if exists && isChaos == "false" {
 | 
			
		||||
				if err := app.Recipe.EnsureVersion(deployedVersion); err != nil {
 | 
			
		||||
				if err := app.Recipe.EnsureVersion(deployMeta.Version); err != nil {
 | 
			
		||||
					log.Fatal(err)
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
@ -66,7 +66,7 @@ var appPsCommand = cli.Command{
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		showPSOutput(app, cl, deployedVersion, chaosVersion)
 | 
			
		||||
		showPSOutput(app, cl, deployMeta.Version, chaosVersion)
 | 
			
		||||
 | 
			
		||||
		return nil
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
@ -66,11 +66,11 @@ flag.
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isDeployed, _, err := stack.IsDeployed(context.Background(), cl, app.StackName())
 | 
			
		||||
		deployMeta, err := stack.IsDeployed(context.Background(), cl, app.StackName())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		if isDeployed {
 | 
			
		||||
		if deployMeta.IsDeployed {
 | 
			
		||||
			log.Fatalf("%s is still deployed. Run \"abra app undeploy %s\"", app.Name, app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -67,12 +67,12 @@ Example:
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isDeployed, _, err := stack.IsDeployed(context.Background(), cl, app.StackName())
 | 
			
		||||
		deployMeta, err := stack.IsDeployed(context.Background(), cl, app.StackName())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !isDeployed {
 | 
			
		||||
		if !deployMeta.IsDeployed {
 | 
			
		||||
			log.Fatalf("%s is not deployed?", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,6 @@ var appRollbackCommand = cli.Command{
 | 
			
		||||
		internal.DebugFlag,
 | 
			
		||||
		internal.NoInputFlag,
 | 
			
		||||
		internal.ForceFlag,
 | 
			
		||||
		internal.ChaosFlag,
 | 
			
		||||
		internal.NoDomainChecksFlag,
 | 
			
		||||
		internal.DontWaitConvergeFlag,
 | 
			
		||||
		internal.OfflineFlag,
 | 
			
		||||
@ -42,21 +41,12 @@ useful if the container runtime has gotten into a weird state.
 | 
			
		||||
 | 
			
		||||
This action could be destructive, please ensure you have a copy of your app
 | 
			
		||||
data beforehand.
 | 
			
		||||
 | 
			
		||||
Chaos mode ("--chaos") will deploy your local checkout of a recipe as-is,
 | 
			
		||||
including unstaged changes and can be useful for live hacking and testing new
 | 
			
		||||
recipes.
 | 
			
		||||
`,
 | 
			
		||||
	BashComplete: autocomplete.AppNameComplete,
 | 
			
		||||
	Action: func(c *cli.Context) error {
 | 
			
		||||
		app := internal.ValidateApp(c)
 | 
			
		||||
		stackName := app.StackName()
 | 
			
		||||
 | 
			
		||||
		specificVersion := c.Args().Get(1)
 | 
			
		||||
		if specificVersion != "" && internal.Chaos {
 | 
			
		||||
			log.Fatal("cannot use <version> and --chaos together")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
@ -72,12 +62,12 @@ recipes.
 | 
			
		||||
 | 
			
		||||
		log.Debugf("checking whether %s is already deployed", stackName)
 | 
			
		||||
 | 
			
		||||
		isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
		deployMeta, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !isDeployed {
 | 
			
		||||
		if !deployMeta.IsDeployed {
 | 
			
		||||
			log.Fatalf("%s is not deployed?", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -91,12 +81,13 @@ recipes.
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(versions) == 0 && !internal.Chaos {
 | 
			
		||||
		if len(versions) == 0 {
 | 
			
		||||
			log.Warn("no published versions in catalogue, trying local recipe repository")
 | 
			
		||||
			recipeVersions, err := app.Recipe.GetRecipeVersions(internal.Offline)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Warn(err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for _, recipeVersion := range recipeVersions {
 | 
			
		||||
				for version := range recipeVersion {
 | 
			
		||||
					versions = append(versions, version)
 | 
			
		||||
@ -105,77 +96,83 @@ recipes.
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var availableDowngrades []string
 | 
			
		||||
		if deployedVersion == "unknown" {
 | 
			
		||||
		if deployMeta.Version == "unknown" {
 | 
			
		||||
			availableDowngrades = versions
 | 
			
		||||
			log.Warnf("failed to determine deployed version of %s", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		specificVersion := c.Args().Get(1)
 | 
			
		||||
		if specificVersion != "" {
 | 
			
		||||
			parsedDeployedVersion, err := tagcmp.Parse(deployedVersion)
 | 
			
		||||
			parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			parsedSpecificVersion, err := tagcmp.Parse(specificVersion)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if parsedSpecificVersion.IsGreaterThan(parsedDeployedVersion) || parsedSpecificVersion.Equals(parsedDeployedVersion) {
 | 
			
		||||
				log.Fatalf("%s is not a downgrade for %s?", deployedVersion, specificVersion)
 | 
			
		||||
				log.Fatalf("%s is not a downgrade for %s?", deployMeta.Version, specificVersion)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			availableDowngrades = append(availableDowngrades, specificVersion)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if deployedVersion != "unknown" && !internal.Chaos && specificVersion == "" {
 | 
			
		||||
		if deployMeta.Version != "unknown" && specificVersion == "" {
 | 
			
		||||
			if deployMeta.IsChaos == "true" {
 | 
			
		||||
				log.Warn("attempting to rollback a chaos deployment")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for _, version := range versions {
 | 
			
		||||
				parsedDeployedVersion, err := tagcmp.Parse(deployedVersion)
 | 
			
		||||
				parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					log.Fatal(err)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				parsedVersion, err := tagcmp.Parse(version)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					log.Fatal(err)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if parsedVersion.IsLessThan(parsedDeployedVersion) && !(parsedVersion.Equals(parsedDeployedVersion)) {
 | 
			
		||||
					availableDowngrades = append(availableDowngrades, version)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if len(availableDowngrades) == 0 && !internal.Force {
 | 
			
		||||
				log.Info("no available downgrades, you're on oldest ✌️")
 | 
			
		||||
				log.Info("no available downgrades")
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var chosenDowngrade string
 | 
			
		||||
		if len(availableDowngrades) > 0 && !internal.Chaos {
 | 
			
		||||
		if len(availableDowngrades) > 0 {
 | 
			
		||||
			if internal.Force || internal.NoInput || specificVersion != "" {
 | 
			
		||||
				chosenDowngrade = availableDowngrades[len(availableDowngrades)-1]
 | 
			
		||||
				log.Debugf("choosing %s as version to downgrade to (--force/--no-input)", chosenDowngrade)
 | 
			
		||||
			} else {
 | 
			
		||||
				msg := fmt.Sprintf("please select a downgrade (version: %s):", deployMeta.Version)
 | 
			
		||||
				if deployMeta.IsChaos == "true" {
 | 
			
		||||
					msg = fmt.Sprintf("please select a downgrade (version: %s, chaosVersion: %s):", deployMeta.Version, deployMeta.ChaosVersion)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				prompt := &survey.Select{
 | 
			
		||||
					Message: fmt.Sprintf("Please select a downgrade (current version: %s):", deployedVersion),
 | 
			
		||||
					Message: msg,
 | 
			
		||||
					Options: internal.ReverseStringList(availableDowngrades),
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if err := survey.AskOne(prompt, &chosenDowngrade); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !internal.Chaos {
 | 
			
		||||
		log.Debugf("choosing %s as version to rollback", chosenDowngrade)
 | 
			
		||||
		if err := app.Recipe.EnsureVersion(chosenDowngrade); err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if internal.Chaos {
 | 
			
		||||
			log.Warn("chaos mode engaged")
 | 
			
		||||
			var err error
 | 
			
		||||
			chosenDowngrade, err = app.Recipe.ChaosVersion()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		abraShEnv, err := envfile.ReadAbraShEnvVars(app.Recipe.AbraShPath)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@ -189,6 +186,7 @@ recipes.
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		deployOpts := stack.Deploy{
 | 
			
		||||
			Composefiles: composeFiles,
 | 
			
		||||
			Namespace:    stackName,
 | 
			
		||||
@ -196,18 +194,25 @@ recipes.
 | 
			
		||||
			ResolveImage: stack.ResolveImageAlways,
 | 
			
		||||
			Detach:       false,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		compose, err := appPkg.GetAppComposeConfig(app.Name, deployOpts, app.Env)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		appPkg.ExposeAllEnv(stackName, compose, app.Env)
 | 
			
		||||
		appPkg.SetRecipeLabel(compose, stackName, app.Recipe.Name)
 | 
			
		||||
		appPkg.SetChaosLabel(compose, stackName, internal.Chaos)
 | 
			
		||||
		appPkg.SetChaosVersionLabel(compose, stackName, chosenDowngrade)
 | 
			
		||||
		appPkg.SetUpdateLabel(compose, stackName, app.Env)
 | 
			
		||||
 | 
			
		||||
		chaosVersion := deployMeta.IsChaos
 | 
			
		||||
		if deployMeta.IsChaos == "true" {
 | 
			
		||||
			chaosVersion = deployMeta.ChaosVersion
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// NOTE(d1): no release notes implemeneted for rolling back
 | 
			
		||||
		if err := internal.NewVersionOverview(app, deployedVersion, chosenDowngrade, ""); err != nil {
 | 
			
		||||
		if err := internal.NewVersionOverview(app, deployMeta.Version, chaosVersion, chosenDowngrade, ""); err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -34,12 +34,12 @@ var appServicesCommand = cli.Command{
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isDeployed, _, err := stack.IsDeployed(context.Background(), cl, app.StackName())
 | 
			
		||||
		deployMeta, err := stack.IsDeployed(context.Background(), cl, app.StackName())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !isDeployed {
 | 
			
		||||
		if !deployMeta.IsDeployed {
 | 
			
		||||
			log.Fatalf("%s is not deployed?", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,6 @@ package app
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"coopcloud.tech/abra/cli/internal"
 | 
			
		||||
	appPkg "coopcloud.tech/abra/pkg/app"
 | 
			
		||||
@ -28,27 +27,10 @@ var pruneFlag = &cli.BoolFlag{
 | 
			
		||||
// pruneApp runs the equivalent of a "docker system prune" but only filtering
 | 
			
		||||
// against resources connected with the app deployment. It is not a system wide
 | 
			
		||||
// prune. Volumes are not pruned to avoid unwated data loss.
 | 
			
		||||
func pruneApp(c *cli.Context, cl *dockerClient.Client, app appPkg.App) error {
 | 
			
		||||
func pruneApp(cl *dockerClient.Client, app appPkg.App) error {
 | 
			
		||||
	stackName := app.StackName()
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		log.Debugf("polling for %s stack, waiting to be undeployed...", stackName)
 | 
			
		||||
 | 
			
		||||
		services, err := stack.GetStackServices(ctx, cl, stackName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(services) == 0 {
 | 
			
		||||
			log.Debugf("%s undeployed, moving on with pruning logic", stackName)
 | 
			
		||||
			time.Sleep(time.Second) // give runtime more time to tear down related state
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		time.Sleep(time.Second)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pruneFilters := filters.NewArgs()
 | 
			
		||||
	stackSearch := fmt.Sprintf("%s*", stackName)
 | 
			
		||||
	pruneFilters.Add("label", stackSearch)
 | 
			
		||||
@ -109,16 +91,21 @@ Passing "-p/--prune" does not remove those volumes.
 | 
			
		||||
 | 
			
		||||
		log.Debugf("checking whether %s is already deployed", stackName)
 | 
			
		||||
 | 
			
		||||
		isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
		deployMeta, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !isDeployed {
 | 
			
		||||
		if !deployMeta.IsDeployed {
 | 
			
		||||
			log.Fatalf("%s is not deployed?", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := internal.DeployOverview(app, deployedVersion, "continue with undeploy?"); err != nil {
 | 
			
		||||
		chaosVersion := deployMeta.IsChaos
 | 
			
		||||
		if deployMeta.IsChaos == "true" {
 | 
			
		||||
			chaosVersion = deployMeta.ChaosVersion
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := internal.DeployOverview(app, deployMeta.Version, chaosVersion, "continue with undeploy?"); err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -131,7 +118,7 @@ Passing "-p/--prune" does not remove those volumes.
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if prune {
 | 
			
		||||
			if err := pruneApp(c, cl, app); err != nil {
 | 
			
		||||
			if err := pruneApp(cl, app); err != nil {
 | 
			
		||||
				log.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,6 @@ var appUpgradeCommand = cli.Command{
 | 
			
		||||
		internal.DebugFlag,
 | 
			
		||||
		internal.NoInputFlag,
 | 
			
		||||
		internal.ForceFlag,
 | 
			
		||||
		internal.ChaosFlag,
 | 
			
		||||
		internal.NoDomainChecksFlag,
 | 
			
		||||
		internal.DontWaitConvergeFlag,
 | 
			
		||||
		internal.OfflineFlag,
 | 
			
		||||
@ -35,11 +34,7 @@ var appUpgradeCommand = cli.Command{
 | 
			
		||||
	},
 | 
			
		||||
	Before: internal.SubCommandBefore,
 | 
			
		||||
	Description: `
 | 
			
		||||
Upgrade an app. You can use it to choose and roll out a new upgrade to an
 | 
			
		||||
existing app.
 | 
			
		||||
 | 
			
		||||
This command specifically supports incrementing the version of running apps, as
 | 
			
		||||
opposed to "abra app deploy <domain>" which will not change the version of a
 | 
			
		||||
Upgrade an app. You can use it to choose and roll out a new upgrade to a
 | 
			
		||||
deployed app.
 | 
			
		||||
 | 
			
		||||
You may pass "--force/-f" to upgrade to the same version again. This can be
 | 
			
		||||
@ -47,21 +42,12 @@ useful if the container runtime has gotten into a weird state.
 | 
			
		||||
 | 
			
		||||
This action could be destructive, please ensure you have a copy of your app
 | 
			
		||||
data beforehand.
 | 
			
		||||
 | 
			
		||||
Chaos mode ("--chaos") will deploy your local checkout of a recipe as-is,
 | 
			
		||||
including unstaged changes and can be useful for live hacking and testing new
 | 
			
		||||
recipes.
 | 
			
		||||
`,
 | 
			
		||||
	BashComplete: autocomplete.AppNameComplete,
 | 
			
		||||
	Action: func(c *cli.Context) error {
 | 
			
		||||
		app := internal.ValidateApp(c)
 | 
			
		||||
		stackName := app.StackName()
 | 
			
		||||
 | 
			
		||||
		specificVersion := c.Args().Get(1)
 | 
			
		||||
		if specificVersion != "" && internal.Chaos {
 | 
			
		||||
			log.Fatal("cannot use <version> and --chaos together")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
@ -77,12 +63,12 @@ recipes.
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
		deployMeta, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !isDeployed {
 | 
			
		||||
		if !deployMeta.IsDeployed {
 | 
			
		||||
			log.Fatalf("%s is not deployed?", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -96,7 +82,7 @@ recipes.
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(versions) == 0 && !internal.Chaos {
 | 
			
		||||
		if len(versions) == 0 {
 | 
			
		||||
			log.Warn("no published versions in catalogue, trying local recipe repository")
 | 
			
		||||
			recipeVersions, err := app.Recipe.GetRecipeVersions(internal.Offline)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
@ -110,13 +96,14 @@ recipes.
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var availableUpgrades []string
 | 
			
		||||
		if deployedVersion == "unknown" {
 | 
			
		||||
		if deployMeta.Version == "unknown" {
 | 
			
		||||
			availableUpgrades = versions
 | 
			
		||||
			log.Warnf("failed to determine deployed version of %s", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		specificVersion := c.Args().Get(1)
 | 
			
		||||
		if specificVersion != "" {
 | 
			
		||||
			parsedDeployedVersion, err := tagcmp.Parse(deployedVersion)
 | 
			
		||||
			parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
@ -125,17 +112,21 @@ recipes.
 | 
			
		||||
				log.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
			if parsedSpecificVersion.IsLessThan(parsedDeployedVersion) || parsedSpecificVersion.Equals(parsedDeployedVersion) {
 | 
			
		||||
				log.Fatalf("%s is not an upgrade for %s?", deployedVersion, specificVersion)
 | 
			
		||||
				log.Fatalf("%s is not an upgrade for %s?", deployMeta.Version, specificVersion)
 | 
			
		||||
			}
 | 
			
		||||
			availableUpgrades = append(availableUpgrades, specificVersion)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		parsedDeployedVersion, err := tagcmp.Parse(deployedVersion)
 | 
			
		||||
		parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if deployedVersion != "unknown" && !internal.Chaos && specificVersion == "" {
 | 
			
		||||
		if deployMeta.Version != "unknown" && specificVersion == "" {
 | 
			
		||||
			if deployMeta.IsChaos == "true" {
 | 
			
		||||
				log.Warn("attempting to upgrade a chaos deployment")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for _, version := range versions {
 | 
			
		||||
				parsedVersion, err := tagcmp.Parse(version)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
@ -147,21 +138,27 @@ recipes.
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if len(availableUpgrades) == 0 && !internal.Force {
 | 
			
		||||
				log.Infof("no available upgrades, you're on latest (%s) ✌️", deployedVersion)
 | 
			
		||||
				log.Info("no available upgrades")
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var chosenUpgrade string
 | 
			
		||||
		if len(availableUpgrades) > 0 && !internal.Chaos {
 | 
			
		||||
		if len(availableUpgrades) > 0 {
 | 
			
		||||
			if internal.Force || internal.NoInput || specificVersion != "" {
 | 
			
		||||
				chosenUpgrade = availableUpgrades[len(availableUpgrades)-1]
 | 
			
		||||
				log.Debugf("choosing %s as version to upgrade to", chosenUpgrade)
 | 
			
		||||
			} else {
 | 
			
		||||
				msg := fmt.Sprintf("please select an upgrade (version: %s):", deployMeta.Version)
 | 
			
		||||
				if deployMeta.IsChaos == "true" {
 | 
			
		||||
					msg = fmt.Sprintf("please select an upgrade (version: %s, chaosVersion: %s):", deployMeta.Version, deployMeta.ChaosVersion)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				prompt := &survey.Select{
 | 
			
		||||
					Message: fmt.Sprintf("Please select an upgrade (current version: %s):", deployedVersion),
 | 
			
		||||
					Message: msg,
 | 
			
		||||
					Options: internal.ReverseStringList(availableUpgrades),
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if err := survey.AskOne(prompt, &chosenUpgrade); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
@ -169,8 +166,8 @@ recipes.
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if internal.Force && chosenUpgrade == "" {
 | 
			
		||||
			log.Warnf("%s is already upgraded to latest but continuing (--force/--chaos)", app.Name)
 | 
			
		||||
			chosenUpgrade = deployedVersion
 | 
			
		||||
			log.Warnf("%s is already upgraded to latest but continuing (--force)", app.Name)
 | 
			
		||||
			chosenUpgrade = deployMeta.Version
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// if release notes written after git tag published, read them before we
 | 
			
		||||
@ -199,20 +196,10 @@ recipes.
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !internal.Chaos {
 | 
			
		||||
		log.Debugf("choosing %s as version to upgrade", chosenUpgrade)
 | 
			
		||||
		if err := app.Recipe.EnsureVersion(chosenUpgrade); err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if internal.Chaos {
 | 
			
		||||
			log.Warn("chaos mode engaged")
 | 
			
		||||
			var err error
 | 
			
		||||
			chosenUpgrade, err = app.Recipe.ChaosVersion()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		abraShEnv, err := envfile.ReadAbraShEnvVars(app.Recipe.AbraShPath)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@ -226,6 +213,7 @@ recipes.
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		deployOpts := stack.Deploy{
 | 
			
		||||
			Composefiles: composeFiles,
 | 
			
		||||
			Namespace:    stackName,
 | 
			
		||||
@ -233,10 +221,12 @@ recipes.
 | 
			
		||||
			ResolveImage: stack.ResolveImageAlways,
 | 
			
		||||
			Detach:       false,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		compose, err := appPkg.GetAppComposeConfig(app.Name, deployOpts, app.Env)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		appPkg.ExposeAllEnv(stackName, compose, app.Env)
 | 
			
		||||
		appPkg.SetRecipeLabel(compose, stackName, app.Recipe.Name)
 | 
			
		||||
		appPkg.SetChaosLabel(compose, stackName, internal.Chaos)
 | 
			
		||||
@ -260,7 +250,12 @@ recipes.
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := internal.NewVersionOverview(app, deployedVersion, chosenUpgrade, releaseNotes); err != nil {
 | 
			
		||||
		chaosVersion := deployMeta.IsChaos
 | 
			
		||||
		if deployMeta.IsChaos == "true" {
 | 
			
		||||
			chaosVersion = deployMeta.ChaosVersion
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := internal.NewVersionOverview(app, deployMeta.Version, chaosVersion, chosenUpgrade, releaseNotes); err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -92,12 +92,12 @@ Passing "--force/-f" will select all volumes for removal. Be careful.
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isDeployed, _, err := stack.IsDeployed(context.Background(), cl, app.StackName())
 | 
			
		||||
		deployMeta, err := stack.IsDeployed(context.Background(), cl, app.StackName())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if isDeployed {
 | 
			
		||||
		if deployMeta.IsDeployed {
 | 
			
		||||
			log.Fatalf("%s is still deployed. Run \"abra app undeploy %s\"", app.Name, app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -13,8 +13,8 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewVersionOverview shows an upgrade or downgrade overview
 | 
			
		||||
func NewVersionOverview(app appPkg.App, currentVersion, newVersion, releaseNotes string) error {
 | 
			
		||||
	tableCol := []string{"server", "recipe", "config", "domain", "current version", "to be deployed"}
 | 
			
		||||
func NewVersionOverview(app appPkg.App, currentVersion, chaosVersion, newVersion, releaseNotes string) error {
 | 
			
		||||
	tableCol := []string{"server", "recipe", "config", "domain", "version", "chaos", "to deploy"}
 | 
			
		||||
	table := formatter.CreateTable(tableCol)
 | 
			
		||||
 | 
			
		||||
	deployConfig := "compose.yml"
 | 
			
		||||
@ -27,7 +27,15 @@ func NewVersionOverview(app appPkg.App, currentVersion, newVersion, releaseNotes
 | 
			
		||||
		server = "local"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	table.Append([]string{server, app.Recipe.Name, deployConfig, app.Domain, currentVersion, newVersion})
 | 
			
		||||
	table.Append([]string{
 | 
			
		||||
		server,
 | 
			
		||||
		app.Recipe.Name,
 | 
			
		||||
		deployConfig,
 | 
			
		||||
		app.Domain,
 | 
			
		||||
		currentVersion,
 | 
			
		||||
		chaosVersion,
 | 
			
		||||
		newVersion,
 | 
			
		||||
	})
 | 
			
		||||
	table.Render()
 | 
			
		||||
 | 
			
		||||
	if releaseNotes != "" && newVersion != "" {
 | 
			
		||||
@ -112,8 +120,8 @@ func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeployOverview shows a deployment overview
 | 
			
		||||
func DeployOverview(app appPkg.App, version, message string) error {
 | 
			
		||||
	tableCol := []string{"server", "recipe", "config", "domain", "version"}
 | 
			
		||||
func DeployOverview(app appPkg.App, version, chaosVersion, message string) error {
 | 
			
		||||
	tableCol := []string{"server", "recipe", "config", "domain", "version", "chaos"}
 | 
			
		||||
	table := formatter.CreateTable(tableCol)
 | 
			
		||||
 | 
			
		||||
	deployConfig := "compose.yml"
 | 
			
		||||
@ -126,7 +134,14 @@ func DeployOverview(app appPkg.App, version, message string) error {
 | 
			
		||||
		server = "local"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	table.Append([]string{server, app.Recipe.Name, deployConfig, app.Domain, version})
 | 
			
		||||
	table.Append([]string{
 | 
			
		||||
		server,
 | 
			
		||||
		app.Recipe.Name,
 | 
			
		||||
		deployConfig,
 | 
			
		||||
		app.Domain,
 | 
			
		||||
		version,
 | 
			
		||||
		chaosVersion,
 | 
			
		||||
	})
 | 
			
		||||
	table.Render()
 | 
			
		||||
 | 
			
		||||
	if NoInput {
 | 
			
		||||
 | 
			
		||||
@ -253,20 +253,20 @@ func getLatestUpgrade(cl *dockerclient.Client, stackName string, recipeName stri
 | 
			
		||||
func getDeployedVersion(cl *dockerclient.Client, stackName string, recipeName string) (string, error) {
 | 
			
		||||
	log.Debugf("retrieve deployed version whether %s is already deployed", stackName)
 | 
			
		||||
 | 
			
		||||
	isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
	deployMeta, err := stack.IsDeployed(context.Background(), cl, stackName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !isDeployed {
 | 
			
		||||
	if !deployMeta.IsDeployed {
 | 
			
		||||
		return "", fmt.Errorf("%s is not deployed?", stackName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if deployedVersion == "unknown" {
 | 
			
		||||
	if deployMeta.Version == "unknown" {
 | 
			
		||||
		return "", fmt.Errorf("failed to determine deployed version of %s", stackName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return deployedVersion, nil
 | 
			
		||||
	return deployMeta.Version, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getAvailableUpgrades returns all available versions of an app that are newer
 | 
			
		||||
 | 
			
		||||
@ -494,13 +494,13 @@ func GetAppComposeConfig(recipe string, opts stack.Deploy, appEnv envfile.AppEnv
 | 
			
		||||
func ExposeAllEnv(stackName string, compose *composetypes.Config, appEnv envfile.AppEnv) {
 | 
			
		||||
	for _, service := range compose.Services {
 | 
			
		||||
		if service.Name == "app" {
 | 
			
		||||
			log.Debugf("Add the following environment to the app service config of %s:", stackName)
 | 
			
		||||
			log.Debugf("add the following environment to the app service config of %s:", stackName)
 | 
			
		||||
			for k, v := range appEnv {
 | 
			
		||||
				_, exists := service.Environment[k]
 | 
			
		||||
				if !exists {
 | 
			
		||||
					value := v
 | 
			
		||||
					service.Environment[k] = &value
 | 
			
		||||
					log.Debugf("Add Key: %s Value: %s to %s", k, value, stackName)
 | 
			
		||||
					log.Debugf("add env var: %s value: %s to %s", k, value, stackName)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/signal"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	stdlibErr "errors"
 | 
			
		||||
@ -35,7 +36,7 @@ const (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Timeout to wait until docker services converge, default is 50s (random choice)
 | 
			
		||||
var WaitTimeout int = 50
 | 
			
		||||
var WaitTimeout = 50
 | 
			
		||||
 | 
			
		||||
type StackStatus struct {
 | 
			
		||||
	Services []swarm.Service
 | 
			
		||||
@ -96,35 +97,64 @@ func GetDeployedServicesByName(ctx context.Context, cl *dockerClient.Client, sta
 | 
			
		||||
	return StackStatus{services, nil}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsDeployed chekcks whether an appp is deployed or not.
 | 
			
		||||
func IsDeployed(ctx context.Context, cl *dockerClient.Client, stackName string) (bool, string, error) {
 | 
			
		||||
	version := "unknown"
 | 
			
		||||
	isDeployed := false
 | 
			
		||||
// DeployMeta is runtime metadata about an app deployment.
 | 
			
		||||
type DeployMeta struct {
 | 
			
		||||
	IsDeployed   bool   // whether the app is deployed or not
 | 
			
		||||
	Version      string // the deployed version
 | 
			
		||||
	IsChaos      string // whether or not the deployment is --chaos
 | 
			
		||||
	ChaosVersion string // the --chaos deployment version
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsDeployed gathers metadata about an app deployment.
 | 
			
		||||
func IsDeployed(ctx context.Context, cl *dockerClient.Client, stackName string) (DeployMeta, error) {
 | 
			
		||||
	deployMeta := DeployMeta{
 | 
			
		||||
		IsDeployed:   false,
 | 
			
		||||
		Version:      "unknown",
 | 
			
		||||
		IsChaos:      "false", // NOTE(d1): match string type used on label
 | 
			
		||||
		ChaosVersion: "false", // NOTE(d1): match string type used on label
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	filter := filters.NewArgs()
 | 
			
		||||
	filter.Add("label", fmt.Sprintf("%s=%s", convert.LabelNamespace, stackName))
 | 
			
		||||
 | 
			
		||||
	services, err := cl.ServiceList(ctx, types.ServiceListOptions{Filters: filter})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, version, err
 | 
			
		||||
		return deployMeta, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(services) > 0 {
 | 
			
		||||
		deployMeta.IsDeployed = true
 | 
			
		||||
 | 
			
		||||
		for _, service := range services {
 | 
			
		||||
			splitter := fmt.Sprintf("%s_", stackName)
 | 
			
		||||
			serviceName := strings.Split(service.Spec.Name, splitter)[1]
 | 
			
		||||
 | 
			
		||||
			if serviceName == "app" {
 | 
			
		||||
				labelKey := fmt.Sprintf("coop-cloud.%s.version", stackName)
 | 
			
		||||
				if deployedVersion, ok := service.Spec.Labels[labelKey]; ok {
 | 
			
		||||
				version = deployedVersion
 | 
			
		||||
				break
 | 
			
		||||
					deployMeta.Version = deployedVersion
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				labelKey = fmt.Sprintf("coop-cloud.%s.chaos", stackName)
 | 
			
		||||
				if isChaos, ok := service.Spec.Labels[labelKey]; ok {
 | 
			
		||||
					deployMeta.IsChaos = isChaos
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				labelKey = fmt.Sprintf("coop-cloud.%s.chaos-version", stackName)
 | 
			
		||||
				if chaosVersion, ok := service.Spec.Labels[labelKey]; ok {
 | 
			
		||||
					deployMeta.ChaosVersion = chaosVersion
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log.Debugf("%s has been detected as deployed with version %s", stackName, version)
 | 
			
		||||
		log.Debugf("%s has been detected as deployed: %v", stackName, deployMeta)
 | 
			
		||||
 | 
			
		||||
		return true, version, nil
 | 
			
		||||
		return deployMeta, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Debugf("%s has been detected as not deployed", stackName)
 | 
			
		||||
	return isDeployed, version, nil
 | 
			
		||||
 | 
			
		||||
	return deployMeta, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// pruneServices removes services that are no longer referenced in the source
 | 
			
		||||
 | 
			
		||||
@ -72,80 +72,6 @@ teardown(){
 | 
			
		||||
  assert_equal $(_get_current_hash) $wantHash
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@test "bail if unstaged changes and no --chaos" {
 | 
			
		||||
  run bash -c "echo foo >> $ABRA_DIR/recipes/$TEST_RECIPE/foo"
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
 | 
			
		||||
 | 
			
		||||
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" status
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial 'foo'
 | 
			
		||||
 | 
			
		||||
  run $ABRA app rollback "$TEST_APP_DOMAIN" --no-input --no-converge-checks
 | 
			
		||||
  assert_failure
 | 
			
		||||
  assert_output --partial 'locally unstaged changes'
 | 
			
		||||
  refute_output --partial 'chaos'
 | 
			
		||||
 | 
			
		||||
  run rm -rf "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
 | 
			
		||||
  assert_not_exists "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# bats test_tags=slow
 | 
			
		||||
@test "do not bail if unstaged changes and --chaos" {
 | 
			
		||||
  run bash -c 'echo "unstaged changes" >> "$ABRA_DIR/recipes/$TEST_RECIPE/foo"'
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
 | 
			
		||||
 | 
			
		||||
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" status
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial 'foo'
 | 
			
		||||
 | 
			
		||||
  run $ABRA app deploy "$TEST_APP_DOMAIN" \
 | 
			
		||||
    --chaos --no-input --no-converge-checks
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial 'chaos'
 | 
			
		||||
 | 
			
		||||
  run $ABRA app rollback "$TEST_APP_DOMAIN" \
 | 
			
		||||
    --chaos --no-input --no-converge-checks
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial 'chaos'
 | 
			
		||||
 | 
			
		||||
  _undeploy_app
 | 
			
		||||
 | 
			
		||||
  run rm -rf "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
 | 
			
		||||
  assert_not_exists "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# bats test_tags=slow
 | 
			
		||||
@test "ensure same commit if --chaos" {
 | 
			
		||||
  latestCommit="$(git -C "$ABRA_DIR/recipes/$TEST_RECIPE" rev-parse --short HEAD)"
 | 
			
		||||
 | 
			
		||||
  run $ABRA app deploy "$TEST_APP_DOMAIN" \
 | 
			
		||||
    --no-input --chaos
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial "${latestCommit}"
 | 
			
		||||
  assert_output --partial 'chaos'
 | 
			
		||||
 | 
			
		||||
  run $ABRA app rollback "$TEST_APP_DOMAIN" \
 | 
			
		||||
    --chaos --no-input --no-converge-checks
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial "$latestCommit"
 | 
			
		||||
  assert_output --partial 'chaos'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# bats test_tags=slow
 | 
			
		||||
@test "no rollback if lint error" {
 | 
			
		||||
  _deploy_app
 | 
			
		||||
 | 
			
		||||
  run sed -i '/traefik.enable=.*/d' "$ABRA_DIR/recipes/$TEST_RECIPE/compose.yml"
 | 
			
		||||
  assert_success
 | 
			
		||||
 | 
			
		||||
  run $ABRA app rollback "$TEST_APP_DOMAIN" \
 | 
			
		||||
    --no-input --chaos --chaos --no-converge-checks
 | 
			
		||||
  assert_failure
 | 
			
		||||
  assert_output --partial 'failed lint checks'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@test "error if not already deployed" {
 | 
			
		||||
  run $ABRA app rollback "$TEST_APP_DOMAIN" --no-input
 | 
			
		||||
  assert_failure
 | 
			
		||||
@ -174,13 +100,6 @@ teardown(){
 | 
			
		||||
  assert_output --partial 'is not a downgrade'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@test "bail out if specific version and chaos" {
 | 
			
		||||
  run $ABRA app rollback "$TEST_APP_DOMAIN" "0.2.0+1.21.0" \
 | 
			
		||||
    --chaos --no-input --no-converge-checks
 | 
			
		||||
  assert_failure
 | 
			
		||||
  assert_output --partial 'cannot use'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# bats test_tags=slow
 | 
			
		||||
@test "rollback to previous version" {
 | 
			
		||||
  run $ABRA app deploy "$TEST_APP_DOMAIN" "0.1.1+1.20.2" --no-input --no-converge-checks
 | 
			
		||||
@ -202,3 +121,27 @@ teardown(){
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial "0.1.0+1.20.0"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# bats test_tags=slow
 | 
			
		||||
@test "rollback chaos deployment" {
 | 
			
		||||
  tagHash=$(_get_tag_hash "0.2.0+1.21.0")
 | 
			
		||||
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" checkout "$tagHash"
 | 
			
		||||
  assert_success
 | 
			
		||||
 | 
			
		||||
  run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input --no-converge-checks --chaos
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial "${tagHash:0:8}"
 | 
			
		||||
 | 
			
		||||
  run $ABRA app rollback "$TEST_APP_DOMAIN" "0.1.1+1.20.2" --no-input --no-converge-checks
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial "0.1.1+1.20.2"
 | 
			
		||||
  assert_output --partial "${tagHash:0:8}"
 | 
			
		||||
 | 
			
		||||
  run $ABRA app rollback "$TEST_APP_DOMAIN" "0.1.0+1.20.0" --no-input --no-converge-checks
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial "0.1.0+1.20.0"
 | 
			
		||||
 | 
			
		||||
  tagHash=$(_get_tag_hash "0.1.1+1.20.2")
 | 
			
		||||
  refute_output --partial "${tagHash:0:8}"
 | 
			
		||||
  assert_output --partial "false"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -41,6 +41,9 @@ teardown(){
 | 
			
		||||
@test "undeploy app" {
 | 
			
		||||
  _deploy_app
 | 
			
		||||
  _undeploy_app
 | 
			
		||||
 | 
			
		||||
  # NOTE(d1): ensure not chaos undeploy
 | 
			
		||||
  assert_output --partial 'false'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# bats test_tags=slow
 | 
			
		||||
@ -50,3 +53,15 @@ teardown(){
 | 
			
		||||
  run $ABRA app undeploy "$TEST_APP_DOMAIN" --no-input --prune
 | 
			
		||||
  assert_success
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# bats test_tags=slow
 | 
			
		||||
@test "undeploy chaos deployment" {
 | 
			
		||||
  run $ABRA app deploy "$TEST_APP_DOMAIN" \
 | 
			
		||||
    --no-input --no-converge-checks --chaos
 | 
			
		||||
 | 
			
		||||
  _undeploy_app
 | 
			
		||||
  
 | 
			
		||||
  # NOTE(d1): ensure chaos undeploy
 | 
			
		||||
  assert_output --partial ${_get_current_hash:0:8}
 | 
			
		||||
  refute_output --partial 'false'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -43,26 +43,6 @@ teardown(){
 | 
			
		||||
  assert_output --partial 'is not an upgrade'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@test "bail out if specific version and chaos" {
 | 
			
		||||
  run $ABRA app upgrade "$TEST_APP_DOMAIN" "0.2.0+1.21.0" \
 | 
			
		||||
    --chaos --no-input --no-converge-checks
 | 
			
		||||
  assert_failure
 | 
			
		||||
  assert_output --partial 'cannot use'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# bats test_tags=slow
 | 
			
		||||
@test "no upgrade if lint error" {
 | 
			
		||||
  _deploy_app
 | 
			
		||||
 | 
			
		||||
  run sed -i '/traefik.enable=.*/d' "$ABRA_DIR/recipes/$TEST_RECIPE/compose.yml"
 | 
			
		||||
  assert_success
 | 
			
		||||
 | 
			
		||||
  run $ABRA app upgrade "$TEST_APP_DOMAIN" \
 | 
			
		||||
    --no-input --no-converge-checks --chaos
 | 
			
		||||
  assert_failure
 | 
			
		||||
  assert_output --partial 'failed lint checks'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# bats test_tags=slow
 | 
			
		||||
@test "no upgrade if on latest version" {
 | 
			
		||||
  _deploy_app
 | 
			
		||||
@ -185,3 +165,27 @@ teardown(){
 | 
			
		||||
  assert_output --partial 'release notes bar' # 0.1.1+1.20.2
 | 
			
		||||
  assert_output --partial 'release notes baz' # 0.2.0+1.21.0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# bats test_tags=slow
 | 
			
		||||
@test "upgrade chaos deployment" {
 | 
			
		||||
  tagHash=$(_get_tag_hash "0.1.0+1.20.0")
 | 
			
		||||
  run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" checkout "$tagHash"
 | 
			
		||||
  assert_success
 | 
			
		||||
 | 
			
		||||
  run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input --no-converge-checks --chaos
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial "${tagHash:0:8}"
 | 
			
		||||
 | 
			
		||||
  run $ABRA app upgrade "$TEST_APP_DOMAIN" "0.1.1+1.20.2" --no-input --no-converge-checks
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial "0.1.1+1.20.2"
 | 
			
		||||
  assert_output --partial "${tagHash:0:8}"
 | 
			
		||||
 | 
			
		||||
  run $ABRA app upgrade "$TEST_APP_DOMAIN" "0.2.0+1.21.0" --no-input --no-converge-checks
 | 
			
		||||
  assert_success
 | 
			
		||||
  assert_output --partial "0.2.0+1.21.0"
 | 
			
		||||
 | 
			
		||||
  tagHash=$(_get_tag_hash "0.1.1+1.20.2")
 | 
			
		||||
  refute_output --partial "${tagHash:0:8}"
 | 
			
		||||
  assert_output --partial "false"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user