forked from toolshed/abra
		
	@ -3,14 +3,15 @@ package app
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"context"
 | 
			
		||||
 | 
			
		||||
	"coopcloud.tech/abra/pkg/catalogue"
 | 
			
		||||
	stack "coopcloud.tech/abra/pkg/client/stack"
 | 
			
		||||
	"coopcloud.tech/abra/pkg/config"
 | 
			
		||||
	"coopcloud.tech/abra/pkg/recipe"
 | 
			
		||||
	"coopcloud.tech/tagcmp"
 | 
			
		||||
 | 
			
		||||
	"coopcloud.tech/abra/cli/internal"
 | 
			
		||||
	appPkg "coopcloud.tech/abra/pkg/app"
 | 
			
		||||
	"coopcloud.tech/abra/pkg/catalogue"
 | 
			
		||||
	"coopcloud.tech/abra/pkg/client"
 | 
			
		||||
	"github.com/AlecAivazis/survey/v2"
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
	"github.com/urfave/cli/v2"
 | 
			
		||||
)
 | 
			
		||||
@ -18,8 +19,14 @@ import (
 | 
			
		||||
var appRollbackCommand = &cli.Command{
 | 
			
		||||
	Name:      "rollback",
 | 
			
		||||
	Usage:     "Roll an app back to a previous version",
 | 
			
		||||
	Aliases:   []string{"r"},
 | 
			
		||||
	ArgsUsage: "[<version>]",
 | 
			
		||||
	Aliases:   []string{"r", "downgrade"},
 | 
			
		||||
	ArgsUsage: "<app>",
 | 
			
		||||
	Flags: []cli.Flag{
 | 
			
		||||
		internal.ForceFlag,
 | 
			
		||||
	},
 | 
			
		||||
	Description: `
 | 
			
		||||
This command rolls an app back to a previous version if one exists.
 | 
			
		||||
`,
 | 
			
		||||
	BashComplete: func(c *cli.Context) {
 | 
			
		||||
		appNames, err := config.GetAppNames()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@ -34,48 +41,110 @@ var appRollbackCommand = &cli.Command{
 | 
			
		||||
	},
 | 
			
		||||
	Action: func(c *cli.Context) error {
 | 
			
		||||
		app := internal.ValidateApp(c)
 | 
			
		||||
		stackName := app.StackName()
 | 
			
		||||
 | 
			
		||||
		ctx := context.Background()
 | 
			
		||||
		cl, err := client.New(app.Server)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		recipeMeta, err := catalogue.GetRecipeMeta(app.Type)
 | 
			
		||||
		logrus.Debugf("checking whether '%s' is already deployed", stackName)
 | 
			
		||||
 | 
			
		||||
		isDeployed, deployedVersion, err := stack.IsDeployed(c.Context, cl, stackName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		if len(recipeMeta.Versions) == 0 {
 | 
			
		||||
			logrus.Fatalf("no catalogue versions available for '%s'", app.Type)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		deployedVersions, isDeployed, err := appPkg.DeployedVersions(ctx, cl, app)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
		if deployedVersion == "" {
 | 
			
		||||
			logrus.Fatalf("failed to determine version of deployed '%s'", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !isDeployed {
 | 
			
		||||
			logrus.Fatalf("'%s' is not deployed?", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
		if _, exists := deployedVersions["app"]; !exists {
 | 
			
		||||
			logrus.Fatalf("no versioned 'app' service for '%s', cannot determine version", app.Name)
 | 
			
		||||
 | 
			
		||||
		versions, err := catalogue.GetRecipeCatalogueVersions(app.Type)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		version := c.Args().Get(1)
 | 
			
		||||
		if version == "" {
 | 
			
		||||
			// TODO:
 | 
			
		||||
			// using deployedVersions["app"], get index+1 version from catalogue
 | 
			
		||||
			// otherwise bail out saying there is nothing to rollback to
 | 
			
		||||
		} else {
 | 
			
		||||
			// TODO
 | 
			
		||||
			// ensure this version is listed in the catalogue
 | 
			
		||||
			// ensure this version is "older" (lower down in the list)
 | 
			
		||||
		var availableDowngrades []string
 | 
			
		||||
		for _, version := range versions {
 | 
			
		||||
			parsedDeployedVersion, err := tagcmp.Parse(deployedVersion)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				logrus.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
			parsedVersion, err := tagcmp.Parse(version)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				logrus.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
			if parsedVersion != parsedDeployedVersion && parsedVersion.IsLessThan(parsedDeployedVersion) {
 | 
			
		||||
				availableDowngrades = append(availableDowngrades, version)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// TODO
 | 
			
		||||
		// display table of existing state and expected state and prompt
 | 
			
		||||
		// run the deployment with this target version!
 | 
			
		||||
		if len(availableDowngrades) == 0 {
 | 
			
		||||
			logrus.Fatal("no available downgrades, you're on latest")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		logrus.Fatal("command not implemented yet, coming soon TM")
 | 
			
		||||
		// FIXME: jeezus golang why do you not have a list reverse function
 | 
			
		||||
		for i, j := 0, len(availableDowngrades)-1; i < j; i, j = i+1, j-1 {
 | 
			
		||||
			availableDowngrades[i], availableDowngrades[j] = availableDowngrades[j], availableDowngrades[i]
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var chosenDowngrade string
 | 
			
		||||
		if !internal.Force {
 | 
			
		||||
			prompt := &survey.Select{
 | 
			
		||||
				Message: fmt.Sprintf("Please select a downgrade (current version: '%s'):", deployedVersion),
 | 
			
		||||
				Options: availableDowngrades,
 | 
			
		||||
			}
 | 
			
		||||
			if err := survey.AskOne(prompt, &chosenDowngrade); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if internal.Force {
 | 
			
		||||
			chosenDowngrade = availableDowngrades[0]
 | 
			
		||||
			logrus.Debugf("choosing '%s' as version to downgrade to", chosenDowngrade)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := recipe.EnsureVersion(app.Type, chosenDowngrade); err != nil {
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		abraShPath := fmt.Sprintf("%s/%s/%s", config.APPS_DIR, app.Type, "abra.sh")
 | 
			
		||||
		abraShEnv, err := config.ReadAbraShEnvVars(abraShPath)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		for k, v := range abraShEnv {
 | 
			
		||||
			app.Env[k] = v
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		composeFiles, err := config.GetAppComposeFiles(app.Type, app.Env)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		deployOpts := stack.Deploy{
 | 
			
		||||
			Composefiles: composeFiles,
 | 
			
		||||
			Namespace:    stackName,
 | 
			
		||||
			Prune:        false,
 | 
			
		||||
			ResolveImage: stack.ResolveImageAlways,
 | 
			
		||||
		}
 | 
			
		||||
		compose, err := config.GetAppComposeConfig(app.Name, deployOpts, app.Env)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !internal.Force {
 | 
			
		||||
			if err := DeployOverview(app, chosenDowngrade); err != nil {
 | 
			
		||||
				logrus.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := stack.RunDeploy(cl, deployOpts, compose); err != nil {
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,9 @@ var appUpgradeCommand = &cli.Command{
 | 
			
		||||
	Aliases:   []string{"u"},
 | 
			
		||||
	Usage:     "Upgrade an app",
 | 
			
		||||
	ArgsUsage: "<app>",
 | 
			
		||||
	Flags: []cli.Flag{
 | 
			
		||||
		internal.ForceFlag,
 | 
			
		||||
	},
 | 
			
		||||
	Description: `
 | 
			
		||||
This command supports upgrading an app. You can use it to choose and roll out a
 | 
			
		||||
new upgrade to an existing app. This command specifically supports changing the
 | 
			
		||||
@ -44,11 +47,11 @@ could be destructive, please ensure you have a copy of your app data beforehand
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if deployedVersion == "" {
 | 
			
		||||
			logrus.Fatal("failed to determine version of deployed '%s'", app.Name)
 | 
			
		||||
			logrus.Fatalf("failed to determine version of deployed '%s'", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !isDeployed {
 | 
			
		||||
			logrus.Fatal("'%s' is not deployed?", app.Name)
 | 
			
		||||
			logrus.Fatalf("'%s' is not deployed?", app.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		versions, err := catalogue.GetRecipeCatalogueVersions(app.Type)
 | 
			
		||||
@ -76,13 +79,20 @@ could be destructive, please ensure you have a copy of your app data beforehand
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var chosenUpgrade string
 | 
			
		||||
		if !internal.Force {
 | 
			
		||||
			prompt := &survey.Select{
 | 
			
		||||
			Message: "Please select an upgrade:",
 | 
			
		||||
				Message: fmt.Sprintf("Please select an upgrade (current version: '%s'):", deployedVersion),
 | 
			
		||||
				Options: availableUpgrades,
 | 
			
		||||
			}
 | 
			
		||||
			if err := survey.AskOne(prompt, &chosenUpgrade); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if internal.Force {
 | 
			
		||||
			chosenUpgrade = availableUpgrades[len(availableUpgrades)-1]
 | 
			
		||||
			logrus.Debugf("choosing '%s' as version to upgrade to", chosenUpgrade)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := recipe.EnsureVersion(app.Type, chosenUpgrade); err != nil {
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
@ -112,9 +122,11 @@ could be destructive, please ensure you have a copy of your app data beforehand
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !internal.Force {
 | 
			
		||||
			if err := DeployOverview(app, chosenUpgrade); err != nil {
 | 
			
		||||
				logrus.Fatal(err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := stack.RunDeploy(cl, deployOpts, compose); err != nil {
 | 
			
		||||
			logrus.Fatal(err)
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user