forked from toolshed/abra
.chglog
.gitea
cli
app
app.go
backup.go
check.go
config.go
cp.go
deploy.go
list.go
logs.go
new.go
ps.go
remove.go
restore.go
rollback.go
run.go
secret.go
undeploy.go
upgrade.go
version.go
volume.go
catalogue
formatter
internal
recipe
server
cli.go
upgrade.go
version.go
cmd
pkg
scripts
tests
.drone.yml
.envrc.sample
.gitignore
.goreleaser.yml
Makefile
README.md
go.mod
go.sum
159 lines
4.0 KiB
Go
159 lines
4.0 KiB
Go
package app
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"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"
|
|
"coopcloud.tech/abra/pkg/client"
|
|
"github.com/AlecAivazis/survey/v2"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
var appRollbackCommand = &cli.Command{
|
|
Name: "rollback",
|
|
Usage: "Roll an app back to a previous 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.
|
|
|
|
You may pass "--force/-f" to downgrade to the same version again. This can be
|
|
useful if the container runtime has gotten into a weird state or your doing
|
|
some live hacking.
|
|
|
|
This action could be destructive, please ensure you have a copy of your app
|
|
data beforehand - see "abra app backup <app>" for more.
|
|
`,
|
|
BashComplete: func(c *cli.Context) {
|
|
appNames, err := config.GetAppNames()
|
|
if err != nil {
|
|
logrus.Warn(err)
|
|
}
|
|
if c.NArg() > 0 {
|
|
return
|
|
}
|
|
for _, a := range appNames {
|
|
fmt.Println(a)
|
|
}
|
|
},
|
|
Action: func(c *cli.Context) error {
|
|
app := internal.ValidateApp(c)
|
|
stackName := app.StackName()
|
|
|
|
cl, err := client.New(app.Server)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
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 deployedVersion == "" {
|
|
logrus.Fatalf("failed to determine version of deployed '%s'", app.Name)
|
|
}
|
|
|
|
if !isDeployed {
|
|
logrus.Fatalf("'%s' is not deployed?", app.Name)
|
|
}
|
|
|
|
versions, err := catalogue.GetRecipeCatalogueVersions(app.Type)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
if len(availableDowngrades) == 0 {
|
|
logrus.Fatal("no available downgrades, you're on latest")
|
|
}
|
|
|
|
// 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 := NewVersionOverview(app, deployedVersion, chosenDowngrade); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|
|
|
|
if err := stack.RunDeploy(cl, deployOpts, compose); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|