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