Compare commits

..

19 Commits

Author SHA1 Message Date
3wc
cd34b64089 Update POT
All checks were successful
continuous-integration/drone/push Build is passing
2025-09-03 13:34:15 -04:00
3wc
bcc208d06a 4matting
Some checks failed
continuous-integration/drone/push Build is failing
2025-09-03 13:33:23 -04:00
3wc
02473f8fbb Add some basic unit tests for new utility methods
Some checks failed
continuous-integration/drone/push Build is failing
2025-09-03 13:33:06 -04:00
3wc
380a47ea4a Move MergeAbraShEnv to shared method
Some checks failed
continuous-integration/drone/push Build is failing
Re #638
2025-09-03 13:32:30 -04:00
3wc
ec2791c6f6 Regen POT
All checks were successful
continuous-integration/drone/push Build is passing
2025-09-03 11:09:58 -04:00
3wc
eaac5a1396 4matting 2025-09-03 11:08:56 -04:00
3wc
1edc64fdf6 Roll out pre-deploy changes to rollback and upgrade 2025-09-03 11:08:56 -04:00
3wc
a4714dda9f Show image differences in pre-deploy overview 2025-09-03 11:08:56 -04:00
3wc
82b9371790 Move secret- and config-gathering to separate file 2025-09-03 11:08:56 -04:00
3wc
cf9fd715e9 Resolve circular import 2025-09-03 11:08:56 -04:00
3wc
6a3c79cb3b Add GetSecretNamesForStack, tidy up GetConfigNamesForStack 2025-09-03 11:08:56 -04:00
3wc
4896b7c782 Warn instead of error on missing config version 2025-09-03 11:08:56 -04:00
3wc
f60c1c328c Working config version comparison 2025-09-03 11:08:56 -04:00
3wc
e8b5b92599 Skip empty sections in deploy overview 2025-09-03 11:08:56 -04:00
3wc
e3db5e357c Only show remote configs used in deployment 2025-09-03 11:08:56 -04:00
3wc
99d2291045 Add some spacing, might delete 2025-09-03 11:08:56 -04:00
3wc
86f324d4b6 Tidy up a little 2025-09-03 11:08:56 -04:00
3wc
4dd96e313b WIP: Working secret and config versions during deploy overview 2025-09-03 11:08:56 -04:00
3wc
d84c1d24ba WIP: Initial stab at secrets/configs/images 2025-09-03 11:08:56 -04:00
22 changed files with 843 additions and 475 deletions

View File

@ -6,14 +6,13 @@ import (
"strings"
"coopcloud.tech/abra/cli/internal"
"coopcloud.tech/abra/pkg/app"
"coopcloud.tech/abra/pkg/autocomplete"
"coopcloud.tech/abra/pkg/config"
"coopcloud.tech/abra/pkg/envfile"
"coopcloud.tech/abra/pkg/secret"
appPkg "coopcloud.tech/abra/pkg/app"
"coopcloud.tech/abra/pkg/client"
"coopcloud.tech/abra/pkg/deploy"
"coopcloud.tech/abra/pkg/dns"
"coopcloud.tech/abra/pkg/formatter"
"coopcloud.tech/abra/pkg/i18n"
@ -108,13 +107,10 @@ checkout as-is. Recipe commit hashes are also supported as values for
}
if !internal.Chaos {
isChaos, err := app.Recipe.EnsureVersion(toDeployVersion)
_, err = app.Recipe.EnsureVersion(toDeployVersion)
if err != nil {
log.Fatal(i18n.G("ensure recipe: %s", err))
}
if isChaos {
log.Fatal(i18n.G("version '%s' appears to be a chaos commit, but --chaos/-C was not provided", toDeployVersion))
}
}
if err := lint.LintForErrors(app.Recipe); err != nil {
@ -129,13 +125,9 @@ checkout as-is. Recipe commit hashes are also supported as values for
log.Fatal(err)
}
abraShEnv, err := envfile.ReadAbraShEnvVars(app.Recipe.AbraShPath)
if err != nil {
if err := deploy.MergeAbraShEnv(app.Recipe, app.Env); err != nil {
log.Fatal(err)
}
for k, v := range abraShEnv {
app.Env[k] = v
}
composeFiles, err := app.Recipe.GetComposeFiles(app.Env)
if err != nil {
@ -194,12 +186,35 @@ checkout as-is. Recipe commit hashes are also supported as values for
deployedVersion = deployMeta.Version
}
// Gather secrets
secretInfo, err := deploy.GatherSecretsForDeploy(cl, app)
if err != nil {
log.Fatal(err)
}
// Gather configs
configInfo, err := deploy.GatherConfigsForDeploy(cl, app, compose, app.Env)
if err != nil {
log.Fatal(err)
}
// Gather images
imageInfo, err := deploy.GatherImagesForDeploy(cl, app, compose)
if err != nil {
log.Fatal(err)
}
// Show deploy overview
if err := internal.DeployOverview(
app,
deployedVersion,
toDeployVersion,
"",
deployWarnMessages,
strings.Join(secretInfo, "\n"),
strings.Join(configInfo, "\n"),
strings.Join(imageInfo, "\n"),
); err != nil {
log.Fatal(err)
}
@ -245,7 +260,7 @@ checkout as-is. Recipe commit hashes are also supported as values for
},
}
func getLatestVersionOrCommit(app app.App) (string, error) {
func getLatestVersionOrCommit(app appPkg.App) (string, error) {
versions, err := app.Recipe.Tags()
if err != nil {
return "", err
@ -280,7 +295,7 @@ func validateArgsAndFlags(args []string) error {
return nil
}
func validateSecrets(cl *dockerClient.Client, app app.App) error {
func validateSecrets(cl *dockerClient.Client, app appPkg.App) error {
secStats, err := secret.PollSecretsStatus(cl, app)
if err != nil {
return err
@ -295,7 +310,7 @@ func validateSecrets(cl *dockerClient.Client, app app.App) error {
return nil
}
func getDeployVersion(cliArgs []string, deployMeta stack.DeployMeta, app app.App) (string, error) {
func getDeployVersion(cliArgs []string, deployMeta stack.DeployMeta, app appPkg.App) (string, error) {
// Chaos mode overrides everything
if internal.Chaos {
v, err := app.Recipe.ChaosVersion()
@ -370,8 +385,8 @@ func init() {
AppDeployCommand.PersistentFlags().BoolVarP(
&internal.DeployLatest,
i18n.G("latest"),
i18n.G("l"),
"latest",
"l",
false,
i18n.G("deploy latest recipe version"),
)

View File

@ -4,11 +4,10 @@ import (
"errors"
"strings"
"coopcloud.tech/abra/pkg/app"
appPkg "coopcloud.tech/abra/pkg/app"
"coopcloud.tech/abra/pkg/autocomplete"
"coopcloud.tech/abra/pkg/config"
"coopcloud.tech/abra/pkg/envfile"
"coopcloud.tech/abra/pkg/deploy"
"coopcloud.tech/abra/pkg/formatter"
"coopcloud.tech/abra/pkg/i18n"
"coopcloud.tech/abra/pkg/lint"
@ -155,13 +154,9 @@ beforehand. See "abra app backup" for more.`),
log.Fatal(err)
}
abraShEnv, err := envfile.ReadAbraShEnvVars(app.Recipe.AbraShPath)
if err != nil {
if err := deploy.MergeAbraShEnv(app.Recipe, app.Env); err != nil {
log.Fatal(err)
}
for k, v := range abraShEnv {
app.Env[k] = v
}
composeFiles, err := app.Recipe.GetComposeFiles(app.Env)
if err != nil {
@ -190,6 +185,24 @@ beforehand. See "abra app backup" for more.`),
}
appPkg.SetUpdateLabel(compose, stackName, app.Env)
// Gather secrets
secretInfo, err := deploy.GatherSecretsForDeploy(cl, app)
if err != nil {
log.Fatal(err)
}
// Gather configs
configInfo, err := deploy.GatherConfigsForDeploy(cl, app, compose, app.Env)
if err != nil {
log.Fatal(err)
}
// Gather images
imageInfo, err := deploy.GatherImagesForDeploy(cl, app, compose)
if err != nil {
log.Fatal(err)
}
// NOTE(d1): no release notes implemeneted for rolling back
if err := internal.DeployOverview(
app,
@ -197,6 +210,9 @@ beforehand. See "abra app backup" for more.`),
chosenDowngrade,
"",
downgradeWarnMessages,
strings.Join(secretInfo, "\n"),
strings.Join(configInfo, "\n"),
strings.Join(imageInfo, "\n"),
); err != nil {
log.Fatal(err)
}
@ -267,7 +283,7 @@ func chooseDowngrade(
// validateDownpgradeVersionArg validates the specific version.
func validateDowngradeVersionArg(
specificVersion string,
app app.App,
app appPkg.App,
deployMeta stack.DeployMeta,
) error {
parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)

View File

@ -71,6 +71,9 @@ Passing "--prune/-p" does not remove those volumes.`),
config.NO_DOMAIN_DEFAULT,
"",
nil,
"",
"",
"",
); err != nil {
log.Fatal(err)
}

View File

@ -7,12 +7,11 @@ import (
"strings"
"coopcloud.tech/abra/cli/internal"
"coopcloud.tech/abra/pkg/app"
appPkg "coopcloud.tech/abra/pkg/app"
"coopcloud.tech/abra/pkg/autocomplete"
"coopcloud.tech/abra/pkg/client"
"coopcloud.tech/abra/pkg/config"
"coopcloud.tech/abra/pkg/envfile"
"coopcloud.tech/abra/pkg/deploy"
"coopcloud.tech/abra/pkg/formatter"
"coopcloud.tech/abra/pkg/i18n"
"coopcloud.tech/abra/pkg/lint"
@ -168,13 +167,9 @@ beforehand. See "abra app backup" for more.`),
log.Fatal(err)
}
abraShEnv, err := envfile.ReadAbraShEnvVars(app.Recipe.AbraShPath)
if err != nil {
if err := deploy.MergeAbraShEnv(app.Recipe, app.Env); err != nil {
log.Fatal(err)
}
for k, v := range abraShEnv {
app.Env[k] = v
}
composeFiles, err := app.Recipe.GetComposeFiles(app.Env)
if err != nil {
@ -216,6 +211,24 @@ beforehand. See "abra app backup" for more.`),
}
}
// Gather secrets
secretInfo, err := deploy.GatherSecretsForDeploy(cl, app)
if err != nil {
log.Fatal(err)
}
// Gather configs
configInfo, err := deploy.GatherConfigsForDeploy(cl, app, compose, app.Env)
if err != nil {
log.Fatal(err)
}
// Gather images
imageInfo, err := deploy.GatherImagesForDeploy(cl, app, compose)
if err != nil {
log.Fatal(err)
}
if showReleaseNotes {
fmt.Print(upgradeReleaseNotes)
return
@ -234,6 +247,9 @@ beforehand. See "abra app backup" for more.`),
chosenUpgrade,
upgradeReleaseNotes,
upgradeWarnMessages,
strings.Join(secretInfo, "\n"),
strings.Join(configInfo, "\n"),
strings.Join(imageInfo, "\n"),
); err != nil {
log.Fatal(err)
}
@ -311,7 +327,7 @@ func chooseUpgrade(
}
func getReleaseNotes(
app app.App,
app appPkg.App,
versions []string,
chosenUpgrade string,
deployMeta stack.DeployMeta,
@ -356,7 +372,7 @@ func getReleaseNotes(
// ensureUpgradesAvailable ensures that there are available upgrades.
func ensureUpgradesAvailable(
app app.App,
app appPkg.App,
versions []string,
availableUpgrades *[]string,
deployMeta stack.DeployMeta,
@ -388,7 +404,7 @@ func ensureUpgradesAvailable(
// validateUpgradeVersionArg validates the specific version.
func validateUpgradeVersionArg(
specificVersion string,
app app.App,
app appPkg.App,
deployMeta stack.DeployMeta,
) error {
parsedSpecificVersion, err := tagcmp.Parse(specificVersion)
@ -415,7 +431,7 @@ func validateUpgradeVersionArg(
// ensureDeployed ensures the app is deployed and if so, returns deployment
// meta info.
func ensureDeployed(cl *dockerClient.Client, app app.App) (stack.DeployMeta, error) {
func ensureDeployed(cl *dockerClient.Client, app appPkg.App) (stack.DeployMeta, error) {
log.Debug(i18n.G("checking whether %s is already deployed", app.StackName()))
deployMeta, err := stack.IsDeployed(context.Background(), cl, app.StackName())

View File

@ -5,8 +5,6 @@ var (
Debug bool
NoInput bool
Offline bool
Help bool
Version bool
// NOTE(d1): sub-command specific
Chaos bool

View File

@ -50,6 +50,9 @@ func DeployOverview(
toDeployVersion string,
releaseNotes string,
warnMessages []string,
secrets string,
configs string,
images string,
) error {
deployConfig := "compose.yml"
if composeFiles, ok := app.Env["COMPOSE_FILE"]; ok {
@ -80,6 +83,24 @@ func DeployOverview(
{i18n.G("CURRENT DEPLOYMENT"), formatter.BoldDirtyDefault(deployedVersion)},
{i18n.G("ENV VERSION"), formatter.BoldDirtyDefault(envVersion)},
{i18n.G("NEW DEPLOYMENT"), formatter.BoldDirtyDefault(toDeployVersion)},
{"", ""},
{i18n.G("IMAGES"), images},
}
if len(secrets) > 0 {
secretsRows := [][]string{
{"", ""},
{i18n.G("SECRETS"), secrets},
}
rows = append(rows, secretsRows...)
}
if len(configs) > 0 {
configsRows := [][]string{
{"", ""},
{i18n.G("CONFIGS"), configs},
}
rows = append(rows, configsRows...)
}
deployType := getDeployType(deployedVersion, toDeployVersion)

View File

@ -47,29 +47,6 @@ Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`)
helpCmd = &cobra.Command{
Use: i18n.G("help [command]"),
// translators: Short description for `help` command
Short: i18n.G("Help about any command"),
Long: i18n.G(`Help provides help for any command in the application.
Simply type abra help [path to command] for full details.`),
Run: func(c *cobra.Command, args []string) {
cmd, _, e := c.Root().Find(args)
if cmd == nil || e != nil {
c.Print(i18n.G("unknown help topic %#q\n", args))
if err := c.Root().Usage(); err != nil {
log.Fatal(err)
}
} else {
cmd.InitDefaultHelpFlag()
cmd.InitDefaultVersionFlag()
if err := cmd.Help(); err != nil {
log.Fatal(err)
}
}
},
}
)
func Run(version, commit string) {
@ -145,7 +122,6 @@ Config:
rootCmd.CompletionOptions.DisableDefaultCmd = true
rootCmd.SetUsageTemplate(usageTemplate)
rootCmd.SetHelpCommand(helpCmd)
// translators: `abra man` aliases. use a comma separated list of aliases
// with no spaces in between
@ -209,24 +185,6 @@ Config:
i18n.G("prefer offline & filesystem access"),
)
rootCmd.PersistentFlags().BoolVarP(
&internal.Help,
i18n.G("help"),
i18n.G("h"),
false,
i18n.G("help for abra"),
)
rootCmd.PersistentFlags().BoolVarP(
&internal.Version,
i18n.G("version"),
// FIXME: temporary workaround for #648
// i18n.G("v"),
"",
false,
i18n.G("version for abra"),
)
catalogue.CatalogueCommand.AddCommand(
catalogue.CatalogueGenerateCommand,
catalogue.CatalogueSyncCommand,

View File

@ -11,6 +11,7 @@ import (
"coopcloud.tech/abra/cli/internal"
appPkg "coopcloud.tech/abra/pkg/app"
"coopcloud.tech/abra/pkg/client"
"coopcloud.tech/abra/pkg/deploy"
"coopcloud.tech/abra/pkg/envfile"
"coopcloud.tech/abra/pkg/i18n"
"coopcloud.tech/abra/pkg/lint"
@ -335,21 +336,6 @@ func processRecipeRepoVersion(r recipe.Recipe, version string) error {
return nil
}
// mergeAbraShEnv merges abra.sh env vars into the app env vars.
func mergeAbraShEnv(recipe recipe.Recipe, env envfile.AppEnv) error {
abraShEnv, err := envfile.ReadAbraShEnvVars(recipe.AbraShPath)
if err != nil {
return err
}
for k, v := range abraShEnv {
log.Debugf("read v:%s k: %s", v, k)
env[k] = v
}
return nil
}
// createDeployConfig merges and enriches the compose config for the deployment.
func createDeployConfig(r recipe.Recipe, stackName string, env envfile.AppEnv) (*composetypes.Config, stack.Deploy, error) {
env["STACK_NAME"] = stackName
@ -444,7 +430,7 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName, upgradeVersion stri
return err
}
if err = mergeAbraShEnv(app.Recipe, app.Env); err != nil {
if err = deploy.MergeAbraShEnv(app.Recipe, app.Env); err != nil {
return err
}

View File

@ -3,6 +3,7 @@ package client
import (
"context"
"errors"
"strings"
"coopcloud.tech/abra/pkg/i18n"
"github.com/docker/docker/api/types/filters"
@ -37,3 +38,12 @@ func RemoveConfigs(cl *client.Client, ctx context.Context, configNames []string,
}
return nil
}
func GetConfigNameAndVersion(fullName string, stackName string) (string, string, error) {
name := strings.TrimPrefix(fullName, stackName+"_")
if lastUnderscore := strings.LastIndex(name, "_"); lastUnderscore != -1 {
return name[0:lastUnderscore], name[lastUnderscore+1:], nil
} else {
return "", "", errors.New(i18n.G("can't parse version from config '%s'", fullName))
}
}

View File

@ -0,0 +1,89 @@
package client
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetConfigNameAndVersion(t *testing.T) {
tests := []struct {
name string
fullName string
stackName string
expected string
expectedVer string
expectError bool
}{
{
name: "valid config with version",
fullName: "myapp_database_v2",
stackName: "myapp",
expected: "database",
expectedVer: "v2",
expectError: false,
},
{
name: "valid config with numeric version",
fullName: "myapp_redis_1",
stackName: "myapp",
expected: "redis",
expectedVer: "1",
expectError: false,
},
{
name: "config without underscore in name",
fullName: "myapp_db_v1",
stackName: "myapp",
expected: "db",
expectedVer: "v1",
expectError: false,
},
{
name: "config with multiple underscores",
fullName: "myapp_my_database_v3",
stackName: "myapp",
expected: "my_database",
expectedVer: "v3",
expectError: false,
},
{
name: "invalid config - no version",
fullName: "myapp_database",
stackName: "myapp",
expectError: true,
},
{
name: "empty config name",
fullName: "myapp__v1",
stackName: "myapp",
expected: "",
expectedVer: "v1",
expectError: false,
},
{
name: "wrong stack prefix",
fullName: "otherapp_database_v1",
stackName: "myapp",
expected: "otherapp_database",
expectedVer: "v1",
expectError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
name, version, err := GetConfigNameAndVersion(tt.fullName, tt.stackName)
if tt.expectError {
assert.Error(t, err)
assert.Empty(t, name)
assert.Empty(t, version)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.expected, name)
assert.Equal(t, tt.expectedVer, version)
}
})
}
}

View File

@ -17,3 +17,11 @@ func StoreSecret(cl *client.Client, secretName, secretValue string) error {
return nil
}
func GetSecretNames(secrets []swarm.Secret) []string {
var secretNames []string
for _, secret := range secrets {
secretNames = append(secretNames, secret.Spec.Name)
}
return secretNames
}

58
pkg/client/secret_test.go Normal file
View File

@ -0,0 +1,58 @@
package client
import (
"testing"
"github.com/docker/docker/api/types/swarm"
"github.com/stretchr/testify/assert"
)
func TestGetSecretNames(t *testing.T) {
tests := []struct {
name string
secrets []swarm.Secret
expected []string
description string
}{
{
name: "empty secrets list",
secrets: []swarm.Secret{},
expected: nil,
description: "should return nil for empty input",
},
{
name: "single secret",
secrets: []swarm.Secret{
{Spec: swarm.SecretSpec{Annotations: swarm.Annotations{Name: "database_password"}}},
},
expected: []string{"database_password"},
description: "should return single secret name",
},
{
name: "multiple secrets",
secrets: []swarm.Secret{
{Spec: swarm.SecretSpec{Annotations: swarm.Annotations{Name: "db_password"}}},
{Spec: swarm.SecretSpec{Annotations: swarm.Annotations{Name: "api_key"}}},
{Spec: swarm.SecretSpec{Annotations: swarm.Annotations{Name: "ssl_cert"}}},
},
expected: []string{"db_password", "api_key", "ssl_cert"},
description: "should return all secret names in order",
},
{
name: "secrets with empty names",
secrets: []swarm.Secret{
{Spec: swarm.SecretSpec{Annotations: swarm.Annotations{Name: ""}}},
{Spec: swarm.SecretSpec{Annotations: swarm.Annotations{Name: "valid_name"}}},
},
expected: []string{"", "valid_name"},
description: "should include empty names if present",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := GetSecretNames(tt.secrets)
assert.Equal(t, tt.expected, result, tt.description)
})
}
}

243
pkg/deploy/utils.go Normal file
View File

@ -0,0 +1,243 @@
package deploy
import (
"context"
"errors"
"fmt"
"regexp"
"sort"
"strings"
appPkg "coopcloud.tech/abra/pkg/app"
"coopcloud.tech/abra/pkg/client"
"coopcloud.tech/abra/pkg/envfile"
"coopcloud.tech/abra/pkg/log"
"coopcloud.tech/abra/pkg/recipe"
"coopcloud.tech/abra/pkg/secret"
composetypes "github.com/docker/cli/cli/compose/types"
"github.com/docker/docker/api/types/swarm"
dockerClient "github.com/docker/docker/client"
)
// MergeAbraShEnv merges abra.sh env vars into the app env vars.
func MergeAbraShEnv(recipe recipe.Recipe, env envfile.AppEnv) error {
abraShEnv, err := envfile.ReadAbraShEnvVars(recipe.AbraShPath)
if err != nil {
return err
}
for k, v := range abraShEnv {
log.Debugf("read v:%s k: %s", v, k)
env[k] = v
}
return nil
}
// GetConfigsForStack retrieves all Docker configs attached to services in a given stack.
func GetConfigsForStack(cl *dockerClient.Client, app appPkg.App) (map[string]string, error) {
filters, err := app.Filters(false, false)
if err != nil {
return nil, err
}
// List all services in the stack
services, err := cl.ServiceList(context.Background(), swarm.ServiceListOptions{
Filters: filters,
})
if err != nil {
return nil, err
}
// Collect unique config names with versions
configs := make(map[string]string)
for _, service := range services {
if service.Spec.TaskTemplate.ContainerSpec != nil {
for _, configRef := range service.Spec.TaskTemplate.ContainerSpec.Configs {
configName := configRef.ConfigName
if configName == "" {
continue
}
configBaseName, configVersion, err := client.GetConfigNameAndVersion(configName, app.StackName())
if err != nil {
log.Warn(err)
continue
}
existingConfigVersion, ok := configs[configBaseName]
if !ok {
// First time seeing this, add to map
configs[configBaseName] = configVersion
} else {
// Just make sure the versions are the same..
if existingConfigVersion != configVersion {
log.Warnf("different versions for config '%s', '%s' and %s'", configBaseName, existingConfigVersion, configVersion)
}
}
}
}
}
return configs, nil
}
func GetImageNameAndTag(imageName string) (string, string, error) {
imageParts := regexp.MustCompile("^([^:]*):([^@]*)@?").FindSubmatch([]byte(imageName))
if len(imageParts) == 0 {
return "", "", errors.New("can't determine image version for image '%s'")
}
imageBaseName := string(imageParts[1])
imageTag := string(imageParts[2])
return imageBaseName, imageTag, nil
}
// GetImagesForStack retrieves all Docker images for services in a given stack.
func GetImagesForStack(cl *dockerClient.Client, app appPkg.App) (map[string]string, error) {
filters, err := app.Filters(false, false)
if err != nil {
return nil, err
}
// List all services in the stack
services, err := cl.ServiceList(context.Background(), swarm.ServiceListOptions{
Filters: filters,
})
if err != nil {
return nil, err
}
// Collect unique image names with versions
images := make(map[string]string)
for _, service := range services {
if service.Spec.TaskTemplate.ContainerSpec != nil {
imageName := service.Spec.TaskTemplate.ContainerSpec.Image
imageBaseName, imageTag, err := GetImageNameAndTag(imageName)
if err != nil {
log.Warn(err)
continue
}
existingImageVersion, ok := images[imageBaseName]
if !ok {
// First time seeing this, add to map
images[imageBaseName] = imageTag
} else {
// Just make sure the versions are the same..
if existingImageVersion != imageTag {
log.Warnf("different versions for image '%s', '%s' and %s'", imageBaseName, existingImageVersion, imageTag)
}
}
}
}
return images, nil
}
func GatherSecretsForDeploy(cl *dockerClient.Client, app appPkg.App) ([]string, error) {
secStats, err := secret.PollSecretsStatus(cl, app)
if err != nil {
return nil, err
}
var secretInfo []string
// Sort secrets to ensure reproducible output
sort.Slice(secStats, func(i, j int) bool {
return secStats[i].LocalName < secStats[j].LocalName
})
for _, secStat := range secStats {
secretInfo = append(secretInfo, fmt.Sprintf("%s: %s", secStat.LocalName, secStat.Version))
}
return secretInfo, nil
}
func GatherConfigsForDeploy(cl *dockerClient.Client, app appPkg.App, compose *composetypes.Config, abraShEnv map[string]string) ([]string, error) {
// Get current configs from existing deployment
currentConfigs, err := GetConfigsForStack(cl, app)
if err != nil {
return nil, err
}
log.Debugf("Deployed config names: %v", currentConfigs)
// Get new configs from the compose specification
newConfigs := compose.Configs
var configInfo []string
for configName := range newConfigs {
log.Debugf("Searching abra.sh for version for %s", configName)
versionKey := strings.ToUpper(configName) + "_VERSION"
newVersion, exists := abraShEnv[versionKey]
if !exists {
log.Warnf("No version found for config %s", configName)
configInfo = append(configInfo, fmt.Sprintf("%s: ? (missing version)", configName))
continue
}
if currentVersion, exists := currentConfigs[configName]; exists {
if currentVersion == newVersion {
configInfo = append(configInfo, fmt.Sprintf("%s: %s (unchanged)", configName, newVersion))
} else {
configInfo = append(configInfo, fmt.Sprintf("%s: %s → %s", configName, currentVersion, newVersion))
}
} else {
configInfo = append(configInfo, fmt.Sprintf("%s: %s (new)", configName, newVersion))
}
}
return configInfo, nil
}
func GatherImagesForDeploy(cl *dockerClient.Client, app appPkg.App, compose *composetypes.Config) ([]string, error) {
// Get current images from existing deployment
currentImages, err := GetImagesForStack(cl, app)
if err != nil {
return nil, err
}
log.Debugf("Deployed images: %v", currentImages)
// Proposed new images from the compose files
newImages := make(map[string]string)
for _, service := range compose.Services {
imageBaseName, imageTag, err := GetImageNameAndTag(service.Image)
if err != nil {
log.Warn(err)
continue
}
existingImageVersion, ok := newImages[imageBaseName]
if !ok {
// First time seeing this, add to map
newImages[imageBaseName] = imageTag
} else {
// Just make sure the versions are the same..
if existingImageVersion != imageTag {
log.Warnf("different versions for image '%s', '%s' and %s'", imageBaseName, existingImageVersion, imageTag)
}
}
}
log.Debugf("Proposed images: %v", newImages)
var imageInfo []string
for newImageName, newImageVersion := range newImages {
if currentVersion, exists := currentImages[newImageName]; exists {
if currentVersion == newImageVersion {
imageInfo = append(imageInfo, fmt.Sprintf("%s: %s (unchanged)", newImageName, newImageVersion))
} else {
imageInfo = append(imageInfo, fmt.Sprintf("%s: %s → %s", newImageName, currentVersion, newImageVersion))
}
} else {
imageInfo = append(imageInfo, fmt.Sprintf("%s: %s (new)", newImageName, newImageVersion))
}
}
return imageInfo, nil
}

87
pkg/deploy/utils_test.go Normal file
View File

@ -0,0 +1,87 @@
package deploy
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetImageNameAndTag(t *testing.T) {
tests := []struct {
name string
imageName string
expectedName string
expectedTag string
expectError bool
description string
}{
{
name: "standard image with tag",
imageName: "nginx:1.23",
expectedName: "nginx",
expectedTag: "1.23",
expectError: false,
description: "should parse standard image name with tag",
},
{
name: "image with digest",
imageName: "nginx:1.23@sha256:abc123",
expectedName: "nginx",
expectedTag: "1.23",
expectError: false,
description: "should parse image with digest, ignoring digest part",
},
{
name: "image with latest tag",
imageName: "redis:latest",
expectedName: "redis",
expectedTag: "latest",
expectError: false,
description: "should parse image with latest tag",
},
{
name: "image with numeric tag",
imageName: "postgres:14",
expectedName: "postgres",
expectedTag: "14",
expectError: false,
description: "should parse image with numeric tag",
},
{
name: "image with complex name",
imageName: "registry.example.com/myapp/api:v1.2.3",
expectedName: "registry.example.com/myapp/api",
expectedTag: "v1.2.3",
expectError: false,
description: "should parse image with registry prefix and complex name",
},
{
name: "image without tag",
imageName: "nginx",
expectError: true,
description: "should error when no tag present",
},
{
name: "empty image name",
imageName: "",
expectError: true,
description: "should error on empty image name",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
name, tag, err := GetImageNameAndTag(tt.imageName)
if tt.expectError {
assert.Error(t, err)
assert.Empty(t, name)
assert.Empty(t, tag)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.expectedName, name)
assert.Equal(t, tt.expectedTag, tag)
}
})
}
}

View File

@ -36,10 +36,6 @@ func LoadLocale() *gotext.Mo {
}
locale := os.Getenv("LANG")
if lastUnderscore := strings.LastIndex(locale, "_"); lastUnderscore != -1 {
locale = locale[0:lastUnderscore]
}
if locale != "" {
if slices.Contains(linguas, locale) {
Locale = locale

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-09-05 17:09-0400\n"
"PO-Revision-Date: 2025-09-04 08:14+0000\n"
"POT-Creation-Date: 2025-09-01 13:48+0200\n"
"PO-Revision-Date: 2025-08-29 21:45+0000\n"
"Last-Translator: chasqui <chasqui@cryptolab.net>\n"
"Language-Team: Spanish <https://translate.coopcloud.tech/projects/co-op-"
"cloud/abra/es/>\n"
@ -44,7 +44,7 @@ msgid ""
" abra recipe fetch gitea --ssh"
msgstr ""
#: cli/run.go:160
#: cli/run.go:136
msgid ""
" # generate the man pages into /usr/local/share/man/man1\n"
" abra_path=$(which abra) # pass abra absolute path to sudo below\n"
@ -376,7 +376,7 @@ msgstr ""
msgid "%s is still deployed. Run \"abra app undeploy %s\""
msgstr ""
#: cli/app/deploy.go:175 cli/app/upgrade.go:214
#: cli/app/deploy.go:172 cli/app/upgrade.go:214
#, c-format
msgid "%s missing from %s.env"
msgstr ""
@ -610,7 +610,7 @@ msgid "Both local recipe and live deployment labels are shown."
msgstr ""
#: cli/app/backup.go:319 cli/app/backup.go:335 cli/app/check.go:95
#: cli/app/cmd.go:285 cli/app/cp.go:385 cli/app/deploy.go:342
#: cli/app/cmd.go:285 cli/app/cp.go:385 cli/app/deploy.go:339
#: cli/app/labels.go:143 cli/app/new.go:377 cli/app/ps.go:213
#: cli/app/restart.go:162 cli/app/restore.go:138 cli/app/secret.go:569
#: cli/app/secret.go:609 cli/app/secret.go:633 cli/app/secret.go:641
@ -700,7 +700,7 @@ msgstr "🚀 Crea una nueva plataforma"
#. translators: Short description for `abra recipe new` command
#: cli/recipe/new.go:43
msgid "Create a new recipe"
msgstr "Crear una nueva receta 🧑‍🍳"
msgstr ""
#. translators: Short description for `app backup create` command
#: cli/app/backup.go:155
@ -777,7 +777,7 @@ msgid ""
"on your $PATH."
msgstr ""
#: cli/app/deploy.go:358 cli/app/new.go:353 cli/app/rollback.go:337
#: cli/app/deploy.go:355 cli/app/new.go:353 cli/app/rollback.go:337
#: cli/app/upgrade.go:447
msgid "D"
msgstr ""
@ -926,7 +926,7 @@ msgid ""
msgstr ""
#. translators: Short description for `man` command
#: cli/run.go:159
#: cli/run.go:135
msgid "Generate manpage"
msgstr "📒 Manual de uso"
@ -956,17 +956,6 @@ msgstr ""
msgid "HOST"
msgstr ""
#. translators: Short description for `help` command
#: cli/run.go:54
msgid "Help about any command"
msgstr ""
#: cli/run.go:55
msgid ""
"Help provides help for any command in the application.\n"
"Simply type abra help [path to command] for full details."
msgstr ""
#: cli/app/ps.go:187 cli/recipe/version.go:69
msgid "IMAGE"
msgstr ""
@ -1417,14 +1406,14 @@ msgid "The Co-op Cloud auto-updater 🤖 🚀"
msgstr "📨 Actualizador automático de Co-op Cloud 🤖 🚀"
#. translators: Short description for `abra` binary
#: cli/run.go:80
#: cli/run.go:57
msgid "The Co-op Cloud command-line utility belt 🎩🐇"
msgstr "La varita de mágica de Co-op Cloud 🪄🎩🐇"
#. translators: Long description for `abra` binary. This needs to be
#. translated in the same way as the Short description so that everything
#. matches up
#: cli/run.go:84
#: cli/run.go:61
#, fuzzy, c-format
msgid ""
"The Co-op Cloud command-line utility belt 🎩🐇\n"
@ -1811,7 +1800,7 @@ msgid "aborting as requested"
msgstr ""
#. translators: `abra` binary name
#: cli/run.go:78
#: cli/run.go:55
msgid "abra [cmd] [args] [flags]"
msgstr ""
@ -1819,7 +1808,7 @@ msgstr ""
msgid "abra app labels 1312.net"
msgstr ""
#: cli/run.go:137
#: cli/run.go:114
#, c-format
msgid "abra version: %s, commit: %s, lang: %s"
msgstr ""
@ -1896,7 +1885,7 @@ msgid "ambiguous service list received, prompting for input"
msgstr ""
#. translators: `abra app` command for autocompletion
#: cli/run.go:91
#: cli/run.go:68
msgid "app"
msgstr "plataforma"
@ -1938,7 +1927,7 @@ msgstr ""
msgid "attempting to run %s"
msgstr ""
#: cli/app/deploy.go:238 cli/app/upgrade.go:273
#: cli/app/deploy.go:235 cli/app/upgrade.go:273
#, c-format
msgid "attempting to run post deploy commands, saw: %s"
msgstr ""
@ -1954,7 +1943,7 @@ msgid "attempting to scale %s to 1"
msgstr ""
#. translators: `abra autocomplete` command for autocompletion
#: cli/run.go:93
#: cli/run.go:70
msgid "autocomplete"
msgstr ""
@ -2034,7 +2023,7 @@ msgstr ""
#. no spaces in between
#. translators: `abra app cp` aliases. use a comma separated list of aliases with
#. no spaces in between
#: cli/app/backup.go:148 cli/app/cp.go:30 cli/app/deploy.go:366
#: cli/app/backup.go:148 cli/app/cp.go:30 cli/app/deploy.go:363
#: cli/app/rollback.go:345 cli/app/upgrade.go:455
msgid "c"
msgstr ""
@ -2104,7 +2093,7 @@ msgstr ""
msgid "cannot use '[secret] [version]' and '--all' together"
msgstr ""
#: cli/app/deploy.go:277
#: cli/app/deploy.go:274
msgid "cannot use --chaos and --latest together"
msgstr ""
@ -2128,16 +2117,16 @@ msgstr ""
msgid "cannot use [service] and --all-services/-a together"
msgstr ""
#: cli/app/deploy.go:269 cli/app/new.go:76
#: cli/app/deploy.go:266 cli/app/new.go:76
msgid "cannot use [version] and --chaos together"
msgstr ""
#: cli/app/deploy.go:273
#: cli/app/deploy.go:270
msgid "cannot use [version] and --latest together"
msgstr ""
#. translators: `abra catalogue` command for autocompletion
#: cli/run.go:95
#: cli/run.go:72
msgid "catalogue"
msgstr ""
@ -2165,7 +2154,7 @@ msgid "cfg"
msgstr ""
#: cli/app/backup.go:318 cli/app/backup.go:334 cli/app/check.go:94
#: cli/app/cmd.go:284 cli/app/cp.go:384 cli/app/deploy.go:341
#: cli/app/cmd.go:284 cli/app/cp.go:384 cli/app/deploy.go:338
#: cli/app/labels.go:142 cli/app/new.go:376 cli/app/ps.go:212
#: cli/app/restart.go:161 cli/app/restore.go:137 cli/app/secret.go:568
#: cli/app/secret.go:608 cli/app/secret.go:632 cli/app/secret.go:640
@ -2523,7 +2512,7 @@ msgstr ""
msgid "deploy labels stanza present"
msgstr ""
#: cli/app/deploy.go:376
#: cli/app/deploy.go:373
#, fuzzy
msgid "deploy latest recipe version"
msgstr "Publicar una nueva versión de una receta"
@ -2601,11 +2590,11 @@ msgstr ""
msgid "dirty: %v, "
msgstr ""
#: cli/app/deploy.go:368 cli/app/rollback.go:347 cli/app/upgrade.go:457
#: cli/app/deploy.go:365 cli/app/rollback.go:347 cli/app/upgrade.go:457
msgid "disable converge logic checks"
msgstr ""
#: cli/app/deploy.go:360 cli/app/rollback.go:339 cli/app/upgrade.go:449
#: cli/app/deploy.go:357 cli/app/rollback.go:339 cli/app/upgrade.go:449
msgid "disable public DNS checks"
msgstr ""
@ -2634,7 +2623,7 @@ msgstr ""
msgid "domain name for app"
msgstr ""
#: cli/run.go:184
#: cli/run.go:160
msgid "don't forget to run 'sudo mandb'"
msgstr ""
@ -2850,7 +2839,7 @@ msgstr ""
#. translators: `abra recipe fetch` aliases. use a comma separated list of aliases
#. with no spaces in between
#: cli/app/deploy.go:350 cli/app/remove.go:163 cli/app/rollback.go:329
#: cli/app/deploy.go:347 cli/app/remove.go:163 cli/app/rollback.go:329
#: cli/app/secret.go:593 cli/app/upgrade.go:439 cli/app/volume.go:217
#: cli/recipe/fetch.go:20 cli/recipe/fetch.go:138
msgid "f"
@ -3088,7 +3077,7 @@ msgstr ""
msgid "for %s read env %s with value: %s from docker service"
msgstr ""
#: cli/app/deploy.go:349 cli/app/remove.go:162 cli/app/rollback.go:328
#: cli/app/deploy.go:346 cli/app/remove.go:162 cli/app/rollback.go:328
#: cli/app/upgrade.go:438 cli/app/volume.go:216 cli/recipe/fetch.go:137
msgid "force"
msgstr ""
@ -3261,10 +3250,6 @@ msgstr ""
msgid "git: opening repository in %s"
msgstr ""
#: cli/run.go:215
msgid "h"
msgstr ""
#: cli/recipe/new.go:94
msgid "happy hacking 🎉"
msgstr ""
@ -3281,19 +3266,6 @@ msgstr ""
msgid "healthcheck enabled for all services"
msgstr ""
#: cli/run.go:214
msgid "help"
msgstr ""
#: cli/run.go:52
#, fuzzy
msgid "help [command]"
msgstr "💻 Ejecutar comandos en una plataforma 🚀"
#: cli/run.go:217
msgid "help for abra"
msgstr ""
#: cli/app/restore.go:129
msgid "hooks"
msgstr ""
@ -3310,7 +3282,7 @@ msgid "id: %s, "
msgstr ""
#: cli/app/backup.go:321 cli/app/backup.go:337 cli/app/check.go:97
#: cli/app/cmd.go:287 cli/app/cp.go:387 cli/app/deploy.go:344
#: cli/app/cmd.go:287 cli/app/cp.go:387 cli/app/deploy.go:341
#: cli/app/labels.go:145 cli/app/new.go:379 cli/app/ps.go:215
#: cli/app/restart.go:164 cli/app/restore.go:140 cli/app/secret.go:571
#: cli/app/secret.go:611 cli/app/secret.go:635 cli/app/secret.go:643
@ -3510,8 +3482,8 @@ msgstr ""
#. no spaces in between
#. translators: `abra recipe lint` aliases. use a comma separated list of
#. aliases with no spaces in between
#: cli/app/cmd.go:261 cli/app/deploy.go:374 cli/app/logs.go:20
#: cli/recipe/lint.go:17 cli/server/add.go:207
#: cli/app/cmd.go:261 cli/app/logs.go:20 cli/recipe/lint.go:17
#: cli/server/add.go:207
msgid "l"
msgstr ""
@ -3520,7 +3492,7 @@ msgstr ""
msgid "labels <domain> [flags]"
msgstr "etiquetas <domain> [flags]"
#: cli/app/deploy.go:373 cli/app/list.go:183
#: cli/app/list.go:183
msgid "latest"
msgstr ""
@ -3647,7 +3619,7 @@ msgstr "plataformas"
#. with no spaces in between
#: cli/app/list.go:318 cli/app/move.go:34 cli/app/ps.go:205
#: cli/app/secret.go:553 cli/app/secret.go:649 cli/recipe/list.go:104
#: cli/recipe/upgrade.go:376 cli/recipe/version.go:139 cli/run.go:152
#: cli/recipe/upgrade.go:376 cli/recipe/version.go:139 cli/run.go:128
#: cli/server/list.go:106 cli/updater/updater.go:560
msgid "m"
msgstr ""
@ -3675,12 +3647,12 @@ msgid "malformed version pin specification: %s"
msgstr ""
#. translators: `abra man` command for autocompletion
#: cli/run.go:97
#: cli/run.go:74
msgid "man"
msgstr ""
#. translators: `man` command
#: cli/run.go:156
#: cli/run.go:132
msgid "man [flags]"
msgstr "manual [flags]"
@ -3722,8 +3694,9 @@ msgstr ""
#. translators: `app move` command
#: cli/app/move.go:38
#, fuzzy
msgid "move <domain> <server> [flags]"
msgstr "mover <domain> [flags]"
msgstr "borrar <domain> [flags]"
#: cli/app/move.go:137
#, c-format
@ -3743,7 +3716,7 @@ msgstr ""
#: cli/app/new.go:48 cli/recipe/new.go:36 cli/updater/updater.go:35
#: cli/updater/updater.go:513
msgid "n"
msgstr "n"
msgstr ""
#: cli/recipe/list.go:43
msgid "name"
@ -3994,11 +3967,11 @@ msgstr ""
msgid "no volumes to remove"
msgstr ""
#: cli/app/deploy.go:365 cli/app/rollback.go:344 cli/app/upgrade.go:454
#: cli/app/deploy.go:362 cli/app/rollback.go:344 cli/app/upgrade.go:454
msgid "no-converge-checks"
msgstr ""
#: cli/app/deploy.go:357 cli/app/rollback.go:336 cli/app/upgrade.go:446
#: cli/app/deploy.go:354 cli/app/rollback.go:336 cli/app/upgrade.go:446
msgid "no-domain-checks"
msgstr ""
@ -4142,7 +4115,7 @@ msgstr ""
msgid "pattern"
msgstr ""
#: cli/app/deploy.go:352 cli/app/remove.go:165 cli/app/rollback.go:331
#: cli/app/deploy.go:349 cli/app/remove.go:165 cli/app/rollback.go:331
#: cli/app/upgrade.go:441 cli/app/volume.go:219
msgid "perform action without further prompt"
msgstr ""
@ -4181,7 +4154,7 @@ msgstr ""
msgid "polling undeploy status"
msgstr "📋 Revisar el estado de una plataforma"
#: cli/run.go:209
#: cli/run.go:185
msgid "prefer offline & filesystem access"
msgstr ""
@ -4322,7 +4295,7 @@ msgid "readme: %s, "
msgstr ""
#. translators: `abra recipe` command for autocompletion
#: cli/app/list.go:302 cli/app/list.go:309 cli/run.go:99
#: cli/app/list.go:302 cli/app/list.go:309 cli/run.go:76
msgid "recipe"
msgstr ""
@ -4667,7 +4640,7 @@ msgstr ""
msgid "run command locally"
msgstr ""
#: cli/app/deploy.go:236 cli/app/upgrade.go:270
#: cli/app/deploy.go:233 cli/app/upgrade.go:270
#, c-format
msgid "run the following post-deploy commands: %s"
msgstr ""
@ -4751,7 +4724,7 @@ msgstr ""
msgid "secret not found: %s"
msgstr ""
#: cli/app/deploy.go:291
#: cli/app/deploy.go:288
#, c-format
msgid "secret not generated: %s"
msgstr ""
@ -4772,7 +4745,7 @@ msgstr ""
#. translators: `abra server` command for autocompletion
#: cli/app/list.go:325 cli/app/list.go:332 cli/app/new.go:337
#: cli/app/new.go:344 cli/run.go:101
#: cli/app/new.go:344 cli/run.go:78
msgid "server"
msgstr ""
@ -4890,7 +4863,7 @@ msgstr ""
msgid "show apps of a specific server"
msgstr ""
#: cli/run.go:193 cli/updater/updater.go:507
#: cli/run.go:169 cli/updater/updater.go:507
msgid "show debug messages"
msgstr ""
@ -4938,11 +4911,11 @@ msgstr ""
msgid "skipping converge logic checks"
msgstr ""
#: cli/app/deploy.go:189
#: cli/app/deploy.go:186
msgid "skipping domain checks"
msgstr ""
#: cli/app/deploy.go:186
#: cli/app/deploy.go:183
msgid "skipping domain checks, no DOMAIN=... configured"
msgstr ""
@ -5174,7 +5147,7 @@ msgstr ""
msgid "tmpfs options are incompatible with type volume"
msgstr ""
#: cli/run.go:201 cli/updater/updater.go:515
#: cli/run.go:177 cli/updater/updater.go:515
msgid "toggle non-interactive mode"
msgstr ""
@ -5259,7 +5232,7 @@ msgstr ""
msgid "unable to convert to JSON: %s"
msgstr ""
#: cli/run.go:117
#: cli/run.go:94
#, c-format
msgid "unable to create %s: %s"
msgstr ""
@ -5354,7 +5327,7 @@ msgstr ""
msgid "unable to parse '%s' value as bool: %s"
msgstr ""
#: cli/run.go:176
#: cli/run.go:152
#, c-format
msgid "unable to proceed, %s does not exist?"
msgstr ""
@ -5517,11 +5490,6 @@ msgstr ""
msgid "unknown deployed version, unable to upgrade"
msgstr ""
#: cli/run.go:60
#, c-format
msgid "unknown help topic %#q\n"
msgstr ""
#: pkg/upstream/convert/service.go:780
#, c-format
msgid "unknown mode: %s"
@ -5563,7 +5531,7 @@ msgid "updating %s to %s in %s"
msgstr ""
#. translators: `abra upgrade` command for autocompletion
#: cli/run.go:103
#: cli/run.go:80
msgid "upgrade"
msgstr ""
@ -5667,30 +5635,16 @@ msgstr ""
msgid "vendor config versions in an abra.sh"
msgstr ""
#: cli/run.go:222
msgid "version"
msgstr ""
#: pkg/app/app.go:688
#, c-format
msgid "version %s saved to %s.env"
msgstr ""
#: cli/app/deploy.go:116
#, c-format
msgid ""
"version '%s' appears to be a chaos commit, but --chaos/-C was not provided"
msgstr ""
#: pkg/recipe/recipe.go:200
#, c-format
msgid "version : %s, "
msgstr ""
#: cli/run.go:227
msgid "version for abra"
msgstr ""
#: pkg/recipe/recipe.go:130
#, c-format
msgid "version seems invalid: %s"
@ -5701,32 +5655,32 @@ msgstr ""
msgid "version wiped from %s.env"
msgstr ""
#: cli/app/deploy.go:318
#: cli/app/deploy.go:315
#, c-format
msgid "version: can not redeploy chaos version %s"
msgstr ""
#: cli/app/deploy.go:305
#: cli/app/deploy.go:302
#, c-format
msgid "version: taking chaos version: %s"
msgstr ""
#: cli/app/deploy.go:326
#: cli/app/deploy.go:323
#, c-format
msgid "version: taking deployed version: %s"
msgstr ""
#: cli/app/deploy.go:331
#: cli/app/deploy.go:328
#, c-format
msgid "version: taking new recipe version: %s"
msgstr ""
#: cli/app/deploy.go:320
#: cli/app/deploy.go:317
#, c-format
msgid "version: taking version from .env file: %s"
msgstr ""
#: cli/app/deploy.go:311
#: cli/app/deploy.go:308
#, c-format
msgid "version: taking version from cli arg: %s"
msgstr ""
@ -5852,7 +5806,7 @@ msgstr ""
msgid "writer: %v, "
msgstr ""
#: cli/app/deploy.go:243 cli/app/new.go:221 cli/app/rollback.go:232
#: cli/app/deploy.go:240 cli/app/new.go:221 cli/app/rollback.go:232
#: cli/app/undeploy.go:111 cli/app/upgrade.go:278
#, c-format
msgid "writing recipe version failed: %s"

View File

@ -280,7 +280,7 @@ type secretStatus struct {
type secretStatuses []secretStatus
// PollSecretsStatus checks status of secrets by comparing the local recipe
// config and deploymend server state.
// config and deployed server state.
func PollSecretsStatus(cl *dockerClient.Client, app appPkg.App) (secretStatuses, error) {
var secStats secretStatuses
@ -306,7 +306,7 @@ func PollSecretsStatus(cl *dockerClient.Client, app appPkg.App) (secretStatuses,
remoteSecretNames := make(map[string]bool)
for _, cont := range secretList {
remoteSecretNames[cont.Spec.Annotations.Name] = true
remoteSecretNames[cont.Spec.Name] = true
}
for secretName, val := range secretsConfig {

View File

@ -174,23 +174,6 @@ teardown(){
assert_output --partial "${wantHash:0:8}"
}
# bats test_tags=slow
@test "bail if env has a hash but no --chaos" {
wantHash=$(_get_n_hash 3)
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" reset --hard HEAD~3
assert_success
assert_equal $(_get_current_hash) "$wantHash"
_ensure_env_version "$wantHash"
run $ABRA app deploy "$TEST_APP_DOMAIN" \
--no-input --no-converge-checks
assert_failure
assert_output --partial "chaos commit"
}
# bats test_tags=slow
@test "retrieve recipe if missing" {
run rm -rf "$ABRA_DIR/recipes/$TEST_RECIPE"

View File

@ -19,18 +19,11 @@ teardown_file(){
_rm_app
_rm_server
_reset_recipe
# NOTE(d1): fallback cleanup, not interested in failures here
run docker secret rm "${TEST_APP_DOMAIN}_test_pass_one_v1"
rm -rf "${BATS_TMPFILE}"
}
setup(){
load "$PWD/tests/integration/helpers/common"
_common_setup
export BATS_TMPFILE="$(mktemp)"
echo MySuperCoolPassword > ${BATS_TMPFILE}
}
teardown(){
@ -331,41 +324,6 @@ teardown(){
assert_not_exists "$ABRA_DIR/recipes/$TEST_RECIPE/foo"
}
@test "rm: dont remove all versions" {
run sed -i 's/SECRET_TEST_PASS_ONE_VERSION=v1/SECRET_TEST_PASS_ONE_VERSION=v2/g' \
"$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
assert_success
run $ABRA app secret generate "$TEST_APP_DOMAIN" --all
assert_success
run $ABRA app secret ls "$TEST_APP_DOMAIN"
assert_success
assert_output --partial 'test_pass_one_v2'
assert_output --partial 'true'
run docker secret create "${TEST_APP_DOMAIN}_test_pass_one_v1" "$BATS_TMPFILE"
assert_success
run docker secret ls
assert_success
assert_output --partial "${TEST_APP_DOMAIN}_test_pass_one_v1"
run $ABRA app secret rm "$TEST_APP_DOMAIN" --all
assert_success
run $ABRA app secret ls "$TEST_APP_DOMAIN"
assert_success
assert_output --partial 'false'
run docker secret ls
assert_success
assert_output --partial "${TEST_APP_DOMAIN}_test_pass_one_v1"
run docker secret rm "${TEST_APP_DOMAIN}_test_pass_one_v1"
assert_success
}
@test "ls: validate arguments" {
run $ABRA app secret ls
assert_failure

View File

@ -30,7 +30,7 @@ _ensure_catalogue(){
}
_ensure_env_version(){
run sed -i "s/TYPE=abra-test-recipe:.*/TYPE=abra-test-recipe:$1/g" \
run sed -i 's/TYPE=abra-test-recipe:.*/TYPE=abra-test-recipe:$1/g' \
"$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
assert_success
}