feat: git hash arg for deploy #434
@ -5,11 +5,10 @@ import (
|
||||
)
|
||||
|
||||
var AppCommand = cli.Command{
|
||||
Name: "app",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Manage apps",
|
||||
ArgsUsage: "<domain>",
|
||||
Description: "Functionality for managing the life cycle of your apps",
|
||||
Name: "app",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Manage apps",
|
||||
ArgsUsage: "<domain>",
|
||||
Subcommands: []cli.Command{
|
||||
appBackupCommand,
|
||||
appCheckCommand,
|
||||
|
@ -29,10 +29,11 @@ They can be run within the context of a service (e.g. app) or locally on your
|
||||
work station by passing "--local". Arguments can be passed into these functions
|
||||
using the "-- <args>" syntax.
|
||||
|
||||
Example:
|
||||
**WARNING**: options must be passed directly after the sub-command "cmd".
|
||||
|
||||
abra app cmd example.com app create_user -- me@example.com
|
||||
`,
|
||||
EXAMPLE:
|
||||
|
||||
abra app cmd --local example.com app create_user -- me@example.com`,
|
||||
ArgsUsage: "<domain> [<service>] <command> [-- <args>]",
|
||||
Flags: []cli.Flag{
|
||||
internal.DebugFlag,
|
||||
|
@ -43,7 +43,7 @@ var appConfigCommand = cli.Command{
|
||||
ed, ok := os.LookupEnv("EDITOR")
|
||||
if !ok {
|
||||
edPrompt := &survey.Select{
|
||||
Message: "Which editor do you wish to use?",
|
||||
Message: "which editor do you wish to use?",
|
||||
Options: []string{"vi", "vim", "nvim", "nano", "pico", "emacs"},
|
||||
}
|
||||
if err := survey.AskOne(edPrompt, &ed); err != nil {
|
||||
|
@ -35,17 +35,18 @@ var appDeployCommand = cli.Command{
|
||||
internal.OfflineFlag,
|
||||
},
|
||||
Before: internal.SubCommandBefore,
|
||||
Description: `
|
||||
Deploy an app. It does not support incrementing the version of a deployed app,
|
||||
for this you need to look at the "abra app upgrade <domain>" command.
|
||||
Description: `Deploy an app.
|
||||
|
||||
You may pass "--force" to re-deploy the same version again. This can be useful
|
||||
if the container runtime has gotten into a weird state.
|
||||
This command supports chaos operations. Use "--chaos" to deploy your recipe
|
||||
checkout as-is. Recipe commit hashes are also supported values for
|
||||
"[<version>]". Please note, "upgrade"/"rollback" do not support chaos
|
||||
operations.
|
||||
|
||||
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.
|
||||
`,
|
||||
EXAMPLE:
|
||||
|
||||
abra app deploy foo.example.com
|
||||
abra app deploy foo.example.com 1.2.3+3.2.1
|
||||
abra app deploy foo.example.com 1e83340e`,
|
||||
BashComplete: autocomplete.AppNameComplete,
|
||||
Action: func(c *cli.Context) error {
|
||||
app := internal.ValidateApp(c)
|
||||
@ -76,6 +77,9 @@ recipes.
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// NOTE(d1): handles "<version> as git hash" use case
|
||||
var isChaosCommit bool
|
||||
|
||||
// NOTE(d1): check out specific version before dealing with secrets. This
|
||||
// is because we need to deal with GetComposeFiles under the hood and these
|
||||
// files change from version to version which therefore affects which
|
||||
@ -84,9 +88,17 @@ recipes.
|
||||
if specificVersion != "" {
|
||||
version = specificVersion
|
||||
log.Debugf("choosing %s as version to deploy", version)
|
||||
if err := app.Recipe.EnsureVersion(version); err != nil {
|
||||
|
||||
var err error
|
||||
isChaosCommit, err = app.Recipe.EnsureVersion(version)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if isChaosCommit {
|
||||
log.Debugf("assuming '%s' is a chaos commit", version)
|
||||
internal.Chaos = true
|
||||
}
|
||||
}
|
||||
|
||||
secStats, err := secret.PollSecretsStatus(cl, app)
|
||||
@ -119,10 +131,10 @@ recipes.
|
||||
}
|
||||
|
||||
if len(versions) == 0 && !internal.Chaos {
|
||||
log.Warn("no published versions in catalogue, trying local recipe repository")
|
||||
log.Debug("no published versions in catalogue, trying local recipe repository")
|
||||
recipeVersions, err := app.Recipe.GetRecipeVersions(internal.Offline)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
for _, recipeVersion := range recipeVersions {
|
||||
for version := range recipeVersion {
|
||||
@ -134,7 +146,7 @@ recipes.
|
||||
if len(versions) > 0 && !internal.Chaos {
|
||||
version = versions[len(versions)-1]
|
||||
log.Debugf("choosing %s as version to deploy", version)
|
||||
if err := app.Recipe.EnsureVersion(version); err != nil {
|
||||
if _, err := app.Recipe.EnsureVersion(version); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
@ -150,10 +162,20 @@ recipes.
|
||||
chaosVersion := "false"
|
||||
if internal.Chaos {
|
||||
log.Warnf("chaos mode engaged")
|
||||
var err error
|
||||
chaosVersion, err = app.Recipe.ChaosVersion()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
||||
if isChaosCommit {
|
||||
chaosVersion = specificVersion
|
||||
versionLabelLocal, err := app.Recipe.GetVersionLabelLocal()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
version = versionLabelLocal
|
||||
} else {
|
||||
var err error
|
||||
chaosVersion, err = app.Recipe.ChaosVersion()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,8 +77,7 @@ generate a report of all your apps.
|
||||
|
||||
By passing the "--status/-S" flag, you can query all your servers for the
|
||||
actual live deployment status. Depending on how many servers you manage, this
|
||||
can take some time.
|
||||
`,
|
||||
can take some time.`,
|
||||
Flags: []cli.Flag{
|
||||
internal.DebugFlag,
|
||||
internal.MachineReadableFlag,
|
||||
|
@ -19,8 +19,8 @@ import (
|
||||
)
|
||||
|
||||
var appNewDescription = `
|
||||
Take a recipe and uses it to create a new app. This new app configuration is
|
||||
stored in your ~/.abra directory under the appropriate server.
|
||||
Creates a new app from a default recipe. This new app configuration is stored
|
||||
in your $ABRA_DIR directory under the appropriate server.
|
||||
|
||||
This command does not deploy your app for you. You will need to run "abra app
|
||||
deploy <domain>" to do so.
|
||||
@ -35,8 +35,7 @@ store them somewhere safe.
|
||||
|
||||
You can use the "--pass/-P" to store these generated passwords locally in a
|
||||
pass store (see passwordstore.org for more). The pass command must be available
|
||||
on your $PATH.
|
||||
`
|
||||
on your $PATH.`
|
||||
|
||||
var appNewCommand = cli.Command{
|
||||
Name: "new",
|
||||
@ -92,7 +91,7 @@ var appNewCommand = cli.Command{
|
||||
version = tag
|
||||
}
|
||||
|
||||
if err := recipe.EnsureVersion(version); err != nil {
|
||||
if _, err := recipe.EnsureVersion(version); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
@ -101,7 +100,7 @@ var appNewCommand = cli.Command{
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := recipe.EnsureVersion(c.Args().Get(1)); err != nil {
|
||||
if _, err := recipe.EnsureVersion(c.Args().Get(1)); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -174,22 +173,25 @@ var appNewCommand = cli.Command{
|
||||
table := formatter.CreateTable(tableCol)
|
||||
table.Append([]string{internal.NewAppServer, recipe.Name, internal.Domain})
|
||||
|
||||
fmt.Println(fmt.Sprintf("A new %s app has been created! Here is an overview:", recipe.Name))
|
||||
log.Infof("new app '%s' created 🌞", recipe.Name)
|
||||
|
||||
fmt.Println("")
|
||||
table.Render()
|
||||
fmt.Println("")
|
||||
fmt.Println("You can configure this app by running the following:")
|
||||
|
||||
fmt.Println("Configure this app:")
|
||||
fmt.Println(fmt.Sprintf("\n abra app config %s", internal.Domain))
|
||||
|
||||
fmt.Println("")
|
||||
fmt.Println("You can deploy this app by running the following:")
|
||||
fmt.Println("Deploy this app:")
|
||||
fmt.Println(fmt.Sprintf("\n abra app deploy %s", internal.Domain))
|
||||
|
||||
if len(secrets) > 0 {
|
||||
fmt.Println("")
|
||||
fmt.Println("Here are your generated secrets:")
|
||||
fmt.Println("Generated secrets:")
|
||||
fmt.Println("")
|
||||
secretTable.Render()
|
||||
log.Warn("generated secrets are not shown again, please take note of them NOW")
|
||||
log.Warn("Generated secrets are not shown again, please take note of them NOW")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -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(deployMeta.Version); err != nil {
|
||||
if _, err := app.Recipe.EnsureVersion(deployMeta.Version); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
|
@ -36,8 +36,7 @@ Please note, if you delete the local app env file without removing volumes and
|
||||
secrets first, Abra will *not* be able to help you remove them afterwards.
|
||||
|
||||
To delete everything without prompt, use the "--force/-f" or the "--no-input/n"
|
||||
flag.
|
||||
`,
|
||||
flag.`,
|
||||
Flags: []cli.Flag{
|
||||
internal.ForceFlag,
|
||||
internal.DebugFlag,
|
||||
|
@ -33,10 +33,9 @@ Run "abra app ps <domain>" to see a list of service names.
|
||||
|
||||
Pass "--all-services/-a" to restart all services.
|
||||
|
||||
Example:
|
||||
EXAMPLE:
|
||||
|
||||
abra app restart example.com app
|
||||
`,
|
||||
abra app restart example.com app`,
|
||||
BashComplete: autocomplete.AppNameComplete,
|
||||
Action: func(c *cli.Context) error {
|
||||
app := internal.ValidateApp(c)
|
||||
|
@ -34,14 +34,18 @@ var appRollbackCommand = cli.Command{
|
||||
},
|
||||
Before: internal.SubCommandBefore,
|
||||
Description: `
|
||||
This command rolls an app back to a previous version if one exists.
|
||||
This command rolls an app back to a previous version.
|
||||
|
||||
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.
|
||||
Unlike "deploy", chaos operations are not supported here. Only recipe versions
|
||||
are supported values for "[<version>]".
|
||||
|
||||
This action could be destructive, please ensure you have a copy of your app
|
||||
data beforehand.
|
||||
`,
|
||||
A rollback can be destructive, please ensure you have a copy of your app data
|
||||
beforehand.
|
||||
|
||||
EXAMPLE:
|
||||
|
||||
abra app rollback foo.example.com
|
||||
abra app rollback foo.example.com 1.2.3+3.2.1`,
|
||||
BashComplete: autocomplete.AppNameComplete,
|
||||
Action: func(c *cli.Context) error {
|
||||
app := internal.ValidateApp(c)
|
||||
@ -82,10 +86,10 @@ data beforehand.
|
||||
}
|
||||
|
||||
if len(versions) == 0 {
|
||||
log.Warn("no published versions in catalogue, trying local recipe repository")
|
||||
log.Debug("no published versions in catalogue, trying local recipe repository")
|
||||
recipeVersions, err := app.Recipe.GetRecipeVersions(internal.Offline)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, recipeVersion := range recipeVersions {
|
||||
@ -105,15 +109,19 @@ data beforehand.
|
||||
if specificVersion != "" {
|
||||
parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Fatalf("'%s' is not a known version for %s", deployMeta.Version, app.Recipe.Name)
|
||||
}
|
||||
|
||||
parsedSpecificVersion, err := tagcmp.Parse(specificVersion)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Fatalf("'%s' is not a known version for %s", specificVersion, app.Recipe.Name)
|
||||
}
|
||||
|
||||
if parsedSpecificVersion.IsGreaterThan(parsedDeployedVersion) || parsedSpecificVersion.Equals(parsedDeployedVersion) {
|
||||
if parsedSpecificVersion.IsGreaterThan(parsedDeployedVersion) && !parsedSpecificVersion.Equals(parsedDeployedVersion) {
|
||||
log.Fatalf("%s is not a downgrade for %s?", deployMeta.Version, specificVersion)
|
||||
}
|
||||
|
||||
if parsedSpecificVersion.Equals(parsedDeployedVersion) && !internal.Force {
|
||||
log.Fatalf("%s is not a downgrade for %s?", deployMeta.Version, specificVersion)
|
||||
}
|
||||
|
||||
@ -121,7 +129,7 @@ data beforehand.
|
||||
}
|
||||
|
||||
if deployMeta.Version != "unknown" && specificVersion == "" {
|
||||
if deployMeta.IsChaos == "true" {
|
||||
if deployMeta.IsChaos {
|
||||
log.Warn("attempting to rollback a chaos deployment")
|
||||
}
|
||||
|
||||
@ -154,7 +162,7 @@ data beforehand.
|
||||
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" {
|
||||
if deployMeta.IsChaos {
|
||||
msg = fmt.Sprintf("please select a downgrade (version: %s, chaosVersion: %s):", deployMeta.Version, deployMeta.ChaosVersion)
|
||||
}
|
||||
|
||||
@ -170,7 +178,7 @@ data beforehand.
|
||||
}
|
||||
|
||||
log.Debugf("choosing %s as version to rollback", chosenDowngrade)
|
||||
if err := app.Recipe.EnsureVersion(chosenDowngrade); err != nil {
|
||||
if _, err := app.Recipe.EnsureVersion(chosenDowngrade); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@ -206,8 +214,8 @@ data beforehand.
|
||||
appPkg.SetChaosVersionLabel(compose, stackName, chosenDowngrade)
|
||||
appPkg.SetUpdateLabel(compose, stackName, app.Env)
|
||||
|
||||
chaosVersion := deployMeta.IsChaos
|
||||
if deployMeta.IsChaos == "true" {
|
||||
chaosVersion := "false"
|
||||
if deployMeta.IsChaos {
|
||||
chaosVersion = deployMeta.ChaosVersion
|
||||
}
|
||||
|
||||
|
@ -78,8 +78,7 @@ This does not destroy any of the application data.
|
||||
However, you should remain vigilant, as your swarm installation will consider
|
||||
any previously attached volumes as eligible for pruning once undeployed.
|
||||
|
||||
Passing "-p/--prune" does not remove those volumes.
|
||||
`,
|
||||
Passing "-p/--prune" does not remove those volumes.`,
|
||||
Action: func(c *cli.Context) error {
|
||||
app := internal.ValidateApp(c)
|
||||
stackName := app.StackName()
|
||||
@ -100,8 +99,8 @@ Passing "-p/--prune" does not remove those volumes.
|
||||
log.Fatalf("%s is not deployed?", app.Name)
|
||||
}
|
||||
|
||||
chaosVersion := deployMeta.IsChaos
|
||||
if deployMeta.IsChaos == "true" {
|
||||
chaosVersion := "false"
|
||||
if deployMeta.IsChaos {
|
||||
chaosVersion = deployMeta.ChaosVersion
|
||||
}
|
||||
|
||||
|
@ -34,15 +34,18 @@ var appUpgradeCommand = cli.Command{
|
||||
},
|
||||
Before: internal.SubCommandBefore,
|
||||
Description: `
|
||||
Upgrade an app. You can use it to choose and roll out a new upgrade to a
|
||||
deployed app.
|
||||
Upgrade an app.
|
||||
|
||||
You may pass "--force/-f" to upgrade to the same version again. This can be
|
||||
useful if the container runtime has gotten into a weird state.
|
||||
Unlike "deploy", chaos operations are not supported here. Only recipe versions
|
||||
are supported values for "[<version>]".
|
||||
|
||||
This action could be destructive, please ensure you have a copy of your app
|
||||
data beforehand.
|
||||
`,
|
||||
An upgrade can be destructive, please ensure you have a copy of your app data
|
||||
beforehand.
|
||||
|
||||
EXAMPLE:
|
||||
|
||||
abra app upgrade foo.example.com
|
||||
abra app upgrade foo.example.com 1.2.3+3.2.1`,
|
||||
BashComplete: autocomplete.AppNameComplete,
|
||||
Action: func(c *cli.Context) error {
|
||||
app := internal.ValidateApp(c)
|
||||
@ -83,10 +86,10 @@ data beforehand.
|
||||
}
|
||||
|
||||
if len(versions) == 0 {
|
||||
log.Warn("no published versions in catalogue, trying local recipe repository")
|
||||
log.Debug("no published versions in catalogue, trying local recipe repository")
|
||||
recipeVersions, err := app.Recipe.GetRecipeVersions(internal.Offline)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
for _, recipeVersion := range recipeVersions {
|
||||
for version := range recipeVersion {
|
||||
@ -105,15 +108,21 @@ data beforehand.
|
||||
if specificVersion != "" {
|
||||
parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Fatalf("'%s' is not a known version for %s", deployMeta.Version, app.Recipe.Name)
|
||||
}
|
||||
parsedSpecificVersion, err := tagcmp.Parse(specificVersion)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Fatalf("'%s' is not a known version for %s", specificVersion, app.Recipe.Name)
|
||||
}
|
||||
if parsedSpecificVersion.IsLessThan(parsedDeployedVersion) || parsedSpecificVersion.Equals(parsedDeployedVersion) {
|
||||
|
||||
if parsedSpecificVersion.IsLessThan(parsedDeployedVersion) && !parsedSpecificVersion.Equals(parsedDeployedVersion) {
|
||||
log.Fatalf("%s is not an upgrade for %s?", deployMeta.Version, specificVersion)
|
||||
}
|
||||
|
||||
if parsedSpecificVersion.Equals(parsedDeployedVersion) && !internal.Force {
|
||||
log.Fatalf("%s is not an upgrade for %s?", deployMeta.Version, specificVersion)
|
||||
}
|
||||
|
||||
availableUpgrades = append(availableUpgrades, specificVersion)
|
||||
}
|
||||
|
||||
@ -123,7 +132,7 @@ data beforehand.
|
||||
}
|
||||
|
||||
if deployMeta.Version != "unknown" && specificVersion == "" {
|
||||
if deployMeta.IsChaos == "true" {
|
||||
if deployMeta.IsChaos {
|
||||
log.Warn("attempting to upgrade a chaos deployment")
|
||||
}
|
||||
|
||||
@ -150,7 +159,7 @@ data beforehand.
|
||||
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" {
|
||||
if deployMeta.IsChaos {
|
||||
msg = fmt.Sprintf("please select an upgrade (version: %s, chaosVersion: %s):", deployMeta.Version, deployMeta.ChaosVersion)
|
||||
}
|
||||
|
||||
@ -197,7 +206,7 @@ data beforehand.
|
||||
}
|
||||
|
||||
log.Debugf("choosing %s as version to upgrade", chosenUpgrade)
|
||||
if err := app.Recipe.EnsureVersion(chosenUpgrade); err != nil {
|
||||
if _, err := app.Recipe.EnsureVersion(chosenUpgrade); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@ -250,8 +259,8 @@ data beforehand.
|
||||
return nil
|
||||
}
|
||||
|
||||
chaosVersion := deployMeta.IsChaos
|
||||
if deployMeta.IsChaos == "true" {
|
||||
chaosVersion := "false"
|
||||
if deployMeta.IsChaos {
|
||||
chaosVersion = deployMeta.ChaosVersion
|
||||
}
|
||||
|
||||
|
@ -73,8 +73,7 @@ The command is interactive and will show a multiple select input which allows
|
||||
you to make a seclection. Use the "?" key to see more help on navigating this
|
||||
interface.
|
||||
|
||||
Passing "--force/-f" will select all volumes for removal. Be careful.
|
||||
`,
|
||||
Passing "--force/-f" will select all volumes for removal. Be careful.`,
|
||||
ArgsUsage: "<domain>",
|
||||
Aliases: []string{"rm"},
|
||||
Flags: []cli.Flag{
|
||||
|
@ -33,14 +33,7 @@ var catalogueGenerateCommand = cli.Command{
|
||||
},
|
||||
Before: internal.SubCommandBefore,
|
||||
Description: `
|
||||
Generate a new copy of the recipe catalogue which can be found on:
|
||||
|
||||
https://recipes.coopcloud.tech (website that humans read)
|
||||
https://recipes.coopcloud.tech/recipes.json (JSON that Abra reads)
|
||||
|
||||
It polls the entire git.coopcloud.tech/coop-cloud/... recipe repository
|
||||
listing, parses README.md and git tags to produce recipe metadata which is
|
||||
loaded into the catalogue JSON file.
|
||||
Generate a new copy of the recipe catalogue.
|
||||
|
||||
It is possible to generate new metadata for a single recipe by passing
|
||||
<recipe>. The existing local catalogue will be updated, not overwritten.
|
||||
@ -51,8 +44,7 @@ If you have a Hub account you can have Abra log you in to avoid this. Pass
|
||||
|
||||
Push your new release to git.coopcloud.tech with "-p/--publish". This requires
|
||||
that you have permission to git push to these repositories and have your SSH
|
||||
keys configured on your account.
|
||||
`,
|
||||
keys configured on your account.`,
|
||||
ArgsUsage: "[<recipe>]",
|
||||
BashComplete: autocomplete.RecipeNameComplete,
|
||||
Action: func(c *cli.Context) error {
|
||||
@ -213,11 +205,10 @@ keys configured on your account.
|
||||
|
||||
// CatalogueCommand defines the `abra catalogue` command and sub-commands.
|
||||
var CatalogueCommand = cli.Command{
|
||||
Name: "catalogue",
|
||||
Usage: "Manage the recipe catalogue",
|
||||
Aliases: []string{"c"},
|
||||
ArgsUsage: "<recipe>",
|
||||
Description: "This command helps recipe packagers interact with the recipe catalogue",
|
||||
Name: "catalogue",
|
||||
Usage: "Manage the recipe catalogue",
|
||||
Aliases: []string{"c"},
|
||||
ArgsUsage: "<recipe>",
|
||||
Subcommands: []cli.Command{
|
||||
catalogueGenerateCommand,
|
||||
},
|
||||
|
41
cli/cli.go
41
cli/cli.go
@ -25,16 +25,15 @@ import (
|
||||
var AutoCompleteCommand = cli.Command{
|
||||
Name: "autocomplete",
|
||||
Aliases: []string{"ac"},
|
||||
Usage: "Configure shell autocompletion (recommended)",
|
||||
Usage: "Configure shell autocompletion",
|
||||
Description: `
|
||||
Set up auto-completion in your shell by downloading the relevant files and
|
||||
laying out what additional information must be loaded. Supported shells are as
|
||||
follows: bash, fish, fizsh & zsh.
|
||||
Set up shell auto-completion.
|
||||
|
||||
Example:
|
||||
Supported shells are: bash, fish, fizsh & zsh.
|
||||
|
||||
abra autocomplete bash
|
||||
`,
|
||||
EXAMPLE:
|
||||
|
||||
abra autocomplete bash`,
|
||||
ArgsUsage: "<shell>",
|
||||
Flags: []cli.Flag{
|
||||
internal.DebugFlag,
|
||||
@ -81,7 +80,7 @@ Example:
|
||||
switch shellType {
|
||||
case "bash":
|
||||
fmt.Println(fmt.Sprintf(`
|
||||
# Run the following commands to install auto-completion
|
||||
# run the following commands to install auto-completion
|
||||
sudo mkdir /etc/bash_completion.d/
|
||||
sudo cp %s /etc/bash_completion.d/abra
|
||||
echo "source /etc/bash_completion.d/abra" >> ~/.bashrc
|
||||
@ -89,19 +88,19 @@ echo "source /etc/bash_completion.d/abra" >> ~/.bashrc
|
||||
`, autocompletionFile))
|
||||
case "zsh":
|
||||
fmt.Println(fmt.Sprintf(`
|
||||
# Run the following commands to install auto-completion
|
||||
# run the following commands to install auto-completion
|
||||
sudo mkdir /etc/zsh/completion.d/
|
||||
sudo cp %s /etc/zsh/completion.d/abra
|
||||
echo "PROG=abra\n_CLI_ZSH_AUTOCOMPLETE_HACK=1\nsource /etc/zsh/completion.d/abra" >> ~/.zshrc
|
||||
# To test, run the following: "abra app <hit tab key>" - you should see command completion!
|
||||
# to test, run the following: "abra app <hit tab key>" - you should see command completion!
|
||||
`, autocompletionFile))
|
||||
case "fish":
|
||||
fmt.Println(fmt.Sprintf(`
|
||||
# Run the following commands to install auto-completion
|
||||
# run the following commands to install auto-completion
|
||||
sudo mkdir -p /etc/fish/completions
|
||||
sudo cp %s /etc/fish/completions/abra
|
||||
echo "source /etc/fish/completions/abra" >> ~/.config/fish/config.fish
|
||||
# To test, run the following: "abra app <hit tab key>" - you should see command completion!
|
||||
# to test, run the following: "abra app <hit tab key>" - you should see command completion!
|
||||
`, autocompletionFile))
|
||||
}
|
||||
|
||||
@ -113,14 +112,18 @@ echo "source /etc/fish/completions/abra" >> ~/.config/fish/config.fish
|
||||
var UpgradeCommand = cli.Command{
|
||||
Name: "upgrade",
|
||||
Aliases: []string{"u"},
|
||||
Usage: "Upgrade Abra itself",
|
||||
Usage: "Upgrade abra",
|
||||
Description: `
|
||||
Upgrade Abra in-place with the latest stable or release candidate.
|
||||
Upgrade abra in-place with the latest stable or release candidate.
|
||||
|
||||
Pass "-r/--rc" to install the latest release candidate. Please bear in mind
|
||||
that it may contain catastrophic bugs. Thank you very much for the testing
|
||||
efforts!
|
||||
`,
|
||||
Use "-r/--rc" to install the latest release candidate. Please bear in mind that
|
||||
it may contain absolutely catastrophic deal-breaker bugs. Thank you very much
|
||||
for the testing efforts 💗
|
||||
|
||||
EXAMPLE:
|
||||
|
||||
abra upgrade
|
||||
abra upgrade --rc`,
|
||||
Flags: []cli.Flag{internal.RCFlag},
|
||||
Action: func(c *cli.Context) error {
|
||||
mainURL := "https://install.abra.coopcloud.tech"
|
||||
@ -144,7 +147,7 @@ efforts!
|
||||
func newAbraApp(version, commit string) *cli.App {
|
||||
app := &cli.App{
|
||||
Name: "abra",
|
||||
Usage: `The Co-op Cloud command-line utility belt 🎩🐇
|
||||
Usage: `the Co-op Cloud command-line utility belt 🎩🐇
|
||||
____ ____ _ _
|
||||
/ ___|___ ___ _ __ / ___| | ___ _ _ __| |
|
||||
| | / _ \ _____ / _ \| '_ \ | | | |/ _ \| | | |/ _' |
|
||||
|
@ -5,14 +5,13 @@ import (
|
||||
"coopcloud.tech/abra/pkg/autocomplete"
|
||||
gitPkg "coopcloud.tech/abra/pkg/git"
|
||||
"coopcloud.tech/abra/pkg/log"
|
||||
"coopcloud.tech/abra/pkg/recipe"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var recipeDiffCommand = cli.Command{
|
||||
Name: "diff",
|
||||
Usage: "Show unstaged changes in recipe config",
|
||||
Description: "Due to limitations in our underlying Git dependency, this command requires /usr/bin/git.",
|
||||
Description: "This command requires /usr/bin/git.",
|
||||
Aliases: []string{"d"},
|
||||
ArgsUsage: "<recipe>",
|
||||
Flags: []cli.Flag{
|
||||
@ -22,12 +21,7 @@ var recipeDiffCommand = cli.Command{
|
||||
Before: internal.SubCommandBefore,
|
||||
BashComplete: autocomplete.RecipeNameComplete,
|
||||
Action: func(c *cli.Context) error {
|
||||
recipeName := c.Args().First()
|
||||
r := recipe.Get(recipeName)
|
||||
|
||||
if recipeName != "" {
|
||||
internal.ValidateRecipe(c)
|
||||
}
|
||||
r := internal.ValidateRecipe(c)
|
||||
|
||||
if err := gitPkg.DiffUnstaged(r.Dir); err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -48,12 +48,7 @@ Create a new recipe.
|
||||
|
||||
Abra uses the built-in example repository which is available here:
|
||||
|
||||
https://git.coopcloud.tech/coop-cloud/example
|
||||
|
||||
Files within the example repository make use of the Golang templating system
|
||||
which Abra uses to inject values into the generated recipe folder (e.g. name of
|
||||
recipe and domain in the sample environment config).
|
||||
`,
|
||||
https://git.coopcloud.tech/coop-cloud/example`,
|
||||
Action: func(c *cli.Context) error {
|
||||
recipeName := c.Args().First()
|
||||
r := recipe.Get(recipeName)
|
||||
@ -100,22 +95,8 @@ recipe and domain in the sample environment config).
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Print(fmt.Sprintf(`
|
||||
Your new %s recipe has been created in %s.
|
||||
|
||||
In order to share your recipe, you can upload it the git repository to:
|
||||
|
||||
https://git.coopcloud.tech/coop-cloud/%s
|
||||
|
||||
If you're not sure how to do that, come chat with us:
|
||||
|
||||
https://docs.coopcloud.tech/intro/contact
|
||||
|
||||
See "abra recipe -h" for additional recipe maintainer commands.
|
||||
|
||||
Happy Hacking!
|
||||
|
||||
`, recipeName, path.Join(r.Dir), recipeName))
|
||||
log.Infof("new recipe '%s' created: %s", recipeName, path.Join(r.Dir))
|
||||
log.Info("happy hacking 🎉")
|
||||
|
||||
return nil
|
||||
},
|
||||
|
@ -18,9 +18,7 @@ for you.
|
||||
|
||||
Anyone who uses a recipe can become a maintainer. Maintainers typically make
|
||||
sure the recipe is in good working order and the config upgraded in a timely
|
||||
manner. Abra supports convenient automation for recipe maintainenace, see the
|
||||
"abra recipe upgrade", "abra recipe sync" and "abra recipe release" commands.
|
||||
`,
|
||||
manner.`,
|
||||
Subcommands: []cli.Command{
|
||||
recipeFetchCommand,
|
||||
recipeLintCommand,
|
||||
|
@ -45,8 +45,7 @@ major and therefore require intervention while doing the upgrade work.
|
||||
|
||||
Publish your new release to git.coopcloud.tech with "-p/--publish". This
|
||||
requires that you have permission to git push to these repositories and have
|
||||
your SSH keys configured on your account.
|
||||
`,
|
||||
your SSH keys configured on your account.`,
|
||||
Flags: []cli.Flag{
|
||||
internal.DebugFlag,
|
||||
internal.NoInputFlag,
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
var recipeResetCommand = cli.Command{
|
||||
Name: "reset",
|
||||
Usage: "Remove all unstaged changes from recipe config",
|
||||
Description: "WARNING, this will delete your changes. Be Careful.",
|
||||
Description: "WARNING: this will delete your changes. Be Careful.",
|
||||
Aliases: []string{"rs"},
|
||||
ArgsUsage: "<recipe>",
|
||||
Flags: []cli.Flag{
|
||||
|
@ -37,8 +37,7 @@ named "app") which corresponds to the following format:
|
||||
|
||||
Where <version> can be specifed on the command-line or Abra can attempt to
|
||||
auto-generate it for you. The <recipe> configuration will be updated on the
|
||||
local file system.
|
||||
`,
|
||||
local file system.`,
|
||||
BashComplete: autocomplete.RecipeNameComplete,
|
||||
Action: func(c *cli.Context) error {
|
||||
recipe := internal.ValidateRecipe(c)
|
||||
|
@ -53,10 +53,11 @@ The command is interactive and will show a select input which allows you to
|
||||
make a seclection. Use the "?" key to see more help on navigating this
|
||||
interface.
|
||||
|
||||
You may invoke this command in "wizard" mode and be prompted for input:
|
||||
You may invoke this command in "wizard" mode and be prompted for input.
|
||||
|
||||
abra recipe upgrade
|
||||
`,
|
||||
EXAMPLE:
|
||||
|
||||
abra recipe upgrade`,
|
||||
ArgsUsage: "<recipe>",
|
||||
Flags: []cli.Flag{
|
||||
internal.DebugFlag,
|
||||
|
@ -24,11 +24,10 @@ func sortServiceByName(versions [][]string) func(i, j int) bool {
|
||||
}
|
||||
|
||||
var recipeVersionCommand = cli.Command{
|
||||
Name: "versions",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "List recipe versions",
|
||||
ArgsUsage: "<recipe>",
|
||||
Description: "Versions are read from the recipe catalogue.",
|
||||
Name: "versions",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "List recipe versions",
|
||||
ArgsUsage: "<recipe>",
|
||||
Flags: []cli.Flag{
|
||||
internal.DebugFlag,
|
||||
internal.OfflineFlag,
|
||||
|
@ -94,7 +94,7 @@ func createServerDir(name string) (bool, error) {
|
||||
var serverAddCommand = cli.Command{
|
||||
Name: "add",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Add a server to your configuration",
|
||||
Usage: "Add a new server to your configuration",
|
||||
Description: `
|
||||
Add a new server to your configuration so that it can be managed by Abra.
|
||||
|
||||
@ -121,8 +121,7 @@ You can also pass "--no-domain-checks/-D" flag to use any arbitrary name
|
||||
instead of a real domain. The host will be resolved with the "Hostname" entry
|
||||
of your ~/.ssh/config. Checks for a valid online domain will be skipped:
|
||||
|
||||
abra server add -D example
|
||||
`,
|
||||
abra server add -D example`,
|
||||
Flags: []cli.Flag{
|
||||
internal.DebugFlag,
|
||||
internal.NoInputFlag,
|
||||
|
@ -31,13 +31,12 @@ var volumesFilterFlag = &cli.BoolFlag{
|
||||
var serverPruneCommand = cli.Command{
|
||||
Name: "prune",
|
||||
Aliases: []string{"p"},
|
||||
Usage: "Prune a managed server; Runs a docker system prune",
|
||||
Usage: "Prune resources on a server",
|
||||
Description: `
|
||||
Prunes unused containers, networks, and dangling images.
|
||||
|
||||
If passing "-v/--volumes" then volumes not connected to a deployed app will
|
||||
also be removed. This can result in unwanted data loss if not used carefully.
|
||||
`,
|
||||
Use "-v/--volumes" to remove volumes that are not associated with a deployed
|
||||
app. This can result in unwanted data loss if not used carefully.`,
|
||||
ArgsUsage: "[<server>]",
|
||||
Flags: []cli.Flag{
|
||||
allFilterFlag,
|
||||
|
@ -17,12 +17,12 @@ var serverRemoveCommand = cli.Command{
|
||||
Aliases: []string{"rm"},
|
||||
ArgsUsage: "<server>",
|
||||
Usage: "Remove a managed server",
|
||||
Description: `Remove a managed server.
|
||||
Description: `
|
||||
Remove a managed server.
|
||||
|
||||
Abra will remove the internal bookkeeping (~/.abra/servers/...) and underlying
|
||||
client connection context. This server will then be lost in time, like tears in
|
||||
rain.
|
||||
`,
|
||||
rain.`,
|
||||
Flags: []cli.Flag{
|
||||
internal.DebugFlag,
|
||||
internal.NoInputFlag,
|
||||
|
@ -54,10 +54,12 @@ var Notify = cli.Command{
|
||||
},
|
||||
Before: internal.SubCommandBefore,
|
||||
Description: `
|
||||
It reads the deployed app versions and looks for new versions in the recipe
|
||||
catalogue. If a new patch/minor version is available, a notification is
|
||||
printed. To include major versions use the --major flag.
|
||||
`,
|
||||
Read the deployed app versions and look for new versions in the recipe
|
||||
catalogue.
|
||||
|
||||
If a new patch/minor version is available, a notification is printed.
|
||||
|
||||
Use "--major" to include new major versions.`,
|
||||
Action: func(c *cli.Context) error {
|
||||
cl, err := client.New("default")
|
||||
if err != nil {
|
||||
@ -103,14 +105,17 @@ var UpgradeApp = cli.Command{
|
||||
},
|
||||
Before: internal.SubCommandBefore,
|
||||
Description: `
|
||||
Upgrade an app by specifying its stack name and recipe. By passing "--all"
|
||||
instead, every deployed app is upgraded. For each apps with enabled auto
|
||||
updates the deployed version is compared with the current recipe catalogue
|
||||
version. If a new patch/minor version is available, the app is upgraded. To
|
||||
include major versions use the "--major" flag. Don't do that, it will probably
|
||||
break things. Only apps that are not deployed with "--chaos" are upgraded, to
|
||||
update chaos deployments use the "--chaos" flag. Use it with care.
|
||||
`,
|
||||
Upgrade an app by specifying stack name and recipe.
|
||||
|
||||
Use "--all" to upgrade every deployed app.
|
||||
|
||||
For each app with auto updates enabled, the deployed version is compared with
|
||||
the current recipe catalogue version. If a new patch/minor version is
|
||||
available, the app is upgraded.
|
||||
|
||||
To include major versions use the "--major" flag. You probably don't want that
|
||||
as it will break things. Only apps that are not deployed with "--chaos" are
|
||||
upgraded, to update chaos deployments use the "--chaos" flag. Use it with care.`,
|
||||
Action: func(c *cli.Context) error {
|
||||
cl, err := client.New("default")
|
||||
if err != nil {
|
||||
@ -327,7 +332,7 @@ func processRecipeRepoVersion(r recipe.Recipe, version string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.EnsureVersion(version); err != nil {
|
||||
if _, err := r.EnsureVersion(version); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -57,21 +57,23 @@ func (r Recipe) EnsureExists() error {
|
||||
}
|
||||
|
||||
// EnsureVersion checks whether a specific version exists for a recipe.
|
||||
func (r Recipe) EnsureVersion(version string) error {
|
||||
func (r Recipe) EnsureVersion(version string) (bool, error) {
|
||||
isChaosCommit := false
|
||||
|
||||
recipeDir := path.Join(config.RECIPES_DIR, r.Name)
|
||||
|
||||
if err := gitPkg.EnsureGitRepo(recipeDir); err != nil {
|
||||
return err
|
||||
return isChaosCommit, err
|
||||
}
|
||||
|
||||
repo, err := git.PlainOpen(recipeDir)
|
||||
if err != nil {
|
||||
return err
|
||||
return isChaosCommit, err
|
||||
}
|
||||
|
||||
tags, err := repo.Tags()
|
||||
if err != nil {
|
||||
return nil
|
||||
return isChaosCommit, err
|
||||
}
|
||||
|
||||
var parsedTags []string
|
||||
@ -83,7 +85,7 @@ func (r Recipe) EnsureVersion(version string) error {
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
return isChaosCommit, err
|
||||
}
|
||||
|
||||
joinedTags := strings.Join(parsedTags, ", ")
|
||||
@ -91,27 +93,33 @@ func (r Recipe) EnsureVersion(version string) error {
|
||||
log.Debugf("read %s as tags for recipe %s", joinedTags, r.Name)
|
||||
}
|
||||
|
||||
var opts *git.CheckoutOptions
|
||||
if tagRef.String() == "" {
|
||||
return fmt.Errorf("the local copy of %s doesn't seem to have version %s available?", r.Name, version)
|
||||
log.Debugf("attempting to checkout '%s' as chaos commit", version)
|
||||
|
||||
hash, err := repo.ResolveRevision(plumbing.Revision(version))
|
||||
if err != nil {
|
||||
log.Fatalf("unable to resolve '%s': %s", version, err)
|
||||
}
|
||||
|
||||
opts = &git.CheckoutOptions{Hash: *hash, Create: false, Force: true}
|
||||
isChaosCommit = true
|
||||
} else {
|
||||
opts = &git.CheckoutOptions{Branch: tagRef, Create: false, Force: true}
|
||||
}
|
||||
|
||||
worktree, err := repo.Worktree()
|
||||
if err != nil {
|
||||
return err
|
||||
return isChaosCommit, nil
|
||||
}
|
||||
|
||||
opts := &git.CheckoutOptions{
|
||||
Branch: tagRef,
|
||||
Create: false,
|
||||
Force: true,
|
||||
}
|
||||
if err := worktree.Checkout(opts); err != nil {
|
||||
return err
|
||||
return isChaosCommit, nil
|
||||
}
|
||||
|
||||
log.Debugf("successfully checked %s out to %s in %s", r.Name, tagRef.Short(), recipeDir)
|
||||
|
||||
return nil
|
||||
return isChaosCommit, nil
|
||||
}
|
||||
|
||||
// EnsureIsClean makes sure that the recipe repository has no unstaged changes.
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -101,7 +102,7 @@ func GetDeployedServicesByName(ctx context.Context, cl *dockerClient.Client, sta
|
||||
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
|
||||
IsChaos bool // whether or not the deployment is --chaos
|
||||
ChaosVersion string // the --chaos deployment version
|
||||
}
|
||||
|
||||
@ -110,7 +111,7 @@ func IsDeployed(ctx context.Context, cl *dockerClient.Client, stackName string)
|
||||
deployMeta := DeployMeta{
|
||||
IsDeployed: false,
|
||||
Version: "unknown",
|
||||
IsChaos: "false", // NOTE(d1): match string type used on label
|
||||
IsChaos: false,
|
||||
ChaosVersion: "false", // NOTE(d1): match string type used on label
|
||||
}
|
||||
|
||||
@ -137,7 +138,11 @@ func IsDeployed(ctx context.Context, cl *dockerClient.Client, stackName string)
|
||||
|
||||
labelKey = fmt.Sprintf("coop-cloud.%s.chaos", stackName)
|
||||
if isChaos, ok := service.Spec.Labels[labelKey]; ok {
|
||||
deployMeta.IsChaos = isChaos
|
||||
boolVal, err := strconv.ParseBool(isChaos)
|
||||
if err != nil {
|
||||
return deployMeta, fmt.Errorf("unable to parse '%s' value as bool: %s", labelKey, err)
|
||||
}
|
||||
deployMeta.IsChaos = boolVal
|
||||
}
|
||||
|
||||
labelKey = fmt.Sprintf("coop-cloud.%s.chaos-version", stackName)
|
||||
|
@ -356,3 +356,12 @@ teardown(){
|
||||
run $ABRA app secret rm "$TEST_APP_DOMAIN" --all --chaos
|
||||
assert_success
|
||||
}
|
||||
|
||||
# bats test_tags=slow
|
||||
@test "deploy chaos commit" {
|
||||
tagHash=$(_get_tag_hash "0.1.0+1.20.0")
|
||||
|
||||
run $ABRA app deploy "$TEST_APP_DOMAIN" "$tagHash" --no-input --no-converge-checks
|
||||
assert_success
|
||||
assert_output --partial 'chaos mode'
|
||||
}
|
||||
|
@ -111,6 +111,26 @@ teardown(){
|
||||
assert_output --partial "0.1.0+1.20.0"
|
||||
}
|
||||
|
||||
# bats test_tags=slow
|
||||
@test "force rollback to previous version" {
|
||||
run $ABRA app deploy "$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'
|
||||
|
||||
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"
|
||||
|
||||
run $ABRA app rollback "$TEST_APP_DOMAIN" "0.1.0+1.20.0" --no-input --no-converge-checks
|
||||
assert_failure
|
||||
assert_output --partial "not a downgrade"
|
||||
|
||||
run $ABRA app rollback "$TEST_APP_DOMAIN" "0.1.0+1.20.0" \
|
||||
--no-input --no-converge-checks --force
|
||||
assert_success
|
||||
assert_output --partial "0.1.0+1.20.0"
|
||||
}
|
||||
|
||||
# bats test_tags=slow
|
||||
@test "rollback to a version 2 tags behind" {
|
||||
run $ABRA app deploy "$TEST_APP_DOMAIN" "0.2.0+1.21.0" --no-input --no-converge-checks
|
||||
@ -145,3 +165,14 @@ teardown(){
|
||||
refute_output --partial "${tagHash:0:8}"
|
||||
assert_output --partial "false"
|
||||
}
|
||||
|
||||
# bats test_tags=slow
|
||||
@test "chaos commit rollback not possible" {
|
||||
_deploy_app
|
||||
|
||||
tagHash=$(_get_tag_hash "0.2.0+1.21.0")
|
||||
|
||||
run $ABRA app rollback "$TEST_APP_DOMAIN" "$tagHash" --no-input --no-converge-checks
|
||||
assert_failure
|
||||
assert_output --partial "not a known version"
|
||||
}
|
||||
|
@ -97,6 +97,26 @@ teardown(){
|
||||
assert_output --partial '0.2.0+1.21.0'
|
||||
}
|
||||
|
||||
# bats test_tags=slow
|
||||
@test "force upgrade specific version" {
|
||||
run $ABRA app deploy "$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'
|
||||
|
||||
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'
|
||||
|
||||
run $ABRA app upgrade "$TEST_APP_DOMAIN" "0.2.0+1.21.0" --no-input --no-converge-checks
|
||||
assert_failure
|
||||
assert_output --partial 'not an upgrade'
|
||||
|
||||
run $ABRA app upgrade "$TEST_APP_DOMAIN" "0.2.0+1.21.0" \
|
||||
--no-input --no-converge-checks --force
|
||||
assert_success
|
||||
assert_output --partial '0.2.0+1.21.0'
|
||||
}
|
||||
|
||||
# bats test_tags=slow
|
||||
@test "upgrade to latest" {
|
||||
run $ABRA app deploy "$TEST_APP_DOMAIN" "0.1.0+1.20.0" --no-input --no-converge-checks
|
||||
@ -189,3 +209,15 @@ teardown(){
|
||||
refute_output --partial "${tagHash:0:8}"
|
||||
assert_output --partial "false"
|
||||
}
|
||||
|
||||
@test "chaos commit upgrade not possible" {
|
||||
run $ABRA app deploy "$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.2.0+1.21.0")
|
||||
|
||||
run $ABRA app upgrade "$TEST_APP_DOMAIN" "$tagHash" --no-input --no-converge-checks
|
||||
assert_failure
|
||||
assert_output --partial "not a known version"
|
||||
}
|
||||
|
@ -16,6 +16,14 @@ setup(){
|
||||
}
|
||||
|
||||
teardown(){
|
||||
if [[ -f "$ABRA_DIR/servers/$TEST_SERVER/foobar.$TEST_SERVER.env" ]]; then
|
||||
run $ABRA app undeploy "foobar.$TEST_SERVER" --no-input
|
||||
assert_success
|
||||
|
||||
run $ABRA app rm "foobar.$TEST_SERVER" --no-input
|
||||
assert_success
|
||||
fi
|
||||
|
||||
if [[ -d "$ABRA_DIR/recipes/foobar" ]]; then
|
||||
run rm -rf "$ABRA_DIR/recipes/foobar"
|
||||
assert_success
|
||||
@ -25,26 +33,32 @@ teardown(){
|
||||
@test "create new recipe" {
|
||||
run $ABRA recipe new foobar
|
||||
assert_success
|
||||
assert_output --partial 'Your new foobar recipe has been created'
|
||||
assert_output --partial "new recipe 'foobar' created"
|
||||
assert_exists "$ABRA_DIR/recipes/foobar"
|
||||
}
|
||||
|
||||
# bats test_tags=slow
|
||||
@test "create new app from new recipe" {
|
||||
run $ABRA recipe new foobar
|
||||
assert_success
|
||||
assert_exists "$ABRA_DIR/recipes/foobar"
|
||||
|
||||
run $ABRA app new foobar \
|
||||
--no-input \
|
||||
--server "$TEST_SERVER" \
|
||||
--domain "foobar.$TEST_SERVER"
|
||||
assert_success
|
||||
assert_output --partial 'A new foobar app has been created!'
|
||||
assert_output --partial "new app 'foobar' created"
|
||||
|
||||
run $ABRA app deploy "foobar.$TEST_SERVER" --no-input
|
||||
assert_success
|
||||
assert_output --partial 'using latest commit'
|
||||
}
|
||||
|
||||
@test "create new recipe with git credentials" {
|
||||
run $ABRA recipe new foobar --git-name fooUser --git-email foo@example.com
|
||||
assert_success
|
||||
assert_output --partial 'Your new foobar recipe has been created'
|
||||
assert_output --partial "new recipe 'foobar' created"
|
||||
assert_exists "$ABRA_DIR/recipes/foobar"
|
||||
|
||||
run bash -c 'git -C "$ABRA_DIR/recipes/foobar" log -n 1'
|
||||
|
Loading…
x
Reference in New Issue
Block a user