diff --git a/README.md b/README.md index 5ae21bbe..112d0abb 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Build Status](https://build.coopcloud.tech/api/badges/toolshed/abra/status.svg?ref=refs/heads/main)](https://build.coopcloud.tech/toolshed/abra) [![Go Report Card](https://goreportcard.com/badge/git.coopcloud.tech/toolshed/abra)](https://goreportcard.com/report/git.coopcloud.tech/toolshed/abra) [![Go Reference](https://pkg.go.dev/badge/coopcloud.tech/abra.svg)](https://pkg.go.dev/coopcloud.tech/abra) +[![Translation status](https://translate.coopcloud.tech/widget/co-op-cloud/svg-badge.svg)](https://translate.coopcloud.tech/engage/co-op-cloud/) The Co-op Cloud utility belt 🎩🐇 diff --git a/cli/app/app.go b/cli/app/app.go index 259dadfc..59f31165 100644 --- a/cli/app/app.go +++ b/cli/app/app.go @@ -1,12 +1,12 @@ package app import ( - "github.com/leonelquinteros/gotext" + "coopcloud.tech/abra/pkg/i18n" "github.com/spf13/cobra" ) var AppCommand = &cobra.Command{ - Use: "app [cmd] [args] [flags]", - Aliases: []string{"a"}, - Short: gotext.Get("Manage apps"), + Use: i18n.G("app [cmd] [args] [flags]"), + Aliases: []string{i18n.G("a")}, + Short: i18n.G("Manage apps"), } diff --git a/cli/app/backup.go b/cli/app/backup.go index 83083172..13d70d7e 100644 --- a/cli/app/backup.go +++ b/cli/app/backup.go @@ -6,14 +6,15 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/spf13/cobra" ) var AppBackupListCommand = &cobra.Command{ - Use: "list [flags]", - Aliases: []string{"ls"}, - Short: "List the contents of a snapshot", + Use: i18n.G("list [flags]"), + Aliases: []string{i18n.G("ls")}, + Short: i18n.G("List the contents of a snapshot"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -40,17 +41,17 @@ var AppBackupListCommand = &cobra.Command{ } if snapshot != "" { - log.Debugf("including SNAPSHOT=%s in backupbot exec invocation", snapshot) + log.Debug(i18n.G("including SNAPSHOT=%s in backupbot exec invocation", snapshot)) execEnv = append(execEnv, fmt.Sprintf("SNAPSHOT=%s", snapshot)) } if showAllPaths { - log.Debugf("including SHOW_ALL=%v in backupbot exec invocation", showAllPaths) + log.Debug(i18n.G("including SHOW_ALL=%v in backupbot exec invocation", showAllPaths)) execEnv = append(execEnv, fmt.Sprintf("SHOW_ALL=%v", showAllPaths)) } if timestamps { - log.Debugf("including TIMESTAMPS=%v in backupbot exec invocation", timestamps) + log.Debug(i18n.G("including TIMESTAMPS=%v in backupbot exec invocation", timestamps)) execEnv = append(execEnv, fmt.Sprintf("TIMESTAMPS=%v", timestamps)) } @@ -61,13 +62,13 @@ var AppBackupListCommand = &cobra.Command{ } var AppBackupDownloadCommand = &cobra.Command{ - Use: "download [flags]", - Aliases: []string{"d"}, - Short: "Download a snapshot", - Long: `Downloads a backup.tar.gz to the current working directory. + Use: i18n.G("download [flags]"), + Aliases: []string{i18n.G("d")}, + Short: i18n.G("Download a snapshot"), + Long: i18n.G(`Downloads a backup.tar.gz to the current working directory. "--volumes/-v" includes data contained in volumes alongide paths specified in -"backupbot.backup.path" labels.`, +"backupbot.backup.path" labels.`), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -98,22 +99,22 @@ var AppBackupDownloadCommand = &cobra.Command{ } if snapshot != "" { - log.Debugf("including SNAPSHOT=%s in backupbot exec invocation", snapshot) + log.Debug(i18n.G("including SNAPSHOT=%s in backupbot exec invocation", snapshot)) execEnv = append(execEnv, fmt.Sprintf("SNAPSHOT=%s", snapshot)) } if includePath != "" { - log.Debugf("including INCLUDE_PATH=%s in backupbot exec invocation", includePath) + log.Debug(i18n.G("including INCLUDE_PATH=%s in backupbot exec invocation", includePath)) execEnv = append(execEnv, fmt.Sprintf("INCLUDE_PATH=%s", includePath)) } if includeSecrets { - log.Debugf("including SECRETS=%v in backupbot exec invocation", includeSecrets) + log.Debug(i18n.G("including SECRETS=%v in backupbot exec invocation", includeSecrets)) execEnv = append(execEnv, fmt.Sprintf("SECRETS=%v", includeSecrets)) } if includeVolumes { - log.Debugf("including VOLUMES=%v in backupbot exec invocation", includeVolumes) + log.Debug(i18n.G("including VOLUMES=%v in backupbot exec invocation", includeVolumes)) execEnv = append(execEnv, fmt.Sprintf("VOLUMES=%v", includeVolumes)) } @@ -130,9 +131,9 @@ var AppBackupDownloadCommand = &cobra.Command{ } var AppBackupCreateCommand = &cobra.Command{ - Use: "create [flags]", - Aliases: []string{"c"}, - Short: "Create a new snapshot", + Use: i18n.G("create [flags]"), + Aliases: []string{i18n.G("c")}, + Short: i18n.G("Create a new snapshot"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -163,7 +164,7 @@ var AppBackupCreateCommand = &cobra.Command{ } if retries != "" { - log.Debugf("including RETRIES=%s in backupbot exec invocation", retries) + log.Debug(i18n.G("including RETRIES=%s in backupbot exec invocation", retries)) execEnv = append(execEnv, fmt.Sprintf("RETRIES=%s", retries)) } @@ -174,9 +175,9 @@ var AppBackupCreateCommand = &cobra.Command{ } var AppBackupSnapshotsCommand = &cobra.Command{ - Use: "snapshots [flags]", - Aliases: []string{"s"}, - Short: "List all snapshots", + Use: i18n.G("snapshots [flags]"), + Aliases: []string{i18n.G("s")}, + Short: i18n.G("List all snapshots"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -209,9 +210,9 @@ var AppBackupSnapshotsCommand = &cobra.Command{ } var AppBackupCommand = &cobra.Command{ - Use: "backup [cmd] [args] [flags]", - Aliases: []string{"b"}, - Short: "Manage app backups", + Use: i18n.G("backup [cmd] [args] [flags]"), + Aliases: []string{i18n.G("b")}, + Short: i18n.G("Manage app backups"), } var ( @@ -227,81 +228,81 @@ var ( func init() { AppBackupListCommand.Flags().StringVarP( &snapshot, - "snapshot", - "s", + i18n.G("snapshot"), + i18n.G("s"), "", - "list specific snapshot", + i18n.G("list specific snapshot"), ) AppBackupListCommand.Flags().BoolVarP( &showAllPaths, - "all", - "a", + i18n.G("all"), + i18n.G("a"), false, - "show all paths", + i18n.G("show all paths"), ) AppBackupListCommand.Flags().BoolVarP( ×tamps, - "timestamps", - "t", + i18n.G("timestamps"), + i18n.G("t"), false, - "include timestamps", + i18n.G("include timestamps"), ) AppBackupDownloadCommand.Flags().StringVarP( &snapshot, - "snapshot", - "s", + i18n.G("snapshot"), + i18n.G("s"), "", - "list specific snapshot", + i18n.G("list specific snapshot"), ) AppBackupDownloadCommand.Flags().StringVarP( &includePath, - "path", - "p", + i18n.G("path"), + i18n.G("p"), "", - "volumes path", + i18n.G("volumes path"), ) AppBackupDownloadCommand.Flags().BoolVarP( &includeSecrets, - "secrets", - "S", + i18n.G("secrets"), + i18n.G("S"), false, - "include secrets", + i18n.G("include secrets"), ) AppBackupDownloadCommand.Flags().BoolVarP( &includeVolumes, - "volumes", - "v", + i18n.G("volumes"), + i18n.G("v"), false, - "include volumes", + i18n.G("include volumes"), ) AppBackupDownloadCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) AppBackupCreateCommand.Flags().StringVarP( &retries, - "retries", - "r", + i18n.G("retries"), + i18n.G("r"), "1", - "number of retry attempts", + i18n.G("number of retry attempts"), ) AppBackupCreateCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) } diff --git a/cli/app/check.go b/cli/app/check.go index dde31b93..fab92047 100644 --- a/cli/app/check.go +++ b/cli/app/check.go @@ -7,16 +7,17 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/charmbracelet/lipgloss" "github.com/spf13/cobra" ) var AppCheckCommand = &cobra.Command{ - Use: "check [flags]", - Aliases: []string{"chk"}, - Short: "Ensure an app is well configured", - Long: `Compare env vars in both the app ".env" and recipe ".env.sample" file. + Use: i18n.G("check [flags]"), + Aliases: []string{i18n.G("chk")}, + Short: i18n.G("Ensure an app is well configured"), + Long: i18n.G(`Compare env vars in both the app ".env" and recipe ".env.sample" file. The goal is to ensure that recipe ".env.sample" env vars are defined in your app ".env" file. Only env var definitions in the ".env.sample" which are @@ -25,7 +26,7 @@ these env vars, then "check" will complain. Recipe maintainers may or may not provide defaults for env vars within their recipes regardless of commenting or not (e.g. through the use of -${FOO:} syntax). "check" does not confirm or deny this for you.`, +${FOO:} syntax). "check" does not confirm or deny this for you.`), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -83,9 +84,9 @@ ${FOO:} syntax). "check" does not confirm or deny this for you.`, func init() { AppCheckCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) } diff --git a/cli/app/cmd.go b/cli/app/cmd.go index a8e2e17f..00477fe0 100644 --- a/cli/app/cmd.go +++ b/cli/app/cmd.go @@ -13,15 +13,16 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/spf13/cobra" ) var AppCmdCommand = &cobra.Command{ - Use: "command [service | --local] [[args] [flags] | [flags] -- [args]]", - Aliases: []string{"cmd"}, - Short: "Run app commands", - Long: `Run an app specific command. + Use: i18n.G("command [service | --local] [[args] [flags] | [flags] -- [args]]"), + Aliases: []string{i18n.G("cmd")}, + Short: i18n.G("Run app commands"), + Long: i18n.G(`Run an app specific command. These commands are bash functions, defined in the abra.sh of the recipe itself. They can be run within the context of a service (e.g. app) or locally on your @@ -30,24 +31,24 @@ work station by passing "--local/-l". N.B. If using the "--" style to pass arguments, flags (e.g. "--local/-l") must be passed *before* the "--". It is possible to pass arguments without the "--" as long as no dashes are present (i.e. "foo" works without "--", "-foo" -does not).`, - Example: ` # pass args/flags without "--" +does not).`), + Example: i18n.G(` # pass args/flags without "--" abra app cmd 1312.net app my_cmd_arg foo --user bar # pass args/flags with "--" abra app cmd 1312.net app my_cmd_args --user bar -- foo -vvv # drop the [service] arg if using "--local/-l" - abra app cmd 1312.net my_cmd --local`, + abra app cmd 1312.net my_cmd --local`), Args: func(cmd *cobra.Command, args []string) error { if local { if !(len(args) >= 2) { - return errors.New("requires at least 2 arguments with --local/-l") + return errors.New(i18n.G("requires at least 2 arguments with --local/-l")) } if slices.Contains(os.Args, "--") { if cmd.ArgsLenAtDash() > 2 { - return errors.New("accepts at most 2 args with --local/-l") + return errors.New(i18n.G("accepts at most 2 args with --local/-l")) } } @@ -63,7 +64,7 @@ does not).`, } if !(len(args) >= 3) { - return errors.New("requires at least 3 arguments") + return errors.New(i18n.G("requires at least 3 arguments")) } return nil @@ -97,14 +98,14 @@ does not).`, } if local && remoteUser != "" { - log.Fatal("cannot use --local & --user together") + log.Fatal(i18n.G("cannot use --local & --user together")) } hasCmdArgs, parsedCmdArgs := parseCmdArgs(args, local) if _, err := os.Stat(app.Recipe.AbraShPath); err != nil { if os.IsNotExist(err) { - log.Fatalf("%s does not exist for %s?", app.Recipe.AbraShPath, app.Name) + log.Fatal(i18n.G("%s does not exist for %s?", app.Recipe.AbraShPath, app.Name)) } log.Fatal(err) } @@ -115,7 +116,7 @@ does not).`, log.Fatal(err) } - log.Debugf("--local detected, running %s on local work station", cmdName) + log.Debug(i18n.G("--local detected, running %s on local work station", cmdName)) var exportEnv string for k, v := range app.Env { @@ -124,16 +125,16 @@ does not).`, var sourceAndExec string if hasCmdArgs { - log.Debugf("parsed following command arguments: %s", parsedCmdArgs) + log.Debug(i18n.G("parsed following command arguments: %s", parsedCmdArgs)) sourceAndExec = fmt.Sprintf("TARGET=local; APP_NAME=%s; STACK_NAME=%s; %s . %s; %s %s", app.Name, app.StackName(), exportEnv, app.Recipe.AbraShPath, cmdName, parsedCmdArgs) } else { - log.Debug("did not detect any command arguments") + log.Debug(i18n.G("did not detect any command arguments")) sourceAndExec = fmt.Sprintf("TARGET=local; APP_NAME=%s; STACK_NAME=%s; %s . %s; %s", app.Name, app.StackName(), exportEnv, app.Recipe.AbraShPath, cmdName) } shell := "/bin/bash" if _, err := os.Stat(shell); errors.Is(err, os.ErrNotExist) { - log.Debugf("%s does not exist locally, use /bin/sh as fallback", shell) + log.Debug(i18n.G("%s does not exist locally, use /bin/sh as fallback", shell)) shell = "/bin/sh" } cmd := exec.Command(shell, "-c", sourceAndExec) @@ -164,15 +165,15 @@ does not).`, } if !matchingServiceName { - log.Fatalf("no service %s for %s?", targetServiceName, app.Name) + log.Fatal(i18n.G("no service %s for %s?", targetServiceName, app.Name)) } - log.Debugf("running command %s within the context of %s_%s", cmdName, app.StackName(), targetServiceName) + log.Debug(i18n.G("running command %s within the context of %s_%s", cmdName, app.StackName(), targetServiceName)) if hasCmdArgs { - log.Debugf("parsed following command arguments: %s", parsedCmdArgs) + log.Debug(i18n.G("parsed following command arguments: %s", parsedCmdArgs)) } else { - log.Debug("did not detect any command arguments") + log.Debug(i18n.G("did not detect any command arguments")) } cl, err := client.New(app.Server) @@ -192,9 +193,9 @@ does not).`, } var AppCmdListCommand = &cobra.Command{ - Use: "list [flags]", - Aliases: []string{"ls"}, - Short: "List all available commands", + Use: i18n.G("list [flags]"), + Aliases: []string{i18n.G("ls")}, + Short: i18n.G("List all available commands"), Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { app := internal.ValidateApp(args) @@ -244,33 +245,33 @@ var ( func init() { AppCmdCommand.Flags().BoolVarP( &local, - "local", - "l", + i18n.G("local"), + i18n.G("l"), false, - "run command locally", + i18n.G("run command locally"), ) AppCmdCommand.Flags().StringVarP( &remoteUser, - "user", - "u", + i18n.G("user"), + i18n.G("u"), "", - "request remote user", + i18n.G("request remote user"), ) AppCmdCommand.Flags().BoolVarP( &disableTTY, - "tty", - "T", + i18n.G("tty"), + i18n.G("T"), false, - "disable remote TTY", + i18n.G("disable remote TTY"), ) AppCmdCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) } diff --git a/cli/app/config.go b/cli/app/config.go index 163f1afc..23028973 100644 --- a/cli/app/config.go +++ b/cli/app/config.go @@ -6,16 +6,17 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/autocomplete" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/AlecAivazis/survey/v2" "github.com/spf13/cobra" ) var AppConfigCommand = &cobra.Command{ - Use: "config [flags]", - Aliases: []string{"cfg"}, - Short: "Edit app config", - Example: " abra config 1312.net", + Use: i18n.G("config [flags]"), + Aliases: []string{i18n.G("cfg")}, + Short: i18n.G("Edit app config"), + Example: i18n.G(" abra config 1312.net"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -32,13 +33,13 @@ var AppConfigCommand = &cobra.Command{ appName := args[0] appFile, exists := files[appName] if !exists { - log.Fatalf("cannot find app with name %s", appName) + log.Fatal(i18n.G("cannot find app with name %s", appName)) } ed, ok := os.LookupEnv("EDITOR") if !ok { edPrompt := &survey.Select{ - Message: "which editor do you wish to use?", + Message: i18n.G("which editor do you wish to use?"), Options: []string{"vi", "vim", "nvim", "nano", "pico", "emacs"}, } if err := survey.AskOne(edPrompt, &ed); err != nil { diff --git a/cli/app/cp.go b/cli/app/cp.go index 6d0b1130..e75a3f7a 100644 --- a/cli/app/cp.go +++ b/cli/app/cp.go @@ -3,7 +3,6 @@ package app import ( "context" "errors" - "fmt" "io" "os" "path" @@ -15,6 +14,7 @@ import ( "coopcloud.tech/abra/pkg/client" containerPkg "coopcloud.tech/abra/pkg/container" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/upstream/container" "github.com/docker/cli/cli/command" @@ -26,14 +26,14 @@ import ( ) var AppCpCommand = &cobra.Command{ - Use: "cp [flags]", - Aliases: []string{"c"}, - Short: "Copy files to/from a deployed app service", - Example: ` # copy myfile.txt to the root of the app service + Use: i18n.G("cp [flags]"), + Aliases: []string{i18n.G("c")}, + Short: i18n.G("Copy files to/from a deployed app service"), + Example: i18n.G(` # copy myfile.txt to the root of the app service abra app cp 1312.net myfile.txt app:/ # copy that file back to your current working directory locally - abra app cp 1312.net app:/myfile.txt ./`, + abra app cp 1312.net app:/myfile.txt ./`), Args: cobra.ExactArgs(3), ValidArgsFunction: func( cmd *cobra.Command, @@ -69,7 +69,7 @@ var AppCpCommand = &cobra.Command{ if err != nil { log.Fatal(err) } - log.Debugf("retrieved %s as target container on %s", formatter.ShortenID(container.ID), app.Server) + log.Debug(i18n.G("retrieved %s as target container on %s", formatter.ShortenID(container.ID), app.Server)) if toContainer { err = CopyToContainer(cl, container.ID, srcPath, dstPath) @@ -82,7 +82,7 @@ var AppCpCommand = &cobra.Command{ }, } -var errServiceMissing = errors.New("one of / arguments must take $SERVICE:$PATH form") +var errServiceMissing = errors.New(i18n.G("one of / arguments must take $SERVICE:$PATH form")) // parseSrcAndDst parses src and dest string. One of src or dst must be of the form $SERVICE:$PATH func parseSrcAndDst(src, dst string) (srcPath string, dstPath string, service string, toContainer bool, err error) { @@ -105,7 +105,7 @@ func parseSrcAndDst(src, dst string) (srcPath string, dstPath string, service st func CopyToContainer(cl *dockerClient.Client, containerID, srcPath, dstPath string) error { srcStat, err := os.Stat(srcPath) if err != nil { - return fmt.Errorf("local %s ", err) + return errors.New(i18n.G("local %s ", err)) } dstStat, err := cl.ContainerStatPath(context.Background(), containerID, dstPath) @@ -114,7 +114,7 @@ func CopyToContainer(cl *dockerClient.Client, containerID, srcPath, dstPath stri if errdefs.IsNotFound(err) { dstExists = false } else { - return fmt.Errorf("remote path: %s", err) + return errors.New(i18n.G("remote path: %s", err)) } } @@ -142,7 +142,7 @@ func CopyToContainer(cl *dockerClient.Client, containerID, srcPath, dstPath stri Detach: false, Tty: true, }); err != nil { - return fmt.Errorf("create remote directory: %s", err) + return errors.New(i18n.G("create remote directory: %s", err)) } case CopyModeFileToFile: // Remove the file component from the path, since docker can only copy @@ -161,7 +161,7 @@ func CopyToContainer(cl *dockerClient.Client, containerID, srcPath, dstPath stri return err } - log.Debugf("copy %s from local to %s on container", srcPath, dstPath) + log.Debug(i18n.G("copy %s from local to %s on container", srcPath, dstPath)) copyOpts := containertypes.CopyToContainerOptions{AllowOverwriteDirWithFile: false, CopyUIDGID: false} if err := cl.CopyToContainer(context.Background(), containerID, dstPath, content, copyOpts); err != nil { return err @@ -181,7 +181,7 @@ func CopyToContainer(cl *dockerClient.Client, containerID, srcPath, dstPath stri Detach: false, Tty: true, }); err != nil { - return fmt.Errorf("create remote directory: %s", err) + return errors.New(i18n.G("create remote directory: %s", err)) } } @@ -194,9 +194,9 @@ func CopyFromContainer(cl *dockerClient.Client, containerID, srcPath, dstPath st srcStat, err := cl.ContainerStatPath(context.Background(), containerID, srcPath) if err != nil { if errdefs.IsNotFound(err) { - return fmt.Errorf("remote: %s does not exist", srcPath) + return errors.New(i18n.G("remote: %s does not exist", srcPath)) } else { - return fmt.Errorf("remote path: %s", err) + return errors.New(i18n.G("remote path: %s", err)) } } @@ -207,7 +207,7 @@ func CopyFromContainer(cl *dockerClient.Client, containerID, srcPath, dstPath st if os.IsNotExist(err) { dstExists = false } else { - return fmt.Errorf("remote path: %s", err) + return errors.New(i18n.G("remote path: %s", err)) } } else { dstMode = dstStat.Mode() @@ -242,7 +242,7 @@ func CopyFromContainer(cl *dockerClient.Client, containerID, srcPath, dstPath st content, _, err := cl.CopyFromContainer(context.Background(), containerID, srcPath) if err != nil { - return fmt.Errorf("copy: %s", err) + return errors.New(i18n.G("copy: %s", err)) } defer content.Close() if err := archive.Untar(content, dstPath, &archive.TarOptions{ @@ -250,7 +250,7 @@ func CopyFromContainer(cl *dockerClient.Client, containerID, srcPath, dstPath st Compression: archive.Gzip, NoLchown: true, }); err != nil { - return fmt.Errorf("untar: %s", err) + return errors.New(i18n.G("untar: %s", err)) } if moveDstFile != "" { @@ -269,8 +269,8 @@ func CopyFromContainer(cl *dockerClient.Client, containerID, srcPath, dstPath st } var ( - ErrCopyDirToFile = fmt.Errorf("can't copy dir to file") - ErrDstDirNotExist = fmt.Errorf("destination directory does not exist") + ErrCopyDirToFile = errors.New(i18n.G("can't copy dir to file")) + ErrDstDirNotExist = errors.New(i18n.G("destination directory does not exist")) ) type CopyMode int @@ -375,9 +375,9 @@ func moveFile(sourcePath, destPath string) error { func init() { AppCpCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) } diff --git a/cli/app/deploy.go b/cli/app/deploy.go index 72e45a58..19cd8872 100644 --- a/cli/app/deploy.go +++ b/cli/app/deploy.go @@ -2,7 +2,7 @@ package app import ( "context" - "fmt" + "errors" "strings" "coopcloud.tech/abra/cli/internal" @@ -16,6 +16,7 @@ import ( "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/dns" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/lint" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/upstream/stack" @@ -24,15 +25,15 @@ import ( ) var AppDeployCommand = &cobra.Command{ - Use: "deploy [version] [flags]", - Aliases: []string{"d"}, - Short: "Deploy an app", - Long: `Deploy an app. + Use: i18n.G("deploy [version] [flags]"), + Aliases: []string{i18n.G("d")}, + Short: i18n.G("Deploy an app"), + Long: i18n.G(`Deploy an app. This command supports chaos operations. Use "--chaos/-C" to deploy your recipe checkout as-is. Recipe commit hashes are also supported as values for -"[version]". Please note, "upgrade"/"rollback" do not support chaos operations.`, - Example: ` # standard deployment +"[version]". Please note, "upgrade"/"rollback" do not support chaos operations.`), + Example: i18n.G(` # standard deployment abra app deploy 1312.net # chaos deployment @@ -42,7 +43,7 @@ checkout as-is. Recipe commit hashes are also supported as values for abra app deploy 1312.net 2.0.0+1.2.3 # deploy a specific git hash - abra app deploy 1312.net 886db76d`, + abra app deploy 1312.net 886db76d`), Args: cobra.RangeArgs(1, 2), ValidArgsFunction: func( cmd *cobra.Command, @@ -55,7 +56,7 @@ checkout as-is. Recipe commit hashes are also supported as values for case 1: app, err := appPkg.Get(args[0]) if err != nil { - errMsg := fmt.Sprintf("autocomplete failed: %s", err) + errMsg := i18n.G("autocomplete failed: %s", err) return []string{errMsg}, cobra.ShellCompDirectiveError } return autocomplete.RecipeVersionComplete(app.Recipe.Name) @@ -84,7 +85,7 @@ checkout as-is. Recipe commit hashes are also supported as values for log.Fatal(err) } - log.Debugf("checking whether %s is already deployed", app.StackName()) + log.Debug(i18n.G("checking whether %s is already deployed", app.StackName())) deployMeta, err := stack.IsDeployed(context.Background(), cl, app.StackName()) if err != nil { @@ -92,18 +93,18 @@ checkout as-is. Recipe commit hashes are also supported as values for } if deployMeta.IsDeployed && !(internal.Force || internal.Chaos) { - log.Fatalf("%s is already deployed", app.Name) + log.Fatal(i18n.G("%s is already deployed", app.Name)) } toDeployVersion, err = getDeployVersion(args, deployMeta, app) if err != nil { - log.Fatal(fmt.Errorf("get deploy version: %s", err)) + log.Fatal(i18n.G("get deploy version: %s", err)) } if !internal.Chaos { _, err = app.Recipe.EnsureVersion(toDeployVersion) if err != nil { - log.Fatalf("ensure recipe: %s", err) + log.Fatal(i18n.G("ensure recipe: %s", err)) } } @@ -162,7 +163,7 @@ checkout as-is. Recipe commit hashes are also supported as values for for _, envVar := range envVars { if !envVar.Present { deployWarnMessages = append(deployWarnMessages, - fmt.Sprintf("%s missing from %s.env", envVar.Name, app.Domain), + i18n.G("%s missing from %s.env", envVar.Name, app.Domain), ) } } @@ -173,10 +174,10 @@ checkout as-is. Recipe commit hashes are also supported as values for log.Fatal(err) } } else { - log.Debug("skipping domain checks, no DOMAIN=... configured") + log.Debug(i18n.G("skipping domain checks, no DOMAIN=... configured")) } } else { - log.Debug("skipping domain checks") + log.Debug(i18n.G("skipping domain checks")) } deployedVersion := config.NO_VERSION_DEFAULT @@ -199,7 +200,7 @@ checkout as-is. Recipe commit hashes are also supported as values for log.Fatal(err) } - log.Debugf("set waiting timeout to %d second(s)", stack.WaitTimeout) + log.Debug(i18n.G("set waiting timeout to %d second(s)", stack.WaitTimeout)) serviceNames, err := appPkg.GetAppServiceNames(app.Name) if err != nil { @@ -225,14 +226,14 @@ checkout as-is. Recipe commit hashes are also supported as values for postDeployCmds, ok := app.Env["POST_DEPLOY_CMDS"] if ok && !internal.DontWaitConverge { - log.Debugf("run the following post-deploy commands: %s", postDeployCmds) + log.Debug(i18n.G("run the following post-deploy commands: %s", postDeployCmds)) if err := internal.PostCmds(cl, app, postDeployCmds); err != nil { - log.Fatalf("attempting to run post deploy commands, saw: %s", err) + log.Fatal(i18n.G("attempting to run post deploy commands, saw: %s", err)) } } if err := app.WriteRecipeVersion(toDeployVersion, false); err != nil { - log.Fatalf("writing recipe version failed: %s", err) + log.Fatal(i18n.G("writing recipe version failed: %s", err)) } }, } @@ -258,7 +259,7 @@ func getLatestVersionOrCommit(app app.App) (string, error) { // validateArgsAndFlags ensures compatible args/flags. func validateArgsAndFlags(args []string) error { if len(args) == 2 && args[1] != "" && internal.Chaos { - return fmt.Errorf("cannot use [version] and --chaos together") + return errors.New(i18n.G("cannot use [version] and --chaos together")) } return nil @@ -272,7 +273,7 @@ func validateSecrets(cl *dockerClient.Client, app app.App) error { for _, secStat := range secStats { if !secStat.CreatedOnRemote { - return fmt.Errorf("secret not generated: %s", secStat.LocalName) + return errors.New(i18n.G("secret not generated: %s", secStat.LocalName)) } } @@ -286,33 +287,33 @@ func getDeployVersion(cliArgs []string, deployMeta stack.DeployMeta, app app.App if err != nil { return "", err } - log.Debugf("version: taking chaos version: %s", v) + log.Debug(i18n.G("version: taking chaos version: %s", v)) return v, nil } // Check if the deploy version is set with a cli argument if len(cliArgs) == 2 && cliArgs[1] != "" { - log.Debugf("version: taking version from cli arg: %s", cliArgs[1]) + log.Debug(i18n.G("version: taking version from cli arg: %s", cliArgs[1])) return cliArgs[1], nil } // Check if the recipe has a version in the .env file if app.Recipe.EnvVersion != "" && !internal.IgnoreEnvVersion { if strings.HasSuffix(app.Recipe.EnvVersionRaw, "+U") { - return "", fmt.Errorf("version: can not redeploy chaos version %s", app.Recipe.EnvVersionRaw) + return "", errors.New(i18n.G("version: can not redeploy chaos version %s", app.Recipe.EnvVersionRaw)) } - log.Debugf("version: taking version from .env file: %s", app.Recipe.EnvVersion) + log.Debug(i18n.G("version: taking version from .env file: %s", app.Recipe.EnvVersion)) return app.Recipe.EnvVersion, nil } // Take deployed version if deployMeta.IsDeployed { - log.Debugf("version: taking deployed version: %s", deployMeta.Version) + log.Debug(i18n.G("version: taking deployed version: %s", deployMeta.Version)) return deployMeta.Version, nil } v, err := getLatestVersionOrCommit(app) - log.Debugf("version: taking new recipe version: %s", v) + log.Debug(i18n.G("version: taking new recipe version: %s", v)) if err != nil { return "", err } @@ -322,33 +323,33 @@ func getDeployVersion(cliArgs []string, deployMeta stack.DeployMeta, app app.App func init() { AppDeployCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) AppDeployCommand.Flags().BoolVarP( &internal.Force, - "force", - "f", + i18n.G("force"), + i18n.G("f"), false, - "perform action without further prompt", + i18n.G("perform action without further prompt"), ) AppDeployCommand.Flags().BoolVarP( &internal.NoDomainChecks, - "no-domain-checks", - "D", + i18n.G("no-domain-checks"), + i18n.G("D"), false, - "disable public DNS checks", + i18n.G("disable public DNS checks"), ) AppDeployCommand.Flags().BoolVarP( &internal.DontWaitConverge, - "no-converge-checks", - "c", + i18n.G("no-converge-checks"), + i18n.G("c"), false, - "disable converge logic checks", + i18n.G("disable converge logic checks"), ) } diff --git a/cli/app/env.go b/cli/app/env.go index 44f3e3fe..265885f1 100644 --- a/cli/app/env.go +++ b/cli/app/env.go @@ -7,14 +7,15 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "github.com/spf13/cobra" ) var AppEnvCommand = &cobra.Command{ - Use: "env [flags]", - Aliases: []string{"e"}, - Short: "Show app .env values", - Example: " abra app env 1312.net", + Use: i18n.G("env [flags]"), + Aliases: []string{i18n.G("e")}, + Short: i18n.G("Show app .env values"), + Example: i18n.G(" abra app env 1312.net"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -37,7 +38,7 @@ var AppEnvCommand = &cobra.Command{ rows = append(rows, []string{k, app.Env[k]}) } - overview := formatter.CreateOverview("ENV OVERVIEW", rows) + overview := formatter.CreateOverview(i18n.G("ENV OVERVIEW"), rows) fmt.Println(overview) }, } diff --git a/cli/app/labels.go b/cli/app/labels.go index 5201db61..43017377 100644 --- a/cli/app/labels.go +++ b/cli/app/labels.go @@ -9,6 +9,7 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/upstream/convert" composetypes "github.com/docker/cli/cli/compose/types" @@ -19,11 +20,11 @@ import ( ) var AppLabelsCommand = &cobra.Command{ - Use: "labels [flags]", - Aliases: []string{"lb"}, - Short: "Show deployment labels", - Long: "Both local recipe and live deployment labels are shown.", - Example: " abra app labels 1312.net", + Use: i18n.G("labels [flags]"), + Aliases: []string{i18n.G("lb")}, + Short: i18n.G("Show deployment labels"), + Long: i18n.G("Both local recipe and live deployment labels are shown."), + Example: i18n.G(" abra app labels 1312.net"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -49,7 +50,7 @@ var AppLabelsCommand = &cobra.Command{ } rows := [][]string{ - {"DEPLOYED LABELS", "---"}, + {i18n.G("DEPLOYED LABELS"), "---"}, } remoteLabelKeys := make([]string, 0, len(remoteLabels)) @@ -67,10 +68,10 @@ var AppLabelsCommand = &cobra.Command{ } if len(remoteLabelKeys) == 0 { - rows = append(rows, []string{"unknown"}) + rows = append(rows, []string{i18n.G("unknown")}) } - rows = append(rows, []string{"RECIPE LABELS", "---"}) + rows = append(rows, []string{i18n.G("RECIPE LABELS"), "---"}) config, err := app.Recipe.GetComposeConfig(app.Env) if err != nil { @@ -98,7 +99,7 @@ var AppLabelsCommand = &cobra.Command{ }) } - overview := formatter.CreateOverview("LABELS OVERVIEW", rows) + overview := formatter.CreateOverview(i18n.G("LABELS OVERVIEW"), rows) fmt.Println(overview) }, } @@ -131,9 +132,9 @@ func getLabels(cl *dockerClient.Client, stackName string) (map[string]string, er func init() { AppLabelsCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) } diff --git a/cli/app/list.go b/cli/app/list.go index 50e7ce5c..2451ed8b 100644 --- a/cli/app/list.go +++ b/cli/app/list.go @@ -11,6 +11,7 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/tagcmp" "github.com/spf13/cobra" @@ -39,20 +40,20 @@ type serverStatus struct { } var AppListCommand = &cobra.Command{ - Use: "list [flags]", - Aliases: []string{"ls"}, - Short: "List all managed apps", - Long: `Generate a report of all managed apps. + Use: i18n.G("list [flags]"), + Aliases: []string{i18n.G("ls")}, + Short: i18n.G("List all managed apps"), + Long: i18n.G(`Generate a report of all managed apps. -Use "--status/-S" flag to query all servers for the live deployment status.`, - Example: ` # list apps of all servers without live status +Use "--status/-S" flag to query all servers for the live deployment status.`), + Example: i18n.G(` # list apps of all servers without live status abra app ls # list apps of a specific server with live status abra app ls -s 1312.net -S # list apps of all servers which match a specific recipe - abra app ls -r gitea`, + abra app ls -r gitea`), Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { appFiles, err := appPkg.LoadAppFiles(listAppServer) @@ -107,11 +108,11 @@ Use "--status/-S" flag to query all servers for the live deployment status.`, totalAppsCount++ if status { - status := "unknown" - version := "unknown" - chaos := "unknown" - chaosVersion := "unknown" - autoUpdate := "unknown" + status := i18n.G("unknown") + version := i18n.G("unknown") + chaos := i18n.G("unknown") + chaosVersion := i18n.G("unknown") + autoUpdate := i18n.G("unknown") if statusMeta, ok := statuses[app.StackName()]; ok { if currentVersion, exists := statusMeta["version"]; exists { if currentVersion != "" { @@ -144,12 +145,12 @@ Use "--status/-S" flag to query all servers for the live deployment status.`, var newUpdates []string if version != "unknown" && chaos == "false" { if err := app.Recipe.EnsureExists(); err != nil { - log.Fatalf("unable to clone %s: %s", app.Name, err) + log.Fatal(i18n.G("unable to clone %s: %s", app.Name, err)) } updates, err := app.Recipe.Tags() if err != nil { - log.Fatalf("unable to retrieve tags for %s: %s", app.Name, err) + log.Fatal(i18n.G("unable to retrieve tags for %s: %s", app.Name, err)) } parsedVersion, err := tagcmp.Parse(version) @@ -171,9 +172,9 @@ Use "--status/-S" flag to query all servers for the live deployment status.`, if len(newUpdates) == 0 { if version == "unknown" { - appStats.Upgrade = "unknown" + appStats.Upgrade = i18n.G("unknown") } else { - appStats.Upgrade = "latest" + appStats.Upgrade = i18n.G("latest") stats.LatestCount++ } } else { @@ -212,14 +213,15 @@ Use "--status/-S" flag to query all servers for the live deployment status.`, serverStat := allStats[app.Server] - headers := []string{"RECIPE", "DOMAIN", "SERVER"} + headers := []string{i18n.G("RECIPE"), i18n.G("DOMAIN"), i18n.G("SERVER")} if status { headers = append(headers, []string{ - "STATUS", - "CHAOS", - "VERSION", - "UPGRADE", - "AUTOUPDATE"}..., + i18n.G("STATUS"), + i18n.G("CHAOS"), + i18n.G("VERSION"), + i18n.G("UPGRADE"), + i18n.G("AUTOUPDATE"), + }..., ) } @@ -283,22 +285,22 @@ var ( func init() { AppListCommand.Flags().BoolVarP( &status, - "status", - "S", + i18n.G("status"), + i18n.G("S"), false, - "show app deployment status", + i18n.G("show app deployment status"), ) AppListCommand.Flags().StringVarP( &recipeFilter, - "recipe", - "r", + i18n.G("recipe"), + i18n.G("r"), "", - "show apps of a specific recipe", + i18n.G("show apps of a specific recipe"), ) AppListCommand.RegisterFlagCompletionFunc( - "recipe", + i18n.G("recipe"), func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return autocomplete.RecipeNameComplete() }, @@ -306,22 +308,22 @@ func init() { AppListCommand.Flags().BoolVarP( &internal.MachineReadable, - "machine", - "m", + i18n.G("machine"), + i18n.G("m"), false, - "print machine-readable output", + i18n.G("print machine-readable output"), ) AppListCommand.Flags().StringVarP( &listAppServer, - "server", - "s", + i18n.G("server"), + i18n.G("s"), "", - "show apps of a specific server", + i18n.G("show apps of a specific server"), ) AppListCommand.RegisterFlagCompletionFunc( - "server", + i18n.G("server"), func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return autocomplete.ServerNameComplete() }, diff --git a/cli/app/logs.go b/cli/app/logs.go index 741bfd1b..6bc6b400 100644 --- a/cli/app/logs.go +++ b/cli/app/logs.go @@ -2,12 +2,12 @@ package app import ( "context" - "fmt" "coopcloud.tech/abra/cli/internal" appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/logs" "coopcloud.tech/abra/pkg/upstream/stack" @@ -15,9 +15,9 @@ import ( ) var AppLogsCommand = &cobra.Command{ - Use: "logs [service] [flags]", - Aliases: []string{"l"}, - Short: "Tail app logs", + Use: i18n.G("logs [service] [flags]"), + Aliases: []string{i18n.G("l")}, + Short: i18n.G("Tail app logs"), Args: cobra.RangeArgs(1, 2), ValidArgsFunction: func( cmd *cobra.Command, @@ -29,8 +29,7 @@ var AppLogsCommand = &cobra.Command{ case 1: app, err := appPkg.Get(args[0]) if err != nil { - errMsg := fmt.Sprintf("autocomplete failed: %s", err) - return []string{errMsg}, cobra.ShellCompDirectiveError + return []string{i18n.G("autocomplete failed: %s", err)}, cobra.ShellCompDirectiveError } return autocomplete.ServiceNameComplete(app.Name) default: @@ -56,7 +55,7 @@ var AppLogsCommand = &cobra.Command{ } if !deployMeta.IsDeployed { - log.Fatalf("%s is not deployed?", app.Name) + log.Fatal(i18n.G("%s is not deployed?", app.Name)) } var serviceNames []string @@ -91,17 +90,17 @@ var ( func init() { AppLogsCommand.Flags().BoolVarP( &stdErr, - "stderr", - "s", + i18n.G("stderr"), + i18n.G("s"), false, - "only tail stderr", + i18n.G("only tail stderr"), ) AppLogsCommand.Flags().StringVarP( &sinceLogs, - "since", - "S", + i18n.G("since"), + i18n.G("S"), "", - "tail logs since YYYY-MM-DDTHH:MM:SSZ", + i18n.G("tail logs since YYYY-MM-DDTHH:MM:SSZ"), ) } diff --git a/cli/app/new.go b/cli/app/new.go index e022beed..26738798 100644 --- a/cli/app/new.go +++ b/cli/app/new.go @@ -1,6 +1,7 @@ package app import ( + "errors" "fmt" "coopcloud.tech/abra/cli/internal" @@ -10,6 +11,7 @@ import ( "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" recipePkg "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/abra/pkg/secret" @@ -19,7 +21,7 @@ import ( "github.com/spf13/cobra" ) -var appNewDescription = `Creates a new app from a default recipe. +var appNewDescription = i18n.G(`Creates a new app from a default recipe. This new app configuration is stored in your $ABRA_DIR directory under the appropriate server. @@ -39,12 +41,12 @@ 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 = &cobra.Command{ - Use: "new [recipe] [version] [flags]", - Aliases: []string{"n"}, - Short: "Create a new app", + Use: i18n.G("new [recipe] [version] [flags]"), + Aliases: []string{i18n.G("n")}, + Short: i18n.G("Create a new app"), Long: appNewDescription, Args: cobra.RangeArgs(0, 2), ValidArgsFunction: func( @@ -65,7 +67,7 @@ var AppNewCommand = &cobra.Command{ recipe := internal.ValidateRecipe(args, cmd.Name()) if len(args) == 2 && internal.Chaos { - log.Fatal("cannot use [version] and --chaos together") + log.Fatal(i18n.G("cannot use [version] and --chaos together")) } var recipeVersion string @@ -113,7 +115,7 @@ var AppNewCommand = &cobra.Command{ if recipeVersion == "" { head, err := recipe.Head() if err != nil { - log.Fatalf("failed to retrieve latest commit for %s: %s", recipe.Name, err) + log.Fatal(i18n.G("failed to retrieve latest commit for %s: %s", recipe.Name, err)) } recipeVersion = formatter.SmallSHA(head.String()) @@ -130,7 +132,7 @@ var AppNewCommand = &cobra.Command{ } sanitisedAppName := appPkg.SanitiseAppName(appDomain) - log.Debugf("%s sanitised as %s for new app", appDomain, sanitisedAppName) + log.Debug(i18n.G("%s sanitised as %s for new app", appDomain, sanitisedAppName)) if err := appPkg.TemplateAppEnvSample( recipe, @@ -182,7 +184,7 @@ var AppNewCommand = &cobra.Command{ log.Fatal(err) } - headers := []string{"NAME", "VALUE"} + headers := []string{i18n.G("NAME"), i18n.G("VALUE")} secretsTable.Headers(headers...) for name, val := range appSecrets { @@ -194,7 +196,7 @@ var AppNewCommand = &cobra.Command{ newAppServer = "local" } - log.Infof("%s created (version: %s)", appDomain, recipeVersion) + log.Info(i18n.G("%s created (version: %s)", appDomain, recipeVersion)) if len(appSecrets) > 0 { rows := [][]string{} @@ -202,15 +204,15 @@ var AppNewCommand = &cobra.Command{ rows = append(rows, []string{k, v}) } - overview := formatter.CreateOverview("SECRETS OVERVIEW", rows) + overview := formatter.CreateOverview(i18n.G("SECRETS OVERVIEW"), rows) fmt.Println(overview) - log.Warnf( + log.Warn(i18n.G( "secrets are %s shown again, please save them %s", formatter.BoldUnderlineStyle.Render("NOT"), formatter.BoldUnderlineStyle.Render("NOW"), - ) + )) } app, err := app.Get(appDomain) @@ -219,7 +221,7 @@ var AppNewCommand = &cobra.Command{ } if err := app.WriteRecipeVersion(recipeVersion, false); err != nil { - log.Fatalf("writing recipe version failed: %s", err) + log.Fatal(i18n.G("writing recipe version failed: %s", err)) } }, } @@ -231,7 +233,7 @@ type AppSecrets map[string]string func createSecrets(cl *dockerClient.Client, secretsConfig map[string]secret.Secret, sanitisedAppName string) (AppSecrets, error) { // NOTE(d1): trim to match app.StackName() implementation if len(sanitisedAppName) > config.MAX_SANITISED_APP_NAME_LENGTH { - log.Debugf("trimming %s to %s to avoid runtime limits", sanitisedAppName, sanitisedAppName[:config.MAX_SANITISED_APP_NAME_LENGTH]) + log.Debug(i18n.G("trimming %s to %s to avoid runtime limits", sanitisedAppName, sanitisedAppName[:config.MAX_SANITISED_APP_NAME_LENGTH])) sanitisedAppName = sanitisedAppName[:config.MAX_SANITISED_APP_NAME_LENGTH] } @@ -261,7 +263,7 @@ func createSecrets(cl *dockerClient.Client, secretsConfig map[string]secret.Secr func ensureDomainFlag(recipe recipePkg.Recipe, server string) error { if appDomain == "" && !internal.NoInput { prompt := &survey.Input{ - Message: "Specify app domain", + Message: i18n.G("Specify app domain"), Default: fmt.Sprintf("%s.%s", recipe.Name, server), } if err := survey.AskOne(prompt, &appDomain); err != nil { @@ -270,7 +272,7 @@ func ensureDomainFlag(recipe recipePkg.Recipe, server string) error { } if appDomain == "" { - return fmt.Errorf("no domain provided") + return fmt.Errorf(i18n.G("no domain provided")) } return nil @@ -279,13 +281,13 @@ func ensureDomainFlag(recipe recipePkg.Recipe, server string) error { // promptForSecrets asks if we should generate secrets for a new app. func promptForSecrets(recipeName string, secretsConfig map[string]secret.Secret) error { if len(secretsConfig) == 0 { - log.Debugf("%s has no secrets to generate, skipping...", recipeName) + log.Debug(i18n.G("%s has no secrets to generate, skipping...", recipeName)) return nil } if !generateSecrets && !internal.NoInput { prompt := &survey.Confirm{ - Message: "Generate app secrets?", + Message: i18n.G("Generate app secrets?"), } if err := survey.AskOne(prompt, &generateSecrets); err != nil { return err @@ -304,13 +306,13 @@ func ensureServerFlag() error { if len(servers) == 1 { newAppServer = servers[0] - log.Infof("single server detected, choosing %s automatically", newAppServer) + log.Info(i18n.G("single server detected, choosing %s automatically", newAppServer)) return nil } if newAppServer == "" && !internal.NoInput { prompt := &survey.Select{ - Message: "Select app server:", + Message: i18n.G("Select app server:"), Options: servers, } if err := survey.AskOne(prompt, &newAppServer); err != nil { @@ -319,7 +321,7 @@ func ensureServerFlag() error { } if newAppServer == "" { - return fmt.Errorf("no server provided") + return errors.New(i18n.G("no server provided")) } return nil @@ -335,14 +337,14 @@ var ( func init() { AppNewCommand.Flags().StringVarP( &newAppServer, - "server", - "s", + i18n.G("server"), + i18n.G("s"), "", - "specify server for new app", + i18n.G("specify server for new app"), ) AppNewCommand.RegisterFlagCompletionFunc( - "server", + i18n.G("server"), func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return autocomplete.ServerNameComplete() }, @@ -350,34 +352,34 @@ func init() { AppNewCommand.Flags().StringVarP( &appDomain, - "domain", - "D", + i18n.G("domain"), + i18n.G("D"), "", - "domain name for app", + i18n.G("domain name for app"), ) AppNewCommand.Flags().BoolVarP( &saveInPass, - "pass", - "p", + i18n.G("pass"), + i18n.G("p"), false, - "store secrets in a local pass store", + i18n.G("store secrets in a local pass store"), ) AppNewCommand.Flags().BoolVarP( &generateSecrets, - "secrets", - "S", + i18n.G("secrets"), + i18n.G("S"), false, - "automatically generate secrets", + i18n.G("automatically generate secrets"), ) AppNewCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) } diff --git a/cli/app/ps.go b/cli/app/ps.go index 029e0d06..1c6540c3 100644 --- a/cli/app/ps.go +++ b/cli/app/ps.go @@ -13,6 +13,7 @@ import ( "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" abraService "coopcloud.tech/abra/pkg/service" stack "coopcloud.tech/abra/pkg/upstream/stack" @@ -24,9 +25,9 @@ import ( ) var AppPsCommand = &cobra.Command{ - Use: "ps [flags]", - Aliases: []string{"p"}, - Short: "Check app deployment status", + Use: i18n.G("ps [flags]"), + Aliases: []string{i18n.G("p")}, + Short: i18n.G("Check app deployment status"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -52,7 +53,7 @@ var AppPsCommand = &cobra.Command{ } if !deployMeta.IsDeployed { - log.Fatalf("%s is not deployed?", app.Name) + log.Fatal(i18n.G("%s is not deployed?", app.Name)) } chaosVersion := config.CHAOS_DEFAULT @@ -115,11 +116,11 @@ func showPSOutput(app appPkg.App, cl *dockerClient.Client, deployedVersion, chao "version": deployedVersion, "chaos": chaosVersion, "service": service.Name, - "image": "unknown", - "created": "unknown", - "status": "unknown", - "state": "unknown", - "ports": "unknown", + "image": i18n.G("unknown"), + "created": i18n.G("unknown"), + "status": i18n.G("unknown"), + "state": i18n.G("unknown"), + "ports": i18n.G("unknown"), } } else { container := containers[0] @@ -161,7 +162,7 @@ func showPSOutput(app appPkg.App, cl *dockerClient.Client, deployedVersion, chao if internal.MachineReadable { rendered, err := json.Marshal(allContainerStats) if err != nil { - log.Fatal("unable to convert to JSON: %s", err) + log.Fatal(i18n.G("unable to convert to JSON: %s", err)) } fmt.Println(string(rendered)) @@ -175,11 +176,11 @@ func showPSOutput(app appPkg.App, cl *dockerClient.Client, deployedVersion, chao } headers := []string{ - "SERVICE", - "STATUS", - "IMAGE", - "VERSION", - "CHAOS", + i18n.G("SERVICE"), + i18n.G("STATUS"), + i18n.G("IMAGE"), + i18n.G("VERSION"), + i18n.G("CHAOS"), } table. @@ -194,17 +195,17 @@ func showPSOutput(app appPkg.App, cl *dockerClient.Client, deployedVersion, chao func init() { AppPsCommand.Flags().BoolVarP( &internal.MachineReadable, - "machine", - "m", + i18n.G("machine"), + i18n.G("m"), false, - "print machine-readable output", + i18n.G("print machine-readable output"), ) AppPsCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) } diff --git a/cli/app/remove.go b/cli/app/remove.go index f65f8638..6d5695ec 100644 --- a/cli/app/remove.go +++ b/cli/app/remove.go @@ -2,12 +2,12 @@ package app import ( "context" - "fmt" "os" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/upstream/stack" "github.com/AlecAivazis/survey/v2" @@ -16,10 +16,10 @@ import ( ) var AppRemoveCommand = &cobra.Command{ - Use: "remove [flags]", - Aliases: []string{"rm"}, - Short: "Remove all app data, locally and remotely", - Long: `Remove everything related to an app which is already undeployed. + Use: i18n.G("remove [flags]"), + Aliases: []string{i18n.G("rm")}, + Short: i18n.G("Remove all app data, locally and remotely"), + Long: i18n.G(`Remove everything related to an app which is already undeployed. By default, it will prompt for confirmation before proceeding. All secrets, volumes and the local app env file will be deleted. @@ -34,8 +34,8 @@ 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.`, - Example: " abra app remove 1312.net", +flag.`), + Example: i18n.G(" abra app remove 1312.net"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -47,16 +47,16 @@ flag.`, app := internal.ValidateApp(args) if !internal.Force && !internal.NoInput { - log.Warnf("ALERTA ALERTA: deleting %s data and config (local/remote)", app.Name) + log.Warn(i18n.G("ALERTA ALERTA: deleting %s data and config (local/remote)", app.Name)) response := false - prompt := &survey.Confirm{Message: "are you sure?"} + prompt := &survey.Confirm{Message: i18n.G("are you sure?")} if err := survey.AskOne(prompt, &response); err != nil { log.Fatal(err) } if !response { - log.Fatal("aborting as requested") + log.Fatal(i18n.G("aborting as requested")) } } @@ -70,7 +70,7 @@ flag.`, log.Fatal(err) } if deployMeta.IsDeployed { - log.Fatalf("%s is still deployed. Run \"abra app undeploy %s\"", app.Name, app.Name) + log.Fatal(i18n.G("%s is still deployed. Run \"abra app undeploy %s\"", app.Name, app.Name)) } fs, err := app.Filters(false, false) @@ -86,12 +86,12 @@ flag.`, if len(configNames) > 0 { if err := client.RemoveConfigs(cl, context.Background(), configNames, internal.Force); err != nil { - log.Fatalf("removing configs failed: %s", err) + log.Fatal(i18n.G("removing configs failed: %s", err)) } - log.Infof("%d config(s) removed successfully", len(configNames)) + log.Info(i18n.G("%d config(s) removed successfully", len(configNames))) } else { - log.Info("no configs to remove") + log.Info(i18n.G("no configs to remove")) } secretList, err := cl.SecretList(context.Background(), types.SecretListOptions{Filters: fs}) @@ -113,10 +113,10 @@ flag.`, if err != nil { log.Fatal(err) } - log.Info(fmt.Sprintf("secret: %s removed", name)) + log.Info(i18n.G("secret: %s removed", name)) } } else { - log.Info("no secrets to remove") + log.Info(i18n.G("no secrets to remove")) } fs, err = app.Filters(false, true) @@ -133,28 +133,28 @@ flag.`, if len(volumeNames) > 0 { err := client.RemoveVolumes(cl, context.Background(), volumeNames, internal.Force, 5) if err != nil { - log.Fatalf("removing volumes failed: %s", err) + log.Fatal(i18n.G("removing volumes failed: %s", err)) } - log.Infof("%d volume(s) removed successfully", len(volumeNames)) + log.Info(i18n.G("%d volume(s) removed successfully", len(volumeNames))) } else { - log.Info("no volumes to remove") + log.Info(i18n.G("no volumes to remove")) } if err = os.Remove(app.Path); err != nil { log.Fatal(err) } - log.Info(fmt.Sprintf("file: %s removed", app.Path)) + log.Info(i18n.G("file: %s removed", app.Path)) }, } func init() { AppRemoveCommand.Flags().BoolVarP( &internal.Force, - "force", - "f", + i18n.G("force"), + i18n.G("f"), false, - "perform action without further prompt", + i18n.G("perform action without further prompt"), ) } diff --git a/cli/app/restart.go b/cli/app/restart.go index 860c77e4..bb838492 100644 --- a/cli/app/restart.go +++ b/cli/app/restart.go @@ -8,6 +8,7 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/ui" upstream "coopcloud.tech/abra/pkg/upstream/service" @@ -17,19 +18,19 @@ import ( ) var AppRestartCommand = &cobra.Command{ - Use: "restart [[service] | --all-services] [flags]", - Aliases: []string{"re"}, - Short: "Restart an app", - Long: `This command restarts services within a deployed app. + Use: i18n.G("restart [[service] | --all-services] [flags]"), + Aliases: []string{i18n.G("re")}, + Short: i18n.G("Restart an app"), + Long: i18n.G(`This command restarts services within a deployed app. Run "abra app ps " to see a list of service names. -Pass "--all-services/-a" to restart all services.`, - Example: ` # restart a single app service +Pass "--all-services/-a" to restart all services.`), + Example: i18n.G(` # restart a single app service abra app restart 1312.net app # restart all app services - abra app restart 1312.net -a`, + abra app restart 1312.net -a`), Args: cobra.RangeArgs(1, 2), ValidArgsFunction: func( cmd *cobra.Command, @@ -60,11 +61,11 @@ Pass "--all-services/-a" to restart all services.`, } if serviceName == "" && !allServices { - log.Fatal("missing [service]") + log.Fatal(i18n.G("missing [service]")) } if serviceName != "" && allServices { - log.Fatal("cannot use [service] and --all-services/-a together") + log.Fatal(i18n.G("cannot use [service] and --all-services/-a together")) } var serviceNames []string @@ -89,7 +90,7 @@ Pass "--all-services/-a" to restart all services.`, } if !deployMeta.IsDeployed { - log.Fatalf("%s is not deployed?", app.Name) + log.Fatal(i18n.G("%s is not deployed?", app.Name)) } for _, serviceName := range serviceNames { @@ -104,7 +105,7 @@ Pass "--all-services/-a" to restart all services.`, log.Fatal(err) } - log.Debugf("attempting to scale %s to 0", stackServiceName) + log.Debug(i18n.G("attempting to scale %s to 0", stackServiceName)) if err := upstream.RunServiceScale(context.Background(), cl, stackServiceName, 0); err != nil { log.Fatal(err) @@ -128,8 +129,8 @@ Pass "--all-services/-a" to restart all services.`, log.Fatal(err) } - log.Debugf("%s has been scaled to 0", stackServiceName) - log.Debugf("attempting to scale %s to 1", stackServiceName) + log.Debug(i18n.G("%s has been scaled to 0", stackServiceName)) + log.Debug(i18n.G("attempting to scale %s to 1", stackServiceName)) if err := upstream.RunServiceScale(context.Background(), cl, stackServiceName, 1); err != nil { log.Fatal(err) @@ -139,8 +140,8 @@ Pass "--all-services/-a" to restart all services.`, log.Fatal(err) } - log.Debugf("%s has been scaled to 1", stackServiceName) - log.Infof("%s service successfully restarted", serviceName) + log.Debug(i18n.G("%s has been scaled to 1", stackServiceName)) + log.Info(i18n.G("%s service successfully restarted", serviceName)) } }, } @@ -150,16 +151,16 @@ var allServices bool func init() { AppRestartCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) AppRestartCommand.Flags().BoolVarP( &allServices, - "all-services", - "a", + i18n.G("all-services"), + i18n.G("a"), false, - "restart all services", + i18n.G("restart all services"), ) } diff --git a/cli/app/restore.go b/cli/app/restore.go index 21b1dcc0..a51d9d21 100644 --- a/cli/app/restore.go +++ b/cli/app/restore.go @@ -7,17 +7,18 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/spf13/cobra" ) var AppRestoreCommand = &cobra.Command{ - Use: "restore [flags]", - Aliases: []string{"rs"}, - Short: "Restore a snapshot", - Long: `Snapshots are restored while apps are deployed. + Use: i18n.G("restore [flags]"), + Aliases: []string{i18n.G("rs")}, + Short: i18n.G("Restore a snapshot"), + Long: i18n.G(`Snapshots are restored while apps are deployed. -Some restore scenarios may require service / app restarts.`, +Some restore scenarios may require service / app restarts.`), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -48,34 +49,34 @@ Some restore scenarios may require service / app restarts.`, } if snapshot != "" { - log.Debugf("including SNAPSHOT=%s in backupbot exec invocation", snapshot) + log.Debug(i18n.G("including SNAPSHOT=%s in backupbot exec invocation", snapshot)) execEnv = append(execEnv, fmt.Sprintf("SNAPSHOT=%s", snapshot)) } if targetPath != "" { - log.Debugf("including TARGET=%s in backupbot exec invocation", targetPath) + log.Debug(i18n.G("including TARGET=%s in backupbot exec invocation", targetPath)) execEnv = append(execEnv, fmt.Sprintf("TARGET=%s", targetPath)) } if internal.NoInput { - log.Debugf("including NONINTERACTIVE=%v in backupbot exec invocation", internal.NoInput) + log.Debug(i18n.G("including NONINTERACTIVE=%v in backupbot exec invocation", internal.NoInput)) execEnv = append(execEnv, fmt.Sprintf("NONINTERACTIVE=%v", internal.NoInput)) } if len(volumes) > 0 { allVolumes := strings.Join(volumes, ",") - log.Debugf("including VOLUMES=%s in backupbot exec invocation", allVolumes) + log.Debug(i18n.G("including VOLUMES=%s in backupbot exec invocation", allVolumes)) execEnv = append(execEnv, fmt.Sprintf("VOLUMES=%s", allVolumes)) } if len(services) > 0 { allServices := strings.Join(services, ",") - log.Debugf("including CONTAINER=%s in backupbot exec invocation", allServices) + log.Debug(i18n.G("including CONTAINER=%s in backupbot exec invocation", allServices)) execEnv = append(execEnv, fmt.Sprintf("CONTAINER=%s", allServices)) } if hooks { - log.Debugf("including NO_COMMANDS=%v in backupbot exec invocation", false) + log.Debug(i18n.G("including NO_COMMANDS=%v in backupbot exec invocation", false)) execEnv = append(execEnv, fmt.Sprintf("NO_COMMANDS=%v", false)) } @@ -95,41 +96,41 @@ var ( func init() { AppRestoreCommand.Flags().StringVarP( &targetPath, - "target", - "t", + i18n.G("target"), + i18n.G("t"), "/", - "target path", + i18n.G("target path"), ) AppRestoreCommand.Flags().StringArrayVarP( &services, - "services", - "s", + i18n.G("services"), + i18n.G("s"), []string{}, - "restore specific services", + i18n.G("restore specific services"), ) AppRestoreCommand.Flags().StringArrayVarP( &volumes, - "volumes", - "v", + i18n.G("volumes"), + i18n.G("v"), []string{}, - "restore specific volumes", + i18n.G("restore specific volumes"), ) AppRestoreCommand.Flags().BoolVarP( &hooks, - "hooks", - "H", + i18n.G("hooks"), + i18n.G("H"), false, - "enable pre/post-hook command execution", + i18n.G("enable pre/post-hook command execution"), ) AppRestoreCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) } diff --git a/cli/app/rollback.go b/cli/app/rollback.go index 7bdebf94..0218dd0a 100644 --- a/cli/app/rollback.go +++ b/cli/app/rollback.go @@ -1,7 +1,7 @@ package app import ( - "fmt" + "errors" "coopcloud.tech/abra/pkg/app" appPkg "coopcloud.tech/abra/pkg/app" @@ -9,6 +9,7 @@ import ( "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/lint" stack "coopcloud.tech/abra/pkg/upstream/stack" "coopcloud.tech/tagcmp" @@ -21,10 +22,10 @@ import ( ) var AppRollbackCommand = &cobra.Command{ - Use: "rollback [version] [flags]", - Aliases: []string{"rl"}, - Short: "Roll an app back to a previous version", - Long: `This command rolls an app back to a previous version. + Use: i18n.G("rollback [version] [flags]"), + Aliases: []string{i18n.G("rl")}, + Short: i18n.G("Roll an app back to a previous version"), + Long: i18n.G(`This command rolls an app back to a previous version. Unlike "abra app deploy", chaos operations are not supported here. Only recipe versions are supported values for "[version]". @@ -37,12 +38,12 @@ are available. The live deployment version is the "source of truth" in this case. The stored .env version is not consulted. A downgrade can be destructive, please ensure you have a copy of your app data -beforehand. See "abra app backup" for more.`, - Example: ` # standard rollback +beforehand. See "abra app backup" for more.`), + Example: i18n.G(` # standard rollback abra app rollback 1312.net # rollback to specific version - abra app rollback 1312.net 2.0.0+1.2.3`, + abra app rollback 1312.net 2.0.0+1.2.3`), Args: cobra.RangeArgs(1, 2), ValidArgsFunction: func( cmd *cobra.Command, @@ -54,8 +55,7 @@ beforehand. See "abra app backup" for more.`, case 1: app, err := appPkg.Get(args[0]) if err != nil { - errMsg := fmt.Sprintf("autocomplete failed: %s", err) - return []string{errMsg}, cobra.ShellCompDirectiveError + return []string{i18n.G("autocomplete failed: %s", err)}, cobra.ShellCompDirectiveError } return autocomplete.RecipeVersionComplete(app.Recipe.Name) default: @@ -117,7 +117,7 @@ beforehand. See "abra app backup" for more.`, } if !downgradeAvailable { - log.Info("no available downgrades") + log.Info(i18n.G("no available downgrades")) return } } @@ -139,10 +139,10 @@ beforehand. See "abra app backup" for more.`, } if chosenDowngrade == "" { - log.Fatal("unknown deployed version, unable to downgrade") + log.Fatal(i18n.G("unknown deployed version, unable to downgrade")) } - log.Debugf("choosing %s as version to rollback", chosenDowngrade) + log.Debug(i18n.G("choosing %s as version to rollback", chosenDowngrade)) if _, err := app.Recipe.EnsureVersion(chosenDowngrade); err != nil { log.Fatal(err) @@ -199,7 +199,7 @@ beforehand. See "abra app backup" for more.`, log.Fatal(err) } - log.Debugf("set waiting timeout to %d second(s)", stack.WaitTimeout) + log.Debug(i18n.G("set waiting timeout to %d second(s)", stack.WaitTimeout)) serviceNames, err := appPkg.GetAppServiceNames(app.Name) if err != nil { @@ -224,7 +224,7 @@ beforehand. See "abra app backup" for more.`, } if err := app.WriteRecipeVersion(chosenDowngrade, false); err != nil { - log.Fatalf("writing recipe version failed: %s", err) + log.Fatal(i18n.G("writing recipe version failed: %s", err)) } }, } @@ -235,12 +235,12 @@ func chooseDowngrade( deployMeta stack.DeployMeta, chosenDowngrade *string, ) error { - msg := fmt.Sprintf("please select a downgrade (version: %s):", deployMeta.Version) + msg := i18n.G("please select a downgrade (version: %s):", deployMeta.Version) if deployMeta.IsChaos { chaosVersion := formatter.BoldDirtyDefault(deployMeta.ChaosVersion) - msg = fmt.Sprintf( + msg = i18n.G( "please select a downgrade (version: %s, chaos: %s):", deployMeta.Version, chaosVersion, @@ -267,21 +267,21 @@ func validateDowngradeVersionArg( ) error { parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version) if err != nil { - return fmt.Errorf("current deployment '%s' is not a known version for %s", deployMeta.Version, app.Recipe.Name) + return errors.New(i18n.G("current deployment '%s' is not a known version for %s", deployMeta.Version, app.Recipe.Name)) } parsedSpecificVersion, err := tagcmp.Parse(specificVersion) if err != nil { - return fmt.Errorf("'%s' is not a known version for %s", specificVersion, app.Recipe.Name) + return errors.New(i18n.G("'%s' is not a known version for %s", specificVersion, app.Recipe.Name)) } if parsedSpecificVersion.IsGreaterThan(parsedDeployedVersion) && !parsedSpecificVersion.Equals(parsedDeployedVersion) { - return fmt.Errorf("%s is not a downgrade for %s?", deployMeta.Version, specificVersion) + return errors.New(i18n.G("%s is not a downgrade for %s?", deployMeta.Version, specificVersion)) } if parsedSpecificVersion.Equals(parsedDeployedVersion) && !internal.Force { - return fmt.Errorf("%s is not a downgrade for %s?", deployMeta.Version, specificVersion) + return errors.New(i18n.G("%s is not a downgrade for %s?", deployMeta.Version, specificVersion)) } return nil @@ -320,24 +320,25 @@ func ensureDowngradesAvailable( func init() { AppRollbackCommand.Flags().BoolVarP( &internal.Force, - "force", - "f", + i18n.G("force"), + i18n.G("f"), false, - "perform action without further prompt", + i18n.G("perform action without further prompt"), ) AppRollbackCommand.Flags().BoolVarP( &internal.NoDomainChecks, - "no-domain-checks", - "D", + i18n.G("no-domain-checks"), + i18n.G("D"), false, - "disable public DNS checks", + i18n.G("disable public DNS checks"), ) AppRollbackCommand.Flags().BoolVarP( - &internal.DontWaitConverge, "no-converge-checks", - "c", + &internal.DontWaitConverge, + i18n.G("no-converge-checks"), + i18n.G("c"), false, - "disable converge logic checks", + i18n.G("disable converge logic checks"), ) } diff --git a/cli/app/run.go b/cli/app/run.go index 21c0f1ea..a0f4a1a9 100644 --- a/cli/app/run.go +++ b/cli/app/run.go @@ -8,6 +8,7 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" containerPkg "coopcloud.tech/abra/pkg/container" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/upstream/container" "github.com/docker/cli/cli/command" @@ -17,17 +18,17 @@ import ( ) var AppRunCommand = &cobra.Command{ - Use: "run [[args] [flags] | [flags] -- [args]]", - Aliases: []string{"r"}, - Short: "Run a command inside a service container", - Example: ` # run with args/flags + Use: i18n.G("run [[args] [flags] | [flags] -- [args]]"), + Aliases: []string{i18n.G("r")}, + Short: i18n.G("Run a command inside a service container"), + Example: i18n.G(` # run with args/flags abra app run 1312.net app -- ls -lha # run without args/flags abra app run 1312.net app bash --user nobody # run with both kinds of args/flags - abra app run 1312.net app --user nobody -- ls -lha`, + abra app run 1312.net app --user nobody -- ls -lha`), Args: cobra.MinimumNArgs(3), ValidArgsFunction: func( cmd *cobra.Command, @@ -98,17 +99,17 @@ var ( func init() { AppRunCommand.Flags().BoolVarP(&noTTY, - "no-tty", - "t", + i18n.G("no-tty"), + i18n.G("t"), false, - "do not request a TTY", + i18n.G("do not request a TTY"), ) AppRunCommand.Flags().StringVarP( &runAsUser, - "user", - "u", + i18n.G("user"), + i18n.G("u"), "", - "run command as user", + i18n.G("run command as user"), ) } diff --git a/cli/app/secret.go b/cli/app/secret.go index 6b5da2a2..550714b2 100644 --- a/cli/app/secret.go +++ b/cli/app/secret.go @@ -12,6 +12,7 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/secret" "github.com/docker/docker/api/types" @@ -20,9 +21,9 @@ import ( ) var AppSecretGenerateCommand = &cobra.Command{ - Use: "generate [[secret] [version] | --all] [flags]", - Aliases: []string{"g"}, - Short: "Generate secrets", + Use: i18n.G("generate [[secret] [version] | --all] [flags]"), + Aliases: []string{i18n.G("g")}, + Short: i18n.G("Generate secrets"), Args: cobra.RangeArgs(1, 3), ValidArgsFunction: func( cmd *cobra.Command, @@ -34,8 +35,7 @@ var AppSecretGenerateCommand = &cobra.Command{ case 1: app, err := appPkg.Get(args[0]) if err != nil { - errMsg := fmt.Sprintf("autocomplete failed: %s", err) - return []string{errMsg}, cobra.ShellCompDirectiveError + return []string{i18n.G("autocomplete failed: %s", err)}, cobra.ShellCompDirectiveError } return autocomplete.SecretComplete(app.Recipe.Name) default: @@ -50,11 +50,11 @@ var AppSecretGenerateCommand = &cobra.Command{ } if len(args) <= 2 && !generateAllSecrets { - log.Fatal("missing arguments [secret]/[version] or '--all'") + log.Fatal(i18n.G("missing arguments [secret]/[version] or '--all'")) } if len(args) > 2 && generateAllSecrets { - log.Fatal("cannot use '[secret] [version]' and '--all' together") + log.Fatal(i18n.G("cannot use '[secret] [version]' and '--all' together")) } composeFiles, err := app.Recipe.GetComposeFiles(app.Env) @@ -72,7 +72,7 @@ var AppSecretGenerateCommand = &cobra.Command{ secretVersion := args[2] s, ok := secrets[secretName] if !ok { - log.Fatalf("%s doesn't exist in the env config?", secretName) + log.Fatal(i18n.G("%s doesn't exist in the env config?", secretName)) } s.Version = secretVersion secrets = map[string]secret.Secret{ @@ -99,11 +99,11 @@ var AppSecretGenerateCommand = &cobra.Command{ } if len(secretVals) == 0 { - log.Warn("no secrets generated") + log.Warn(i18n.G("no secrets generated")) os.Exit(1) } - headers := []string{"NAME", "VALUE"} + headers := []string{i18n.G("NAME"), i18n.G("VALUE")} table, err := formatter.CreateTable() if err != nil { log.Fatal(err) @@ -121,7 +121,7 @@ var AppSecretGenerateCommand = &cobra.Command{ if internal.MachineReadable { out, err := formatter.ToJSON(headers, rows) if err != nil { - log.Fatal("unable to render to JSON: %s", err) + log.Fatal(i18n.G("unable to render to JSON: %s", err)) } fmt.Println(out) return @@ -131,31 +131,31 @@ var AppSecretGenerateCommand = &cobra.Command{ log.Fatal(err) } - log.Warnf( + log.Warn(i18n.G( "generated secrets %s shown again, please take note of them %s", - formatter.BoldStyle.Render("NOT"), - formatter.BoldStyle.Render("NOW"), - ) + formatter.BoldStyle.Render(i18n.G("NOT")), + formatter.BoldStyle.Render(i18n.G("NOW")), + )) }, } var AppSecretInsertCommand = &cobra.Command{ - Use: "insert [flags]", - Aliases: []string{"i"}, - Short: "Insert secret", - Long: `This command inserts a secret into an app environment. + Use: i18n.G("insert [flags]"), + Aliases: []string{i18n.G("i")}, + Short: i18n.G("Insert secret"), + Long: i18n.G(`This command inserts a secret into an app environment. Arbitrary secret insertion is not supported. Secrets that are inserted must match those configured in the recipe beforehand. This can be useful when you want to manually generate secrets for an app environment. Typically, you can let Abra generate them for you on app creation -(see "abra app new --secrets/-S" for more).`, - Example: ` # insert regular secret +(see "abra app new --secrets/-S" for more).`), + Example: i18n.G(` # insert regular secret abra app secret insert 1312.net my_secret v1 mySuperSecret # insert secret as file - abra app secret insert 1312.net my_secret v1 secret.txt -f`, + abra app secret insert 1312.net my_secret v1 secret.txt -f`), Args: cobra.MinimumNArgs(4), ValidArgsFunction: func( cmd *cobra.Command, @@ -167,8 +167,7 @@ environment. Typically, you can let Abra generate them for you on app creation case 1: app, err := appPkg.Get(args[0]) if err != nil { - errMsg := fmt.Sprintf("autocomplete failed: %s", err) - return []string{errMsg}, cobra.ShellCompDirectiveError + return []string{i18n.G("autocomplete failed: %s", err)}, cobra.ShellCompDirectiveError } return autocomplete.SecretComplete(app.Recipe.Name) default: @@ -208,13 +207,13 @@ environment. Typically, you can let Abra generate them for you on app creation } } if !isRecipeSecret { - log.Fatalf("no secret %s available for recipe %s?", name, app.Recipe.Name) + log.Fatal(i18n.G("no secret %s available for recipe %s?", name, app.Recipe.Name)) } if insertFromFile { raw, err := os.ReadFile(data) if err != nil { - log.Fatalf("reading secret from file: %s", err) + log.Fatal(i18n.G("reading secret from file: %s", err)) } data = string(raw) } @@ -228,7 +227,7 @@ environment. Typically, you can let Abra generate them for you on app creation log.Fatal(err) } - log.Infof("%s successfully stored on server", secretName) + log.Info(i18n.G("%s successfully stored on server", secretName)) if storeInPass { if err := secret.PassInsertSecret(data, name, app.Name, app.Server); err != nil { @@ -244,28 +243,28 @@ func secretRm(cl *dockerClient.Client, app appPkg.App, secretName, parsed string return err } - log.Infof("deleted %s successfully from server", secretName) + log.Info(i18n.G("deleted %s successfully from server", secretName)) if removeFromPass { if err := secret.PassRmSecret(parsed, app.StackName(), app.Server); err != nil { return err } - log.Infof("deleted %s successfully from local pass store", secretName) + log.Info(i18n.G("deleted %s successfully from local pass store", secretName)) } return nil } var AppSecretRmCommand = &cobra.Command{ - Use: "remove [[secret] | --all] [flags]", - Aliases: []string{"rm"}, - Short: "Remove a secret", - Long: `This command removes a secret from an app environment. + Use: i18n.G("remove [[secret] | --all] [flags]"), + Aliases: []string{i18n.G("rm")}, + Short: i18n.G("Remove a secret"), + Long: i18n.G(`This command removes a secret from an app environment. Arbitrary secret removal is not supported. Secrets that are removed must -match those configured in the recipe beforehand.`, - Example: " abra app secret rm 1312.net oauth_key", +match those configured in the recipe beforehand.`), + Example: i18n.G(" abra app secret rm 1312.net oauth_key"), Args: cobra.RangeArgs(1, 2), ValidArgsFunction: func( cmd *cobra.Command, @@ -278,8 +277,7 @@ match those configured in the recipe beforehand.`, if !rmAllSecrets { app, err := appPkg.Get(args[0]) if err != nil { - errMsg := fmt.Sprintf("autocomplete failed: %s", err) - return []string{errMsg}, cobra.ShellCompDirectiveError + return []string{i18n.G("autocomplete failed: %s", err)}, cobra.ShellCompDirectiveError } return autocomplete.SecretComplete(app.Recipe.Name) } @@ -306,11 +304,11 @@ match those configured in the recipe beforehand.`, } if len(args) == 2 && rmAllSecrets { - log.Fatal("cannot use [secret] and --all/-a together") + log.Fatal(i18n.G("cannot use [secret] and --all/-a together")) } if len(args) != 2 && !rmAllSecrets { - log.Fatal("no secret(s) specified?") + log.Fatal(i18n.G("no secret(s) specified?")) } cl, err := client.New(app.Server) @@ -361,19 +359,19 @@ match those configured in the recipe beforehand.`, } if !match && secretToRm != "" { - log.Fatalf("%s doesn't exist on server?", secretToRm) + log.Fatal(i18n.G("%s doesn't exist on server?", secretToRm)) } if !match { - log.Fatal("no secrets to remove?") + log.Fatal(i18n.G("no secrets to remove?")) } }, } var AppSecretLsCommand = &cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List all secrets", + Use: i18n.G("list "), + Aliases: []string{i18n.G("ls")}, + Short: i18n.G("List all secrets"), Args: cobra.MinimumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -393,7 +391,7 @@ var AppSecretLsCommand = &cobra.Command{ log.Fatal(err) } - headers := []string{"NAME", "VERSION", "GENERATED NAME", "CREATED ON SERVER"} + headers := []string{i18n.G("NAME"), i18n.G("VERSION"), i18n.G("GENERATED NAME"), i18n.G("CREATED ON SERVER")} table, err := formatter.CreateTable() if err != nil { log.Fatal(err) @@ -423,7 +421,7 @@ var AppSecretLsCommand = &cobra.Command{ if internal.MachineReadable { out, err := formatter.ToJSON(headers, rows) if err != nil { - log.Fatal("unable to render to JSON: %s", err) + log.Fatal(i18n.G("unable to render to JSON: %s", err)) } fmt.Println(out) return @@ -436,14 +434,14 @@ var AppSecretLsCommand = &cobra.Command{ return } - log.Warnf("no secrets stored for %s", app.Name) + log.Warn(i18n.G("no secrets stored for %s", app.Name)) }, } var AppSecretCommand = &cobra.Command{ - Use: "secret [cmd] [args] [flags]", - Aliases: []string{"s"}, - Short: "Manage app secrets", + Use: i18n.G("secret [cmd] [args] [flags]"), + Aliases: []string{i18n.G("s")}, + Short: i18n.G("Manage app secrets"), } var ( @@ -458,105 +456,105 @@ var ( func init() { AppSecretGenerateCommand.Flags().BoolVarP( &internal.MachineReadable, - "machine", - "m", + i18n.G("machine"), + i18n.G("m"), false, - "print machine-readable output", + i18n.G("print machine-readable output"), ) AppSecretGenerateCommand.Flags().BoolVarP( &storeInPass, - "pass", - "p", + i18n.G("pass"), + i18n.G("p"), false, - "store generated secrets in a local pass store", + i18n.G("store generated secrets in a local pass store"), ) AppSecretGenerateCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) AppSecretGenerateCommand.Flags().BoolVarP( &generateAllSecrets, - "all", - "a", + i18n.G("all"), + i18n.G("a"), false, - "generate all secrets", + i18n.G("generate all secrets"), ) AppSecretInsertCommand.Flags().BoolVarP( &storeInPass, - "pass", - "p", + i18n.G("pass"), + i18n.G("p"), false, - "store generated secrets in a local pass store", + i18n.G("store generated secrets in a local pass store"), ) AppSecretInsertCommand.Flags().BoolVarP( &insertFromFile, - "file", - "f", + i18n.G("file"), + i18n.G("f"), false, - "treat input as a file", + i18n.G("treat input as a file"), ) AppSecretInsertCommand.Flags().BoolVarP( &trimInput, - "trim", - "t", + i18n.G("trim"), + i18n.G("t"), false, - "trim input", + i18n.G("trim input"), ) AppSecretInsertCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) AppSecretRmCommand.Flags().BoolVarP( &rmAllSecrets, - "all", - "a", + i18n.G("all"), + i18n.G("a"), false, - "remove all secrets", + i18n.G("remove all secrets"), ) AppSecretRmCommand.Flags().BoolVarP( &removeFromPass, - "pass", - "p", + i18n.G("pass"), + i18n.G("p"), false, - "remove generated secrets from a local pass store", + i18n.G("remove generated secrets from a local pass store"), ) AppSecretRmCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) AppSecretLsCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) AppSecretLsCommand.Flags().BoolVarP( &internal.MachineReadable, - "machine", - "m", + i18n.G("machine"), + i18n.G("m"), false, - "print machine-readable output", + i18n.G("print machine-readable output"), ) } diff --git a/cli/app/services.go b/cli/app/services.go index a49eba9c..4843ea86 100644 --- a/cli/app/services.go +++ b/cli/app/services.go @@ -9,6 +9,7 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/service" stack "coopcloud.tech/abra/pkg/upstream/stack" @@ -17,9 +18,9 @@ import ( ) var AppServicesCommand = &cobra.Command{ - Use: "services [flags]", - Aliases: []string{"sr"}, - Short: "Display all services of an app", + Use: i18n.G("services [flags]"), + Aliases: []string{i18n.G("sr")}, + Short: i18n.G("Display all services of an app"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -45,7 +46,7 @@ var AppServicesCommand = &cobra.Command{ } if !deployMeta.IsDeployed { - log.Fatalf("%s is not deployed?", app.Name) + log.Fatal(i18n.G("%s is not deployed?", app.Name)) } filters, err := app.Filters(true, true) @@ -63,7 +64,7 @@ var AppServicesCommand = &cobra.Command{ log.Fatal(err) } - headers := []string{"SERVICE (SHORT)", "SERVICE (LONG)"} + headers := []string{i18n.G("SERVICE (SHORT)"), i18n.G("SERVICE (LONG)")} table.Headers(headers...) var rows [][]string diff --git a/cli/app/undeploy.go b/cli/app/undeploy.go index 12aba61c..ecb32365 100644 --- a/cli/app/undeploy.go +++ b/cli/app/undeploy.go @@ -10,6 +10,7 @@ import ( "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" stack "coopcloud.tech/abra/pkg/upstream/stack" "github.com/docker/docker/api/types/filters" @@ -18,15 +19,15 @@ import ( ) var AppUndeployCommand = &cobra.Command{ - Use: "undeploy [flags]", - Aliases: []string{"un"}, - Short: "Undeploy an app", - Long: `This does not destroy any application data. + Use: i18n.G("undeploy [flags]"), + Aliases: []string{i18n.G("un")}, + Short: i18n.G("Undeploy an app"), + Long: i18n.G(`This does not destroy any application data. However, you should remain vigilant, as your swarm installation will consider any previously attached volumes as eligible for pruning once undeployed. -Passing "--prune/-p" does not remove those volumes.`, +Passing "--prune/-p" does not remove those volumes.`), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -47,7 +48,7 @@ Passing "--prune/-p" does not remove those volumes.`, log.Fatal(err) } - log.Debugf("checking whether %s is already deployed", stackName) + log.Debug(i18n.G("checking whether %s is already deployed", stackName)) deployMeta, err := stack.IsDeployed(context.Background(), cl, stackName) if err != nil { @@ -55,7 +56,7 @@ Passing "--prune/-p" does not remove those volumes.`, } if !deployMeta.IsDeployed { - log.Fatalf("%s is not deployed?", app.Name) + log.Fatal(i18n.G("%s is not deployed?", app.Name)) } if err := internal.DeployOverview( @@ -84,7 +85,7 @@ Passing "--prune/-p" does not remove those volumes.`, log.Fatal(err) } - log.Info("initialising undeploy") + log.Info(i18n.G("initialising undeploy")) rmOpts := stack.Remove{ Namespaces: []string{stackName}, @@ -100,10 +101,10 @@ Passing "--prune/-p" does not remove those volumes.`, } } - log.Info("undeploy succeeded 🟢") + log.Info(i18n.G("undeploy succeeded 🟢")) if err := app.WriteRecipeVersion(deployMeta.Version, false); err != nil { - log.Fatalf("writing recipe version failed: %s", err) + log.Fatal(i18n.G("writing recipe version failed: %s", err)) } }, } @@ -124,14 +125,14 @@ func pruneApp(cl *dockerClient.Client, app appPkg.App) error { } cntSpaceReclaimed := formatter.ByteCountSI(cr.SpaceReclaimed) - log.Infof("containers pruned: %d; space reclaimed: %s", len(cr.ContainersDeleted), cntSpaceReclaimed) + log.Info(i18n.G("containers pruned: %d; space reclaimed: %s", len(cr.ContainersDeleted), cntSpaceReclaimed)) nr, err := cl.NetworksPrune(ctx, pruneFilters) if err != nil { return err } - log.Infof("networks pruned: %d", len(nr.NetworksDeleted)) + log.Info(i18n.G("networks pruned: %d", len(nr.NetworksDeleted))) ir, err := cl.ImagesPrune(ctx, pruneFilters) if err != nil { @@ -139,7 +140,7 @@ func pruneApp(cl *dockerClient.Client, app appPkg.App) error { } imgSpaceReclaimed := formatter.ByteCountSI(ir.SpaceReclaimed) - log.Infof("images pruned: %d; space reclaimed: %s", len(ir.ImagesDeleted), imgSpaceReclaimed) + log.Info(i18n.G("images pruned: %d; space reclaimed: %s", len(ir.ImagesDeleted), imgSpaceReclaimed)) return nil } @@ -151,9 +152,9 @@ var ( func init() { AppUndeployCommand.Flags().BoolVarP( &prune, - "prune", - "p", + i18n.G("prune"), + i18n.G("p"), false, - "prune unused containers, networks, and dangling images", + i18n.G("prune unused containers, networks, and dangling images"), ) } diff --git a/cli/app/upgrade.go b/cli/app/upgrade.go index 5e6ef87d..be574c45 100644 --- a/cli/app/upgrade.go +++ b/cli/app/upgrade.go @@ -2,6 +2,7 @@ package app import ( "context" + "errors" "fmt" "strings" @@ -13,6 +14,7 @@ import ( "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/lint" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" @@ -24,10 +26,10 @@ import ( ) var AppUpgradeCommand = &cobra.Command{ - Use: "upgrade [version] [flags]", - Aliases: []string{"up"}, - Short: "Upgrade an app", - Long: `Upgrade an app. + Use: i18n.G("upgrade [version] [flags]"), + Aliases: []string{i18n.G("up")}, + Short: i18n.G("Upgrade an app"), + Long: i18n.G(`Upgrade an app. Unlike "abra app deploy", chaos operations are not supported here. Only recipe versions are supported values for "[version]". @@ -40,7 +42,7 @@ are available. The live deployment version is the "source of truth" in this case. The stored .env version is not consulted. An upgrade can be destructive, please ensure you have a copy of your app data -beforehand. See "abra app backup" for more.`, +beforehand. See "abra app backup" for more.`), Args: cobra.RangeArgs(1, 2), ValidArgsFunction: func( cmd *cobra.Command, @@ -53,8 +55,7 @@ beforehand. See "abra app backup" for more.`, case 1: app, err := appPkg.Get(args[0]) if err != nil { - errMsg := fmt.Sprintf("autocomplete failed: %s", err) - return []string{errMsg}, cobra.ShellCompDirectiveError + return []string{i18n.G("autocomplete failed: %s", err)}, cobra.ShellCompDirectiveError } return autocomplete.RecipeVersionComplete(app.Recipe.Name) default: @@ -123,7 +124,7 @@ beforehand. See "abra app backup" for more.`, } if !upgradeAvailable { - log.Info("no available upgrades") + log.Info(i18n.G("no available upgrades")) return } } @@ -145,10 +146,10 @@ beforehand. See "abra app backup" for more.`, } if chosenUpgrade == "" { - log.Fatal("unknown deployed version, unable to upgrade") + log.Fatal(i18n.G("unknown deployed version, unable to upgrade")) } - log.Debugf("choosing %s as version to upgrade", chosenUpgrade) + log.Debug(i18n.G("choosing %s as version to upgrade", chosenUpgrade)) // Get the release notes before checking out the new version in the // recipe. This enables us to get release notes, that were added after @@ -204,7 +205,7 @@ beforehand. See "abra app backup" for more.`, for _, envVar := range envVars { if !envVar.Present { upgradeWarnMessages = append(upgradeWarnMessages, - fmt.Sprintf("%s missing from %s.env", envVar.Name, app.Domain), + i18n.G("%s missing from %s.env", envVar.Name, app.Domain), ) } } @@ -236,7 +237,7 @@ beforehand. See "abra app backup" for more.`, log.Fatal(err) } - log.Debugf("set waiting timeout to %d second(s)", stack.WaitTimeout) + log.Debug(i18n.G("set waiting timeout to %d second(s)", stack.WaitTimeout)) serviceNames, err := appPkg.GetAppServiceNames(app.Name) if err != nil { @@ -262,15 +263,15 @@ beforehand. See "abra app backup" for more.`, postDeployCmds, ok := app.Env["POST_UPGRADE_CMDS"] if ok && !internal.DontWaitConverge { - log.Debugf("run the following post-deploy commands: %s", postDeployCmds) + log.Debug(i18n.G("run the following post-deploy commands: %s", postDeployCmds)) if err := internal.PostCmds(cl, app, postDeployCmds); err != nil { - log.Fatalf("attempting to run post deploy commands, saw: %s", err) + log.Fatal(i18n.G("attempting to run post deploy commands, saw: %s", err)) } } if err := app.WriteRecipeVersion(chosenUpgrade, false); err != nil { - log.Fatalf("writing recipe version failed: %s", err) + log.Fatal(i18n.G("writing recipe version failed: %s", err)) } }, } @@ -281,12 +282,12 @@ func chooseUpgrade( deployMeta stack.DeployMeta, chosenUpgrade *string, ) error { - msg := fmt.Sprintf("please select an upgrade (version: %s):", deployMeta.Version) + msg := i18n.G("please select an upgrade (version: %s):", deployMeta.Version) if deployMeta.IsChaos { chaosVersion := formatter.BoldDirtyDefault(deployMeta.ChaosVersion) - msg = fmt.Sprintf( + msg = i18n.G( "please select an upgrade (version: %s, chaos: %s):", deployMeta.Version, chaosVersion, @@ -314,18 +315,18 @@ func getReleaseNotes( ) error { parsedChosenUpgrade, err := tagcmp.Parse(chosenUpgrade) if err != nil { - return fmt.Errorf("parsing chosen upgrade version failed: %s", err) + return errors.New(i18n.G("parsing chosen upgrade version failed: %s", err)) } parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version) if err != nil { - return fmt.Errorf("parsing deployment version failed: %s", err) + return errors.New(i18n.G("parsing deployment version failed: %s", err)) } for _, version := range internal.SortVersionsDesc(versions) { parsedVersion, err := tagcmp.Parse(version) if err != nil { - return fmt.Errorf("parsing recipe version failed: %s", err) + return errors.New(i18n.G("parsing recipe version failed: %s", err)) } if parsedVersion.IsGreaterThan(parsedDeployedVersion) && @@ -358,13 +359,13 @@ func ensureUpgradesAvailable( ) (bool, error) { parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version) if err != nil { - return false, fmt.Errorf("parsing deployed version failed: %s", err) + return false, errors.New(i18n.G("parsing deployed version failed: %s", err)) } for _, version := range versions { parsedVersion, err := tagcmp.Parse(version) if err != nil { - return false, fmt.Errorf("parsing recipe version failed: %s", err) + return false, errors.New(i18n.G("parsing recipe version failed: %s", err)) } if parsedVersion.IsGreaterThan(parsedDeployedVersion) && @@ -388,21 +389,21 @@ func validateUpgradeVersionArg( ) error { parsedSpecificVersion, err := tagcmp.Parse(specificVersion) if err != nil { - return fmt.Errorf("'%s' is not a known version for %s", specificVersion, app.Recipe.Name) + return errors.New(i18n.G("'%s' is not a known version for %s", specificVersion, app.Recipe.Name)) } parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version) if err != nil { - return fmt.Errorf("'%s' is not a known version", deployMeta.Version) + return errors.New(i18n.G("'%s' is not a known version", deployMeta.Version)) } if parsedSpecificVersion.IsLessThan(parsedDeployedVersion) && !parsedSpecificVersion.Equals(parsedDeployedVersion) { - return fmt.Errorf("%s is not an upgrade for %s?", deployMeta.Version, specificVersion) + return errors.New(i18n.G("%s is not an upgrade for %s?", deployMeta.Version, specificVersion)) } if parsedSpecificVersion.Equals(parsedDeployedVersion) && !internal.Force { - return fmt.Errorf("%s is not an upgrade for %s?", deployMeta.Version, specificVersion) + return errors.New(i18n.G("%s is not an upgrade for %s?", deployMeta.Version, specificVersion)) } return nil @@ -411,7 +412,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) { - log.Debugf("checking whether %s is already deployed", app.StackName()) + log.Debug(i18n.G("checking whether %s is already deployed", app.StackName())) deployMeta, err := stack.IsDeployed(context.Background(), cl, app.StackName()) if err != nil { @@ -419,7 +420,7 @@ func ensureDeployed(cl *dockerClient.Client, app app.App) (stack.DeployMeta, err } if !deployMeta.IsDeployed { - return stack.DeployMeta{}, fmt.Errorf("%s is not deployed?", app.Name) + return stack.DeployMeta{}, errors.New(i18n.G("%s is not deployed?", app.Name)) } return deployMeta, nil @@ -430,32 +431,33 @@ var showReleaseNotes bool func init() { AppUpgradeCommand.Flags().BoolVarP( &internal.Force, - "force", - "f", + i18n.G("force"), + i18n.G("f"), false, - "perform action without further prompt", + i18n.G("perform action without further prompt"), ) AppUpgradeCommand.Flags().BoolVarP( &internal.NoDomainChecks, - "no-domain-checks", - "D", + i18n.G("no-domain-checks"), + i18n.G("D"), false, - "disable public DNS checks", + i18n.G("disable public DNS checks"), ) AppUpgradeCommand.Flags().BoolVarP( - &internal.DontWaitConverge, "no-converge-checks", - "c", + &internal.DontWaitConverge, + i18n.G("no-converge-checks"), + i18n.G("c"), false, - "disable converge logic checks", + i18n.G("disable converge logic checks"), ) AppUpgradeCommand.Flags().BoolVarP( &showReleaseNotes, - "releasenotes", - "r", + i18n.G("releasenotes"), + i18n.G("r"), false, - "only show release notes", + i18n.G("only show release notes"), ) } diff --git a/cli/app/volume.go b/cli/app/volume.go index a19ab65c..bde116e6 100644 --- a/cli/app/volume.go +++ b/cli/app/volume.go @@ -8,6 +8,7 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/upstream/stack" "github.com/AlecAivazis/survey/v2" @@ -15,9 +16,9 @@ import ( ) var AppVolumeListCommand = &cobra.Command{ - Use: "list [flags]", - Aliases: []string{"ls"}, - Short: "List volumes associated with an app", + Use: i18n.G("list [flags]"), + Aliases: []string{i18n.G("ls")}, + Short: i18n.G("List volumes associated with an app"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -43,7 +44,7 @@ var AppVolumeListCommand = &cobra.Command{ log.Fatal(err) } - headers := []string{"NAME", "ON SERVER"} + headers := []string{i18n.G("NAME"), i18n.G("ON SERVER")} table, err := formatter.CreateTable() if err != nil { @@ -67,14 +68,14 @@ var AppVolumeListCommand = &cobra.Command{ return } - log.Warnf("no volumes created for %s", app.Name) + log.Warn(i18n.G("no volumes created for %s", app.Name)) }, } var AppVolumeRemoveCommand = &cobra.Command{ - Use: "remove [volume] [flags]", - Short: "Remove volume(s) associated with an app", - Long: `Remove volumes associated with an app. + Use: i18n.G("remove [volume] [flags]"), + Short: i18n.G("Remove volume(s) associated with an app"), + Long: i18n.G(`Remove volumes associated with an app. The app in question must be undeployed before you try to remove volumes. See "abra app undeploy " for more. @@ -83,13 +84,13 @@ 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.`, - Example: ` # delete volumes interactively +Passing "--force/-f" will select all volumes for removal. Be careful.`), + Example: i18n.G(` # delete volumes interactively abra app volume rm 1312.net # delete specific volume - abra app volume rm 1312.net my_volume`, - Aliases: []string{"rm"}, + abra app volume rm 1312.net my_volume`), + Aliases: []string{i18n.G("rm")}, Args: cobra.MinimumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -116,7 +117,7 @@ Passing "--force/-f" will select all volumes for removal. Be careful.`, } if deployMeta.IsDeployed { - log.Fatalf("%s is still deployed. Run \"abra app undeploy %s\"", app.Name, app.Name) + log.Fatal(i18n.G("%s is still deployed. Run \"abra app undeploy %s\"", app.Name, app.Name)) } filters, err := app.Filters(false, true) @@ -141,15 +142,15 @@ Passing "--force/-f" will select all volumes for removal. Be careful.`, } if !exactMatch { - log.Fatalf("unable to remove volume: no volume with name '%s'?", volumeToDelete) + log.Fatal(i18n.G("unable to remove volume: no volume with name '%s'?", volumeToDelete)) } err := client.RemoveVolumes(cl, context.Background(), []string{fullVolumeToDeleteName}, internal.Force, 5) if err != nil { - log.Fatalf("removing volume %s failed: %s", volumeToDelete, err) + log.Fatal(i18n.G("removing volume %s failed: %s", volumeToDelete, err)) } - log.Infof("volume %s removed successfully", volumeToDelete) + log.Info(i18n.G("volume %s removed successfully", volumeToDelete)) return } @@ -157,8 +158,8 @@ Passing "--force/-f" will select all volumes for removal. Be careful.`, var volumesToRemove []string if !internal.Force && !internal.NoInput { volumesPrompt := &survey.MultiSelect{ - Message: "which volumes do you want to remove?", - Help: "'x' indicates selected, enter / return to confirm, ctrl-c to exit, vim mode is enabled", + Message: i18n.G("which volumes do you want to remove?"), + Help: i18n.G("'x' indicates selected, enter / return to confirm, ctrl-c to exit, vim mode is enabled"), VimMode: true, Options: volumeNames, Default: volumeNames, @@ -175,28 +176,28 @@ Passing "--force/-f" will select all volumes for removal. Be careful.`, if len(volumesToRemove) > 0 { err := client.RemoveVolumes(cl, context.Background(), volumesToRemove, internal.Force, 5) if err != nil { - log.Fatalf("removing volumes failed: %s", err) + log.Fatal(i18n.G("removing volumes failed: %s", err)) } - log.Infof("%d volumes removed successfully", len(volumesToRemove)) + log.Info(i18n.G("%d volumes removed successfully", len(volumesToRemove))) } else { - log.Info("no volumes removed") + log.Info(i18n.G("no volumes removed")) } }, } var AppVolumeCommand = &cobra.Command{ - Use: "volume [cmd] [args] [flags]", - Aliases: []string{"vl"}, - Short: "Manage app volumes", + Use: i18n.G("volume [cmd] [args] [flags]"), + Aliases: []string{i18n.G("vl")}, + Short: i18n.G("Manage app volumes"), } func init() { AppVolumeRemoveCommand.Flags().BoolVarP( &internal.Force, - "force", - "f", + i18n.G("force"), + i18n.G("f"), false, - "perform action without further prompt", + i18n.G("perform action without further prompt"), ) } diff --git a/cli/catalogue/catalogue.go b/cli/catalogue/catalogue.go index 9c7abd27..6998f1aa 100644 --- a/cli/catalogue/catalogue.go +++ b/cli/catalogue/catalogue.go @@ -13,6 +13,7 @@ import ( "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/formatter" gitPkg "coopcloud.tech/abra/pkg/git" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" "github.com/go-git/go-git/v5" @@ -20,10 +21,10 @@ import ( ) var CatalogueGenerateCommand = &cobra.Command{ - Use: "generate [recipe] [flags]", - Aliases: []string{"g"}, - Short: "Generate the recipe catalogue", - Long: `Generate a new copy of the recipe catalogue. + Use: i18n.G("generate [recipe] [flags]"), + Aliases: []string{i18n.G("g")}, + Short: i18n.G("Generate the recipe catalogue"), + Long: i18n.G(`Generate a new copy of the recipe catalogue. N.B. this command **will** wipe local unstaged changes from your local recipes if present. "--chaos/-C" on this command refers to the catalogue repository @@ -39,7 +40,7 @@ use those details. Push your new release to git.coopcloud.tech with "--publish/-p". 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.`), Args: cobra.RangeArgs(0, 1), ValidArgsFunction: func( cmd *cobra.Command, @@ -85,7 +86,7 @@ keys configured on your account.`, var warnings []string catl := make(recipe.RecipeCatalogue) - catlBar := formatter.CreateProgressbar(barLength, "collecting catalogue metadata") + catlBar := formatter.CreateProgressbar(barLength, i18n.G("collecting catalogue metadata")) for _, recipeMeta := range repos { if recipeName != "" && recipeName != recipeMeta.Name { if !internal.Debug { @@ -171,7 +172,7 @@ keys configured on your account.`, } } - log.Infof("generated recipe catalogue: %s", config.RECIPES_JSON) + log.Info(i18n.G("generated recipe catalogue: %s", config.RECIPES_JSON)) cataloguePath := path.Join(config.ABRA_DIR, "catalogue") if publishChanges { @@ -183,11 +184,11 @@ keys configured on your account.`, if isClean { if !internal.Dry { - log.Fatalf("no changes discovered in %s, nothing to publish?", cataloguePath) + log.Fatal(i18n.G("no changes discovered in %s, nothing to publish?", cataloguePath)) } } - msg := "chore: publish new catalogue release changes" + msg := i18n.G("chore: publish new catalogue release changes") if err := gitPkg.Commit(cataloguePath, msg, internal.Dry); err != nil { log.Fatal(err) } @@ -219,19 +220,19 @@ keys configured on your account.`, if !internal.Dry && publishChanges { url := fmt.Sprintf("%s/%s/commit/%s", config.REPOS_BASE_URL, config.CATALOGUE_JSON_REPO_NAME, head.Hash()) - log.Infof("new changes published: %s", url) + log.Info(i18n.G("new changes published: %s", url)) } if internal.Dry { - log.Info("dry run: no changes published") + log.Info(i18n.G("dry run: no changes published")) } }, } // CatalogueCommand defines the `abra catalogue` command and sub-commands. var CatalogueCommand = &cobra.Command{ - Use: "catalogue [cmd] [args] [flags]", - Short: "Manage the recipe catalogue", + Use: i18n.G("catalogue [cmd] [args] [flags]"), + Short: i18n.G("Manage the recipe catalogue"), Aliases: []string{"c"}, } @@ -243,33 +244,33 @@ var ( func init() { CatalogueGenerateCommand.Flags().BoolVarP( &publishChanges, - "publish", - "p", + i18n.G("publish"), + i18n.G("p"), false, - "publish changes to git.coopcloud.tech", + i18n.G("publish changes to git.coopcloud.tech"), ) CatalogueGenerateCommand.Flags().BoolVarP( &internal.Dry, - "dry-run", - "r", + i18n.G("dry-run"), + i18n.G("r"), false, - "report changes that would be made", + i18n.G("report changes that would be made"), ) CatalogueGenerateCommand.Flags().BoolVarP( &skipUpdates, - "skip-updates", - "s", + i18n.G("skip-updates"), + i18n.G("s"), false, - "skip updating recipe repositories", + i18n.G("skip updating recipe repositories"), ) CatalogueGenerateCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) } diff --git a/cli/complete.go b/cli/complete.go index 7f520df9..3eeb2105 100644 --- a/cli/complete.go +++ b/cli/complete.go @@ -3,13 +3,14 @@ package cli import ( "os" + "coopcloud.tech/abra/pkg/i18n" "github.com/spf13/cobra" ) var AutocompleteCommand = &cobra.Command{ - Use: "autocomplete [bash|zsh|fish|powershell]", - Short: "Generate autocompletion script", - Long: `To load completions: + Use: i18n.G("autocomplete [bash|zsh|fish|powershell]"), + Short: i18n.G("Generate autocompletion script"), + Long: i18n.G(`To load completions: Bash: # Load autocompletion for the current Bash session @@ -43,7 +44,7 @@ PowerShell: # To load autocompletions for every new session, run: PS> abra autocomplete powershell > abra.ps1 - # and source this file from your PowerShell profile.`, + # and source this file from your PowerShell profile.`), DisableFlagsInUseLine: true, ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), diff --git a/cli/internal/backup.go b/cli/internal/backup.go index 7554f973..d4355ef0 100644 --- a/cli/internal/backup.go +++ b/cli/internal/backup.go @@ -2,11 +2,12 @@ package internal import ( "context" - "fmt" + "errors" "io" "coopcloud.tech/abra/pkg/config" containerPkg "coopcloud.tech/abra/pkg/container" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/service" "coopcloud.tech/abra/pkg/upstream/container" @@ -22,10 +23,10 @@ func RetrieveBackupBotContainer(cl *dockerClient.Client) (types.Container, error ctx := context.Background() chosenService, err := service.GetServiceByLabel(ctx, cl, config.BackupbotLabel, NoInput) if err != nil { - return types.Container{}, fmt.Errorf("no backupbot discovered, is it deployed?") + return types.Container{}, errors.New(i18n.G("no backupbot discovered, is it deployed?")) } - log.Debugf("retrieved %s as backup enabled service", chosenService.Spec.Name) + log.Debug(i18n.G("retrieved %s as backup enabled service", chosenService.Spec.Name)) filters := filters.NewArgs() filters.Add("name", chosenService.Spec.Name) @@ -58,7 +59,7 @@ func RunBackupCmdRemote( Tty: true, } - log.Debugf("running backup %s on %s with exec config %v", backupCmd, containerID, execBackupListOpts) + log.Debug(i18n.G("running backup %s on %s with exec config %v", backupCmd, containerID, execBackupListOpts)) // FIXME: avoid instantiating a new CLI dcli, err := command.NewDockerCli() diff --git a/cli/internal/cli.go b/cli/internal/cli.go index 7c4825ad..be00b3f4 100644 --- a/cli/internal/cli.go +++ b/cli/internal/cli.go @@ -6,6 +6,7 @@ var ( NoInput bool Offline bool IgnoreEnvVersion bool + Locale string // NOTE(d1): sub-command specific Chaos bool diff --git a/cli/internal/command.go b/cli/internal/command.go index 854d82d0..7f9ea578 100644 --- a/cli/internal/command.go +++ b/cli/internal/command.go @@ -3,6 +3,7 @@ package internal import ( "bufio" "context" + "errors" "fmt" "io/ioutil" "os/exec" @@ -11,6 +12,7 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" containerPkg "coopcloud.tech/abra/pkg/container" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/upstream/container" "github.com/docker/cli/cli/command" @@ -34,7 +36,7 @@ func RunCmdRemote( return err } - log.Debugf("retrieved %s as target container on %s", formatter.ShortenID(targetContainer.ID), app.Server) + log.Debug(i18n.G("retrieved %s as target container on %s", formatter.ShortenID(targetContainer.ID), app.Server)) toTarOpts := &archive.TarOptions{NoOverwriteDirNonDir: true, Compression: archive.Gzip} content, err := archive.TarWithOptions(abraSh, toTarOpts) @@ -65,7 +67,7 @@ func RunCmdRemote( } if _, err := container.RunExec(dcli, cl, targetContainer.ID, &execCreateOpts); err != nil { - log.Infof("%s does not exist for %s, use /bin/sh as fallback", shell, app.Name) + log.Info(i18n.G("%s does not exist for %s, use /bin/sh as fallback", shell, app.Name)) shell = "/bin/sh" } @@ -76,10 +78,10 @@ func RunCmdRemote( cmd = []string{shell, "-c", fmt.Sprintf("TARGET=%s; APP_NAME=%s; STACK_NAME=%s; . /tmp/abra.sh; %s", serviceName, app.Name, app.StackName(), cmdName)} } - log.Debugf("running command: %s", strings.Join(cmd, " ")) + log.Debug(i18n.G("running command: %s", strings.Join(cmd, " "))) if remoteUser != "" { - log.Debugf("running command with user %s", remoteUser) + log.Debug(i18n.G("running command with user %s", remoteUser)) execCreateOpts.User = remoteUser } @@ -88,7 +90,7 @@ func RunCmdRemote( execCreateOpts.Tty = true if disableTTY { execCreateOpts.Tty = false - log.Debugf("not requesting a remote TTY") + log.Debug(i18n.G("not requesting a remote TTY")) } if _, err := container.RunExec(dcli, cl, targetContainer.ID, &execCreateOpts); err != nil { @@ -105,7 +107,7 @@ func EnsureCommand(abraSh, recipeName, execCmd string) error { } if !strings.Contains(string(bytes), execCmd) { - return fmt.Errorf("%s doesn't have a %s function", recipeName, execCmd) + return errors.New(i18n.G("%s doesn't have a %s function", recipeName, execCmd)) } return nil diff --git a/cli/internal/deploy.go b/cli/internal/deploy.go index d687c49f..37406128 100644 --- a/cli/internal/deploy.go +++ b/cli/internal/deploy.go @@ -1,6 +1,7 @@ package internal import ( + "errors" "fmt" "os" "sort" @@ -9,6 +10,7 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/tagcmp" "github.com/AlecAivazis/survey/v2" @@ -70,18 +72,18 @@ func DeployOverview( } rows := [][]string{ - {"DOMAIN", domain}, - {"RECIPE", app.Recipe.Name}, - {"SERVER", server}, - {"CONFIG", deployConfig}, + {i18n.G("DOMAIN"), domain}, + {i18n.G("RECIPE"), app.Recipe.Name}, + {i18n.G("SERVER"), server}, + {i18n.G("CONFIG"), deployConfig}, {"", ""}, - {"CURRENT DEPLOYMENT", formatter.BoldDirtyDefault(deployedVersion)}, - {"ENV VERSION", formatter.BoldDirtyDefault(envVersion)}, - {"NEW DEPLOYMENT", formatter.BoldDirtyDefault(toDeployVersion)}, + {i18n.G("CURRENT DEPLOYMENT"), formatter.BoldDirtyDefault(deployedVersion)}, + {i18n.G("ENV VERSION"), formatter.BoldDirtyDefault(envVersion)}, + {i18n.G("NEW DEPLOYMENT"), formatter.BoldDirtyDefault(toDeployVersion)}, } deployType := getDeployType(deployedVersion, toDeployVersion) - overview := formatter.CreateOverview(fmt.Sprintf("%s OVERVIEW", deployType), rows) + overview := formatter.CreateOverview(i18n.G("%s OVERVIEW", deployType), rows) fmt.Println(overview) @@ -104,7 +106,7 @@ func DeployOverview( } if !response { - log.Fatal("deployment cancelled") + log.Fatal(i18n.G("deployment cancelled")) } return nil @@ -112,32 +114,32 @@ func DeployOverview( func getDeployType(currentVersion, newVersion string) string { if newVersion == config.NO_DOMAIN_DEFAULT { - return "UNDEPLOY" + return i18n.G("UNDEPLOY") } if strings.Contains(newVersion, "+U") { - return "CHAOS DEPLOY" + return i18n.G("CHAOS DEPLOY") } if strings.Contains(currentVersion, "+U") { - return "UNCHAOS DEPLOY" + return i18n.G("UNCHAOS DEPLOY") } if currentVersion == newVersion { - return "REDEPLOY" + return ("REDEPLOY") } if currentVersion == config.NO_VERSION_DEFAULT { - return "NEW DEPLOY" + return i18n.G("NEW DEPLOY") } currentParsed, err := tagcmp.Parse(currentVersion) if err != nil { - return "DEPLOY" + return i18n.G("DEPLOY") } newParsed, err := tagcmp.Parse(newVersion) if err != nil { - return "DEPLOY" + return i18n.G("DEPLOY") } if currentParsed.IsLessThan(newParsed) { - return "UPGRADE" + return i18n.G("UPGRADE") } - return "DOWNGRADE" + return i18n.G("DOWNGRADE") } // PostCmds parses a string of commands and executes them inside of the respective services @@ -146,7 +148,7 @@ func getDeployType(currentVersion, newVersion string) string { func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error { if _, err := os.Stat(app.Recipe.AbraShPath); err != nil { if os.IsNotExist(err) { - return fmt.Errorf("%s does not exist for %s?", app.Recipe.AbraShPath, app.Name) + return errors.New(i18n.G("%s does not exist for %s?", app.Recipe.AbraShPath, app.Name)) } return err } @@ -154,7 +156,7 @@ func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error { for _, command := range strings.Split(commands, "|") { commandParts := strings.Split(command, " ") if len(commandParts) < 2 { - return fmt.Errorf("not enough arguments: %s", command) + return errors.New(i18n.G("not enough arguments: %s", command)) } targetServiceName := commandParts[0] cmdName := commandParts[1] @@ -162,7 +164,7 @@ func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error { if len(commandParts) > 2 { parsedCmdArgs = fmt.Sprintf("%s ", strings.Join(commandParts[2:], " ")) } - log.Infof("running post-command '%s %s' in container %s", cmdName, parsedCmdArgs, targetServiceName) + log.Info(i18n.G("running post-command '%s %s' in container %s", cmdName, parsedCmdArgs, targetServiceName)) if err := EnsureCommand(app.Recipe.AbraShPath, app.Recipe.Name, cmdName); err != nil { return err @@ -184,7 +186,7 @@ func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error { return fmt.Errorf("no service %s for %s?", targetServiceName, app.Name) } - log.Debugf("running command %s %s within the context of %s_%s", cmdName, parsedCmdArgs, app.StackName(), targetServiceName) + log.Debug(i18n.G("running command %s %s within the context of %s_%s", cmdName, parsedCmdArgs, app.StackName(), targetServiceName)) requestTTY := true if err := RunCmdRemote( diff --git a/cli/internal/recipe.go b/cli/internal/recipe.go index 2e209ae1..1c253ef3 100644 --- a/cli/internal/recipe.go +++ b/cli/internal/recipe.go @@ -1,9 +1,11 @@ package internal import ( + "errors" "fmt" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" "github.com/AlecAivazis/survey/v2" @@ -13,7 +15,7 @@ import ( // PromptBumpType prompts for version bump type func PromptBumpType(tagString, latestRelease string) error { if (!Major && !Minor && !Patch) && tagString == "" { - fmt.Printf(` + fmt.Print(i18n.G(` You need to make a decision about what kind of an update this new recipe version is. If someone else performs this upgrade, do they have to do some migration work or take care of some breaking changes? This can be signaled in @@ -36,12 +38,12 @@ Here is a semver cheat sheet (more on https://semver.org): should also Just Work and is mostly to do with minor bug fixes and/or security patches. "nothing to worry about". -`, latestRelease) +`, latestRelease)) var chosenBumpType string prompt := &survey.Select{ Message: fmt.Sprintf("select recipe version increment type"), - Options: []string{"major", "minor", "patch"}, + Options: []string{i18n.G("major"), i18n.G("minor"), i18n.G("patch")}, } if err := survey.AskOne(prompt, &chosenBumpType); err != nil { @@ -59,13 +61,13 @@ func GetBumpType() string { var bumpType string if Major { - bumpType = "major" + bumpType = i18n.G("major") } else if Minor { - bumpType = "minor" + bumpType = i18n.G("minor") } else if Patch { - bumpType = "patch" + bumpType = i18n.G("patch") } else { - log.Fatal("no version bump type specififed?") + log.Fatal(i18n.G("no version bump type specififed?")) } return bumpType @@ -73,14 +75,14 @@ func GetBumpType() string { // SetBumpType figures out which bump type is specified func SetBumpType(bumpType string) { - if bumpType == "major" { + if bumpType == i18n.G("major") { Major = true - } else if bumpType == "minor" { + } else if bumpType == i18n.G("minor") { Minor = true - } else if bumpType == "patch" { + } else if bumpType == i18n.G("patch") { Patch = true } else { - log.Fatal("no version bump type specififed?") + log.Fatal(i18n.G("no version bump type specififed?")) } } @@ -107,7 +109,7 @@ func GetMainAppImage(recipe recipe.Recipe) (string, error) { } if path == "" { - return path, fmt.Errorf("%s has no main 'app' service?", recipe.Name) + return path, errors.New(i18n.G("%s has no main 'app' service?", recipe.Name)) } return path, nil diff --git a/cli/internal/validate.go b/cli/internal/validate.go index 9c067db4..f39b9d34 100644 --- a/cli/internal/validate.go +++ b/cli/internal/validate.go @@ -5,6 +5,7 @@ import ( "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/config" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" "github.com/AlecAivazis/survey/v2" @@ -31,7 +32,7 @@ func ValidateRecipe(args []string, cmdName string) recipe.Recipe { localRecipes, err := recipe.GetRecipesLocal() if err != nil { - log.Debugf("can't read local recipes: %s", err) + log.Debug(i18n.G("can't read local recipes: %s", err)) } else { for _, recipeLocal := range localRecipes { if _, ok := knownRecipes[recipeLocal]; !ok { @@ -46,7 +47,7 @@ func ValidateRecipe(args []string, cmdName string) recipe.Recipe { if recipeName == "" && !NoInput { prompt := &survey.Select{ - Message: "Select recipe", + Message: i18n.G("Select recipe"), Options: recipes, } if err := survey.AskOne(prompt, &recipeName); err != nil { @@ -55,12 +56,12 @@ func ValidateRecipe(args []string, cmdName string) recipe.Recipe { } if recipeName == "" { - log.Fatal("no recipe name provided") + log.Fatal(i18n.G("no recipe name provided")) } if _, ok := knownRecipes[recipeName]; !ok { if !strings.Contains(recipeName, "/") { - log.Fatalf("no recipe '%s' exists?", recipeName) + log.Fatal(i18n.G("no recipe '%s' exists?", recipeName)) } } @@ -71,20 +72,20 @@ func ValidateRecipe(args []string, cmdName string) recipe.Recipe { _, err = chosenRecipe.GetComposeConfig(nil) if err != nil { - if cmdName == "generate" { + if cmdName == i18n.G("generate") { if strings.Contains(err.Error(), "missing a compose") { log.Fatal(err) } log.Warn(err) } else { if strings.Contains(err.Error(), "template_driver is not allowed") { - log.Warnf("ensure %s recipe compose.* files include \"version: '3.8'\"", recipeName) + log.Warn(i18n.G("ensure %s recipe compose.* files include \"version: '3.8'\"", recipeName)) } - log.Fatalf("unable to validate recipe: %s", err) + log.Fatal(i18n.G("unable to validate recipe: %s", err)) } } - log.Debugf("validated %s as recipe argument", recipeName) + log.Debug(i18n.G("validated %s as recipe argument", recipeName)) return chosenRecipe } @@ -92,7 +93,7 @@ func ValidateRecipe(args []string, cmdName string) recipe.Recipe { // ValidateApp ensures the app name arg is valid. func ValidateApp(args []string) app.App { if len(args) == 0 { - log.Fatal("no app provided") + log.Fatal(i18n.G("no app provided")) } appName := args[0] @@ -102,7 +103,7 @@ func ValidateApp(args []string) app.App { log.Fatal(err) } - log.Debugf("validated %s as app argument", appName) + log.Debug(i18n.G("validated %s as app argument", appName)) return app } @@ -116,8 +117,8 @@ func ValidateDomain(args []string) string { if domainName == "" && !NoInput { prompt := &survey.Input{ - Message: "Specify a domain name", - Default: "example.com", + Message: i18n.G("Specify a domain name"), + Default: "1312.net", } if err := survey.AskOne(prompt, &domainName); err != nil { log.Fatal(err) @@ -125,10 +126,10 @@ func ValidateDomain(args []string) string { } if domainName == "" { - log.Fatal("no domain provided") + log.Fatal(i18n.G("no domain provided")) } - log.Debugf("validated %s as domain argument", domainName) + log.Debug(i18n.G("validated %s as domain argument", domainName)) return domainName } @@ -147,7 +148,7 @@ func ValidateServer(args []string) string { if serverName == "" && !NoInput { prompt := &survey.Select{ - Message: "Specify a server name", + Message: i18n.G("Specify a server name"), Options: serverNames, } if err := survey.AskOne(prompt, &serverName); err != nil { @@ -163,14 +164,14 @@ func ValidateServer(args []string) string { } if serverName == "" { - log.Fatal("no server provided") + log.Fatal(i18n.G("no server provided")) } if !matched { - log.Fatal("server doesn't exist?") + log.Fatal(i18n.G("server doesn't exist?")) } - log.Debugf("validated %s as server argument", serverName) + log.Debug(i18n.G("validated %s as server argument", serverName)) return serverName } diff --git a/cli/recipe/diff.go b/cli/recipe/diff.go index b8bdfd67..990352c8 100644 --- a/cli/recipe/diff.go +++ b/cli/recipe/diff.go @@ -4,15 +4,16 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" gitPkg "coopcloud.tech/abra/pkg/git" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/spf13/cobra" ) var RecipeDiffCommand = &cobra.Command{ - Use: "diff [flags]", - Aliases: []string{"d"}, - Short: "Show unstaged changes in recipe config", - Long: "This command requires /usr/bin/git.", + Use: i18n.G("diff [flags]"), + Aliases: []string{i18n.G("d")}, + Short: i18n.G("Show unstaged changes in recipe config"), + Long: i18n.G("This command requires /usr/bin/git."), Args: cobra.MinimumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, diff --git a/cli/recipe/fetch.go b/cli/recipe/fetch.go index a5c1a368..519130d3 100644 --- a/cli/recipe/fetch.go +++ b/cli/recipe/fetch.go @@ -6,6 +6,7 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" "github.com/go-git/go-git/v5" @@ -14,19 +15,19 @@ import ( ) var RecipeFetchCommand = &cobra.Command{ - Use: "fetch [recipe | --all] [flags]", - Aliases: []string{"f"}, - Short: "Clone recipe(s) locally", - Long: `Using "--force/-f" Git syncs an existing recipe. It does not erase unstaged changes.`, + Use: i18n.G("fetch [recipe | --all] [flags]"), + Aliases: []string{i18n.G("f")}, + Short: i18n.G("Clone recipe(s) locally"), + Long: i18n.G(`Using "--force/-f" Git syncs an existing recipe. It does not erase unstaged changes.`), Args: cobra.RangeArgs(0, 1), - Example: ` # fetch from recipe catalogue + Example: i18n.G(` # fetch from recipe catalogue abra recipe fetch gitea # fetch from remote recipe abra recipe fetch git.foo.org/recipes/myrecipe # fetch with ssh remote for hacking - abra recipe fetch gitea --ssh`, + abra recipe fetch gitea --ssh`), ValidArgsFunction: func( cmd *cobra.Command, args []string, @@ -40,18 +41,18 @@ var RecipeFetchCommand = &cobra.Command{ } if recipeName == "" && !fetchAllRecipes { - log.Fatal("missing [recipe] or --all/-a") + log.Fatal(i18n.G("missing [recipe] or --all/-a")) } if recipeName != "" && fetchAllRecipes { - log.Fatal("cannot use [recipe] and --all/-a together") + log.Fatal(i18n.G("cannot use [recipe] and --all/-a together")) } if recipeName != "" { r := recipe.Get(recipeName) if _, err := os.Stat(r.Dir); !os.IsNotExist(err) { if !force { - log.Warnf("%s is already fetched", r.Name) + log.Warn(i18n.G("%s is already fetched", r.Name)) return } } @@ -60,24 +61,24 @@ var RecipeFetchCommand = &cobra.Command{ if sshRemote { if r.SSHURL == "" { - log.Warnf("unable to discover SSH remote for %s", r.Name) + log.Warn(i18n.G("unable to discover SSH remote for %s", r.Name)) return } repo, err := git.PlainOpen(r.Dir) if err != nil { - log.Fatalf("unable to open %s: %s", r.Dir, err) + log.Fatal(i18n.G("unable to open %s: %s", r.Dir, err)) } if err = repo.DeleteRemote("origin"); err != nil { - log.Fatalf("unable to remove default remote in %s: %s", r.Dir, err) + log.Fatal(i18n.G("unable to remove default remote in %s: %s", r.Dir, err)) } if _, err := repo.CreateRemote(&gitCfg.RemoteConfig{ Name: "origin", URLs: []string{r.SSHURL}, }); err != nil { - log.Fatalf("unable to set SSH remote in %s: %s", r.Dir, err) + log.Fatal(i18n.G("unable to set SSH remote in %s: %s", r.Dir, err)) } } @@ -89,7 +90,7 @@ var RecipeFetchCommand = &cobra.Command{ log.Fatal(err) } - catlBar := formatter.CreateProgressbar(len(catalogue), "fetching latest recipes...") + catlBar := formatter.CreateProgressbar(len(catalogue), i18n.G("fetching latest recipes...")) ensureCtx := internal.GetEnsureContext() for recipeName := range catalogue { r := recipe.Get(recipeName) @@ -110,25 +111,25 @@ var ( func init() { RecipeFetchCommand.Flags().BoolVarP( &fetchAllRecipes, - "all", - "a", + i18n.G("all"), + i18n.G("a"), false, - "fetch all recipes", + i18n.G("fetch all recipes"), ) RecipeFetchCommand.Flags().BoolVarP( &sshRemote, - "ssh", - "s", + i18n.G("ssh"), + i18n.G("s"), false, - "automatically set ssh remote", + i18n.G("automatically set ssh remote"), ) RecipeFetchCommand.Flags().BoolVarP( &force, - "force", - "f", + i18n.G("force"), + i18n.G("f"), false, - "force re-fetch", + i18n.G("force re-fetch"), ) } diff --git a/cli/recipe/lint.go b/cli/recipe/lint.go index d885fe04..55c4d523 100644 --- a/cli/recipe/lint.go +++ b/cli/recipe/lint.go @@ -4,15 +4,16 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/lint" "coopcloud.tech/abra/pkg/log" "github.com/spf13/cobra" ) var RecipeLintCommand = &cobra.Command{ - Use: "lint [flags]", - Short: "Lint a recipe", - Aliases: []string{"l"}, + Use: i18n.G("lint [flags]"), + Short: i18n.G("Lint a recipe"), + Aliases: []string{i18n.G("l")}, Args: cobra.MinimumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -28,12 +29,12 @@ var RecipeLintCommand = &cobra.Command{ } headers := []string{ - "ref", - "rule", - "severity", - "satisfied", - "skipped", - "resolve", + i18n.G("ref"), + i18n.G("rule"), + i18n.G("severity"), + i18n.G("satisfied"), + i18n.G("skipped"), + i18n.G("resolve"), } table, err := formatter.CreateTable() @@ -49,7 +50,7 @@ var RecipeLintCommand = &cobra.Command{ for level := range lint.LintRules { for _, rule := range lint.LintRules[level] { if onlyError && rule.Level != "error" { - log.Debugf("skipping %s, does not have level \"error\"", rule.Ref) + log.Debug(i18n.G("skipping %s, does not have level \"error\"", rule.Ref)) continue } @@ -70,7 +71,7 @@ var RecipeLintCommand = &cobra.Command{ warnMessages = append(warnMessages, err.Error()) } - if !ok && rule.Level == "error" { + if !ok && rule.Level == i18n.G("error") { hasError = true } @@ -111,7 +112,7 @@ var RecipeLintCommand = &cobra.Command{ } if hasError { - log.Warnf("critical errors present in %s config", recipe.Name) + log.Warn(i18n.G("critical errors present in %s config", recipe.Name)) } } }, @@ -124,17 +125,17 @@ var ( func init() { RecipeLintCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) RecipeLintCommand.Flags().BoolVarP( &onlyError, - "error", - "e", + i18n.G("error"), + i18n.G("e"), false, - "only show errors", + i18n.G("only show errors"), ) } diff --git a/cli/recipe/list.go b/cli/recipe/list.go index e0b44c08..884dccb1 100644 --- a/cli/recipe/list.go +++ b/cli/recipe/list.go @@ -8,15 +8,16 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" "github.com/spf13/cobra" ) var RecipeListCommand = &cobra.Command{ - Use: "list", - Short: "List recipes", - Aliases: []string{"ls"}, + Use: i18n.G("list"), + Short: i18n.G("List recipes"), + Aliases: []string{i18n.G("ls")}, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { catl, err := recipe.ReadRecipeCatalogue(internal.Offline) @@ -33,14 +34,14 @@ var RecipeListCommand = &cobra.Command{ } headers := []string{ - "name", - "category", - "status", - "healthcheck", - "backups", - "email", - "tests", - "SSO", + i18n.G("name"), + i18n.G("category"), + i18n.G("status"), + i18n.G("healthcheck"), + i18n.G("backups"), + i18n.G("email"), + i18n.G("tests"), + i18n.G("SSO"), } table.Headers(headers...) @@ -73,7 +74,7 @@ var RecipeListCommand = &cobra.Command{ if internal.MachineReadable { out, err := formatter.ToJSON(headers, rows) if err != nil { - log.Fatal("unable to render to JSON: %s", err) + log.Fatal(i18n.G("unable to render to JSON: %s", err)) } fmt.Println(out) return @@ -93,17 +94,17 @@ var ( func init() { RecipeListCommand.Flags().BoolVarP( &internal.MachineReadable, - "machine", - "m", + i18n.G("machine"), + i18n.G("m"), false, - "print machine-readable output", + i18n.G("print machine-readable output"), ) RecipeListCommand.Flags().StringVarP( &pattern, - "pattern", - "p", + i18n.G("pattern"), + i18n.G("p"), "", - "filter by recipe", + i18n.G("filter by recipe"), ) } diff --git a/cli/recipe/new.go b/cli/recipe/new.go index a5380e39..3a7fe514 100644 --- a/cli/recipe/new.go +++ b/cli/recipe/new.go @@ -10,6 +10,7 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/git" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" "github.com/spf13/cobra" @@ -30,10 +31,10 @@ type recipeMetadata struct { } var RecipeNewCommand = &cobra.Command{ - Use: "new [flags]", - Aliases: []string{"n"}, - Short: "Create a new recipe", - Long: `A community managed recipe template is used.`, + Use: i18n.G("new [flags]"), + Aliases: []string{i18n.G("n")}, + Short: i18n.G("Create a new recipe"), + Long: i18n.G(`A community managed recipe template is used.`), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -46,10 +47,10 @@ var RecipeNewCommand = &cobra.Command{ r := recipe.Get(recipeName) if _, err := os.Stat(r.Dir); !os.IsNotExist(err) { - log.Fatalf("%s recipe directory already exists?", r.Dir) + log.Fatal(i18n.G("%s recipe directory already exists?", r.Dir)) } - url := fmt.Sprintf("%s/example.git", config.REPOS_BASE_URL) + url := i18n.G("%s/example.git", config.REPOS_BASE_URL) if err := git.Clone(r.Dir, url); err != nil { log.Fatal(err) } @@ -58,7 +59,7 @@ var RecipeNewCommand = &cobra.Command{ if err := os.RemoveAll(gitRepo); err != nil { log.Fatal(err) } - log.Debugf("removed .git repo in %s", gitRepo) + log.Debug(i18n.G("removed .git repo in %s", gitRepo)) meta := newRecipeMeta(recipeName) @@ -82,8 +83,8 @@ var RecipeNewCommand = &cobra.Command{ log.Fatal(err) } - log.Infof("new recipe '%s' created: %s", recipeName, path.Join(r.Dir)) - log.Info("happy hacking 🎉") + log.Info(i18n.G("new recipe '%s' created: %s", recipeName, path.Join(r.Dir))) + log.Info(i18n.G("happy hacking 🎉")) }, } @@ -111,17 +112,17 @@ var ( func init() { RecipeNewCommand.Flags().StringVarP( &gitName, - "git-name", - "N", + i18n.G("git-name"), + i18n.G("N"), "", - "Git (user) name to do commits with", + i18n.G("Git (user) name to do commits with"), ) RecipeNewCommand.Flags().StringVarP( &gitEmail, - "git-email", - "e", + i18n.G("git-email"), + i18n.G("e"), "", - "Git email name to do commits with", + i18n.G("Git email name to do commits with"), ) } diff --git a/cli/recipe/recipe.go b/cli/recipe/recipe.go index 733ffec5..bcba8bbf 100644 --- a/cli/recipe/recipe.go +++ b/cli/recipe/recipe.go @@ -1,13 +1,16 @@ package recipe -import "github.com/spf13/cobra" +import ( + "coopcloud.tech/abra/pkg/i18n" + "github.com/spf13/cobra" +) // RecipeCommand defines all recipe related sub-commands. var RecipeCommand = &cobra.Command{ - Use: "recipe [cmd] [args] [flags]", - Aliases: []string{"r"}, - Short: "Manage recipes", - Long: `A recipe is a blueprint for an app. + Use: i18n.G("recipe [cmd] [args] [flags]"), + Aliases: []string{i18n.G("r")}, + Short: i18n.G("Manage recipes"), + Long: i18n.G(`A recipe is a blueprint for an app. It is a bunch of config files which describe how to deploy and maintain an app. Recipes are maintained by the Co-op Cloud community and you can use Abra to @@ -15,5 +18,5 @@ read them, deploy them and create apps 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.`, +manner.`), } diff --git a/cli/recipe/release.go b/cli/recipe/release.go index d56b88c7..b4bda80a 100644 --- a/cli/recipe/release.go +++ b/cli/recipe/release.go @@ -12,6 +12,7 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/formatter" gitPkg "coopcloud.tech/abra/pkg/git" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/tagcmp" @@ -22,10 +23,10 @@ import ( ) var RecipeReleaseCommand = &cobra.Command{ - Use: "release [version] [flags]", - Aliases: []string{"rl"}, - Short: "Release a new recipe version", - Long: `Create a new version of a recipe. + Use: i18n.G("release [version] [flags]"), + Aliases: []string{i18n.G("rl")}, + Short: i18n.G("Release a new recipe version"), + Long: i18n.G(`Create a new version of a recipe. These versions are then published on the Co-op Cloud recipe catalogue. These versions take the following form: @@ -44,7 +45,7 @@ major and therefore require intervention while doing the upgrade work. Publish your new release to git.coopcloud.tech with "--publish/-p". 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.`), Args: cobra.RangeArgs(1, 2), ValidArgsFunction: func( cmd *cobra.Command, @@ -74,7 +75,7 @@ your SSH keys configured on your account.`, mainAppVersion := imagesTmp[mainApp] if mainAppVersion == "" { - log.Fatalf("main app service version for %s is empty?", recipe.Name) + log.Fatal(i18n.G("main app service version for %s is empty?", recipe.Name)) } var tagString string @@ -84,12 +85,12 @@ your SSH keys configured on your account.`, if tagString != "" { if _, err := tagcmp.Parse(tagString); err != nil { - log.Fatalf("cannot parse %s, invalid tag specified?", tagString) + log.Fatal(i18n.G("cannot parse %s, invalid tag specified?", tagString)) } } if (internal.Major || internal.Minor || internal.Patch) && tagString != "" { - log.Fatal("cannot specify tag and bump type at the same time") + log.Fatal(i18n.G("cannot specify tag and bump type at the same time")) } if tagString != "" { @@ -117,19 +118,19 @@ your SSH keys configured on your account.`, } if !isClean { - log.Infof("%s currently has these unstaged changes 👇", recipe.Name) + log.Info(i18n.G("%s currently has these unstaged changes 👇", recipe.Name)) if err := gitPkg.DiffUnstaged(recipe.Dir); err != nil { log.Fatal(err) } } if len(tags) > 0 { - log.Warnf("previous git tags detected, assuming this is a new semver release") + log.Warn(i18n.G("previous git tags detected, assuming this is a new semver release")) if err := createReleaseFromPreviousTag(tagString, mainAppVersion, recipe, tags); err != nil { log.Fatal(err) } } else { - log.Warnf("no tag specified and no previous tag available for %s, assuming this is the initial release", recipe.Name) + log.Warn(i18n.G("no tag specified and no previous tag available for %s, assuming this is the initial release", recipe.Name)) if err := createReleaseFromTag(recipe, tagString, mainAppVersion); err != nil { if cleanUpErr := cleanUpTag(recipe, tagString); err != nil { @@ -181,7 +182,7 @@ func getImageVersions(recipe recipe.Recipe) (map[string]string, error) { } if missingTag { - return services, fmt.Errorf("app service is missing image tag?") + return services, errors.New(i18n.G("app service is missing image tag?")) } return services, nil @@ -245,7 +246,7 @@ func btoi(b bool) int { // getTagCreateOptions constructs git tag create options func getTagCreateOptions(tag string) (git.CreateTagOptions, error) { - msg := fmt.Sprintf("chore: publish %s release", tag) + msg := i18n.G("chore: publish %s release", tag) return git.CreateTagOptions{Message: msg}, nil } @@ -273,13 +274,13 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error { if _, err := os.Stat(nextReleaseNotePath); err == nil { // release/next note exists. Move it to release/ if internal.Dry { - log.Debugf("dry run: move release note from 'next' to %s", tag) + log.Debug(i18n.G("dry run: move release note from 'next' to %s", tag)) return nil } if !internal.NoInput { prompt := &survey.Confirm{ - Message: "Use release note in release/next?", + Message: i18n.G("Use release note in release/next?"), } if err := survey.AskOne(prompt, &addNextAsReleaseNotes); err != nil { @@ -313,7 +314,7 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error { } prompt := &survey.Input{ - Message: "Release Note (leave empty for no release note)", + Message: i18n.G("Release Note (leave empty for no release note)"), } var releaseNote string @@ -338,7 +339,7 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error { func commitRelease(recipe recipe.Recipe, tag string) error { if internal.Dry { - log.Debugf("dry run: no changes committed") + log.Debug(i18n.G("dry run: no changes committed")) return nil } @@ -349,7 +350,7 @@ func commitRelease(recipe recipe.Recipe, tag string) error { if isClean { if !internal.Dry { - return fmt.Errorf("no changes discovered in %s, nothing to publish?", recipe.Dir) + return errors.New(i18n.G("no changes discovered in %s, nothing to publish?", recipe.Dir)) } } @@ -363,7 +364,7 @@ func commitRelease(recipe recipe.Recipe, tag string) error { func tagRelease(tagString string, repo *git.Repository) error { if internal.Dry { - log.Debugf("dry run: no git tag created (%s)", tagString) + log.Debug(i18n.G("dry run: no git tag created (%s)", tagString)) return nil } @@ -383,20 +384,20 @@ func tagRelease(tagString string, repo *git.Repository) error { } hash := formatter.SmallSHA(head.Hash().String()) - log.Debugf(fmt.Sprintf("created tag %s at %s", tagString, hash)) + log.Debug(i18n.G("created tag %s at %s", tagString, hash)) return nil } func pushRelease(recipe recipe.Recipe, tagString string) error { if internal.Dry { - log.Info("dry run: no changes published") + log.Info(i18n.G("dry run: no changes published")) return nil } if !publish && !internal.NoInput { prompt := &survey.Confirm{ - Message: "publish new release?", + Message: i18n.G("publish new release?"), } if err := survey.AskOne(prompt, &publish); err != nil { @@ -409,9 +410,9 @@ func pushRelease(recipe recipe.Recipe, tagString string) error { return err } url := fmt.Sprintf("%s/src/tag/%s", recipe.GitURL, tagString) - log.Infof("new release published: %s", url) + log.Info(i18n.G("new release published: %s", url)) } else { - log.Info("no -p/--publish passed, not publishing") + log.Info(i18n.G("no -p/--publish passed, not publishing")) } return nil @@ -426,7 +427,7 @@ func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recip bumpType := btoi(internal.Major)*4 + btoi(internal.Minor)*2 + btoi(internal.Patch) if bumpType != 0 { if (bumpType & (bumpType - 1)) != 0 { - return fmt.Errorf("you can only use one of: --major, --minor, --patch") + return errors.New(i18n.G("you can only use one of: --major, --minor, --patch")) } } @@ -483,12 +484,12 @@ func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recip } if lastGitTag.String() == tagString { - log.Fatalf("latest git tag (%s) and synced label (%s) are the same?", lastGitTag, tagString) + log.Fatal(i18n.G("latest git tag (%s) and synced label (%s) are the same?", lastGitTag, tagString)) } if !internal.NoInput { prompt := &survey.Confirm{ - Message: fmt.Sprintf("current: %s, new: %s, correct?", lastGitTag, tagString), + Message: i18n.G("current: %s, new: %s, correct?", lastGitTag, tagString), } var ok bool @@ -497,7 +498,7 @@ func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recip } if !ok { - log.Fatal("exiting as requested") + log.Fatal(i18n.G("exiting as requested")) } } @@ -506,15 +507,15 @@ func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recip } if err := commitRelease(recipe, tagString); err != nil { - log.Fatalf("failed to commit changes: %s", err.Error()) + log.Fatal(i18n.G("failed to commit changes: %s", err.Error())) } if err := tagRelease(tagString, repo); err != nil { - log.Fatalf("failed to tag release: %s", err.Error()) + log.Fatal(i18n.G("failed to tag release: %s", err.Error())) } if err := pushRelease(recipe, tagString); err != nil { - log.Fatalf("failed to publish new release: %s", err.Error()) + log.Fatal(i18n.G("failed to publish new release: %s", err.Error())) } return nil @@ -533,7 +534,7 @@ func cleanUpTag(recipe recipe.Recipe, tag string) error { } } - log.Debugf("removed freshly created tag %s", tag) + log.Debug(i18n.G("removed freshly created tag %s", tag)) return nil } @@ -545,20 +546,20 @@ func getLabelVersion(recipe recipe.Recipe, prompt bool) (string, error) { } if initTag == "" { - log.Fatalf("unable to read version for %s from synced label. Did you try running \"abra recipe sync %s\" already?", recipe.Name, recipe.Name) + log.Fatal(i18n.G("unable to read version for %s from synced label. Did you try running \"abra recipe sync %s\" already?", recipe.Name, recipe.Name)) } - log.Warnf("discovered %s as currently synced recipe label", initTag) + log.Warn(i18n.G("discovered %s as currently synced recipe label", initTag)) if prompt && !internal.NoInput { var response bool - prompt := &survey.Confirm{Message: fmt.Sprintf("use %s as the new version?", initTag)} + prompt := &survey.Confirm{Message: i18n.G("use %s as the new version?", initTag)} if err := survey.AskOne(prompt, &response); err != nil { return "", err } if !response { - return "", fmt.Errorf("please fix your synced label for %s and re-run this command", recipe.Name) + return "", errors.New(i18n.G("please fix your synced label for %s and re-run this command", recipe.Name)) } } @@ -572,42 +573,41 @@ var ( func init() { RecipeReleaseCommand.Flags().BoolVarP( &internal.Dry, - "dry-run", - "r", + i18n.G("dry-run"), + i18n.G("r"), false, - "report changes that would be made", + i18n.G("report changes that would be made"), ) RecipeReleaseCommand.Flags().BoolVarP( &internal.Major, - "major", - "x", + i18n.G("major"), + i18n.G("x"), false, - "increase the major part of the version", + i18n.G("increase the major part of the version"), ) RecipeReleaseCommand.Flags().BoolVarP( &internal.Minor, - "minor", - "y", + i18n.G("minor"), + i18n.G("y"), false, - "increase the minor part of the version", + i18n.G("increase the minor part of the version"), ) RecipeReleaseCommand.Flags().BoolVarP( &internal.Patch, - "patch", - "z", + i18n.G("patch"), + i18n.G("z"), false, - "increase the patch part of the version", + i18n.G("increase the patch part of the version"), ) RecipeReleaseCommand.Flags().BoolVarP( &publish, - "publish", - "p", + i18n.G("publish"), + i18n.G("p"), false, - "publish changes to git.coopcloud.tech", + i18n.G("publish changes to git.coopcloud.tech"), ) - } diff --git a/cli/recipe/reset.go b/cli/recipe/reset.go index 664fc467..0299513e 100644 --- a/cli/recipe/reset.go +++ b/cli/recipe/reset.go @@ -3,16 +3,17 @@ package recipe import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/go-git/go-git/v5" "github.com/spf13/cobra" ) var RecipeResetCommand = &cobra.Command{ - Use: "reset [flags]", - Aliases: []string{"rs"}, - Short: "Remove all unstaged changes from recipe config", - Long: "WARNING: this will delete your changes. Be Careful.", + Use: i18n.G("reset [flags]"), + Aliases: []string{i18n.G("rs")}, + Short: i18n.G("Remove all unstaged changes from recipe config"), + Long: i18n.G("WARNING: this will delete your changes. Be Careful."), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, diff --git a/cli/recipe/sync.go b/cli/recipe/sync.go index 73bc55bf..cfa46436 100644 --- a/cli/recipe/sync.go +++ b/cli/recipe/sync.go @@ -7,6 +7,7 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" gitPkg "coopcloud.tech/abra/pkg/git" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/tagcmp" "github.com/AlecAivazis/survey/v2" @@ -16,10 +17,10 @@ import ( ) var RecipeSyncCommand = &cobra.Command{ - Use: "sync [version] [flags]", - Aliases: []string{"s"}, - Short: "Sync recipe version label", - Long: `Generate labels for the main recipe service. + Use: i18n.G("sync [version] [flags]"), + Aliases: []string{i18n.G("s")}, + Short: i18n.G("Sync recipe version label"), + Long: i18n.G(`Generate labels for the main recipe service. By convention, the service named "app" using the following format: @@ -27,7 +28,7 @@ By convention, the service named "app" using the following format: Where [version] can be specifed on the command-line or Abra can attempt to auto-generate it for you. The configuration will be updated on the -local file system.`, +local file system.`), Args: cobra.RangeArgs(1, 2), ValidArgsFunction: func( cmd *cobra.Command, @@ -68,11 +69,11 @@ local file system.`, } if len(tags) == 0 && nextTag == "" { - log.Warnf("no git tags found for %s", recipe.Name) + log.Warn(i18n.G("no git tags found for %s", recipe.Name)) if internal.NoInput { - log.Fatalf("unable to continue, input required for initial version") + log.Fatal(i18n.G("unable to continue, input required for initial version")) } - fmt.Println(fmt.Sprintf(` + fmt.Println(i18n.G(` The following options are two types of initial semantic version that you can pick for %s that will be published in the recipe catalogue. This follows the semver convention (more on https://semver.org), here is a short cheatsheet @@ -92,7 +93,7 @@ likely to change. `, recipe.Name, recipe.Name)) var chosenVersion string edPrompt := &survey.Select{ - Message: "which version do you want to begin with?", + Message: i18n.G("which version do you want to begin with?"), Options: []string{"0.1.0", "1.0.0"}, } @@ -125,7 +126,7 @@ likely to change. if err := iter.ForEach(func(ref *plumbing.Reference) error { obj, err := repo.TagObject(ref.Hash()) if err != nil { - log.Fatal("Tag at commit ", ref.Hash(), " is unannotated or otherwise broken. Please fix it.") + log.Fatal(i18n.G("tag at commit %s is unannotated or otherwise broken", ref.Hash())) return err } @@ -150,7 +151,7 @@ likely to change. if bumpType != 0 { // a bitwise check if the number is a power of 2 if (bumpType & (bumpType - 1)) != 0 { - log.Fatal("you can only use one version flag: --major, --minor or --patch") + log.Fatal(i18n.G("you can only use one version flag: --major, --minor or --patch")) } } @@ -184,22 +185,22 @@ likely to change. } newTag.Metadata = mainAppVersion - log.Debugf("choosing %s as new version for %s", newTag.String(), recipe.Name) + log.Debug(i18n.G("choosing %s as new version for %s", newTag.String(), recipe.Name)) nextTag = newTag.String() } if _, err := tagcmp.Parse(nextTag); err != nil { - log.Fatalf("invalid version %s specified", nextTag) + log.Fatal(i18n.G("invalid version %s specified", nextTag)) } mainService := "app" - label := fmt.Sprintf("coop-cloud.${STACK_NAME}.version=%s", nextTag) + label := i18n.G("coop-cloud.${STACK_NAME}.version=%s", nextTag) if !internal.Dry { if err := recipe.UpdateLabel("compose.y*ml", mainService, label); err != nil { log.Fatal(err) } } else { - log.Infof("dry run: not syncing label %s for recipe %s", nextTag, recipe.Name) + log.Info(i18n.G("dry run: not syncing label %s for recipe %s", nextTag, recipe.Name)) } isClean, err := gitPkg.IsClean(recipe.Dir) @@ -207,7 +208,7 @@ likely to change. log.Fatal(err) } if !isClean { - log.Infof("%s currently has these unstaged changes 👇", recipe.Name) + log.Info(i18n.G("%s currently has these unstaged changes 👇", recipe.Name)) if err := gitPkg.DiffUnstaged(recipe.Dir); err != nil { log.Fatal(err) } @@ -218,33 +219,33 @@ likely to change. func init() { RecipeSyncCommand.Flags().BoolVarP( &internal.Dry, - "dry-run", - "r", + i18n.G("dry-run"), + i18n.G("r"), false, - "report changes that would be made", + i18n.G("report changes that would be made"), ) RecipeSyncCommand.Flags().BoolVarP( &internal.Major, - "major", - "x", + i18n.G("major"), + i18n.G("x"), false, - "increase the major part of the version", + i18n.G("increase the major part of the version"), ) RecipeSyncCommand.Flags().BoolVarP( &internal.Minor, - "minor", - "y", + i18n.G("minor"), + i18n.G("y"), false, - "increase the minor part of the version", + i18n.G("increase the minor part of the version"), ) RecipeSyncCommand.Flags().BoolVarP( &internal.Patch, - "patch", - "z", + i18n.G("patch"), + i18n.G("z"), false, - "increase the patch part of the version", + i18n.G("increase the patch part of the version"), ) } diff --git a/cli/recipe/upgrade.go b/cli/recipe/upgrade.go index 9eb262c8..834cc9d5 100644 --- a/cli/recipe/upgrade.go +++ b/cli/recipe/upgrade.go @@ -14,6 +14,7 @@ import ( "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/formatter" gitPkg "coopcloud.tech/abra/pkg/git" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" recipePkg "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/tagcmp" @@ -37,10 +38,10 @@ type anUpgrade struct { } var RecipeUpgradeCommand = &cobra.Command{ - Use: "upgrade [flags]", - Aliases: []string{"u"}, - Short: "Upgrade recipe image tags", - Long: `Upgrade a given configuration. + Use: i18n.G("upgrade [flags]"), + Aliases: []string{i18n.G("u")}, + Short: i18n.G("Upgrade recipe image tags"), + Long: i18n.G(`Upgrade a given configuration. It will update the relevant compose file tags on the local file system. @@ -52,7 +53,7 @@ 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.`), Args: cobra.RangeArgs(0, 1), ValidArgsFunction: func( cmd *cobra.Command, @@ -71,7 +72,7 @@ You may invoke this command in "wizard" mode and be prompted for input.`, if bumpType != 0 { // a bitwise check if the number is a power of 2 if (bumpType & (bumpType - 1)) != 0 { - log.Fatal("you can only use one of: --major, --minor, --patch.") + log.Fatal(i18n.G("you can only use one of: --major, --minor, --patch.")) } } @@ -87,7 +88,7 @@ You may invoke this command in "wizard" mode and be prompted for input.`, versionsPath := path.Join(recipe.Dir, "versions") servicePins := make(map[string]imgPin) if _, err := os.Stat(versionsPath); err == nil { - log.Debugf("found versions file for %s", recipe.Name) + log.Debug(i18n.G("found versions file for %s", recipe.Name)) file, err := os.Open(versionsPath) if err != nil { log.Fatal(err) @@ -97,7 +98,7 @@ You may invoke this command in "wizard" mode and be prompted for input.`, line := scanner.Text() splitLine := strings.Split(line, " ") if splitLine[0] != "pin" || len(splitLine) != 3 { - log.Fatalf("malformed version pin specification: %s", line) + log.Fatal(i18n.G("malformed version pin specification: %s", line)) } pinSlice := strings.Split(splitLine[2], ":") pinTag, err := tagcmp.Parse(pinSlice[1]) @@ -115,7 +116,7 @@ You may invoke this command in "wizard" mode and be prompted for input.`, } versionsPresent = true } else { - log.Debugf("did not find versions file for %s", recipe.Name) + log.Debug(i18n.G("did not find versions file for %s", recipe.Name)) } config, err := recipe.GetComposeConfig(nil) @@ -135,26 +136,26 @@ You may invoke this command in "wizard" mode and be prompted for input.`, } image := reference.Path(img) - log.Debugf("retrieved %s from remote registry for %s", regVersions, image) + log.Debug(i18n.G("retrieved %s from remote registry for %s", regVersions, image)) image = formatter.StripTagMeta(image) switch img.(type) { case reference.NamedTagged: if !tagcmp.IsParsable(img.(reference.NamedTagged).Tag()) { - log.Debugf("%s not considered semver-like", img.(reference.NamedTagged).Tag()) + log.Debug(i18n.G("%s not considered semver-like", img.(reference.NamedTagged).Tag())) } default: - log.Warnf("unable to read tag for image %s, is it missing? skipping upgrade for %s", image, service.Name) + log.Warn(i18n.G("unable to read tag for image %s, is it missing? skipping upgrade for %s", image, service.Name)) continue } tag, err := tagcmp.Parse(img.(reference.NamedTagged).Tag()) if err != nil { - log.Warnf("unable to parse %s, error was: %s, skipping upgrade for %s", image, err.Error(), service.Name) + log.Warn(i18n.G("unable to parse %s, error was: %s, skipping upgrade for %s", image, err.Error(), service.Name)) continue } - log.Debugf("parsed %s for %s", tag, service.Name) + log.Debug(i18n.G("parsed %s for %s", tag, service.Name)) var compatible []tagcmp.Tag for _, regVersion := range regVersions { @@ -168,12 +169,12 @@ You may invoke this command in "wizard" mode and be prompted for input.`, } } - log.Debugf("detected potential upgradable tags %s for %s", compatible, service.Name) + log.Debug(i18n.G("detected potential upgradable tags %s for %s", compatible, service.Name)) sort.Sort(tagcmp.ByTagDesc(compatible)) if len(compatible) == 0 && !allTags { - log.Info(fmt.Sprintf("no new versions available for %s, assuming %s is the latest (use -a/--all-tags to see all anyway)", image, tag)) + log.Info(i18n.G("no new versions available for %s, assuming %s is the latest (use -a/--all-tags to see all anyway)", image, tag)) continue // skip on to the next tag and don't update any compose files } @@ -195,7 +196,7 @@ You may invoke this command in "wizard" mode and be prompted for input.`, } } - log.Debugf("detected compatible upgradable tags %s for %s", compatibleStrings, service.Name) + log.Debug(i18n.G("detected compatible upgradable tags %s for %s", compatibleStrings, service.Name)) var upgradeTag string _, ok := servicePins[service.Name] @@ -212,13 +213,13 @@ You may invoke this command in "wizard" mode and be prompted for input.`, } } if contains { - log.Infof("upgrading service %s from %s to %s (pinned tag: %s)", service.Name, tag.String(), upgradeTag, pinnedTagString) + log.Info(i18n.G("upgrading service %s from %s to %s (pinned tag: %s)", service.Name, tag.String(), upgradeTag, pinnedTagString)) } else { - log.Infof("service %s, image %s pinned to %s, no compatible upgrade found", service.Name, servicePins[service.Name].image, pinnedTagString) + log.Info(i18n.G("service %s, image %s pinned to %s, no compatible upgrade found", service.Name, servicePins[service.Name].image, pinnedTagString)) continue } } else { - log.Fatalf("service %s is at version %s, but pinned to %s, please correct your compose.yml file manually!", service.Name, tag.String(), pinnedTag.String()) + log.Fatal(i18n.G("service %s is at version %s, but pinned to %s, please correct your compose.yml file manually!", service.Name, tag.String(), pinnedTag.String())) continue } } else { @@ -235,17 +236,17 @@ You may invoke this command in "wizard" mode and be prompted for input.`, } } if upgradeTag == "" { - log.Warnf("not upgrading from %s to %s for %s, because the upgrade type is more serious than what user wants", tag.String(), compatible[0].String(), image) + log.Warn(i18n.G("not upgrading from %s to %s for %s, because the upgrade type is more serious than what user wants", tag.String(), compatible[0].String(), image)) continue } } else { - msg := fmt.Sprintf("upgrade to which tag? (service: %s, image: %s, tag: %s)", service.Name, image, tag) + msg := i18n.G("upgrade to which tag? (service: %s, image: %s, tag: %s)", service.Name, image, tag) if !tagcmp.IsParsable(img.(reference.NamedTagged).Tag()) || allTags { tag := img.(reference.NamedTagged).Tag() if !allTags { - log.Warn(fmt.Sprintf("unable to determine versioning semantics of %s, listing all tags", tag)) + log.Warn(i18n.G("unable to determine versioning semantics of %s, listing all tags", tag)) } - msg = fmt.Sprintf("upgrade to which tag? (service: %s, tag: %s)", service.Name, tag) + msg = i18n.G("upgrade to which tag? (service: %s, tag: %s)", service.Name, tag) compatibleStrings = []string{"skip"} for _, regVersion := range regVersions { compatibleStrings = append(compatibleStrings, regVersion) @@ -276,7 +277,7 @@ You may invoke this command in "wizard" mode and be prompted for input.`, } else { prompt := &survey.Select{ Message: msg, - Help: "enter / return to confirm, choose 'skip' to not upgrade this tag, vim mode is enabled", + Help: i18n.G("enter / return to confirm, choose 'skip' to not upgrade this tag, vim mode is enabled"), VimMode: true, Options: compatibleStrings, } @@ -292,11 +293,11 @@ You may invoke this command in "wizard" mode and be prompted for input.`, log.Fatal(err) } if ok { - log.Infof("tag upgraded from %s to %s for %s", tag.String(), upgradeTag, image) + log.Info(i18n.G("tag upgraded from %s to %s for %s", tag.String(), upgradeTag, image)) } } else { if !internal.NoInput { - log.Warnf("not upgrading %s, skipping as requested", image) + log.Warn(i18n.G("not upgrading %s, skipping as requested", image)) } } } @@ -314,7 +315,7 @@ You may invoke this command in "wizard" mode and be prompted for input.`, } for _, upgrade := range upgradeList { - log.Infof("can upgrade service: %s, image: %s, tag: %s ::", upgrade.Service, upgrade.Image, upgrade.Tag) + log.Info(i18n.G("can upgrade service: %s, image: %s, tag: %s ::", upgrade.Service, upgrade.Image, upgrade.Tag)) for _, utag := range upgrade.UpgradeTags { log.Infof(" %s", utag) } @@ -326,7 +327,7 @@ You may invoke this command in "wizard" mode and be prompted for input.`, log.Fatal(err) } if !isClean { - log.Infof("%s currently has these unstaged changes 👇", recipe.Name) + log.Info(i18n.G("%s currently has these unstaged changes 👇", recipe.Name)) if err := gitPkg.DiffUnstaged(recipe.Dir); err != nil { log.Fatal(err) } @@ -341,41 +342,41 @@ var ( func init() { RecipeUpgradeCommand.Flags().BoolVarP( &internal.Major, - "major", - "x", + i18n.G("major"), + i18n.G("x"), false, - "increase the major part of the version", + i18n.G("increase the major part of the version"), ) RecipeUpgradeCommand.Flags().BoolVarP( &internal.Minor, - "minor", - "y", + i18n.G("minor"), + i18n.G("y"), false, - "increase the minor part of the version", + i18n.G("increase the minor part of the version"), ) RecipeUpgradeCommand.Flags().BoolVarP( &internal.Patch, - "patch", - "z", + i18n.G("patch"), + i18n.G("z"), false, - "increase the patch part of the version", + i18n.G("increase the patch part of the version"), ) RecipeUpgradeCommand.Flags().BoolVarP( &internal.MachineReadable, - "machine", - "m", + i18n.G("machine"), + i18n.G("m"), false, - "print machine-readable output", + i18n.G("print machine-readable output"), ) RecipeUpgradeCommand.Flags().BoolVarP( &allTags, - "all-tags", - "a", + i18n.G("all-tags"), + i18n.G("a"), false, - "list all tags, not just upgrades", + i18n.G("list all tags, not just upgrades"), ) } diff --git a/cli/recipe/version.go b/cli/recipe/version.go index 0ae32bd8..62db7a59 100644 --- a/cli/recipe/version.go +++ b/cli/recipe/version.go @@ -7,15 +7,16 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" recipePkg "coopcloud.tech/abra/pkg/recipe" "github.com/spf13/cobra" ) var RecipeVersionCommand = &cobra.Command{ - Use: "versions [flags]", - Aliases: []string{"v"}, - Short: "List recipe versions", + Use: i18n.G("versions [flags]"), + Aliases: []string{i18n.G("v")}, + Short: i18n.G("List recipe versions"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -35,7 +36,7 @@ var RecipeVersionCommand = &cobra.Command{ recipeMeta, ok := catl[recipe.Name] if !ok { - warnMessages = append(warnMessages, "retrieved versions from local recipe repository") + warnMessages = append(warnMessages, i18n.G("retrieved versions from local recipe repository")) recipeVersions, warnMsg, err := recipe.GetRecipeVersions() if err != nil { @@ -49,7 +50,7 @@ var RecipeVersionCommand = &cobra.Command{ } if len(recipeMeta.Versions) == 0 { - log.Fatalf("%s has no published versions?", recipe.Name) + log.Fatal(i18n.G("%s has no published versions?", recipe.Name)) } for i := len(recipeMeta.Versions) - 1; i >= 0; i-- { @@ -58,7 +59,7 @@ var RecipeVersionCommand = &cobra.Command{ log.Fatal(err) } - table.Headers("SERVICE", "IMAGE", "TAG", "VERSION") + table.Headers(i18n.G("SERVICE"), i18n.G("IMAGE"), i18n.G("TAG"), i18n.G("VERSION")) for version, meta := range recipeMeta.Versions[i] { var allRows [][]string @@ -99,10 +100,10 @@ var RecipeVersionCommand = &cobra.Command{ if internal.MachineReadable { sort.Slice(allRows, sortServiceByName(allRows)) - headers := []string{"VERSION", "SERVICE", "NAME", "TAG"} + headers := []string{i18n.G("VERSION"), i18n.G("SERVICE"), i18n.G("NAME"), i18n.G("TAG")} out, err := formatter.ToJSON(headers, allRows) if err != nil { - log.Fatal("unable to render to JSON: %s", err) + log.Fatal(i18n.G("unable to render to JSON: %s", err)) } fmt.Println(out) continue @@ -127,9 +128,9 @@ func sortServiceByName(versions [][]string) func(i, j int) bool { func init() { RecipeVersionCommand.Flags().BoolVarP( &internal.MachineReadable, - "machine", - "m", + i18n.G("machine"), + i18n.G("m"), false, - "print machine-readable output", + i18n.G("print machine-readable output"), ) } diff --git a/cli/run.go b/cli/run.go index 13dd8aad..25f4cdaa 100644 --- a/cli/run.go +++ b/cli/run.go @@ -1,6 +1,7 @@ package cli import ( + "errors" "fmt" "os" @@ -10,6 +11,8 @@ import ( "coopcloud.tech/abra/cli/recipe" "coopcloud.tech/abra/cli/server" "coopcloud.tech/abra/pkg/config" + "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" charmLog "github.com/charmbracelet/log" "github.com/spf13/cobra" @@ -18,19 +21,20 @@ import ( func Run(version, commit string) { rootCmd := &cobra.Command{ - Use: "abra [cmd] [args] [flags]", - Short: "The Co-op Cloud command-line utility belt 🎩🐇", + Use: i18n.G("abra [cmd] [args] [flags]"), + Short: i18n.G("The Co-op Cloud command-line utility belt 🎩🐇"), Version: fmt.Sprintf("%s-%s", version, commit[:7]), ValidArgs: []string{ - "app", - "autocomplete", - "catalogue", - "man", - "recipe", - "server", - "upgrade", + i18n.G("app"), + i18n.G("autocomplete"), + i18n.G("catalogue"), + i18n.G("man"), + i18n.G("recipe"), + i18n.G("server"), + i18n.G("upgrade"), }, - PersistentPreRun: func(cmd *cobra.Command, args []string) { + + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { dirs := []map[string]os.FileMode{ {config.ABRA_DIR: 0764}, {config.SERVERS_DIR: 0700}, @@ -42,7 +46,7 @@ func Run(version, commit string) { for path, perm := range dir { if err := os.Mkdir(path, perm); err != nil { if !os.IsExist(err) { - log.Fatal(err) + return errors.New(i18n.G("unable to create %s: %s", path, err)) } continue } @@ -62,24 +66,38 @@ func Run(version, commit string) { log.SetReportCaller(true) } - log.Debugf("abra version %s, commit %s", version, commit) + if internal.Locale != "" { + // FIXME(d1): get list of valid locales from pkg/locales/* + switch internal.Locale { + case "es": + default: + return errors.New(i18n.G("unsupported --lang: %s (want: es)", internal.Locale)) + } + } + + log.Debug(i18n.G( + "abra version: %s, commit: %s, lang: %s", + version, formatter.SmallSHA(commit), internal.Locale, + )) + + return nil }, } rootCmd.CompletionOptions.DisableDefaultCmd = true manCommand := &cobra.Command{ - Use: "man [flags]", + Use: i18n.G("man [flags]"), Aliases: []string{"m"}, - Short: "Generate manpage", - Example: ` # generate the man pages into /usr/local/share/man/man1 + Short: i18n.G("Generate manpage"), + Example: i18n.G(` # generate the man pages into /usr/local/share/man/man1 abra_path=$(which abra) # pass abra absolute path to sudo below sudo $abra_path man sudo mandb # read the man pages man abra - man abra-app-deploy`, + man abra-app-deploy`), Run: func(cmd *cobra.Command, args []string) { header := &doc.GenManHeader{ Title: "ABRA", @@ -88,7 +106,7 @@ func Run(version, commit string) { manDir := "/usr/local/share/man/man1" if _, err := os.Stat(manDir); os.IsNotExist(err) { - log.Fatalf("unable to proceed, '%s' does not exist?") + log.Fatal(i18n.G("unable to proceed, %s does not exist?", manDir)) } err := doc.GenManTree(rootCmd, header, manDir) @@ -96,7 +114,7 @@ func Run(version, commit string) { log.Fatal(err) } - log.Info("don't forget to run 'sudo mandb'") + log.Info(i18n.G("don't forget to run 'sudo mandb'")) }, } @@ -105,7 +123,7 @@ func Run(version, commit string) { "debug", "d", false, - "show debug messages", + i18n.G("show debug messages"), ) rootCmd.PersistentFlags().BoolVarP( @@ -113,7 +131,7 @@ func Run(version, commit string) { "no-input", "n", false, - "toggle non-interactive mode", + i18n.G("toggle non-interactive mode"), ) rootCmd.PersistentFlags().BoolVarP( @@ -121,7 +139,7 @@ func Run(version, commit string) { "offline", "o", false, - "prefer offline & filesystem access", + i18n.G("prefer offline & filesystem access"), ) rootCmd.PersistentFlags().BoolVarP( @@ -129,7 +147,16 @@ func Run(version, commit string) { "ignore-env-version", "i", false, - "ignore .env version checkout", + i18n.G("ignore .env version checkout"), + ) + + rootCmd.PersistentFlags().StringVarP( + &internal.Locale, + "lang", + "l", + "", + // FIXME(d1): provide supported list of language via *.po file listing + i18n.G("force select language (supported: XXX)"), ) catalogue.CatalogueCommand.AddCommand( diff --git a/cli/server/add.go b/cli/server/add.go index 12ca137f..a366a010 100644 --- a/cli/server/add.go +++ b/cli/server/add.go @@ -10,6 +10,7 @@ import ( "coopcloud.tech/abra/pkg/config" contextPkg "coopcloud.tech/abra/pkg/context" "coopcloud.tech/abra/pkg/dns" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/server" sshPkg "coopcloud.tech/abra/pkg/ssh" @@ -17,10 +18,10 @@ import ( ) var ServerAddCommand = &cobra.Command{ - Use: "add [[server] | --local] [flags]", - Aliases: []string{"a"}, - Short: "Add a new server", - Long: `Add a new server to your configuration so that it can be managed by Abra. + Use: i18n.G("add [[server] | --local] [flags]"), + Aliases: []string{i18n.G("a")}, + Short: i18n.G("Add a new server"), + Long: i18n.G(`Add a new server to your configuration so that it can be managed by Abra. Abra relies on the standard SSH command-line and ~/.ssh/config for client connection details. You must configure an entry per-host in your ~/.ssh/config @@ -35,8 +36,8 @@ for each server: If "--local" is passed, then Abra assumes that the current local server is intended as the target server. This is useful when you want to have your entire Co-op Cloud config located on the server itself, and not on your local -developer machine. The domain is then set to "default".`, - Example: " abra server add 1312.net", +developer machine. The domain is then set to "default".`), + Example: i18n.G(" abra server add 1312.net"), Args: cobra.RangeArgs(0, 1), ValidArgsFunction: func( cmd *cobra.Command, @@ -49,11 +50,11 @@ developer machine. The domain is then set to "default".`, }, Run: func(cmd *cobra.Command, args []string) { if len(args) > 0 && local { - log.Fatal("cannot use [server] and --local together") + log.Fatal(i18n.G("cannot use [server] and --local together")) } if len(args) == 0 && !local { - log.Fatal("missing argument or --local/-l flag") + log.Fatal(i18n.G("missing argument or --local/-l flag")) } name := "default" @@ -72,7 +73,7 @@ developer machine. The domain is then set to "default".`, log.Fatal(err) } - log.Debugf("attempting to create client for %s", name) + log.Debug(i18n.G("attempting to create client for %s", name)) if _, err := client.New(name, timeout); err != nil { cleanUp(name) @@ -80,9 +81,9 @@ developer machine. The domain is then set to "default".`, } if created { - log.Info("local server successfully added") + log.Info(i18n.G("local server successfully added")) } else { - log.Warn("local server already exists") + log.Warn(i18n.G("local server already exists")) } return @@ -96,27 +97,27 @@ developer machine. The domain is then set to "default".`, created, err := newContext(name) if err != nil { cleanUp(name) - log.Fatalf("unable to create local context: %s", err) + log.Fatal(i18n.G("unable to create local context: %s", err)) } - log.Debugf("attempting to create client for %s", name) + log.Debug(i18n.G("attempting to create client for %s", name)) if _, err := client.New(name, timeout); err != nil { cleanUp(name) - log.Fatalf("ssh %s error: %s", name, sshPkg.Fatal(name, err)) + log.Fatal(i18n.G("ssh %s error: %s", name, sshPkg.Fatal(name, err))) } if created { - log.Infof("%s successfully added", name) + log.Info(i18n.G("%s successfully added", name)) if _, err := dns.EnsureIPv4(name); err != nil { - log.Warnf("unable to resolve IPv4 for %s", name) + log.Warn(i18n.G("unable to resolve IPv4 for %s", name)) } return } - log.Warnf("%s already exists", name) + log.Warn(i18n.G("%s already exists", name)) }, } @@ -124,7 +125,7 @@ developer machine. The domain is then set to "default".`, // "server add" attempt. func cleanUp(name string) { if name != "default" { - log.Debugf("serverAdd: cleanUp: cleaning up context for %s", name) + log.Debug(i18n.G("serverAdd: cleanUp: cleaning up context for %s", name)) if err := client.DeleteContext(name); err != nil { log.Fatal(err) } @@ -133,16 +134,16 @@ func cleanUp(name string) { serverDir := filepath.Join(config.SERVERS_DIR, name) files, err := config.GetAllFilesInDirectory(serverDir) if err != nil { - log.Fatalf("serverAdd: cleanUp: unable to list files in %s: %s", serverDir, err) + log.Fatal(i18n.G("serverAdd: cleanUp: unable to list files in %s: %s", serverDir, err)) } if len(files) > 0 { - log.Debugf("serverAdd: cleanUp: %s is not empty, aborting cleanup", serverDir) + log.Debug(i18n.G("serverAdd: cleanUp: %s is not empty, aborting cleanup", serverDir)) return } if err := os.RemoveAll(serverDir); err != nil { - log.Fatalf("serverAdd: cleanUp: failed to remove %s: %s", serverDir, err) + log.Fatal(i18n.G("serverAdd: cleanUp: failed to remove %s: %s", serverDir, err)) } } @@ -159,12 +160,12 @@ func newContext(name string) (bool, error) { for _, context := range contexts { if context.Name == name { - log.Debugf("context for %s already exists", name) + log.Debug(i18n.G("context for %s already exists", name)) return false, nil } } - log.Debugf("creating context with domain %s", name) + log.Debugf(i18n.G("creating context with domain %s", name)) if err := client.CreateContext(name); err != nil { return false, nil @@ -180,7 +181,7 @@ func createServerDir(name string) (bool, error) { return false, err } - log.Debugf("server dir for %s already created", name) + log.Debug(i18n.G("server dir for %s already created", name)) return false, nil } @@ -195,9 +196,9 @@ var ( func init() { ServerAddCommand.Flags().BoolVarP( &local, - "local", - "l", + i18n.G("local"), + i18n.G("l"), false, - "use local server", + i18n.G("use local server"), ) } diff --git a/cli/server/list.go b/cli/server/list.go index dd3fd211..b7df081f 100644 --- a/cli/server/list.go +++ b/cli/server/list.go @@ -8,15 +8,16 @@ import ( "coopcloud.tech/abra/pkg/config" contextPkg "coopcloud.tech/abra/pkg/context" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/docker/cli/cli/connhelper/ssh" "github.com/spf13/cobra" ) var ServerListCommand = &cobra.Command{ - Use: "list [flags]", - Aliases: []string{"ls"}, - Short: "List managed servers", + Use: i18n.G("list [flags]"), + Aliases: []string{i18n.G("ls")}, + Short: i18n.G("List managed servers"), Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { dockerContextStore := contextPkg.NewDefaultDockerContextStore() @@ -30,7 +31,7 @@ var ServerListCommand = &cobra.Command{ log.Fatal(err) } - headers := []string{"NAME", "HOST"} + headers := []string{i18n.G("NAME"), i18n.G("HOST")} table.Headers(headers...) serverNames, err := config.ReadServerNames() @@ -55,7 +56,7 @@ var ServerListCommand = &cobra.Command{ } if sp.Host == "" { - sp.Host = "unknown" + sp.Host = i18n.G("unknown") } row = []string{serverName, sp.Host} @@ -65,9 +66,9 @@ var ServerListCommand = &cobra.Command{ if len(row) == 0 { if serverName == "default" { - row = []string{serverName, "local"} + row = []string{serverName, i18n.G("local")} } else { - row = []string{serverName, "unknown"} + row = []string{serverName, i18n.G("unknown")} } rows = append(rows, row) } @@ -78,7 +79,7 @@ var ServerListCommand = &cobra.Command{ if internal.MachineReadable { out, err := formatter.ToJSON(headers, rows) if err != nil { - log.Fatal("unable to render to JSON: %s", err) + log.Fatal(i18n.G("unable to render to JSON: %s", err)) } fmt.Println(out) @@ -95,9 +96,9 @@ var ServerListCommand = &cobra.Command{ func init() { ServerListCommand.Flags().BoolVarP( &internal.MachineReadable, - "machine", - "m", + i18n.G("machine"), + i18n.G("m"), false, - "print machine-readable output", + i18n.G("print machine-readable output"), ) } diff --git a/cli/server/prune.go b/cli/server/prune.go index 7a4e5c25..1a097714 100644 --- a/cli/server/prune.go +++ b/cli/server/prune.go @@ -5,19 +5,20 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/docker/docker/api/types/filters" "github.com/spf13/cobra" ) var ServerPruneCommand = &cobra.Command{ - Use: "prune [flags]", - Aliases: []string{"p"}, - Short: "Prune resources on a server", - Long: `Prunes unused containers, networks, and dangling images. + Use: i18n.G("prune [flags]"), + Aliases: []string{i18n.G("p")}, + Short: i18n.G("Prune resources on a server"), + Long: i18n.G(`Prunes unused containers, networks, and dangling images. Use "--volumes/-v" to remove volumes that are not associated with a deployed -app. This can result in unwanted data loss if not used carefully.`, +app. This can result in unwanted data loss if not used carefully.`), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -41,18 +42,18 @@ app. This can result in unwanted data loss if not used carefully.`, } cntSpaceReclaimed := formatter.ByteCountSI(cr.SpaceReclaimed) - log.Infof("containers pruned: %d; space reclaimed: %s", len(cr.ContainersDeleted), cntSpaceReclaimed) + log.Info(i18n.G("containers pruned: %d; space reclaimed: %s", len(cr.ContainersDeleted), cntSpaceReclaimed)) nr, err := cl.NetworksPrune(cmd.Context(), filterArgs) if err != nil { log.Fatal(err) } - log.Infof("networks pruned: %d", len(nr.NetworksDeleted)) + log.Info(i18n.G("networks pruned: %d", len(nr.NetworksDeleted))) pruneFilters := filters.NewArgs() if allFilter { - log.Debugf("removing all images, not only dangling ones") + log.Debug(i18n.G("removing all images, not only dangling ones")) pruneFilters.Add("dangling", "false") } @@ -62,7 +63,7 @@ app. This can result in unwanted data loss if not used carefully.`, } imgSpaceReclaimed := formatter.ByteCountSI(ir.SpaceReclaimed) - log.Infof("images pruned: %d; space reclaimed: %s", len(ir.ImagesDeleted), imgSpaceReclaimed) + log.Info(i18n.G("images pruned: %d; space reclaimed: %s", len(ir.ImagesDeleted), imgSpaceReclaimed)) if volumesFilter { vr, err := cl.VolumesPrune(cmd.Context(), filterArgs) @@ -71,7 +72,7 @@ app. This can result in unwanted data loss if not used carefully.`, } volSpaceReclaimed := formatter.ByteCountSI(vr.SpaceReclaimed) - log.Infof("volumes pruned: %d; space reclaimed: %s", len(vr.VolumesDeleted), volSpaceReclaimed) + log.Info(i18n.G("volumes pruned: %d; space reclaimed: %s", len(vr.VolumesDeleted), volSpaceReclaimed)) } return @@ -86,17 +87,17 @@ var ( func init() { ServerPruneCommand.Flags().BoolVarP( &allFilter, - "all", - "a", + i18n.G("all"), + i18n.G("a"), false, - "remove all unused images", + i18n.G("remove all unused images"), ) ServerPruneCommand.Flags().BoolVarP( &volumesFilter, - "volumes", - "v", + i18n.G("volumes"), + i18n.G("v"), false, - "remove volumes", + i18n.G("remove volumes"), ) } diff --git a/cli/server/remove.go b/cli/server/remove.go index 4e79643f..db49a980 100644 --- a/cli/server/remove.go +++ b/cli/server/remove.go @@ -8,19 +8,20 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/config" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/spf13/cobra" ) var ServerRemoveCommand = &cobra.Command{ - Use: "remove [flags]", - Aliases: []string{"rm"}, - Short: "Remove a managed server", - Long: `Remove a managed server. + Use: i18n.G("remove [flags]"), + Aliases: []string{i18n.G("rm")}, + Short: i18n.G("Remove a managed server"), + Long: i18n.G(`Remove a managed server. Abra will remove the internal bookkeeping ($ABRA_DIR/servers/...) and underlying client connection context. This server will then be lost in time, -like tears in rain.`, +like tears in rain.`), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -39,7 +40,7 @@ like tears in rain.`, log.Fatal(err) } - log.Infof("%s is now lost in time, like tears in rain", serverName) + log.Info(i18n.G("%s is now lost in time, like tears in rain", serverName)) return }, diff --git a/cli/server/server.go b/cli/server/server.go index a9876aba..868a439d 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -1,10 +1,13 @@ package server -import "github.com/spf13/cobra" +import ( + "coopcloud.tech/abra/pkg/i18n" + "github.com/spf13/cobra" +) // ServerCommand defines the `abra server` command and its subcommands var ServerCommand = &cobra.Command{ - Use: "server [cmd] [args] [flags]", - Aliases: []string{"s"}, - Short: "Manage servers", + Use: i18n.G("server [cmd] [args] [flags]"), + Aliases: []string{i18n.G("s")}, + Short: i18n.G("Manage servers"), } diff --git a/cli/updater/updater.go b/cli/updater/updater.go index e0979107..2c59cb48 100644 --- a/cli/updater/updater.go +++ b/cli/updater/updater.go @@ -2,6 +2,7 @@ package updater import ( "context" + "errors" "fmt" "os" "strconv" @@ -11,6 +12,7 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/envfile" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/lint" "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/abra/pkg/upstream/convert" @@ -30,14 +32,14 @@ const SERVER = "localhost" // NotifyCommand checks for available upgrades. var NotifyCommand = &cobra.Command{ - Use: "notify [flags]", - Aliases: []string{"n"}, - Short: "Check for available upgrades", - Long: `Notify on new versions for deployed apps. + Use: i18n.G("notify [flags]"), + Aliases: []string{i18n.G("n")}, + Short: i18n.G("Check for available upgrades"), + Long: i18n.G(`Notify on new versions for deployed apps. If a new patch/minor version is available, a notification is printed. -Use "--major/-m" to include new major versions.`, +Use "--major/-m" to include new major versions.`), Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { cl, err := client.New("default") @@ -69,10 +71,10 @@ Use "--major/-m" to include new major versions.`, // UpgradeCommand upgrades apps. var UpgradeCommand = &cobra.Command{ - Use: "upgrade [[stack] [recipe] | --all] [flags]", - Aliases: []string{"u"}, - Short: "Upgrade apps", - Long: `Upgrade an app by specifying stack name and recipe. + Use: i18n.G("upgrade [[stack] [recipe] | --all] [flags]"), + Aliases: []string{i18n.G("u")}, + Short: i18n.G("Upgrade apps"), + Long: i18n.G(`Upgrade an app by specifying stack name and recipe. Use "--all" to upgrade every deployed app. @@ -83,7 +85,7 @@ available, the app is upgraded. To include major versions use the "--major/-m" flag. You probably don't want that as it will break things. Only apps that are not deployed with "--chaos/-C" are upgraded, to update chaos deployments use the "--chaos/-C" flag. Use it -with care.`, +with care.`), Args: cobra.RangeArgs(0, 2), // TODO(d1): complete stack/recipe // ValidArgsFunction: func( @@ -98,7 +100,7 @@ with care.`, } if !updateAll && len(args) != 2 { - log.Fatal("missing arguments or --all/-a flag") + log.Fatal(i18n.G("missing arguments or --all/-a flag")) } if !updateAll { @@ -150,7 +152,7 @@ func getLabel(cl *dockerclient.Client, stackName string, label string) (string, } } - log.Debugf("no %s label found for %s", label, stackName) + log.Debug(i18n.G("no %s label found for %s", label, stackName)) return "", nil } @@ -171,7 +173,7 @@ func getBoolLabel(cl *dockerclient.Client, stackName string, label string) (bool return value, nil } - log.Debugf("boolean label %s could not be found for %s, set default to false.", label, stackName) + log.Debug(i18n.G("boolean label %s could not be found for %s, set default to false.", label, stackName)) return false, nil } @@ -192,12 +194,12 @@ func getEnv(cl *dockerclient.Client, stackName string) (envfile.AppEnv, error) { for _, envString := range envList { splitString := strings.SplitN(envString, "=", 2) if len(splitString) != 2 { - log.Debugf("can't separate key from value: %s (this variable is probably unset)", envString) + log.Debug(i18n.G("can't separate key from value: %s (this variable is probably unset)", envString)) continue } k := splitString[0] v := splitString[1] - log.Debugf("for %s read env %s with value: %s from docker service", stackName, k, v) + log.Debugf(i18n.G("for %s read env %s with value: %s from docker service", stackName, k, v)) envMap[k] = v } } @@ -219,14 +221,14 @@ func getLatestUpgrade(cl *dockerclient.Client, stackName string, recipeName stri } if len(availableUpgrades) == 0 { - log.Debugf("no available upgrades for %s", stackName) + log.Debugf(i18n.G("no available upgrades for %s", stackName)) return "", nil } var chosenUpgrade string if len(availableUpgrades) > 0 { chosenUpgrade = availableUpgrades[len(availableUpgrades)-1] - log.Infof("%s (%s) can be upgraded from version %s to %s", stackName, recipeName, deployedVersion, chosenUpgrade) + log.Info(i18n.G("%s (%s) can be upgraded from version %s to %s", stackName, recipeName, deployedVersion, chosenUpgrade)) } return chosenUpgrade, nil @@ -234,7 +236,7 @@ func getLatestUpgrade(cl *dockerclient.Client, stackName string, recipeName stri // getDeployedVersion returns the currently deployed version of an app. func getDeployedVersion(cl *dockerclient.Client, stackName string, recipeName string) (string, error) { - log.Debugf("retrieve deployed version whether %s is already deployed", stackName) + log.Debug(i18n.G("retrieve deployed version whether %s is already deployed", stackName)) deployMeta, err := stack.IsDeployed(context.Background(), cl, stackName) if err != nil { @@ -242,11 +244,11 @@ func getDeployedVersion(cl *dockerclient.Client, stackName string, recipeName st } if !deployMeta.IsDeployed { - return "", fmt.Errorf("%s is not deployed?", stackName) + return "", errors.New(i18n.G("%s is not deployed?", stackName)) } if deployMeta.Version == "unknown" { - return "", fmt.Errorf("failed to determine deployed version of %s", stackName) + return "", errors.New(i18n.G("failed to determine deployed version of %s", stackName)) } return deployMeta.Version, nil @@ -268,7 +270,7 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName } if len(versions) == 0 { - log.Warnf("no published releases for %s in the recipe catalogue?", recipeName) + log.Warn(i18n.G("no published releases for %s in the recipe catalogue?", recipeName)) return nil, nil } @@ -294,7 +296,7 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName } } - log.Debugf("available updates for %s: %s", stackName, availableUpgrades) + log.Debug(i18n.G("available updates for %s: %s", stackName, availableUpgrades)) return availableUpgrades, nil } @@ -371,7 +373,7 @@ func createDeployConfig(r recipe.Recipe, stackName string, env envfile.AppEnv) ( // tryUpgrade performs the upgrade if all the requirements are fulfilled. func tryUpgrade(cl *dockerclient.Client, stackName, recipeName string) error { if recipeName == "" { - log.Debugf("don't update %s due to missing recipe name", stackName) + log.Debug(i18n.G("don't update %s due to missing recipe name", stackName)) return nil } @@ -381,7 +383,7 @@ func tryUpgrade(cl *dockerclient.Client, stackName, recipeName string) error { } if chaos && !internal.Chaos { - log.Debugf("don't update %s due to chaos deployment", stackName) + log.Debug(i18n.G("don't update %s due to chaos deployment", stackName)) return nil } @@ -391,7 +393,7 @@ func tryUpgrade(cl *dockerclient.Client, stackName, recipeName string) error { } if !updatesEnabled { - log.Debugf("don't update %s due to disabled auto updates or missing ENABLE_AUTO_UPDATE env", stackName) + log.Debug(i18n.G("don't update %s due to disabled auto updates or missing ENABLE_AUTO_UPDATE env", stackName)) return nil } @@ -401,7 +403,7 @@ func tryUpgrade(cl *dockerclient.Client, stackName, recipeName string) error { } if upgradeVersion == "" { - log.Debugf("don't update %s due to no new version", stackName) + log.Debug(i18n.G("don't update %s due to no new version", stackName)) return nil } @@ -439,7 +441,7 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName, upgradeVersion stri return err } - log.Infof("upgrade %s (%s) to version %s", stackName, recipeName, upgradeVersion) + log.Info(i18n.G("upgrade %s (%s) to version %s", stackName, recipeName, upgradeVersion)) serviceNames, err := appPkg.GetAppServiceNames(app.Name) if err != nil { @@ -466,9 +468,9 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName, upgradeVersion stri func newKadabraApp(version, commit string) *cobra.Command { rootCmd := &cobra.Command{ - Use: "kadabra [cmd] [flags]", + Use: i18n.G("kadabra [cmd] [flags]"), Version: fmt.Sprintf("%s-%s", version, commit[:7]), - Short: "The Co-op Cloud auto-updater 🤖 🚀", + Short: i18n.G("The Co-op Cloud auto-updater 🤖 🚀"), PersistentPreRun: func(cmd *cobra.Command, args []string) { log.Logger.SetStyles(charmLog.DefaultStyles()) charmLog.SetDefault(log.Logger) @@ -479,18 +481,24 @@ func newKadabraApp(version, commit string) *cobra.Command { log.SetReportCaller(true) } - log.Debugf("kadabra version %s, commit %s", version, commit) + log.Debug(i18n.G("kadabra version %s, commit %s", version, commit)) }, } rootCmd.PersistentFlags().BoolVarP( - &internal.Debug, "debug", "d", false, - "show debug messages", + &internal.Debug, + i18n.G("debug"), + i18n.G("d"), + false, + i18n.G("show debug messages"), ) rootCmd.PersistentFlags().BoolVarP( - &internal.NoInput, "no-input", "n", false, - "toggle non-interactive mode", + &internal.NoInput, + i18n.G("no-input"), + i18n.G("n"), + false, + i18n.G("toggle non-interactive mode"), ) rootCmd.AddCommand( @@ -526,25 +534,25 @@ func init() { UpgradeCommand.Flags().BoolVarP( &internal.Chaos, - "chaos", - "C", + i18n.G("chaos"), + i18n.G("C"), false, - "ignore uncommitted recipes changes", + i18n.G("ignore uncommitted recipes changes"), ) UpgradeCommand.Flags().BoolVarP( &includeMajorUpdates, - "major", - "m", + i18n.G("major"), + i18n.G("m"), false, - "check for major updates", + i18n.G("check for major updates"), ) UpgradeCommand.Flags().BoolVarP( &updateAll, - "all", - "a", + i18n.G("all"), + i18n.G("a"), false, - "update all deployed apps", + i18n.G("update all deployed apps"), ) } diff --git a/cli/upgrade.go b/cli/upgrade.go index aafa1310..74bb52c2 100644 --- a/cli/upgrade.go +++ b/cli/upgrade.go @@ -7,22 +7,23 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/log" + "coopcloud.tech/abra/pkg/i18n" "github.com/spf13/cobra" ) // UpgradeCommand upgrades abra in-place. var UpgradeCommand = &cobra.Command{ - Use: "upgrade [flags]", + Use: i18n.G("upgrade [flags]"), Aliases: []string{"u"}, - Short: "Upgrade abra", - Long: `Upgrade abra in-place with the latest stable or release candidate. + Short: i18n.G("Upgrade abra"), + Long: i18n.G(`Upgrade abra in-place with the latest stable or release candidate. By default, the latest stable release is downloaded. Use "--rc/-r" 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 --rc", +for the testing efforts 💗`), + Example: i18n.G(" abra upgrade --rc"), Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { mainURL := "https://install.abra.coopcloud.tech" @@ -33,7 +34,7 @@ for the testing efforts 💗`, c = exec.Command("bash", "-c", fmt.Sprintf("wget -q -O- %s | bash -s -- --rc", releaseCandidateURL)) } - log.Debugf("attempting to run %s", c) + log.Debugf(i18n.G("attempting to run %s", c)) if err := internal.RunCmd(c); err != nil { log.Fatal(err) @@ -51,6 +52,6 @@ func init() { "rc", "r", false, - "install release candidate (may contain bugs)", + i18n.G("install release candidate (may contain bugs)"), ) } diff --git a/go.mod b/go.mod index be78dc17..8af1e328 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,6 @@ require ( require ( dario.cat/mergo v1.0.2 // indirect - github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/BurntSushi/toml v1.5.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect @@ -52,14 +51,12 @@ require ( github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect github.com/docker/go-connections v0.6.0 // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect @@ -85,11 +82,9 @@ require ( github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/miekg/pkcs11 v1.1.1 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/go-archive v0.1.0 // indirect github.com/moby/sys/atomicwriter v0.1.0 // indirect - github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/user v0.4.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect github.com/morikuni/aec v1.0.0 // indirect @@ -100,7 +95,6 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/runc v1.1.13 // indirect github.com/opencontainers/runtime-spec v1.1.0 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect github.com/pjbgf/sha1cd v0.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.6.2 // indirect diff --git a/go.sum b/go.sum index ed1015b9..ceab1712 100644 --- a/go.sum +++ b/go.sum @@ -22,21 +22,13 @@ cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIA cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb h1:Ws6WEwKXeaYEkfdkX6AqX1XLPuaCeyStEtxbmEJPllk= -coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb/go.mod h1:ESVm0wQKcbcFi06jItF3rI7enf4Jt2PvbkWpDDHk1DQ= -coopcloud.tech/tagcmp v0.0.0-20250427094623-9ea3bbbde8e5 h1:tphJCjFJw9fdjyKnbU0f7f3z5KtYE8VbUcAfu+oHKg8= -coopcloud.tech/tagcmp v0.0.0-20250427094623-9ea3bbbde8e5/go.mod h1:ESVm0wQKcbcFi06jItF3rI7enf4Jt2PvbkWpDDHk1DQ= coopcloud.tech/tagcmp v0.0.0-20250818180036-0ec1b205b5ca h1:gSD53tBAsbIGq4SnFfq+mEep6foekQ2a5ea7b38qkm0= coopcloud.tech/tagcmp v0.0.0-20250818180036-0ec1b205b5ca/go.mod h1:ESVm0wQKcbcFi06jItF3rI7enf4Jt2PvbkWpDDHk1DQ= -dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= -dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c h1:oeKnUB79PKYD8D0/unYuu7MRcWryQQWOns8+JL+acrs= git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c/go.mod h1:fQuhwrpg6qb9NlFXKYi/LysWu1wxjraS8sxyW12CUF0= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= @@ -57,8 +49,6 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -89,8 +79,6 @@ github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb0 github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= -github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -98,7 +86,6 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -133,11 +120,8 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0 h1:s7+5BfS4WFJoVF9pnB8kBk03S7pZXRdKamnV0FOl5Sc= github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -145,29 +129,18 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI= -github.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo= github.com/charmbracelet/bubbletea v1.3.6 h1:VkHIxPJQeDt0aFJIsVxw8BQdh/F/L2KKZGsK6et5taU= github.com/charmbracelet/bubbletea v1.3.6/go.mod h1:oQD9VCRQFF8KplacJLo28/jofOI2ToOfGYeFgBBxHOc= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= -github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL3m+AxCzDz40= -github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0= github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI= github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= -github.com/charmbracelet/log v0.4.1 h1:6AYnoHKADkghm/vt4neaNEXkxcXLSV2g1rdyFDOpTyk= -github.com/charmbracelet/log v0.4.1/go.mod h1:pXgyTsqsVu4N9hGdHmQ0xEA4RsXof402LX9ZgiITn2I= github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig= github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw= -github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= -github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ= github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= @@ -191,10 +164,7 @@ github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ= github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= -github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= -github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -316,7 +286,6 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= @@ -347,8 +316,6 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v28.0.1+incompatible h1:g0h5NQNda3/CxIsaZfH4Tyf6vpxFth7PYl3hgCPOKzs= -github.com/docker/cli v28.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v28.3.3+incompatible h1:fp9ZHAr1WWPGdIWBM1b3zLtgCF+83gRdVMTJsUeiyAo= github.com/docker/cli v28.3.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= @@ -357,8 +324,6 @@ github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4Kfc github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0= -github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= @@ -367,8 +332,6 @@ github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= @@ -413,8 +376,6 @@ github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= @@ -430,8 +391,6 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60= -github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k= github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM= github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -447,8 +406,6 @@ github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -464,11 +421,8 @@ github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8 github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-sql-driver/mysql v1.3.0 h1:pgwjLi/dvffoP9aabwkT3AKpXQM93QARkjFhDDqC1UE= github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= @@ -522,7 +476,6 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93 h1:jc2UWq7CbdszqeH6qu1ougXMIUBfSy8Pbh/anURYbGI= github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -575,13 +528,9 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -592,13 +541,10 @@ github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVH github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= -github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= @@ -615,9 +561,7 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8 h1:CZkYfurY6KGhVtlalI4QwQ6T0Cu6iuY3e0x5RLu96WE= github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= -github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d h1:jRQLvyVGL+iVtDElaEIDdKwpPqUIZJfzkNLV34htpEc= github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -670,7 +614,6 @@ github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -710,8 +653,6 @@ github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= @@ -725,8 +666,6 @@ github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtl github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= -github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -734,8 +673,6 @@ github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiT github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0= github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= -github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= -github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= @@ -817,15 +754,10 @@ github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqi github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= -github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pjbgf/sha1cd v0.4.0 h1:NXzbL1RvjTUi6kgYZCX3fPwwl27Q1LJndxtUDVfJGRY= github.com/pjbgf/sha1cd v0.4.0/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -843,8 +775,6 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk= -github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc= github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -852,8 +782,6 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1: github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= @@ -862,8 +790,6 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= -github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -877,8 +803,6 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0= github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= @@ -890,7 +814,6 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -901,8 +824,6 @@ github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8G github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= -github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -923,10 +844,8 @@ github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:s github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= -github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= @@ -935,7 +854,6 @@ github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHN github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -943,12 +861,10 @@ github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bd github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= -github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -1023,47 +939,27 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.37.0 h1:zG8GlgXCJQd5BU98C0hZnBbElszTmUgCNCfYneaDL0A= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.37.0/go.mod h1:hOfBCz8kv/wuq73Mx2H2QnWokh/kHZxkh6SNF2bdKtw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 h1:EtFWSnwW9hGObjkIdmlnWSydO+Qs8OwzfzXLUPg4xOc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0/go.mod h1:QjUEoiGCPkvFZ/MjK6ZZfNOS6mfVEVKYE99dFhuN2LI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= -go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1090,8 +986,6 @@ golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1104,10 +998,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= -golang.org/x/exp v0.0.0-20250811191247-51f88131bc50 h1:3yiSh9fhy5/RhCSntf4Sy0Tnx50DmMpQ4MQdKKk4yg4= -golang.org/x/exp v0.0.0-20250811191247-51f88131bc50/go.mod h1:rT6SFzZ7oxADUDx58pcaKFTcZ+inxAa9fTrYx/uVYwg= golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE= golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -1173,8 +1063,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1194,8 +1082,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1275,17 +1161,12 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1297,8 +1178,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1307,8 +1186,6 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1404,12 +1281,8 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 h1:IFnXJq3UPB3oBREOodn1v1aGQeZYQclEmvWRMN0PSsY= -google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:c8q6Z6OCqnfVIqUFJkCzKcrj8eCvUrz+K4KRzSTuANg= google.golang.org/genproto/googleapis/api v0.0.0-20250811230008-5f3141c8851a h1:DMCgtIAIQGZqJXMVzJF4MV8BlWoJh2ZuFiRdAleyr58= google.golang.org/genproto/googleapis/api v0.0.0-20250811230008-5f3141c8851a/go.mod h1:y2yVLIE/CSMCPXaHnSKXxu1spLPnglFLegmgdY23uuE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a h1:tPE/Kp+x9dMSwUm/uM0JKK0IfdiJkwAbSMSeZBXXJXc= google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -1431,8 +1304,6 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= -google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1448,13 +1319,10 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII= gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1470,7 +1338,6 @@ gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKW gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx73duwUwM= gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -1491,7 +1358,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= diff --git a/locales/default.pot b/locales/default.pot deleted file mode 100644 index 39987c8b..00000000 --- a/locales/default.pot +++ /dev/null @@ -1,12 +0,0 @@ -msgid "" -msgstr "" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: \n" -"X-Generator: xgotext\n" - -#: app.go:11 -msgid "Manage apps" -msgstr "" \ No newline at end of file diff --git a/locales/es/LC_MESSAGES/default.po b/locales/es/LC_MESSAGES/default.po deleted file mode 100644 index a50fdda0..00000000 --- a/locales/es/LC_MESSAGES/default.po +++ /dev/null @@ -1,20 +0,0 @@ -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-08-04 14:15+0000\n" -"PO-Revision-Date: 2025-08-04 14:15+0000\n" -"Last-Translator: 3wordchant <3wc.coopcloud@doesthisthing.work>\n" -"Language-Team: Spanish \n" -"Language: es\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: ENCODING\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.12.2\n" - -#: app.go:11 -msgid "Manage apps" -msgstr "Gestionar aplicaciones" diff --git a/pkg/app/app.go b/pkg/app/app.go index f7b7f27f..cca0e1ca 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -2,6 +2,7 @@ package app import ( "bufio" + "errors" "fmt" "os" "path" @@ -13,6 +14,7 @@ import ( "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/abra/pkg/upstream/convert" "coopcloud.tech/abra/pkg/upstream/stack" @@ -36,7 +38,7 @@ func Get(appName string) (App, error) { return App{}, err } - log.Debugf("loaded app %s: %s", appName, app) + log.Debug(i18n.G("loaded app %s: %s", appName, app)) return app, nil } @@ -47,7 +49,7 @@ func Get(appName string) (App, error) { func GetApp(apps AppFiles, name AppName) (App, error) { appFile, exists := apps[name] if !exists { - return App{}, fmt.Errorf("cannot find app with name %s", name) + return App{}, errors.New(i18n.G("cannot find app with name %s", name)) } app, err := ReadAppEnvFile(appFile, name) @@ -136,7 +138,7 @@ func StackName(appName string) string { stackName := SanitiseAppName(appName) if len(stackName) > config.MAX_SANITISED_APP_NAME_LENGTH { - log.Debugf("trimming %s to %s to avoid runtime limits", stackName, stackName[:config.MAX_SANITISED_APP_NAME_LENGTH]) + log.Debug(i18n.G("trimming %s to %s to avoid runtime limits", stackName, stackName[:config.MAX_SANITISED_APP_NAME_LENGTH])) stackName = stackName[:config.MAX_SANITISED_APP_NAME_LENGTH] } @@ -243,12 +245,12 @@ func (a ByName) Less(i, j int) bool { func ReadAppEnvFile(appFile AppFile, name AppName) (App, error) { env, err := envfile.ReadEnv(appFile.Path) if err != nil { - return App{}, fmt.Errorf("env file for %s couldn't be read: %s", name, err.Error()) + return App{}, errors.New(i18n.G("env file for %s couldn't be read: %s", name, err.Error())) } app, err := NewApp(env, name, appFile) if err != nil { - return App{}, fmt.Errorf("env file for %s has issues: %s", name, err.Error()) + return App{}, errors.New(i18n.G("env file for %s has issues: %s", name, err.Error())) } return app, nil @@ -262,7 +264,7 @@ func NewApp(env envfile.AppEnv, name string, appFile AppFile) (App, error) { if !exists { recipeName, exists = env["TYPE"] if !exists { - return App{}, fmt.Errorf("%s is missing the TYPE env var?", name) + return App{}, errors.New(i18n.G("%s is missing the TYPE env var?", name)) } } @@ -290,13 +292,13 @@ func LoadAppFiles(servers ...string) (AppFiles, error) { } } - log.Debugf("collecting metadata from %v servers: %s", len(servers), strings.Join(servers, ", ")) + log.Debug(i18n.G("collecting metadata from %v servers: %s", len(servers), strings.Join(servers, ", "))) for _, server := range servers { serverDir := path.Join(config.SERVERS_DIR, server) files, err := config.GetAllFilesInDirectory(serverDir) if err != nil { - return appFiles, fmt.Errorf("server %s doesn't exist? Run \"abra server ls\" to check", server) + return appFiles, errors.New(i18n.G("server %s doesn't exist? Run \"abra server ls\" to check", server)) } for _, file := range files { @@ -375,7 +377,7 @@ func TemplateAppEnvSample(r recipe.Recipe, appName, server, domain string) error appEnvPath := path.Join(config.ABRA_DIR, "servers", server, fmt.Sprintf("%s.env", appName)) if _, err := os.Stat(appEnvPath); !os.IsNotExist(err) { - return fmt.Errorf("%s already exists?", appEnvPath) + return errors.New(i18n.G("%s already exists?", appEnvPath)) } err = os.WriteFile(appEnvPath, envSample, 0o664) @@ -395,7 +397,7 @@ func TemplateAppEnvSample(r recipe.Recipe, appName, server, domain string) error return err } - log.Debugf("copied & templated %s to %s", r.SampleEnvPath, appEnvPath) + log.Debug(i18n.G("copied & templated %s to %s", r.SampleEnvPath, appEnvPath)) return nil } @@ -419,7 +421,7 @@ func GetAppStatuses(apps []App, MachineReadable bool) (map[string]map[string]str var bar *progressbar.ProgressBar if !MachineReadable { - bar = formatter.CreateProgressbar(len(servers), "querying remote servers...") + bar = formatter.CreateProgressbar(len(servers), i18n.G("querying remote servers...")) } ch := make(chan stack.StackStatus, len(servers)) @@ -482,7 +484,7 @@ func GetAppStatuses(apps []App, MachineReadable bool) (map[string]map[string]str } } - log.Debugf("retrieved app statuses: %s", statuses) + log.Debug(i18n.G("retrieved app statuses: %s", statuses)) return statuses, nil } @@ -496,7 +498,7 @@ func GetAppComposeConfig(recipe string, opts stack.Deploy, appEnv envfile.AppEnv return &composetypes.Config{}, err } - log.Debugf("retrieved %s for %s", compose.Filename, recipe) + log.Debug(i18n.G("retrieved %s for %s", compose.Filename, recipe)) return compose, nil } @@ -505,13 +507,13 @@ func GetAppComposeConfig(recipe string, opts stack.Deploy, appEnv envfile.AppEnv func ExposeAllEnv(stackName string, compose *composetypes.Config, appEnv envfile.AppEnv) { for _, service := range compose.Services { if service.Name == "app" { - log.Debugf("adding env vars to %s service config", stackName) + log.Debug(i18n.G("adding env vars to %s service config", stackName)) for k, v := range appEnv { _, exists := service.Environment[k] if !exists { value := v service.Environment[k] = &value - log.Debugf("%s: %s: %s", stackName, k, value) + log.Debug(i18n.G("%s: %s: %s", stackName, k, value)) } } } @@ -572,9 +574,9 @@ func ReadAbraShCmdNames(abraSh string) ([]string, error) { } if len(cmdNames) > 0 { - log.Debugf("read %s from %s", strings.Join(cmdNames, " "), abraSh) + log.Debug(i18n.G("read %s from %s", strings.Join(cmdNames, " "), abraSh)) } else { - log.Debugf("read 0 command names from %s", abraSh) + log.Debug(i18n.G("read 0 command names from %s", abraSh)) } return cmdNames, nil @@ -617,7 +619,7 @@ func (a App) WipeRecipeVersion() error { log.Fatal(err) } - log.Debugf("version wiped from %s.env", a.Domain) + log.Debug(i18n.G("version wiped from %s.env", a.Domain)) return nil } @@ -674,13 +676,13 @@ func (a App) WriteRecipeVersion(version string, dryRun bool) error { log.Fatal(err) } } else { - log.Debugf("skipping writing version %s because dry run", version) + log.Debug(i18n.G("skipping writing version %s because dry run", version)) } if !skipped { - log.Debugf("version %s saved to %s.env", version, a.Domain) + log.Debug(i18n.G("version %s saved to %s.env", version, a.Domain)) } else { - log.Debugf("skipping version %s write as already exists in %s.env", version, a.Domain) + log.Debug(i18n.G("skipping version %s write as already exists in %s.env", version, a.Domain)) } return nil diff --git a/pkg/app/compose.go b/pkg/app/compose.go index 1bc7b461..dd5070b1 100644 --- a/pkg/app/compose.go +++ b/pkg/app/compose.go @@ -5,6 +5,7 @@ import ( "strconv" "coopcloud.tech/abra/pkg/envfile" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" composetypes "github.com/docker/cli/cli/compose/types" ) @@ -14,7 +15,7 @@ import ( func SetRecipeLabel(compose *composetypes.Config, stackName string, recipe string) { for _, service := range compose.Services { if service.Name == "app" { - log.Debugf("set recipe label 'coop-cloud.%s.recipe' to %s for %s", stackName, recipe, stackName) + log.Debug(i18n.G("set recipe label 'coop-cloud.%s.recipe' to %s for %s", stackName, recipe, stackName)) labelKey := fmt.Sprintf("coop-cloud.%s.recipe", stackName) service.Deploy.Labels[labelKey] = recipe } @@ -26,7 +27,7 @@ func SetRecipeLabel(compose *composetypes.Config, stackName string, recipe strin func SetChaosLabel(compose *composetypes.Config, stackName string, chaos bool) { for _, service := range compose.Services { if service.Name == "app" { - log.Debugf("set label 'coop-cloud.%s.chaos' to %v for %s", stackName, chaos, stackName) + log.Debug(i18n.G("set label 'coop-cloud.%s.chaos' to %v for %s", stackName, chaos, stackName)) labelKey := fmt.Sprintf("coop-cloud.%s.chaos", stackName) service.Deploy.Labels[labelKey] = strconv.FormatBool(chaos) } @@ -37,7 +38,7 @@ func SetChaosLabel(compose *composetypes.Config, stackName string, chaos bool) { func SetChaosVersionLabel(compose *composetypes.Config, stackName string, chaosVersion string) { for _, service := range compose.Services { if service.Name == "app" { - log.Debugf("set label 'coop-cloud.%s.chaos-version' to %v for %s", stackName, chaosVersion, stackName) + log.Debug(i18n.G("set label 'coop-cloud.%s.chaos-version' to %v for %s", stackName, chaosVersion, stackName)) labelKey := fmt.Sprintf("coop-cloud.%s.chaos-version", stackName) service.Deploy.Labels[labelKey] = chaosVersion } @@ -47,7 +48,7 @@ func SetChaosVersionLabel(compose *composetypes.Config, stackName string, chaosV func SetVersionLabel(compose *composetypes.Config, stackName string, version string) { for _, service := range compose.Services { if service.Name == "app" { - log.Debugf("set label 'coop-cloud.%s.version' to %v for %s", stackName, version, stackName) + log.Debug(i18n.G("set label 'coop-cloud.%s.version' to %v for %s", stackName, version, stackName)) labelKey := fmt.Sprintf("coop-cloud.%s.version", stackName) service.Deploy.Labels[labelKey] = version } @@ -64,7 +65,7 @@ func SetUpdateLabel(compose *composetypes.Config, stackName string, appEnv envfi if !exists { enable_auto_update = "false" } - log.Debugf("set label 'coop-cloud.%s.autoupdate' to %s for %s", stackName, enable_auto_update, stackName) + log.Debug(i18n.G("set label 'coop-cloud.%s.autoupdate' to %s for %s", stackName, enable_auto_update, stackName)) labelKey := fmt.Sprintf("coop-cloud.%s.autoupdate", stackName) service.Deploy.Labels[labelKey] = enable_auto_update } @@ -76,13 +77,13 @@ func GetLabel(compose *composetypes.Config, stackName string, label string) stri for _, service := range compose.Services { if service.Name == "app" { labelKey := fmt.Sprintf("coop-cloud.%s.%s", stackName, label) - log.Debugf("get label '%s'", labelKey) + log.Debug(i18n.G("get label '%s'", labelKey)) if labelValue, ok := service.Deploy.Labels[labelKey]; ok { return labelValue } } } - log.Debugf("no %s label found for %s", label, stackName) + log.Debug(i18n.G("no %s label found for %s", label, stackName)) return "" } @@ -91,7 +92,7 @@ func GetTimeoutFromLabel(compose *composetypes.Config, stackName string) (int, e timeout := 50 // Default Timeout var err error = nil if timeoutLabel := GetLabel(compose, stackName, "timeout"); timeoutLabel != "" { - log.Debugf("timeout label: %s", timeoutLabel) + log.Debug(i18n.G("timeout label: %s", timeoutLabel)) timeout, err = strconv.Atoi(timeoutLabel) } return timeout, err diff --git a/pkg/autocomplete/autocomplete.go b/pkg/autocomplete/autocomplete.go index aafea741..03986c63 100644 --- a/pkg/autocomplete/autocomplete.go +++ b/pkg/autocomplete/autocomplete.go @@ -1,11 +1,11 @@ package autocomplete import ( - "fmt" "sort" "coopcloud.tech/abra/pkg/app" appPkg "coopcloud.tech/abra/pkg/app" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/recipe" "github.com/spf13/cobra" ) @@ -14,7 +14,7 @@ import ( func AppNameComplete() ([]string, cobra.ShellCompDirective) { appFiles, err := app.LoadAppFiles("") if err != nil { - err := fmt.Sprintf("autocomplete failed: %s", err) + err := i18n.G("autocomplete failed: %s", err) return []string{err}, cobra.ShellCompDirectiveError } @@ -29,7 +29,7 @@ func AppNameComplete() ([]string, cobra.ShellCompDirective) { func ServiceNameComplete(appName string) ([]string, cobra.ShellCompDirective) { serviceNames, err := app.GetAppServiceNames(appName) if err != nil { - err := fmt.Sprintf("autocomplete failed: %s", err) + err := i18n.G("autocomplete failed: %s", err) return []string{err}, cobra.ShellCompDirectiveError } @@ -40,7 +40,7 @@ func ServiceNameComplete(appName string) ([]string, cobra.ShellCompDirective) { func RecipeNameComplete() ([]string, cobra.ShellCompDirective) { catl, err := recipe.ReadRecipeCatalogue(false) if err != nil { - err := fmt.Sprintf("autocomplete failed: %s", err) + err := i18n.G("autocomplete failed: %s", err) return []string{err}, cobra.ShellCompDirectiveError } @@ -56,7 +56,7 @@ func RecipeNameComplete() ([]string, cobra.ShellCompDirective) { func RecipeVersionComplete(recipeName string) ([]string, cobra.ShellCompDirective) { catl, err := recipe.ReadRecipeCatalogue(true) if err != nil { - err := fmt.Sprintf("autocomplete failed: %s", err) + err := i18n.G("autocomplete failed: %s", err) return []string{err}, cobra.ShellCompDirectiveError } @@ -74,7 +74,7 @@ func RecipeVersionComplete(recipeName string) ([]string, cobra.ShellCompDirectiv func ServerNameComplete() ([]string, cobra.ShellCompDirective) { files, err := app.LoadAppFiles("") if err != nil { - err := fmt.Sprintf("autocomplete failed: %s", err) + err := i18n.G("autocomplete failed: %s", err) return []string{err}, cobra.ShellCompDirectiveError } @@ -90,13 +90,13 @@ func ServerNameComplete() ([]string, cobra.ShellCompDirective) { func CommandNameComplete(appName string) ([]string, cobra.ShellCompDirective) { app, err := app.Get(appName) if err != nil { - err := fmt.Sprintf("autocomplete failed: %s", err) + err := i18n.G("autocomplete failed: %s", err) return []string{err}, cobra.ShellCompDirectiveError } cmdNames, err := appPkg.ReadAbraShCmdNames(app.Recipe.AbraShPath) if err != nil { - err := fmt.Sprintf("autocomplete failed: %s", err) + err := i18n.G("autocomplete failed: %s", err) return []string{err}, cobra.ShellCompDirectiveError } @@ -111,7 +111,7 @@ func SecretComplete(recipeName string) ([]string, cobra.ShellCompDirective) { config, err := r.GetComposeConfig(nil) if err != nil { - err := fmt.Sprintf("autocomplete failed: %s", err) + err := i18n.G("autocomplete failed: %s", err) return []string{err}, cobra.ShellCompDirectiveError } diff --git a/pkg/catalogue/catalogue.go b/pkg/catalogue/catalogue.go index 76859616..cc043e52 100644 --- a/pkg/catalogue/catalogue.go +++ b/pkg/catalogue/catalogue.go @@ -1,6 +1,7 @@ package catalogue import ( + "errors" "fmt" "os" "path" @@ -8,6 +9,7 @@ import ( "coopcloud.tech/abra/pkg/config" gitPkg "coopcloud.tech/abra/pkg/git" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/go-git/go-git/v5" ) @@ -16,7 +18,7 @@ import ( func EnsureCatalogue() error { catalogueDir := path.Join(config.ABRA_DIR, "catalogue") if _, err := os.Stat(catalogueDir); err != nil && os.IsNotExist(err) { - log.Debugf("catalogue is missing, retrieving now") + log.Debug(i18n.G("catalogue is missing, retrieving now")) url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, config.CATALOGUE_JSON_REPO_NAME) if err := gitPkg.Clone(catalogueDir, url); err != nil { @@ -35,8 +37,7 @@ func EnsureIsClean() error { } if !isClean { - msg := "%s has locally unstaged changes? please commit/remove your changes before proceeding" - return fmt.Errorf(msg, config.CATALOGUE_DIR) + return errors.New(i18n.G("%s has locally unstaged changes? please commit/remove your changes before proceeding", config.CATALOGUE_DIR)) } return nil @@ -55,8 +56,7 @@ func EnsureUpToDate() error { } if len(remotes) == 0 { - msg := "cannot ensure %s is up-to-date, no git remotes configured" - log.Debugf(msg, config.CATALOGUE_DIR) + log.Debug(i18n.G("cannot ensure %s is up-to-date, no git remotes configured", config.CATALOGUE_DIR)) return nil } @@ -81,7 +81,7 @@ func EnsureUpToDate() error { } } - log.Debugf("fetched latest git changes for %s", config.CATALOGUE_DIR) + log.Debug(i18n.G("fetched latest git changes for %s", config.CATALOGUE_DIR)) return nil } diff --git a/pkg/client/client.go b/pkg/client/client.go index 315a2732..b73a2a2c 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -4,12 +4,12 @@ package client import ( "context" "errors" - "fmt" "net/http" "os" "time" contextPkg "coopcloud.tech/abra/pkg/context" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" sshPkg "coopcloud.tech/abra/pkg/ssh" commandconnPkg "coopcloud.tech/abra/pkg/upstream/commandconn" @@ -41,7 +41,7 @@ func New(serverName string, opts ...Opt) (*client.Client, error) { if serverName != "default" { context, err := GetContext(serverName) if err != nil { - return nil, fmt.Errorf("unknown server, run \"abra server add %s\"?", serverName) + return nil, errors.New(i18n.G("unknown server, run \"abra server add %s\"?", serverName)) } ctxEndpoint, err := contextPkg.GetContextEndpoint(context) @@ -85,7 +85,7 @@ func New(serverName string, opts ...Opt) (*client.Client, error) { return nil, err } - log.Debugf("created client for %s", serverName) + log.Debug(i18n.G("created client for %s", serverName)) info, err := cl.Info(context.Background()) if err != nil { @@ -94,10 +94,10 @@ func New(serverName string, opts ...Opt) (*client.Client, error) { if info.Swarm.LocalNodeState == "inactive" { if serverName != "default" { - return cl, fmt.Errorf("swarm mode not enabled on %s?", serverName) + return cl, errors.New(i18n.G("swarm mode not enabled on %s?", serverName)) } - return cl, errors.New("swarm mode not enabled on local server?") + return cl, errors.New(i18n.G("swarm mode not enabled on local server?")) } return cl, nil diff --git a/pkg/client/configs.go b/pkg/client/configs.go index efe14ab4..282ea864 100644 --- a/pkg/client/configs.go +++ b/pkg/client/configs.go @@ -2,11 +2,12 @@ package client import ( "context" - "fmt" + "errors" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" + "coopcloud.tech/abra/pkg/i18n" ) func GetConfigs(cl *client.Client, ctx context.Context, server string, fs filters.Args) ([]swarm.Config, error) { @@ -31,7 +32,7 @@ func GetConfigNames(configs []swarm.Config) []string { func RemoveConfigs(cl *client.Client, ctx context.Context, configNames []string, force bool) error { for _, confName := range configNames { if err := cl.ConfigRemove(context.Background(), confName); err != nil { - return fmt.Errorf("conf %s: %s", confName, err) + return errors.New(i18n.G("conf %s: %s", confName, err)) } } return nil diff --git a/pkg/client/context.go b/pkg/client/context.go index 4408bda5..7bdddda2 100644 --- a/pkg/client/context.go +++ b/pkg/client/context.go @@ -10,6 +10,7 @@ import ( dConfig "github.com/docker/cli/cli/config" "github.com/docker/cli/cli/context/docker" contextStore "github.com/docker/cli/cli/context/store" + "coopcloud.tech/abra/pkg/i18n" ) type Context = contextStore.Metadata @@ -22,7 +23,7 @@ func CreateContext(contextName string) error { return err } - log.Debugf("created the %s context", contextName) + log.Debug(i18n.G("created the %s context", contextName)) return nil } @@ -62,7 +63,7 @@ func createContext(name string, host string) error { func DeleteContext(name string) error { if name == "default" { - return errors.New("context 'default' cannot be removed") + return errors.New(i18n.G("context 'default' cannot be removed")) } if _, err := GetContext(name); err != nil { diff --git a/pkg/client/registry.go b/pkg/client/registry.go index 36d0ea73..75d66674 100644 --- a/pkg/client/registry.go +++ b/pkg/client/registry.go @@ -2,11 +2,13 @@ package client import ( "context" + "errors" "fmt" "github.com/containers/image/docker" "github.com/containers/image/types" "github.com/distribution/reference" + "coopcloud.tech/abra/pkg/i18n" ) // GetRegistryTags retrieves all tags of an image from a container registry. @@ -15,7 +17,7 @@ func GetRegistryTags(img reference.Named) ([]string, error) { ref, err := docker.ParseReference(fmt.Sprintf("//%s", img)) if err != nil { - return tags, fmt.Errorf("failed to parse image %s, saw: %s", img, err.Error()) + return tags, errors.New(i18n.G("failed to parse image %s, saw: %s", img, err.Error())) } ctx := context.Background() diff --git a/pkg/client/volumes.go b/pkg/client/volumes.go index c7af7619..3fedf783 100644 --- a/pkg/client/volumes.go +++ b/pkg/client/volumes.go @@ -2,9 +2,10 @@ package client import ( "context" - "fmt" + "errors" "time" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/volume" @@ -37,7 +38,7 @@ func RemoveVolumes(cl *client.Client, ctx context.Context, volumeNames []string, return cl.VolumeRemove(context.Background(), volName, force) }) if err != nil { - return fmt.Errorf("volume %s: %s", volName, err) + return errors.New(i18n.G("volume %s: %s", volName, err)) } } return nil @@ -54,9 +55,9 @@ func retryFunc(retries int, fn func() error) error { } if i+1 < retries { sleep := time.Duration(i+1) * time.Duration(i+1) - log.Infof("%s: waiting %d seconds before next retry", err, sleep) + log.Info(i18n.G("%s: waiting %d seconds before next retry", err, sleep)) time.Sleep(sleep * time.Second) } } - return fmt.Errorf("%d retries failed", retries) + return errors.New(i18n.G("%d retries failed", retries)) } diff --git a/pkg/config/abra.go b/pkg/config/abra.go index e0a5d452..48781b00 100644 --- a/pkg/config/abra.go +++ b/pkg/config/abra.go @@ -5,6 +5,7 @@ import ( "path" "path/filepath" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "gopkg.in/yaml.v3" ) @@ -16,13 +17,13 @@ func LoadAbraConfig() Abra { wd, _ := os.Getwd() configFile := findAbraConfig(wd) if configFile == "" { - log.Debugf("no config file found") + log.Debug(i18n.G("no config file found")) return Abra{} } data, err := os.ReadFile(configFile) if err != nil { // Do nothing, when an error occurs - log.Debugf("error reading config file: %s", err) + log.Debug(i18n.G("error reading config file: %s", err)) return Abra{} } @@ -30,10 +31,10 @@ func LoadAbraConfig() Abra { err = yaml.Unmarshal(data, &config) if err != nil { // Do nothing, when an error occurs - log.Debugf("error loading config file: %s", err) + log.Debug(i18n.G("error loading config file: %s", err)) return Abra{} } - log.Debugf("config file loaded from: %s", configFile) + log.Debug(i18n.G("config file loaded from: %s", configFile)) config.configPath = filepath.Dir(configFile) return config } @@ -73,26 +74,24 @@ type Abra struct { // 3. use $HOME/.abra when above two options failed func (a Abra) GetAbraDir() string { if dir, exists := os.LookupEnv("ABRA_DIR"); exists && dir != "" { - log.Debug("read abra dir from $ABRA_DIR") + log.Debug(i18n.G("read abra dir from $ABRA_DIR")) return dir } if a.AbraDir != "" { - log.Debug("read abra dir from config file") + log.Debug(i18n.G("read abra dir from config file")) if path.IsAbs(a.AbraDir) { return a.AbraDir } // Make the path absolute return path.Join(a.configPath, a.AbraDir) } - log.Debug("using default abra dir") + log.Debug(i18n.G("using default abra dir")) return os.ExpandEnv("$HOME/.abra") } func (a Abra) GetServersDir() string { return path.Join(a.GetAbraDir(), "servers") } func (a Abra) GetRecipesDir() string { return path.Join(a.GetAbraDir(), "recipes") } func (a Abra) GetLogsDir() string { return path.Join(a.GetAbraDir(), "logs") } -func (a Abra) GetVendorDir() string { return path.Join(a.GetAbraDir(), "vendor") } -func (a Abra) GetBackupDir() string { return path.Join(a.GetAbraDir(), "backups") } func (a Abra) GetCatalogueDir() string { return path.Join(a.GetAbraDir(), "catalogue") } var config = LoadAbraConfig() @@ -102,8 +101,6 @@ var ( SERVERS_DIR = config.GetServersDir() RECIPES_DIR = config.GetRecipesDir() LOGS_DIR = config.GetLogsDir() - VENDOR_DIR = config.GetVendorDir() - BACKUP_DIR = config.GetBackupDir() CATALOGUE_DIR = config.GetCatalogueDir() RECIPES_JSON = path.Join(config.GetCatalogueDir(), "recipes.json") REPOS_BASE_URL = "https://git.coopcloud.tech/coop-cloud" diff --git a/pkg/config/env.go b/pkg/config/env.go index c07a1e98..5550bd60 100644 --- a/pkg/config/env.go +++ b/pkg/config/env.go @@ -1,7 +1,7 @@ package config import ( - "fmt" + "errors" "io/fs" "io/ioutil" "os" @@ -9,6 +9,7 @@ import ( "path/filepath" "strings" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" ) @@ -33,7 +34,7 @@ func GetServers() ([]string, error) { } } - log.Debugf("retrieved %v servers: %s", len(filtered), filtered) + log.Debug(i18n.G("retrieved %v servers: %s", len(filtered), filtered)) return filtered, nil } @@ -46,7 +47,7 @@ func ReadServerNames() ([]string, error) { return nil, err } - log.Debugf("read %s from %s", strings.Join(serverNames, ","), SERVERS_DIR) + log.Debug(i18n.G("read %s from %s", strings.Join(serverNames, ","), SERVERS_DIR)) return serverNames, nil } @@ -70,7 +71,7 @@ func GetAllFilesInDirectory(directory string) ([]fs.FileInfo, error) { realPath, err := filepath.EvalSymlinks(filePath) if err != nil { - log.Warnf("broken symlink in your abra config folders: %s", filePath) + log.Warn(i18n.G("broken symlink in your abra config folders: %s", filePath)) } else { realFile, err := os.Stat(realPath) if err != nil { @@ -94,7 +95,7 @@ func GetAllFoldersInDirectory(directory string) ([]string, error) { return nil, err } if len(files) == 0 { - return nil, fmt.Errorf("directory is empty: %s", directory) + return nil, errors.New(i18n.G("directory is empty: %s", directory)) } for _, file := range files { @@ -103,7 +104,7 @@ func GetAllFoldersInDirectory(directory string) ([]string, error) { filePath := path.Join(directory, file.Name()) realDir, err := filepath.EvalSymlinks(filePath) if err != nil { - log.Warnf("broken symlink in your abra config folders: %s", filePath) + log.Warn(i18n.G("broken symlink in your abra config folders: %s", filePath)) } else if stat, err := os.Stat(realDir); err == nil && stat.IsDir() { // path is a directory folders = append(folders, file.Name()) diff --git a/pkg/container/container.go b/pkg/container/container.go index 16316218..1ec1a36d 100644 --- a/pkg/container/container.go +++ b/pkg/container/container.go @@ -2,6 +2,7 @@ package container import ( "context" + "errors" "fmt" "strings" @@ -12,6 +13,7 @@ import ( containerTypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/client" + "coopcloud.tech/abra/pkg/i18n" ) // GetContainer retrieves a container. If noInput is false and the retrievd @@ -26,7 +28,7 @@ func GetContainer(c context.Context, cl *client.Client, filters filters.Args, no if len(containers) == 0 { filter := filters.Get("name")[0] - return types.Container{}, fmt.Errorf("no containers matching the %v filter found?", filter) + return types.Container{}, errors.New(i18n.G("no containers matching the %v filter found?", filter)) } if len(containers) > 1 { @@ -35,19 +37,19 @@ func GetContainer(c context.Context, cl *client.Client, filters filters.Args, no containerName := strings.Join(container.Names, " ") trimmed := strings.TrimPrefix(containerName, "/") created := formatter.HumanDuration(container.Created) - containersRaw = append(containersRaw, fmt.Sprintf("%s (created %v)", trimmed, created)) + containersRaw = append(containersRaw, i18n.G("%s (created %v)", trimmed, created)) } if noInput { - err := fmt.Errorf("expected 1 container but found %v: %s", len(containers), strings.Join(containersRaw, " ")) + err := errors.New(i18n.G("expected 1 container but found %v: %s", len(containers), strings.Join(containersRaw, " "))) return types.Container{}, err } - log.Warnf("ambiguous container list received, prompting for input") + log.Warnf(i18n.G("ambiguous container list received, prompting for input")) var response string prompt := &survey.Select{ - Message: "which container are you looking for?", + Message: i18n.G("which container are you looking for?"), Options: containersRaw, } @@ -64,7 +66,7 @@ func GetContainer(c context.Context, cl *client.Client, filters filters.Args, no } } - log.Fatal("failed to match chosen container") + log.Fatal(i18n.G("failed to match chosen container")) } return containers[0], nil @@ -79,5 +81,6 @@ func GetContainerFromStackAndService(cl *client.Client, stack, service string) ( if err != nil { return types.Container{}, err } + return container, nil } diff --git a/pkg/context/context.go b/pkg/context/context.go index 9842f23c..aa3f6fa3 100644 --- a/pkg/context/context.go +++ b/pkg/context/context.go @@ -8,6 +8,7 @@ import ( "github.com/docker/cli/cli/context" contextStore "github.com/docker/cli/cli/context/store" cliflags "github.com/docker/cli/cli/flags" + "coopcloud.tech/abra/pkg/i18n" ) func NewDefaultDockerContextStore() *command.ContextStoreWithDefault { @@ -30,7 +31,7 @@ func NewDefaultDockerContextStore() *command.ContextStoreWithDefault { func GetContextEndpoint(ctx contextStore.Metadata) (string, error) { endpointmeta, ok := ctx.Endpoints["docker"].(context.EndpointMetaBase) if !ok { - err := errors.New("context lacks Docker endpoint") + err := errors.New(i18n.G("context lacks Docker endpoint")) return "", err } return endpointmeta.Host, nil diff --git a/pkg/dns/dns.go b/pkg/dns/dns.go index 40497d66..145b8885 100644 --- a/pkg/dns/dns.go +++ b/pkg/dns/dns.go @@ -1,19 +1,21 @@ package dns import ( - "fmt" + "errors" "net" + + "coopcloud.tech/abra/pkg/i18n" ) // EnsureIPv4 ensures that an ipv4 address is set for a domain name func EnsureIPv4(domainName string) (string, error) { ipv4, err := net.ResolveIPAddr("ip4", domainName) if err != nil { - return "", fmt.Errorf("%s: unable to resolve IPv4 address: %s", domainName, err) + return "", errors.New(i18n.G("%s: unable to resolve IPv4 address: %s", domainName, err)) } if ipv4 == nil { - return "", fmt.Errorf("%s: no IPv4 available", domainName) + return "", errors.New(i18n.G("%s: no IPv4 available", domainName)) } return ipv4.String(), nil @@ -33,7 +35,7 @@ func EnsureDomainsResolveSameIPv4(domainName, server string) (string, error) { } if domainIPv4 == "" { - return ipv4, fmt.Errorf("cannot resolve ipv4 for %s?", domainName) + return ipv4, errors.New(i18n.G("cannot resolve ipv4 for %s?", domainName)) } serverIPv4, err := EnsureIPv4(server) @@ -42,12 +44,16 @@ func EnsureDomainsResolveSameIPv4(domainName, server string) (string, error) { } if serverIPv4 == "" { - return ipv4, fmt.Errorf("cannot resolve ipv4 for %s?", server) + return ipv4, errors.New(i18n.G("cannot resolve ipv4 for %s?", server)) } if domainIPv4 != serverIPv4 { - err := "app domain %s (%s) does not appear to resolve to app server %s (%s)?" - return ipv4, fmt.Errorf(err, domainName, domainIPv4, server, serverIPv4) + return ipv4, errors.New( + i18n.G( + "app domain %s (%s) does not appear to resolve to app server %s (%s)?", + domainName, domainIPv4, server, serverIPv4, + ), + ) } return ipv4, nil diff --git a/pkg/envfile/envfile.go b/pkg/envfile/envfile.go index 0e3bd80f..1e72675a 100644 --- a/pkg/envfile/envfile.go +++ b/pkg/envfile/envfile.go @@ -2,13 +2,14 @@ package envfile import ( "bufio" - "fmt" + "errors" "os" "regexp" "strings" "coopcloud.tech/abra/pkg/log" "git.coopcloud.tech/toolshed/godotenv" + "coopcloud.tech/abra/pkg/i18n" ) // AppEnv is a map of the values in an apps env config @@ -38,7 +39,7 @@ func ReadEnvWithModifiers(filePath string) (AppEnv, AppModifiers, error) { return nil, mods, err } - log.Debugf("read %s from %s", envVars, filePath) + log.Debug(i18n.G("read %s from %s", envVars, filePath)) return envVars, mods, nil } @@ -69,16 +70,16 @@ func ReadAbraShEnvVars(abraSh string) (map[string]string, error) { envVarDef := splitVals[len(splitVals)-1] keyVal := strings.Split(envVarDef, "=") if len(keyVal) != 2 { - return envVars, fmt.Errorf("couldn't parse %s", txt) + return envVars, errors.New(i18n.G("couldn't parse %s", txt)) } envVars[keyVal[0]] = keyVal[1] } } if len(envVars) > 0 { - log.Debugf("read %s from %s", envVars, abraSh) + log.Debug(i18n.G("read %s from %s", envVars, abraSh)) } else { - log.Debugf("read 0 env var exports from %s", abraSh) + log.Debug(i18n.G("read 0 env var exports from %s", abraSh)) } return envVars, nil diff --git a/pkg/formatter/formatter.go b/pkg/formatter/formatter.go index 3c4d1400..567a2e6e 100644 --- a/pkg/formatter/formatter.go +++ b/pkg/formatter/formatter.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "coopcloud.tech/abra/pkg/i18n" "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss/table" "github.com/docker/go-units" @@ -42,7 +43,7 @@ func RemoveSha(str string) string { func HumanDuration(timestamp int64) string { date := time.Unix(timestamp, 0) now := time.Now().UTC() - return units.HumanDuration(now.Sub(date)) + " ago" + return units.HumanDuration(now.Sub(date)) + i18n.G(" ago") } // CreateTable prepares a table layout for output. @@ -76,7 +77,7 @@ func CreateTable() (*table.Table, error) { func PrintTable(t *table.Table) error { if isAbraCI, ok := os.LookupEnv("ABRA_CI"); ok && isAbraCI == "1" { // NOTE(d1): no width limits for CI testing since we test against outputs - log.Debug("detected ABRA_CI=1") + log.Debug(i18n.G("detected ABRA_CI=1")) fmt.Println(t) return nil } @@ -130,7 +131,7 @@ func CreateOverview(header string, rows [][]string) string { } if len(row) > 2 { - panic("CreateOverview: only accepts rows of len == 2") + panic(i18n.G("CreateOverview: only accepts rows of len == 2")) } lenOffset := 4 @@ -234,7 +235,7 @@ func StripTagMeta(image string) string { } if originalImage != image { - log.Debugf("stripped %s to %s for parsing", originalImage, image) + log.Debug(i18n.G("stripped %s to %s for parsing", originalImage, image)) } return image diff --git a/pkg/git/add.go b/pkg/git/add.go index d5bc3d14..eb660b3a 100644 --- a/pkg/git/add.go +++ b/pkg/git/add.go @@ -3,6 +3,7 @@ package git import ( "coopcloud.tech/abra/pkg/log" "github.com/go-git/go-git/v5" + "coopcloud.tech/abra/pkg/i18n" ) // Add adds a file to the git index. @@ -18,7 +19,7 @@ func Add(repoPath, path string, dryRun bool) error { } if dryRun { - log.Debugf("dry run: adding %s", path) + log.Debug(i18n.G("dry run: adding %s", path)) } else { worktree.Add(path) } diff --git a/pkg/git/branch.go b/pkg/git/branch.go index 1125bd3a..6a42c561 100644 --- a/pkg/git/branch.go +++ b/pkg/git/branch.go @@ -1,11 +1,13 @@ package git import ( + "errors" "fmt" "coopcloud.tech/abra/pkg/log" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" + "coopcloud.tech/abra/pkg/i18n" ) // Check if a branch exists in a repo. Use this and not repository.Branch(), @@ -63,7 +65,7 @@ func GetDefaultBranch(repo *git.Repository, repoPath string) (plumbing.Reference if !HasBranch(repo, "master") { if !HasBranch(repo, "main") { - return "", fmt.Errorf("failed to select default branch in %s", repoPath) + return "", errors.New(i18n.G("failed to select default branch in %s", repoPath)) } branch = "main" } @@ -90,11 +92,11 @@ func CheckoutDefaultBranch(repo *git.Repository, repoPath string) (plumbing.Refe } if err := worktree.Checkout(checkOutOpts); err != nil { - log.Debugf("failed to check out %s in %s", branch, repoPath) + log.Debug(i18n.G("failed to check out %s in %s", branch, repoPath)) return branch, err } - log.Debugf("successfully checked out %v in %s", branch, repoPath) + log.Debug(i18n.G("successfully checked out %v in %s", branch, repoPath)) return branch, nil } diff --git a/pkg/git/clone.go b/pkg/git/clone.go index 87145f54..9c10eb78 100644 --- a/pkg/git/clone.go +++ b/pkg/git/clone.go @@ -2,6 +2,7 @@ package git import ( "context" + "errors" "fmt" "os" "os/signal" @@ -10,6 +11,7 @@ import ( "coopcloud.tech/abra/pkg/log" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" + "coopcloud.tech/abra/pkg/i18n" ) // gitCloneIgnoreErr checks whether we can ignore a git clone error or not. @@ -44,7 +46,7 @@ func Clone(dir, url string) error { go func() { if _, err := os.Stat(dir); os.IsNotExist(err) { - log.Debugf("git clone: %s", url) + log.Debug(i18n.G("git clone: %s", url)) _, err := git.PlainCloneContext(ctx, dir, false, &git.CloneOptions{ URL: url, @@ -54,16 +56,16 @@ func Clone(dir, url string) error { }) if err != nil && gitCloneIgnoreErr(err) { - log.Debugf("git clone: %s cloned successfully", dir) + log.Debug(i18n.G("git clone: %s cloned successfully", dir)) errCh <- nil } if err := ctx.Err(); err != nil { - errCh <- fmt.Errorf("git clone %s: cancelled due to interrupt", dir) + errCh <- errors.New(i18n.G("git clone %s: cancelled due to interrupt", dir)) } if err != nil { - log.Debug("git clone: main branch failed, attempting master branch") + log.Debug(i18n.G("git clone: main branch failed, attempting master branch")) _, err := git.PlainCloneContext(ctx, dir, false, &git.CloneOptions{ URL: url, @@ -73,7 +75,7 @@ func Clone(dir, url string) error { }) if err != nil && gitCloneIgnoreErr(err) { - log.Debugf("git clone: %s cloned successfully", dir) + log.Debug(i18n.G("git clone: %s cloned successfully", dir)) errCh <- nil } @@ -82,9 +84,9 @@ func Clone(dir, url string) error { } } - log.Debugf("git clone: %s cloned successfully", dir) + log.Debug(i18n.G("git clone: %s cloned successfully", dir)) } else { - log.Debugf("git clone: %s already exists", dir) + log.Debug(i18n.G("git clone: %s already exists", dir)) } errCh <- nil @@ -95,9 +97,9 @@ func Clone(dir, url string) error { cancelCtx() fmt.Println() // NOTE(d1): newline after ^C if err := os.RemoveAll(dir); err != nil { - return fmt.Errorf("unable to clean up git clone of %s: %s", dir, err) + return errors.New(i18n.G("unable to clean up git clone of %s: %s", dir, err)) } - return fmt.Errorf("git clone %s: cancelled due to interrupt", dir) + return errors.New(i18n.G("git clone %s: cancelled due to interrupt", dir)) case err := <-errCh: return err } diff --git a/pkg/git/commit.go b/pkg/git/commit.go index 7775e518..a7ff9f29 100644 --- a/pkg/git/commit.go +++ b/pkg/git/commit.go @@ -1,16 +1,17 @@ package git import ( - "fmt" + "errors" "coopcloud.tech/abra/pkg/log" "github.com/go-git/go-git/v5" + "coopcloud.tech/abra/pkg/i18n" ) // Commit runs a git commit func Commit(repoPath, commitMessage string, dryRun bool) error { if commitMessage == "" { - return fmt.Errorf("no commit message specified?") + return errors.New(i18n.G("no commit message specified?")) } commitRepo, err := git.PlainOpen(repoPath) @@ -38,9 +39,9 @@ func Commit(repoPath, commitMessage string, dryRun bool) error { if err != nil { return err } - log.Debug("git changes commited") + log.Debug(i18n.G("git changes commited")) } else { - log.Debug("dry run: no changes commited") + log.Debug(i18n.G("dry run: no changes commited")) } return nil diff --git a/pkg/git/common.go b/pkg/git/common.go index ff4eb7d7..e41f2124 100644 --- a/pkg/git/common.go +++ b/pkg/git/common.go @@ -1,14 +1,16 @@ package git import ( - "fmt" + "errors" "os" + + "coopcloud.tech/abra/pkg/i18n" ) // EnsureGitRepo ensures a git repo .git folder exists func EnsureGitRepo(repoPath string) error { if _, err := os.Stat(repoPath); os.IsNotExist(err) { - return fmt.Errorf("no .git directory in %s?", repoPath) + return errors.New(i18n.G("no .git directory in %s?", repoPath)) } return nil } diff --git a/pkg/git/diff.go b/pkg/git/diff.go index 6242d654..2e9a3377 100644 --- a/pkg/git/diff.go +++ b/pkg/git/diff.go @@ -5,6 +5,7 @@ import ( "os/exec" "coopcloud.tech/abra/pkg/log" + "coopcloud.tech/abra/pkg/i18n" ) // getGitDiffArgs builds the `git diff` invocation args. It removes the usage @@ -26,7 +27,7 @@ func getGitDiffArgs(repoPath string) []string { // skips if it cannot find the command on the system. func DiffUnstaged(path string) error { if _, err := exec.LookPath("git"); err != nil { - log.Warnf("unable to locate git command, cannot output diff") + log.Warnf(i18n.G("unable to locate git command, cannot output diff")) return nil } diff --git a/pkg/git/init.go b/pkg/git/init.go index 5adf37b1..ad7e6f0a 100644 --- a/pkg/git/init.go +++ b/pkg/git/init.go @@ -1,40 +1,41 @@ package git import ( - "fmt" + "errors" "coopcloud.tech/abra/pkg/log" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" + "coopcloud.tech/abra/pkg/i18n" ) // Init inits a new repo and commits all the stuff if you want func Init(repoPath string, commit bool, gitName, gitEmail string) error { repo, err := git.PlainInit(repoPath, false) if err != nil { - return fmt.Errorf("git init: %s", err) + return errors.New(i18n.G("git init: %s", err)) } if err = SwitchToMain(repo); err != nil { - return fmt.Errorf("git branch rename: %s", err) + return errors.New(i18n.G("git branch rename: %s", err)) } - log.Debugf("initialised new git repo in %s", repoPath) + log.Debug(i18n.G("initialised new git repo in %s", repoPath)) if commit { commitRepo, err := git.PlainOpen(repoPath) if err != nil { - return fmt.Errorf("git open: %s", err) + return errors.New(i18n.G("git open: %s", err)) } commitWorktree, err := commitRepo.Worktree() if err != nil { - return fmt.Errorf("git worktree: %s", err) + return errors.New(i18n.G("git worktree: %s", err)) } if err := commitWorktree.AddWithOptions(&git.AddOptions{All: true}); err != nil { - return fmt.Errorf("git add: %s", err) + return errors.New(i18n.G("git add: %s", err)) } var author *object.Signature @@ -43,10 +44,10 @@ func Init(repoPath string, commit bool, gitName, gitEmail string) error { } if _, err = commitWorktree.Commit("init", &git.CommitOptions{Author: author}); err != nil { - return fmt.Errorf("git commit: %s", err) + return errors.New(i18n.G("git commit: %s", err)) } - log.Debugf("init committed all files for new git repo in %s", repoPath) + log.Debug(i18n.G("init committed all files for new git repo in %s", repoPath)) } return nil @@ -56,20 +57,20 @@ func Init(repoPath string, commit bool, gitName, gitEmail string) error { func SwitchToMain(repo *git.Repository) error { ref := plumbing.NewSymbolicReference(plumbing.HEAD, plumbing.ReferenceName("refs/heads/main")) if err := repo.Storer.SetReference(ref); err != nil { - return fmt.Errorf("set reference: %s", err) + return errors.New(i18n.G("set reference: %s", err)) } cfg, err := repo.Config() if err != nil { - return fmt.Errorf("repo config: %s", err) + return errors.New(i18n.G("repo config: %s", err)) } cfg.Init.DefaultBranch = "main" if err := repo.SetConfig(cfg); err != nil { - return fmt.Errorf("repo set config: %s", err) + return errors.New(i18n.G("repo set config: %s", err)) } - log.Debug("set 'main' as the default branch") + log.Debug(i18n.G("set 'main' as the default branch")) return nil } diff --git a/pkg/git/push.go b/pkg/git/push.go index 9d279e65..77b64e7c 100644 --- a/pkg/git/push.go +++ b/pkg/git/push.go @@ -4,12 +4,13 @@ import ( "coopcloud.tech/abra/pkg/log" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" + "coopcloud.tech/abra/pkg/i18n" ) // Push pushes the latest changes & optionally tags to the default remote func Push(repoDir string, remote string, tags bool, dryRun bool) error { if dryRun { - log.Debugf("dry run: no git changes pushed in %s", repoDir) + log.Debug(i18n.G("dry run: no git changes pushed in %s", repoDir)) return nil } @@ -27,7 +28,7 @@ func Push(repoDir string, remote string, tags bool, dryRun bool) error { return err } - log.Debugf("git changes pushed") + log.Debug(i18n.G("git changes pushed")) if tags { opts.RefSpecs = append(opts.RefSpecs, config.RefSpec("+refs/tags/*:refs/tags/*")) @@ -36,7 +37,7 @@ func Push(repoDir string, remote string, tags bool, dryRun bool) error { return err } - log.Debugf("git tags pushed") + log.Debug(i18n.G("git tags pushed")) } return nil diff --git a/pkg/git/read.go b/pkg/git/read.go index b2991357..8e08ee99 100644 --- a/pkg/git/read.go +++ b/pkg/git/read.go @@ -2,7 +2,6 @@ package git import ( "errors" - "fmt" "io/ioutil" "os" "os/user" @@ -13,6 +12,7 @@ import ( "github.com/go-git/go-git/v5" gitConfigPkg "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing/format/gitignore" + "coopcloud.tech/abra/pkg/i18n" ) // IsClean checks if a repo has unstaged changes @@ -23,12 +23,12 @@ func IsClean(repoPath string) (bool, error) { return false, git.ErrRepositoryNotExists } - return false, fmt.Errorf("unable to open %s: %s", repoPath, err) + return false, errors.New(i18n.G("unable to open %s: %s", repoPath, err)) } worktree, err := repo.Worktree() if err != nil { - return false, fmt.Errorf("unable to open worktree of %s: %s", repoPath, err) + return false, errors.New(i18n.G("unable to open worktree of %s: %s", repoPath, err)) } patterns, err := GetExcludesFiles() @@ -42,14 +42,14 @@ func IsClean(repoPath string) (bool, error) { status, err := worktree.Status() if err != nil { - return false, fmt.Errorf("unable to query status of %s: %s", repoPath, err) + return false, errors.New(i18n.G("unable to query status of %s: %s", repoPath, err)) } if status.String() != "" { noNewline := strings.TrimSuffix(status.String(), "\n") - log.Debugf("git status: %s: %s", repoPath, noNewline) + log.Debug(i18n.G("git status: %s: %s", repoPath, noNewline)) } else { - log.Debugf("git status: %s: clean", repoPath) + log.Debug(i18n.G("git status: %s: clean", repoPath)) } return status.IsClean(), nil @@ -85,7 +85,7 @@ func parseGitConfig() (*gitConfigPkg.Config, error) { globalGitConfig := filepath.Join(usr.HomeDir, ".gitconfig") if _, err := os.Stat(globalGitConfig); err != nil { if os.IsNotExist(err) { - log.Debugf("no %s exists, not reading any global gitignore config", globalGitConfig) + log.Debug(i18n.G("no %s exists, not reading any global gitignore config", globalGitConfig)) return cfg, nil } return cfg, err @@ -127,7 +127,7 @@ func parseExcludesFile(excludesfile string) ([]gitignore.Pattern, error) { if _, err := os.Stat(excludesfile); err != nil { if os.IsNotExist(err) { - log.Debugf("no %s exists, skipping reading gitignore paths", excludesfile) + log.Debug(i18n.G("no %s exists, skipping reading gitignore paths", excludesfile)) return ps, nil } return ps, err @@ -146,7 +146,7 @@ func parseExcludesFile(excludesfile string) ([]gitignore.Pattern, error) { } } - log.Debugf("read global ignore paths: %s", strings.Join(pathsRaw, " ")) + log.Debug(i18n.G("read global ignore paths: %s", strings.Join(pathsRaw, " "))) return ps, nil } diff --git a/pkg/git/remote.go b/pkg/git/remote.go index 5d7d7af4..1a96b232 100644 --- a/pkg/git/remote.go +++ b/pkg/git/remote.go @@ -6,12 +6,13 @@ import ( "coopcloud.tech/abra/pkg/log" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" + "coopcloud.tech/abra/pkg/i18n" ) // CreateRemote creates a new git remote in a repository func CreateRemote(repo *git.Repository, name, url string, dryRun bool) error { if dryRun { - log.Debugf("dry run: remote %s (%s) not created", name, url) + log.Debug(i18n.G("dry run: remote %s (%s) not created", name, url)) return nil } diff --git a/pkg/i18n/i18n.go b/pkg/i18n/i18n.go new file mode 100644 index 00000000..a3f01b92 --- /dev/null +++ b/pkg/i18n/i18n.go @@ -0,0 +1,34 @@ +package i18n + +import ( + "embed" + "fmt" + "os" + + "github.com/leonelquinteros/gotext" +) + +//go:embed locales +var assetFS embed.FS + +func GetLocale() string { + return os.Getenv("LANG") +} + +func LoadLocale() *gotext.Po { + locale := GetLocale() + + localePath := fmt.Sprintf("locales/%s/LC_MESSAGES/default.po", locale) + + b, err := assetFS.ReadFile(localePath) + if err != nil { + panic(fmt.Sprintf("i18n: unable to load %s: %s", localePath, err)) + } + + po := gotext.NewPo() + po.Parse(b) + + return po +} + +var G = LoadLocale().Get diff --git a/pkg/i18n/locales/default.pot b/pkg/i18n/locales/default.pot new file mode 100644 index 00000000..7e021be5 --- /dev/null +++ b/pkg/i18n/locales/default.pot @@ -0,0 +1,4686 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "Project-Id-Version: \n" + "Report-Msgid-Bugs-To: EMAIL\n" + "POT-Creation-Date: 2025-08-23 15:58+0200\n" + "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" + "Last-Translator: FULL NAME \n" + "Language-Team: LANGUAGE \n" + "Language: \n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + +#: ./pkg/recipe/git.go:410 +#, c-format +msgid "git checkout: %s in %s" +msgstr "" + +#: ./cli/app/secret.go:475 ./cli/app/secret.go:515 ./cli/app/secret.go:539 ./cli/app/secret.go:547 ./cli/app/restore.go:131 ./cli/app/ps.go:206 ./cli/app/cmd.go:272 ./cli/app/new.go:379 ./cli/app/check.go:87 ./cli/app/restart.go:154 ./cli/app/deploy.go:326 ./cli/app/cp.go:378 ./cli/app/backup.go:287 ./cli/app/backup.go:303 ./cli/app/labels.go:135 ./cli/catalogue/catalogue.go:271 ./cli/recipe/lint.go:128 ./cli/updater/updater.go:537 +msgid "chaos" +msgstr "" + +#: ./cli/app/upgrade.go:208 ./cli/app/deploy.go:166 +#, c-format +msgid "%s missing from %s.env" +msgstr "" + +#: ./cli/app/upgrade.go:397 +#, c-format +msgid "'%s' is not a known version" +msgstr "" + +#: ./cli/app/backup.go:298 +msgid "number of retry attempts" +msgstr "" + +#: ./cli/server/add.go:128 +#, c-format +msgid "serverAdd: cleanUp: cleaning up context for %s" +msgstr "" + +#: ./pkg/client/volumes.go:58 +#, c-format +msgid "%s: waiting %d seconds before next retry" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:162 +msgid "volume type must be volume, bind, tmpfs or npipe" +msgstr "" + +#: ./pkg/ui/deploy.go:121 +#, c-format +msgid "^%s" +msgstr "" + +#: ./cli/app/ps.go:119 ./cli/app/ps.go:120 ./cli/app/ps.go:121 ./cli/app/ps.go:122 ./cli/app/ps.go:123 ./cli/app/list.go:111 ./cli/app/list.go:112 ./cli/app/list.go:113 ./cli/app/list.go:114 ./cli/app/list.go:115 ./cli/app/list.go:175 ./cli/app/labels.go:71 ./cli/server/list.go:59 ./cli/server/list.go:71 +msgid "unknown" +msgstr "" + +#: ./cli/app/new.go:211 +#, c-format +msgid "secrets are %s shown again, please save them %s" +msgstr "" + +#: ./pkg/recipe/git.go:274 +#, c-format +msgid "unable to git pull in %s: %s" +msgstr "" + +#: ./cli/app/secret.go:261 ./cli/app/remove.go:20 ./cli/app/volume.go:93 ./cli/server/remove.go:18 +msgid "rm" +msgstr "" + +#: ./cli/app/run.go:23 +msgid "Run a command inside a service container" +msgstr "" + +#: ./cli/server/add.go:137 +#, c-format +msgid "serverAdd: cleanUp: unable to list files in %s: %s" +msgstr "" + +#: ./cli/recipe/upgrade.go:280 +msgid "enter / return to confirm, choose 'skip' to not upgrade this tag, vim mode is enabled" +msgstr "" + +#: ./cli/updater/updater.go:473 +msgid "The Co-op Cloud auto-updater 🤖 🚀" +msgstr "" + +#: ./cli/app/config.go:17 +msgid "cfg" +msgstr "" + +#: ./cli/app/backup.go:274 +msgid "include secrets" +msgstr "" + +#: ./pkg/app/app.go:683 +#, c-format +msgid "version %s saved to %s.env" +msgstr "" + +#: ./cli/app/secret.go:230 +#, c-format +msgid "%s successfully stored on server" +msgstr "" + +#: ./cli/updater/updater.go:38 +msgid "Notify on new versions for deployed apps.\n" + "\n" + "If a new patch/minor version is available, a notification is printed.\n" + "\n" + "Use \"--major/-m\" to include new major versions." +msgstr "" + +#: ./pkg/client/context.go:66 +msgid "context 'default' cannot be removed" +msgstr "" + +#: ./pkg/recipe/compose.go:233 +#, c-format +msgid "%s is already set, nothing to do?" +msgstr "" + +#: ./cli/app/env.go:16 ./cli/recipe/new.go:124 ./cli/recipe/lint.go:137 +msgid "e" +msgstr "" + +#: ./cli/recipe/upgrade.go:222 +#, c-format +msgid "service %s is at version %s, but pinned to %s, please correct your compose.yml file manually!" +msgstr "" + +#: ./cli/updater/updater.go:103 +msgid "missing arguments or --all/-a flag" +msgstr "" + +#: ./pkg/web/web.go:45 +#, c-format +msgid "bad status: %s" +msgstr "" + +#: ./cli/app/cmd.go:23 +msgid "cmd" +msgstr "" + +#: ./cli/app/services.go:21 +msgid "services [flags]" +msgstr "" + +#: ./cli/app/cmd.go:251 +msgid "run command locally" +msgstr "" + +#: ./cli/recipe/fetch.go:44 +msgid "missing [recipe] or --all/-a" +msgstr "" + +#: ./pkg/git/read.go:149 +#, c-format +msgid "read global ignore paths: %s" +msgstr "" + +#: ./cli/run.go:28 +msgid "app" +msgstr "" + +#: ./cli/recipe/diff.go:16 +msgid "This command requires /usr/bin/git." +msgstr "" + +#: ./pkg/upstream/container/hijack.go:82 +#, c-format +msgid "unable to set IO streams as raw terminal: %s" +msgstr "" + +#: ./cli/app/cmd.go:51 +msgid "accepts at most 2 args with --local/-l" +msgstr "" + +#: ./cli/app/restart.go:143 +#, c-format +msgid "%s has been scaled to 1" +msgstr "" + +#: ./cli/recipe/lint.go:37 +msgid "resolve" +msgstr "" + +#: ./pkg/lint/recipe.go:162 +msgid "all services have images" +msgstr "" + +#: ./pkg/upstream/commandconn/commandconn.go:162 +#, c-format +msgid "command %v did not exit after %v: stderr=%q" +msgstr "" + +#: ./pkg/recipe/recipe.go:406 +#, c-format +msgid "read recipe catalogue from file system cache in %s" +msgstr "" + +#: ./cli/app/rollback.go:42 +msgid " # standard rollback\n" + " abra app rollback 1312.net\n" + "\n" + " # rollback to specific version\n" + " abra app rollback 1312.net 2.0.0+1.2.3" +msgstr "" + +#: ./cli/recipe/release.go:492 +#, c-format +msgid "current: %s, new: %s, correct?" +msgstr "" + +#: ./cli/internal/backup.go:62 +#, c-format +msgid "running backup %s on %s with exec config %v" +msgstr "" + +#: ./pkg/recipe/recipe.go:659 +msgid "retrieving recipes" +msgstr "" + +#: ./cli/app/upgrade.go:31 +msgid "Upgrade an app" +msgstr "" + +#: ./cli/app/new.go:340 ./cli/app/new.go:347 ./cli/app/list.go:319 ./cli/app/list.go:326 ./cli/run.go:33 +msgid "server" +msgstr "" + +#: ./cli/internal/deploy.go:82 +msgid "NEW DEPLOYMENT" +msgstr "" + +#: ./pkg/recipe/recipe.go:175 +#, c-format +msgid "failed to check git status of %s: %s" +msgstr "" + +#: ./cli/app/cp.go:164 +#, c-format +msgid "copy %s from local to %s on container" +msgstr "" + +#: ./cli/recipe/fetch.go:70 ./pkg/lint/recipe.go:491 ./pkg/recipe/git.go:236 ./pkg/git/read.go:26 +#, c-format +msgid "unable to open %s: %s" +msgstr "" + +#: ./cli/recipe/fetch.go:74 +#, c-format +msgid "unable to remove default remote in %s: %s" +msgstr "" + +#: ./cli/recipe/lint.go:139 +msgid "only show errors" +msgstr "" + +#: ./pkg/lint/recipe.go:21 ./pkg/lint/recipe.go:67 ./pkg/lint/recipe.go:74 ./pkg/lint/recipe.go:81 ./pkg/lint/recipe.go:88 ./pkg/lint/recipe.go:95 ./pkg/lint/recipe.go:102 ./pkg/lint/recipe.go:109 ./pkg/lint/recipe.go:116 ./pkg/lint/recipe.go:123 +msgid "warn" +msgstr "" + +#: ./pkg/git/clone.go:89 +#, c-format +msgid "git clone: %s already exists" +msgstr "" + +#: ./cli/app/new.go:309 +#, c-format +msgid "single server detected, choosing %s automatically" +msgstr "" + +#: ./cli/app/backup.go:266 +msgid "volumes path" +msgstr "" + +#: ./cli/recipe/list.go:40 +msgid "healthcheck" +msgstr "" + +#: ./cli/app/restore.go:17 ./cli/recipe/reset.go:14 +msgid "rs" +msgstr "" + +#: ./cli/recipe/new.go:116 +msgid "N" +msgstr "" + +#: ./pkg/git/commit.go:44 +msgid "dry run: no changes commited" +msgstr "" + +#: ./cli/app/restore.go:107 +msgid "services" +msgstr "" + +#: ./cli/recipe/lint.go:14 +msgid "lint [flags]" +msgstr "" + +#: ./pkg/recipe/recipe.go:201 +#, c-format +msgid "dirty: %v, " +msgstr "" + +#: ./pkg/git/commit.go:42 +msgid "git changes commited" +msgstr "" + +#: ./cli/internal/deploy.go:123 +msgid "UNCHAOS DEPLOY" +msgstr "" + +#: ./pkg/app/compose.go:51 +#, c-format +msgid "set label 'coop-cloud.%s.version' to %v for %s" +msgstr "" + +#: ./pkg/client/client.go:88 +#, c-format +msgid "created client for %s" +msgstr "" + +#: ./pkg/git/commit.go:14 +msgid "no commit message specified?" +msgstr "" + +#: ./cli/server/add.go:168 +#, c-format +msgid "creating context with domain %s" +msgstr "" + +#: ./cli/recipe/sync.go:188 +#, c-format +msgid "choosing %s as new version for %s" +msgstr "" + +#: ./pkg/recipe/git.go:458 +#, c-format +msgid "collected %s for %s" +msgstr "" + +#: ./cli/app/secret.go:134 +#, c-format +msgid "generated secrets %s shown again, please take note of them %s" +msgstr "" + +#: ./cli/app/secret.go:267 +msgid " abra app secret rm 1312.net oauth_key" +msgstr "" + +#: ./cli/app/config.go:18 +msgid "Edit app config" +msgstr "" + +#: ./cli/run.go:92 +msgid "Generate manpage" +msgstr "" + +#: ./cli/recipe/sync.go:74 +msgid "unable to continue, input required for initial version" +msgstr "" + +#: ./cli/updater/updater.go:202 +#, c-format +msgid "for %s read env %s with value: %s from docker service" +msgstr "" + +#: ./pkg/recipe/git.go:151 +#, c-format +msgid "read %s as tags for recipe %s" +msgstr "" + +#: ./cli/app/new.go:199 +#, c-format +msgid "%s created (version: %s)" +msgstr "" + +#: ./cli/recipe/sync.go:20 +msgid "sync [version] [flags]" +msgstr "" + +#: ./pkg/ssh/ssh.go:20 +#, c-format +msgid "connection timed out for %s" +msgstr "" + +#: ./pkg/upstream/commandconn/commandconn.go:259 +#, c-format +msgid "unimplemented call: SetReadDeadline(%v)" +msgstr "" + +#: ./cli/app/secret.go:307 +msgid "cannot use [secret] and --all/-a together" +msgstr "" + +#: ./cli/app/upgrade.go:362 +#, c-format +msgid "parsing deployed version failed: %s" +msgstr "" + +#: ./cli/app/cp.go:108 +#, c-format +msgid "local %s " +msgstr "" + +#: ./pkg/upstream/commandconn/commandconn.go:65 +#, c-format +msgid "commandconn (%s):" +msgstr "" + +#: ./cli/app/cmd.go:267 +msgid "disable remote TTY" +msgstr "" + +#: ./cli/app/rollback.go:28 +msgid "This command rolls an app back to a previous version.\n" + "\n" + "Unlike \"abra app deploy\", chaos operations are not supported here. Only recipe\n" + "versions are supported values for \"[version]\".\n" + "\n" + "It is possible to \"--force/-f\" an downgrade if you want to re-deploy a specific\n" + "version.\n" + "\n" + "Only the deployed version is consulted when trying to determine what downgrades\n" + "are available. The live deployment version is the \"source of truth\" in this\n" + "case. The stored .env version is not consulted.\n" + "\n" + "A downgrade can be destructive, please ensure you have a copy of your app data\n" + "beforehand. See \"abra app backup\" for more." +msgstr "" + +#: ./cli/recipe/upgrade.go:177 +#, c-format +msgid "no new versions available for %s, assuming %s is the latest (use -a/--all-tags to see all anyway)" +msgstr "" + +#: ./pkg/upstream/container/hijack.go:172 +#, c-format +msgid "couldn't send EOF: %s" +msgstr "" + +#: ./cli/app/deploy.go:305 +#, c-format +msgid "version: taking version from .env file: %s" +msgstr "" + +#: ./cli/app/remove.go:73 ./cli/app/volume.go:120 +#, c-format +msgid "%s is still deployed. Run \"abra app undeploy %s\"" +msgstr "" + +#: ./cli/server/add.go:111 +#, c-format +msgid "%s successfully added" +msgstr "" + +#: ./cli/recipe/upgrade.go:148 +#, c-format +msgid "unable to read tag for image %s, is it missing? skipping upgrade for %s" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:47 +msgid "bind options are incompatible with type volume" +msgstr "" + +#: ./cli/app/backup.go:295 +msgid "retries" +msgstr "" + +#: ./pkg/git/clone.go:100 +#, c-format +msgid "unable to clean up git clone of %s: %s" +msgstr "" + +#: ./cli/app/cmd.go:46 +msgid "requires at least 2 arguments with --local/-l" +msgstr "" + +#: ./pkg/app/app.go:577 ./pkg/envfile/envfile.go:42 ./pkg/envfile/envfile.go:80 ./pkg/config/env.go:50 +#, c-format +msgid "read %s from %s" +msgstr "" + +#: ./pkg/git/init.go:34 +#, c-format +msgid "git worktree: %s" +msgstr "" + +#: ./cli/app/deploy.go:101 +#, c-format +msgid "get deploy version: %s" +msgstr "" + +#: ./cli/recipe/upgrade.go:91 +#, c-format +msgid "found versions file for %s" +msgstr "" + +#: ./cli/internal/command.go:84 +#, c-format +msgid "running command with user %s" +msgstr "" + +#: ./cli/internal/command.go:93 +msgid "not requesting a remote TTY" +msgstr "" + +#: ./cli/app/secret.go:75 +#, c-format +msgid "%s doesn't exist in the env config?" +msgstr "" + +#: ./cli/app/restart.go:23 +msgid "Restart an app" +msgstr "" + +#: ./cli/app/list.go:216 ./cli/internal/deploy.go:77 +msgid "SERVER" +msgstr "" + +#: ./cli/app/labels.go:102 +msgid "LABELS OVERVIEW" +msgstr "" + +#: ./cli/app/secret.go:311 +msgid "no secret(s) specified?" +msgstr "" + +#: ./cli/app/logs.go:96 +msgid "only tail stderr" +msgstr "" + +#: ./cli/app/list.go:296 ./cli/app/list.go:303 ./cli/run.go:32 +msgid "recipe" +msgstr "" + +#: ./cli/server/prune.go:93 +msgid "remove all unused images" +msgstr "" + +#: ./cli/internal/deploy.go:109 +msgid "deployment cancelled" +msgstr "" + +#: ./cli/app/secret.go:263 +msgid "This command removes a secret from an app environment.\n" + "\n" + "Arbitrary secret removal is not supported. Secrets that are removed must\n" + "match those configured in the recipe beforehand." +msgstr "" + +#: ./cli/app/cmd.go:198 +msgid "List all available commands" +msgstr "" + +#: ./cli/catalogue/catalogue.go:266 +msgid "skip updating recipe repositories" +msgstr "" + +#: ./cli/run.go:30 +msgid "catalogue" +msgstr "" + +#: ./cli/app/restore.go:110 +msgid "restore specific services" +msgstr "" + +#: ./cli/internal/validate.go:35 +#, c-format +msgid "can't read local recipes: %s" +msgstr "" + +#: ./cli/app/list.go:288 ./cli/recipe/list.go:39 +msgid "status" +msgstr "" + +#: ./cli/app/cmd.go:196 ./cli/app/backup.go:15 ./cli/app/volume.go:19 +msgid "list [flags]" +msgstr "" + +#: ./cli/run.go:142 +msgid "prefer offline & filesystem access" +msgstr "" + +#: ./cli/recipe/lint.go:53 +#, c-format +msgid "skipping %s, does not have level \"error\"" +msgstr "" + +#: ./pkg/lint/recipe.go:155 +msgid "include \"traefik.enable=true\" deploy label" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:93 +msgid "volume options are incompatible with type bind" +msgstr "" + +#: ./pkg/recipe/git.go:52 +#, c-format +msgid "can not redeploy chaos version (%s) without --chaos" +msgstr "" + +#: ./pkg/git/read.go:52 +#, c-format +msgid "git status: %s: clean" +msgstr "" + +#: ./cli/app/secret.go:57 +msgid "cannot use '[secret] [version]' and '--all' together" +msgstr "" + +#: ./cli/app/cmd.go:137 +#, c-format +msgid "%s does not exist locally, use /bin/sh as fallback" +msgstr "" + +#: ./cli/app/rollback.go:120 +msgid "no available downgrades" +msgstr "" + +#: ./cli/catalogue/catalogue.go:26 +msgid "Generate the recipe catalogue" +msgstr "" + +#: ./cli/recipe/recipe.go:10 +msgid "recipe [cmd] [args] [flags]" +msgstr "" + +#: ./pkg/lint/recipe.go:96 +msgid "tags use semver-like format" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:130 +msgid "invalid npipe source, source cannot be empty" +msgstr "" + +#: ./pkg/recipe/recipe.go:325 +#, c-format +msgid "%s: image meta has incorrect format: %s" +msgstr "" + +#: ./cli/app/secret.go:143 +msgid "insert [flags]" +msgstr "" + +#: ./cli/app/logs.go:18 +msgid "logs [service] [flags]" +msgstr "" + +#: ./cli/internal/deploy.go:129 +msgid "NEW DEPLOY" +msgstr "" + +#: ./pkg/upstream/convert/service.go:604 +msgid "test and disable can't be set at the same time" +msgstr "" + +#: ./cli/recipe/sync.go:22 +msgid "Sync recipe version label" +msgstr "" + +#: ./pkg/app/compose.go:95 +#, c-format +msgid "timeout label: %s" +msgstr "" + +#: ./pkg/upstream/convert/service.go:153 ./pkg/upstream/convert/service.go:168 +#, c-format +msgid "config not found: %s" +msgstr "" + +#: ./pkg/git/push.go:13 +#, c-format +msgid "dry run: no git changes pushed in %s" +msgstr "" + +#: ./cli/app/new.go:324 ./cli/internal/validate.go:167 +msgid "no server provided" +msgstr "" + +#: ./cli/app/backup.go:242 +msgid "show all paths" +msgstr "" + +#: ./cli/recipe/upgrade.go:139 +#, c-format +msgid "retrieved %s from remote registry for %s" +msgstr "" + +#: ./cli/updater/updater.go:386 +#, c-format +msgid "don't update %s due to chaos deployment" +msgstr "" + +#: ./pkg/dns/dns.go:52 +#, c-format +msgid "app domain %s (%s) does not appear to resolve to app server %s (%s)?" +msgstr "" + +#: ./pkg/service/service.go:77 ./pkg/service/service.go:131 +msgid "failed to match chosen service" +msgstr "" + +#: ./pkg/formatter/formatter.go:238 +#, c-format +msgid "stripped %s to %s for parsing" +msgstr "" + +#: ./cli/app/secret.go:502 +msgid "treat input as a file" +msgstr "" + +#: ./cli/server/list.go:20 +msgid "List managed servers" +msgstr "" + +#: ./pkg/git/read.go:130 +#, c-format +msgid "no %s exists, skipping reading gitignore paths" +msgstr "" + +#: ./pkg/client/client.go:100 +msgid "swarm mode not enabled on local server?" +msgstr "" + +#: ./pkg/lint/recipe.go:261 ./pkg/recipe/files.go:17 +#, c-format +msgid "unable to discover .env.sample for %s" +msgstr "" + +#: ./pkg/formatter/formatter.go:80 +msgid "detected ABRA_CI=1" +msgstr "" + +#: ./cli/app/upgrade.go:461 +msgid "only show release notes" +msgstr "" + +#: ./cli/app/env.go:18 +msgid " abra app env 1312.net" +msgstr "" + +#: ./pkg/app/app.go:267 +#, c-format +msgid "%s is missing the TYPE env var?" +msgstr "" + +#: ./cli/app/ps.go:180 ./cli/app/list.go:219 +msgid "STATUS" +msgstr "" + +#: ./cli/recipe/sync.go:193 +#, c-format +msgid "invalid version %s specified" +msgstr "" + +#: ./cli/app/secret.go:262 +msgid "Remove a secret" +msgstr "" + +#: ./cli/app/upgrade.go:323 +#, c-format +msgid "parsing deployment version failed: %s" +msgstr "" + +#: ./cli/app/list.go:223 +msgid "AUTOUPDATE" +msgstr "" + +#: ./cli/recipe/version.go:39 +msgid "retrieved versions from local recipe repository" +msgstr "" + +#: ./cli/recipe/release.go:249 +#, c-format +msgid "chore: publish %s release" +msgstr "" + +#: ./pkg/recipe/git.go:398 +#, c-format +msgid "processing %s for %s" +msgstr "" + +#: ./cli/recipe/release.go:556 +#, c-format +msgid "use %s as the new version?" +msgstr "" + +#: ./pkg/lint/recipe.go:147 +msgid "deploy labels stanza present" +msgstr "" + +#: ./pkg/ssh/ssh.go:22 +#, c-format +msgid "ssh auth: permission denied for %s" +msgstr "" + +#: ./pkg/recipe/git.go:160 +#, c-format +msgid "unable to resolve '%s': %s" +msgstr "" + +#: ./cli/app/volume.go:182 +#, c-format +msgid "%d volumes removed successfully" +msgstr "" + +#: ./cli/recipe/version.go:17 +msgid "versions [flags]" +msgstr "" + +#: ./pkg/lint/recipe.go:133 +msgid ".env.sample provided" +msgstr "" + +#: ./cli/app/services.go:67 +msgid "SERVICE (LONG)" +msgstr "" + +#: ./cli/app/backup.go:17 +msgid "List the contents of a snapshot" +msgstr "" + +#: ./cli/app/backup.go:234 ./cli/app/backup.go:258 +msgid "list specific snapshot" +msgstr "" + +#: ./cli/catalogue/catalogue.go:27 +msgid "Generate a new copy of the recipe catalogue.\n" + "\n" + "N.B. this command **will** wipe local unstaged changes from your local recipes\n" + "if present. \"--chaos/-C\" on this command refers to the catalogue repository\n" + "(\"$ABRA_DIR/catalogue\") and not the recipes. Please take care not to lose your\n" + "changes.\n" + "\n" + "It is possible to generate new metadata for a single recipe by passing\n" + "[recipe]. The existing local catalogue will be updated, not overwritten.\n" + "\n" + "It is quite easy to get rate limited by Docker Hub when running this command.\n" + "If you have a Hub account you can \"docker login\" and Abra will automatically\n" + "use those details.\n" + "\n" + "Push your new release to git.coopcloud.tech with \"--publish/-p\". This requires\n" + "that you have permission to git push to these repositories and have your SSH\n" + "keys configured on your account." +msgstr "" + +#: ./cli/recipe/upgrade.go:199 +#, c-format +msgid "detected compatible upgradable tags %s for %s" +msgstr "" + +#: ./cli/app/cmd.go:25 +msgid "Run an app specific command.\n" + "\n" + "These commands are bash functions, defined in the abra.sh of the recipe itself.\n" + "They can be run within the context of a service (e.g. app) or locally on your\n" + "work station by passing \"--local/-l\".\n" + "\n" + "N.B. If using the \"--\" style to pass arguments, flags (e.g. \"--local/-l\") must\n" + "be passed *before* the \"--\". It is possible to pass arguments without the \"--\"\n" + "as long as no dashes are present (i.e. \"foo\" works without \"--\", \"-foo\"\n" + "does not)." +msgstr "" + +#: ./cli/app/secret.go:373 ./cli/app/cmd.go:197 ./cli/app/backup.go:16 ./cli/app/volume.go:20 ./cli/app/list.go:44 ./cli/server/list.go:19 ./cli/recipe/list.go:20 +msgid "ls" +msgstr "" + +#: ./cli/app/volume.go:77 +msgid "Remove volume(s) associated with an app" +msgstr "" + +#: ./cli/app/list.go:291 +msgid "show app deployment status" +msgstr "" + +#: ./cli/recipe/upgrade.go:353 ./cli/recipe/sync.go:238 ./cli/recipe/release.go:592 ./cli/internal/recipe.go:46 ./cli/internal/recipe.go:66 ./cli/internal/recipe.go:80 +msgid "minor" +msgstr "" + +#: ./pkg/recipe/recipe.go:549 +msgid "collecting recipe listing" +msgstr "" + +#: ./cli/app/backup.go:117 +#, c-format +msgid "including VOLUMES=%v in backupbot exec invocation" +msgstr "" + +#: ./cli/catalogue/catalogue.go:191 +msgid "chore: publish new catalogue release changes" +msgstr "" + +#: ./cli/updater/updater.go:37 +msgid "Check for available upgrades" +msgstr "" + +#: ./cli/internal/recipe.go:18 +#, c-format +msgid "\n" + "You need to make a decision about what kind of an update this new recipe\n" + "version is. If someone else performs this upgrade, do they have to do some\n" + "migration work or take care of some breaking changes? This can be signaled in\n" + "the version you specify on the recipe deploy label and is called a semantic\n" + "version.\n" + "\n" + "The latest published version is %s.\n" + "\n" + "Here is a semver cheat sheet (more on https://semver.org):\n" + "\n" + " major: new features/bug fixes, backwards incompatible (e.g 1.0.0 -> 2.0.0).\n" + " the upgrade won't work without some preparation work and others need\n" + " to take care when performing it. \"it could go wrong\".\n" + "\n" + " minor: new features/bug fixes, backwards compatible (e.g. 0.1.0 -> 0.2.0).\n" + " the upgrade should Just Work and there are no breaking changes in\n" + " the app and the recipe config. \"it should go fine\".\n" + "\n" + " patch: bug fixes, backwards compatible (e.g. 0.0.1 -> 0.0.2). this upgrade\n" + " should also Just Work and is mostly to do with minor bug fixes\n" + " and/or security patches. \"nothing to worry about\".\n" + "\n" +msgstr "" + +#: ./pkg/recipe/compose.go:123 +#, c-format +msgid "considering %s config(s) for tag update" +msgstr "" + +#: ./cli/app/secret.go:470 ./cli/app/secret.go:494 +msgid "store generated secrets in a local pass store" +msgstr "" + +#: ./cli/internal/validate.go:64 +#, c-format +msgid "no recipe '%s' exists?" +msgstr "" + +#: ./pkg/app/app.go:41 +#, c-format +msgid "loaded app %s: %s" +msgstr "" + +#: ./cli/app/remove.go:94 +msgid "no configs to remove" +msgstr "" + +#: ./pkg/recipe/compose.go:47 +#, c-format +msgid "COMPOSE_FILE (=\"%s\") parsing failed?" +msgstr "" + +#: ./pkg/recipe/recipe.go:361 +#, c-format +msgid "%s: marker string %s not found" +msgstr "" + +#: ./cli/app/upgrade.go:437 ./cli/app/rollback.go:326 ./cli/app/deploy.go:337 ./cli/app/remove.go:158 ./cli/app/volume.go:201 +msgid "perform action without further prompt" +msgstr "" + +#: ./pkg/secret/secret.go:268 +#, c-format +msgid "generated and stored %v on %s" +msgstr "" + +#: ./pkg/upstream/commandconn/commandconn.go:263 +#, c-format +msgid "unimplemented call: SetWriteDeadline(%v)" +msgstr "" + +#: ./cli/recipe/upgrade.go:154 +#, c-format +msgid "unable to parse %s, error was: %s, skipping upgrade for %s" +msgstr "" + +#: ./pkg/lint/recipe.go:134 +msgid "create an example .env.sample" +msgstr "" + +#: ./pkg/server/server.go:25 +#, c-format +msgid "successfully created %s" +msgstr "" + +#: ./cli/app/upgrade.go:290 +#, c-format +msgid "please select an upgrade (version: %s, chaos: %s):" +msgstr "" + +#: ./cli/app/volume.go:47 +msgid "ON SERVER" +msgstr "" + +#: ./cli/run.go:117 +msgid "don't forget to run 'sudo mandb'" +msgstr "" + +#: ./cli/server/add.go:21 +msgid "add [[server] | --local] [flags]" +msgstr "" + +#: ./pkg/recipe/git.go:178 +#, c-format +msgid "successfully checked %s out to %s in %s" +msgstr "" + +#: ./pkg/git/clone.go:49 +#, c-format +msgid "git clone: %s" +msgstr "" + +#: ./cli/app/upgrade.go:392 ./cli/app/rollback.go:275 +#, c-format +msgid "'%s' is not a known version for %s" +msgstr "" + +#: ./cli/app/backup.go:49 +#, c-format +msgid "including SHOW_ALL=%v in backupbot exec invocation" +msgstr "" + +#: ./cli/app/list.go:322 +msgid "show apps of a specific server" +msgstr "" + +#: ./cli/app/labels.go:24 +msgid "lb" +msgstr "" + +#: ./cli/recipe/upgrade.go:300 +#, c-format +msgid "not upgrading %s, skipping as requested" +msgstr "" + +#: ./pkg/ui/deploy.go:86 +#, c-format +msgid "reader: %v, " +msgstr "" + +#: ./cli/recipe/recipe.go:13 +msgid "A recipe is a blueprint for an app.\n" + "\n" + "It is a bunch of config files which describe how to deploy and maintain an app.\n" + "Recipes are maintained by the Co-op Cloud community and you can use Abra to\n" + "read them, deploy them and create apps for you.\n" + "\n" + "Anyone who uses a recipe can become a maintainer. Maintainers typically make\n" + "sure the recipe is in good working order and the config upgraded in a timely\n" + "manner." +msgstr "" + +#: ./cli/app/upgrade.go:453 ./cli/app/rollback.go:342 ./cli/app/deploy.go:353 +msgid "disable converge logic checks" +msgstr "" + +#: ./cli/app/new.go:275 ./cli/internal/validate.go:129 +msgid "no domain provided" +msgstr "" + +#: ./cli/updater/updater.go:251 +#, c-format +msgid "failed to determine deployed version of %s" +msgstr "" + +#: ./pkg/ssh/ssh.go:18 +#, c-format +msgid "could not resolve hostname for %s" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:44 +msgid "tmpfs options are incompatible with type volume" +msgstr "" + +#: ./cli/app/secret.go:26 +msgid "Generate secrets" +msgstr "" + +#: ./cli/complete.go:11 +msgid "autocomplete [bash|zsh|fish|powershell]" +msgstr "" + +#: ./cli/recipe/lint.go:74 ./cli/recipe/lint.go:136 ./pkg/lint/recipe.go:132 ./pkg/lint/recipe.go:139 ./pkg/lint/recipe.go:146 ./pkg/lint/recipe.go:153 ./pkg/lint/recipe.go:161 ./pkg/lint/recipe.go:168 ./pkg/lint/recipe.go:175 +msgid "error" +msgstr "" + +#: ./pkg/lint/recipe.go:124 +msgid "long secret names" +msgstr "" + +#: ./cli/app/secret.go:210 +#, c-format +msgid "no secret %s available for recipe %s?" +msgstr "" + +#: ./cli/app/ps.go:56 ./cli/app/upgrade.go:423 ./cli/app/undeploy.go:59 ./cli/app/services.go:49 ./cli/app/restart.go:93 ./cli/app/logs.go:58 ./cli/updater/updater.go:247 +#, c-format +msgid "%s is not deployed?" +msgstr "" + +#: ./cli/updater/updater.go:406 +#, c-format +msgid "don't update %s due to no new version" +msgstr "" + +#: ./pkg/lint/recipe.go:111 +msgid "fill out all the metadata" +msgstr "" + +#: ./cli/app/restore.go:74 +#, c-format +msgid "including CONTAINER=%s in backupbot exec invocation" +msgstr "" + +#: ./cli/app/upgrade.go:32 +msgid "Upgrade an app.\n" + "\n" + "Unlike \"abra app deploy\", chaos operations are not supported here. Only recipe\n" + "versions are supported values for \"[version]\".\n" + "\n" + "It is possible to \"--force/-f\" an upgrade if you want to re-deploy a specific\n" + "version.\n" + "\n" + "Only the deployed version is consulted when trying to determine what upgrades\n" + "are available. The live deployment version is the \"source of truth\" in this\n" + "case. The stored .env version is not consulted.\n" + "\n" + "An upgrade can be destructive, please ensure you have a copy of your app data\n" + "beforehand. See \"abra app backup\" for more." +msgstr "" + +#: ./pkg/recipe/git.go:187 +#, c-format +msgid "unable to check git clean status in %s: %s" +msgstr "" + +#: ./cli/app/secret.go:24 +msgid "generate [[secret] [version] | --all] [flags]" +msgstr "" + +#: ./cli/app/secret.go:144 +msgid "i" +msgstr "" + +#: ./cli/app/restart.go:64 +msgid "missing [service]" +msgstr "" + +#: ./cli/recipe/lint.go:34 +msgid "severity" +msgstr "" + +#: ./pkg/ssh/ssh.go:24 +#, c-format +msgid "unable to connect to %s, please check your SSH config" +msgstr "" + +#: ./cli/app/env.go:17 +msgid "Show app .env values" +msgstr "" + +#: ./pkg/git/init.go:50 +#, c-format +msgid "init committed all files for new git repo in %s" +msgstr "" + +#: ./cli/app/run.go:22 ./cli/app/upgrade.go:459 ./cli/app/backup.go:296 ./cli/app/list.go:297 ./cli/catalogue/catalogue.go:256 ./cli/recipe/sync.go:223 ./cli/recipe/recipe.go:11 ./cli/recipe/release.go:577 +msgid "r" +msgstr "" + +#: ./cli/app/upgrade.go:442 ./cli/app/rollback.go:331 ./cli/app/deploy.go:342 +msgid "no-domain-checks" +msgstr "" + +#: ./pkg/recipe/recipe.go:203 +#, c-format +msgid "git url: %s, " +msgstr "" + +#: ./cli/app/ps.go:183 ./cli/app/list.go:220 +msgid "CHAOS" +msgstr "" + +#: ./cli/server/remove.go:19 +msgid "Remove a managed server" +msgstr "" + +#: ./cli/updater/updater.go:176 +#, c-format +msgid "boolean label %s could not be found for %s, set default to false." +msgstr "" + +#: ./cli/internal/deploy.go:133 ./cli/internal/deploy.go:137 +msgid "DEPLOY" +msgstr "" + +#: ./cli/internal/recipe.go:70 ./cli/internal/recipe.go:85 +msgid "no version bump type specififed?" +msgstr "" + +#: ./pkg/app/compose.go:41 +#, c-format +msgid "set label 'coop-cloud.%s.chaos-version' to %v for %s" +msgstr "" + +#: ./pkg/recipe/git.go:191 +#, c-format +msgid "%s (%s) has locally unstaged changes?" +msgstr "" + +#: ./pkg/container/container.go:52 +msgid "which container are you looking for?" +msgstr "" + +#: ./cli/app/cmd.go:131 ./cli/app/cmd.go:176 +msgid "did not detect any command arguments" +msgstr "" + +#: ./cli/internal/deploy.go:142 +msgid "DOWNGRADE" +msgstr "" + +#: ./pkg/catalogue/catalogue.go:21 +msgid "catalogue is missing, retrieving now" +msgstr "" + +#: ./pkg/upstream/convert/service.go:72 +#, c-format +msgid "secret not found: %s" +msgstr "" + +#: ./cli/app/rollback.go:145 +#, c-format +msgid "choosing %s as version to rollback" +msgstr "" + +#: ./cli/app/cp.go:29 +msgid "cp [flags]" +msgstr "" + +#: ./pkg/upstream/container/exec.go:43 +msgid "exec ID empty" +msgstr "" + +#: ./pkg/recipe/git.go:251 +#, c-format +msgid "unable to open git work tree in %s: %s" +msgstr "" + +#: ./cli/app/list.go:216 ./cli/internal/deploy.go:76 +msgid "RECIPE" +msgstr "" + +#: ./cli/updater/updater.go:299 +#, c-format +msgid "available updates for %s: %s" +msgstr "" + +#: ./cli/app/secret.go:443 ./cli/app/restore.go:108 ./cli/app/new.go:341 ./cli/app/logs.go:94 ./cli/app/backup.go:179 ./cli/app/backup.go:232 ./cli/app/backup.go:256 ./cli/app/list.go:320 ./cli/catalogue/catalogue.go:264 ./cli/server/server.go:11 ./cli/recipe/fetch.go:123 ./cli/recipe/sync.go:21 +msgid "s" +msgstr "" + +#: ./cli/app/run.go:111 ./cli/app/cmd.go:257 ./cli/recipe/upgrade.go:42 ./cli/updater/updater.go:75 +msgid "u" +msgstr "" + +#: ./cli/app/cmd.go:101 +msgid "cannot use --local & --user together" +msgstr "" + +#: ./cli/app/new.go:118 +#, c-format +msgid "failed to retrieve latest commit for %s: %s" +msgstr "" + +#: ./cli/app/cp.go:253 +#, c-format +msgid "untar: %s" +msgstr "" + +#: ./cli/catalogue/catalogue.go:255 ./cli/recipe/sync.go:222 ./cli/recipe/release.go:576 +msgid "dry-run" +msgstr "" + +#: ./pkg/recipe/recipe.go:200 +#, c-format +msgid "version : %s, " +msgstr "" + +#: ./cli/app/remove.go:92 +#, c-format +msgid "%d config(s) removed successfully" +msgstr "" + +#: ./cli/server/add.go:100 +#, c-format +msgid "unable to create local context: %s" +msgstr "" + +#: ./cli/app/new.go:358 +msgid "domain name for app" +msgstr "" + +#: ./cli/recipe/release.go:93 +msgid "cannot specify tag and bump type at the same time" +msgstr "" + +#: ./cli/internal/validate.go:132 +#, c-format +msgid "validated %s as domain argument" +msgstr "" + +#: ./cli/app/upgrade.go:29 +msgid "upgrade [version] [flags]" +msgstr "" + +#: ./cli/app/restart.go:144 +#, c-format +msgid "%s service successfully restarted" +msgstr "" + +#: ./cli/recipe/lint.go:32 +msgid "ref" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:90 +msgid "invalid bind source, source cannot be empty" +msgstr "" + +#: ./pkg/ui/deploy.go:87 +#, c-format +msgid "writer: %v, " +msgstr "" + +#: ./cli/app/deploy.go:36 +msgid " # standard deployment\n" + " abra app deploy 1312.net\n" + "\n" + " # chaos deployment\n" + " abra app deploy 1312.net --chaos\n" + " \n" + " # deploy specific version\n" + " abra app deploy 1312.net 2.0.0+1.2.3\n" + "\n" + " # deploy a specific git hash\n" + " abra app deploy 1312.net 886db76d" +msgstr "" + +#: ./cli/server/add.go:76 ./cli/server/add.go:103 +#, c-format +msgid "attempting to create client for %s" +msgstr "" + +#: ./cli/recipe/sync.go:197 ./pkg/recipe/compose.go:229 +#, c-format +msgid "coop-cloud.${STACK_NAME}.version=%s" +msgstr "" + +#: ./cli/app/upgrade.go:445 ./cli/app/rollback.go:334 ./cli/app/deploy.go:345 +msgid "disable public DNS checks" +msgstr "" + +#: ./cli/app/rollback.go:26 ./cli/recipe/release.go:27 +msgid "rl" +msgstr "" + +#: ./cli/app/services.go:67 +msgid "SERVICE (SHORT)" +msgstr "" + +#: ./cli/recipe/upgrade.go:377 +msgid "all-tags" +msgstr "" + +#: ./cli/recipe/sync.go:129 +#, c-format +msgid "tag at commit %s is unannotated or otherwise broken" +msgstr "" + +#: ./cli/recipe/release.go:342 +msgid "dry run: no changes committed" +msgstr "" + +#: ./cli/recipe/release.go:400 +msgid "publish new release?" +msgstr "" + +#: ./cli/internal/command.go:81 +#, c-format +msgid "running command: %s" +msgstr "" + +#: ./cli/app/secret.go:154 +msgid " # insert regular secret\n" + " abra app secret insert 1312.net my_secret v1 mySuperSecret\n" + "\n" + " # insert secret as file\n" + " abra app secret insert 1312.net my_secret v1 secret.txt -f" +msgstr "" + +#: ./cli/app/secret.go:394 +msgid "CREATED ON SERVER" +msgstr "" + +#: ./cli/catalogue/catalogue.go:89 +msgid "collecting catalogue metadata" +msgstr "" + +#: ./cli/recipe/fetch.go:18 +msgid "fetch [recipe | --all] [flags]" +msgstr "" + +#: ./cli/recipe/sync.go:76 +#, c-format +msgid "\n" + "The following options are two types of initial semantic version that you can\n" + "pick for %s that will be published in the recipe catalogue. This follows the\n" + "semver convention (more on https://semver.org), here is a short cheatsheet\n" + "\n" + " 0.1.0: development release, still hacking. when you make a major upgrade\n" + " you increment the \"y\" part (i.e. 0.1.0 -> 0.2.0) and only move to\n" + " using the \"x\" part when things are stable.\n" + "\n" + " 1.0.0: public release, assumed to be working. you already have a stable\n" + " and reliable deployment of this app and feel relatively confident\n" + " about it.\n" + "\n" + "If you want people to be able alpha test your current config for %s but don't\n" + "think it is quite reliable, go with 0.1.0 and people will know that things are\n" + "likely to change.\n" + "\n" +msgstr "" + +#: ./cli/recipe/list.go:105 +msgid "pattern" +msgstr "" + +#: ./cli/app/remove.go:22 +msgid "Remove everything related to an app which is already undeployed.\n" + "\n" + "By default, it will prompt for confirmation before proceeding. All secrets,\n" + "volumes and the local app env file will be deleted.\n" + "\n" + "Only run this command when you are sure you want to completely remove the app\n" + "and all associated app data. This is a destructive action, Be Careful!\n" + "\n" + "If you would like to delete specific volumes or secrets, please use removal\n" + "sub-commands under \"app volume\" and \"app secret\" instead.\n" + "\n" + "Please note, if you delete the local app env file without removing volumes and\n" + "secrets first, Abra will *not* be able to help you remove them afterwards.\n" + "\n" + "To delete everything without prompt, use the \"--force/-f\" or the \"--no-input/n\"\n" + "flag." +msgstr "" + +#: ./cli/app/backup.go:107 +#, c-format +msgid "including INCLUDE_PATH=%s in backupbot exec invocation" +msgstr "" + +#: ./pkg/lint/recipe.go:203 +#, c-format +msgid "\n" + "lint %s: %s" +msgstr "" + +#: ./cli/app/rollback.go:280 ./cli/app/rollback.go:284 +#, c-format +msgid "%s is not a downgrade for %s?" +msgstr "" + +#: ./cli/app/list.go:153 +#, c-format +msgid "unable to retrieve tags for %s: %s" +msgstr "" + +#: ./cli/server/add.go:163 +#, c-format +msgid "context for %s already exists" +msgstr "" + +#: ./pkg/ui/deploy.go:85 +#, c-format +msgid "name: %s, " +msgstr "" + +#: ./pkg/recipe/compose.go:29 +#, c-format +msgid "no COMPOSE_FILE detected, loading default: %s" +msgstr "" + +#: ./pkg/recipe/recipe.go:130 +#, c-format +msgid "version seems invalid: %s" +msgstr "" + +#: ./cli/recipe/upgrade.go:239 +#, c-format +msgid "not upgrading from %s to %s for %s, because the upgrade type is more serious than what user wants" +msgstr "" + +#: ./cli/app/cmd.go:35 +msgid " # pass args/flags without \"--\"\n" + " abra app cmd 1312.net app my_cmd_arg foo --user bar\n" + "\n" + " # pass args/flags with \"--\"\n" + " abra app cmd 1312.net app my_cmd_args --user bar -- foo -vvv\n" + "\n" + " # drop the [service] arg if using \"--local/-l\"\n" + " abra app cmd 1312.net my_cmd --local" +msgstr "" + +#: ./cli/app/secret.go:460 ./cli/app/secret.go:556 ./cli/app/ps.go:199 ./cli/app/list.go:312 ./cli/server/list.go:100 ./cli/recipe/upgrade.go:370 ./cli/recipe/version.go:132 ./cli/recipe/list.go:98 ./cli/updater/updater.go:546 +msgid "m" +msgstr "" + +#: ./pkg/service/service.go:103 ./pkg/container/container.go:40 +#, c-format +msgid "%s (created %v)" +msgstr "" + +#: ./pkg/lint/recipe.go:104 +msgid "publish a recipe version to the catalogue" +msgstr "" + +#: ./cli/app/secret.go:484 ./cli/app/secret.go:524 ./cli/app/restart.go:162 ./cli/app/app.go:10 ./cli/app/backup.go:240 ./cli/server/prune.go:91 ./cli/server/add.go:22 ./cli/recipe/upgrade.go:378 ./cli/recipe/fetch.go:115 ./cli/updater/updater.go:554 +msgid "a" +msgstr "" + +#: ./cli/app/restore.go:102 +msgid "target path" +msgstr "" + +#: ./cli/app/cp.go:31 +msgid "Copy files to/from a deployed app service" +msgstr "" + +#: ./cli/server/add.go:53 +msgid "cannot use [server] and --local together" +msgstr "" + +#: ./pkg/recipe/compose.go:243 +#, c-format +msgid "synced label %s to service %s" +msgstr "" + +#: ./cli/app/backup.go:250 +msgid "include timestamps" +msgstr "" + +#: ./cli/server/prune.go:56 +msgid "removing all images, not only dangling ones" +msgstr "" + +#: ./pkg/app/app.go:295 +#, c-format +msgid "collecting metadata from %v servers: %s" +msgstr "" + +#: ./pkg/lint/recipe.go:215 +#, c-format +msgid "linting successful, %s is well configured" +msgstr "" + +#: ./pkg/recipe/compose.go:153 +#, c-format +msgid "unable to parse %s, skipping" +msgstr "" + +#: ./cli/app/upgrade.go:329 ./cli/app/upgrade.go:368 +#, c-format +msgid "parsing recipe version failed: %s" +msgstr "" + +#: ./cli/app/services.go:23 +msgid "Display all services of an app" +msgstr "" + +#: ./cli/app/deploy.go:29 ./cli/app/backup.go:66 ./cli/recipe/diff.go:14 ./cli/updater/updater.go:491 +msgid "d" +msgstr "" + +#: ./cli/recipe/fetch.go:125 +msgid "automatically set ssh remote" +msgstr "" + +#: ./pkg/lint/recipe.go:117 +msgid "git.coopcloud.tech repo exists" +msgstr "" + +#: ./pkg/upstream/container/hijack.go:135 +#, c-format +msgid "error receiveStdout: %s" +msgstr "" + +#: ./pkg/git/init.go:70 +#, c-format +msgid "repo set config: %s" +msgstr "" + +#: ./cli/recipe/fetch.go:20 +msgid "Clone recipe(s) locally" +msgstr "" + +#: ./pkg/lint/recipe.go:187 +#, c-format +msgid "linting for critical errors in %s configs" +msgstr "" + +#: ./pkg/recipe/git.go:262 +#, c-format +msgid "unable to fetch tags in %s: %s" +msgstr "" + +#: ./cli/app/cp.go:117 ./cli/app/cp.go:199 ./cli/app/cp.go:210 +#, c-format +msgid "remote path: %s" +msgstr "" + +#: ./cli/recipe/release.go:518 +#, c-format +msgid "failed to publish new release: %s" +msgstr "" + +#: ./pkg/logs/logs.go:86 +#, c-format +msgid "tailLogs: unable to copy buffer: %s" +msgstr "" + +#: ./pkg/recipe/recipe.go:138 +#, c-format +msgid "removed dirty suffix from .env version: %s -> %s" +msgstr "" + +#: ./pkg/container/container.go:31 +#, c-format +msgid "no containers matching the %v filter found?" +msgstr "" + +#: ./cli/app/new.go:48 ./cli/recipe/new.go:35 ./cli/updater/updater.go:36 ./cli/updater/updater.go:499 +msgid "n" +msgstr "" + +#: ./cli/recipe/new.go:53 +#, c-format +msgid "%s/example.git" +msgstr "" + +#: ./cli/internal/validate.go:50 +msgid "Select recipe" +msgstr "" + +#: ./pkg/recipe/compose.go:38 +#, c-format +msgid "COMPOSE_FILE detected, loading %s" +msgstr "" + +#: ./pkg/recipe/recipe.go:206 +#, c-format +msgid "readme: %s, " +msgstr "" + +#: ./cli/app/ps.go:179 ./cli/recipe/version.go:62 ./cli/recipe/version.go:103 +msgid "SERVICE" +msgstr "" + +#: ./cli/app/remove.go:139 +#, c-format +msgid "%d volume(s) removed successfully" +msgstr "" + +#: ./cli/app/volume.go:21 +msgid "List volumes associated with an app" +msgstr "" + +#: ./cli/run.go:31 +msgid "man" +msgstr "" + +#: ./cli/recipe/lint.go:36 +msgid "skipped" +msgstr "" + +#: ./pkg/upstream/commandconn/commandconn.go:141 +msgid "commandconn: failed to wait" +msgstr "" + +#: ./cli/app/services.go:22 +msgid "sr" +msgstr "" + +#: ./pkg/upstream/commandconn/commandconn.go:239 +#, c-format +msgid "commandConn.Close: CloseRead: %v" +msgstr "" + +#: ./pkg/recipe/compose.go:191 +#, c-format +msgid "considering %s config(s) for label update" +msgstr "" + +#: ./pkg/git/init.go:24 +#, c-format +msgid "initialised new git repo in %s" +msgstr "" + +#: ./cli/app/rollback.go:238 +#, c-format +msgid "please select a downgrade (version: %s):" +msgstr "" + +#: ./cli/app/deploy.go:296 +#, c-format +msgid "version: taking version from cli arg: %s" +msgstr "" + +#: ./cli/app/remove.go:89 +#, c-format +msgid "removing configs failed: %s" +msgstr "" + +#: ./cli/updater/updater.go:74 +msgid "upgrade [[stack] [recipe] | --all] [flags]" +msgstr "" + +#: ./cli/app/undeploy.go:88 +msgid "initialising undeploy" +msgstr "" + +#: ./cli/recipe/upgrade.go:75 +msgid "you can only use one of: --major, --minor, --patch." +msgstr "" + +#: ./cli/recipe/sync.go:96 +msgid "which version do you want to begin with?" +msgstr "" + +#: ./pkg/dns/dns.go:14 +#, c-format +msgid "%s: unable to resolve IPv4 address: %s" +msgstr "" + +#: ./cli/app/secret.go:124 ./cli/app/secret.go:424 ./cli/server/list.go:82 ./cli/recipe/version.go:106 ./cli/recipe/list.go:77 +#, c-format +msgid "unable to render to JSON: %s" +msgstr "" + +#: ./pkg/recipe/recipe.go:74 +#, c-format +msgid "choosing %s as latest version of %s" +msgstr "" + +#: ./pkg/recipe/recipe.go:199 +#, c-format +msgid "{name: %s, " +msgstr "" + +#: ./cli/app/restore.go:116 ./cli/app/backup.go:280 ./cli/server/prune.go:99 ./cli/recipe/version.go:18 +msgid "v" +msgstr "" + +#: ./cli/app/list.go:222 ./cli/internal/deploy.go:140 +msgid "UPGRADE" +msgstr "" + +#: ./pkg/service/service.go:53 ./pkg/service/service.go:107 +#, c-format +msgid "expected 1 service but found %v: %s" +msgstr "" + +#: ./pkg/lint/recipe.go:75 +msgid "healthcheck enabled for all services" +msgstr "" + +#: ./cli/app/restore.go:52 ./cli/app/backup.go:44 ./cli/app/backup.go:102 +#, c-format +msgid "including SNAPSHOT=%s in backupbot exec invocation" +msgstr "" + +#: ./cli/app/undeploy.go:128 ./cli/server/prune.go:45 +#, c-format +msgid "containers pruned: %d; space reclaimed: %s" +msgstr "" + +#: ./cli/recipe/version.go:53 +#, c-format +msgid "%s has no published versions?" +msgstr "" + +#: ./cli/internal/validate.go:75 +msgid "generate" +msgstr "" + +#: ./pkg/lint/recipe.go:118 +msgid "upload your recipe to git.coopcloud.tech/coop-cloud/..." +msgstr "" + +#: ./pkg/dns/dns.go:18 +#, c-format +msgid "%s: no IPv4 available" +msgstr "" + +#: ./cli/app/backup.go:134 +msgid "create [flags]" +msgstr "" + +#: ./cli/updater/updater.go:498 +msgid "no-input" +msgstr "" + +#: ./pkg/recipe/git.go:256 +#, c-format +msgid "unable to check out default branch in %s: %s" +msgstr "" + +#: ./cli/app/cp.go:32 +msgid " # copy myfile.txt to the root of the app service\n" + " abra app cp 1312.net myfile.txt app:/\n" + "\n" + " # copy that file back to your current working directory locally\n" + " abra app cp 1312.net app:/myfile.txt ./" +msgstr "" + +#: ./pkg/app/compose.go:80 +#, c-format +msgid "get label '%s'" +msgstr "" + +#: ./pkg/config/abra.go:88 +msgid "using default abra dir" +msgstr "" + +#: ./cli/app/restore.go:99 +msgid "target" +msgstr "" + +#: ./cli/recipe/release.go:317 +msgid "Release Note (leave empty for no release note)" +msgstr "" + +#: ./pkg/client/configs.go:35 +#, c-format +msgid "conf %s: %s" +msgstr "" + +#: ./pkg/lint/recipe.go:89 +msgid "no unstable tags" +msgstr "" + +#: ./cli/app/volume.go:71 +#, c-format +msgid "no volumes created for %s" +msgstr "" + +#: ./pkg/app/app.go:579 +#, c-format +msgid "read 0 command names from %s" +msgstr "" + +#: ./pkg/secret/secret.go:130 +#, c-format +msgid "%s not enabled in recipe config, skipping" +msgstr "" + +#: ./pkg/dns/dns.go:38 ./pkg/dns/dns.go:47 +#, c-format +msgid "cannot resolve ipv4 for %s?" +msgstr "" + +#: ./pkg/recipe/recipe.go:368 +#, c-format +msgid "%s: end marker %s not found" +msgstr "" + +#: ./cli/app/logs.go:104 +msgid "tail logs since YYYY-MM-DDTHH:MM:SSZ" +msgstr "" + +#: ./cli/recipe/upgrade.go:41 +msgid "upgrade [flags]" +msgstr "" + +#: ./pkg/git/read.go:50 +#, c-format +msgid "git status: %s: %s" +msgstr "" + +#: ./cli/app/restore.go:19 +msgid "Snapshots are restored while apps are deployed.\n" + "\n" + "Some restore scenarios may require service / app restarts." +msgstr "" + +#: ./cli/app/restart.go:68 +msgid "cannot use [service] and --all-services/-a together" +msgstr "" + +#: ./cli/app/config.go:42 +msgid "which editor do you wish to use?" +msgstr "" + +#: ./cli/server/prune.go:17 +msgid "Prune resources on a server" +msgstr "" + +#: ./cli/recipe/release.go:510 +#, c-format +msgid "failed to commit changes: %s" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:136 +msgid "tmpfs options are incompatible with type npipe" +msgstr "" + +#: ./pkg/config/abra.go:26 +#, c-format +msgid "error reading config file: %s" +msgstr "" + +#: ./pkg/git/push.go:40 +msgid "git tags pushed" +msgstr "" + +#: ./cli/updater/updater.go:490 +msgid "debug" +msgstr "" + +#: ./cli/internal/validate.go:120 +msgid "Specify a domain name" +msgstr "" + +#: ./cli/app/secret.go:216 +#, c-format +msgid "reading secret from file: %s" +msgstr "" + +#: ./cli/app/restore.go:68 +#, c-format +msgid "including VOLUMES=%s in backupbot exec invocation" +msgstr "" + +#: ./cli/app/backup.go:136 +msgid "Create a new snapshot" +msgstr "" + +#: ./cli/recipe/lint.go:35 +msgid "satisfied" +msgstr "" + +#: ./cli/internal/validate.go:88 +#, c-format +msgid "validated %s as recipe argument" +msgstr "" + +#: ./cli/app/secret.go:478 ./cli/app/secret.go:518 ./cli/app/secret.go:542 ./cli/app/secret.go:550 ./cli/app/restore.go:134 ./cli/app/ps.go:209 ./cli/app/cmd.go:275 ./cli/app/new.go:382 ./cli/app/check.go:90 ./cli/app/restart.go:157 ./cli/app/deploy.go:329 ./cli/app/cp.go:381 ./cli/app/backup.go:290 ./cli/app/backup.go:306 ./cli/app/labels.go:138 ./cli/catalogue/catalogue.go:274 ./cli/recipe/lint.go:131 ./cli/updater/updater.go:540 +msgid "ignore uncommitted recipes changes" +msgstr "" + +#: ./cli/app/deploy.go:303 +#, c-format +msgid "version: can not redeploy chaos version %s" +msgstr "" + +#: ./cli/app/remove.go:119 +msgid "no secrets to remove" +msgstr "" + +#: ./cli/app/list.go:177 +msgid "latest" +msgstr "" + +#: ./cli/recipe/new.go:118 +msgid "Git (user) name to do commits with" +msgstr "" + +#: ./cli/app/cmd.go:249 ./cli/app/logs.go:19 ./cli/server/add.go:200 ./cli/recipe/lint.go:16 +msgid "l" +msgstr "" + +#: ./cli/app/new.go:135 +#, c-format +msgid "%s sanitised as %s for new app" +msgstr "" + +#: ./cli/app/volume.go:184 +msgid "no volumes removed" +msgstr "" + +#: ./cli/server/add.go:86 +msgid "local server already exists" +msgstr "" + +#: ./cli/app/check.go:19 +msgid "Ensure an app is well configured" +msgstr "" + +#: ./cli/app/cp.go:145 ./cli/app/cp.go:184 +#, c-format +msgid "create remote directory: %s" +msgstr "" + +#: ./cli/app/backup.go:282 +msgid "include volumes" +msgstr "" + +#: ./cli/recipe/new.go:37 +msgid "A community managed recipe template is used." +msgstr "" + +#: ./cli/updater/updater.go:484 +#, c-format +msgid "kadabra version %s, commit %s" +msgstr "" + +#: ./cli/internal/validate.go:84 +#, c-format +msgid "unable to validate recipe: %s" +msgstr "" + +#: ./pkg/recipe/compose.go:171 ./pkg/recipe/compose.go:237 +#, c-format +msgid "updating %s to %s in %s" +msgstr "" + +#: ./cli/app/cp.go:245 +#, c-format +msgid "copy: %s" +msgstr "" + +#: ./cli/recipe/upgrade.go:364 ./cli/recipe/sync.go:249 ./cli/recipe/release.go:603 +msgid "increase the patch part of the version" +msgstr "" + +#: ./pkg/catalogue/catalogue.go:59 ./pkg/recipe/git.go:245 +#, c-format +msgid "cannot ensure %s is up-to-date, no git remotes configured" +msgstr "" + +#: ./cli/server/add.go:120 ./pkg/secret/secret.go:223 ./pkg/secret/secret.go:243 ./pkg/server/server.go:21 +#, c-format +msgid "%s already exists" +msgstr "" + +#: ./cli/internal/deploy.go:78 +msgid "CONFIG" +msgstr "" + +#: ./pkg/lint/recipe.go:76 +msgid "wire up healthchecks" +msgstr "" + +#: ./cli/recipe/list.go:38 +msgid "category" +msgstr "" + +#: ./cli/internal/validate.go:59 +msgid "no recipe name provided" +msgstr "" + +#: ./cli/internal/validate.go:96 +msgid "no app provided" +msgstr "" + +#: ./cli/app/run.go:102 +msgid "no-tty" +msgstr "" + +#: ./cli/app/ps.go:30 +msgid "Check app deployment status" +msgstr "" + +#: ./cli/app/upgrade.go:274 ./cli/app/undeploy.go:107 ./cli/app/new.go:224 ./cli/app/rollback.go:227 ./cli/app/deploy.go:236 +#, c-format +msgid "writing recipe version failed: %s" +msgstr "" + +#: ./cli/app/rollback.go:25 +msgid "rollback [version] [flags]" +msgstr "" + +#: ./cli/app/restart.go:161 +msgid "all-services" +msgstr "" + +#: ./cli/app/list.go:49 +msgid " # list apps of all servers without live status\n" + " abra app ls\n" + "\n" + " # list apps of a specific server with live status\n" + " abra app ls -s 1312.net -S\n" + "\n" + " # list apps of all servers which match a specific recipe\n" + " abra app ls -r gitea" +msgstr "" + +#: ./cli/recipe/fetch.go:48 +msgid "cannot use [recipe] and --all/-a together" +msgstr "" + +#: ./cli/recipe/lint.go:15 +msgid "Lint a recipe" +msgstr "" + +#: ./cli/app/secret.go:508 ./cli/app/restore.go:100 ./cli/app/run.go:103 ./cli/app/backup.go:248 +msgid "t" +msgstr "" + +#: ./cli/recipe/list.go:44 +msgid "SSO" +msgstr "" + +#: ./cli/recipe/release.go:28 +msgid "Release a new recipe version" +msgstr "" + +#: ./cli/updater/updater.go:197 +#, c-format +msgid "can't separate key from value: %s (this variable is probably unset)" +msgstr "" + +#: ./cli/recipe/release.go:537 +#, c-format +msgid "removed freshly created tag %s" +msgstr "" + +#: ./pkg/lint/recipe.go:83 +msgid "use a tag for all images" +msgstr "" + +#: ./pkg/lint/recipe.go:163 +msgid "ensure \"image: ...\" set on all services" +msgstr "" + +#: ./cli/app/restart.go:22 +msgid "re" +msgstr "" + +#: ./cli/app/secret.go:260 +msgid "remove [[secret] | --all] [flags]" +msgstr "" + +#: ./cli/server/add.go:57 +msgid "missing argument or --local/-l flag" +msgstr "" + +#: ./pkg/lint/recipe.go:148 +msgid "include \"deploy: labels: ...\" stanza" +msgstr "" + +#: ./pkg/git/read.go:88 +#, c-format +msgid "no %s exists, not reading any global gitignore config" +msgstr "" + +#: ./cli/recipe/upgrade.go:43 +msgid "Upgrade recipe image tags" +msgstr "" + +#: ./cli/updater/updater.go:35 +msgid "notify [flags]" +msgstr "" + +#: ./cli/updater/updater.go:239 +#, c-format +msgid "retrieve deployed version whether %s is already deployed" +msgstr "" + +#: ./cli/app/remove.go:116 +#, c-format +msgid "secret: %s removed" +msgstr "" + +#: ./pkg/lint/recipe.go:110 +msgid "README.md metadata filled in" +msgstr "" + +#: ./pkg/secret/secret.go:119 +msgid "not generating app secrets, none enabled in recipe config" +msgstr "" + +#: ./pkg/recipe/git.go:50 +#, c-format +msgid "ensuring env version %s" +msgstr "" + +#: ./cli/app/upgrade.go:443 ./cli/app/new.go:356 ./cli/app/rollback.go:332 ./cli/app/deploy.go:343 +msgid "D" +msgstr "" + +#: ./cli/app/volume.go:88 +msgid " # delete volumes interactively\n" + " abra app volume rm 1312.net\n" + "\n" + " # delete specific volume\n" + " abra app volume rm 1312.net my_volume" +msgstr "" + +#: ./cli/complete.go:13 +msgid "To load completions:\n" + "\n" + "Bash:\n" + " # Load autocompletion for the current Bash session\n" + " $ source <(abra autocomplete bash)\n" + "\n" + " # To load autocompletion for each session, execute once:\n" + " # Linux:\n" + " $ abra autocomplete bash | sudo tee /etc/bash_completion.d/abra\n" + " # macOS:\n" + " $ abra autocomplete bash | sudo tee $(brew --prefix)/etc/bash_completion.d/abra\n" + "\n" + "Zsh:\n" + " # If shell autocompletion is not already enabled in your environment,\n" + " # you will need to enable it. You can execute the following once:\n" + "\n" + " $ echo \"autoload -U compinit; compinit\" >> ~/.zshrc\n" + "\n" + " # To load autocompletions for each session, execute once:\n" + " $ abra autocomplete zsh > \"${fpath[1]}/_abra\"\n" + "\n" + " # You will need to start a new shell for this setup to take effect.\n" + "\n" + "fish:\n" + " $ abra autocomplete fish | source\n" + "\n" + " # To load autocompletions for each session, execute once:\n" + " $ abra autocomplete fish > ~/.config/fish/completions/abra.fish\n" + "\n" + "PowerShell:\n" + " PS> abra autocomplete powershell | Out-String | Invoke-Expression\n" + "\n" + " # To load autocompletions for every new session, run:\n" + " PS> abra autocomplete powershell > abra.ps1\n" + " # and source this file from your PowerShell profile." +msgstr "" + +#: ./cli/server/server.go:10 +msgid "server [cmd] [args] [flags]" +msgstr "" + +#: ./cli/catalogue/catalogue.go:234 +msgid "catalogue [cmd] [args] [flags]" +msgstr "" + +#: ./cli/recipe/upgrade.go:362 ./cli/recipe/sync.go:247 ./cli/recipe/release.go:601 +msgid "z" +msgstr "" + +#: ./cli/recipe/release.go:78 +#, c-format +msgid "main app service version for %s is empty?" +msgstr "" + +#: ./pkg/ui/deploy.go:84 +#, c-format +msgid "id: %s, " +msgstr "" + +#: ./pkg/recipe/recipe.go:555 +#, c-format +msgid "fetching repo metadata from %s" +msgstr "" + +#: ./cli/app/secret.go:106 ./cli/app/new.go:187 +msgid "VALUE" +msgstr "" + +#: ./cli/recipe/upgrade.go:345 ./cli/recipe/sync.go:230 ./cli/recipe/release.go:584 ./cli/updater/updater.go:545 ./cli/internal/recipe.go:46 ./cli/internal/recipe.go:64 ./cli/internal/recipe.go:78 +msgid "major" +msgstr "" + +#: ./cli/recipe/upgrade.go:356 ./cli/recipe/sync.go:241 ./cli/recipe/release.go:595 +msgid "increase the minor part of the version" +msgstr "" + +#: ./cli/app/secret.go:136 +msgid "NOT" +msgstr "" + +#: ./cli/app/secret.go:146 +msgid "This command inserts a secret into an app environment.\n" + "\n" + "Arbitrary secret insertion is not supported. Secrets that are inserted must\n" + "match those configured in the recipe beforehand.\n" + "\n" + "This can be useful when you want to manually generate secrets for an app\n" + "environment. Typically, you can let Abra generate them for you on app creation\n" + "(see \"abra app new --secrets/-S\" for more)." +msgstr "" + +#: ./cli/app/volume.go:192 +msgid "Manage app volumes" +msgstr "" + +#: ./cli/catalogue/catalogue.go:247 ./cli/recipe/release.go:608 +msgid "publish" +msgstr "" + +#: ./cli/updater/updater.go:224 +#, c-format +msgid "no available upgrades for %s" +msgstr "" + +#: ./pkg/lint/recipe.go:177 +msgid "replace lightweight tag with annotated tag" +msgstr "" + +#: ./pkg/ui/deploy.go:82 +#, c-format +msgid "{decoder: %v, " +msgstr "" + +#: ./cli/recipe/upgrade.go:346 ./cli/recipe/sync.go:231 ./cli/recipe/release.go:585 +msgid "x" +msgstr "" + +#: ./cli/recipe/fetch.go:122 +msgid "ssh" +msgstr "" + +#: ./cli/recipe/new.go:115 +msgid "git-name" +msgstr "" + +#: ./pkg/config/env.go:37 +#, c-format +msgid "retrieved %v servers: %s" +msgstr "" + +#: ./cli/app/upgrade.go:451 ./cli/app/rollback.go:340 ./cli/app/deploy.go:351 ./cli/app/cp.go:30 ./cli/app/backup.go:135 +msgid "c" +msgstr "" + +#: ./cli/app/labels.go:26 +msgid "Both local recipe and live deployment labels are shown." +msgstr "" + +#: ./cli/internal/recipe.go:112 +#, c-format +msgid "%s has no main 'app' service?" +msgstr "" + +#: ./pkg/upstream/container/tty.go:66 +msgid "failed to resize tty, using default size" +msgstr "" + +#: ./pkg/recipe/recipe.go:205 +#, c-format +msgid "compose: %s, " +msgstr "" + +#: ./cli/app/logs.go:20 +msgid "Tail app logs" +msgstr "" + +#: ./cli/app/backup.go:54 +#, c-format +msgid "including TIMESTAMPS=%v in backupbot exec invocation" +msgstr "" + +#: ./cli/app/backup.go:65 +msgid "download [flags]" +msgstr "" + +#: ./cli/run.go:24 +msgid "abra [cmd] [args] [flags]" +msgstr "" + +#: ./cli/upgrade.go:37 ./pkg/secret/pass.go:23 ./pkg/secret/pass.go:45 +#, c-format +msgid "attempting to run %s" +msgstr "" + +#: ./cli/server/prune.go:101 +msgid "remove volumes" +msgstr "" + +#: ./cli/server/remove.go:17 +msgid "remove [flags]" +msgstr "" + +#: ./cli/recipe/release.go:26 +msgid "release [version] [flags]" +msgstr "" + +#: ./cli/internal/backup.go:29 +#, c-format +msgid "retrieved %s as backup enabled service" +msgstr "" + +#: ./pkg/client/registry.go:20 +#, c-format +msgid "failed to parse image %s, saw: %s" +msgstr "" + +#: ./pkg/upstream/convert/service.go:43 +#, c-format +msgid "duplicate secret target for %s not allowed" +msgstr "" + +#: ./cli/recipe/upgrade.go:318 +#, c-format +msgid "can upgrade service: %s, image: %s, tag: %s ::" +msgstr "" + +#: ./cli/recipe/fetch.go:81 +#, c-format +msgid "unable to set SSH remote in %s: %s" +msgstr "" + +#: ./cli/recipe/release.go:514 +#, c-format +msgid "failed to tag release: %s" +msgstr "" + +#: ./pkg/upstream/convert/service.go:813 +#, c-format +msgid "invalid credential spec: cannot specify both %s and %s" +msgstr "" + +#: ./pkg/recipe/git.go:225 ./pkg/recipe/git.go:406 ./pkg/git/branch.go:95 +#, c-format +msgid "failed to check out %s in %s" +msgstr "" + +#: ./pkg/app/app.go:679 +#, c-format +msgid "skipping writing version %s because dry run" +msgstr "" + +#: ./pkg/upstream/container/hijack.go:43 +#, c-format +msgid "unable to setup input stream: %s" +msgstr "" + +#: ./cli/app/run.go:113 +msgid "run command as user" +msgstr "" + +#: ./cli/app/cmd.go:264 +msgid "tty" +msgstr "" + +#: ./cli/catalogue/catalogue.go:24 +msgid "generate [recipe] [flags]" +msgstr "" + +#: ./cli/run.go:29 +msgid "autocomplete" +msgstr "" + +#: ./cli/app/ps.go:165 +#, c-format +msgid "unable to convert to JSON: %s" +msgstr "" + +#: ./pkg/app/app.go:380 +#, c-format +msgid "%s already exists?" +msgstr "" + +#: ./cli/run.go:25 +msgid "The Co-op Cloud command-line utility belt 🎩🐇" +msgstr "" + +#: ./pkg/recipe/recipe.go:147 +#, c-format +msgid "invalid recipe: %s" +msgstr "" + +#: ./pkg/recipe/recipe.go:208 +#, c-format +msgid "abra.sh: %s}" +msgstr "" + +#: ./pkg/git/clone.go:59 ./pkg/git/clone.go:78 ./pkg/git/clone.go:87 +#, c-format +msgid "git clone: %s cloned successfully" +msgstr "" + +#: ./pkg/container/container.go:48 +msgid "ambiguous container list received, prompting for input" +msgstr "" + +#: ./cli/app/ps.go:28 +msgid "ps [flags]" +msgstr "" + +#: ./cli/app/labels.go:53 +msgid "DEPLOYED LABELS" +msgstr "" + +#: ./cli/recipe/upgrade.go:249 +#, c-format +msgid "upgrade to which tag? (service: %s, tag: %s)" +msgstr "" + +#: ./pkg/secret/pass.go:29 +#, c-format +msgid "%s inserted into pass store" +msgstr "" + +#: ./pkg/recipe/recipe.go:202 +#, c-format +msgid "dir: %s, " +msgstr "" + +#: ./cli/app/deploy.go:177 +msgid "skipping domain checks, no DOMAIN=... configured" +msgstr "" + +#: ./cli/app/remove.go:136 ./cli/app/volume.go:179 +#, c-format +msgid "removing volumes failed: %s" +msgstr "" + +#: ./cli/recipe/upgrade.go:361 ./cli/recipe/sync.go:246 ./cli/recipe/release.go:600 ./cli/internal/recipe.go:46 ./cli/internal/recipe.go:68 ./cli/internal/recipe.go:82 +msgid "patch" +msgstr "" + +#: ./cli/recipe/release.go:88 +#, c-format +msgid "cannot parse %s, invalid tag specified?" +msgstr "" + +#: ./cli/updater/updater.go:77 +msgid "Upgrade an app by specifying stack name and recipe. \n" + "\n" + "Use \"--all\" to upgrade every deployed app.\n" + "\n" + "For each app with auto updates enabled, the deployed version is compared with\n" + "the current recipe catalogue version. If a new patch/minor version is\n" + "available, the app is upgraded.\n" + "\n" + "To include major versions use the \"--major/-m\" flag. You probably don't want\n" + "that as it will break things. Only apps that are not deployed with \"--chaos/-C\"\n" + "are upgraded, to update chaos deployments use the \"--chaos/-C\" flag. Use it\n" + "with care." +msgstr "" + +#: ./cli/app/app.go:11 +msgid "Manage apps" +msgstr "" + +#: ./cli/upgrade.go:18 +msgid "Upgrade abra" +msgstr "" + +#: ./pkg/catalogue/catalogue.go:40 +#, c-format +msgid "%s has locally unstaged changes? please commit/remove your changes before proceeding" +msgstr "" + +#: ./cli/app/secret.go:534 +msgid "remove generated secrets from a local pass store" +msgstr "" + +#: ./cli/app/upgrade.go:285 +#, c-format +msgid "please select an upgrade (version: %s):" +msgstr "" + +#: ./cli/app/backup.go:231 ./cli/app/backup.go:255 +msgid "snapshot" +msgstr "" + +#: ./cli/run.go:90 +msgid "man [flags]" +msgstr "" + +#: ./cli/internal/validate.go:82 +#, c-format +msgid "ensure %s recipe compose.* files include \"version: '3.8'\"" +msgstr "" + +#: ./pkg/app/app.go:501 +#, c-format +msgid "retrieved %s for %s" +msgstr "" + +#: ./cli/app/restore.go:126 +msgid "enable pre/post-hook command execution" +msgstr "" + +#: ./cli/app/secret.go:442 +msgid "secret [cmd] [args] [flags]" +msgstr "" + +#: ./cli/recipe/upgrade.go:158 +#, c-format +msgid "parsed %s for %s" +msgstr "" + +#: ./cli/recipe/upgrade.go:348 ./cli/recipe/sync.go:233 ./cli/recipe/release.go:587 +msgid "increase the major part of the version" +msgstr "" + +#: ./cli/app/cp.go:273 +msgid "destination directory does not exist" +msgstr "" + +#: ./cli/recipe/new.go:123 +msgid "git-email" +msgstr "" + +#: ./cli/internal/backup.go:26 +msgid "no backupbot discovered, is it deployed?" +msgstr "" + +#: ./pkg/app/app.go:516 +#, c-format +msgid "%s: %s: %s" +msgstr "" + +#: ./pkg/service/service.go:61 ./pkg/service/service.go:115 +msgid "which service are you looking for?" +msgstr "" + +#: ./cli/app/labels.go:27 +msgid " abra app labels 1312.net" +msgstr "" + +#: ./cli/catalogue/catalogue.go:223 +#, c-format +msgid "new changes published: %s" +msgstr "" + +#: ./cli/recipe/list.go:18 +msgid "list" +msgstr "" + +#: ./pkg/app/app.go:622 +#, c-format +msgid "version wiped from %s.env" +msgstr "" + +#: ./cli/recipe/upgrade.go:101 +#, c-format +msgid "malformed version pin specification: %s" +msgstr "" + +#: ./cli/recipe/sync.go:203 +#, c-format +msgid "dry run: not syncing label %s for recipe %s" +msgstr "" + +#: ./cli/recipe/release.go:501 +msgid "exiting as requested" +msgstr "" + +#: ./pkg/lint/recipe.go:82 +msgid "all images use a tag" +msgstr "" + +#: ./pkg/upstream/container/exec.go:113 +#, c-format +msgid "Error hijack: %s" +msgstr "" + +#: ./cli/app/secret.go:468 ./cli/app/secret.go:492 ./cli/app/secret.go:532 ./cli/app/ps.go:29 ./cli/app/undeploy.go:156 ./cli/app/new.go:364 ./cli/app/backup.go:264 ./cli/catalogue/catalogue.go:248 ./cli/server/prune.go:16 ./cli/recipe/list.go:106 ./cli/recipe/release.go:609 +msgid "p" +msgstr "" + +#: ./cli/app/deploy.go:316 +#, c-format +msgid "version: taking new recipe version: %s" +msgstr "" + +#: ./cli/app/cp.go:85 +msgid "one of / arguments must take $SERVICE:$PATH form" +msgstr "" + +#: ./cli/app/restore.go:123 +msgid "hooks" +msgstr "" + +#: ./cli/app/rollback.go:243 +#, c-format +msgid "please select a downgrade (version: %s, chaos: %s):" +msgstr "" + +#: ./cli/app/rollback.go:270 +#, c-format +msgid "current deployment '%s' is not a known version for %s" +msgstr "" + +#: ./pkg/recipe/compose.go:249 +#, c-format +msgid "add '- \"%s\"' manually to the 'app' service in %s" +msgstr "" + +#: ./pkg/recipe/recipe.go:204 +#, c-format +msgid "ssh url: %s, " +msgstr "" + +#: ./cli/app/deploy.go:107 +#, c-format +msgid "ensure recipe: %s" +msgstr "" + +#: ./cli/app/volume.go:150 +#, c-format +msgid "removing volume %s failed: %s" +msgstr "" + +#: ./cli/internal/validate.go:151 +msgid "Specify a server name" +msgstr "" + +#: ./pkg/context/context.go:34 +msgid "context lacks Docker endpoint" +msgstr "" + +#: ./cli/app/restore.go:18 +msgid "Restore a snapshot" +msgstr "" + +#: ./cli/app/volume.go:153 +#, c-format +msgid "volume %s removed successfully" +msgstr "" + +#: ./cli/internal/deploy.go:81 +msgid "ENV VERSION" +msgstr "" + +#: ./cli/recipe/list.go:43 +msgid "tests" +msgstr "" + +#: ./cli/recipe/release.go:277 +#, c-format +msgid "dry run: move release note from 'next' to %s" +msgstr "" + +#: ./cli/app/secret.go:437 +#, c-format +msgid "no secrets stored for %s" +msgstr "" + +#: ./cli/app/rollback.go:27 +msgid "Roll an app back to a previous version" +msgstr "" + +#: ./cli/catalogue/catalogue.go:227 ./cli/recipe/release.go:394 +msgid "dry run: no changes published" +msgstr "" + +#: ./cli/app/cmd.go:259 +msgid "request remote user" +msgstr "" + +#: ./cli/app/undeploy.go:158 +msgid "prune unused containers, networks, and dangling images" +msgstr "" + +#: ./cli/recipe/recipe.go:12 +msgid "Manage recipes" +msgstr "" + +#: ./cli/recipe/reset.go:15 +msgid "Remove all unstaged changes from recipe config" +msgstr "" + +#: ./pkg/upstream/convert/service.go:414 +#, c-format +msgid "undefined secret %q" +msgstr "" + +#: ./pkg/service/service.go:30 +msgid "no services deployed?" +msgstr "" + +#: ./pkg/lint/recipe.go:176 +msgid "only annotated tags used for recipe version" +msgstr "" + +#: ./pkg/upstream/commandconn/commandconn.go:255 +#, c-format +msgid "unimplemented call: SetDeadline(%v)" +msgstr "" + +#: ./cli/app/secret.go:500 ./cli/app/upgrade.go:435 ./cli/app/rollback.go:324 ./cli/app/deploy.go:335 ./cli/app/remove.go:156 ./cli/app/volume.go:199 ./cli/recipe/fetch.go:19 ./cli/recipe/fetch.go:131 +msgid "f" +msgstr "" + +#: ./cli/recipe/upgrade.go:172 +#, c-format +msgid "detected potential upgradable tags %s for %s" +msgstr "" + +#: ./pkg/secret/secret.go:62 ./pkg/secret/secret.go:80 +#, c-format +msgid "generated %s" +msgstr "" + +#: ./pkg/git/push.go:31 +msgid "git changes pushed" +msgstr "" + +#: ./cli/app/new.go:207 +msgid "SECRETS OVERVIEW" +msgstr "" + +#: ./cli/app/logs.go:93 +msgid "stderr" +msgstr "" + +#: ./cli/internal/deploy.go:117 +msgid "UNDEPLOY" +msgstr "" + +#: ./pkg/git/add.go:22 +#, c-format +msgid "dry run: adding %s" +msgstr "" + +#: ./cli/app/secret.go:38 ./cli/app/secret.go:170 ./cli/app/secret.go:280 ./cli/app/upgrade.go:58 ./cli/app/rollback.go:58 ./cli/app/deploy.go:59 ./cli/app/logs.go:32 ./pkg/autocomplete/autocomplete.go:17 ./pkg/autocomplete/autocomplete.go:32 ./pkg/autocomplete/autocomplete.go:43 ./pkg/autocomplete/autocomplete.go:59 ./pkg/autocomplete/autocomplete.go:77 ./pkg/autocomplete/autocomplete.go:93 ./pkg/autocomplete/autocomplete.go:99 ./pkg/autocomplete/autocomplete.go:114 +#, c-format +msgid "autocomplete failed: %s" +msgstr "" + +#: ./cli/app/secret.go:507 +msgid "trim" +msgstr "" + +#: ./cli/updater/updater.go:471 +msgid "kadabra [cmd] [flags]" +msgstr "" + +#: ./pkg/formatter/formatter.go:46 +msgid " ago" +msgstr "" + +#: ./cli/app/upgrade.go:402 ./cli/app/upgrade.go:406 +#, c-format +msgid "%s is not an upgrade for %s?" +msgstr "" + +#: ./cli/app/new.go:24 +msgid "Creates a new app from a default recipe.\n" + "\n" + "This new app configuration is stored in your $ABRA_DIR directory under the\n" + "appropriate server.\n" + "\n" + "This command does not deploy your app for you. You will need to run \"abra app\n" + "deploy \" to do so.\n" + "\n" + "You can see what recipes are available (i.e. values for the [recipe] argument)\n" + "by running \"abra recipe ls\".\n" + "\n" + "Recipe commit hashes are supported values for \"[version]\".\n" + "\n" + "Passing the \"--secrets/-S\" flag will automatically generate secrets for your\n" + "app and store them encrypted at rest on the chosen target server. These\n" + "generated secrets are only visible at generation time, so please take care to\n" + "store them somewhere safe.\n" + "\n" + "You can use the \"--pass/-P\" to store these generated passwords locally in a\n" + "pass store (see passwordstore.org for more). The pass command must be available\n" + "on your $PATH." +msgstr "" + +#: ./cli/app/backup.go:213 +msgid "backup [cmd] [args] [flags]" +msgstr "" + +#: ./cli/recipe/release.go:549 +#, c-format +msgid "unable to read version for %s from synced label. Did you try running \"abra recipe sync %s\" already?" +msgstr "" + +#: ./cli/app/upgrade.go:269 ./cli/app/deploy.go:231 +#, c-format +msgid "attempting to run post deploy commands, saw: %s" +msgstr "" + +#: ./cli/catalogue/catalogue.go:187 ./cli/recipe/release.go:353 +#, c-format +msgid "no changes discovered in %s, nothing to publish?" +msgstr "" + +#: ./cli/recipe/new.go:86 +#, c-format +msgid "new recipe '%s' created: %s" +msgstr "" + +#: ./pkg/app/compose.go:18 +#, c-format +msgid "set recipe label 'coop-cloud.%s.recipe' to %s for %s" +msgstr "" + +#: ./cli/app/secret.go:476 ./cli/app/secret.go:516 ./cli/app/secret.go:540 ./cli/app/secret.go:548 ./cli/app/restore.go:132 ./cli/app/ps.go:207 ./cli/app/cmd.go:273 ./cli/app/new.go:380 ./cli/app/check.go:88 ./cli/app/restart.go:155 ./cli/app/deploy.go:327 ./cli/app/cp.go:379 ./cli/app/backup.go:288 ./cli/app/backup.go:304 ./cli/app/labels.go:136 ./cli/catalogue/catalogue.go:272 ./cli/recipe/lint.go:129 ./cli/updater/updater.go:538 +msgid "C" +msgstr "" + +#: ./cli/app/secret.go:145 +msgid "Insert secret" +msgstr "" + +#: ./cli/app/undeploy.go:155 +msgid "prune" +msgstr "" + +#: ./cli/recipe/release.go:430 +msgid "you can only use one of: --major, --minor, --patch" +msgstr "" + +#: ./cli/internal/deploy.go:189 +#, c-format +msgid "running command %s %s within the context of %s_%s" +msgstr "" + +#: ./pkg/upstream/container/exec.go:108 +msgid "Error monitoring TTY size:" +msgstr "" + +#: ./cli/app/restore.go:16 +msgid "restore [flags]" +msgstr "" + +#: ./cli/app/ps.go:181 ./cli/recipe/version.go:62 +msgid "IMAGE" +msgstr "" + +#: ./cli/app/run.go:105 +msgid "do not request a TTY" +msgstr "" + +#: ./cli/app/check.go:18 +msgid "chk" +msgstr "" + +#: ./cli/recipe/fetch.go:55 +#, c-format +msgid "%s is already fetched" +msgstr "" + +#: ./pkg/upstream/commandconn/commandconn.go:172 +#, c-format +msgid "command %v has exited with %v, please make sure the URL is valid, and Docker 18.09 or later is installed on the remote host: stderr=%s" +msgstr "" + +#: ./cli/server/list.go:34 +msgid "HOST" +msgstr "" + +#: ./cli/recipe/list.go:108 +msgid "filter by recipe" +msgstr "" + +#: ./cli/app/secret.go:362 +#, c-format +msgid "%s doesn't exist on server?" +msgstr "" + +#: ./cli/recipe/release.go:128 +msgid "previous git tags detected, assuming this is a new semver release" +msgstr "" + +#: ./cli/catalogue/catalogue.go:263 +msgid "skip-updates" +msgstr "" + +#: ./cli/run.go:74 +#, c-format +msgid "unsupported --lang: %s (want: es)" +msgstr "" + +#: ./cli/upgrade.go:16 +msgid "upgrade [flags]" +msgstr "" + +#: ./cli/upgrade.go:55 +msgid "install release candidate (may contain bugs)" +msgstr "" + +#: ./cli/internal/validate.go:174 +#, c-format +msgid "validated %s as server argument" +msgstr "" + +#: ./cli/app/restore.go:124 +msgid "H" +msgstr "" + +#: ./pkg/lint/recipe.go:52 +#, c-format +msgid "%s: skip condition: %s" +msgstr "" + +#: ./pkg/recipe/recipe.go:330 +#, c-format +msgid "%s: image meta is empty?" +msgstr "" + +#: ./cli/app/new.go:343 +msgid "specify server for new app" +msgstr "" + +#: ./cli/app/backup.go:215 +msgid "Manage app backups" +msgstr "" + +#: ./cli/internal/validate.go:106 +#, c-format +msgid "validated %s as app argument" +msgstr "" + +#: ./cli/app/upgrade.go:127 +msgid "no available upgrades" +msgstr "" + +#: ./cli/app/deploy.go:31 +msgid "Deploy an app.\n" + "\n" + "This command supports chaos operations. Use \"--chaos/-C\" to deploy your recipe\n" + "checkout as-is. Recipe commit hashes are also supported as values for\n" + "\"[version]\". Please note, \"upgrade\"/\"rollback\" do not support chaos operations." +msgstr "" + +#: ./cli/app/remove.go:21 +msgid "Remove all app data, locally and remotely" +msgstr "" + +#: ./pkg/app/app.go:253 +#, c-format +msgid "env file for %s has issues: %s" +msgstr "" + +#: ./pkg/client/client.go:44 +#, c-format +msgid "unknown server, run \"abra server add %s\"?" +msgstr "" + +#: ./pkg/upstream/convert/service.go:815 +#, c-format +msgid "invalid credential spec: cannot specify both %s, and %s" +msgstr "" + +#: ./pkg/git/clone.go:64 ./pkg/git/clone.go:102 +#, c-format +msgid "git clone %s: cancelled due to interrupt" +msgstr "" + +#: ./cli/app/secret.go:526 +msgid "remove all secrets" +msgstr "" + +#: ./cli/app/new.go:284 +#, c-format +msgid "%s has no secrets to generate, skipping..." +msgstr "" + +#: ./cli/app/deploy.go:30 +msgid "Deploy an app" +msgstr "" + +#: ./cli/app/backup.go:112 +#, c-format +msgid "including SECRETS=%v in backupbot exec invocation" +msgstr "" + +#: ./cli/complete.go:12 +msgid "Generate autocompletion script" +msgstr "" + +#: ./cli/recipe/sync.go:72 +#, c-format +msgid "no git tags found for %s" +msgstr "" + +#: ./pkg/lint/recipe.go:68 +msgid "compose config has expected version" +msgstr "" + +#: ./pkg/secret/secret.go:139 +#, c-format +msgid "secret %s is > %d chars when combined with %s" +msgstr "" + +#: ./cli/app/secret.go:462 ./cli/app/secret.go:558 ./cli/app/ps.go:201 ./cli/app/list.go:314 ./cli/server/list.go:102 ./cli/recipe/upgrade.go:372 ./cli/recipe/version.go:134 ./cli/recipe/list.go:100 +msgid "print machine-readable output" +msgstr "" + +#: ./cli/app/cmd.go:24 +msgid "Run app commands" +msgstr "" + +#: ./pkg/recipe/git.go:367 +#, c-format +msgid "detected %s as tags for recipe %s" +msgstr "" + +#: ./pkg/git/branch.go:99 +#, c-format +msgid "successfully checked out %v in %s" +msgstr "" + +#: ./cli/app/upgrade.go:30 +msgid "up" +msgstr "" + +#: ./cli/recipe/fetch.go:133 +msgid "force re-fetch" +msgstr "" + +#: ./cli/recipe/list.go:42 +msgid "email" +msgstr "" + +#: ./pkg/upstream/commandconn/connection.go:38 +msgid "ssh host connection is not valid" +msgstr "" + +#: ./cli/app/undeploy.go:25 +msgid "This does not destroy any application data.\n" + "\n" + "However, you should remain vigilant, as your swarm installation will consider\n" + "any previously attached volumes as eligible for pruning once undeployed.\n" + "\n" + "Passing \"--prune/-p\" does not remove those volumes." +msgstr "" + +#: ./cli/app/backup.go:180 +msgid "List all snapshots" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:116 +msgid "volume options are incompatible with type tmpfs" +msgstr "" + +#: ./cli/app/new.go:70 ./cli/app/deploy.go:262 +msgid "cannot use [version] and --chaos together" +msgstr "" + +#: ./cli/app/config.go:16 +msgid "config [flags]" +msgstr "" + +#: ./cli/server/add.go:184 +#, c-format +msgid "server dir for %s already created" +msgstr "" + +#: ./cli/updater/updater.go:376 +#, c-format +msgid "don't update %s due to missing recipe name" +msgstr "" + +#: ./pkg/recipe/recipe.go:435 +#, c-format +msgid "detected versions %s for %s" +msgstr "" + +#: ./pkg/git/init.go:73 +msgid "set 'main' as the default branch" +msgstr "" + +#: ./cli/app/list.go:45 +msgid "List all managed apps" +msgstr "" + +#: ./cli/recipe/release.go:562 +#, c-format +msgid "please fix your synced label for %s and re-run this command" +msgstr "" + +#: ./pkg/ssh/ssh.go:16 +#, c-format +msgid "SSH host key verification failed for %s" +msgstr "" + +#: ./cli/app/secret.go:25 ./cli/catalogue/catalogue.go:25 +msgid "g" +msgstr "" + +#: ./cli/recipe/new.go:87 +msgid "happy hacking 🎉" +msgstr "" + +#: ./cli/internal/deploy.go:120 +msgid "CHAOS DEPLOY" +msgstr "" + +#: ./pkg/app/compose.go:68 +#, c-format +msgid "set label 'coop-cloud.%s.autoupdate' to %s for %s" +msgstr "" + +#: ./pkg/ui/deploy.go:83 +#, c-format +msgid "err: %v, " +msgstr "" + +#: ./cli/app/undeploy.go:143 ./cli/server/prune.go:66 +#, c-format +msgid "images pruned: %d; space reclaimed: %s" +msgstr "" + +#: ./cli/internal/command.go:110 +#, c-format +msgid "%s doesn't have a %s function" +msgstr "" + +#: ./cli/app/secret.go:459 ./cli/app/secret.go:555 ./cli/app/ps.go:198 ./cli/app/list.go:311 ./cli/server/list.go:99 ./cli/recipe/upgrade.go:369 ./cli/recipe/version.go:131 ./cli/recipe/list.go:97 +msgid "machine" +msgstr "" + +#: ./cli/recipe/sync.go:23 +msgid "Generate labels for the main recipe service.\n" + "\n" + "By convention, the service named \"app\" using the following format:\n" + "\n" + " coop-cloud.${STACK_NAME}.version=\n" + "\n" + "Where [version] can be specifed on the command-line or Abra can attempt to\n" + "auto-generate it for you. The configuration will be updated on the\n" + "local file system." +msgstr "" + +#: ./cli/recipe/release.go:29 +msgid "Create a new version of a recipe.\n" + "\n" + "These versions are then published on the Co-op Cloud recipe catalogue. These\n" + "versions take the following form:\n" + "\n" + " a.b.c+x.y.z\n" + "\n" + "Where the \"a.b.c\" part is a semantic version determined by the maintainer. The\n" + "\"x.y.z\" part is the image tag of the recipe \"app\" service (the main container\n" + "which contains the software to be used, by naming convention).\n" + "\n" + "We maintain a semantic versioning scheme (\"a.b.c\") alongside the recipe\n" + "versioning scheme (\"x.y.z\") in order to maximise the chances that the nature of\n" + "recipe updates are properly communicated. I.e. developers of an app might\n" + "publish a minor version but that might lead to changes in the recipe which are\n" + "major and therefore require intervention while doing the upgrade work.\n" + "\n" + "Publish your new release to git.coopcloud.tech with \"--publish/-p\". This\n" + "requires that you have permission to git push to these repositories and have\n" + "your SSH keys configured on your account." +msgstr "" + +#: ./cli/updater/updater.go:396 +#, c-format +msgid "don't update %s due to disabled auto updates or missing ENABLE_AUTO_UPDATE env" +msgstr "" + +#: ./cli/internal/deploy.go:167 +#, c-format +msgid "running post-command '%s %s' in container %s" +msgstr "" + +#: ./pkg/service/service.go:57 ./pkg/service/service.go:111 +msgid "ambiguous service list received, prompting for input" +msgstr "" + +#: ./pkg/lint/recipe.go:97 +msgid "use semver-like tags" +msgstr "" + +#: ./pkg/ssh/ssh.go:26 +msgid "docker: is the daemon running / your user has docker permissions?" +msgstr "" + +#: ./cli/server/prune.go:15 +msgid "prune [flags]" +msgstr "" + +#: ./cli/updater/updater.go:556 +msgid "update all deployed apps" +msgstr "" + +#: ./pkg/git/diff.go:30 +msgid "unable to locate git command, cannot output diff" +msgstr "" + +#: ./pkg/git/read.go:31 +#, c-format +msgid "unable to open worktree of %s: %s" +msgstr "" + +#: ./cli/app/deploy.go:28 +msgid "deploy [version] [flags]" +msgstr "" + +#: ./pkg/upstream/convert/service.go:834 +#, c-format +msgid "invalid credential spec: spec specifies config %v, but no such config can be found" +msgstr "" + +#: ./pkg/config/env.go:74 ./pkg/config/env.go:107 +#, c-format +msgid "broken symlink in your abra config folders: %s" +msgstr "" + +#: ./cli/app/undeploy.go:135 ./cli/server/prune.go:52 +#, c-format +msgid "networks pruned: %d" +msgstr "" + +#: ./pkg/app/compose.go:30 +#, c-format +msgid "set label 'coop-cloud.%s.chaos' to %v for %s" +msgstr "" + +#: ./cli/app/remove.go:148 +#, c-format +msgid "file: %s removed" +msgstr "" + +#: ./cli/server/prune.go:75 +#, c-format +msgid "volumes pruned: %d; space reclaimed: %s" +msgstr "" + +#: ./cli/recipe/upgrade.go:247 +#, c-format +msgid "unable to determine versioning semantics of %s, listing all tags" +msgstr "" + +#: ./pkg/upstream/convert/service.go:462 +#, c-format +msgid "undefined config %q" +msgstr "" + +#: ./cli/app/rollback.go:142 +msgid "unknown deployed version, unable to downgrade" +msgstr "" + +#: ./cli/app/remove.go:19 +msgid "remove [flags]" +msgstr "" + +#: ./cli/app/remove.go:50 +#, c-format +msgid "ALERTA ALERTA: deleting %s data and config (local/remote)" +msgstr "" + +#: ./cli/app/volume.go:162 +msgid "'x' indicates selected, enter / return to confirm, ctrl-c to exit, vim mode is enabled" +msgstr "" + +#: ./cli/run.go:49 +#, c-format +msgid "unable to create %s: %s" +msgstr "" + +#: ./cli/server/add.go:202 +msgid "use local server" +msgstr "" + +#: ./cli/recipe/upgrade.go:216 +#, c-format +msgid "upgrading service %s from %s to %s (pinned tag: %s)" +msgstr "" + +#: ./cli/recipe/release.go:133 +#, c-format +msgid "no tag specified and no previous tag available for %s, assuming this is the initial release" +msgstr "" + +#: ./cli/recipe/release.go:185 +msgid "app service is missing image tag?" +msgstr "" + +#: ./cli/updater/updater.go:231 +#, c-format +msgid "%s (%s) can be upgraded from version %s to %s" +msgstr "" + +#: ./pkg/lint/recipe.go:140 +msgid "one service named 'app'" +msgstr "" + +#: ./cli/app/restart.go:24 +msgid "This command restarts services within a deployed app.\n" + "\n" + "Run \"abra app ps \" to see a list of service names.\n" + "\n" + "Pass \"--all-services/-a\" to restart all services." +msgstr "" + +#: ./cli/app/deploy.go:96 +#, c-format +msgid "%s is already deployed" +msgstr "" + +#: ./cli/recipe/upgrade.go:380 +msgid "list all tags, not just upgrades" +msgstr "" + +#: ./cli/recipe/version.go:19 +msgid "List recipe versions" +msgstr "" + +#: ./pkg/app/app.go:510 +#, c-format +msgid "adding env vars to %s service config" +msgstr "" + +#: ./pkg/lint/recipe.go:141 +msgid "name a servce 'app'" +msgstr "" + +#: ./pkg/recipe/recipe.go:462 +#, c-format +msgid "recipe metadata retrieved for %s" +msgstr "" + +#: ./cli/app/upgrade.go:434 ./cli/app/rollback.go:323 ./cli/app/deploy.go:334 ./cli/app/remove.go:155 ./cli/app/volume.go:198 ./cli/recipe/fetch.go:130 +msgid "force" +msgstr "" + +#: ./cli/server/prune.go:18 +msgid "Prunes unused containers, networks, and dangling images.\n" + "\n" + "Use \"--volumes/-v\" to remove volumes that are not associated with a deployed\n" + "app. This can result in unwanted data loss if not used carefully." +msgstr "" + +#: ./cli/internal/command.go:70 +#, c-format +msgid "%s does not exist for %s, use /bin/sh as fallback" +msgstr "" + +#: ./pkg/git/remote.go:15 +#, c-format +msgid "dry run: remote %s (%s) not created" +msgstr "" + +#: ./pkg/container/container.go:44 +#, c-format +msgid "expected 1 container but found %v: %s" +msgstr "" + +#: ./cli/app/secret.go:444 +msgid "Manage app secrets" +msgstr "" + +#: ./cli/server/add.go:23 +msgid "Add a new server" +msgstr "" + +#: ./cli/recipe/lint.go:115 +#, c-format +msgid "critical errors present in %s config" +msgstr "" + +#: ./pkg/lint/recipe.go:90 +msgid "tag all images with stable tags" +msgstr "" + +#: ./pkg/lint/recipe.go:170 +msgid "vendor config versions in an abra.sh" +msgstr "" + +#: ./pkg/lint/recipe.go:496 +#, c-format +msgid "unable to list local tags for %s" +msgstr "" + +#: ./cli/app/backup.go:68 +msgid "Downloads a backup.tar.gz to the current working directory.\n" + "\n" + "\"--volumes/-v\" includes data contained in volumes alongide paths specified in\n" + "\"backupbot.backup.path\" labels." +msgstr "" + +#: ./cli/run.go:126 ./cli/updater/updater.go:493 +msgid "show debug messages" +msgstr "" + +#: ./pkg/app/app.go:400 +#, c-format +msgid "copied & templated %s to %s" +msgstr "" + +#: ./pkg/lint/recipe.go:504 +msgid "invalid lightweight tag detected" +msgstr "" + +#: ./cli/app/new.go:374 +msgid "automatically generate secrets" +msgstr "" + +#: ./cli/app/restart.go:164 +msgid "restart all services" +msgstr "" + +#: ./pkg/ui/deploy.go:341 +#, c-format +msgid "%s: %s (retries: %v, healthcheck: %s)" +msgstr "" + +#: ./pkg/config/abra.go:34 +#, c-format +msgid "error loading config file: %s" +msgstr "" + +#: ./pkg/recipe/git.go:434 +#, c-format +msgid "%s service is missing image tag?" +msgstr "" + +#: ./pkg/git/init.go:60 +#, c-format +msgid "set reference: %s" +msgstr "" + +#: ./cli/app/new.go:266 +msgid "Specify app domain" +msgstr "" + +#: ./pkg/lint/recipe.go:169 +msgid "config version are vendored" +msgstr "" + +#: ./cli/app/secret.go:394 ./cli/app/ps.go:182 ./cli/app/list.go:221 ./cli/recipe/version.go:62 ./cli/recipe/version.go:103 +msgid "VERSION" +msgstr "" + +#: ./cli/app/undeploy.go:23 +msgid "un" +msgstr "" + +#: ./cli/app/volume.go:161 +msgid "which volumes do you want to remove?" +msgstr "" + +#: ./cli/catalogue/catalogue.go:175 +#, c-format +msgid "generated recipe catalogue: %s" +msgstr "" + +#: ./cli/recipe/upgrade.go:243 +#, c-format +msgid "upgrade to which tag? (service: %s, image: %s, tag: %s)" +msgstr "" + +#: ./pkg/git/read.go:45 +#, c-format +msgid "unable to query status of %s: %s" +msgstr "" + +#: ./cli/app/backup.go:263 +msgid "path" +msgstr "" + +#: ./cli/recipe/release.go:413 +#, c-format +msgid "new release published: %s" +msgstr "" + +#: ./cli/app/list.go:148 +#, c-format +msgid "unable to clone %s: %s" +msgstr "" + +#: ./cli/server/remove.go:20 +msgid "Remove a managed server.\n" + "\n" + "Abra will remove the internal bookkeeping ($ABRA_DIR/servers/...) and\n" + "underlying client connection context. This server will then be lost in time,\n" + "like tears in rain." +msgstr "" + +#: ./pkg/service/service.go:95 +#, c-format +msgid "no services matching the %v filter found?" +msgstr "" + +#: ./pkg/secret/pass.go:15 ./pkg/secret/pass.go:37 +msgid "pass command not found on $PATH, is it installed?" +msgstr "" + +#: ./cli/app/volume.go:145 +#, c-format +msgid "unable to remove volume: no volume with name '%s'?" +msgstr "" + +#: ./cli/updater/updater.go:155 ./pkg/app/compose.go:86 +#, c-format +msgid "no %s label found for %s" +msgstr "" + +#: ./pkg/secret/secret.go:212 +#, c-format +msgid "attempting to generate and store %s on %s" +msgstr "" + +#: ./cli/app/cmd.go:119 +#, c-format +msgid "--local detected, running %s on local work station" +msgstr "" + +#: ./cli/app/secret.go:102 +msgid "no secrets generated" +msgstr "" + +#: ./cli/app/secret.go:483 ./cli/app/secret.go:523 ./cli/app/backup.go:239 ./cli/server/prune.go:90 ./cli/recipe/fetch.go:114 ./cli/updater/updater.go:553 +msgid "all" +msgstr "" + +#: ./cli/app/new.go:371 ./cli/app/backup.go:271 +msgid "secrets" +msgstr "" + +#: ./cli/app/restart.go:21 +msgid "restart [[service] | --all-services] [flags]" +msgstr "" + +#: ./cli/server/add.go:40 +msgid " abra server add 1312.net" +msgstr "" + +#: ./cli/app/secret.go:253 +#, c-format +msgid "deleted %s successfully from local pass store" +msgstr "" + +#: ./cli/app/new.go:49 +msgid "Create a new app" +msgstr "" + +#: ./cli/app/remove.go:141 +msgid "no volumes to remove" +msgstr "" + +#: ./cli/app/run.go:24 +msgid " # run with args/flags\n" + " abra app run 1312.net app -- ls -lha\n" + "\n" + " # run without args/flags\n" + " abra app run 1312.net app bash --user nobody\n" + "\n" + " # run with both kinds of args/flags \n" + " abra app run 1312.net app --user nobody -- ls -lha" +msgstr "" + +#: ./cli/app/upgrade.go:152 +#, c-format +msgid "choosing %s as version to upgrade" +msgstr "" + +#: ./cli/recipe/fetch.go:117 +msgid "fetch all recipes" +msgstr "" + +#: ./pkg/recipe/recipe.go:458 +#, c-format +msgid "recipe %s does not exist?" +msgstr "" + +#: ./cli/app/restore.go:118 +msgid "restore specific volumes" +msgstr "" + +#: ./cli/app/upgrade.go:415 ./cli/app/undeploy.go:51 ./cli/app/deploy.go:88 +#, c-format +msgid "checking whether %s is already deployed" +msgstr "" + +#: ./cli/app/upgrade.go:450 ./cli/app/rollback.go:339 ./cli/app/deploy.go:350 +msgid "no-converge-checks" +msgstr "" + +#: ./cli/app/env.go:41 +msgid "ENV OVERVIEW" +msgstr "" + +#: ./pkg/lint/recipe.go:69 +msgid "ensure 'version: \"3.8\"' in compose configs" +msgstr "" + +#: ./cli/internal/deploy.go:80 +msgid "CURRENT DEPLOYMENT" +msgstr "" + +#: ./pkg/client/client.go:97 +#, c-format +msgid "swarm mode not enabled on %s?" +msgstr "" + +#: ./pkg/client/volumes.go:41 +#, c-format +msgid "volume %s: %s" +msgstr "" + +#: ./cli/app/deploy.go:276 +#, c-format +msgid "secret not generated: %s" +msgstr "" + +#: ./cli/app/volume.go:76 +msgid "remove [volume] [flags]" +msgstr "" + +#: ./cli/recipe/fetch.go:21 +msgid "Using \"--force/-f\" Git syncs an existing recipe. It does not erase unstaged changes." +msgstr "" + +#: ./pkg/upstream/convert/service.go:774 +msgid "replicas can only be used with replicated mode" +msgstr "" + +#: ./cli/app/new.go:315 +msgid "Select app server:" +msgstr "" + +#: ./cli/recipe/upgrade.go:44 +msgid "Upgrade a given configuration.\n" + "\n" + "It will update the relevant compose file tags on the local file system.\n" + "\n" + "Some image tags cannot be parsed because they do not follow some sort of\n" + "semver-like convention. In this case, all possible tags will be listed and it\n" + "is up to the end-user to decide.\n" + "\n" + "The command is interactive and will show a select input which allows you to\n" + "make a seclection. Use the \"?\" key to see more help on navigating this\n" + "interface.\n" + "\n" + "You may invoke this command in \"wizard\" mode and be prompted for input." +msgstr "" + +#: ./cli/recipe/fetch.go:64 +#, c-format +msgid "unable to discover SSH remote for %s" +msgstr "" + +#: ./cli/recipe/release.go:283 +msgid "Use release note in release/next?" +msgstr "" + +#: ./cli/app/remove.go:38 +msgid " abra app remove 1312.net" +msgstr "" + +#: ./cli/app/remove.go:53 +msgid "are you sure?" +msgstr "" + +#: ./cli/run.go:159 +msgid "force select language (supported: XXX)" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:96 +msgid "tmpfs options are incompatible with type bind" +msgstr "" + +#: ./cli/app/upgrade.go:318 +#, c-format +msgid "parsing chosen upgrade version failed: %s" +msgstr "" + +#: ./cli/recipe/new.go:36 +msgid "Create a new recipe" +msgstr "" + +#: ./cli/recipe/new.go:126 +msgid "Git email name to do commits with" +msgstr "" + +#: ./cli/recipe/release.go:387 +#, c-format +msgid "created tag %s at %s" +msgstr "" + +#: ./pkg/recipe/compose.go:59 +#, c-format +msgid "retrieved %s configs for %s" +msgstr "" + +#: ./cli/app/secret.go:366 +msgid "no secrets to remove?" +msgstr "" + +#: ./cli/app/deploy.go:180 +msgid "skipping domain checks" +msgstr "" + +#: ./cli/app/backup.go:67 +msgid "Download a snapshot" +msgstr "" + +#: ./cli/upgrade.go:19 +msgid "Upgrade abra in-place with the latest stable or release candidate.\n" + "\n" + "By default, the latest stable release is downloaded.\n" + "\n" + "Use \"--rc/-r\" to install the latest release candidate. Please bear in mind that\n" + "it may contain absolutely catastrophic deal-breaker bugs. Thank you very much\n" + "for the testing efforts 💗" +msgstr "" + +#: ./cli/server/add.go:24 +msgid "Add a new server to your configuration so that it can be managed by Abra.\n" + "\n" + "Abra relies on the standard SSH command-line and ~/.ssh/config for client\n" + "connection details. You must configure an entry per-host in your ~/.ssh/config\n" + "for each server:\n" + "\n" + " Host 1312.net 1312\n" + " Hostname 1312.net\n" + " User antifa\n" + " Port 12345\n" + " IdentityFile ~/.ssh/antifa@somewhere\n" + "\n" + "If \"--local\" is passed, then Abra assumes that the current local server is\n" + "intended as the target server. This is useful when you want to have your entire\n" + "Co-op Cloud config located on the server itself, and not on your local\n" + "developer machine. The domain is then set to \"default\"." +msgstr "" + +#: ./cli/recipe/diff.go:13 +msgid "diff [flags]" +msgstr "" + +#: ./pkg/app/app.go:487 +#, c-format +msgid "retrieved app statuses: %s" +msgstr "" + +#: ./pkg/container/container.go:69 +msgid "failed to match chosen container" +msgstr "" + +#: ./cli/app/new.go:372 ./cli/app/logs.go:102 ./cli/app/backup.go:272 ./cli/app/list.go:289 +msgid "S" +msgstr "" + +#: ./cli/app/secret.go:394 +msgid "GENERATED NAME" +msgstr "" + +#: ./cli/recipe/diff.go:15 +msgid "Show unstaged changes in recipe config" +msgstr "" + +#: ./cli/server/add.go:107 +#, c-format +msgid "ssh %s error: %s" +msgstr "" + +#: ./cli/recipe/lint.go:33 +msgid "rule" +msgstr "" + +#: ./cli/internal/validate.go:171 +msgid "server doesn't exist?" +msgstr "" + +#: ./pkg/upstream/container/hijack.go:167 +#, c-format +msgid "error sendStdin: %s" +msgstr "" + +#: ./pkg/recipe/recipe.go:237 +#, c-format +msgid "%s: attempt recipe metadata parse" +msgstr "" + +#: ./cli/app/upgrade.go:458 +msgid "releasenotes" +msgstr "" + +#: ./cli/app/undeploy.go:104 +msgid "undeploy succeeded 🟢" +msgstr "" + +#: ./cli/app/cp.go:272 +msgid "can't copy dir to file" +msgstr "" + +#: ./cli/server/add.go:146 +#, c-format +msgid "serverAdd: cleanUp: failed to remove %s: %s" +msgstr "" + +#: ./pkg/secret/secret.go:207 +#, c-format +msgid "skipping generation of %s (generate=false)" +msgstr "" + +#: ./cli/app/cp.go:197 +#, c-format +msgid "remote: %s does not exist" +msgstr "" + +#: ./pkg/recipe/compose.go:72 +#, c-format +msgid "%s is missing a compose.yml or compose.*.yml file?" +msgstr "" + +#: ./pkg/recipe/compose.go:159 +#, c-format +msgid "parsed %s from %s" +msgstr "" + +#: ./cli/app/secret.go:499 +msgid "file" +msgstr "" + +#: ./cli/run.go:78 +#, c-format +msgid "abra version: %s, commit: %s, lang: %s" +msgstr "" + +#: ./pkg/app/app.go:424 +msgid "querying remote servers..." +msgstr "" + +#: ./pkg/secret/secret.go:126 +#, c-format +msgid "missing version for secret? (%s)" +msgstr "" + +#: ./pkg/upstream/convert/service.go:122 +#, c-format +msgid "duplicate config target for %s not allowed" +msgstr "" + +#: ./cli/app/restore.go:79 +#, c-format +msgid "including NO_COMMANDS=%v in backupbot exec invocation" +msgstr "" + +#: ./cli/app/check.go:17 +msgid "check [flags]" +msgstr "" + +#: ./cli/app/cp.go:72 ./cli/internal/command.go:39 +#, c-format +msgid "retrieved %s as target container on %s" +msgstr "" + +#: ./cli/app/remove.go:59 +msgid "aborting as requested" +msgstr "" + +#: ./cli/app/logs.go:101 +msgid "since" +msgstr "" + +#: ./cli/run.go:150 +msgid "ignore .env version checkout" +msgstr "" + +#: ./pkg/ui/deploy.go:88 +#, c-format +msgid "status: %s}" +msgstr "" + +#: ./cli/app/undeploy.go:24 +msgid "Undeploy an app" +msgstr "" + +#: ./cli/app/deploy.go:290 +#, c-format +msgid "version: taking chaos version: %s" +msgstr "" + +#: ./cli/app/env.go:15 +msgid "env [flags]" +msgstr "" + +#: ./pkg/lint/recipe.go:154 +msgid "traefik routing enabled" +msgstr "" + +#: ./cli/app/secret.go:372 +msgid "list " +msgstr "" + +#: ./cli/app/new.go:47 +msgid "new [recipe] [version] [flags]" +msgstr "" + +#: ./cli/run.go:34 +msgid "upgrade" +msgstr "" + +#: ./cli/recipe/upgrade.go:330 ./cli/recipe/sync.go:211 ./cli/recipe/release.go:121 +#, c-format +msgid "%s currently has these unstaged changes 👇" +msgstr "" + +#: ./pkg/upstream/convert/service.go:375 +#, c-format +msgid "undefined network %q" +msgstr "" + +#: ./cli/updater/updater.go:76 +msgid "Upgrade apps" +msgstr "" + +#: ./pkg/lint/recipe.go:212 +#, c-format +msgid "recipe '%s' failed lint checks:\n" + "%s" +msgstr "" + +#: ./cli/app/check.go:20 +msgid "Compare env vars in both the app \".env\" and recipe \".env.sample\" file.\n" + "\n" + "The goal is to ensure that recipe \".env.sample\" env vars are defined in your\n" + "app \".env\" file. Only env var definitions in the \".env.sample\" which are\n" + "uncommented, e.g. \"FOO=bar\" are checked. If an app \".env\" file does not include\n" + "these env vars, then \"check\" will complain.\n" + "\n" + "Recipe maintainers may or may not provide defaults for env vars within their\n" + "recipes regardless of commenting or not (e.g. through the use of\n" + "${FOO:} syntax). \"check\" does not confirm or deny this for you." +msgstr "" + +#: ./cli/server/add.go:114 +#, c-format +msgid "unable to resolve IPv4 for %s" +msgstr "" + +#: ./cli/app/deploy.go:311 +#, c-format +msgid "version: taking deployed version: %s" +msgstr "" + +#: ./cli/updater/updater.go:273 +#, c-format +msgid "no published releases for %s in the recipe catalogue?" +msgstr "" + +#: ./cli/updater/updater.go:548 +msgid "check for major updates" +msgstr "" + +#: ./pkg/ui/deploy.go:333 +msgid "rolled back" +msgstr "" + +#: ./pkg/recipe/git.go:156 +#, c-format +msgid "attempting to checkout '%s' as chaos commit" +msgstr "" + +#: ./cli/app/restart.go:133 +#, c-format +msgid "attempting to scale %s to 1" +msgstr "" + +#: ./cli/app/volume.go:190 +msgid "volume [cmd] [args] [flags]" +msgstr "" + +#: ./cli/app/backup.go:178 +msgid "snapshots [flags]" +msgstr "" + +#: ./cli/recipe/sync.go:154 +msgid "you can only use one version flag: --major, --minor or --patch" +msgstr "" + +#: ./pkg/recipe/git.go:378 +#, c-format +msgid "git: opening repository in %s" +msgstr "" + +#: ./pkg/recipe/recipe.go:207 +#, c-format +msgid "sample env: %s, " +msgstr "" + +#: ./cli/app/secret.go:246 +#, c-format +msgid "deleted %s successfully from server" +msgstr "" + +#: ./cli/recipe/upgrade.go:218 +#, c-format +msgid "service %s, image %s pinned to %s, no compatible upgrade found" +msgstr "" + +#: ./pkg/lint/recipe.go:22 +msgid "critical" +msgstr "" + +#: ./pkg/upstream/container/tty.go:39 +#, c-format +msgid "error resize: %s" +msgstr "" + +#: ./pkg/upstream/convert/service.go:780 +#, c-format +msgid "unknown mode: %s" +msgstr "" + +#: ./cli/app/secret.go:374 +msgid "List all secrets" +msgstr "" + +#: ./cli/app/restore.go:57 +#, c-format +msgid "including TARGET=%s in backupbot exec invocation" +msgstr "" + +#: ./cli/app/cmd.go:128 ./cli/app/cmd.go:174 +#, c-format +msgid "parsed following command arguments: %s" +msgstr "" + +#: ./cli/app/upgrade.go:266 ./cli/app/deploy.go:229 +#, c-format +msgid "run the following post-deploy commands: %s" +msgstr "" + +#: ./pkg/upstream/container/hijack.go:132 +msgid "[hijack] end of stdout" +msgstr "" + +#: ./pkg/formatter/formatter.go:134 +msgid "CreateOverview: only accepts rows of len == 2" +msgstr "" + +#: ./cli/app/backup.go:247 +msgid "timestamps" +msgstr "" + +#: ./cli/app/list.go:46 +msgid "Generate a report of all managed apps.\n" + "\n" + "Use \"--status/-S\" flag to query all servers for the live deployment status." +msgstr "" + +#: ./cli/catalogue/catalogue.go:235 +msgid "Manage the recipe catalogue" +msgstr "" + +#: ./pkg/secret/pass.go:51 +#, c-format +msgid "%s removed from pass store" +msgstr "" + +#: ./pkg/recipe/compose.go:58 +#, c-format +msgid "COMPOSE_FILE detected (%s), loading %s" +msgstr "" + +#: ./cli/app/secret.go:486 +msgid "generate all secrets" +msgstr "" + +#: ./cli/app/new.go:355 +msgid "domain" +msgstr "" + +#: ./cli/app/volume.go:78 +msgid "Remove volumes associated with an app.\n" + "\n" + "The app in question must be undeployed before you try to remove volumes. See\n" + "\"abra app undeploy \" for more.\n" + "\n" + "The command is interactive and will show a multiple select input which allows\n" + "you to make a seclection. Use the \"?\" key to see more help on navigating this\n" + "interface.\n" + "\n" + "Passing \"--force/-f\" will select all volumes for removal. Be careful." +msgstr "" + +#: ./cli/app/list.go:43 ./cli/server/list.go:18 +msgid "list [flags]" +msgstr "" + +#: ./cli/recipe/fetch.go:23 +msgid " # fetch from recipe catalogue\n" + " abra recipe fetch gitea\n" + "\n" + " # fetch from remote recipe\n" + " abra recipe fetch git.foo.org/recipes/myrecipe\n" + "\n" + " # fetch with ssh remote for hacking\n" + " abra recipe fetch gitea --ssh" +msgstr "" + +#: ./pkg/git/clone.go:68 +msgid "git clone: main branch failed, attempting master branch" +msgstr "" + +#: ./pkg/recipe/compose.go:248 +msgid "no existing label found, automagic insertion not supported yet" +msgstr "" + +#: ./cli/app/run.go:21 +msgid "run [[args] [flags] | [flags] -- [args]]" +msgstr "" + +#: ./cli/app/cmd.go:168 +#, c-format +msgid "no service %s for %s?" +msgstr "" + +#: ./cli/recipe/reset.go:13 +msgid "reset [flags]" +msgstr "" + +#: ./cli/updater/updater.go:444 +#, c-format +msgid "upgrade %s (%s) to version %s" +msgstr "" + +#: ./pkg/git/init.go:21 +#, c-format +msgid "git branch rename: %s" +msgstr "" + +#: ./pkg/git/branch.go:68 +#, c-format +msgid "failed to select default branch in %s" +msgstr "" + +#: ./cli/recipe/upgrade.go:296 +#, c-format +msgid "tag upgraded from %s to %s for %s" +msgstr "" + +#: ./pkg/client/context.go:26 +#, c-format +msgid "created the %s context" +msgstr "" + +#: ./pkg/upstream/commandconn/commandconn.go:49 +#, c-format +msgid "commandconn: starting %s with %v" +msgstr "" + +#: ./pkg/git/common.go:13 +#, c-format +msgid "no .git directory in %s?" +msgstr "" + +#: ./cli/app/backup.go:167 +#, c-format +msgid "including RETRIES=%s in backupbot exec invocation" +msgstr "" + +#: ./cli/recipe/fetch.go:93 +msgid "fetching latest recipes..." +msgstr "" + +#: ./cli/app/restore.go:115 ./cli/app/backup.go:279 ./cli/server/prune.go:98 +msgid "volumes" +msgstr "" + +#: ./cli/app/undeploy.go:22 +msgid "undeploy [flags]" +msgstr "" + +#: ./cli/app/config.go:19 +msgid " abra config 1312.net" +msgstr "" + +#: ./cli/app/backup.go:214 +msgid "b" +msgstr "" + +#: ./cli/catalogue/catalogue.go:250 ./cli/recipe/release.go:611 +msgid "publish changes to git.coopcloud.tech" +msgstr "" + +#: ./cli/server/server.go:12 +msgid "Manage servers" +msgstr "" + +#: ./cli/app/secret.go:53 +msgid "missing arguments [secret]/[version] or '--all'" +msgstr "" + +#: ./cli/app/new.go:236 ./pkg/app/app.go:141 +#, c-format +msgid "trimming %s to %s to avoid runtime limits" +msgstr "" + +#: ./cli/app/volume.go:191 +msgid "vl" +msgstr "" + +#: ./pkg/config/abra.go:37 +#, c-format +msgid "config file loaded from: %s" +msgstr "" + +#: ./cli/app/restore.go:62 +#, c-format +msgid "including NONINTERACTIVE=%v in backupbot exec invocation" +msgstr "" + +#: ./cli/app/new.go:366 +msgid "store secrets in a local pass store" +msgstr "" + +#: ./cli/app/cmd.go:265 +msgid "T" +msgstr "" + +#: ./cli/recipe/new.go:50 +#, c-format +msgid "%s recipe directory already exists?" +msgstr "" + +#: ./cli/recipe/release.go:487 +#, c-format +msgid "latest git tag (%s) and synced label (%s) are the same?" +msgstr "" + +#: ./cli/recipe/release.go:552 +#, c-format +msgid "discovered %s as currently synced recipe label" +msgstr "" + +#: ./pkg/catalogue/catalogue.go:84 ./pkg/recipe/git.go:278 +#, c-format +msgid "fetched latest git changes for %s" +msgstr "" + +#: ./pkg/app/app.go:301 +#, c-format +msgid "server %s doesn't exist? Run \"abra server ls\" to check" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:56 +#, c-format +msgid "undefined volume %q" +msgstr "" + +#: ./cli/app/secret.go:137 +msgid "NOW" +msgstr "" + +#: ./cli/recipe/upgrade.go:119 +#, c-format +msgid "did not find versions file for %s" +msgstr "" + +#: ./cli/app/cmd.go:108 ./cli/internal/deploy.go:151 +#, c-format +msgid "%s does not exist for %s?" +msgstr "" + +#: ./cli/catalogue/catalogue.go:258 ./cli/recipe/sync.go:225 ./cli/recipe/release.go:579 +msgid "report changes that would be made" +msgstr "" + +#: ./cli/internal/deploy.go:86 +#, c-format +msgid "%s OVERVIEW" +msgstr "" + +#: ./pkg/envfile/envfile.go:73 +#, c-format +msgid "couldn't parse %s" +msgstr "" + +#: ./pkg/recipe/git.go:241 +#, c-format +msgid "unable to read remotes in %s: %s" +msgstr "" + +#: ./cli/app/cmd.go:248 ./cli/server/add.go:199 ./cli/server/list.go:69 +msgid "local" +msgstr "" + +#: ./cli/recipe/upgrade.go:145 +#, c-format +msgid "%s not considered semver-like" +msgstr "" + +#: ./cli/recipe/list.go:37 +msgid "name" +msgstr "" + +#: ./pkg/app/app.go:248 +#, c-format +msgid "env file for %s couldn't be read: %s" +msgstr "" + +#: ./pkg/lint/recipe.go:481 +#, c-format +msgid "secret %s is longer than 12 characters" +msgstr "" + +#: ./pkg/upstream/container/hijack.go:100 +#, c-format +msgid "invalid detach escape keys, using default: %s" +msgstr "" + +#: ./pkg/config/env.go:98 +#, c-format +msgid "directory is empty: %s" +msgstr "" + +#: ./cli/app/upgrade.go:240 ./cli/app/rollback.go:202 ./cli/app/deploy.go:203 +#, c-format +msgid "set waiting timeout to %d second(s)" +msgstr "" + +#: ./cli/app/restart.go:108 +#, c-format +msgid "attempting to scale %s to 0" +msgstr "" + +#: ./pkg/lint/recipe.go:125 +msgid "reduce length of secret names to 12 chars" +msgstr "" + +#: ./pkg/recipe/files.go:36 +#, c-format +msgid "%s release notes:" +msgstr "" + +#: ./pkg/git/init.go:17 +#, c-format +msgid "git init: %s" +msgstr "" + +#: ./pkg/git/init.go:47 +#, c-format +msgid "git commit: %s" +msgstr "" + +#: ./cli/app/labels.go:25 +msgid "Show deployment labels" +msgstr "" + +#: ./cli/run.go:93 +msgid " # generate the man pages into /usr/local/share/man/man1\n" + " abra_path=$(which abra) # pass abra absolute path to sudo below\n" + " sudo $abra_path man\n" + " sudo mandb\n" + "\n" + " # read the man pages\n" + " man abra\n" + " man abra-app-deploy" +msgstr "" + +#: ./pkg/app/app.go:685 +#, c-format +msgid "skipping version %s write as already exists in %s.env" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:133 +msgid "volume options are incompatible with type npipe" +msgstr "" + +#: ./pkg/git/init.go:38 +#, c-format +msgid "git add: %s" +msgstr "" + +#: ./pkg/upstream/container/hijack.go:156 +msgid "[hijack] End of stdin" +msgstr "" + +#: ./cli/app/secret.go:106 ./cli/app/secret.go:394 ./cli/app/new.go:187 ./cli/app/volume.go:47 ./cli/server/list.go:34 ./cli/recipe/version.go:103 +msgid "NAME" +msgstr "" + +#: ./cli/app/labels.go:23 +msgid "labels [flags]" +msgstr "" + +#: ./cli/recipe/version.go:62 ./cli/recipe/version.go:103 +msgid "TAG" +msgstr "" + +#: ./cli/recipe/release.go:367 +#, c-format +msgid "dry run: no git tag created (%s)" +msgstr "" + +#: ./cli/recipe/release.go:415 +msgid "no -p/--publish passed, not publishing" +msgstr "" + +#: ./pkg/git/init.go:29 +#, c-format +msgid "git open: %s" +msgstr "" + +#: ./cli/app/secret.go:510 +msgid "trim input" +msgstr "" + +#: ./cli/app/cmd.go:22 +msgid "command [service | --local] [[args] [flags] | [flags] -- [args]]" +msgstr "" + +#: ./cli/app/new.go:290 +msgid "Generate app secrets?" +msgstr "" + +#: ./cli/run.go:134 ./cli/updater/updater.go:501 +msgid "toggle non-interactive mode" +msgstr "" + +#: ./cli/recipe/new.go:34 +msgid "new [flags]" +msgstr "" + +#: ./cli/recipe/list.go:41 +msgid "backups" +msgstr "" + +#: ./pkg/config/abra.go:20 +msgid "no config file found" +msgstr "" + +#: ./pkg/git/init.go:65 +#, c-format +msgid "repo config: %s" +msgstr "" + +#: ./cli/app/cmd.go:67 +msgid "requires at least 3 arguments" +msgstr "" + +#: ./cli/app/cmd.go:171 +#, c-format +msgid "running command %s within the context of %s_%s" +msgstr "" + +#: ./cli/app/list.go:216 ./cli/internal/deploy.go:75 +msgid "DOMAIN" +msgstr "" + +#: ./cli/server/remove.go:43 +#, c-format +msgid "%s is now lost in time, like tears in rain" +msgstr "" + +#: ./cli/recipe/upgrade.go:354 ./cli/recipe/sync.go:239 ./cli/recipe/release.go:593 +msgid "y" +msgstr "" + +#: ./pkg/service/service.go:41 +#, c-format +msgid "no services deployed matching label '%s'?" +msgstr "" + +#: ./pkg/lint/recipe.go:103 +msgid "has published catalogue version" +msgstr "" + +#: ./cli/run.go:109 +#, c-format +msgid "unable to proceed, %s does not exist?" +msgstr "" + +#: ./cli/recipe/new.go:62 +#, c-format +msgid "removed .git repo in %s" +msgstr "" + +#: ./cli/recipe/reset.go:16 +msgid "WARNING: this will delete your changes. Be Careful." +msgstr "" + +#: ./cli/app/list.go:299 +msgid "show apps of a specific recipe" +msgstr "" + +#: ./cli/app/labels.go:74 +msgid "RECIPE LABELS" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:110 +msgid "invalid tmpfs source, source must be empty" +msgstr "" + +#: ./pkg/ui/deploy.go:330 +msgid "succeeded" +msgstr "" + +#: ./pkg/recipe/compose.go:107 +#, c-format +msgid "%s has no version label? try running \"abra recipe sync %s\" first?" +msgstr "" + +#: ./cli/app/restart.go:132 +#, c-format +msgid "%s has been scaled to 0" +msgstr "" + +#: ./pkg/client/volumes.go:62 +#, c-format +msgid "%d retries failed" +msgstr "" + +#: ./cli/app/app.go:9 +msgid "app [cmd] [args] [flags]" +msgstr "" + +#: ./cli/server/add.go:141 +#, c-format +msgid "serverAdd: cleanUp: %s is not empty, aborting cleanup" +msgstr "" + +#: ./pkg/lint/recipe.go:55 +#, c-format +msgid "skipping %s based on skip condition" +msgstr "" + +#: ./cli/app/config.go:36 ./pkg/app/app.go:52 +#, c-format +msgid "cannot find app with name %s" +msgstr "" + +#: ./cli/upgrade.go:26 +msgid " abra upgrade --rc" +msgstr "" + +#: ./pkg/upstream/convert/service.go:652 +#, c-format +msgid "unknown restart policy: %s" +msgstr "" + +#: ./pkg/envfile/envfile.go:82 +#, c-format +msgid "read 0 env var exports from %s" +msgstr "" + +#: ./cli/app/upgrade.go:149 +msgid "unknown deployed version, unable to upgrade" +msgstr "" + +#: ./cli/recipe/list.go:19 +msgid "List recipes" +msgstr "" + +#: ./cli/internal/deploy.go:159 +#, c-format +msgid "not enough arguments: %s" +msgstr "" + +#: ./pkg/config/abra.go:81 +msgid "read abra dir from config file" +msgstr "" + +#: ./cli/app/run.go:110 ./cli/app/cmd.go:256 +msgid "user" +msgstr "" + +#: ./pkg/upstream/convert/volume.go:113 +msgid "bind options are incompatible with type tmpfs" +msgstr "" + +#: ./pkg/config/abra.go:77 +msgid "read abra dir from $ABRA_DIR" +msgstr "" + +#: ./cli/app/secret.go:467 ./cli/app/secret.go:491 ./cli/app/secret.go:531 ./cli/app/new.go:363 +msgid "pass" +msgstr "" + +#: ./cli/app/restart.go:29 +msgid " # restart a single app service\n" + " abra app restart 1312.net app\n" + "\n" + " # restart all app services\n" + " abra app restart 1312.net -a" +msgstr "" + +#: ./cli/server/add.go:84 +msgid "local server successfully added" +msgstr "" + diff --git a/pkg/i18n/locales/es/LC_MESSAGES/default.po b/pkg/i18n/locales/es/LC_MESSAGES/default.po new file mode 100644 index 00000000..18ffa862 --- /dev/null +++ b/pkg/i18n/locales/es/LC_MESSAGES/default.po @@ -0,0 +1,4912 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: EMAIL\n" +"POT-Creation-Date: 2025-08-23 15:58+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: pkg/recipe/git.go:410 +#, c-format +msgid "git checkout: %s in %s" +msgstr "" + +#: cli/app/secret.go:475 cli/app/secret.go:515 cli/app/secret.go:539 +#: cli/app/secret.go:547 cli/app/restore.go:131 cli/app/ps.go:206 +#: cli/app/cmd.go:272 cli/app/new.go:379 cli/app/check.go:87 +#: cli/app/restart.go:154 cli/app/deploy.go:326 cli/app/cp.go:378 +#: cli/app/backup.go:287 cli/app/backup.go:303 cli/app/labels.go:135 +#: cli/catalogue/catalogue.go:271 cli/recipe/lint.go:128 +#: cli/updater/updater.go:537 +msgid "chaos" +msgstr "" + +#: cli/app/upgrade.go:208 cli/app/deploy.go:166 +#, c-format +msgid "%s missing from %s.env" +msgstr "" + +#: cli/app/upgrade.go:397 +#, c-format +msgid "'%s' is not a known version" +msgstr "" + +#: cli/app/backup.go:298 +msgid "number of retry attempts" +msgstr "" + +#: cli/server/add.go:128 +#, c-format +msgid "serverAdd: cleanUp: cleaning up context for %s" +msgstr "" + +#: pkg/client/volumes.go:58 +#, c-format +msgid "%s: waiting %d seconds before next retry" +msgstr "" + +#: pkg/upstream/convert/volume.go:162 +msgid "volume type must be volume, bind, tmpfs or npipe" +msgstr "" + +#: pkg/ui/deploy.go:121 +#, c-format +msgid "^%s" +msgstr "" + +#: cli/app/ps.go:119 cli/app/ps.go:120 cli/app/ps.go:121 cli/app/ps.go:122 +#: cli/app/ps.go:123 cli/app/list.go:111 cli/app/list.go:112 +#: cli/app/list.go:113 cli/app/list.go:114 cli/app/list.go:115 +#: cli/app/list.go:175 cli/app/labels.go:71 cli/server/list.go:59 +#: cli/server/list.go:71 +msgid "unknown" +msgstr "" + +#: cli/app/new.go:211 +#, c-format +msgid "secrets are %s shown again, please save them %s" +msgstr "" + +#: pkg/recipe/git.go:274 +#, c-format +msgid "unable to git pull in %s: %s" +msgstr "" + +#: cli/app/secret.go:261 cli/app/remove.go:20 cli/app/volume.go:93 +#: cli/server/remove.go:18 +msgid "rm" +msgstr "" + +#: cli/app/run.go:23 +msgid "Run a command inside a service container" +msgstr "" + +#: cli/server/add.go:137 +#, c-format +msgid "serverAdd: cleanUp: unable to list files in %s: %s" +msgstr "" + +#: cli/recipe/upgrade.go:280 +msgid "" +"enter / return to confirm, choose 'skip' to not upgrade this tag, vim mode " +"is enabled" +msgstr "" + +#: cli/updater/updater.go:473 +msgid "The Co-op Cloud auto-updater 🤖 🚀" +msgstr "" + +#: cli/app/config.go:17 +msgid "cfg" +msgstr "" + +#: cli/app/backup.go:274 +msgid "include secrets" +msgstr "" + +#: pkg/app/app.go:683 +#, c-format +msgid "version %s saved to %s.env" +msgstr "" + +#: cli/app/secret.go:230 +#, c-format +msgid "%s successfully stored on server" +msgstr "" + +#: cli/updater/updater.go:38 +msgid "" +"Notify on new versions for deployed apps.\n" +"\n" +"If a new patch/minor version is available, a notification is printed.\n" +"\n" +"Use \"--major/-m\" to include new major versions." +msgstr "" + +#: pkg/client/context.go:66 +msgid "context 'default' cannot be removed" +msgstr "" + +#: pkg/recipe/compose.go:233 +#, c-format +msgid "%s is already set, nothing to do?" +msgstr "" + +#: cli/app/env.go:16 cli/recipe/new.go:124 cli/recipe/lint.go:137 +msgid "e" +msgstr "" + +#: cli/recipe/upgrade.go:222 +#, c-format +msgid "" +"service %s is at version %s, but pinned to %s, please correct your " +"compose.yml file manually!" +msgstr "" + +#: cli/updater/updater.go:103 +msgid "missing arguments or --all/-a flag" +msgstr "" + +#: pkg/web/web.go:45 +#, c-format +msgid "bad status: %s" +msgstr "" + +#: cli/app/cmd.go:23 +msgid "cmd" +msgstr "" + +#: cli/app/services.go:21 +msgid "services [flags]" +msgstr "" + +#: cli/app/cmd.go:251 +msgid "run command locally" +msgstr "" + +#: cli/recipe/fetch.go:44 +msgid "missing [recipe] or --all/-a" +msgstr "" + +#: pkg/git/read.go:149 +#, c-format +msgid "read global ignore paths: %s" +msgstr "" + +#: cli/run.go:28 +msgid "app" +msgstr "" + +#: cli/recipe/diff.go:16 +msgid "This command requires /usr/bin/git." +msgstr "" + +#: pkg/upstream/container/hijack.go:82 +#, c-format +msgid "unable to set IO streams as raw terminal: %s" +msgstr "" + +#: cli/app/cmd.go:51 +msgid "accepts at most 2 args with --local/-l" +msgstr "" + +#: cli/app/restart.go:143 +#, c-format +msgid "%s has been scaled to 1" +msgstr "" + +#: cli/recipe/lint.go:37 +msgid "resolve" +msgstr "" + +#: pkg/lint/recipe.go:162 +msgid "all services have images" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:162 +#, c-format +msgid "command %v did not exit after %v: stderr=%q" +msgstr "" + +#: pkg/recipe/recipe.go:406 +#, c-format +msgid "read recipe catalogue from file system cache in %s" +msgstr "" + +#: cli/app/rollback.go:42 +msgid "" +" # standard rollback\n" +" abra app rollback 1312.net\n" +"\n" +" # rollback to specific version\n" +" abra app rollback 1312.net 2.0.0+1.2.3" +msgstr "" + +#: cli/recipe/release.go:492 +#, c-format +msgid "current: %s, new: %s, correct?" +msgstr "" + +#: cli/internal/backup.go:62 +#, c-format +msgid "running backup %s on %s with exec config %v" +msgstr "" + +#: pkg/recipe/recipe.go:659 +msgid "retrieving recipes" +msgstr "" + +#: cli/app/upgrade.go:31 +msgid "Upgrade an app" +msgstr "" + +#: cli/app/new.go:340 cli/app/new.go:347 cli/app/list.go:319 +#: cli/app/list.go:326 cli/run.go:33 +msgid "server" +msgstr "" + +#: cli/internal/deploy.go:82 +msgid "NEW DEPLOYMENT" +msgstr "" + +#: pkg/recipe/recipe.go:175 +#, c-format +msgid "failed to check git status of %s: %s" +msgstr "" + +#: cli/app/cp.go:164 +#, c-format +msgid "copy %s from local to %s on container" +msgstr "" + +#: cli/recipe/fetch.go:70 pkg/lint/recipe.go:491 pkg/recipe/git.go:236 +#: pkg/git/read.go:26 +#, c-format +msgid "unable to open %s: %s" +msgstr "" + +#: cli/recipe/fetch.go:74 +#, c-format +msgid "unable to remove default remote in %s: %s" +msgstr "" + +#: cli/recipe/lint.go:139 +msgid "only show errors" +msgstr "" + +#: pkg/lint/recipe.go:21 pkg/lint/recipe.go:67 pkg/lint/recipe.go:74 +#: pkg/lint/recipe.go:81 pkg/lint/recipe.go:88 pkg/lint/recipe.go:95 +#: pkg/lint/recipe.go:102 pkg/lint/recipe.go:109 pkg/lint/recipe.go:116 +#: pkg/lint/recipe.go:123 +msgid "warn" +msgstr "" + +#: pkg/git/clone.go:89 +#, c-format +msgid "git clone: %s already exists" +msgstr "" + +#: cli/app/new.go:309 +#, c-format +msgid "single server detected, choosing %s automatically" +msgstr "" + +#: cli/app/backup.go:266 +msgid "volumes path" +msgstr "" + +#: cli/recipe/list.go:40 +msgid "healthcheck" +msgstr "" + +#: cli/app/restore.go:17 cli/recipe/reset.go:14 +msgid "rs" +msgstr "" + +#: cli/recipe/new.go:116 +msgid "N" +msgstr "" + +#: pkg/git/commit.go:44 +msgid "dry run: no changes commited" +msgstr "" + +#: cli/app/restore.go:107 +msgid "services" +msgstr "" + +#: cli/recipe/lint.go:14 +msgid "lint [flags]" +msgstr "" + +#: pkg/recipe/recipe.go:201 +#, c-format +msgid "dirty: %v, " +msgstr "" + +#: pkg/git/commit.go:42 +msgid "git changes commited" +msgstr "" + +#: cli/internal/deploy.go:123 +msgid "UNCHAOS DEPLOY" +msgstr "" + +#: pkg/app/compose.go:51 +#, c-format +msgid "set label 'coop-cloud.%s.version' to %v for %s" +msgstr "" + +#: pkg/client/client.go:88 +#, c-format +msgid "created client for %s" +msgstr "" + +#: pkg/git/commit.go:14 +msgid "no commit message specified?" +msgstr "" + +#: cli/server/add.go:168 +#, c-format +msgid "creating context with domain %s" +msgstr "" + +#: cli/recipe/sync.go:188 +#, c-format +msgid "choosing %s as new version for %s" +msgstr "" + +#: pkg/recipe/git.go:458 +#, c-format +msgid "collected %s for %s" +msgstr "" + +#: cli/app/secret.go:134 +#, c-format +msgid "generated secrets %s shown again, please take note of them %s" +msgstr "" + +#: cli/app/secret.go:267 +msgid " abra app secret rm 1312.net oauth_key" +msgstr "" + +#: cli/app/config.go:18 +msgid "Edit app config" +msgstr "" + +#: cli/run.go:92 +msgid "Generate manpage" +msgstr "" + +#: cli/recipe/sync.go:74 +msgid "unable to continue, input required for initial version" +msgstr "" + +#: cli/updater/updater.go:202 +#, c-format +msgid "for %s read env %s with value: %s from docker service" +msgstr "" + +#: pkg/recipe/git.go:151 +#, c-format +msgid "read %s as tags for recipe %s" +msgstr "" + +#: cli/app/new.go:199 +#, c-format +msgid "%s created (version: %s)" +msgstr "" + +#: cli/recipe/sync.go:20 +msgid "sync [version] [flags]" +msgstr "" + +#: pkg/ssh/ssh.go:20 +#, c-format +msgid "connection timed out for %s" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:259 +#, c-format +msgid "unimplemented call: SetReadDeadline(%v)" +msgstr "" + +#: cli/app/secret.go:307 +msgid "cannot use [secret] and --all/-a together" +msgstr "" + +#: cli/app/upgrade.go:362 +#, c-format +msgid "parsing deployed version failed: %s" +msgstr "" + +#: cli/app/cp.go:108 +#, c-format +msgid "local %s " +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:65 +#, c-format +msgid "commandconn (%s):" +msgstr "" + +#: cli/app/cmd.go:267 +msgid "disable remote TTY" +msgstr "" + +#: cli/app/rollback.go:28 +msgid "" +"This command rolls an app back to a previous version.\n" +"\n" +"Unlike \"abra app deploy\", chaos operations are not supported here. Only " +"recipe\n" +"versions are supported values for \"[version]\".\n" +"\n" +"It is possible to \"--force/-f\" an downgrade if you want to re-deploy a " +"specific\n" +"version.\n" +"\n" +"Only the deployed version is consulted when trying to determine what " +"downgrades\n" +"are available. The live deployment version is the \"source of truth\" in " +"this\n" +"case. The stored .env version is not consulted.\n" +"\n" +"A downgrade can be destructive, please ensure you have a copy of your app " +"data\n" +"beforehand. See \"abra app backup\" for more." +msgstr "" + +#: cli/recipe/upgrade.go:177 +#, c-format +msgid "" +"no new versions available for %s, assuming %s is the latest (use -a/--all-" +"tags to see all anyway)" +msgstr "" + +#: pkg/upstream/container/hijack.go:172 +#, c-format +msgid "couldn't send EOF: %s" +msgstr "" + +#: cli/app/deploy.go:305 +#, c-format +msgid "version: taking version from .env file: %s" +msgstr "" + +#: cli/app/remove.go:73 cli/app/volume.go:120 +#, c-format +msgid "%s is still deployed. Run \"abra app undeploy %s\"" +msgstr "" + +#: cli/server/add.go:111 +#, c-format +msgid "%s successfully added" +msgstr "" + +#: cli/recipe/upgrade.go:148 +#, c-format +msgid "unable to read tag for image %s, is it missing? skipping upgrade for %s" +msgstr "" + +#: pkg/upstream/convert/volume.go:47 +msgid "bind options are incompatible with type volume" +msgstr "" + +#: cli/app/backup.go:295 +msgid "retries" +msgstr "" + +#: pkg/git/clone.go:100 +#, c-format +msgid "unable to clean up git clone of %s: %s" +msgstr "" + +#: cli/app/cmd.go:46 +msgid "requires at least 2 arguments with --local/-l" +msgstr "" + +#: pkg/app/app.go:577 pkg/envfile/envfile.go:42 pkg/envfile/envfile.go:80 +#: pkg/config/env.go:50 +#, c-format +msgid "read %s from %s" +msgstr "" + +#: pkg/git/init.go:34 +#, c-format +msgid "git worktree: %s" +msgstr "" + +#: cli/app/deploy.go:101 +#, c-format +msgid "get deploy version: %s" +msgstr "" + +#: cli/recipe/upgrade.go:91 +#, c-format +msgid "found versions file for %s" +msgstr "" + +#: cli/internal/command.go:84 +#, c-format +msgid "running command with user %s" +msgstr "" + +#: cli/internal/command.go:93 +msgid "not requesting a remote TTY" +msgstr "" + +#: cli/app/secret.go:75 +#, c-format +msgid "%s doesn't exist in the env config?" +msgstr "" + +#: cli/app/restart.go:23 +msgid "Restart an app" +msgstr "" + +#: cli/app/list.go:216 cli/internal/deploy.go:77 +msgid "SERVER" +msgstr "" + +#: cli/app/labels.go:102 +msgid "LABELS OVERVIEW" +msgstr "" + +#: cli/app/secret.go:311 +msgid "no secret(s) specified?" +msgstr "" + +#: cli/app/logs.go:96 +msgid "only tail stderr" +msgstr "" + +#: cli/app/list.go:296 cli/app/list.go:303 cli/run.go:32 +msgid "recipe" +msgstr "" + +#: cli/server/prune.go:93 +msgid "remove all unused images" +msgstr "" + +#: cli/internal/deploy.go:109 +msgid "deployment cancelled" +msgstr "" + +#: cli/app/secret.go:263 +msgid "" +"This command removes a secret from an app environment.\n" +"\n" +"Arbitrary secret removal is not supported. Secrets that are removed must\n" +"match those configured in the recipe beforehand." +msgstr "" + +#: cli/app/cmd.go:198 +msgid "List all available commands" +msgstr "" + +#: cli/catalogue/catalogue.go:266 +msgid "skip updating recipe repositories" +msgstr "" + +#: cli/run.go:30 +msgid "catalogue" +msgstr "" + +#: cli/app/restore.go:110 +msgid "restore specific services" +msgstr "" + +#: cli/internal/validate.go:35 +#, c-format +msgid "can't read local recipes: %s" +msgstr "" + +#: cli/app/list.go:288 cli/recipe/list.go:39 +msgid "status" +msgstr "" + +#: cli/app/cmd.go:196 cli/app/backup.go:15 cli/app/volume.go:19 +msgid "list [flags]" +msgstr "" + +#: cli/run.go:142 +msgid "prefer offline & filesystem access" +msgstr "" + +#: cli/recipe/lint.go:53 +#, c-format +msgid "skipping %s, does not have level \"error\"" +msgstr "" + +#: pkg/lint/recipe.go:155 +msgid "include \"traefik.enable=true\" deploy label" +msgstr "" + +#: pkg/upstream/convert/volume.go:93 +msgid "volume options are incompatible with type bind" +msgstr "" + +#: pkg/recipe/git.go:52 +#, c-format +msgid "can not redeploy chaos version (%s) without --chaos" +msgstr "" + +#: pkg/git/read.go:52 +#, c-format +msgid "git status: %s: clean" +msgstr "" + +#: cli/app/secret.go:57 +msgid "cannot use '[secret] [version]' and '--all' together" +msgstr "" + +#: cli/app/cmd.go:137 +#, c-format +msgid "%s does not exist locally, use /bin/sh as fallback" +msgstr "" + +#: cli/app/rollback.go:120 +msgid "no available downgrades" +msgstr "" + +#: cli/catalogue/catalogue.go:26 +msgid "Generate the recipe catalogue" +msgstr "TRANSLATE THIS FUCKING SHIT ALREADY" + +#: cli/recipe/recipe.go:10 +msgid "recipe [cmd] [args] [flags]" +msgstr "" + +#: pkg/lint/recipe.go:96 +msgid "tags use semver-like format" +msgstr "" + +#: pkg/upstream/convert/volume.go:130 +msgid "invalid npipe source, source cannot be empty" +msgstr "" + +#: pkg/recipe/recipe.go:325 +#, c-format +msgid "%s: image meta has incorrect format: %s" +msgstr "" + +#: cli/app/secret.go:143 +msgid "insert [flags]" +msgstr "" + +#: cli/app/logs.go:18 +msgid "logs [service] [flags]" +msgstr "" + +#: cli/internal/deploy.go:129 +msgid "NEW DEPLOY" +msgstr "" + +#: pkg/upstream/convert/service.go:604 +msgid "test and disable can't be set at the same time" +msgstr "" + +#: cli/recipe/sync.go:22 +msgid "Sync recipe version label" +msgstr "" + +#: pkg/app/compose.go:95 +#, c-format +msgid "timeout label: %s" +msgstr "" + +#: pkg/upstream/convert/service.go:153 pkg/upstream/convert/service.go:168 +#, c-format +msgid "config not found: %s" +msgstr "" + +#: pkg/git/push.go:13 +#, c-format +msgid "dry run: no git changes pushed in %s" +msgstr "" + +#: cli/app/new.go:324 cli/internal/validate.go:167 +msgid "no server provided" +msgstr "" + +#: cli/app/backup.go:242 +msgid "show all paths" +msgstr "" + +#: cli/recipe/upgrade.go:139 +#, c-format +msgid "retrieved %s from remote registry for %s" +msgstr "" + +#: cli/updater/updater.go:386 +#, c-format +msgid "don't update %s due to chaos deployment" +msgstr "" + +#: pkg/dns/dns.go:52 +#, c-format +msgid "app domain %s (%s) does not appear to resolve to app server %s (%s)?" +msgstr "" + +#: pkg/service/service.go:77 pkg/service/service.go:131 +msgid "failed to match chosen service" +msgstr "" + +#: pkg/formatter/formatter.go:238 +#, c-format +msgid "stripped %s to %s for parsing" +msgstr "" + +#: cli/app/secret.go:502 +msgid "treat input as a file" +msgstr "" + +#: cli/server/list.go:20 +msgid "List managed servers" +msgstr "" + +#: pkg/git/read.go:130 +#, c-format +msgid "no %s exists, skipping reading gitignore paths" +msgstr "" + +#: pkg/client/client.go:100 +msgid "swarm mode not enabled on local server?" +msgstr "" + +#: pkg/lint/recipe.go:261 pkg/recipe/files.go:17 +#, c-format +msgid "unable to discover .env.sample for %s" +msgstr "" + +#: pkg/formatter/formatter.go:80 +msgid "detected ABRA_CI=1" +msgstr "" + +#: cli/app/upgrade.go:461 +msgid "only show release notes" +msgstr "" + +#: cli/app/env.go:18 +msgid " abra app env 1312.net" +msgstr "" + +#: pkg/app/app.go:267 +#, c-format +msgid "%s is missing the TYPE env var?" +msgstr "" + +#: cli/app/ps.go:180 cli/app/list.go:219 +msgid "STATUS" +msgstr "" + +#: cli/recipe/sync.go:193 +#, c-format +msgid "invalid version %s specified" +msgstr "" + +#: cli/app/secret.go:262 +msgid "Remove a secret" +msgstr "" + +#: cli/app/upgrade.go:323 +#, c-format +msgid "parsing deployment version failed: %s" +msgstr "" + +#: cli/app/list.go:223 +msgid "AUTOUPDATE" +msgstr "" + +#: cli/recipe/version.go:39 +msgid "retrieved versions from local recipe repository" +msgstr "" + +#: cli/recipe/release.go:249 +#, c-format +msgid "chore: publish %s release" +msgstr "" + +#: pkg/recipe/git.go:398 +#, c-format +msgid "processing %s for %s" +msgstr "" + +#: cli/recipe/release.go:556 +#, c-format +msgid "use %s as the new version?" +msgstr "" + +#: pkg/lint/recipe.go:147 +msgid "deploy labels stanza present" +msgstr "" + +#: pkg/ssh/ssh.go:22 +#, c-format +msgid "ssh auth: permission denied for %s" +msgstr "" + +#: pkg/recipe/git.go:160 +#, c-format +msgid "unable to resolve '%s': %s" +msgstr "" + +#: cli/app/volume.go:182 +#, c-format +msgid "%d volumes removed successfully" +msgstr "" + +#: cli/recipe/version.go:17 +msgid "versions [flags]" +msgstr "" + +#: pkg/lint/recipe.go:133 +msgid ".env.sample provided" +msgstr "" + +#: cli/app/services.go:67 +msgid "SERVICE (LONG)" +msgstr "" + +#: cli/app/backup.go:17 +msgid "List the contents of a snapshot" +msgstr "" + +#: cli/app/backup.go:234 cli/app/backup.go:258 +msgid "list specific snapshot" +msgstr "" + +#: cli/catalogue/catalogue.go:27 +msgid "" +"Generate a new copy of the recipe catalogue.\n" +"\n" +"N.B. this command **will** wipe local unstaged changes from your local " +"recipes\n" +"if present. \"--chaos/-C\" on this command refers to the catalogue " +"repository\n" +"(\"$ABRA_DIR/catalogue\") and not the recipes. Please take care not to lose " +"your\n" +"changes.\n" +"\n" +"It is possible to generate new metadata for a single recipe by passing\n" +"[recipe]. The existing local catalogue will be updated, not overwritten.\n" +"\n" +"It is quite easy to get rate limited by Docker Hub when running this " +"command.\n" +"If you have a Hub account you can \"docker login\" and Abra will " +"automatically\n" +"use those details.\n" +"\n" +"Push your new release to git.coopcloud.tech with \"--publish/-p\". This " +"requires\n" +"that you have permission to git push to these repositories and have your " +"SSH\n" +"keys configured on your account." +msgstr "" + +#: cli/recipe/upgrade.go:199 +#, c-format +msgid "detected compatible upgradable tags %s for %s" +msgstr "" + +#: cli/app/cmd.go:25 +msgid "" +"Run an app specific command.\n" +"\n" +"These commands are bash functions, defined in the abra.sh of the recipe " +"itself.\n" +"They can be run within the context of a service (e.g. app) or locally on " +"your\n" +"work station by passing \"--local/-l\".\n" +"\n" +"N.B. If using the \"--\" style to pass arguments, flags (e.g. \"--local/-" +"l\") must\n" +"be passed *before* the \"--\". It is possible to pass arguments without the " +"\"--\"\n" +"as long as no dashes are present (i.e. \"foo\" works without \"--\", \"-" +"foo\"\n" +"does not)." +msgstr "" + +#: cli/app/secret.go:373 cli/app/cmd.go:197 cli/app/backup.go:16 +#: cli/app/volume.go:20 cli/app/list.go:44 cli/server/list.go:19 +#: cli/recipe/list.go:20 +msgid "ls" +msgstr "" + +#: cli/app/volume.go:77 +msgid "Remove volume(s) associated with an app" +msgstr "" + +#: cli/app/list.go:291 +msgid "show app deployment status" +msgstr "" + +#: cli/recipe/upgrade.go:353 cli/recipe/sync.go:238 cli/recipe/release.go:592 +#: cli/internal/recipe.go:46 cli/internal/recipe.go:66 +#: cli/internal/recipe.go:80 +msgid "minor" +msgstr "" + +#: pkg/recipe/recipe.go:549 +msgid "collecting recipe listing" +msgstr "" + +#: cli/app/backup.go:117 +#, c-format +msgid "including VOLUMES=%v in backupbot exec invocation" +msgstr "" + +#: cli/catalogue/catalogue.go:191 +msgid "chore: publish new catalogue release changes" +msgstr "" + +#: cli/updater/updater.go:37 +msgid "Check for available upgrades" +msgstr "" + +#: cli/internal/recipe.go:18 +#, c-format +msgid "" +"\n" +"You need to make a decision about what kind of an update this new recipe\n" +"version is. If someone else performs this upgrade, do they have to do some\n" +"migration work or take care of some breaking changes? This can be signaled " +"in\n" +"the version you specify on the recipe deploy label and is called a semantic\n" +"version.\n" +"\n" +"The latest published version is %s.\n" +"\n" +"Here is a semver cheat sheet (more on https://semver.org):\n" +"\n" +" major: new features/bug fixes, backwards incompatible (e.g 1.0.0 -> " +"2.0.0).\n" +" the upgrade won't work without some preparation work and others " +"need\n" +" to take care when performing it. \"it could go wrong\".\n" +"\n" +" minor: new features/bug fixes, backwards compatible (e.g. 0.1.0 -> " +"0.2.0).\n" +" the upgrade should Just Work and there are no breaking changes " +"in\n" +" the app and the recipe config. \"it should go fine\".\n" +"\n" +" patch: bug fixes, backwards compatible (e.g. 0.0.1 -> 0.0.2). this " +"upgrade\n" +" should also Just Work and is mostly to do with minor bug fixes\n" +" and/or security patches. \"nothing to worry about\".\n" +"\n" +msgstr "" + +#: pkg/recipe/compose.go:123 +#, c-format +msgid "considering %s config(s) for tag update" +msgstr "" + +#: cli/app/secret.go:470 cli/app/secret.go:494 +msgid "store generated secrets in a local pass store" +msgstr "" + +#: cli/internal/validate.go:64 +#, c-format +msgid "no recipe '%s' exists?" +msgstr "" + +#: pkg/app/app.go:41 +#, c-format +msgid "loaded app %s: %s" +msgstr "" + +#: cli/app/remove.go:94 +msgid "no configs to remove" +msgstr "" + +#: pkg/recipe/compose.go:47 +#, c-format +msgid "COMPOSE_FILE (=\"%s\") parsing failed?" +msgstr "" + +#: pkg/recipe/recipe.go:361 +#, c-format +msgid "%s: marker string %s not found" +msgstr "" + +#: cli/app/upgrade.go:437 cli/app/rollback.go:326 cli/app/deploy.go:337 +#: cli/app/remove.go:158 cli/app/volume.go:201 +msgid "perform action without further prompt" +msgstr "" + +#: pkg/secret/secret.go:268 +#, c-format +msgid "generated and stored %v on %s" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:263 +#, c-format +msgid "unimplemented call: SetWriteDeadline(%v)" +msgstr "" + +#: cli/recipe/upgrade.go:154 +#, c-format +msgid "unable to parse %s, error was: %s, skipping upgrade for %s" +msgstr "" + +#: pkg/lint/recipe.go:134 +msgid "create an example .env.sample" +msgstr "" + +#: pkg/server/server.go:25 +#, c-format +msgid "successfully created %s" +msgstr "" + +#: cli/app/upgrade.go:290 +#, c-format +msgid "please select an upgrade (version: %s, chaos: %s):" +msgstr "" + +#: cli/app/volume.go:47 +msgid "ON SERVER" +msgstr "" + +#: cli/run.go:117 +msgid "don't forget to run 'sudo mandb'" +msgstr "" + +#: cli/server/add.go:21 +msgid "add [[server] | --local] [flags]" +msgstr "" + +#: pkg/recipe/git.go:178 +#, c-format +msgid "successfully checked %s out to %s in %s" +msgstr "" + +#: pkg/git/clone.go:49 +#, c-format +msgid "git clone: %s" +msgstr "" + +#: cli/app/upgrade.go:392 cli/app/rollback.go:275 +#, c-format +msgid "'%s' is not a known version for %s" +msgstr "" + +#: cli/app/backup.go:49 +#, c-format +msgid "including SHOW_ALL=%v in backupbot exec invocation" +msgstr "" + +#: cli/app/list.go:322 +msgid "show apps of a specific server" +msgstr "" + +#: cli/app/labels.go:24 +msgid "lb" +msgstr "" + +#: cli/recipe/upgrade.go:300 +#, c-format +msgid "not upgrading %s, skipping as requested" +msgstr "" + +#: pkg/ui/deploy.go:86 +#, c-format +msgid "reader: %v, " +msgstr "" + +#: cli/recipe/recipe.go:13 +msgid "" +"A recipe is a blueprint for an app.\n" +"\n" +"It is a bunch of config files which describe how to deploy and maintain an " +"app.\n" +"Recipes are maintained by the Co-op Cloud community and you can use Abra to\n" +"read them, deploy them and create apps for you.\n" +"\n" +"Anyone who uses a recipe can become a maintainer. Maintainers typically " +"make\n" +"sure the recipe is in good working order and the config upgraded in a " +"timely\n" +"manner." +msgstr "" + +#: cli/app/upgrade.go:453 cli/app/rollback.go:342 cli/app/deploy.go:353 +msgid "disable converge logic checks" +msgstr "" + +#: cli/app/new.go:275 cli/internal/validate.go:129 +msgid "no domain provided" +msgstr "" + +#: cli/updater/updater.go:251 +#, c-format +msgid "failed to determine deployed version of %s" +msgstr "" + +#: pkg/ssh/ssh.go:18 +#, c-format +msgid "could not resolve hostname for %s" +msgstr "" + +#: pkg/upstream/convert/volume.go:44 +msgid "tmpfs options are incompatible with type volume" +msgstr "" + +#: cli/app/secret.go:26 +msgid "Generate secrets" +msgstr "" + +#: cli/complete.go:11 +msgid "autocomplete [bash|zsh|fish|powershell]" +msgstr "" + +#: cli/recipe/lint.go:74 cli/recipe/lint.go:136 pkg/lint/recipe.go:132 +#: pkg/lint/recipe.go:139 pkg/lint/recipe.go:146 pkg/lint/recipe.go:153 +#: pkg/lint/recipe.go:161 pkg/lint/recipe.go:168 pkg/lint/recipe.go:175 +msgid "error" +msgstr "" + +#: pkg/lint/recipe.go:124 +msgid "long secret names" +msgstr "" + +#: cli/app/secret.go:210 +#, c-format +msgid "no secret %s available for recipe %s?" +msgstr "" + +#: cli/app/ps.go:56 cli/app/upgrade.go:423 cli/app/undeploy.go:59 +#: cli/app/services.go:49 cli/app/restart.go:93 cli/app/logs.go:58 +#: cli/updater/updater.go:247 +#, c-format +msgid "%s is not deployed?" +msgstr "" + +#: cli/updater/updater.go:406 +#, c-format +msgid "don't update %s due to no new version" +msgstr "" + +#: pkg/lint/recipe.go:111 +msgid "fill out all the metadata" +msgstr "" + +#: cli/app/restore.go:74 +#, c-format +msgid "including CONTAINER=%s in backupbot exec invocation" +msgstr "" + +#: cli/app/upgrade.go:32 +msgid "" +"Upgrade an app.\n" +"\n" +"Unlike \"abra app deploy\", chaos operations are not supported here. Only " +"recipe\n" +"versions are supported values for \"[version]\".\n" +"\n" +"It is possible to \"--force/-f\" an upgrade if you want to re-deploy a " +"specific\n" +"version.\n" +"\n" +"Only the deployed version is consulted when trying to determine what " +"upgrades\n" +"are available. The live deployment version is the \"source of truth\" in " +"this\n" +"case. The stored .env version is not consulted.\n" +"\n" +"An upgrade can be destructive, please ensure you have a copy of your app " +"data\n" +"beforehand. See \"abra app backup\" for more." +msgstr "" + +#: pkg/recipe/git.go:187 +#, c-format +msgid "unable to check git clean status in %s: %s" +msgstr "" + +#: cli/app/secret.go:24 +msgid "generate [[secret] [version] | --all] [flags]" +msgstr "" + +#: cli/app/secret.go:144 +msgid "i" +msgstr "" + +#: cli/app/restart.go:64 +msgid "missing [service]" +msgstr "" + +#: cli/recipe/lint.go:34 +msgid "severity" +msgstr "" + +#: pkg/ssh/ssh.go:24 +#, c-format +msgid "unable to connect to %s, please check your SSH config" +msgstr "" + +#: cli/app/env.go:17 +msgid "Show app .env values" +msgstr "" + +#: pkg/git/init.go:50 +#, c-format +msgid "init committed all files for new git repo in %s" +msgstr "" + +#: cli/app/run.go:22 cli/app/upgrade.go:459 cli/app/backup.go:296 +#: cli/app/list.go:297 cli/catalogue/catalogue.go:256 cli/recipe/sync.go:223 +#: cli/recipe/recipe.go:11 cli/recipe/release.go:577 +msgid "r" +msgstr "" + +#: cli/app/upgrade.go:442 cli/app/rollback.go:331 cli/app/deploy.go:342 +msgid "no-domain-checks" +msgstr "" + +#: pkg/recipe/recipe.go:203 +#, c-format +msgid "git url: %s, " +msgstr "" + +#: cli/app/ps.go:183 cli/app/list.go:220 +msgid "CHAOS" +msgstr "" + +#: cli/server/remove.go:19 +msgid "Remove a managed server" +msgstr "" + +#: cli/updater/updater.go:176 +#, c-format +msgid "boolean label %s could not be found for %s, set default to false." +msgstr "" + +#: cli/internal/deploy.go:133 cli/internal/deploy.go:137 +msgid "DEPLOY" +msgstr "" + +#: cli/internal/recipe.go:70 cli/internal/recipe.go:85 +msgid "no version bump type specififed?" +msgstr "" + +#: pkg/app/compose.go:41 +#, c-format +msgid "set label 'coop-cloud.%s.chaos-version' to %v for %s" +msgstr "" + +#: pkg/recipe/git.go:191 +#, c-format +msgid "%s (%s) has locally unstaged changes?" +msgstr "" + +#: pkg/container/container.go:52 +msgid "which container are you looking for?" +msgstr "" + +#: cli/app/cmd.go:131 cli/app/cmd.go:176 +msgid "did not detect any command arguments" +msgstr "" + +#: cli/internal/deploy.go:142 +msgid "DOWNGRADE" +msgstr "" + +#: pkg/catalogue/catalogue.go:21 +msgid "catalogue is missing, retrieving now" +msgstr "" + +#: pkg/upstream/convert/service.go:72 +#, c-format +msgid "secret not found: %s" +msgstr "" + +#: cli/app/rollback.go:145 +#, c-format +msgid "choosing %s as version to rollback" +msgstr "" + +#: cli/app/cp.go:29 +msgid "cp [flags]" +msgstr "" + +#: pkg/upstream/container/exec.go:43 +msgid "exec ID empty" +msgstr "" + +#: pkg/recipe/git.go:251 +#, c-format +msgid "unable to open git work tree in %s: %s" +msgstr "" + +#: cli/app/list.go:216 cli/internal/deploy.go:76 +msgid "RECIPE" +msgstr "" + +#: cli/updater/updater.go:299 +#, c-format +msgid "available updates for %s: %s" +msgstr "" + +#: cli/app/secret.go:443 cli/app/restore.go:108 cli/app/new.go:341 +#: cli/app/logs.go:94 cli/app/backup.go:179 cli/app/backup.go:232 +#: cli/app/backup.go:256 cli/app/list.go:320 cli/catalogue/catalogue.go:264 +#: cli/server/server.go:11 cli/recipe/fetch.go:123 cli/recipe/sync.go:21 +msgid "s" +msgstr "" + +#: cli/app/run.go:111 cli/app/cmd.go:257 cli/recipe/upgrade.go:42 +#: cli/updater/updater.go:75 +msgid "u" +msgstr "" + +#: cli/app/cmd.go:101 +msgid "cannot use --local & --user together" +msgstr "" + +#: cli/app/new.go:118 +#, c-format +msgid "failed to retrieve latest commit for %s: %s" +msgstr "" + +#: cli/app/cp.go:253 +#, c-format +msgid "untar: %s" +msgstr "" + +#: cli/catalogue/catalogue.go:255 cli/recipe/sync.go:222 +#: cli/recipe/release.go:576 +msgid "dry-run" +msgstr "" + +#: pkg/recipe/recipe.go:200 +#, c-format +msgid "version : %s, " +msgstr "" + +#: cli/app/remove.go:92 +#, c-format +msgid "%d config(s) removed successfully" +msgstr "" + +#: cli/server/add.go:100 +#, c-format +msgid "unable to create local context: %s" +msgstr "" + +#: cli/app/new.go:358 +msgid "domain name for app" +msgstr "" + +#: cli/recipe/release.go:93 +msgid "cannot specify tag and bump type at the same time" +msgstr "" + +#: cli/internal/validate.go:132 +#, c-format +msgid "validated %s as domain argument" +msgstr "" + +#: cli/app/upgrade.go:29 +msgid "upgrade [version] [flags]" +msgstr "" + +#: cli/app/restart.go:144 +#, c-format +msgid "%s service successfully restarted" +msgstr "" + +#: cli/recipe/lint.go:32 +msgid "ref" +msgstr "" + +#: pkg/upstream/convert/volume.go:90 +msgid "invalid bind source, source cannot be empty" +msgstr "" + +#: pkg/ui/deploy.go:87 +#, c-format +msgid "writer: %v, " +msgstr "" + +#: cli/app/deploy.go:36 +msgid "" +" # standard deployment\n" +" abra app deploy 1312.net\n" +"\n" +" # chaos deployment\n" +" abra app deploy 1312.net --chaos\n" +" \n" +" # deploy specific version\n" +" abra app deploy 1312.net 2.0.0+1.2.3\n" +"\n" +" # deploy a specific git hash\n" +" abra app deploy 1312.net 886db76d" +msgstr "" + +#: cli/server/add.go:76 cli/server/add.go:103 +#, c-format +msgid "attempting to create client for %s" +msgstr "" + +#: cli/recipe/sync.go:197 pkg/recipe/compose.go:229 +#, c-format +msgid "coop-cloud.${STACK_NAME}.version=%s" +msgstr "" + +#: cli/app/upgrade.go:445 cli/app/rollback.go:334 cli/app/deploy.go:345 +msgid "disable public DNS checks" +msgstr "" + +#: cli/app/rollback.go:26 cli/recipe/release.go:27 +msgid "rl" +msgstr "" + +#: cli/app/services.go:67 +msgid "SERVICE (SHORT)" +msgstr "" + +#: cli/recipe/upgrade.go:377 +msgid "all-tags" +msgstr "" + +#: cli/recipe/sync.go:129 +#, c-format +msgid "tag at commit %s is unannotated or otherwise broken" +msgstr "" + +#: cli/recipe/release.go:342 +msgid "dry run: no changes committed" +msgstr "" + +#: cli/recipe/release.go:400 +msgid "publish new release?" +msgstr "" + +#: cli/internal/command.go:81 +#, c-format +msgid "running command: %s" +msgstr "" + +#: cli/app/secret.go:154 +msgid "" +" # insert regular secret\n" +" abra app secret insert 1312.net my_secret v1 mySuperSecret\n" +"\n" +" # insert secret as file\n" +" abra app secret insert 1312.net my_secret v1 secret.txt -f" +msgstr "" + +#: cli/app/secret.go:394 +msgid "CREATED ON SERVER" +msgstr "" + +#: cli/catalogue/catalogue.go:89 +msgid "collecting catalogue metadata" +msgstr "" + +#: cli/recipe/fetch.go:18 +msgid "fetch [recipe | --all] [flags]" +msgstr "" + +#: cli/recipe/sync.go:76 +#, c-format +msgid "" +"\n" +"The following options are two types of initial semantic version that you " +"can\n" +"pick for %s that will be published in the recipe catalogue. This follows " +"the\n" +"semver convention (more on https://semver.org), here is a short cheatsheet\n" +"\n" +" 0.1.0: development release, still hacking. when you make a major " +"upgrade\n" +" you increment the \"y\" part (i.e. 0.1.0 -> 0.2.0) and only move " +"to\n" +" using the \"x\" part when things are stable.\n" +"\n" +" 1.0.0: public release, assumed to be working. you already have a stable\n" +" and reliable deployment of this app and feel relatively " +"confident\n" +" about it.\n" +"\n" +"If you want people to be able alpha test your current config for %s but " +"don't\n" +"think it is quite reliable, go with 0.1.0 and people will know that things " +"are\n" +"likely to change.\n" +"\n" +msgstr "" + +#: cli/recipe/list.go:105 +msgid "pattern" +msgstr "" + +#: cli/app/remove.go:22 +msgid "" +"Remove everything related to an app which is already undeployed.\n" +"\n" +"By default, it will prompt for confirmation before proceeding. All secrets,\n" +"volumes and the local app env file will be deleted.\n" +"\n" +"Only run this command when you are sure you want to completely remove the " +"app\n" +"and all associated app data. This is a destructive action, Be Careful!\n" +"\n" +"If you would like to delete specific volumes or secrets, please use removal\n" +"sub-commands under \"app volume\" and \"app secret\" instead.\n" +"\n" +"Please note, if you delete the local app env file without removing volumes " +"and\n" +"secrets first, Abra will *not* be able to help you remove them afterwards.\n" +"\n" +"To delete everything without prompt, use the \"--force/-f\" or the \"--no-" +"input/n\"\n" +"flag." +msgstr "" + +#: cli/app/backup.go:107 +#, c-format +msgid "including INCLUDE_PATH=%s in backupbot exec invocation" +msgstr "" + +#: pkg/lint/recipe.go:203 +#, c-format +msgid "" +"\n" +"lint %s: %s" +msgstr "" + +#: cli/app/rollback.go:280 cli/app/rollback.go:284 +#, c-format +msgid "%s is not a downgrade for %s?" +msgstr "" + +#: cli/app/list.go:153 +#, c-format +msgid "unable to retrieve tags for %s: %s" +msgstr "" + +#: cli/server/add.go:163 +#, c-format +msgid "context for %s already exists" +msgstr "" + +#: pkg/ui/deploy.go:85 +#, c-format +msgid "name: %s, " +msgstr "" + +#: pkg/recipe/compose.go:29 +#, c-format +msgid "no COMPOSE_FILE detected, loading default: %s" +msgstr "" + +#: pkg/recipe/recipe.go:130 +#, c-format +msgid "version seems invalid: %s" +msgstr "" + +#: cli/recipe/upgrade.go:239 +#, c-format +msgid "" +"not upgrading from %s to %s for %s, because the upgrade type is more serious " +"than what user wants" +msgstr "" + +#: cli/app/cmd.go:35 +msgid "" +" # pass args/flags without \"--\"\n" +" abra app cmd 1312.net app my_cmd_arg foo --user bar\n" +"\n" +" # pass args/flags with \"--\"\n" +" abra app cmd 1312.net app my_cmd_args --user bar -- foo -vvv\n" +"\n" +" # drop the [service] arg if using \"--local/-l\"\n" +" abra app cmd 1312.net my_cmd --local" +msgstr "" + +#: cli/app/secret.go:460 cli/app/secret.go:556 cli/app/ps.go:199 +#: cli/app/list.go:312 cli/server/list.go:100 cli/recipe/upgrade.go:370 +#: cli/recipe/version.go:132 cli/recipe/list.go:98 cli/updater/updater.go:546 +msgid "m" +msgstr "" + +#: pkg/service/service.go:103 pkg/container/container.go:40 +#, c-format +msgid "%s (created %v)" +msgstr "" + +#: pkg/lint/recipe.go:104 +msgid "publish a recipe version to the catalogue" +msgstr "" + +#: cli/app/secret.go:484 cli/app/secret.go:524 cli/app/restart.go:162 +#: cli/app/app.go:10 cli/app/backup.go:240 cli/server/prune.go:91 +#: cli/server/add.go:22 cli/recipe/upgrade.go:378 cli/recipe/fetch.go:115 +#: cli/updater/updater.go:554 +msgid "a" +msgstr "" + +#: cli/app/restore.go:102 +msgid "target path" +msgstr "" + +#: cli/app/cp.go:31 +msgid "Copy files to/from a deployed app service" +msgstr "" + +#: cli/server/add.go:53 +msgid "cannot use [server] and --local together" +msgstr "" + +#: pkg/recipe/compose.go:243 +#, c-format +msgid "synced label %s to service %s" +msgstr "" + +#: cli/app/backup.go:250 +msgid "include timestamps" +msgstr "" + +#: cli/server/prune.go:56 +msgid "removing all images, not only dangling ones" +msgstr "" + +#: pkg/app/app.go:295 +#, c-format +msgid "collecting metadata from %v servers: %s" +msgstr "" + +#: pkg/lint/recipe.go:215 +#, c-format +msgid "linting successful, %s is well configured" +msgstr "" + +#: pkg/recipe/compose.go:153 +#, c-format +msgid "unable to parse %s, skipping" +msgstr "" + +#: cli/app/upgrade.go:329 cli/app/upgrade.go:368 +#, c-format +msgid "parsing recipe version failed: %s" +msgstr "" + +#: cli/app/services.go:23 +msgid "Display all services of an app" +msgstr "" + +#: cli/app/deploy.go:29 cli/app/backup.go:66 cli/recipe/diff.go:14 +#: cli/updater/updater.go:491 +msgid "d" +msgstr "" + +#: cli/recipe/fetch.go:125 +msgid "automatically set ssh remote" +msgstr "" + +#: pkg/lint/recipe.go:117 +msgid "git.coopcloud.tech repo exists" +msgstr "" + +#: pkg/upstream/container/hijack.go:135 +#, c-format +msgid "error receiveStdout: %s" +msgstr "" + +#: pkg/git/init.go:70 +#, c-format +msgid "repo set config: %s" +msgstr "" + +#: cli/recipe/fetch.go:20 +msgid "Clone recipe(s) locally" +msgstr "" + +#: pkg/lint/recipe.go:187 +#, c-format +msgid "linting for critical errors in %s configs" +msgstr "" + +#: pkg/recipe/git.go:262 +#, c-format +msgid "unable to fetch tags in %s: %s" +msgstr "" + +#: cli/app/cp.go:117 cli/app/cp.go:199 cli/app/cp.go:210 +#, c-format +msgid "remote path: %s" +msgstr "" + +#: cli/recipe/release.go:518 +#, c-format +msgid "failed to publish new release: %s" +msgstr "" + +#: pkg/logs/logs.go:86 +#, c-format +msgid "tailLogs: unable to copy buffer: %s" +msgstr "" + +#: pkg/recipe/recipe.go:138 +#, c-format +msgid "removed dirty suffix from .env version: %s -> %s" +msgstr "" + +#: pkg/container/container.go:31 +#, c-format +msgid "no containers matching the %v filter found?" +msgstr "" + +#: cli/app/new.go:48 cli/recipe/new.go:35 cli/updater/updater.go:36 +#: cli/updater/updater.go:499 +msgid "n" +msgstr "" + +#: cli/recipe/new.go:53 +#, c-format +msgid "%s/example.git" +msgstr "" + +#: cli/internal/validate.go:50 +msgid "Select recipe" +msgstr "" + +#: pkg/recipe/compose.go:38 +#, c-format +msgid "COMPOSE_FILE detected, loading %s" +msgstr "" + +#: pkg/recipe/recipe.go:206 +#, c-format +msgid "readme: %s, " +msgstr "" + +#: cli/app/ps.go:179 cli/recipe/version.go:62 cli/recipe/version.go:103 +msgid "SERVICE" +msgstr "" + +#: cli/app/remove.go:139 +#, c-format +msgid "%d volume(s) removed successfully" +msgstr "" + +#: cli/app/volume.go:21 +msgid "List volumes associated with an app" +msgstr "" + +#: cli/run.go:31 +msgid "man" +msgstr "" + +#: cli/recipe/lint.go:36 +msgid "skipped" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:141 +msgid "commandconn: failed to wait" +msgstr "" + +#: cli/app/services.go:22 +msgid "sr" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:239 +#, c-format +msgid "commandConn.Close: CloseRead: %v" +msgstr "" + +#: pkg/recipe/compose.go:191 +#, c-format +msgid "considering %s config(s) for label update" +msgstr "" + +#: pkg/git/init.go:24 +#, c-format +msgid "initialised new git repo in %s" +msgstr "" + +#: cli/app/rollback.go:238 +#, c-format +msgid "please select a downgrade (version: %s):" +msgstr "" + +#: cli/app/deploy.go:296 +#, c-format +msgid "version: taking version from cli arg: %s" +msgstr "" + +#: cli/app/remove.go:89 +#, c-format +msgid "removing configs failed: %s" +msgstr "" + +#: cli/updater/updater.go:74 +msgid "upgrade [[stack] [recipe] | --all] [flags]" +msgstr "" + +#: cli/app/undeploy.go:88 +msgid "initialising undeploy" +msgstr "" + +#: cli/recipe/upgrade.go:75 +msgid "you can only use one of: --major, --minor, --patch." +msgstr "" + +#: cli/recipe/sync.go:96 +msgid "which version do you want to begin with?" +msgstr "" + +#: pkg/dns/dns.go:14 +#, c-format +msgid "%s: unable to resolve IPv4 address: %s" +msgstr "" + +#: cli/app/secret.go:124 cli/app/secret.go:424 cli/server/list.go:82 +#: cli/recipe/version.go:106 cli/recipe/list.go:77 +#, c-format +msgid "unable to render to JSON: %s" +msgstr "" + +#: pkg/recipe/recipe.go:74 +#, c-format +msgid "choosing %s as latest version of %s" +msgstr "" + +#: pkg/recipe/recipe.go:199 +#, c-format +msgid "{name: %s, " +msgstr "" + +#: cli/app/restore.go:116 cli/app/backup.go:280 cli/server/prune.go:99 +#: cli/recipe/version.go:18 +msgid "v" +msgstr "" + +#: cli/app/list.go:222 cli/internal/deploy.go:140 +msgid "UPGRADE" +msgstr "" + +#: pkg/service/service.go:53 pkg/service/service.go:107 +#, c-format +msgid "expected 1 service but found %v: %s" +msgstr "" + +#: pkg/lint/recipe.go:75 +msgid "healthcheck enabled for all services" +msgstr "" + +#: cli/app/restore.go:52 cli/app/backup.go:44 cli/app/backup.go:102 +#, c-format +msgid "including SNAPSHOT=%s in backupbot exec invocation" +msgstr "" + +#: cli/app/undeploy.go:128 cli/server/prune.go:45 +#, c-format +msgid "containers pruned: %d; space reclaimed: %s" +msgstr "" + +#: cli/recipe/version.go:53 +#, c-format +msgid "%s has no published versions?" +msgstr "" + +#: cli/internal/validate.go:75 +msgid "generate" +msgstr "" + +#: pkg/lint/recipe.go:118 +msgid "upload your recipe to git.coopcloud.tech/coop-cloud/..." +msgstr "" + +#: pkg/dns/dns.go:18 +#, c-format +msgid "%s: no IPv4 available" +msgstr "" + +#: cli/app/backup.go:134 +msgid "create [flags]" +msgstr "" + +#: cli/updater/updater.go:498 +msgid "no-input" +msgstr "" + +#: pkg/recipe/git.go:256 +#, c-format +msgid "unable to check out default branch in %s: %s" +msgstr "" + +#: cli/app/cp.go:32 +msgid "" +" # copy myfile.txt to the root of the app service\n" +" abra app cp 1312.net myfile.txt app:/\n" +"\n" +" # copy that file back to your current working directory locally\n" +" abra app cp 1312.net app:/myfile.txt ./" +msgstr "" + +#: pkg/app/compose.go:80 +#, c-format +msgid "get label '%s'" +msgstr "" + +#: pkg/config/abra.go:88 +msgid "using default abra dir" +msgstr "" + +#: cli/app/restore.go:99 +msgid "target" +msgstr "" + +#: cli/recipe/release.go:317 +msgid "Release Note (leave empty for no release note)" +msgstr "" + +#: pkg/client/configs.go:35 +#, c-format +msgid "conf %s: %s" +msgstr "" + +#: pkg/lint/recipe.go:89 +msgid "no unstable tags" +msgstr "" + +#: cli/app/volume.go:71 +#, c-format +msgid "no volumes created for %s" +msgstr "" + +#: pkg/app/app.go:579 +#, c-format +msgid "read 0 command names from %s" +msgstr "" + +#: pkg/secret/secret.go:130 +#, c-format +msgid "%s not enabled in recipe config, skipping" +msgstr "" + +#: pkg/dns/dns.go:38 pkg/dns/dns.go:47 +#, c-format +msgid "cannot resolve ipv4 for %s?" +msgstr "" + +#: pkg/recipe/recipe.go:368 +#, c-format +msgid "%s: end marker %s not found" +msgstr "" + +#: cli/app/logs.go:104 +msgid "tail logs since YYYY-MM-DDTHH:MM:SSZ" +msgstr "" + +#: cli/recipe/upgrade.go:41 +msgid "upgrade [flags]" +msgstr "" + +#: pkg/git/read.go:50 +#, c-format +msgid "git status: %s: %s" +msgstr "" + +#: cli/app/restore.go:19 +msgid "" +"Snapshots are restored while apps are deployed.\n" +"\n" +"Some restore scenarios may require service / app restarts." +msgstr "" + +#: cli/app/restart.go:68 +msgid "cannot use [service] and --all-services/-a together" +msgstr "" + +#: cli/app/config.go:42 +msgid "which editor do you wish to use?" +msgstr "" + +#: cli/server/prune.go:17 +msgid "Prune resources on a server" +msgstr "" + +#: cli/recipe/release.go:510 +#, c-format +msgid "failed to commit changes: %s" +msgstr "" + +#: pkg/upstream/convert/volume.go:136 +msgid "tmpfs options are incompatible with type npipe" +msgstr "" + +#: pkg/config/abra.go:26 +#, c-format +msgid "error reading config file: %s" +msgstr "" + +#: pkg/git/push.go:40 +msgid "git tags pushed" +msgstr "" + +#: cli/updater/updater.go:490 +msgid "debug" +msgstr "" + +#: cli/internal/validate.go:120 +msgid "Specify a domain name" +msgstr "" + +#: cli/app/secret.go:216 +#, c-format +msgid "reading secret from file: %s" +msgstr "" + +#: cli/app/restore.go:68 +#, c-format +msgid "including VOLUMES=%s in backupbot exec invocation" +msgstr "" + +#: cli/app/backup.go:136 +msgid "Create a new snapshot" +msgstr "" + +#: cli/recipe/lint.go:35 +msgid "satisfied" +msgstr "" + +#: cli/internal/validate.go:88 +#, c-format +msgid "validated %s as recipe argument" +msgstr "" + +#: cli/app/secret.go:478 cli/app/secret.go:518 cli/app/secret.go:542 +#: cli/app/secret.go:550 cli/app/restore.go:134 cli/app/ps.go:209 +#: cli/app/cmd.go:275 cli/app/new.go:382 cli/app/check.go:90 +#: cli/app/restart.go:157 cli/app/deploy.go:329 cli/app/cp.go:381 +#: cli/app/backup.go:290 cli/app/backup.go:306 cli/app/labels.go:138 +#: cli/catalogue/catalogue.go:274 cli/recipe/lint.go:131 +#: cli/updater/updater.go:540 +msgid "ignore uncommitted recipes changes" +msgstr "" + +#: cli/app/deploy.go:303 +#, c-format +msgid "version: can not redeploy chaos version %s" +msgstr "" + +#: cli/app/remove.go:119 +msgid "no secrets to remove" +msgstr "" + +#: cli/app/list.go:177 +msgid "latest" +msgstr "" + +#: cli/recipe/new.go:118 +msgid "Git (user) name to do commits with" +msgstr "" + +#: cli/app/cmd.go:249 cli/app/logs.go:19 cli/server/add.go:200 +#: cli/recipe/lint.go:16 +msgid "l" +msgstr "" + +#: cli/app/new.go:135 +#, c-format +msgid "%s sanitised as %s for new app" +msgstr "" + +#: cli/app/volume.go:184 +msgid "no volumes removed" +msgstr "" + +#: cli/server/add.go:86 +msgid "local server already exists" +msgstr "" + +#: cli/app/check.go:19 +msgid "Ensure an app is well configured" +msgstr "" + +#: cli/app/cp.go:145 cli/app/cp.go:184 +#, c-format +msgid "create remote directory: %s" +msgstr "" + +#: cli/app/backup.go:282 +msgid "include volumes" +msgstr "" + +#: cli/recipe/new.go:37 +msgid "A community managed recipe template is used." +msgstr "" + +#: cli/updater/updater.go:484 +#, c-format +msgid "kadabra version %s, commit %s" +msgstr "" + +#: cli/internal/validate.go:84 +#, c-format +msgid "unable to validate recipe: %s" +msgstr "" + +#: pkg/recipe/compose.go:171 pkg/recipe/compose.go:237 +#, c-format +msgid "updating %s to %s in %s" +msgstr "" + +#: cli/app/cp.go:245 +#, c-format +msgid "copy: %s" +msgstr "" + +#: cli/recipe/upgrade.go:364 cli/recipe/sync.go:249 cli/recipe/release.go:603 +msgid "increase the patch part of the version" +msgstr "" + +#: pkg/catalogue/catalogue.go:59 pkg/recipe/git.go:245 +#, c-format +msgid "cannot ensure %s is up-to-date, no git remotes configured" +msgstr "" + +#: cli/server/add.go:120 pkg/secret/secret.go:223 pkg/secret/secret.go:243 +#: pkg/server/server.go:21 +#, c-format +msgid "%s already exists" +msgstr "" + +#: cli/internal/deploy.go:78 +msgid "CONFIG" +msgstr "" + +#: pkg/lint/recipe.go:76 +msgid "wire up healthchecks" +msgstr "" + +#: cli/recipe/list.go:38 +msgid "category" +msgstr "" + +#: cli/internal/validate.go:59 +msgid "no recipe name provided" +msgstr "" + +#: cli/internal/validate.go:96 +msgid "no app provided" +msgstr "" + +#: cli/app/run.go:102 +msgid "no-tty" +msgstr "" + +#: cli/app/ps.go:30 +msgid "Check app deployment status" +msgstr "" + +#: cli/app/upgrade.go:274 cli/app/undeploy.go:107 cli/app/new.go:224 +#: cli/app/rollback.go:227 cli/app/deploy.go:236 +#, c-format +msgid "writing recipe version failed: %s" +msgstr "" + +#: cli/app/rollback.go:25 +msgid "rollback [version] [flags]" +msgstr "" + +#: cli/app/restart.go:161 +msgid "all-services" +msgstr "" + +#: cli/app/list.go:49 +msgid "" +" # list apps of all servers without live status\n" +" abra app ls\n" +"\n" +" # list apps of a specific server with live status\n" +" abra app ls -s 1312.net -S\n" +"\n" +" # list apps of all servers which match a specific recipe\n" +" abra app ls -r gitea" +msgstr "" + +#: cli/recipe/fetch.go:48 +msgid "cannot use [recipe] and --all/-a together" +msgstr "" + +#: cli/recipe/lint.go:15 +msgid "Lint a recipe" +msgstr "" + +#: cli/app/secret.go:508 cli/app/restore.go:100 cli/app/run.go:103 +#: cli/app/backup.go:248 +msgid "t" +msgstr "" + +#: cli/recipe/list.go:44 +msgid "SSO" +msgstr "" + +#: cli/recipe/release.go:28 +msgid "Release a new recipe version" +msgstr "" + +#: cli/updater/updater.go:197 +#, c-format +msgid "can't separate key from value: %s (this variable is probably unset)" +msgstr "" + +#: cli/recipe/release.go:537 +#, c-format +msgid "removed freshly created tag %s" +msgstr "" + +#: pkg/lint/recipe.go:83 +msgid "use a tag for all images" +msgstr "" + +#: pkg/lint/recipe.go:163 +msgid "ensure \"image: ...\" set on all services" +msgstr "" + +#: cli/app/restart.go:22 +msgid "re" +msgstr "" + +#: cli/app/secret.go:260 +msgid "remove [[secret] | --all] [flags]" +msgstr "" + +#: cli/server/add.go:57 +msgid "missing argument or --local/-l flag" +msgstr "" + +#: pkg/lint/recipe.go:148 +msgid "include \"deploy: labels: ...\" stanza" +msgstr "" + +#: pkg/git/read.go:88 +#, c-format +msgid "no %s exists, not reading any global gitignore config" +msgstr "" + +#: cli/recipe/upgrade.go:43 +msgid "Upgrade recipe image tags" +msgstr "" + +#: cli/updater/updater.go:35 +msgid "notify [flags]" +msgstr "" + +#: cli/updater/updater.go:239 +#, c-format +msgid "retrieve deployed version whether %s is already deployed" +msgstr "" + +#: cli/app/remove.go:116 +#, c-format +msgid "secret: %s removed" +msgstr "" + +#: pkg/lint/recipe.go:110 +msgid "README.md metadata filled in" +msgstr "" + +#: pkg/secret/secret.go:119 +msgid "not generating app secrets, none enabled in recipe config" +msgstr "" + +#: pkg/recipe/git.go:50 +#, c-format +msgid "ensuring env version %s" +msgstr "" + +#: cli/app/upgrade.go:443 cli/app/new.go:356 cli/app/rollback.go:332 +#: cli/app/deploy.go:343 +msgid "D" +msgstr "" + +#: cli/app/volume.go:88 +msgid "" +" # delete volumes interactively\n" +" abra app volume rm 1312.net\n" +"\n" +" # delete specific volume\n" +" abra app volume rm 1312.net my_volume" +msgstr "" + +#: cli/complete.go:13 +msgid "" +"To load completions:\n" +"\n" +"Bash:\n" +" # Load autocompletion for the current Bash session\n" +" $ source <(abra autocomplete bash)\n" +"\n" +" # To load autocompletion for each session, execute once:\n" +" # Linux:\n" +" $ abra autocomplete bash | sudo tee /etc/bash_completion.d/abra\n" +" # macOS:\n" +" $ abra autocomplete bash | sudo tee $(brew --prefix)/etc/bash_completion.d/" +"abra\n" +"\n" +"Zsh:\n" +" # If shell autocompletion is not already enabled in your environment,\n" +" # you will need to enable it. You can execute the following once:\n" +"\n" +" $ echo \"autoload -U compinit; compinit\" >> ~/.zshrc\n" +"\n" +" # To load autocompletions for each session, execute once:\n" +" $ abra autocomplete zsh > \"${fpath[1]}/_abra\"\n" +"\n" +" # You will need to start a new shell for this setup to take effect.\n" +"\n" +"fish:\n" +" $ abra autocomplete fish | source\n" +"\n" +" # To load autocompletions for each session, execute once:\n" +" $ abra autocomplete fish > ~/.config/fish/completions/abra.fish\n" +"\n" +"PowerShell:\n" +" PS> abra autocomplete powershell | Out-String | Invoke-Expression\n" +"\n" +" # To load autocompletions for every new session, run:\n" +" PS> abra autocomplete powershell > abra.ps1\n" +" # and source this file from your PowerShell profile." +msgstr "" + +#: cli/server/server.go:10 +msgid "server [cmd] [args] [flags]" +msgstr "" + +#: cli/catalogue/catalogue.go:234 +msgid "catalogue [cmd] [args] [flags]" +msgstr "" + +#: cli/recipe/upgrade.go:362 cli/recipe/sync.go:247 cli/recipe/release.go:601 +msgid "z" +msgstr "" + +#: cli/recipe/release.go:78 +#, c-format +msgid "main app service version for %s is empty?" +msgstr "" + +#: pkg/ui/deploy.go:84 +#, c-format +msgid "id: %s, " +msgstr "" + +#: pkg/recipe/recipe.go:555 +#, c-format +msgid "fetching repo metadata from %s" +msgstr "" + +#: cli/app/secret.go:106 cli/app/new.go:187 +msgid "VALUE" +msgstr "" + +#: cli/recipe/upgrade.go:345 cli/recipe/sync.go:230 cli/recipe/release.go:584 +#: cli/updater/updater.go:545 cli/internal/recipe.go:46 +#: cli/internal/recipe.go:64 cli/internal/recipe.go:78 +msgid "major" +msgstr "" + +#: cli/recipe/upgrade.go:356 cli/recipe/sync.go:241 cli/recipe/release.go:595 +msgid "increase the minor part of the version" +msgstr "" + +#: cli/app/secret.go:136 +msgid "NOT" +msgstr "" + +#: cli/app/secret.go:146 +msgid "" +"This command inserts a secret into an app environment.\n" +"\n" +"Arbitrary secret insertion is not supported. Secrets that are inserted must\n" +"match those configured in the recipe beforehand.\n" +"\n" +"This can be useful when you want to manually generate secrets for an app\n" +"environment. Typically, you can let Abra generate them for you on app " +"creation\n" +"(see \"abra app new --secrets/-S\" for more)." +msgstr "" + +#: cli/app/volume.go:192 +msgid "Manage app volumes" +msgstr "" + +#: cli/catalogue/catalogue.go:247 cli/recipe/release.go:608 +msgid "publish" +msgstr "" + +#: cli/updater/updater.go:224 +#, c-format +msgid "no available upgrades for %s" +msgstr "" + +#: pkg/lint/recipe.go:177 +msgid "replace lightweight tag with annotated tag" +msgstr "" + +#: pkg/ui/deploy.go:82 +#, c-format +msgid "{decoder: %v, " +msgstr "" + +#: cli/recipe/upgrade.go:346 cli/recipe/sync.go:231 cli/recipe/release.go:585 +msgid "x" +msgstr "" + +#: cli/recipe/fetch.go:122 +msgid "ssh" +msgstr "" + +#: cli/recipe/new.go:115 +msgid "git-name" +msgstr "" + +#: pkg/config/env.go:37 +#, c-format +msgid "retrieved %v servers: %s" +msgstr "" + +#: cli/app/upgrade.go:451 cli/app/rollback.go:340 cli/app/deploy.go:351 +#: cli/app/cp.go:30 cli/app/backup.go:135 +msgid "c" +msgstr "" + +#: cli/app/labels.go:26 +msgid "Both local recipe and live deployment labels are shown." +msgstr "" + +#: cli/internal/recipe.go:112 +#, c-format +msgid "%s has no main 'app' service?" +msgstr "" + +#: pkg/upstream/container/tty.go:66 +msgid "failed to resize tty, using default size" +msgstr "" + +#: pkg/recipe/recipe.go:205 +#, c-format +msgid "compose: %s, " +msgstr "" + +#: cli/app/logs.go:20 +msgid "Tail app logs" +msgstr "" + +#: cli/app/backup.go:54 +#, c-format +msgid "including TIMESTAMPS=%v in backupbot exec invocation" +msgstr "" + +#: cli/app/backup.go:65 +msgid "download [flags]" +msgstr "" + +#: cli/run.go:24 +msgid "abra [cmd] [args] [flags]" +msgstr "" + +#: cli/upgrade.go:37 pkg/secret/pass.go:23 pkg/secret/pass.go:45 +#, c-format +msgid "attempting to run %s" +msgstr "" + +#: cli/server/prune.go:101 +msgid "remove volumes" +msgstr "" + +#: cli/server/remove.go:17 +msgid "remove [flags]" +msgstr "" + +#: cli/recipe/release.go:26 +msgid "release [version] [flags]" +msgstr "" + +#: cli/internal/backup.go:29 +#, c-format +msgid "retrieved %s as backup enabled service" +msgstr "" + +#: pkg/client/registry.go:20 +#, c-format +msgid "failed to parse image %s, saw: %s" +msgstr "" + +#: pkg/upstream/convert/service.go:43 +#, c-format +msgid "duplicate secret target for %s not allowed" +msgstr "" + +#: cli/recipe/upgrade.go:318 +#, c-format +msgid "can upgrade service: %s, image: %s, tag: %s ::" +msgstr "" + +#: cli/recipe/fetch.go:81 +#, c-format +msgid "unable to set SSH remote in %s: %s" +msgstr "" + +#: cli/recipe/release.go:514 +#, c-format +msgid "failed to tag release: %s" +msgstr "" + +#: pkg/upstream/convert/service.go:813 +#, c-format +msgid "invalid credential spec: cannot specify both %s and %s" +msgstr "" + +#: pkg/recipe/git.go:225 pkg/recipe/git.go:406 pkg/git/branch.go:95 +#, c-format +msgid "failed to check out %s in %s" +msgstr "" + +#: pkg/app/app.go:679 +#, c-format +msgid "skipping writing version %s because dry run" +msgstr "" + +#: pkg/upstream/container/hijack.go:43 +#, c-format +msgid "unable to setup input stream: %s" +msgstr "" + +#: cli/app/run.go:113 +msgid "run command as user" +msgstr "" + +#: cli/app/cmd.go:264 +msgid "tty" +msgstr "" + +#: cli/catalogue/catalogue.go:24 +msgid "generate [recipe] [flags]" +msgstr "" + +#: cli/run.go:29 +msgid "autocomplete" +msgstr "" + +#: cli/app/ps.go:165 +#, c-format +msgid "unable to convert to JSON: %s" +msgstr "" + +#: pkg/app/app.go:380 +#, c-format +msgid "%s already exists?" +msgstr "" + +#: cli/run.go:25 +msgid "The Co-op Cloud command-line utility belt 🎩🐇" +msgstr "" + +#: pkg/recipe/recipe.go:147 +#, c-format +msgid "invalid recipe: %s" +msgstr "" + +#: pkg/recipe/recipe.go:208 +#, c-format +msgid "abra.sh: %s}" +msgstr "" + +#: pkg/git/clone.go:59 pkg/git/clone.go:78 pkg/git/clone.go:87 +#, c-format +msgid "git clone: %s cloned successfully" +msgstr "" + +#: pkg/container/container.go:48 +msgid "ambiguous container list received, prompting for input" +msgstr "" + +#: cli/app/ps.go:28 +msgid "ps [flags]" +msgstr "" + +#: cli/app/labels.go:53 +msgid "DEPLOYED LABELS" +msgstr "" + +#: cli/recipe/upgrade.go:249 +#, c-format +msgid "upgrade to which tag? (service: %s, tag: %s)" +msgstr "" + +#: pkg/secret/pass.go:29 +#, c-format +msgid "%s inserted into pass store" +msgstr "" + +#: pkg/recipe/recipe.go:202 +#, c-format +msgid "dir: %s, " +msgstr "" + +#: cli/app/deploy.go:177 +msgid "skipping domain checks, no DOMAIN=... configured" +msgstr "" + +#: cli/app/remove.go:136 cli/app/volume.go:179 +#, c-format +msgid "removing volumes failed: %s" +msgstr "" + +#: cli/recipe/upgrade.go:361 cli/recipe/sync.go:246 cli/recipe/release.go:600 +#: cli/internal/recipe.go:46 cli/internal/recipe.go:68 +#: cli/internal/recipe.go:82 +msgid "patch" +msgstr "" + +#: cli/recipe/release.go:88 +#, c-format +msgid "cannot parse %s, invalid tag specified?" +msgstr "" + +#: cli/updater/updater.go:77 +msgid "" +"Upgrade an app by specifying stack name and recipe. \n" +"\n" +"Use \"--all\" to upgrade every deployed app.\n" +"\n" +"For each app with auto updates enabled, the deployed version is compared " +"with\n" +"the current recipe catalogue version. If a new patch/minor version is\n" +"available, the app is upgraded.\n" +"\n" +"To include major versions use the \"--major/-m\" flag. You probably don't " +"want\n" +"that as it will break things. Only apps that are not deployed with \"--" +"chaos/-C\"\n" +"are upgraded, to update chaos deployments use the \"--chaos/-C\" flag. Use " +"it\n" +"with care." +msgstr "" + +#: cli/app/app.go:11 +msgid "Manage apps" +msgstr "" + +#: cli/upgrade.go:18 +msgid "Upgrade abra" +msgstr "" + +#: pkg/catalogue/catalogue.go:40 +#, c-format +msgid "" +"%s has locally unstaged changes? please commit/remove your changes before " +"proceeding" +msgstr "" + +#: cli/app/secret.go:534 +msgid "remove generated secrets from a local pass store" +msgstr "" + +#: cli/app/upgrade.go:285 +#, c-format +msgid "please select an upgrade (version: %s):" +msgstr "" + +#: cli/app/backup.go:231 cli/app/backup.go:255 +msgid "snapshot" +msgstr "" + +#: cli/run.go:90 +msgid "man [flags]" +msgstr "" + +#: cli/internal/validate.go:82 +#, c-format +msgid "ensure %s recipe compose.* files include \"version: '3.8'\"" +msgstr "" + +#: pkg/app/app.go:501 +#, c-format +msgid "retrieved %s for %s" +msgstr "" + +#: cli/app/restore.go:126 +msgid "enable pre/post-hook command execution" +msgstr "" + +#: cli/app/secret.go:442 +msgid "secret [cmd] [args] [flags]" +msgstr "" + +#: cli/recipe/upgrade.go:158 +#, c-format +msgid "parsed %s for %s" +msgstr "" + +#: cli/recipe/upgrade.go:348 cli/recipe/sync.go:233 cli/recipe/release.go:587 +msgid "increase the major part of the version" +msgstr "" + +#: cli/app/cp.go:273 +msgid "destination directory does not exist" +msgstr "" + +#: cli/recipe/new.go:123 +msgid "git-email" +msgstr "" + +#: cli/internal/backup.go:26 +msgid "no backupbot discovered, is it deployed?" +msgstr "" + +#: pkg/app/app.go:516 +#, c-format +msgid "%s: %s: %s" +msgstr "" + +#: pkg/service/service.go:61 pkg/service/service.go:115 +msgid "which service are you looking for?" +msgstr "" + +#: cli/app/labels.go:27 +msgid " abra app labels 1312.net" +msgstr "" + +#: cli/catalogue/catalogue.go:223 +#, c-format +msgid "new changes published: %s" +msgstr "" + +#: cli/recipe/list.go:18 +msgid "list" +msgstr "" + +#: pkg/app/app.go:622 +#, c-format +msgid "version wiped from %s.env" +msgstr "" + +#: cli/recipe/upgrade.go:101 +#, c-format +msgid "malformed version pin specification: %s" +msgstr "" + +#: cli/recipe/sync.go:203 +#, c-format +msgid "dry run: not syncing label %s for recipe %s" +msgstr "" + +#: cli/recipe/release.go:501 +msgid "exiting as requested" +msgstr "" + +#: pkg/lint/recipe.go:82 +msgid "all images use a tag" +msgstr "" + +#: pkg/upstream/container/exec.go:113 +#, c-format +msgid "Error hijack: %s" +msgstr "" + +#: cli/app/secret.go:468 cli/app/secret.go:492 cli/app/secret.go:532 +#: cli/app/ps.go:29 cli/app/undeploy.go:156 cli/app/new.go:364 +#: cli/app/backup.go:264 cli/catalogue/catalogue.go:248 cli/server/prune.go:16 +#: cli/recipe/list.go:106 cli/recipe/release.go:609 +msgid "p" +msgstr "" + +#: cli/app/deploy.go:316 +#, c-format +msgid "version: taking new recipe version: %s" +msgstr "" + +#: cli/app/cp.go:85 +msgid "one of / arguments must take $SERVICE:$PATH form" +msgstr "" + +#: cli/app/restore.go:123 +msgid "hooks" +msgstr "" + +#: cli/app/rollback.go:243 +#, c-format +msgid "please select a downgrade (version: %s, chaos: %s):" +msgstr "" + +#: cli/app/rollback.go:270 +#, c-format +msgid "current deployment '%s' is not a known version for %s" +msgstr "" + +#: pkg/recipe/compose.go:249 +#, c-format +msgid "add '- \"%s\"' manually to the 'app' service in %s" +msgstr "" + +#: pkg/recipe/recipe.go:204 +#, c-format +msgid "ssh url: %s, " +msgstr "" + +#: cli/app/deploy.go:107 +#, c-format +msgid "ensure recipe: %s" +msgstr "" + +#: cli/app/volume.go:150 +#, c-format +msgid "removing volume %s failed: %s" +msgstr "" + +#: cli/internal/validate.go:151 +msgid "Specify a server name" +msgstr "" + +#: pkg/context/context.go:34 +msgid "context lacks Docker endpoint" +msgstr "" + +#: cli/app/restore.go:18 +msgid "Restore a snapshot" +msgstr "" + +#: cli/app/volume.go:153 +#, c-format +msgid "volume %s removed successfully" +msgstr "" + +#: cli/internal/deploy.go:81 +msgid "ENV VERSION" +msgstr "" + +#: cli/recipe/list.go:43 +msgid "tests" +msgstr "" + +#: cli/recipe/release.go:277 +#, c-format +msgid "dry run: move release note from 'next' to %s" +msgstr "" + +#: cli/app/secret.go:437 +#, c-format +msgid "no secrets stored for %s" +msgstr "" + +#: cli/app/rollback.go:27 +msgid "Roll an app back to a previous version" +msgstr "" + +#: cli/catalogue/catalogue.go:227 cli/recipe/release.go:394 +msgid "dry run: no changes published" +msgstr "" + +#: cli/app/cmd.go:259 +msgid "request remote user" +msgstr "" + +#: cli/app/undeploy.go:158 +msgid "prune unused containers, networks, and dangling images" +msgstr "" + +#: cli/recipe/recipe.go:12 +msgid "Manage recipes" +msgstr "" + +#: cli/recipe/reset.go:15 +msgid "Remove all unstaged changes from recipe config" +msgstr "" + +#: pkg/upstream/convert/service.go:414 +#, c-format +msgid "undefined secret %q" +msgstr "" + +#: pkg/service/service.go:30 +msgid "no services deployed?" +msgstr "" + +#: pkg/lint/recipe.go:176 +msgid "only annotated tags used for recipe version" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:255 +#, c-format +msgid "unimplemented call: SetDeadline(%v)" +msgstr "" + +#: cli/app/secret.go:500 cli/app/upgrade.go:435 cli/app/rollback.go:324 +#: cli/app/deploy.go:335 cli/app/remove.go:156 cli/app/volume.go:199 +#: cli/recipe/fetch.go:19 cli/recipe/fetch.go:131 +msgid "f" +msgstr "" + +#: cli/recipe/upgrade.go:172 +#, c-format +msgid "detected potential upgradable tags %s for %s" +msgstr "" + +#: pkg/secret/secret.go:62 pkg/secret/secret.go:80 +#, c-format +msgid "generated %s" +msgstr "" + +#: pkg/git/push.go:31 +msgid "git changes pushed" +msgstr "" + +#: cli/app/new.go:207 +msgid "SECRETS OVERVIEW" +msgstr "" + +#: cli/app/logs.go:93 +msgid "stderr" +msgstr "" + +#: cli/internal/deploy.go:117 +msgid "UNDEPLOY" +msgstr "" + +#: pkg/git/add.go:22 +#, c-format +msgid "dry run: adding %s" +msgstr "" + +#: cli/app/secret.go:38 cli/app/secret.go:170 cli/app/secret.go:280 +#: cli/app/upgrade.go:58 cli/app/rollback.go:58 cli/app/deploy.go:59 +#: cli/app/logs.go:32 pkg/autocomplete/autocomplete.go:17 +#: pkg/autocomplete/autocomplete.go:32 pkg/autocomplete/autocomplete.go:43 +#: pkg/autocomplete/autocomplete.go:59 pkg/autocomplete/autocomplete.go:77 +#: pkg/autocomplete/autocomplete.go:93 pkg/autocomplete/autocomplete.go:99 +#: pkg/autocomplete/autocomplete.go:114 +#, c-format +msgid "autocomplete failed: %s" +msgstr "" + +#: cli/app/secret.go:507 +msgid "trim" +msgstr "" + +#: cli/updater/updater.go:471 +msgid "kadabra [cmd] [flags]" +msgstr "" + +#: pkg/formatter/formatter.go:46 +msgid " ago" +msgstr "" + +#: cli/app/upgrade.go:402 cli/app/upgrade.go:406 +#, c-format +msgid "%s is not an upgrade for %s?" +msgstr "" + +#: cli/app/new.go:24 +msgid "" +"Creates a new app from a default recipe.\n" +"\n" +"This new app configuration is stored in your $ABRA_DIR directory under the\n" +"appropriate server.\n" +"\n" +"This command does not deploy your app for you. You will need to run \"abra " +"app\n" +"deploy \" to do so.\n" +"\n" +"You can see what recipes are available (i.e. values for the [recipe] " +"argument)\n" +"by running \"abra recipe ls\".\n" +"\n" +"Recipe commit hashes are supported values for \"[version]\".\n" +"\n" +"Passing the \"--secrets/-S\" flag will automatically generate secrets for " +"your\n" +"app and store them encrypted at rest on the chosen target server. These\n" +"generated secrets are only visible at generation time, so please take care " +"to\n" +"store them somewhere safe.\n" +"\n" +"You can use the \"--pass/-P\" to store these generated passwords locally in " +"a\n" +"pass store (see passwordstore.org for more). The pass command must be " +"available\n" +"on your $PATH." +msgstr "" + +#: cli/app/backup.go:213 +msgid "backup [cmd] [args] [flags]" +msgstr "" + +#: cli/recipe/release.go:549 +#, c-format +msgid "" +"unable to read version for %s from synced label. Did you try running \"abra " +"recipe sync %s\" already?" +msgstr "" + +#: cli/app/upgrade.go:269 cli/app/deploy.go:231 +#, c-format +msgid "attempting to run post deploy commands, saw: %s" +msgstr "" + +#: cli/catalogue/catalogue.go:187 cli/recipe/release.go:353 +#, c-format +msgid "no changes discovered in %s, nothing to publish?" +msgstr "" + +#: cli/recipe/new.go:86 +#, c-format +msgid "new recipe '%s' created: %s" +msgstr "" + +#: pkg/app/compose.go:18 +#, c-format +msgid "set recipe label 'coop-cloud.%s.recipe' to %s for %s" +msgstr "" + +#: cli/app/secret.go:476 cli/app/secret.go:516 cli/app/secret.go:540 +#: cli/app/secret.go:548 cli/app/restore.go:132 cli/app/ps.go:207 +#: cli/app/cmd.go:273 cli/app/new.go:380 cli/app/check.go:88 +#: cli/app/restart.go:155 cli/app/deploy.go:327 cli/app/cp.go:379 +#: cli/app/backup.go:288 cli/app/backup.go:304 cli/app/labels.go:136 +#: cli/catalogue/catalogue.go:272 cli/recipe/lint.go:129 +#: cli/updater/updater.go:538 +msgid "C" +msgstr "" + +#: cli/app/secret.go:145 +msgid "Insert secret" +msgstr "" + +#: cli/app/undeploy.go:155 +msgid "prune" +msgstr "" + +#: cli/recipe/release.go:430 +msgid "you can only use one of: --major, --minor, --patch" +msgstr "" + +#: cli/internal/deploy.go:189 +#, c-format +msgid "running command %s %s within the context of %s_%s" +msgstr "" + +#: pkg/upstream/container/exec.go:108 +msgid "Error monitoring TTY size:" +msgstr "" + +#: cli/app/restore.go:16 +msgid "restore [flags]" +msgstr "" + +#: cli/app/ps.go:181 cli/recipe/version.go:62 +msgid "IMAGE" +msgstr "" + +#: cli/app/run.go:105 +msgid "do not request a TTY" +msgstr "" + +#: cli/app/check.go:18 +msgid "chk" +msgstr "" + +#: cli/recipe/fetch.go:55 +#, c-format +msgid "%s is already fetched" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:172 +#, c-format +msgid "" +"command %v has exited with %v, please make sure the URL is valid, and Docker " +"18.09 or later is installed on the remote host: stderr=%s" +msgstr "" + +#: cli/server/list.go:34 +msgid "HOST" +msgstr "" + +#: cli/recipe/list.go:108 +msgid "filter by recipe" +msgstr "" + +#: cli/app/secret.go:362 +#, c-format +msgid "%s doesn't exist on server?" +msgstr "" + +#: cli/recipe/release.go:128 +msgid "previous git tags detected, assuming this is a new semver release" +msgstr "" + +#: cli/catalogue/catalogue.go:263 +msgid "skip-updates" +msgstr "" + +#: cli/run.go:74 +#, c-format +msgid "unsupported --lang: %s (want: es)" +msgstr "" + +#: cli/upgrade.go:16 +msgid "upgrade [flags]" +msgstr "" + +#: cli/upgrade.go:55 +msgid "install release candidate (may contain bugs)" +msgstr "" + +#: cli/internal/validate.go:174 +#, c-format +msgid "validated %s as server argument" +msgstr "" + +#: cli/app/restore.go:124 +msgid "H" +msgstr "" + +#: pkg/lint/recipe.go:52 +#, c-format +msgid "%s: skip condition: %s" +msgstr "" + +#: pkg/recipe/recipe.go:330 +#, c-format +msgid "%s: image meta is empty?" +msgstr "" + +#: cli/app/new.go:343 +msgid "specify server for new app" +msgstr "" + +#: cli/app/backup.go:215 +msgid "Manage app backups" +msgstr "" + +#: cli/internal/validate.go:106 +#, c-format +msgid "validated %s as app argument" +msgstr "" + +#: cli/app/upgrade.go:127 +msgid "no available upgrades" +msgstr "" + +#: cli/app/deploy.go:31 +msgid "" +"Deploy an app.\n" +"\n" +"This command supports chaos operations. Use \"--chaos/-C\" to deploy your " +"recipe\n" +"checkout as-is. Recipe commit hashes are also supported as values for\n" +"\"[version]\". Please note, \"upgrade\"/\"rollback\" do not support chaos " +"operations." +msgstr "" + +#: cli/app/remove.go:21 +msgid "Remove all app data, locally and remotely" +msgstr "" + +#: pkg/app/app.go:253 +#, c-format +msgid "env file for %s has issues: %s" +msgstr "" + +#: pkg/client/client.go:44 +#, c-format +msgid "unknown server, run \"abra server add %s\"?" +msgstr "" + +#: pkg/upstream/convert/service.go:815 +#, c-format +msgid "invalid credential spec: cannot specify both %s, and %s" +msgstr "" + +#: pkg/git/clone.go:64 pkg/git/clone.go:102 +#, c-format +msgid "git clone %s: cancelled due to interrupt" +msgstr "" + +#: cli/app/secret.go:526 +msgid "remove all secrets" +msgstr "" + +#: cli/app/new.go:284 +#, c-format +msgid "%s has no secrets to generate, skipping..." +msgstr "" + +#: cli/app/deploy.go:30 +msgid "Deploy an app" +msgstr "" + +#: cli/app/backup.go:112 +#, c-format +msgid "including SECRETS=%v in backupbot exec invocation" +msgstr "" + +#: cli/complete.go:12 +msgid "Generate autocompletion script" +msgstr "" + +#: cli/recipe/sync.go:72 +#, c-format +msgid "no git tags found for %s" +msgstr "" + +#: pkg/lint/recipe.go:68 +msgid "compose config has expected version" +msgstr "" + +#: pkg/secret/secret.go:139 +#, c-format +msgid "secret %s is > %d chars when combined with %s" +msgstr "" + +#: cli/app/secret.go:462 cli/app/secret.go:558 cli/app/ps.go:201 +#: cli/app/list.go:314 cli/server/list.go:102 cli/recipe/upgrade.go:372 +#: cli/recipe/version.go:134 cli/recipe/list.go:100 +msgid "print machine-readable output" +msgstr "" + +#: cli/app/cmd.go:24 +msgid "Run app commands" +msgstr "" + +#: pkg/recipe/git.go:367 +#, c-format +msgid "detected %s as tags for recipe %s" +msgstr "" + +#: pkg/git/branch.go:99 +#, c-format +msgid "successfully checked out %v in %s" +msgstr "" + +#: cli/app/upgrade.go:30 +msgid "up" +msgstr "" + +#: cli/recipe/fetch.go:133 +msgid "force re-fetch" +msgstr "" + +#: cli/recipe/list.go:42 +msgid "email" +msgstr "" + +#: pkg/upstream/commandconn/connection.go:38 +msgid "ssh host connection is not valid" +msgstr "" + +#: cli/app/undeploy.go:25 +msgid "" +"This does not destroy any application data.\n" +"\n" +"However, you should remain vigilant, as your swarm installation will " +"consider\n" +"any previously attached volumes as eligible for pruning once undeployed.\n" +"\n" +"Passing \"--prune/-p\" does not remove those volumes." +msgstr "" + +#: cli/app/backup.go:180 +msgid "List all snapshots" +msgstr "" + +#: pkg/upstream/convert/volume.go:116 +msgid "volume options are incompatible with type tmpfs" +msgstr "" + +#: cli/app/new.go:70 cli/app/deploy.go:262 +msgid "cannot use [version] and --chaos together" +msgstr "" + +#: cli/app/config.go:16 +msgid "config [flags]" +msgstr "" + +#: cli/server/add.go:184 +#, c-format +msgid "server dir for %s already created" +msgstr "" + +#: cli/updater/updater.go:376 +#, c-format +msgid "don't update %s due to missing recipe name" +msgstr "" + +#: pkg/recipe/recipe.go:435 +#, c-format +msgid "detected versions %s for %s" +msgstr "" + +#: pkg/git/init.go:73 +msgid "set 'main' as the default branch" +msgstr "" + +#: cli/app/list.go:45 +msgid "List all managed apps" +msgstr "" + +#: cli/recipe/release.go:562 +#, c-format +msgid "please fix your synced label for %s and re-run this command" +msgstr "" + +#: pkg/ssh/ssh.go:16 +#, c-format +msgid "SSH host key verification failed for %s" +msgstr "" + +#: cli/app/secret.go:25 cli/catalogue/catalogue.go:25 +msgid "g" +msgstr "" + +#: cli/recipe/new.go:87 +msgid "happy hacking 🎉" +msgstr "" + +#: cli/internal/deploy.go:120 +msgid "CHAOS DEPLOY" +msgstr "" + +#: pkg/app/compose.go:68 +#, c-format +msgid "set label 'coop-cloud.%s.autoupdate' to %s for %s" +msgstr "" + +#: pkg/ui/deploy.go:83 +#, c-format +msgid "err: %v, " +msgstr "" + +#: cli/app/undeploy.go:143 cli/server/prune.go:66 +#, c-format +msgid "images pruned: %d; space reclaimed: %s" +msgstr "" + +#: cli/internal/command.go:110 +#, c-format +msgid "%s doesn't have a %s function" +msgstr "" + +#: cli/app/secret.go:459 cli/app/secret.go:555 cli/app/ps.go:198 +#: cli/app/list.go:311 cli/server/list.go:99 cli/recipe/upgrade.go:369 +#: cli/recipe/version.go:131 cli/recipe/list.go:97 +msgid "machine" +msgstr "" + +#: cli/recipe/sync.go:23 +msgid "" +"Generate labels for the main recipe service.\n" +"\n" +"By convention, the service named \"app\" using the following format:\n" +"\n" +" coop-cloud.${STACK_NAME}.version=\n" +"\n" +"Where [version] can be specifed on the command-line or Abra can attempt to\n" +"auto-generate it for you. The configuration will be updated on the\n" +"local file system." +msgstr "" + +#: cli/recipe/release.go:29 +msgid "" +"Create a new version of a recipe.\n" +"\n" +"These versions are then published on the Co-op Cloud recipe catalogue. " +"These\n" +"versions take the following form:\n" +"\n" +" a.b.c+x.y.z\n" +"\n" +"Where the \"a.b.c\" part is a semantic version determined by the maintainer. " +"The\n" +"\"x.y.z\" part is the image tag of the recipe \"app\" service (the main " +"container\n" +"which contains the software to be used, by naming convention).\n" +"\n" +"We maintain a semantic versioning scheme (\"a.b.c\") alongside the recipe\n" +"versioning scheme (\"x.y.z\") in order to maximise the chances that the " +"nature of\n" +"recipe updates are properly communicated. I.e. developers of an app might\n" +"publish a minor version but that might lead to changes in the recipe which " +"are\n" +"major and therefore require intervention while doing the upgrade work.\n" +"\n" +"Publish your new release to git.coopcloud.tech with \"--publish/-p\". This\n" +"requires that you have permission to git push to these repositories and " +"have\n" +"your SSH keys configured on your account." +msgstr "" + +#: cli/updater/updater.go:396 +#, c-format +msgid "" +"don't update %s due to disabled auto updates or missing ENABLE_AUTO_UPDATE " +"env" +msgstr "" + +#: cli/internal/deploy.go:167 +#, c-format +msgid "running post-command '%s %s' in container %s" +msgstr "" + +#: pkg/service/service.go:57 pkg/service/service.go:111 +msgid "ambiguous service list received, prompting for input" +msgstr "" + +#: pkg/lint/recipe.go:97 +msgid "use semver-like tags" +msgstr "" + +#: pkg/ssh/ssh.go:26 +msgid "docker: is the daemon running / your user has docker permissions?" +msgstr "" + +#: cli/server/prune.go:15 +msgid "prune [flags]" +msgstr "" + +#: cli/updater/updater.go:556 +msgid "update all deployed apps" +msgstr "" + +#: pkg/git/diff.go:30 +msgid "unable to locate git command, cannot output diff" +msgstr "" + +#: pkg/git/read.go:31 +#, c-format +msgid "unable to open worktree of %s: %s" +msgstr "" + +#: cli/app/deploy.go:28 +msgid "deploy [version] [flags]" +msgstr "" + +#: pkg/upstream/convert/service.go:834 +#, c-format +msgid "" +"invalid credential spec: spec specifies config %v, but no such config can be " +"found" +msgstr "" + +#: pkg/config/env.go:74 pkg/config/env.go:107 +#, c-format +msgid "broken symlink in your abra config folders: %s" +msgstr "" + +#: cli/app/undeploy.go:135 cli/server/prune.go:52 +#, c-format +msgid "networks pruned: %d" +msgstr "" + +#: pkg/app/compose.go:30 +#, c-format +msgid "set label 'coop-cloud.%s.chaos' to %v for %s" +msgstr "" + +#: cli/app/remove.go:148 +#, c-format +msgid "file: %s removed" +msgstr "" + +#: cli/server/prune.go:75 +#, c-format +msgid "volumes pruned: %d; space reclaimed: %s" +msgstr "" + +#: cli/recipe/upgrade.go:247 +#, c-format +msgid "unable to determine versioning semantics of %s, listing all tags" +msgstr "" + +#: pkg/upstream/convert/service.go:462 +#, c-format +msgid "undefined config %q" +msgstr "" + +#: cli/app/rollback.go:142 +msgid "unknown deployed version, unable to downgrade" +msgstr "" + +#: cli/app/remove.go:19 +msgid "remove [flags]" +msgstr "" + +#: cli/app/remove.go:50 +#, c-format +msgid "ALERTA ALERTA: deleting %s data and config (local/remote)" +msgstr "" + +#: cli/app/volume.go:162 +msgid "" +"'x' indicates selected, enter / return to confirm, ctrl-c to exit, vim mode " +"is enabled" +msgstr "" + +#: cli/run.go:49 +#, c-format +msgid "unable to create %s: %s" +msgstr "" + +#: cli/server/add.go:202 +msgid "use local server" +msgstr "" + +#: cli/recipe/upgrade.go:216 +#, c-format +msgid "upgrading service %s from %s to %s (pinned tag: %s)" +msgstr "" + +#: cli/recipe/release.go:133 +#, c-format +msgid "" +"no tag specified and no previous tag available for %s, assuming this is the " +"initial release" +msgstr "" + +#: cli/recipe/release.go:185 +msgid "app service is missing image tag?" +msgstr "" + +#: cli/updater/updater.go:231 +#, c-format +msgid "%s (%s) can be upgraded from version %s to %s" +msgstr "" + +#: pkg/lint/recipe.go:140 +msgid "one service named 'app'" +msgstr "" + +#: cli/app/restart.go:24 +msgid "" +"This command restarts services within a deployed app.\n" +"\n" +"Run \"abra app ps \" to see a list of service names.\n" +"\n" +"Pass \"--all-services/-a\" to restart all services." +msgstr "" + +#: cli/app/deploy.go:96 +#, c-format +msgid "%s is already deployed" +msgstr "" + +#: cli/recipe/upgrade.go:380 +msgid "list all tags, not just upgrades" +msgstr "" + +#: cli/recipe/version.go:19 +msgid "List recipe versions" +msgstr "" + +#: pkg/app/app.go:510 +#, c-format +msgid "adding env vars to %s service config" +msgstr "" + +#: pkg/lint/recipe.go:141 +msgid "name a servce 'app'" +msgstr "" + +#: pkg/recipe/recipe.go:462 +#, c-format +msgid "recipe metadata retrieved for %s" +msgstr "" + +#: cli/app/upgrade.go:434 cli/app/rollback.go:323 cli/app/deploy.go:334 +#: cli/app/remove.go:155 cli/app/volume.go:198 cli/recipe/fetch.go:130 +msgid "force" +msgstr "" + +#: cli/server/prune.go:18 +msgid "" +"Prunes unused containers, networks, and dangling images.\n" +"\n" +"Use \"--volumes/-v\" to remove volumes that are not associated with a " +"deployed\n" +"app. This can result in unwanted data loss if not used carefully." +msgstr "" + +#: cli/internal/command.go:70 +#, c-format +msgid "%s does not exist for %s, use /bin/sh as fallback" +msgstr "" + +#: pkg/git/remote.go:15 +#, c-format +msgid "dry run: remote %s (%s) not created" +msgstr "" + +#: pkg/container/container.go:44 +#, c-format +msgid "expected 1 container but found %v: %s" +msgstr "" + +#: cli/app/secret.go:444 +msgid "Manage app secrets" +msgstr "" + +#: cli/server/add.go:23 +msgid "Add a new server" +msgstr "" + +#: cli/recipe/lint.go:115 +#, c-format +msgid "critical errors present in %s config" +msgstr "" + +#: pkg/lint/recipe.go:90 +msgid "tag all images with stable tags" +msgstr "" + +#: pkg/lint/recipe.go:170 +msgid "vendor config versions in an abra.sh" +msgstr "" + +#: pkg/lint/recipe.go:496 +#, c-format +msgid "unable to list local tags for %s" +msgstr "" + +#: cli/app/backup.go:68 +msgid "" +"Downloads a backup.tar.gz to the current working directory.\n" +"\n" +"\"--volumes/-v\" includes data contained in volumes alongide paths specified " +"in\n" +"\"backupbot.backup.path\" labels." +msgstr "" + +#: cli/run.go:126 cli/updater/updater.go:493 +msgid "show debug messages" +msgstr "" + +#: pkg/app/app.go:400 +#, c-format +msgid "copied & templated %s to %s" +msgstr "" + +#: pkg/lint/recipe.go:504 +msgid "invalid lightweight tag detected" +msgstr "" + +#: cli/app/new.go:374 +msgid "automatically generate secrets" +msgstr "" + +#: cli/app/restart.go:164 +msgid "restart all services" +msgstr "" + +#: pkg/ui/deploy.go:341 +#, c-format +msgid "%s: %s (retries: %v, healthcheck: %s)" +msgstr "" + +#: pkg/config/abra.go:34 +#, c-format +msgid "error loading config file: %s" +msgstr "" + +#: pkg/recipe/git.go:434 +#, c-format +msgid "%s service is missing image tag?" +msgstr "" + +#: pkg/git/init.go:60 +#, c-format +msgid "set reference: %s" +msgstr "" + +#: cli/app/new.go:266 +msgid "Specify app domain" +msgstr "" + +#: pkg/lint/recipe.go:169 +msgid "config version are vendored" +msgstr "" + +#: cli/app/secret.go:394 cli/app/ps.go:182 cli/app/list.go:221 +#: cli/recipe/version.go:62 cli/recipe/version.go:103 +msgid "VERSION" +msgstr "" + +#: cli/app/undeploy.go:23 +msgid "un" +msgstr "" + +#: cli/app/volume.go:161 +msgid "which volumes do you want to remove?" +msgstr "" + +#: cli/catalogue/catalogue.go:175 +#, c-format +msgid "generated recipe catalogue: %s" +msgstr "" + +#: cli/recipe/upgrade.go:243 +#, c-format +msgid "upgrade to which tag? (service: %s, image: %s, tag: %s)" +msgstr "" + +#: pkg/git/read.go:45 +#, c-format +msgid "unable to query status of %s: %s" +msgstr "" + +#: cli/app/backup.go:263 +msgid "path" +msgstr "" + +#: cli/recipe/release.go:413 +#, c-format +msgid "new release published: %s" +msgstr "" + +#: cli/app/list.go:148 +#, c-format +msgid "unable to clone %s: %s" +msgstr "" + +#: cli/server/remove.go:20 +msgid "" +"Remove a managed server.\n" +"\n" +"Abra will remove the internal bookkeeping ($ABRA_DIR/servers/...) and\n" +"underlying client connection context. This server will then be lost in " +"time,\n" +"like tears in rain." +msgstr "" + +#: pkg/service/service.go:95 +#, c-format +msgid "no services matching the %v filter found?" +msgstr "" + +#: pkg/secret/pass.go:15 pkg/secret/pass.go:37 +msgid "pass command not found on $PATH, is it installed?" +msgstr "" + +#: cli/app/volume.go:145 +#, c-format +msgid "unable to remove volume: no volume with name '%s'?" +msgstr "" + +#: cli/updater/updater.go:155 pkg/app/compose.go:86 +#, c-format +msgid "no %s label found for %s" +msgstr "" + +#: pkg/secret/secret.go:212 +#, c-format +msgid "attempting to generate and store %s on %s" +msgstr "" + +#: cli/app/cmd.go:119 +#, c-format +msgid "--local detected, running %s on local work station" +msgstr "" + +#: cli/app/secret.go:102 +msgid "no secrets generated" +msgstr "" + +#: cli/app/secret.go:483 cli/app/secret.go:523 cli/app/backup.go:239 +#: cli/server/prune.go:90 cli/recipe/fetch.go:114 cli/updater/updater.go:553 +msgid "all" +msgstr "" + +#: cli/app/new.go:371 cli/app/backup.go:271 +msgid "secrets" +msgstr "" + +#: cli/app/restart.go:21 +msgid "restart [[service] | --all-services] [flags]" +msgstr "" + +#: cli/server/add.go:40 +msgid " abra server add 1312.net" +msgstr "" + +#: cli/app/secret.go:253 +#, c-format +msgid "deleted %s successfully from local pass store" +msgstr "" + +#: cli/app/new.go:49 +msgid "Create a new app" +msgstr "" + +#: cli/app/remove.go:141 +msgid "no volumes to remove" +msgstr "" + +#: cli/app/run.go:24 +msgid "" +" # run with args/flags\n" +" abra app run 1312.net app -- ls -lha\n" +"\n" +" # run without args/flags\n" +" abra app run 1312.net app bash --user nobody\n" +"\n" +" # run with both kinds of args/flags \n" +" abra app run 1312.net app --user nobody -- ls -lha" +msgstr "" + +#: cli/app/upgrade.go:152 +#, c-format +msgid "choosing %s as version to upgrade" +msgstr "" + +#: cli/recipe/fetch.go:117 +msgid "fetch all recipes" +msgstr "" + +#: pkg/recipe/recipe.go:458 +#, c-format +msgid "recipe %s does not exist?" +msgstr "" + +#: cli/app/restore.go:118 +msgid "restore specific volumes" +msgstr "" + +#: cli/app/upgrade.go:415 cli/app/undeploy.go:51 cli/app/deploy.go:88 +#, c-format +msgid "checking whether %s is already deployed" +msgstr "" + +#: cli/app/upgrade.go:450 cli/app/rollback.go:339 cli/app/deploy.go:350 +msgid "no-converge-checks" +msgstr "" + +#: cli/app/env.go:41 +msgid "ENV OVERVIEW" +msgstr "" + +#: pkg/lint/recipe.go:69 +msgid "ensure 'version: \"3.8\"' in compose configs" +msgstr "" + +#: cli/internal/deploy.go:80 +msgid "CURRENT DEPLOYMENT" +msgstr "" + +#: pkg/client/client.go:97 +#, c-format +msgid "swarm mode not enabled on %s?" +msgstr "" + +#: pkg/client/volumes.go:41 +#, c-format +msgid "volume %s: %s" +msgstr "" + +#: cli/app/deploy.go:276 +#, c-format +msgid "secret not generated: %s" +msgstr "" + +#: cli/app/volume.go:76 +msgid "remove [volume] [flags]" +msgstr "" + +#: cli/recipe/fetch.go:21 +msgid "" +"Using \"--force/-f\" Git syncs an existing recipe. It does not erase " +"unstaged changes." +msgstr "" + +#: pkg/upstream/convert/service.go:774 +msgid "replicas can only be used with replicated mode" +msgstr "" + +#: cli/app/new.go:315 +msgid "Select app server:" +msgstr "" + +#: cli/recipe/upgrade.go:44 +msgid "" +"Upgrade a given configuration.\n" +"\n" +"It will update the relevant compose file tags on the local file system.\n" +"\n" +"Some image tags cannot be parsed because they do not follow some sort of\n" +"semver-like convention. In this case, all possible tags will be listed and " +"it\n" +"is up to the end-user to decide.\n" +"\n" +"The command is interactive and will show a select input which allows you to\n" +"make a seclection. Use the \"?\" key to see more help on navigating this\n" +"interface.\n" +"\n" +"You may invoke this command in \"wizard\" mode and be prompted for input." +msgstr "" + +#: cli/recipe/fetch.go:64 +#, c-format +msgid "unable to discover SSH remote for %s" +msgstr "" + +#: cli/recipe/release.go:283 +msgid "Use release note in release/next?" +msgstr "" + +#: cli/app/remove.go:38 +msgid " abra app remove 1312.net" +msgstr "" + +#: cli/app/remove.go:53 +msgid "are you sure?" +msgstr "" + +#: cli/run.go:159 +msgid "force select language (supported: XXX)" +msgstr "" + +#: pkg/upstream/convert/volume.go:96 +msgid "tmpfs options are incompatible with type bind" +msgstr "" + +#: cli/app/upgrade.go:318 +#, c-format +msgid "parsing chosen upgrade version failed: %s" +msgstr "" + +#: cli/recipe/new.go:36 +msgid "Create a new recipe" +msgstr "" + +#: cli/recipe/new.go:126 +msgid "Git email name to do commits with" +msgstr "" + +#: cli/recipe/release.go:387 +#, c-format +msgid "created tag %s at %s" +msgstr "" + +#: pkg/recipe/compose.go:59 +#, c-format +msgid "retrieved %s configs for %s" +msgstr "" + +#: cli/app/secret.go:366 +msgid "no secrets to remove?" +msgstr "" + +#: cli/app/deploy.go:180 +msgid "skipping domain checks" +msgstr "" + +#: cli/app/backup.go:67 +msgid "Download a snapshot" +msgstr "" + +#: cli/upgrade.go:19 +msgid "" +"Upgrade abra in-place with the latest stable or release candidate.\n" +"\n" +"By default, the latest stable release is downloaded.\n" +"\n" +"Use \"--rc/-r\" to install the latest release candidate. Please bear in mind " +"that\n" +"it may contain absolutely catastrophic deal-breaker bugs. Thank you very " +"much\n" +"for the testing efforts 💗" +msgstr "" + +#: cli/server/add.go:24 +msgid "" +"Add a new server to your configuration so that it can be managed by Abra.\n" +"\n" +"Abra relies on the standard SSH command-line and ~/.ssh/config for client\n" +"connection details. You must configure an entry per-host in your ~/.ssh/" +"config\n" +"for each server:\n" +"\n" +" Host 1312.net 1312\n" +" Hostname 1312.net\n" +" User antifa\n" +" Port 12345\n" +" IdentityFile ~/.ssh/antifa@somewhere\n" +"\n" +"If \"--local\" is passed, then Abra assumes that the current local server " +"is\n" +"intended as the target server. This is useful when you want to have your " +"entire\n" +"Co-op Cloud config located on the server itself, and not on your local\n" +"developer machine. The domain is then set to \"default\"." +msgstr "" + +#: cli/recipe/diff.go:13 +msgid "diff [flags]" +msgstr "" + +#: pkg/app/app.go:487 +#, c-format +msgid "retrieved app statuses: %s" +msgstr "" + +#: pkg/container/container.go:69 +msgid "failed to match chosen container" +msgstr "" + +#: cli/app/new.go:372 cli/app/logs.go:102 cli/app/backup.go:272 +#: cli/app/list.go:289 +msgid "S" +msgstr "" + +#: cli/app/secret.go:394 +msgid "GENERATED NAME" +msgstr "" + +#: cli/recipe/diff.go:15 +msgid "Show unstaged changes in recipe config" +msgstr "" + +#: cli/server/add.go:107 +#, c-format +msgid "ssh %s error: %s" +msgstr "" + +#: cli/recipe/lint.go:33 +msgid "rule" +msgstr "" + +#: cli/internal/validate.go:171 +msgid "server doesn't exist?" +msgstr "" + +#: pkg/upstream/container/hijack.go:167 +#, c-format +msgid "error sendStdin: %s" +msgstr "" + +#: pkg/recipe/recipe.go:237 +#, c-format +msgid "%s: attempt recipe metadata parse" +msgstr "" + +#: cli/app/upgrade.go:458 +msgid "releasenotes" +msgstr "" + +#: cli/app/undeploy.go:104 +msgid "undeploy succeeded 🟢" +msgstr "" + +#: cli/app/cp.go:272 +msgid "can't copy dir to file" +msgstr "" + +#: cli/server/add.go:146 +#, c-format +msgid "serverAdd: cleanUp: failed to remove %s: %s" +msgstr "" + +#: pkg/secret/secret.go:207 +#, c-format +msgid "skipping generation of %s (generate=false)" +msgstr "" + +#: cli/app/cp.go:197 +#, c-format +msgid "remote: %s does not exist" +msgstr "" + +#: pkg/recipe/compose.go:72 +#, c-format +msgid "%s is missing a compose.yml or compose.*.yml file?" +msgstr "" + +#: pkg/recipe/compose.go:159 +#, c-format +msgid "parsed %s from %s" +msgstr "" + +#: cli/app/secret.go:499 +msgid "file" +msgstr "" + +#: cli/run.go:78 +#, c-format +msgid "abra version: %s, commit: %s, lang: %s" +msgstr "" + +#: pkg/app/app.go:424 +msgid "querying remote servers..." +msgstr "" + +#: pkg/secret/secret.go:126 +#, c-format +msgid "missing version for secret? (%s)" +msgstr "" + +#: pkg/upstream/convert/service.go:122 +#, c-format +msgid "duplicate config target for %s not allowed" +msgstr "" + +#: cli/app/restore.go:79 +#, c-format +msgid "including NO_COMMANDS=%v in backupbot exec invocation" +msgstr "" + +#: cli/app/check.go:17 +msgid "check [flags]" +msgstr "" + +#: cli/app/cp.go:72 cli/internal/command.go:39 +#, c-format +msgid "retrieved %s as target container on %s" +msgstr "" + +#: cli/app/remove.go:59 +msgid "aborting as requested" +msgstr "" + +#: cli/app/logs.go:101 +msgid "since" +msgstr "" + +#: cli/run.go:150 +msgid "ignore .env version checkout" +msgstr "" + +#: pkg/ui/deploy.go:88 +#, c-format +msgid "status: %s}" +msgstr "" + +#: cli/app/undeploy.go:24 +msgid "Undeploy an app" +msgstr "" + +#: cli/app/deploy.go:290 +#, c-format +msgid "version: taking chaos version: %s" +msgstr "" + +#: cli/app/env.go:15 +msgid "env [flags]" +msgstr "" + +#: pkg/lint/recipe.go:154 +msgid "traefik routing enabled" +msgstr "" + +#: cli/app/secret.go:372 +msgid "list " +msgstr "" + +#: cli/app/new.go:47 +msgid "new [recipe] [version] [flags]" +msgstr "" + +#: cli/run.go:34 +msgid "upgrade" +msgstr "" + +#: cli/recipe/upgrade.go:330 cli/recipe/sync.go:211 cli/recipe/release.go:121 +#, c-format +msgid "%s currently has these unstaged changes 👇" +msgstr "" + +#: pkg/upstream/convert/service.go:375 +#, c-format +msgid "undefined network %q" +msgstr "" + +#: cli/updater/updater.go:76 +msgid "Upgrade apps" +msgstr "" + +#: pkg/lint/recipe.go:212 +#, c-format +msgid "" +"recipe '%s' failed lint checks:\n" +"%s" +msgstr "" + +#: cli/app/check.go:20 +msgid "" +"Compare env vars in both the app \".env\" and recipe \".env.sample\" file.\n" +"\n" +"The goal is to ensure that recipe \".env.sample\" env vars are defined in " +"your\n" +"app \".env\" file. Only env var definitions in the \".env.sample\" which " +"are\n" +"uncommented, e.g. \"FOO=bar\" are checked. If an app \".env\" file does not " +"include\n" +"these env vars, then \"check\" will complain.\n" +"\n" +"Recipe maintainers may or may not provide defaults for env vars within " +"their\n" +"recipes regardless of commenting or not (e.g. through the use of\n" +"${FOO:} syntax). \"check\" does not confirm or deny this for you." +msgstr "" + +#: cli/server/add.go:114 +#, c-format +msgid "unable to resolve IPv4 for %s" +msgstr "" + +#: cli/app/deploy.go:311 +#, c-format +msgid "version: taking deployed version: %s" +msgstr "" + +#: cli/updater/updater.go:273 +#, fuzzy, c-format +msgid "no published releases for %s in the recipe catalogue?" +msgstr "TRANSLATE THIS FUCKING SHIT ALREADY" + +#: cli/updater/updater.go:548 +msgid "check for major updates" +msgstr "" + +#: pkg/ui/deploy.go:333 +msgid "rolled back" +msgstr "" + +#: pkg/recipe/git.go:156 +#, c-format +msgid "attempting to checkout '%s' as chaos commit" +msgstr "" + +#: cli/app/restart.go:133 +#, c-format +msgid "attempting to scale %s to 1" +msgstr "" + +#: cli/app/volume.go:190 +msgid "volume [cmd] [args] [flags]" +msgstr "" + +#: cli/app/backup.go:178 +msgid "snapshots [flags]" +msgstr "" + +#: cli/recipe/sync.go:154 +msgid "you can only use one version flag: --major, --minor or --patch" +msgstr "" + +#: pkg/recipe/git.go:378 +#, c-format +msgid "git: opening repository in %s" +msgstr "" + +#: pkg/recipe/recipe.go:207 +#, c-format +msgid "sample env: %s, " +msgstr "" + +#: cli/app/secret.go:246 +#, c-format +msgid "deleted %s successfully from server" +msgstr "" + +#: cli/recipe/upgrade.go:218 +#, c-format +msgid "service %s, image %s pinned to %s, no compatible upgrade found" +msgstr "" + +#: pkg/lint/recipe.go:22 +msgid "critical" +msgstr "" + +#: pkg/upstream/container/tty.go:39 +#, c-format +msgid "error resize: %s" +msgstr "" + +#: pkg/upstream/convert/service.go:780 +#, c-format +msgid "unknown mode: %s" +msgstr "" + +#: cli/app/secret.go:374 +msgid "List all secrets" +msgstr "" + +#: cli/app/restore.go:57 +#, c-format +msgid "including TARGET=%s in backupbot exec invocation" +msgstr "" + +#: cli/app/cmd.go:128 cli/app/cmd.go:174 +#, c-format +msgid "parsed following command arguments: %s" +msgstr "" + +#: cli/app/upgrade.go:266 cli/app/deploy.go:229 +#, c-format +msgid "run the following post-deploy commands: %s" +msgstr "" + +#: pkg/upstream/container/hijack.go:132 +msgid "[hijack] end of stdout" +msgstr "" + +#: pkg/formatter/formatter.go:134 +msgid "CreateOverview: only accepts rows of len == 2" +msgstr "" + +#: cli/app/backup.go:247 +msgid "timestamps" +msgstr "" + +#: cli/app/list.go:46 +msgid "" +"Generate a report of all managed apps.\n" +"\n" +"Use \"--status/-S\" flag to query all servers for the live deployment status." +msgstr "" + +#: cli/catalogue/catalogue.go:235 +msgid "Manage the recipe catalogue" +msgstr "" + +#: pkg/secret/pass.go:51 +#, c-format +msgid "%s removed from pass store" +msgstr "" + +#: pkg/recipe/compose.go:58 +#, c-format +msgid "COMPOSE_FILE detected (%s), loading %s" +msgstr "" + +#: cli/app/secret.go:486 +msgid "generate all secrets" +msgstr "" + +#: cli/app/new.go:355 +msgid "domain" +msgstr "" + +#: cli/app/volume.go:78 +msgid "" +"Remove volumes associated with an app.\n" +"\n" +"The app in question must be undeployed before you try to remove volumes. " +"See\n" +"\"abra app undeploy \" for more.\n" +"\n" +"The command is interactive and will show a multiple select input which " +"allows\n" +"you to make a seclection. Use the \"?\" key to see more help on navigating " +"this\n" +"interface.\n" +"\n" +"Passing \"--force/-f\" will select all volumes for removal. Be careful." +msgstr "" + +#: cli/app/list.go:43 cli/server/list.go:18 +msgid "list [flags]" +msgstr "" + +#: cli/recipe/fetch.go:23 +msgid "" +" # fetch from recipe catalogue\n" +" abra recipe fetch gitea\n" +"\n" +" # fetch from remote recipe\n" +" abra recipe fetch git.foo.org/recipes/myrecipe\n" +"\n" +" # fetch with ssh remote for hacking\n" +" abra recipe fetch gitea --ssh" +msgstr "" + +#: pkg/git/clone.go:68 +msgid "git clone: main branch failed, attempting master branch" +msgstr "" + +#: pkg/recipe/compose.go:248 +msgid "no existing label found, automagic insertion not supported yet" +msgstr "" + +#: cli/app/run.go:21 +msgid "run [[args] [flags] | [flags] -- [args]]" +msgstr "" + +#: cli/app/cmd.go:168 +#, c-format +msgid "no service %s for %s?" +msgstr "" + +#: cli/recipe/reset.go:13 +msgid "reset [flags]" +msgstr "" + +#: cli/updater/updater.go:444 +#, c-format +msgid "upgrade %s (%s) to version %s" +msgstr "" + +#: pkg/git/init.go:21 +#, c-format +msgid "git branch rename: %s" +msgstr "" + +#: pkg/git/branch.go:68 +#, c-format +msgid "failed to select default branch in %s" +msgstr "" + +#: cli/recipe/upgrade.go:296 +#, c-format +msgid "tag upgraded from %s to %s for %s" +msgstr "" + +#: pkg/client/context.go:26 +#, c-format +msgid "created the %s context" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:49 +#, c-format +msgid "commandconn: starting %s with %v" +msgstr "" + +#: pkg/git/common.go:13 +#, c-format +msgid "no .git directory in %s?" +msgstr "" + +#: cli/app/backup.go:167 +#, c-format +msgid "including RETRIES=%s in backupbot exec invocation" +msgstr "" + +#: cli/recipe/fetch.go:93 +msgid "fetching latest recipes..." +msgstr "" + +#: cli/app/restore.go:115 cli/app/backup.go:279 cli/server/prune.go:98 +msgid "volumes" +msgstr "" + +#: cli/app/undeploy.go:22 +msgid "undeploy [flags]" +msgstr "" + +#: cli/app/config.go:19 +msgid " abra config 1312.net" +msgstr "" + +#: cli/app/backup.go:214 +msgid "b" +msgstr "" + +#: cli/catalogue/catalogue.go:250 cli/recipe/release.go:611 +msgid "publish changes to git.coopcloud.tech" +msgstr "" + +#: cli/server/server.go:12 +msgid "Manage servers" +msgstr "" + +#: cli/app/secret.go:53 +msgid "missing arguments [secret]/[version] or '--all'" +msgstr "" + +#: cli/app/new.go:236 pkg/app/app.go:141 +#, c-format +msgid "trimming %s to %s to avoid runtime limits" +msgstr "" + +#: cli/app/volume.go:191 +msgid "vl" +msgstr "" + +#: pkg/config/abra.go:37 +#, c-format +msgid "config file loaded from: %s" +msgstr "" + +#: cli/app/restore.go:62 +#, c-format +msgid "including NONINTERACTIVE=%v in backupbot exec invocation" +msgstr "" + +#: cli/app/new.go:366 +msgid "store secrets in a local pass store" +msgstr "" + +#: cli/app/cmd.go:265 +msgid "T" +msgstr "" + +#: cli/recipe/new.go:50 +#, c-format +msgid "%s recipe directory already exists?" +msgstr "" + +#: cli/recipe/release.go:487 +#, c-format +msgid "latest git tag (%s) and synced label (%s) are the same?" +msgstr "" + +#: cli/recipe/release.go:552 +#, c-format +msgid "discovered %s as currently synced recipe label" +msgstr "" + +#: pkg/catalogue/catalogue.go:84 pkg/recipe/git.go:278 +#, c-format +msgid "fetched latest git changes for %s" +msgstr "" + +#: pkg/app/app.go:301 +#, c-format +msgid "server %s doesn't exist? Run \"abra server ls\" to check" +msgstr "" + +#: pkg/upstream/convert/volume.go:56 +#, c-format +msgid "undefined volume %q" +msgstr "" + +#: cli/app/secret.go:137 +msgid "NOW" +msgstr "" + +#: cli/recipe/upgrade.go:119 +#, c-format +msgid "did not find versions file for %s" +msgstr "" + +#: cli/app/cmd.go:108 cli/internal/deploy.go:151 +#, c-format +msgid "%s does not exist for %s?" +msgstr "" + +#: cli/catalogue/catalogue.go:258 cli/recipe/sync.go:225 +#: cli/recipe/release.go:579 +msgid "report changes that would be made" +msgstr "" + +#: cli/internal/deploy.go:86 +#, c-format +msgid "%s OVERVIEW" +msgstr "" + +#: pkg/envfile/envfile.go:73 +#, c-format +msgid "couldn't parse %s" +msgstr "" + +#: pkg/recipe/git.go:241 +#, c-format +msgid "unable to read remotes in %s: %s" +msgstr "" + +#: cli/app/cmd.go:248 cli/server/add.go:199 cli/server/list.go:69 +msgid "local" +msgstr "" + +#: cli/recipe/upgrade.go:145 +#, c-format +msgid "%s not considered semver-like" +msgstr "" + +#: cli/recipe/list.go:37 +msgid "name" +msgstr "" + +#: pkg/app/app.go:248 +#, c-format +msgid "env file for %s couldn't be read: %s" +msgstr "" + +#: pkg/lint/recipe.go:481 +#, c-format +msgid "secret %s is longer than 12 characters" +msgstr "" + +#: pkg/upstream/container/hijack.go:100 +#, c-format +msgid "invalid detach escape keys, using default: %s" +msgstr "" + +#: pkg/config/env.go:98 +#, c-format +msgid "directory is empty: %s" +msgstr "" + +#: cli/app/upgrade.go:240 cli/app/rollback.go:202 cli/app/deploy.go:203 +#, c-format +msgid "set waiting timeout to %d second(s)" +msgstr "" + +#: cli/app/restart.go:108 +#, c-format +msgid "attempting to scale %s to 0" +msgstr "" + +#: pkg/lint/recipe.go:125 +msgid "reduce length of secret names to 12 chars" +msgstr "" + +#: pkg/recipe/files.go:36 +#, c-format +msgid "%s release notes:" +msgstr "" + +#: pkg/git/init.go:17 +#, c-format +msgid "git init: %s" +msgstr "" + +#: pkg/git/init.go:47 +#, c-format +msgid "git commit: %s" +msgstr "" + +#: cli/app/labels.go:25 +msgid "Show deployment labels" +msgstr "" + +#: cli/run.go:93 +msgid "" +" # generate the man pages into /usr/local/share/man/man1\n" +" abra_path=$(which abra) # pass abra absolute path to sudo below\n" +" sudo $abra_path man\n" +" sudo mandb\n" +"\n" +" # read the man pages\n" +" man abra\n" +" man abra-app-deploy" +msgstr "" + +#: pkg/app/app.go:685 +#, c-format +msgid "skipping version %s write as already exists in %s.env" +msgstr "" + +#: pkg/upstream/convert/volume.go:133 +msgid "volume options are incompatible with type npipe" +msgstr "" + +#: pkg/git/init.go:38 +#, c-format +msgid "git add: %s" +msgstr "" + +#: pkg/upstream/container/hijack.go:156 +msgid "[hijack] End of stdin" +msgstr "" + +#: cli/app/secret.go:106 cli/app/secret.go:394 cli/app/new.go:187 +#: cli/app/volume.go:47 cli/server/list.go:34 cli/recipe/version.go:103 +msgid "NAME" +msgstr "" + +#: cli/app/labels.go:23 +msgid "labels [flags]" +msgstr "" + +#: cli/recipe/version.go:62 cli/recipe/version.go:103 +msgid "TAG" +msgstr "" + +#: cli/recipe/release.go:367 +#, c-format +msgid "dry run: no git tag created (%s)" +msgstr "" + +#: cli/recipe/release.go:415 +msgid "no -p/--publish passed, not publishing" +msgstr "" + +#: pkg/git/init.go:29 +#, c-format +msgid "git open: %s" +msgstr "" + +#: cli/app/secret.go:510 +msgid "trim input" +msgstr "" + +#: cli/app/cmd.go:22 +msgid "" +"command [service | --local] [[args] [flags] | [flags] -- " +"[args]]" +msgstr "" + +#: cli/app/new.go:290 +msgid "Generate app secrets?" +msgstr "" + +#: cli/run.go:134 cli/updater/updater.go:501 +msgid "toggle non-interactive mode" +msgstr "" + +#: cli/recipe/new.go:34 +msgid "new [flags]" +msgstr "" + +#: cli/recipe/list.go:41 +msgid "backups" +msgstr "" + +#: pkg/config/abra.go:20 +msgid "no config file found" +msgstr "" + +#: pkg/git/init.go:65 +#, c-format +msgid "repo config: %s" +msgstr "" + +#: cli/app/cmd.go:67 +msgid "requires at least 3 arguments" +msgstr "" + +#: cli/app/cmd.go:171 +#, c-format +msgid "running command %s within the context of %s_%s" +msgstr "" + +#: cli/app/list.go:216 cli/internal/deploy.go:75 +msgid "DOMAIN" +msgstr "" + +#: cli/server/remove.go:43 +#, c-format +msgid "%s is now lost in time, like tears in rain" +msgstr "" + +#: cli/recipe/upgrade.go:354 cli/recipe/sync.go:239 cli/recipe/release.go:593 +msgid "y" +msgstr "" + +#: pkg/service/service.go:41 +#, c-format +msgid "no services deployed matching label '%s'?" +msgstr "" + +#: pkg/lint/recipe.go:103 +msgid "has published catalogue version" +msgstr "" + +#: cli/run.go:109 +#, c-format +msgid "unable to proceed, %s does not exist?" +msgstr "" + +#: cli/recipe/new.go:62 +#, c-format +msgid "removed .git repo in %s" +msgstr "" + +#: cli/recipe/reset.go:16 +msgid "WARNING: this will delete your changes. Be Careful." +msgstr "" + +#: cli/app/list.go:299 +msgid "show apps of a specific recipe" +msgstr "" + +#: cli/app/labels.go:74 +msgid "RECIPE LABELS" +msgstr "" + +#: pkg/upstream/convert/volume.go:110 +msgid "invalid tmpfs source, source must be empty" +msgstr "" + +#: pkg/ui/deploy.go:330 +msgid "succeeded" +msgstr "" + +#: pkg/recipe/compose.go:107 +#, c-format +msgid "%s has no version label? try running \"abra recipe sync %s\" first?" +msgstr "" + +#: cli/app/restart.go:132 +#, c-format +msgid "%s has been scaled to 0" +msgstr "" + +#: pkg/client/volumes.go:62 +#, c-format +msgid "%d retries failed" +msgstr "" + +#: cli/app/app.go:9 +msgid "app [cmd] [args] [flags]" +msgstr "" + +#: cli/server/add.go:141 +#, c-format +msgid "serverAdd: cleanUp: %s is not empty, aborting cleanup" +msgstr "" + +#: pkg/lint/recipe.go:55 +#, c-format +msgid "skipping %s based on skip condition" +msgstr "" + +#: cli/app/config.go:36 pkg/app/app.go:52 +#, c-format +msgid "cannot find app with name %s" +msgstr "" + +#: cli/upgrade.go:26 +msgid " abra upgrade --rc" +msgstr "" + +#: pkg/upstream/convert/service.go:652 +#, c-format +msgid "unknown restart policy: %s" +msgstr "" + +#: pkg/envfile/envfile.go:82 +#, c-format +msgid "read 0 env var exports from %s" +msgstr "" + +#: cli/app/upgrade.go:149 +msgid "unknown deployed version, unable to upgrade" +msgstr "" + +#: cli/recipe/list.go:19 +msgid "List recipes" +msgstr "" + +#: cli/internal/deploy.go:159 +#, c-format +msgid "not enough arguments: %s" +msgstr "" + +#: pkg/config/abra.go:81 +msgid "read abra dir from config file" +msgstr "" + +#: cli/app/run.go:110 cli/app/cmd.go:256 +msgid "user" +msgstr "" + +#: pkg/upstream/convert/volume.go:113 +msgid "bind options are incompatible with type tmpfs" +msgstr "" + +#: pkg/config/abra.go:77 +msgid "read abra dir from $ABRA_DIR" +msgstr "" + +#: cli/app/secret.go:467 cli/app/secret.go:491 cli/app/secret.go:531 +#: cli/app/new.go:363 +msgid "pass" +msgstr "" + +#: cli/app/restart.go:29 +msgid "" +" # restart a single app service\n" +" abra app restart 1312.net app\n" +"\n" +" # restart all app services\n" +" abra app restart 1312.net -a" +msgstr "" + +#: cli/server/add.go:84 +msgid "local server successfully added" +msgstr "" diff --git a/pkg/i18n/locales/es/LC_MESSAGES/default.po~ b/pkg/i18n/locales/es/LC_MESSAGES/default.po~ new file mode 100644 index 00000000..41a9e5a5 --- /dev/null +++ b/pkg/i18n/locales/es/LC_MESSAGES/default.po~ @@ -0,0 +1,4782 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: EMAIL\n" +"POT-Creation-Date: 2025-08-23 15:32+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: cli/app/secret.go:311 +msgid "no secret(s) specified?" +msgstr "" + +#: cli/app/volume.go:71 +#, c-format +msgid "no volumes created for %s" +msgstr "" + +#: cli/recipe/lint.go:74 cli/recipe/lint.go:136 pkg/lint/recipe.go:132 +#: pkg/lint/recipe.go:139 pkg/lint/recipe.go:146 pkg/lint/recipe.go:153 +#: pkg/lint/recipe.go:161 pkg/lint/recipe.go:168 pkg/lint/recipe.go:175 +msgid "error" +msgstr "" + +#: pkg/service/service.go:61 pkg/service/service.go:115 +msgid "which service are you looking for?" +msgstr "" + +#: pkg/recipe/recipe.go:361 +#, c-format +msgid "%s: marker string %s not found" +msgstr "" + +#: cli/server/add.go:84 +msgid "local server successfully added" +msgstr "" + +#: pkg/ssh/ssh.go:18 +#, c-format +msgid "could not resolve hostname for %s" +msgstr "" + +#: pkg/git/read.go:130 +#, c-format +msgid "no %s exists, skipping reading gitignore paths" +msgstr "" + +#: cli/app/secret.go:372 +msgid "list " +msgstr "" + +#: cli/app/rollback.go:42 +msgid "" +" # standard rollback\n" +" abra app rollback 1312.net\n" +"\n" +" # rollback to specific version\n" +" abra app rollback 1312.net 2.0.0+1.2.3" +msgstr "" + +#: cli/app/deploy.go:101 +#, c-format +msgid "get deploy version: %s" +msgstr "" + +#: cli/app/restore.go:74 +#, c-format +msgid "including CONTAINER=%s in backupbot exec invocation" +msgstr "" + +#: cli/app/restore.go:107 +msgid "services" +msgstr "" + +#: cli/app/check.go:18 +msgid "chk" +msgstr "" + +#: cli/complete.go:12 +msgid "Generate autocompletion script" +msgstr "" + +#: cli/recipe/new.go:126 +msgid "Git email name to do commits with" +msgstr "" + +#: cli/app/backup.go:214 +msgid "b" +msgstr "" + +#: cli/recipe/diff.go:13 +msgid "diff [flags]" +msgstr "" + +#: pkg/service/service.go:53 pkg/service/service.go:107 +#, c-format +msgid "expected 1 service but found %v: %s" +msgstr "" + +#: pkg/upstream/convert/service.go:834 +#, c-format +msgid "" +"invalid credential spec: spec specifies config %v, but no such config can be " +"found" +msgstr "" + +#: pkg/git/init.go:29 +#, c-format +msgid "git open: %s" +msgstr "" + +#: cli/app/env.go:17 +msgid "Show app .env values" +msgstr "" + +#: cli/app/upgrade.go:450 cli/app/rollback.go:339 cli/app/deploy.go:350 +msgid "no-converge-checks" +msgstr "" + +#: cli/app/list.go:216 cli/internal/deploy.go:75 +msgid "DOMAIN" +msgstr "" + +#: pkg/client/volumes.go:59 +#, c-format +msgid "%s: waiting %d seconds before next retry" +msgstr "" + +#: cli/app/new.go:266 +msgid "Specify app domain" +msgstr "" + +#: cli/app/deploy.go:311 +#, c-format +msgid "version: taking deployed version: %s" +msgstr "" + +#: cli/recipe/new.go:36 +msgid "Create a new recipe" +msgstr "" + +#: pkg/upstream/commandconn/connection.go:38 +msgid "ssh host connection is not valid" +msgstr "" + +#: cli/app/upgrade.go:240 cli/app/rollback.go:202 cli/app/deploy.go:203 +#, c-format +msgid "set waiting timeout to %d second(s)" +msgstr "" + +#: cli/app/deploy.go:290 +#, c-format +msgid "version: taking chaos version: %s" +msgstr "" + +#: pkg/upstream/convert/volume.go:113 +msgid "bind options are incompatible with type tmpfs" +msgstr "" + +#: cli/server/prune.go:101 +msgid "remove volumes" +msgstr "" + +#: cli/recipe/lint.go:32 +msgid "ref" +msgstr "" + +#: cli/app/secret.go:476 cli/app/secret.go:516 cli/app/secret.go:540 +#: cli/app/secret.go:548 cli/app/restore.go:132 cli/app/ps.go:207 +#: cli/app/cmd.go:273 cli/app/new.go:380 cli/app/check.go:88 +#: cli/app/restart.go:155 cli/app/deploy.go:327 cli/app/cp.go:379 +#: cli/app/backup.go:288 cli/app/backup.go:304 cli/app/labels.go:136 +#: cli/catalogue/catalogue.go:272 cli/recipe/lint.go:129 +#: cli/updater/updater.go:538 +msgid "C" +msgstr "" + +#: cli/app/restore.go:110 +msgid "restore specific services" +msgstr "" + +#: cli/app/new.go:24 +msgid "" +"Creates a new app from a default recipe.\n" +"\n" +"This new app configuration is stored in your $ABRA_DIR directory under the\n" +"appropriate server.\n" +"\n" +"This command does not deploy your app for you. You will need to run \"abra " +"app\n" +"deploy \" to do so.\n" +"\n" +"You can see what recipes are available (i.e. values for the [recipe] " +"argument)\n" +"by running \"abra recipe ls\".\n" +"\n" +"Recipe commit hashes are supported values for \"[version]\".\n" +"\n" +"Passing the \"--secrets/-S\" flag will automatically generate secrets for " +"your\n" +"app and store them encrypted at rest on the chosen target server. These\n" +"generated secrets are only visible at generation time, so please take care " +"to\n" +"store them somewhere safe.\n" +"\n" +"You can use the \"--pass/-P\" to store these generated passwords locally in " +"a\n" +"pass store (see passwordstore.org for more). The pass command must be " +"available\n" +"on your $PATH." +msgstr "" + +#: cli/app/list.go:223 +msgid "AUTOUPDATE" +msgstr "" + +#: cli/recipe/sync.go:22 +msgid "Sync recipe version label" +msgstr "" + +#: cli/updater/updater.go:490 +msgid "debug" +msgstr "" + +#: cli/app/logs.go:104 +msgid "tail logs since YYYY-MM-DDTHH:MM:SSZ" +msgstr "" + +#: cli/app/backup.go:242 +msgid "show all paths" +msgstr "" + +#: cli/app/undeploy.go:104 +msgid "undeploy succeeded 🟢" +msgstr "" + +#: cli/app/new.go:211 +#, c-format +msgid "secrets are %s shown again, please save them %s" +msgstr "" + +#: cli/run.go:142 +msgid "prefer offline & filesystem access" +msgstr "" + +#: pkg/recipe/compose.go:159 +#, c-format +msgid "parsed %s from %s" +msgstr "" + +#: cli/app/cp.go:31 +msgid "Copy files to/from a deployed app service" +msgstr "" + +#: cli/app/env.go:16 cli/recipe/new.go:124 cli/recipe/lint.go:137 +msgid "e" +msgstr "" + +#: cli/app/secret.go:526 +msgid "remove all secrets" +msgstr "" + +#: cli/server/prune.go:18 +msgid "" +"Prunes unused containers, networks, and dangling images.\n" +"\n" +"Use \"--volumes/-v\" to remove volumes that are not associated with a " +"deployed\n" +"app. This can result in unwanted data loss if not used carefully." +msgstr "" + +#: cli/recipe/upgrade.go:239 +#, c-format +msgid "" +"not upgrading from %s to %s for %s, because the upgrade type is more serious " +"than what user wants" +msgstr "" + +#: pkg/lint/recipe.go:69 +msgid "ensure 'version: \"3.8\"' in compose configs" +msgstr "" + +#: pkg/recipe/compose.go:153 +#, c-format +msgid "unable to parse %s, skipping" +msgstr "" + +#: cli/app/cmd.go:108 cli/internal/deploy.go:151 +#, c-format +msgid "%s does not exist for %s?" +msgstr "" + +#: cli/app/upgrade.go:149 +msgid "unknown deployed version, unable to upgrade" +msgstr "" + +#: cli/app/upgrade.go:323 +#, c-format +msgid "parsing deployment version failed: %s" +msgstr "" + +#: cli/app/new.go:199 +#, c-format +msgid "%s created (version: %s)" +msgstr "" + +#: cli/recipe/fetch.go:21 +msgid "" +"Using \"--force/-f\" Git syncs an existing recipe. It does not erase " +"unstaged changes." +msgstr "" + +#: cli/recipe/sync.go:20 +msgid "sync [version] [flags]" +msgstr "" + +#: pkg/lint/recipe.go:124 +msgid "long secret names" +msgstr "" + +#: cli/catalogue/catalogue.go:255 cli/recipe/sync.go:222 +#: cli/recipe/release.go:576 +msgid "dry-run" +msgstr "" + +#: pkg/upstream/convert/service.go:122 +#, c-format +msgid "duplicate config target for %s not allowed" +msgstr "" + +#: pkg/dns/dns.go:14 +#, c-format +msgid "%s: unable to resolve IPv4 address: %s" +msgstr "" + +#: pkg/git/clone.go:49 +#, c-format +msgid "git clone: %s" +msgstr "" + +#: cli/app/cp.go:245 +#, c-format +msgid "copy: %s" +msgstr "" + +#: cli/app/remove.go:139 +#, c-format +msgid "%d volume(s) removed successfully" +msgstr "" + +#: cli/app/volume.go:161 +msgid "which volumes do you want to remove?" +msgstr "" + +#: cli/server/server.go:10 +msgid "server [cmd] [args] [flags]" +msgstr "" + +#: cli/recipe/version.go:62 cli/recipe/version.go:103 +msgid "TAG" +msgstr "" + +#: pkg/lint/recipe.go:177 +msgid "replace lightweight tag with annotated tag" +msgstr "" + +#: pkg/ui/deploy.go:121 +#, c-format +msgid "^%s" +msgstr "" + +#: pkg/recipe/compose.go:72 +#, c-format +msgid "%s is missing a compose.yml or compose.*.yml file?" +msgstr "" + +#: cli/app/cp.go:85 +msgid "one of / arguments must take $SERVICE:$PATH form" +msgstr "" + +#: cli/app/cp.go:272 +msgid "can't copy dir to file" +msgstr "" + +#: cli/app/backup.go:178 +msgid "snapshots [flags]" +msgstr "" + +#: cli/app/volume.go:184 +msgid "no volumes removed" +msgstr "" + +#: cli/recipe/new.go:50 +#, c-format +msgid "%s recipe directory already exists?" +msgstr "" + +#: cli/app/secret.go:462 cli/app/secret.go:558 cli/app/ps.go:201 +#: cli/app/list.go:314 cli/server/list.go:102 cli/recipe/upgrade.go:372 +#: cli/recipe/version.go:134 cli/recipe/list.go:100 +msgid "print machine-readable output" +msgstr "" + +#: cli/server/prune.go:75 +#, c-format +msgid "volumes pruned: %d; space reclaimed: %s" +msgstr "" + +#: cli/internal/validate.go:106 +#, c-format +msgid "validated %s as app argument" +msgstr "" + +#: pkg/upstream/convert/service.go:375 +#, c-format +msgid "undefined network %q" +msgstr "" + +#: pkg/envfile/envfile.go:82 +#, c-format +msgid "read 0 env var exports from %s" +msgstr "" + +#: pkg/web/web.go:45 +#, c-format +msgid "bad status: %s" +msgstr "" + +#: cli/app/run.go:105 +msgid "do not request a TTY" +msgstr "" + +#: cli/app/upgrade.go:30 +msgid "up" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:263 +#, c-format +msgid "unimplemented call: SetWriteDeadline(%v)" +msgstr "" + +#: cli/app/cp.go:29 +msgid "cp [flags]" +msgstr "" + +#: cli/app/backup.go:107 +#, c-format +msgid "including INCLUDE_PATH=%s in backupbot exec invocation" +msgstr "" + +#: cli/server/add.go:114 +#, c-format +msgid "unable to resolve IPv4 for %s" +msgstr "" + +#: cli/recipe/upgrade.go:158 +#, c-format +msgid "parsed %s for %s" +msgstr "" + +#: cli/recipe/upgrade.go:222 +#, c-format +msgid "" +"service %s is at version %s, but pinned to %s, please correct your " +"compose.yml file manually!" +msgstr "" + +#: cli/internal/validate.go:174 +#, c-format +msgid "validated %s as server argument" +msgstr "" + +#: cli/internal/deploy.go:109 +msgid "deployment cancelled" +msgstr "" + +#: pkg/recipe/compose.go:29 +#, c-format +msgid "no COMPOSE_FILE detected, loading default: %s" +msgstr "" + +#: cli/app/secret.go:75 +#, c-format +msgid "%s doesn't exist in the env config?" +msgstr "" + +#: cli/app/undeploy.go:128 cli/server/prune.go:45 +#, c-format +msgid "containers pruned: %d; space reclaimed: %s" +msgstr "" + +#: cli/app/services.go:21 +msgid "services [flags]" +msgstr "" + +#: cli/app/backup.go:231 cli/app/backup.go:255 +msgid "snapshot" +msgstr "" + +#: pkg/recipe/git.go:151 +#, c-format +msgid "read %s as tags for recipe %s" +msgstr "" + +#: pkg/recipe/git.go:256 +#, c-format +msgid "unable to check out default branch in %s: %s" +msgstr "" + +#: pkg/recipe/compose.go:59 +#, c-format +msgid "retrieved %s configs for %s" +msgstr "" + +#: cli/app/rollback.go:28 +msgid "" +"This command rolls an app back to a previous version.\n" +"\n" +"Unlike \"abra app deploy\", chaos operations are not supported here. Only " +"recipe\n" +"versions are supported values for \"[version]\".\n" +"\n" +"It is possible to \"--force/-f\" an downgrade if you want to re-deploy a " +"specific\n" +"version.\n" +"\n" +"Only the deployed version is consulted when trying to determine what " +"downgrades\n" +"are available. The live deployment version is the \"source of truth\" in " +"this\n" +"case. The stored .env version is not consulted.\n" +"\n" +"A downgrade can be destructive, please ensure you have a copy of your app " +"data\n" +"beforehand. See \"abra app backup\" for more." +msgstr "" + +#: cli/app/backup.go:49 +#, c-format +msgid "including SHOW_ALL=%v in backupbot exec invocation" +msgstr "" + +#: cli/internal/validate.go:84 +#, c-format +msgid "unable to validate recipe: %s" +msgstr "" + +#: pkg/client/client.go:88 +#, c-format +msgid "created client for %s" +msgstr "" + +#: pkg/client/registry.go:20 +#, c-format +msgid "failed to parse image %s, saw: %s" +msgstr "" + +#: pkg/upstream/container/exec.go:113 +#, c-format +msgid "Error hijack: %s" +msgstr "" + +#: cli/run.go:24 +msgid "abra [cmd] [args] [flags]" +msgstr "" + +#: cli/app/secret.go:24 +msgid "generate [[secret] [version] | --all] [flags]" +msgstr "" + +#: pkg/git/init.go:50 +#, c-format +msgid "init committed all files for new git repo in %s" +msgstr "" + +#: cli/app/secret.go:499 +msgid "file" +msgstr "" + +#: cli/app/new.go:135 +#, c-format +msgid "%s sanitised as %s for new app" +msgstr "" + +#: cli/app/backup.go:136 +msgid "Create a new snapshot" +msgstr "" + +#: pkg/lint/recipe.go:147 +msgid "deploy labels stanza present" +msgstr "" + +#: pkg/upstream/container/hijack.go:172 +#, c-format +msgid "couldn't send EOF: %s" +msgstr "" + +#: cli/app/list.go:46 +msgid "" +"Generate a report of all managed apps.\n" +"\n" +"Use \"--status/-S\" flag to query all servers for the live deployment status." +msgstr "" + +#: cli/recipe/fetch.go:48 +msgid "cannot use [recipe] and --all/-a together" +msgstr "" + +#: cli/recipe/release.go:492 +#, c-format +msgid "current: %s, new: %s, correct?" +msgstr "" + +#: pkg/dns/dns.go:52 +#, c-format +msgid "app domain %s (%s) does not appear to resolve to app server %s (%s)?" +msgstr "" + +#: pkg/recipe/git.go:378 +#, c-format +msgid "git: opening repository in %s" +msgstr "" + +#: cli/app/secret.go:230 +#, c-format +msgid "%s successfully stored on server" +msgstr "" + +#: cli/app/secret.go:394 +msgid "CREATED ON SERVER" +msgstr "" + +#: cli/updater/updater.go:231 +#, c-format +msgid "%s (%s) can be upgraded from version %s to %s" +msgstr "" + +#: pkg/lint/recipe.go:83 +msgid "use a tag for all images" +msgstr "" + +#: pkg/lint/recipe.go:90 +msgid "tag all images with stable tags" +msgstr "" + +#: pkg/lint/recipe.go:141 +msgid "name a servce 'app'" +msgstr "" + +#: pkg/upstream/container/exec.go:108 +msgid "Error monitoring TTY size:" +msgstr "" + +#: pkg/ui/deploy.go:85 +#, c-format +msgid "name: %s, " +msgstr "" + +#: cli/app/config.go:36 +#, c-format +msgid "cannot find app with name %s" +msgstr "" + +#: cli/catalogue/catalogue.go:258 cli/recipe/sync.go:225 +#: cli/recipe/release.go:579 +msgid "report changes that would be made" +msgstr "" + +#: pkg/git/branch.go:68 +#, c-format +msgid "failed to select default branch in %s" +msgstr "" + +#: cli/app/deploy.go:96 +#, c-format +msgid "%s is already deployed" +msgstr "" + +#: cli/recipe/upgrade.go:119 +#, c-format +msgid "did not find versions file for %s" +msgstr "" + +#: cli/updater/updater.go:251 +#, c-format +msgid "failed to determine deployed version of %s" +msgstr "" + +#: pkg/git/init.go:21 +#, c-format +msgid "git branch rename: %s" +msgstr "" + +#: cli/app/undeploy.go:155 +msgid "prune" +msgstr "" + +#: pkg/secret/pass.go:15 pkg/secret/pass.go:37 +msgid "pass command not found on $PATH, is it installed?" +msgstr "" + +#: cli/app/upgrade.go:362 +#, c-format +msgid "parsing deployed version failed: %s" +msgstr "" + +#: cli/recipe/release.go:556 +#, c-format +msgid "use %s as the new version?" +msgstr "" + +#: cli/updater/updater.go:273 +#, fuzzy, c-format +msgid "no published releases for %s in the recipe catalogue?" +msgstr "TRANSLATE THIS FUCKING SHIT ALREADY" + +#: cli/app/cmd.go:51 +msgid "accepts at most 2 args with --local/-l" +msgstr "" + +#: cli/app/remove.go:92 +#, c-format +msgid "%d config(s) removed successfully" +msgstr "" + +#: cli/server/add.go:137 +#, c-format +msgid "serverAdd: cleanUp: unable to list files in %s: %s" +msgstr "" + +#: cli/updater/updater.go:376 +#, c-format +msgid "don't update %s due to missing recipe name" +msgstr "" + +#: cli/app/cmd.go:128 cli/app/cmd.go:174 +#, c-format +msgid "parsed following command arguments: %s" +msgstr "" + +#: cli/server/add.go:100 +#, c-format +msgid "unable to create local context: %s" +msgstr "" + +#: cli/server/server.go:12 +msgid "Manage servers" +msgstr "" + +#: cli/internal/backup.go:62 +#, c-format +msgid "running backup %s on %s with exec config %v" +msgstr "" + +#: pkg/recipe/recipe.go:237 +#, c-format +msgid "%s: attempt recipe metadata parse" +msgstr "" + +#: pkg/lint/recipe.go:21 pkg/lint/recipe.go:67 pkg/lint/recipe.go:74 +#: pkg/lint/recipe.go:81 pkg/lint/recipe.go:88 pkg/lint/recipe.go:95 +#: pkg/lint/recipe.go:102 pkg/lint/recipe.go:109 pkg/lint/recipe.go:116 +#: pkg/lint/recipe.go:123 +msgid "warn" +msgstr "" + +#: cli/recipe/upgrade.go:218 +#, c-format +msgid "service %s, image %s pinned to %s, no compatible upgrade found" +msgstr "" + +#: cli/recipe/list.go:44 +msgid "SSO" +msgstr "" + +#: pkg/lint/recipe.go:133 +msgid ".env.sample provided" +msgstr "" + +#: pkg/secret/secret.go:126 +#, c-format +msgid "missing version for secret? (%s)" +msgstr "" + +#: cli/run.go:31 +msgid "man" +msgstr "" + +#: cli/recipe/new.go:118 +msgid "Git (user) name to do commits with" +msgstr "" + +#: cli/app/labels.go:102 +msgid "LABELS OVERVIEW" +msgstr "" + +#: cli/app/restart.go:22 +msgid "re" +msgstr "" + +#: cli/app/secret.go:484 cli/app/secret.go:524 cli/app/restart.go:162 +#: cli/app/app.go:10 cli/app/backup.go:240 cli/server/prune.go:91 +#: cli/server/add.go:22 cli/recipe/upgrade.go:378 cli/recipe/fetch.go:115 +#: cli/updater/updater.go:554 +msgid "a" +msgstr "" + +#: cli/recipe/new.go:123 +msgid "git-email" +msgstr "" + +#: pkg/formatter/formatter.go:80 +msgid "detected ABRA_CI=1" +msgstr "" + +#: cli/app/ps.go:181 cli/recipe/version.go:62 +msgid "IMAGE" +msgstr "" + +#: cli/recipe/fetch.go:70 pkg/lint/recipe.go:491 pkg/recipe/git.go:236 +#: pkg/git/read.go:26 +#, c-format +msgid "unable to open %s: %s" +msgstr "" + +#: cli/recipe/list.go:38 +msgid "category" +msgstr "" + +#: cli/app/new.go:372 cli/app/logs.go:102 cli/app/backup.go:272 +#: cli/app/list.go:289 +msgid "S" +msgstr "" + +#: cli/internal/validate.go:59 +msgid "no recipe name provided" +msgstr "" + +#: pkg/git/clone.go:68 +msgid "git clone: main branch failed, attempting master branch" +msgstr "" + +#: cli/app/remove.go:73 cli/app/volume.go:120 +#, c-format +msgid "%s is still deployed. Run \"abra app undeploy %s\"" +msgstr "" + +#: cli/recipe/release.go:562 +#, c-format +msgid "please fix your synced label for %s and re-run this command" +msgstr "" + +#: pkg/lint/recipe.go:154 +msgid "traefik routing enabled" +msgstr "" + +#: pkg/recipe/recipe.go:325 +#, c-format +msgid "%s: image meta has incorrect format: %s" +msgstr "" + +#: pkg/git/init.go:65 +#, c-format +msgid "repo config: %s" +msgstr "" + +#: cli/app/upgrade.go:29 +msgid "upgrade [version] [flags]" +msgstr "" + +#: cli/internal/backup.go:26 +msgid "no backupbot discovered, is it deployed?" +msgstr "" + +#: pkg/upstream/convert/service.go:72 +#, c-format +msgid "secret not found: %s" +msgstr "" + +#: cli/app/secret.go:366 +msgid "no secrets to remove?" +msgstr "" + +#: cli/app/restore.go:19 +msgid "" +"Snapshots are restored while apps are deployed.\n" +"\n" +"Some restore scenarios may require service / app restarts." +msgstr "" + +#: cli/app/volume.go:76 +msgid "remove [volume] [flags]" +msgstr "" + +#: cli/recipe/new.go:37 +msgid "A community managed recipe template is used." +msgstr "" + +#: pkg/git/commit.go:44 +msgid "dry run: no changes commited" +msgstr "" + +#: cli/app/volume.go:47 +msgid "ON SERVER" +msgstr "" + +#: cli/internal/validate.go:88 +#, c-format +msgid "validated %s as recipe argument" +msgstr "" + +#: pkg/recipe/recipe.go:462 +#, c-format +msgid "recipe metadata retrieved for %s" +msgstr "" + +#: pkg/ui/deploy.go:82 +#, c-format +msgid "{decoder: %v, " +msgstr "" + +#: cli/app/new.go:324 cli/internal/validate.go:167 +msgid "no server provided" +msgstr "" + +#: cli/recipe/release.go:514 +#, c-format +msgid "failed to tag release: %s" +msgstr "" + +#: cli/app/cmd.go:131 cli/app/cmd.go:176 +msgid "did not detect any command arguments" +msgstr "" + +#: cli/app/app.go:9 +msgid "app [cmd] [args] [flags]" +msgstr "" + +#: cli/app/list.go:291 +msgid "show app deployment status" +msgstr "" + +#: cli/recipe/upgrade.go:353 cli/recipe/sync.go:238 cli/recipe/release.go:592 +#: cli/internal/recipe.go:46 cli/internal/recipe.go:66 +#: cli/internal/recipe.go:80 +msgid "minor" +msgstr "" + +#: cli/app/volume.go:162 +msgid "" +"'x' indicates selected, enter / return to confirm, ctrl-c to exit, vim mode " +"is enabled" +msgstr "" + +#: cli/updater/updater.go:239 +#, c-format +msgid "retrieve deployed version whether %s is already deployed" +msgstr "" + +#: pkg/lint/recipe.go:176 +msgid "only annotated tags used for recipe version" +msgstr "" + +#: cli/catalogue/catalogue.go:247 cli/recipe/release.go:608 +msgid "publish" +msgstr "" + +#: pkg/git/init.go:60 +#, c-format +msgid "set reference: %s" +msgstr "" + +#: pkg/git/init.go:73 +msgid "set 'main' as the default branch" +msgstr "" + +#: cli/app/ps.go:165 +#, c-format +msgid "unable to convert to JSON: %s" +msgstr "" + +#: cli/recipe/release.go:29 +msgid "" +"Create a new version of a recipe.\n" +"\n" +"These versions are then published on the Co-op Cloud recipe catalogue. " +"These\n" +"versions take the following form:\n" +"\n" +" a.b.c+x.y.z\n" +"\n" +"Where the \"a.b.c\" part is a semantic version determined by the maintainer. " +"The\n" +"\"x.y.z\" part is the image tag of the recipe \"app\" service (the main " +"container\n" +"which contains the software to be used, by naming convention).\n" +"\n" +"We maintain a semantic versioning scheme (\"a.b.c\") alongside the recipe\n" +"versioning scheme (\"x.y.z\") in order to maximise the chances that the " +"nature of\n" +"recipe updates are properly communicated. I.e. developers of an app might\n" +"publish a minor version but that might lead to changes in the recipe which " +"are\n" +"major and therefore require intervention while doing the upgrade work.\n" +"\n" +"Publish your new release to git.coopcloud.tech with \"--publish/-p\". This\n" +"requires that you have permission to git push to these repositories and " +"have\n" +"your SSH keys configured on your account." +msgstr "" + +#: cli/updater/updater.go:197 +#, c-format +msgid "can't separate key from value: %s (this variable is probably unset)" +msgstr "" + +#: pkg/lint/recipe.go:117 +msgid "git.coopcloud.tech repo exists" +msgstr "" + +#: pkg/recipe/git.go:187 +#, c-format +msgid "unable to check git clean status in %s: %s" +msgstr "" + +#: pkg/container/container.go:44 +#, c-format +msgid "expected 1 container but found %v: %s" +msgstr "" + +#: cli/app/upgrade.go:266 cli/app/deploy.go:229 +#, c-format +msgid "run the following post-deploy commands: %s" +msgstr "" + +#: cli/catalogue/catalogue.go:27 +msgid "" +"Generate a new copy of the recipe catalogue.\n" +"\n" +"N.B. this command **will** wipe local unstaged changes from your local " +"recipes\n" +"if present. \"--chaos/-C\" on this command refers to the catalogue " +"repository\n" +"(\"$ABRA_DIR/catalogue\") and not the recipes. Please take care not to lose " +"your\n" +"changes.\n" +"\n" +"It is possible to generate new metadata for a single recipe by passing\n" +"[recipe]. The existing local catalogue will be updated, not overwritten.\n" +"\n" +"It is quite easy to get rate limited by Docker Hub when running this " +"command.\n" +"If you have a Hub account you can \"docker login\" and Abra will " +"automatically\n" +"use those details.\n" +"\n" +"Push your new release to git.coopcloud.tech with \"--publish/-p\". This " +"requires\n" +"that you have permission to git push to these repositories and have your " +"SSH\n" +"keys configured on your account." +msgstr "" + +#: pkg/upstream/convert/volume.go:56 +#, c-format +msgid "undefined volume %q" +msgstr "" + +#: cli/app/deploy.go:276 +#, c-format +msgid "secret not generated: %s" +msgstr "" + +#: pkg/upstream/convert/volume.go:116 +msgid "volume options are incompatible with type tmpfs" +msgstr "" + +#: cli/recipe/list.go:42 +msgid "email" +msgstr "" + +#: cli/internal/validate.go:50 +msgid "Select recipe" +msgstr "" + +#: pkg/recipe/git.go:178 +#, c-format +msgid "successfully checked %s out to %s in %s" +msgstr "" + +#: pkg/recipe/compose.go:171 pkg/recipe/compose.go:237 +#, c-format +msgid "updating %s to %s in %s" +msgstr "" + +#: cli/app/undeploy.go:24 +msgid "Undeploy an app" +msgstr "" + +#: cli/app/restart.go:24 +msgid "" +"This command restarts services within a deployed app.\n" +"\n" +"Run \"abra app ps \" to see a list of service names.\n" +"\n" +"Pass \"--all-services/-a\" to restart all services." +msgstr "" + +#: cli/app/logs.go:93 +msgid "stderr" +msgstr "" + +#: pkg/catalogue/catalogue.go:59 pkg/recipe/git.go:245 +#, c-format +msgid "cannot ensure %s is up-to-date, no git remotes configured" +msgstr "" + +#: pkg/recipe/recipe.go:175 +#, c-format +msgid "failed to check git status of %s: %s" +msgstr "" + +#: cli/recipe/list.go:18 +msgid "list" +msgstr "" + +#: cli/internal/command.go:80 +#, c-format +msgid "running command: %s" +msgstr "" + +#: pkg/logs/logs.go:86 +#, c-format +msgid "tailLogs: unable to copy buffer: %s" +msgstr "" + +#: cli/app/upgrade.go:442 cli/app/rollback.go:331 cli/app/deploy.go:342 +msgid "no-domain-checks" +msgstr "" + +#: cli/app/list.go:177 +msgid "latest" +msgstr "" + +#: cli/upgrade.go:18 +msgid "Upgrade abra" +msgstr "" + +#: cli/internal/validate.go:64 +#, c-format +msgid "no recipe '%s' exists?" +msgstr "" + +#: cli/app/upgrade.go:392 cli/app/rollback.go:275 +#, c-format +msgid "'%s' is not a known version for %s" +msgstr "" + +#: cli/run.go:134 cli/updater/updater.go:501 +msgid "toggle non-interactive mode" +msgstr "" + +#: pkg/client/client.go:44 +#, c-format +msgid "unknown server, run \"abra server add %s\"?" +msgstr "" + +#: pkg/upstream/convert/volume.go:47 +msgid "bind options are incompatible with type volume" +msgstr "" + +#: pkg/recipe/recipe.go:204 +#, c-format +msgid "ssh url: %s, " +msgstr "" + +#: pkg/git/add.go:22 +#, c-format +msgid "dry run: adding %s" +msgstr "" + +#: cli/app/secret.go:246 +#, c-format +msgid "deleted %s successfully from server" +msgstr "" + +#: cli/app/restore.go:68 +#, c-format +msgid "including VOLUMES=%s in backupbot exec invocation" +msgstr "" + +#: cli/server/add.go:76 cli/server/add.go:103 +#, c-format +msgid "attempting to create client for %s" +msgstr "" + +#: cli/recipe/new.go:86 +#, c-format +msgid "new recipe '%s' created: %s" +msgstr "" + +#: pkg/upstream/convert/service.go:414 +#, c-format +msgid "undefined secret %q" +msgstr "" + +#: pkg/git/init.go:17 +#, c-format +msgid "git init: %s" +msgstr "" + +#: cli/internal/validate.go:82 +#, c-format +msgid "ensure %s recipe compose.* files include \"version: '3.8'\"" +msgstr "" + +#: pkg/upstream/convert/volume.go:90 +msgid "invalid bind source, source cannot be empty" +msgstr "" + +#: cli/app/upgrade.go:32 +msgid "" +"Upgrade an app.\n" +"\n" +"Unlike \"abra app deploy\", chaos operations are not supported here. Only " +"recipe\n" +"versions are supported values for \"[version]\".\n" +"\n" +"It is possible to \"--force/-f\" an upgrade if you want to re-deploy a " +"specific\n" +"version.\n" +"\n" +"Only the deployed version is consulted when trying to determine what " +"upgrades\n" +"are available. The live deployment version is the \"source of truth\" in " +"this\n" +"case. The stored .env version is not consulted.\n" +"\n" +"An upgrade can be destructive, please ensure you have a copy of your app " +"data\n" +"beforehand. See \"abra app backup\" for more." +msgstr "" + +#: cli/app/services.go:67 +msgid "SERVICE (SHORT)" +msgstr "" + +#: cli/app/logs.go:20 +msgid "Tail app logs" +msgstr "" + +#: cli/app/list.go:296 cli/app/list.go:303 cli/run.go:32 +msgid "recipe" +msgstr "" + +#: cli/recipe/upgrade.go:43 +msgid "Upgrade recipe image tags" +msgstr "" + +#: pkg/recipe/compose.go:191 +#, c-format +msgid "considering %s config(s) for label update" +msgstr "" + +#: cli/app/list.go:153 +#, c-format +msgid "unable to retrieve tags for %s: %s" +msgstr "" + +#: cli/server/remove.go:20 +msgid "" +"Remove a managed server.\n" +"\n" +"Abra will remove the internal bookkeeping ($ABRA_DIR/servers/...) and\n" +"underlying client connection context. This server will then be lost in " +"time,\n" +"like tears in rain." +msgstr "" + +#: pkg/upstream/convert/service.go:604 +msgid "test and disable can't be set at the same time" +msgstr "" + +#: cli/app/remove.go:59 +msgid "aborting as requested" +msgstr "" + +#: cli/app/labels.go:53 +msgid "DEPLOYED LABELS" +msgstr "" + +#: pkg/lint/recipe.go:169 +msgid "config version are vendored" +msgstr "" + +#: cli/app/cmd.go:101 +msgid "cannot use --local & --user together" +msgstr "" + +#: cli/app/cp.go:145 cli/app/cp.go:184 +#, c-format +msgid "create remote directory: %s" +msgstr "" + +#: cli/app/env.go:41 +msgid "ENV OVERVIEW" +msgstr "" + +#: cli/app/config.go:42 +msgid "which editor do you wish to use?" +msgstr "" + +#: cli/app/labels.go:23 +msgid "labels [flags]" +msgstr "" + +#: cli/app/labels.go:26 +msgid "Both local recipe and live deployment labels are shown." +msgstr "" + +#: pkg/service/service.go:57 pkg/service/service.go:111 +msgid "ambiguous service list received, prompting for input" +msgstr "" + +#: pkg/git/clone.go:100 +#, c-format +msgid "unable to clean up git clone of %s: %s" +msgstr "" + +#: pkg/git/remote.go:15 +#, c-format +msgid "dry run: remote %s (%s) not created" +msgstr "" + +#: cli/app/restore.go:115 cli/app/backup.go:279 cli/server/prune.go:98 +msgid "volumes" +msgstr "" + +#: cli/recipe/upgrade.go:139 +#, c-format +msgid "retrieved %s from remote registry for %s" +msgstr "" + +#: pkg/lint/recipe.go:89 +msgid "no unstable tags" +msgstr "" + +#: cli/app/secret.go:437 +#, c-format +msgid "no secrets stored for %s" +msgstr "" + +#: pkg/config/abra.go:20 +msgid "no config file found" +msgstr "" + +#: pkg/config/abra.go:26 +#, c-format +msgid "error reading config file: %s" +msgstr "" + +#: cli/app/upgrade.go:461 +msgid "only show release notes" +msgstr "" + +#: cli/app/deploy.go:296 +#, c-format +msgid "version: taking version from cli arg: %s" +msgstr "" + +#: cli/app/volume.go:153 +#, c-format +msgid "volume %s removed successfully" +msgstr "" + +#: cli/recipe/release.go:487 +#, c-format +msgid "latest git tag (%s) and synced label (%s) are the same?" +msgstr "" + +#: pkg/config/env.go:37 +#, c-format +msgid "retrieved %v servers: %s" +msgstr "" + +#: cli/server/add.go:57 +msgid "missing argument or --local/-l flag" +msgstr "" + +#: pkg/recipe/recipe.go:203 +#, c-format +msgid "git url: %s, " +msgstr "" + +#: cli/internal/deploy.go:81 +msgid "ENV VERSION" +msgstr "" + +#: cli/app/cmd.go:249 cli/app/logs.go:19 cli/server/add.go:200 +#: cli/recipe/lint.go:16 +msgid "l" +msgstr "" + +#: cli/app/restart.go:64 +msgid "missing [service]" +msgstr "" + +#: cli/updater/updater.go:155 +#, c-format +msgid "no %s label found for %s" +msgstr "" + +#: pkg/recipe/recipe.go:199 +#, c-format +msgid "{name: %s, " +msgstr "" + +#: cli/recipe/release.go:367 +#, c-format +msgid "dry run: no git tag created (%s)" +msgstr "" + +#: pkg/service/service.go:95 +#, c-format +msgid "no services matching the %v filter found?" +msgstr "" + +#: pkg/ssh/ssh.go:20 +#, c-format +msgid "connection timed out for %s" +msgstr "" + +#: pkg/git/init.go:47 +#, c-format +msgid "git commit: %s" +msgstr "" + +#: cli/recipe/upgrade.go:247 +#, c-format +msgid "unable to determine versioning semantics of %s, listing all tags" +msgstr "" + +#: cli/recipe/lint.go:15 +msgid "Lint a recipe" +msgstr "" + +#: cli/recipe/release.go:317 +msgid "Release Note (leave empty for no release note)" +msgstr "" + +#: cli/updater/updater.go:556 +msgid "update all deployed apps" +msgstr "" + +#: cli/app/secret.go:106 cli/app/secret.go:394 cli/app/new.go:187 +#: cli/app/volume.go:47 cli/server/list.go:34 cli/recipe/version.go:103 +msgid "NAME" +msgstr "" + +#: cli/app/secret.go:362 +#, c-format +msgid "%s doesn't exist on server?" +msgstr "" + +#: cli/app/backup.go:266 +msgid "volumes path" +msgstr "" + +#: cli/app/labels.go:24 +msgid "lb" +msgstr "" + +#: cli/recipe/release.go:387 +#, c-format +msgid "created tag %s at %s" +msgstr "" + +#: cli/app/deploy.go:30 +msgid "Deploy an app" +msgstr "" + +#: cli/app/config.go:17 +msgid "cfg" +msgstr "" + +#: cli/server/list.go:20 +msgid "List managed servers" +msgstr "" + +#: cli/app/cp.go:253 +#, c-format +msgid "untar: %s" +msgstr "" + +#: pkg/recipe/recipe.go:201 +#, c-format +msgid "dirty: %v, " +msgstr "" + +#: pkg/git/read.go:88 +#, c-format +msgid "no %s exists, not reading any global gitignore config" +msgstr "" + +#: cli/app/cmd.go:171 +#, c-format +msgid "running command %s within the context of %s_%s" +msgstr "" + +#: cli/app/new.go:315 +msgid "Select app server:" +msgstr "" + +#: cli/app/backup.go:215 +msgid "Manage app backups" +msgstr "" + +#: cli/recipe/sync.go:23 +msgid "" +"Generate labels for the main recipe service.\n" +"\n" +"By convention, the service named \"app\" using the following format:\n" +"\n" +" coop-cloud.${STACK_NAME}.version=\n" +"\n" +"Where [version] can be specifed on the command-line or Abra can attempt to\n" +"auto-generate it for you. The configuration will be updated on the\n" +"local file system." +msgstr "" + +#: cli/recipe/list.go:37 +msgid "name" +msgstr "" + +#: pkg/catalogue/catalogue.go:40 +#, c-format +msgid "" +"%s has locally unstaged changes? please commit/remove your changes before " +"proceeding" +msgstr "" + +#: cli/app/cmd.go:196 cli/app/backup.go:15 cli/app/volume.go:19 +msgid "list [flags]" +msgstr "" + +#: cli/app/new.go:47 +msgid "new [recipe] [version] [flags]" +msgstr "" + +#: pkg/client/context.go:66 +msgid "context 'default' cannot be removed" +msgstr "" + +#: pkg/lint/recipe.go:125 +msgid "reduce length of secret names to 12 chars" +msgstr "" + +#: pkg/dns/dns.go:38 pkg/dns/dns.go:47 +#, c-format +msgid "cannot resolve ipv4 for %s?" +msgstr "" + +#: cli/app/cmd.go:265 +msgid "T" +msgstr "" + +#: cli/app/labels.go:74 +msgid "RECIPE LABELS" +msgstr "" + +#: cli/recipe/fetch.go:64 +#, c-format +msgid "unable to discover SSH remote for %s" +msgstr "" + +#: pkg/recipe/compose.go:47 +#, c-format +msgid "COMPOSE_FILE (=\"%s\") parsing failed?" +msgstr "" + +#: cli/app/secret.go:137 +msgid "NOW" +msgstr "" + +#: cli/app/cmd.go:35 +msgid "" +" # pass args/flags without \"--\"\n" +" abra app cmd 1312.net app my_cmd_arg foo --user bar\n" +"\n" +" # pass args/flags with \"--\"\n" +" abra app cmd 1312.net app my_cmd_args --user bar -- foo -vvv\n" +"\n" +" # drop the [service] arg if using \"--local/-l\"\n" +" abra app cmd 1312.net my_cmd --local" +msgstr "" + +#: cli/app/new.go:290 +msgid "Generate app secrets?" +msgstr "" + +#: cli/app/new.go:371 cli/app/backup.go:271 +msgid "secrets" +msgstr "" + +#: cli/run.go:90 +msgid "man [flags]" +msgstr "" + +#: pkg/service/service.go:30 +msgid "no services deployed?" +msgstr "" + +#: cli/app/cmd.go:267 +msgid "disable remote TTY" +msgstr "" + +#: cli/app/rollback.go:238 +#, c-format +msgid "please select a downgrade (version: %s):" +msgstr "" + +#: cli/internal/deploy.go:133 cli/internal/deploy.go:137 +msgid "DEPLOY" +msgstr "" + +#: cli/app/list.go:216 cli/internal/deploy.go:77 +msgid "SERVER" +msgstr "" + +#: pkg/recipe/git.go:191 +#, c-format +msgid "%s (%s) has locally unstaged changes?" +msgstr "" + +#: cli/internal/command.go:83 +#, c-format +msgid "running command with user %s" +msgstr "" + +#: cli/app/secret.go:253 +#, c-format +msgid "deleted %s successfully from local pass store" +msgstr "" + +#: cli/app/backup.go:17 +msgid "List the contents of a snapshot" +msgstr "" + +#: cli/server/add.go:107 +#, c-format +msgid "ssh %s error: %s" +msgstr "" + +#: cli/recipe/list.go:40 +msgid "healthcheck" +msgstr "" + +#: pkg/upstream/convert/volume.go:136 +msgid "tmpfs options are incompatible with type npipe" +msgstr "" + +#: cli/app/backup.go:112 +#, c-format +msgid "including SECRETS=%v in backupbot exec invocation" +msgstr "" + +#: cli/recipe/fetch.go:93 +msgid "fetching latest recipes..." +msgstr "" + +#: pkg/git/init.go:38 +#, c-format +msgid "git add: %s" +msgstr "" + +#: cli/app/secret.go:38 cli/app/secret.go:170 cli/app/secret.go:280 +#: cli/app/upgrade.go:58 cli/app/rollback.go:58 cli/app/deploy.go:59 +#: cli/app/logs.go:32 pkg/autocomplete/autocomplete.go:17 +#: pkg/autocomplete/autocomplete.go:32 pkg/autocomplete/autocomplete.go:43 +#: pkg/autocomplete/autocomplete.go:59 pkg/autocomplete/autocomplete.go:77 +#: pkg/autocomplete/autocomplete.go:93 pkg/autocomplete/autocomplete.go:99 +#: pkg/autocomplete/autocomplete.go:114 +#, c-format +msgid "autocomplete failed: %s" +msgstr "" + +#: cli/app/secret.go:374 +msgid "List all secrets" +msgstr "" + +#: cli/app/cmd.go:168 +#, c-format +msgid "no service %s for %s?" +msgstr "" + +#: cli/app/volume.go:78 +msgid "" +"Remove volumes associated with an app.\n" +"\n" +"The app in question must be undeployed before you try to remove volumes. " +"See\n" +"\"abra app undeploy \" for more.\n" +"\n" +"The command is interactive and will show a multiple select input which " +"allows\n" +"you to make a seclection. Use the \"?\" key to see more help on navigating " +"this\n" +"interface.\n" +"\n" +"Passing \"--force/-f\" will select all volumes for removal. Be careful." +msgstr "" + +#: pkg/lint/recipe.go:134 +msgid "create an example .env.sample" +msgstr "" + +#: cli/recipe/upgrade.go:330 cli/recipe/sync.go:211 cli/recipe/release.go:121 +#, c-format +msgid "%s currently has these unstaged changes 👇" +msgstr "" + +#: cli/recipe/list.go:108 +msgid "filter by recipe" +msgstr "" + +#: cli/updater/updater.go:38 +msgid "" +"Notify on new versions for deployed apps.\n" +"\n" +"If a new patch/minor version is available, a notification is printed.\n" +"\n" +"Use \"--major/-m\" to include new major versions." +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:255 +#, c-format +msgid "unimplemented call: SetDeadline(%v)" +msgstr "" + +#: pkg/recipe/compose.go:58 +#, c-format +msgid "COMPOSE_FILE detected (%s), loading %s" +msgstr "" + +#: pkg/recipe/recipe.go:659 +msgid "retrieving recipes" +msgstr "" + +#: cli/app/remove.go:50 +#, c-format +msgid "ALERTA ALERTA: deleting %s data and config (local/remote)" +msgstr "" + +#: cli/updater/updater.go:484 +#, c-format +msgid "kadabra version %s, commit %s" +msgstr "" + +#: cli/app/secret.go:143 +msgid "insert [flags]" +msgstr "" + +#: cli/app/list.go:148 +#, c-format +msgid "unable to clone %s: %s" +msgstr "" + +#: cli/recipe/release.go:26 +msgid "release [version] [flags]" +msgstr "" + +#: cli/app/restore.go:99 +msgid "target" +msgstr "" + +#: cli/app/restart.go:143 +#, c-format +msgid "%s has been scaled to 1" +msgstr "" + +#: cli/recipe/upgrade.go:354 cli/recipe/sync.go:239 cli/recipe/release.go:593 +msgid "y" +msgstr "" + +#: pkg/lint/recipe.go:140 +msgid "one service named 'app'" +msgstr "" + +#: cli/app/run.go:102 +msgid "no-tty" +msgstr "" + +#: pkg/recipe/recipe.go:202 +#, c-format +msgid "dir: %s, " +msgstr "" + +#: cli/app/upgrade.go:127 +msgid "no available upgrades" +msgstr "" + +#: cli/app/rollback.go:243 +#, c-format +msgid "please select a downgrade (version: %s, chaos: %s):" +msgstr "" + +#: cli/server/add.go:202 +msgid "use local server" +msgstr "" + +#: cli/recipe/list.go:43 +msgid "tests" +msgstr "" + +#: cli/internal/validate.go:35 +#, c-format +msgid "can't read local recipes: %s" +msgstr "" + +#: cli/internal/deploy.go:78 +msgid "CONFIG" +msgstr "" + +#: cli/app/secret.go:57 +msgid "cannot use '[secret] [version]' and '--all' together" +msgstr "" + +#: cli/app/secret.go:102 +msgid "no secrets generated" +msgstr "" + +#: cli/app/secret.go:106 cli/app/new.go:187 +msgid "VALUE" +msgstr "" + +#: cli/app/ps.go:28 +msgid "ps [flags]" +msgstr "" + +#: cli/recipe/upgrade.go:356 cli/recipe/sync.go:241 cli/recipe/release.go:595 +msgid "increase the minor part of the version" +msgstr "" + +#: pkg/lint/recipe.go:148 +msgid "include \"deploy: labels: ...\" stanza" +msgstr "" + +#: pkg/lint/recipe.go:163 +msgid "ensure \"image: ...\" set on all services" +msgstr "" + +#: pkg/catalogue/catalogue.go:84 pkg/recipe/git.go:278 +#, c-format +msgid "fetched latest git changes for %s" +msgstr "" + +#: pkg/recipe/compose.go:107 +#, c-format +msgid "%s has no version label? try running \"abra recipe sync %s\" first?" +msgstr "" + +#: cli/app/backup.go:250 +msgid "include timestamps" +msgstr "" + +#: pkg/upstream/container/hijack.go:132 +msgid "[hijack] end of stdout" +msgstr "" + +#: cli/app/ps.go:119 cli/app/ps.go:120 cli/app/ps.go:121 cli/app/ps.go:122 +#: cli/app/ps.go:123 cli/app/list.go:111 cli/app/list.go:112 +#: cli/app/list.go:113 cli/app/list.go:114 cli/app/list.go:115 +#: cli/app/list.go:175 cli/app/labels.go:71 cli/server/list.go:59 +#: cli/server/list.go:71 +msgid "unknown" +msgstr "" + +#: pkg/lint/recipe.go:504 +msgid "invalid lightweight tag detected" +msgstr "" + +#: cli/recipe/new.go:87 +msgid "happy hacking 🎉" +msgstr "" + +#: cli/recipe/release.go:133 +#, c-format +msgid "" +"no tag specified and no previous tag available for %s, assuming this is the " +"initial release" +msgstr "" + +#: pkg/lint/recipe.go:215 +#, c-format +msgid "linting successful, %s is well configured" +msgstr "" + +#: cli/app/secret.go:442 +msgid "secret [cmd] [args] [flags]" +msgstr "" + +#: cli/app/secret.go:468 cli/app/secret.go:492 cli/app/secret.go:532 +#: cli/app/ps.go:29 cli/app/undeploy.go:156 cli/app/new.go:364 +#: cli/app/backup.go:264 cli/catalogue/catalogue.go:248 cli/server/prune.go:16 +#: cli/recipe/list.go:106 cli/recipe/release.go:609 +msgid "p" +msgstr "" + +#: cli/app/restore.go:57 +#, c-format +msgid "including TARGET=%s in backupbot exec invocation" +msgstr "" + +#: cli/app/cp.go:164 +#, c-format +msgid "copy %s from local to %s on container" +msgstr "" + +#: cli/recipe/upgrade.go:41 +msgid "upgrade [flags]" +msgstr "" + +#: cli/recipe/upgrade.go:362 cli/recipe/sync.go:247 cli/recipe/release.go:601 +msgid "z" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:172 +#, c-format +msgid "" +"command %v has exited with %v, please make sure the URL is valid, and Docker " +"18.09 or later is installed on the remote host: stderr=%s" +msgstr "" + +#: pkg/upstream/convert/service.go:815 +#, c-format +msgid "invalid credential spec: cannot specify both %s, and %s" +msgstr "" + +#: cli/app/secret.go:124 cli/app/secret.go:424 cli/server/list.go:82 +#: cli/recipe/version.go:106 cli/recipe/list.go:77 +#, c-format +msgid "unable to render to JSON: %s" +msgstr "" + +#: pkg/upstream/convert/volume.go:44 +msgid "tmpfs options are incompatible with type volume" +msgstr "" + +#: pkg/recipe/compose.go:123 +#, c-format +msgid "considering %s config(s) for tag update" +msgstr "" + +#: pkg/git/init.go:24 +#, c-format +msgid "initialised new git repo in %s" +msgstr "" + +#: pkg/container/container.go:31 +#, c-format +msgid "no containers matching the %v filter found?" +msgstr "" + +#: cli/app/list.go:49 +msgid "" +" # list apps of all servers without live status\n" +" abra app ls\n" +"\n" +" # list apps of a specific server with live status\n" +" abra app ls -s 1312.net -S\n" +"\n" +" # list apps of all servers which match a specific recipe\n" +" abra app ls -r gitea" +msgstr "" + +#: cli/run.go:150 +msgid "ignore .env version checkout" +msgstr "" + +#: pkg/git/push.go:13 +#, c-format +msgid "dry run: no git changes pushed in %s" +msgstr "" + +#: cli/app/upgrade.go:397 +#, c-format +msgid "'%s' is not a known version" +msgstr "" + +#: cli/app/env.go:15 +msgid "env [flags]" +msgstr "" + +#: cli/recipe/diff.go:15 +msgid "Show unstaged changes in recipe config" +msgstr "" + +#: cli/recipe/upgrade.go:154 +#, c-format +msgid "unable to parse %s, error was: %s, skipping upgrade for %s" +msgstr "" + +#: cli/recipe/list.go:105 +msgid "pattern" +msgstr "" + +#: cli/server/prune.go:15 +msgid "prune [flags]" +msgstr "" + +#: pkg/recipe/recipe.go:74 +#, c-format +msgid "choosing %s as latest version of %s" +msgstr "" + +#: cli/app/upgrade.go:443 cli/app/new.go:356 cli/app/rollback.go:332 +#: cli/app/deploy.go:343 +msgid "D" +msgstr "" + +#: cli/app/remove.go:21 +msgid "Remove all app data, locally and remotely" +msgstr "" + +#: cli/app/labels.go:25 +msgid "Show deployment labels" +msgstr "" + +#: cli/recipe/fetch.go:55 +#, c-format +msgid "%s is already fetched" +msgstr "" + +#: pkg/ssh/ssh.go:26 +msgid "docker: is the daemon running / your user has docker permissions?" +msgstr "" + +#: cli/app/cmd.go:251 +msgid "run command locally" +msgstr "" + +#: cli/app/remove.go:119 +msgid "no secrets to remove" +msgstr "" + +#: pkg/upstream/convert/service.go:813 +#, c-format +msgid "invalid credential spec: cannot specify both %s and %s" +msgstr "" + +#: pkg/upstream/convert/volume.go:133 +msgid "volume options are incompatible with type npipe" +msgstr "" + +#: pkg/git/commit.go:14 +msgid "no commit message specified?" +msgstr "" + +#: cli/app/backup.go:274 +msgid "include secrets" +msgstr "" + +#: cli/updater/updater.go:473 +msgid "The Co-op Cloud auto-updater 🤖 🚀" +msgstr "" + +#: pkg/lint/recipe.go:52 +#, c-format +msgid "%s: skip condition: %s" +msgstr "" + +#: pkg/lint/recipe.go:155 +msgid "include \"traefik.enable=true\" deploy label" +msgstr "" + +#: pkg/lint/recipe.go:481 +#, c-format +msgid "secret %s is longer than 12 characters" +msgstr "" + +#: pkg/recipe/recipe.go:549 +msgid "collecting recipe listing" +msgstr "" + +#: cli/app/secret.go:267 +msgid " abra app secret rm 1312.net oauth_key" +msgstr "" + +#: cli/app/undeploy.go:25 +msgid "" +"This does not destroy any application data.\n" +"\n" +"However, you should remain vigilant, as your swarm installation will " +"consider\n" +"any previously attached volumes as eligible for pruning once undeployed.\n" +"\n" +"Passing \"--prune/-p\" does not remove those volumes." +msgstr "" + +#: cli/recipe/fetch.go:20 +msgid "Clone recipe(s) locally" +msgstr "" + +#: cli/internal/deploy.go:129 +msgid "NEW DEPLOY" +msgstr "" + +#: pkg/lint/recipe.go:76 +msgid "wire up healthchecks" +msgstr "" + +#: pkg/git/read.go:149 +#, c-format +msgid "read global ignore paths: %s" +msgstr "" + +#: cli/app/secret.go:478 cli/app/secret.go:518 cli/app/secret.go:542 +#: cli/app/secret.go:550 cli/app/restore.go:134 cli/app/ps.go:209 +#: cli/app/cmd.go:275 cli/app/new.go:382 cli/app/check.go:90 +#: cli/app/restart.go:157 cli/app/deploy.go:329 cli/app/cp.go:381 +#: cli/app/backup.go:290 cli/app/backup.go:306 cli/app/labels.go:138 +#: cli/catalogue/catalogue.go:274 cli/recipe/lint.go:131 +#: cli/updater/updater.go:540 +msgid "ignore uncommitted recipes changes" +msgstr "" + +#: cli/app/restart.go:23 +msgid "Restart an app" +msgstr "" + +#: cli/run.go:49 +#, c-format +msgid "unable to create %s: %s" +msgstr "" + +#: cli/app/deploy.go:31 +msgid "" +"Deploy an app.\n" +"\n" +"This command supports chaos operations. Use \"--chaos/-C\" to deploy your " +"recipe\n" +"checkout as-is. Recipe commit hashes are also supported as values for\n" +"\"[version]\". Please note, \"upgrade\"/\"rollback\" do not support chaos " +"operations." +msgstr "" + +#: cli/app/cp.go:72 cli/internal/command.go:38 +#, c-format +msgid "retrieved %s as target container on %s" +msgstr "" + +#: pkg/lint/recipe.go:111 +msgid "fill out all the metadata" +msgstr "" + +#: cli/app/secret.go:307 +msgid "cannot use [secret] and --all/-a together" +msgstr "" + +#: cli/app/ps.go:180 cli/app/list.go:219 +msgid "STATUS" +msgstr "" + +#: cli/app/deploy.go:305 +#, c-format +msgid "version: taking version from .env file: %s" +msgstr "" + +#: cli/updater/updater.go:37 +msgid "Check for available upgrades" +msgstr "" + +#: pkg/upstream/container/hijack.go:100 +#, c-format +msgid "invalid detach escape keys, using default: %s" +msgstr "" + +#: pkg/upstream/container/hijack.go:135 +#, c-format +msgid "error receiveStdout: %s" +msgstr "" + +#: pkg/upstream/container/hijack.go:167 +#, c-format +msgid "error sendStdin: %s" +msgstr "" + +#: pkg/recipe/compose.go:248 +msgid "no existing label found, automagic insertion not supported yet" +msgstr "" + +#: cli/app/restore.go:62 +#, c-format +msgid "including NONINTERACTIVE=%v in backupbot exec invocation" +msgstr "" + +#: cli/app/upgrade.go:437 cli/app/rollback.go:326 cli/app/deploy.go:337 +#: cli/app/remove.go:158 cli/app/volume.go:201 +msgid "perform action without further prompt" +msgstr "" + +#: cli/app/undeploy.go:135 cli/server/prune.go:52 +#, c-format +msgid "networks pruned: %d" +msgstr "" + +#: cli/recipe/release.go:28 +msgid "Release a new recipe version" +msgstr "" + +#: pkg/lint/recipe.go:187 +#, c-format +msgid "linting for critical errors in %s configs" +msgstr "" + +#: pkg/upstream/container/hijack.go:82 +#, c-format +msgid "unable to set IO streams as raw terminal: %s" +msgstr "" + +#: pkg/ui/deploy.go:88 +#, c-format +msgid "status: %s, " +msgstr "" + +#: pkg/config/abra.go:81 +msgid "read abra dir from config file" +msgstr "" + +#: cli/app/secret.go:394 cli/app/ps.go:182 cli/app/list.go:221 +#: cli/recipe/version.go:62 cli/recipe/version.go:103 +msgid "VERSION" +msgstr "" + +#: cli/app/restore.go:102 +msgid "target path" +msgstr "" + +#: cli/app/new.go:355 +msgid "domain" +msgstr "" + +#: cli/recipe/fetch.go:23 +msgid "" +" # fetch from recipe catalogue\n" +" abra recipe fetch gitea\n" +"\n" +" # fetch from remote recipe\n" +" abra recipe fetch git.foo.org/recipes/myrecipe\n" +"\n" +" # fetch with ssh remote for hacking\n" +" abra recipe fetch gitea --ssh" +msgstr "" + +#: cli/app/upgrade.go:415 cli/app/undeploy.go:51 cli/app/deploy.go:88 +#, c-format +msgid "checking whether %s is already deployed" +msgstr "" + +#: cli/app/volume.go:145 +#, c-format +msgid "unable to remove volume: no volume with name '%s'?" +msgstr "" + +#: pkg/recipe/git.go:274 +#, c-format +msgid "unable to git pull in %s: %s" +msgstr "" + +#: pkg/recipe/git.go:367 +#, c-format +msgid "detected %s as tags for recipe %s" +msgstr "" + +#: cli/app/secret.go:443 cli/app/restore.go:108 cli/app/new.go:341 +#: cli/app/logs.go:94 cli/app/backup.go:179 cli/app/backup.go:232 +#: cli/app/backup.go:256 cli/app/list.go:320 cli/catalogue/catalogue.go:264 +#: cli/server/server.go:11 cli/recipe/fetch.go:123 cli/recipe/sync.go:21 +msgid "s" +msgstr "" + +#: cli/recipe/upgrade.go:348 cli/recipe/sync.go:233 cli/recipe/release.go:587 +msgid "increase the major part of the version" +msgstr "" + +#: cli/recipe/version.go:17 +msgid "versions [flags]" +msgstr "" + +#: cli/recipe/release.go:518 +#, c-format +msgid "failed to publish new release: %s" +msgstr "" + +#: cli/app/upgrade.go:274 cli/app/undeploy.go:107 cli/app/new.go:224 +#: cli/app/rollback.go:227 cli/app/deploy.go:236 +#, c-format +msgid "writing recipe version failed: %s" +msgstr "" + +#: cli/app/upgrade.go:285 +#, c-format +msgid "please select an upgrade (version: %s):" +msgstr "" + +#: cli/app/undeploy.go:143 cli/server/prune.go:66 +#, c-format +msgid "images pruned: %d; space reclaimed: %s" +msgstr "" + +#: cli/catalogue/catalogue.go:234 +msgid "catalogue [cmd] [args] [flags]" +msgstr "" + +#: cli/recipe/new.go:115 +msgid "git-name" +msgstr "" + +#: cli/internal/deploy.go:82 +msgid "NEW DEPLOYMENT" +msgstr "" + +#: cli/app/secret.go:500 cli/app/upgrade.go:435 cli/app/rollback.go:324 +#: cli/app/deploy.go:335 cli/app/remove.go:156 cli/app/volume.go:199 +#: cli/recipe/fetch.go:19 cli/recipe/fetch.go:131 +msgid "f" +msgstr "" + +#: cli/app/backup.go:134 +msgid "create [flags]" +msgstr "" + +#: pkg/recipe/recipe.go:330 +#, c-format +msgid "%s: image meta is empty?" +msgstr "" + +#: cli/app/upgrade.go:152 +#, c-format +msgid "choosing %s as version to upgrade" +msgstr "" + +#: pkg/lint/recipe.go:97 +msgid "use semver-like tags" +msgstr "" + +#: pkg/secret/secret.go:268 +#, c-format +msgid "generated and stored %v on %s" +msgstr "" + +#: cli/recipe/release.go:501 +msgid "exiting as requested" +msgstr "" + +#: cli/updater/updater.go:74 +msgid "upgrade [[stack] [recipe] | --all] [flags]" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:259 +#, c-format +msgid "unimplemented call: SetReadDeadline(%v)" +msgstr "" + +#: cli/app/restore.go:17 cli/recipe/reset.go:14 +msgid "rs" +msgstr "" + +#: cli/app/cp.go:197 +#, c-format +msgid "remote: %s does not exist" +msgstr "" + +#: cli/internal/command.go:109 +#, c-format +msgid "%s doesn't have a %s function" +msgstr "" + +#: pkg/upstream/convert/volume.go:110 +msgid "invalid tmpfs source, source must be empty" +msgstr "" + +#: pkg/recipe/recipe.go:206 +#, c-format +msgid "readme: %s, " +msgstr "" + +#: cli/app/restore.go:124 +msgid "H" +msgstr "" + +#: cli/recipe/sync.go:197 pkg/recipe/compose.go:229 +#, c-format +msgid "coop-cloud.${STACK_NAME}.version=%s" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:65 +#, c-format +msgid "commandconn (%s):" +msgstr "" + +#: cli/server/add.go:24 +msgid "" +"Add a new server to your configuration so that it can be managed by Abra.\n" +"\n" +"Abra relies on the standard SSH command-line and ~/.ssh/config for client\n" +"connection details. You must configure an entry per-host in your ~/.ssh/" +"config\n" +"for each server:\n" +"\n" +" Host 1312.net 1312\n" +" Hostname 1312.net\n" +" User antifa\n" +" Port 12345\n" +" IdentityFile ~/.ssh/antifa@somewhere\n" +"\n" +"If \"--local\" is passed, then Abra assumes that the current local server " +"is\n" +"intended as the target server. This is useful when you want to have your " +"entire\n" +"Co-op Cloud config located on the server itself, and not on your local\n" +"developer machine. The domain is then set to \"default\"." +msgstr "" + +#: cli/recipe/release.go:93 +msgid "cannot specify tag and bump type at the same time" +msgstr "" + +#: cli/app/backup.go:167 +#, c-format +msgid "including RETRIES=%s in backupbot exec invocation" +msgstr "" + +#: cli/app/undeploy.go:88 +msgid "initialising undeploy" +msgstr "" + +#: cli/run.go:126 cli/updater/updater.go:493 +msgid "show debug messages" +msgstr "" + +#: pkg/config/abra.go:34 +#, c-format +msgid "error loading config file: %s" +msgstr "" + +#: pkg/recipe/recipe.go:200 +#, c-format +msgid "version : %s, " +msgstr "" + +#: cli/run.go:34 +msgid "upgrade" +msgstr "" + +#: cli/recipe/list.go:41 +msgid "backups" +msgstr "" + +#: cli/internal/deploy.go:80 +msgid "CURRENT DEPLOYMENT" +msgstr "" + +#: cli/app/secret.go:467 cli/app/secret.go:491 cli/app/secret.go:531 +#: cli/app/new.go:363 +msgid "pass" +msgstr "" + +#: cli/catalogue/catalogue.go:187 cli/recipe/release.go:353 +#, c-format +msgid "no changes discovered in %s, nothing to publish?" +msgstr "" + +#: cli/upgrade.go:26 +msgid " abra upgrade --rc" +msgstr "" + +#: pkg/lint/recipe.go:82 +msgid "all images use a tag" +msgstr "" + +#: cli/app/secret.go:483 cli/app/secret.go:523 cli/app/backup.go:239 +#: cli/server/prune.go:90 cli/recipe/fetch.go:114 cli/updater/updater.go:553 +msgid "all" +msgstr "" + +#: cli/app/config.go:19 +msgid " abra config 1312.net" +msgstr "" + +#: cli/app/backup.go:298 +msgid "number of retry attempts" +msgstr "" + +#: pkg/lint/recipe.go:55 +#, c-format +msgid "skipping %s based on skip condition" +msgstr "" + +#: pkg/lint/recipe.go:110 +msgid "README.md metadata filled in" +msgstr "" + +#: pkg/server/server.go:25 +#, c-format +msgid "successfully created %s" +msgstr "" + +#: pkg/recipe/git.go:262 +#, c-format +msgid "unable to fetch tags in %s: %s" +msgstr "" + +#: pkg/formatter/formatter.go:46 +msgid " ago" +msgstr "" + +#: cli/app/backup.go:282 +msgid "include volumes" +msgstr "" + +#: cli/recipe/lint.go:53 +#, c-format +msgid "skipping %s, does not have level \"error\"" +msgstr "" + +#: cli/recipe/sync.go:188 +#, c-format +msgid "choosing %s as new version for %s" +msgstr "" + +#: cli/updater/updater.go:471 +msgid "kadabra [cmd] [flags]" +msgstr "" + +#: pkg/lint/recipe.go:103 +msgid "has published catalogue version" +msgstr "" + +#: pkg/upstream/container/exec.go:43 +msgid "exec ID empty" +msgstr "" + +#: pkg/git/common.go:13 +#, c-format +msgid "no .git directory in %s?" +msgstr "" + +#: cli/app/secret.go:154 +msgid "" +" # insert regular secret\n" +" abra app secret insert 1312.net my_secret v1 mySuperSecret\n" +"\n" +" # insert secret as file\n" +" abra app secret insert 1312.net my_secret v1 secret.txt -f" +msgstr "" + +#: cli/app/restore.go:18 +msgid "Restore a snapshot" +msgstr "" + +#: cli/app/new.go:309 +#, c-format +msgid "single server detected, choosing %s automatically" +msgstr "" + +#: pkg/context/context.go:34 +msgid "context lacks Docker endpoint" +msgstr "" + +#: pkg/lint/recipe.go:203 +#, c-format +msgid "" +"\n" +"lint %s: %s" +msgstr "" + +#: pkg/git/commit.go:42 +msgid "git changes commited" +msgstr "" + +#: cli/app/deploy.go:29 cli/app/backup.go:66 cli/recipe/diff.go:14 +#: cli/updater/updater.go:491 +msgid "d" +msgstr "" + +#: cli/app/remove.go:22 +msgid "" +"Remove everything related to an app which is already undeployed.\n" +"\n" +"By default, it will prompt for confirmation before proceeding. All secrets,\n" +"volumes and the local app env file will be deleted.\n" +"\n" +"Only run this command when you are sure you want to completely remove the " +"app\n" +"and all associated app data. This is a destructive action, Be Careful!\n" +"\n" +"If you would like to delete specific volumes or secrets, please use removal\n" +"sub-commands under \"app volume\" and \"app secret\" instead.\n" +"\n" +"Please note, if you delete the local app env file without removing volumes " +"and\n" +"secrets first, Abra will *not* be able to help you remove them afterwards.\n" +"\n" +"To delete everything without prompt, use the \"--force/-f\" or the \"--no-" +"input/n\"\n" +"flag." +msgstr "" + +#: cli/app/remove.go:38 +msgid " abra app remove 1312.net" +msgstr "" + +#: cli/app/list.go:222 cli/internal/deploy.go:140 +msgid "UPGRADE" +msgstr "" + +#: cli/recipe/upgrade.go:318 +#, c-format +msgid "can upgrade service: %s, image: %s, tag: %s ::" +msgstr "" + +#: cli/recipe/release.go:277 +#, c-format +msgid "dry run: move release note from 'next' to %s" +msgstr "" + +#: pkg/lint/recipe.go:75 +msgid "healthcheck enabled for all services" +msgstr "" + +#: pkg/config/abra.go:37 +#, c-format +msgid "config file loaded from: %s" +msgstr "" + +#: cli/app/ps.go:183 cli/app/list.go:220 +msgid "CHAOS" +msgstr "" + +#: cli/app/secret.go:146 +msgid "" +"This command inserts a secret into an app environment.\n" +"\n" +"Arbitrary secret insertion is not supported. Secrets that are inserted must\n" +"match those configured in the recipe beforehand.\n" +"\n" +"This can be useful when you want to manually generate secrets for an app\n" +"environment. Typically, you can let Abra generate them for you on app " +"creation\n" +"(see \"abra app new --secrets/-S\" for more)." +msgstr "" + +#: cli/app/restore.go:126 +msgid "enable pre/post-hook command execution" +msgstr "" + +#: cli/app/cp.go:117 cli/app/cp.go:199 cli/app/cp.go:210 +#, c-format +msgid "remote path: %s" +msgstr "" + +#: cli/recipe/version.go:53 +#, c-format +msgid "%s has no published versions?" +msgstr "" + +#: cli/app/restart.go:161 +msgid "all-services" +msgstr "" + +#: cli/app/cp.go:108 +#, c-format +msgid "local %s " +msgstr "" + +#: cli/app/ps.go:56 cli/app/upgrade.go:423 cli/app/undeploy.go:59 +#: cli/app/services.go:49 cli/app/restart.go:93 cli/app/logs.go:58 +#: cli/updater/updater.go:247 +#, c-format +msgid "%s is not deployed?" +msgstr "" + +#: cli/app/config.go:18 +msgid "Edit app config" +msgstr "" + +#: cli/app/backup.go:234 cli/app/backup.go:258 +msgid "list specific snapshot" +msgstr "" + +#: cli/recipe/sync.go:76 +#, c-format +msgid "" +"\n" +"The following options are two types of initial semantic version that you " +"can\n" +"pick for %s that will be published in the recipe catalogue. This follows " +"the\n" +"semver convention (more on https://semver.org), here is a short cheatsheet\n" +"\n" +" 0.1.0: development release, still hacking. when you make a major " +"upgrade\n" +" you increment the \"y\" part (i.e. 0.1.0 -> 0.2.0) and only move " +"to\n" +" using the \"x\" part when things are stable.\n" +"\n" +" 1.0.0: public release, assumed to be working. you already have a stable\n" +" and reliable deployment of this app and feel relatively " +"confident\n" +" about it.\n" +"\n" +"If you want people to be able alpha test your current config for %s but " +"don't\n" +"think it is quite reliable, go with 0.1.0 and people will know that things " +"are\n" +"likely to change.\n" +"\n" +msgstr "" + +#: cli/recipe/release.go:537 +#, c-format +msgid "removed freshly created tag %s" +msgstr "" + +#: pkg/upstream/convert/volume.go:93 +msgid "volume options are incompatible with type bind" +msgstr "" + +#: pkg/ui/deploy.go:330 +msgid "succeeded" +msgstr "" + +#: pkg/git/read.go:45 +#, c-format +msgid "unable to query status of %s: %s" +msgstr "" + +#: cli/app/run.go:21 +msgid "run [[args] [flags] | [flags] -- [args]]" +msgstr "" + +#: cli/app/rollback.go:26 cli/recipe/release.go:27 +msgid "rl" +msgstr "" + +#: cli/app/app.go:11 +msgid "Manage apps" +msgstr "" + +#: cli/recipe/upgrade.go:345 cli/recipe/sync.go:230 cli/recipe/release.go:584 +#: cli/updater/updater.go:545 cli/internal/recipe.go:46 +#: cli/internal/recipe.go:64 cli/internal/recipe.go:78 +msgid "major" +msgstr "" + +#: cli/recipe/fetch.go:117 +msgid "fetch all recipes" +msgstr "" + +#: cli/app/cmd.go:259 +msgid "request remote user" +msgstr "" + +#: cli/app/restart.go:144 +#, c-format +msgid "%s service successfully restarted" +msgstr "" + +#: cli/app/new.go:374 +msgid "automatically generate secrets" +msgstr "" + +#: cli/server/add.go:21 +msgid "add [[server] | --local] [flags]" +msgstr "" + +#: cli/recipe/upgrade.go:177 +#, c-format +msgid "" +"no new versions available for %s, assuming %s is the latest (use -a/--all-" +"tags to see all anyway)" +msgstr "" + +#: cli/app/restore.go:52 cli/app/backup.go:44 cli/app/backup.go:102 +#, c-format +msgid "including SNAPSHOT=%s in backupbot exec invocation" +msgstr "" + +#: cli/app/cp.go:273 +msgid "destination directory does not exist" +msgstr "" + +#: cli/app/list.go:288 cli/recipe/list.go:39 +msgid "status" +msgstr "" + +#: cli/recipe/upgrade.go:199 +#, c-format +msgid "detected compatible upgradable tags %s for %s" +msgstr "" + +#: pkg/upstream/convert/volume.go:162 +msgid "volume type must be volume, bind, tmpfs or npipe" +msgstr "" + +#: cli/app/new.go:343 +msgid "specify server for new app" +msgstr "" + +#: cli/recipe/lint.go:115 +#, c-format +msgid "critical errors present in %s config" +msgstr "" + +#: cli/app/restore.go:79 +#, c-format +msgid "including NO_COMMANDS=%v in backupbot exec invocation" +msgstr "" + +#: cli/app/run.go:111 cli/app/cmd.go:257 cli/recipe/upgrade.go:42 +#: cli/updater/updater.go:75 +msgid "u" +msgstr "" + +#: cli/app/upgrade.go:402 cli/app/upgrade.go:406 +#, c-format +msgid "%s is not an upgrade for %s?" +msgstr "" + +#: cli/server/add.go:86 +msgid "local server already exists" +msgstr "" + +#: cli/recipe/version.go:39 +msgid "retrieved versions from local recipe repository" +msgstr "" + +#: cli/recipe/sync.go:74 +msgid "unable to continue, input required for initial version" +msgstr "" + +#: cli/app/secret.go:216 +#, c-format +msgid "reading secret from file: %s" +msgstr "" + +#: cli/app/secret.go:263 +msgid "" +"This command removes a secret from an app environment.\n" +"\n" +"Arbitrary secret removal is not supported. Secrets that are removed must\n" +"match those configured in the recipe beforehand." +msgstr "" + +#: cli/app/cmd.go:22 +msgid "" +"command [service | --local] [[args] [flags] | [flags] -- " +"[args]]" +msgstr "" + +#: cli/app/backup.go:65 +msgid "download [flags]" +msgstr "" + +#: cli/recipe/sync.go:129 +#, c-format +msgid "tag at commit %s is unannotated or otherwise broken" +msgstr "" + +#: cli/updater/updater.go:202 +#, c-format +msgid "for %s read env %s with value: %s from docker service" +msgstr "" + +#: pkg/ui/deploy.go:86 +#, c-format +msgid "reader: %v, " +msgstr "" + +#: cli/app/restore.go:118 +msgid "restore specific volumes" +msgstr "" + +#: cli/app/upgrade.go:445 cli/app/rollback.go:334 cli/app/deploy.go:345 +msgid "disable public DNS checks" +msgstr "" + +#: cli/app/rollback.go:120 +msgid "no available downgrades" +msgstr "" + +#: cli/updater/updater.go:224 +#, c-format +msgid "no available upgrades for %s" +msgstr "" + +#: pkg/upstream/convert/service.go:462 +#, c-format +msgid "undefined config %q" +msgstr "" + +#: pkg/container/container.go:48 +msgid "ambiguous container list received, prompting for input" +msgstr "" + +#: cli/app/secret.go:460 cli/app/secret.go:556 cli/app/ps.go:199 +#: cli/app/list.go:312 cli/server/list.go:100 cli/recipe/upgrade.go:370 +#: cli/recipe/version.go:132 cli/recipe/list.go:98 cli/updater/updater.go:546 +msgid "m" +msgstr "" + +#: cli/app/restart.go:21 +msgid "restart [[service] | --all-services] [flags]" +msgstr "" + +#: cli/app/volume.go:150 +#, c-format +msgid "removing volume %s failed: %s" +msgstr "" + +#: cli/catalogue/catalogue.go:175 +#, c-format +msgid "generated recipe catalogue: %s" +msgstr "" + +#: cli/app/upgrade.go:269 cli/app/deploy.go:231 +#, c-format +msgid "attempting to run post deploy commands, saw: %s" +msgstr "" + +#: cli/recipe/upgrade.go:216 +#, c-format +msgid "upgrading service %s from %s to %s (pinned tag: %s)" +msgstr "" + +#: cli/recipe/fetch.go:74 +#, c-format +msgid "unable to remove default remote in %s: %s" +msgstr "" + +#: cli/internal/recipe.go:18 +#, c-format +msgid "" +"\n" +"You need to make a decision about what kind of an update this new recipe\n" +"version is. If someone else performs this upgrade, do they have to do some\n" +"migration work or take care of some breaking changes? This can be signaled " +"in\n" +"the version you specify on the recipe deploy label and is called a semantic\n" +"version.\n" +"\n" +"The latest published version is %s.\n" +"\n" +"Here is a semver cheat sheet (more on https://semver.org):\n" +"\n" +" major: new features/bug fixes, backwards incompatible (e.g 1.0.0 -> " +"2.0.0).\n" +" the upgrade won't work without some preparation work and others " +"need\n" +" to take care when performing it. \"it could go wrong\".\n" +"\n" +" minor: new features/bug fixes, backwards compatible (e.g. 0.1.0 -> " +"0.2.0).\n" +" the upgrade should Just Work and there are no breaking changes " +"in\n" +" the app and the recipe config. \"it should go fine\".\n" +"\n" +" patch: bug fixes, backwards compatible (e.g. 0.0.1 -> 0.0.2). this " +"upgrade\n" +" should also Just Work and is mostly to do with minor bug fixes\n" +" and/or security patches. \"nothing to worry about\".\n" +"\n" +msgstr "" + +#: cli/app/new.go:340 cli/app/new.go:347 cli/app/list.go:319 +#: cli/app/list.go:326 cli/run.go:33 +msgid "server" +msgstr "" + +#: cli/app/logs.go:18 +msgid "logs [service] [flags]" +msgstr "" + +#: cli/server/remove.go:19 +msgid "Remove a managed server" +msgstr "" + +#: cli/app/upgrade.go:434 cli/app/rollback.go:323 cli/app/deploy.go:334 +#: cli/app/remove.go:155 cli/app/volume.go:198 cli/recipe/fetch.go:130 +msgid "force" +msgstr "" + +#: cli/server/add.go:141 +#, c-format +msgid "serverAdd: cleanUp: %s is not empty, aborting cleanup" +msgstr "" + +#: cli/app/cmd.go:198 +msgid "List all available commands" +msgstr "" + +#: cli/app/deploy.go:177 +msgid "skipping domain checks, no DOMAIN=... configured" +msgstr "" + +#: cli/app/remove.go:53 +msgid "are you sure?" +msgstr "" + +#: cli/catalogue/catalogue.go:250 cli/recipe/release.go:611 +msgid "publish changes to git.coopcloud.tech" +msgstr "" + +#: pkg/recipe/recipe.go:207 +#, c-format +msgid "sample env: %s, " +msgstr "" + +#: cli/recipe/release.go:415 +msgid "no -p/--publish passed, not publishing" +msgstr "" + +#: cli/recipe/release.go:510 +#, c-format +msgid "failed to commit changes: %s" +msgstr "" + +#: pkg/recipe/compose.go:233 +#, c-format +msgid "%s is already set, nothing to do?" +msgstr "" + +#: cli/app/deploy.go:303 +#, c-format +msgid "version: can not redeploy chaos version %s" +msgstr "" + +#: cli/recipe/upgrade.go:145 +#, c-format +msgid "%s not considered semver-like" +msgstr "" + +#: cli/internal/validate.go:151 +msgid "Specify a server name" +msgstr "" + +#: pkg/ssh/ssh.go:16 +#, c-format +msgid "SSH host key verification failed for %s" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:141 +msgid "commandconn: failed to wait" +msgstr "" + +#: cli/app/restart.go:108 +#, c-format +msgid "attempting to scale %s to 0" +msgstr "" + +#: cli/run.go:92 +msgid "Generate manpage" +msgstr "" + +#: cli/recipe/release.go:552 +#, c-format +msgid "discovered %s as currently synced recipe label" +msgstr "" + +#: pkg/recipe/recipe.go:130 +#, c-format +msgid "version seems invalid: %s" +msgstr "" + +#: cli/internal/command.go:92 +msgid "not requesting a remote TTY" +msgstr "" + +#: pkg/recipe/git.go:398 +#, c-format +msgid "processing %s for %s" +msgstr "" + +#: cli/app/secret.go:470 cli/app/secret.go:494 +msgid "store generated secrets in a local pass store" +msgstr "" + +#: cli/app/list.go:299 +msgid "show apps of a specific recipe" +msgstr "" + +#: cli/recipe/release.go:413 +#, c-format +msgid "new release published: %s" +msgstr "" + +#: pkg/client/context.go:26 +#, c-format +msgid "created the %s context" +msgstr "" + +#: pkg/recipe/git.go:52 +#, c-format +msgid "can not redeploy chaos version (%s) without --chaos" +msgstr "" + +#: cli/app/upgrade.go:453 cli/app/rollback.go:342 cli/app/deploy.go:353 +msgid "disable converge logic checks" +msgstr "" + +#: cli/internal/validate.go:171 +msgid "server doesn't exist?" +msgstr "" + +#: cli/server/prune.go:93 +msgid "remove all unused images" +msgstr "" + +#: cli/recipe/release.go:185 +msgid "app service is missing image tag?" +msgstr "" + +#: pkg/lint/recipe.go:68 +msgid "compose config has expected version" +msgstr "" + +#: pkg/secret/secret.go:207 +#, c-format +msgid "skipping generation of %s (generate=false)" +msgstr "" + +#: cli/app/backup.go:68 +msgid "" +"Downloads a backup.tar.gz to the current working directory.\n" +"\n" +"\"--volumes/-v\" includes data contained in volumes alongide paths specified " +"in\n" +"\"backupbot.backup.path\" labels." +msgstr "" + +#: cli/updater/updater.go:386 +#, c-format +msgid "don't update %s due to chaos deployment" +msgstr "" + +#: cli/internal/validate.go:120 +msgid "Specify a domain name" +msgstr "" + +#: pkg/secret/secret.go:139 +#, c-format +msgid "secret %s is > %d chars when combined with %s" +msgstr "" + +#: pkg/catalogue/catalogue.go:21 +msgid "catalogue is missing, retrieving now" +msgstr "" + +#: cli/app/secret.go:507 +msgid "trim" +msgstr "" + +#: cli/server/add.go:168 +#, c-format +msgid "creating context with domain %s" +msgstr "" + +#: cli/app/list.go:45 +msgid "List all managed apps" +msgstr "" + +#: cli/app/labels.go:27 +msgid " abra app labels 1312.net" +msgstr "" + +#: pkg/upstream/container/tty.go:39 +#, c-format +msgid "error resize: %s" +msgstr "" + +#: pkg/recipe/git.go:225 pkg/recipe/git.go:406 pkg/git/branch.go:95 +#, c-format +msgid "failed to check out %s in %s" +msgstr "" + +#: pkg/recipe/recipe.go:458 +#, c-format +msgid "recipe %s does not exist?" +msgstr "" + +#: cli/app/upgrade.go:208 cli/app/deploy.go:166 +#, c-format +msgid "%s missing from %s.env" +msgstr "" + +#: cli/recipe/upgrade.go:44 +msgid "" +"Upgrade a given configuration.\n" +"\n" +"It will update the relevant compose file tags on the local file system.\n" +"\n" +"Some image tags cannot be parsed because they do not follow some sort of\n" +"semver-like convention. In this case, all possible tags will be listed and " +"it\n" +"is up to the end-user to decide.\n" +"\n" +"The command is interactive and will show a select input which allows you to\n" +"make a seclection. Use the \"?\" key to see more help on navigating this\n" +"interface.\n" +"\n" +"You may invoke this command in \"wizard\" mode and be prompted for input." +msgstr "" + +#: cli/internal/validate.go:132 +#, c-format +msgid "validated %s as domain argument" +msgstr "" + +#: pkg/upstream/convert/volume.go:130 +msgid "invalid npipe source, source cannot be empty" +msgstr "" + +#: cli/app/remove.go:148 +#, c-format +msgid "file: %s removed" +msgstr "" + +#: cli/server/add.go:146 +#, c-format +msgid "serverAdd: cleanUp: failed to remove %s: %s" +msgstr "" + +#: cli/recipe/release.go:88 +#, c-format +msgid "cannot parse %s, invalid tag specified?" +msgstr "" + +#: cli/recipe/release.go:549 +#, c-format +msgid "" +"unable to read version for %s from synced label. Did you try running \"abra " +"recipe sync %s\" already?" +msgstr "" + +#: pkg/git/clone.go:59 pkg/git/clone.go:78 pkg/git/clone.go:87 +#, c-format +msgid "git clone: %s cloned successfully" +msgstr "" + +#: cli/updater/updater.go:444 +#, c-format +msgid "upgrade %s (%s) to version %s" +msgstr "" + +#: cli/app/rollback.go:142 +msgid "unknown deployed version, unable to downgrade" +msgstr "" + +#: cli/app/remove.go:94 +msgid "no configs to remove" +msgstr "" + +#: cli/app/backup.go:180 +msgid "List all snapshots" +msgstr "" + +#: cli/app/backup.go:295 +msgid "retries" +msgstr "" + +#: cli/catalogue/catalogue.go:24 +msgid "generate [recipe] [flags]" +msgstr "" + +#: cli/run.go:30 +msgid "catalogue" +msgstr "" + +#: pkg/upstream/container/hijack.go:43 +#, c-format +msgid "unable to setup input stream: %s" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:239 +#, c-format +msgid "commandConn.Close: CloseRead: %v" +msgstr "" + +#: pkg/recipe/git.go:50 +#, c-format +msgid "ensuring env version %s" +msgstr "" + +#: pkg/recipe/recipe.go:406 +#, c-format +msgid "read recipe catalogue from file system cache in %s" +msgstr "" + +#: pkg/git/diff.go:30 +msgid "unable to locate git command, cannot output diff" +msgstr "" + +#: cli/app/secret.go:486 +msgid "generate all secrets" +msgstr "" + +#: cli/app/cmd.go:25 +msgid "" +"Run an app specific command.\n" +"\n" +"These commands are bash functions, defined in the abra.sh of the recipe " +"itself.\n" +"They can be run within the context of a service (e.g. app) or locally on " +"your\n" +"work station by passing \"--local/-l\".\n" +"\n" +"N.B. If using the \"--\" style to pass arguments, flags (e.g. \"--local/-" +"l\") must\n" +"be passed *before* the \"--\". It is possible to pass arguments without the " +"\"--\"\n" +"as long as no dashes are present (i.e. \"foo\" works without \"--\", \"-" +"foo\"\n" +"does not)." +msgstr "" + +#: cli/app/check.go:17 +msgid "check [flags]" +msgstr "" + +#: cli/recipe/upgrade.go:75 +msgid "you can only use one of: --major, --minor, --patch." +msgstr "" + +#: pkg/service/service.go:77 pkg/service/service.go:131 +msgid "failed to match chosen service" +msgstr "" + +#: pkg/lint/recipe.go:261 pkg/recipe/files.go:17 +#, c-format +msgid "unable to discover .env.sample for %s" +msgstr "" + +#: pkg/recipe/git.go:160 +#, c-format +msgid "unable to resolve '%s': %s" +msgstr "" + +#: cli/app/restart.go:29 +msgid "" +" # restart a single app service\n" +" abra app restart 1312.net app\n" +"\n" +" # restart all app services\n" +" abra app restart 1312.net -a" +msgstr "" + +#: cli/app/env.go:18 +msgid " abra app env 1312.net" +msgstr "" + +#: cli/recipe/lint.go:34 +msgid "severity" +msgstr "" + +#: pkg/lint/recipe.go:170 +msgid "vendor config versions in an abra.sh" +msgstr "" + +#: cli/app/volume.go:192 +msgid "Manage app volumes" +msgstr "" + +#: cli/upgrade.go:37 pkg/secret/pass.go:23 pkg/secret/pass.go:45 +#, c-format +msgid "attempting to run %s" +msgstr "" + +#: cli/recipe/new.go:34 +msgid "new [flags]" +msgstr "" + +#: pkg/upstream/convert/service.go:43 +#, c-format +msgid "duplicate secret target for %s not allowed" +msgstr "" + +#: pkg/recipe/git.go:241 +#, c-format +msgid "unable to read remotes in %s: %s" +msgstr "" + +#: pkg/recipe/recipe.go:205 +#, c-format +msgid "compose: %s, " +msgstr "" + +#: cli/app/restore.go:123 +msgid "hooks" +msgstr "" + +#: cli/app/ps.go:30 +msgid "Check app deployment status" +msgstr "" + +#: cli/recipe/version.go:19 +msgid "List recipe versions" +msgstr "" + +#: cli/recipe/sync.go:96 +msgid "which version do you want to begin with?" +msgstr "" + +#: pkg/recipe/recipe.go:138 +#, c-format +msgid "removed dirty suffix from .env version: %s -> %s" +msgstr "" + +#: cli/app/secret.go:145 +msgid "Insert secret" +msgstr "" + +#: cli/recipe/lint.go:36 +msgid "skipped" +msgstr "" + +#: cli/app/secret.go:261 cli/app/remove.go:20 cli/app/volume.go:93 +#: cli/server/remove.go:18 +msgid "rm" +msgstr "" + +#: cli/app/secret.go:508 cli/app/restore.go:100 cli/app/run.go:103 +#: cli/app/backup.go:248 +msgid "t" +msgstr "" + +#: cli/app/logs.go:96 +msgid "only tail stderr" +msgstr "" + +#: cli/recipe/new.go:53 +#, c-format +msgid "%s/example.git" +msgstr "" + +#: cli/recipe/release.go:283 +msgid "Use release note in release/next?" +msgstr "" + +#: pkg/recipe/recipe.go:147 +#, c-format +msgid "invalid recipe: %s" +msgstr "" + +#: pkg/formatter/formatter.go:238 +#, c-format +msgid "stripped %s to %s for parsing" +msgstr "" + +#: cli/app/secret.go:510 +msgid "trim input" +msgstr "" + +#: cli/recipe/diff.go:16 +msgid "This command requires /usr/bin/git." +msgstr "" + +#: cli/recipe/recipe.go:10 +msgid "recipe [cmd] [args] [flags]" +msgstr "" + +#: cli/app/secret.go:459 cli/app/secret.go:555 cli/app/ps.go:198 +#: cli/app/list.go:311 cli/server/list.go:99 cli/recipe/upgrade.go:369 +#: cli/recipe/version.go:131 cli/recipe/list.go:97 +msgid "machine" +msgstr "" + +#: cli/app/secret.go:475 cli/app/secret.go:515 cli/app/secret.go:539 +#: cli/app/secret.go:547 cli/app/restore.go:131 cli/app/ps.go:206 +#: cli/app/cmd.go:272 cli/app/new.go:379 cli/app/check.go:87 +#: cli/app/restart.go:154 cli/app/deploy.go:326 cli/app/cp.go:378 +#: cli/app/backup.go:287 cli/app/backup.go:303 cli/app/labels.go:135 +#: cli/catalogue/catalogue.go:271 cli/recipe/lint.go:128 +#: cli/updater/updater.go:537 +msgid "chaos" +msgstr "" + +#: pkg/upstream/convert/service.go:153 pkg/upstream/convert/service.go:168 +#, c-format +msgid "config not found: %s" +msgstr "" + +#: cli/app/run.go:24 +msgid "" +" # run with args/flags\n" +" abra app run 1312.net app -- ls -lha\n" +"\n" +" # run without args/flags\n" +" abra app run 1312.net app bash --user nobody\n" +"\n" +" # run with both kinds of args/flags \n" +" abra app run 1312.net app --user nobody -- ls -lha" +msgstr "" + +#: cli/catalogue/catalogue.go:26 +msgid "Generate the recipe catalogue" +msgstr "TRANSLATE THIS FUCKING SHIT ALREADY" + +#: cli/recipe/fetch.go:125 +msgid "automatically set ssh remote" +msgstr "" + +#: cli/internal/recipe.go:112 +#, c-format +msgid "%s has no main 'app' service?" +msgstr "" + +#: cli/app/secret.go:534 +msgid "remove generated secrets from a local pass store" +msgstr "" + +#: cli/app/cmd.go:67 +msgid "requires at least 3 arguments" +msgstr "" + +#: cli/app/deploy.go:180 +msgid "skipping domain checks" +msgstr "" + +#: cli/app/backup.go:247 +msgid "timestamps" +msgstr "" + +#: cli/app/volume.go:182 +#, c-format +msgid "%d volumes removed successfully" +msgstr "" + +#: cli/updater/updater.go:176 +#, c-format +msgid "boolean label %s could not be found for %s, set default to false." +msgstr "" + +#: pkg/envfile/envfile.go:42 pkg/envfile/envfile.go:80 pkg/config/env.go:50 +#, c-format +msgid "read %s from %s" +msgstr "" + +#: pkg/recipe/git.go:434 +#, c-format +msgid "%s service is missing image tag?" +msgstr "" + +#: cli/app/secret.go:373 cli/app/cmd.go:197 cli/app/backup.go:16 +#: cli/app/volume.go:20 cli/app/list.go:44 cli/server/list.go:19 +#: cli/recipe/list.go:20 +msgid "ls" +msgstr "" + +#: cli/recipe/upgrade.go:91 +#, c-format +msgid "found versions file for %s" +msgstr "" + +#: cli/recipe/upgrade.go:101 +#, c-format +msgid "malformed version pin specification: %s" +msgstr "" + +#: pkg/service/service.go:103 pkg/container/container.go:40 +#, c-format +msgid "%s (created %v)" +msgstr "" + +#: pkg/git/init.go:70 +#, c-format +msgid "repo set config: %s" +msgstr "" + +#: cli/server/add.go:163 +#, c-format +msgid "context for %s already exists" +msgstr "" + +#: pkg/lint/recipe.go:162 +msgid "all services have images" +msgstr "" + +#: pkg/ui/deploy.go:87 +#, c-format +msgid "writer: %v, " +msgstr "" + +#: cli/app/restore.go:116 cli/app/backup.go:280 cli/server/prune.go:99 +#: cli/recipe/version.go:18 +msgid "v" +msgstr "" + +#: cli/server/remove.go:17 +msgid "remove [flags]" +msgstr "" + +#: cli/internal/deploy.go:142 +msgid "DOWNGRADE" +msgstr "" + +#: pkg/envfile/envfile.go:73 +#, c-format +msgid "couldn't parse %s" +msgstr "" + +#: pkg/git/read.go:52 +#, c-format +msgid "git status: %s: clean" +msgstr "" + +#: pkg/formatter/formatter.go:134 +msgid "CreateOverview: only accepts rows of len == 2" +msgstr "" + +#: cli/app/remove.go:136 cli/app/volume.go:179 +#, c-format +msgid "removing volumes failed: %s" +msgstr "" + +#: cli/server/add.go:184 +#, c-format +msgid "server dir for %s already created" +msgstr "" + +#: cli/internal/backup.go:29 +#, c-format +msgid "retrieved %s as backup enabled service" +msgstr "" + +#: cli/app/secret.go:502 +msgid "treat input as a file" +msgstr "" + +#: cli/app/upgrade.go:318 +#, c-format +msgid "parsing chosen upgrade version failed: %s" +msgstr "" + +#: cli/app/new.go:118 +#, c-format +msgid "failed to retrieve latest commit for %s: %s" +msgstr "" + +#: cli/app/backup.go:213 +msgid "backup [cmd] [args] [flags]" +msgstr "" + +#: cli/catalogue/catalogue.go:263 +msgid "skip-updates" +msgstr "" + +#: cli/recipe/lint.go:33 +msgid "rule" +msgstr "" + +#: pkg/client/configs.go:35 +#, c-format +msgid "conf %s: %s" +msgstr "" + +#: pkg/config/abra.go:77 +msgid "read abra dir from $ABRA_DIR" +msgstr "" + +#: cli/app/remove.go:116 +#, c-format +msgid "secret: %s removed" +msgstr "" + +#: cli/app/backup.go:117 +#, c-format +msgid "including VOLUMES=%v in backupbot exec invocation" +msgstr "" + +#: cli/updater/updater.go:77 +msgid "" +"Upgrade an app by specifying stack name and recipe. \n" +"\n" +"Use \"--all\" to upgrade every deployed app.\n" +"\n" +"For each app with auto updates enabled, the deployed version is compared " +"with\n" +"the current recipe catalogue version. If a new patch/minor version is\n" +"available, the app is upgraded.\n" +"\n" +"To include major versions use the \"--major/-m\" flag. You probably don't " +"want\n" +"that as it will break things. Only apps that are not deployed with \"--" +"chaos/-C\"\n" +"are upgraded, to update chaos deployments use the \"--chaos/-C\" flag. Use " +"it\n" +"with care." +msgstr "" + +#: pkg/lint/recipe.go:96 +msgid "tags use semver-like format" +msgstr "" + +#: cli/app/run.go:113 +msgid "run command as user" +msgstr "" + +#: cli/app/upgrade.go:290 +#, c-format +msgid "please select an upgrade (version: %s, chaos: %s):" +msgstr "" + +#: cli/app/volume.go:77 +msgid "Remove volume(s) associated with an app" +msgstr "" + +#: cli/catalogue/catalogue.go:227 cli/recipe/release.go:394 +msgid "dry run: no changes published" +msgstr "" + +#: cli/upgrade.go:16 +msgid "upgrade [flags]" +msgstr "" + +#: cli/recipe/fetch.go:44 +msgid "missing [recipe] or --all/-a" +msgstr "" + +#: cli/app/restart.go:164 +msgid "restart all services" +msgstr "" + +#: cli/updater/updater.go:548 +msgid "check for major updates" +msgstr "" + +#: cli/internal/deploy.go:189 +#, c-format +msgid "running command %s %s within the context of %s_%s" +msgstr "" + +#: pkg/recipe/git.go:410 +#, c-format +msgid "git checkout: %s in %s" +msgstr "" + +#: cli/app/secret.go:53 +msgid "missing arguments [secret]/[version] or '--all'" +msgstr "" + +#: cli/complete.go:13 +msgid "" +"To load completions:\n" +"\n" +"Bash:\n" +" # Load autocompletion for the current Bash session\n" +" $ source <(abra autocomplete bash)\n" +"\n" +" # To load autocompletion for each session, execute once:\n" +" # Linux:\n" +" $ abra autocomplete bash | sudo tee /etc/bash_completion.d/abra\n" +" # macOS:\n" +" $ abra autocomplete bash | sudo tee $(brew --prefix)/etc/bash_completion.d/" +"abra\n" +"\n" +"Zsh:\n" +" # If shell autocompletion is not already enabled in your environment,\n" +" # you will need to enable it. You can execute the following once:\n" +"\n" +" $ echo \"autoload -U compinit; compinit\" >> ~/.zshrc\n" +"\n" +" # To load autocompletions for each session, execute once:\n" +" $ abra autocomplete zsh > \"${fpath[1]}/_abra\"\n" +"\n" +" # You will need to start a new shell for this setup to take effect.\n" +"\n" +"fish:\n" +" $ abra autocomplete fish | source\n" +"\n" +" # To load autocompletions for each session, execute once:\n" +" $ abra autocomplete fish > ~/.config/fish/completions/abra.fish\n" +"\n" +"PowerShell:\n" +" PS> abra autocomplete powershell | Out-String | Invoke-Expression\n" +"\n" +" # To load autocompletions for every new session, run:\n" +" PS> abra autocomplete powershell > abra.ps1\n" +" # and source this file from your PowerShell profile." +msgstr "" + +#: pkg/secret/secret.go:119 +msgid "not generating app secrets, none enabled in recipe config" +msgstr "" + +#: cli/app/secret.go:394 +msgid "GENERATED NAME" +msgstr "" + +#: cli/app/cmd.go:46 +msgid "requires at least 2 arguments with --local/-l" +msgstr "" + +#: pkg/secret/pass.go:29 +#, c-format +msgid "%s inserted into pass store" +msgstr "" + +#: cli/app/list.go:322 +msgid "show apps of a specific server" +msgstr "" + +#: cli/updater/updater.go:103 +msgid "missing arguments or --all/-a flag" +msgstr "" + +#: pkg/client/client.go:100 +msgid "swarm mode not enabled on local server?" +msgstr "" + +#: cli/recipe/upgrade.go:300 +#, c-format +msgid "not upgrading %s, skipping as requested" +msgstr "" + +#: cli/recipe/upgrade.go:148 +#, c-format +msgid "unable to read tag for image %s, is it missing? skipping upgrade for %s" +msgstr "" + +#: cli/recipe/sync.go:154 +msgid "you can only use one version flag: --major, --minor or --patch" +msgstr "" + +#: cli/recipe/release.go:430 +msgid "you can only use one of: --major, --minor, --patch" +msgstr "" + +#: cli/internal/deploy.go:86 +#, c-format +msgid "%s OVERVIEW" +msgstr "" + +#: cli/app/check.go:19 +msgid "Ensure an app is well configured" +msgstr "" + +#: cli/app/run.go:22 cli/app/upgrade.go:459 cli/app/backup.go:296 +#: cli/app/list.go:297 cli/catalogue/catalogue.go:256 cli/recipe/sync.go:223 +#: cli/recipe/recipe.go:11 cli/recipe/release.go:577 +msgid "r" +msgstr "" + +#: cli/app/undeploy.go:23 +msgid "un" +msgstr "" + +#: cli/app/rollback.go:270 +#, c-format +msgid "current deployment '%s' is not a known version for %s" +msgstr "" + +#: cli/run.go:28 +msgid "app" +msgstr "" + +#: cli/internal/deploy.go:117 +msgid "UNDEPLOY" +msgstr "" + +#: pkg/ui/deploy.go:84 +#, c-format +msgid "id: %s, " +msgstr "" + +#: pkg/git/read.go:50 +#, c-format +msgid "git status: %s: %s" +msgstr "" + +#: cli/app/secret.go:136 +msgid "NOT" +msgstr "" + +#: cli/app/restart.go:133 +#, c-format +msgid "attempting to scale %s to 1" +msgstr "" + +#: cli/app/volume.go:191 +msgid "vl" +msgstr "" + +#: cli/recipe/recipe.go:13 +msgid "" +"A recipe is a blueprint for an app.\n" +"\n" +"It is a bunch of config files which describe how to deploy and maintain an " +"app.\n" +"Recipes are maintained by the Co-op Cloud community and you can use Abra to\n" +"read them, deploy them and create apps for you.\n" +"\n" +"Anyone who uses a recipe can become a maintainer. Maintainers typically " +"make\n" +"sure the recipe is in good working order and the config upgraded in a " +"timely\n" +"manner." +msgstr "" + +#: cli/app/cmd.go:119 +#, c-format +msgid "--local detected, running %s on local work station" +msgstr "" + +#: cli/app/new.go:236 +#, c-format +msgid "trimming %s to %s to avoid runtime limits" +msgstr "" + +#: cli/app/remove.go:141 +msgid "no volumes to remove" +msgstr "" + +#: cli/app/list.go:43 cli/server/list.go:18 +msgid "list [flags]" +msgstr "" + +#: cli/server/list.go:34 +msgid "HOST" +msgstr "" + +#: cli/recipe/upgrade.go:361 cli/recipe/sync.go:246 cli/recipe/release.go:600 +#: cli/internal/recipe.go:46 cli/internal/recipe.go:68 +#: cli/internal/recipe.go:82 +msgid "patch" +msgstr "" + +#: cli/recipe/sync.go:193 +#, c-format +msgid "invalid version %s specified" +msgstr "" + +#: pkg/service/service.go:41 +#, c-format +msgid "no services deployed matching label '%s'?" +msgstr "" + +#: cli/app/secret.go:26 +msgid "Generate secrets" +msgstr "" + +#: cli/app/new.go:284 +#, c-format +msgid "%s has no secrets to generate, skipping..." +msgstr "" + +#: cli/run.go:29 +msgid "autocomplete" +msgstr "" + +#: pkg/secret/secret.go:62 pkg/secret/secret.go:80 +#, c-format +msgid "generated %s" +msgstr "" + +#: pkg/secret/pass.go:51 +#, c-format +msgid "%s removed from pass store" +msgstr "" + +#: cli/app/restart.go:68 +msgid "cannot use [service] and --all-services/-a together" +msgstr "" + +#: cli/complete.go:11 +msgid "autocomplete [bash|zsh|fish|powershell]" +msgstr "" + +#: pkg/ssh/ssh.go:24 +#, c-format +msgid "unable to connect to %s, please check your SSH config" +msgstr "" + +#: cli/app/secret.go:210 +#, c-format +msgid "no secret %s available for recipe %s?" +msgstr "" + +#: cli/app/new.go:366 +msgid "store secrets in a local pass store" +msgstr "" + +#: cli/recipe/fetch.go:81 +#, c-format +msgid "unable to set SSH remote in %s: %s" +msgstr "" + +#: cli/recipe/list.go:19 +msgid "List recipes" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:49 +#, c-format +msgid "commandconn: starting %s with %v" +msgstr "" + +#: pkg/git/init.go:34 +#, c-format +msgid "git worktree: %s" +msgstr "" + +#: cli/app/secret.go:144 +msgid "i" +msgstr "" + +#: cli/recipe/new.go:62 +#, c-format +msgid "removed .git repo in %s" +msgstr "" + +#: cli/internal/recipe.go:70 cli/internal/recipe.go:85 +msgid "no version bump type specififed?" +msgstr "" + +#: pkg/ssh/ssh.go:22 +#, c-format +msgid "ssh auth: permission denied for %s" +msgstr "" + +#: cli/app/cmd.go:24 +msgid "Run app commands" +msgstr "" + +#: cli/app/cmd.go:264 +msgid "tty" +msgstr "" + +#: cli/catalogue/catalogue.go:266 +msgid "skip updating recipe repositories" +msgstr "" + +#: cli/run.go:109 +#, c-format +msgid "unable to proceed, %s does not exist?" +msgstr "" + +#: cli/recipe/sync.go:72 +#, c-format +msgid "no git tags found for %s" +msgstr "" + +#: cli/internal/validate.go:75 +msgid "generate" +msgstr "" + +#: pkg/config/env.go:98 +#, c-format +msgid "directory is empty: %s" +msgstr "" + +#: cli/app/secret.go:260 +msgid "remove [[secret] | --all] [flags]" +msgstr "" + +#: cli/app/ps.go:179 cli/recipe/version.go:62 cli/recipe/version.go:103 +msgid "SERVICE" +msgstr "" + +#: cli/app/deploy.go:107 +#, c-format +msgid "ensure recipe: %s" +msgstr "" + +#: cli/app/cp.go:32 +msgid "" +" # copy myfile.txt to the root of the app service\n" +" abra app cp 1312.net myfile.txt app:/\n" +"\n" +" # copy that file back to your current working directory locally\n" +" abra app cp 1312.net app:/myfile.txt ./" +msgstr "" + +#: cli/updater/updater.go:35 +msgid "notify [flags]" +msgstr "" + +#: cli/internal/command.go:69 +#, c-format +msgid "%s does not exist for %s, use /bin/sh as fallback" +msgstr "" + +#: cli/internal/deploy.go:167 +#, c-format +msgid "running post-command '%s %s' in container %s" +msgstr "" + +#: cli/app/undeploy.go:158 +msgid "prune unused containers, networks, and dangling images" +msgstr "" + +#: cli/app/new.go:49 +msgid "Create a new app" +msgstr "" + +#: cli/app/rollback.go:145 +#, c-format +msgid "choosing %s as version to rollback" +msgstr "" + +#: cli/server/add.go:40 +msgid " abra server add 1312.net" +msgstr "" + +#: pkg/ui/deploy.go:341 +#, c-format +msgid "%s: %s (retries: %v, healthcheck: %s)" +msgstr "" + +#: cli/app/upgrade.go:31 +msgid "Upgrade an app" +msgstr "" + +#: cli/app/new.go:275 cli/internal/validate.go:129 +msgid "no domain provided" +msgstr "" + +#: cli/app/remove.go:19 +msgid "remove [flags]" +msgstr "" + +#: cli/recipe/release.go:249 +#, c-format +msgid "chore: publish %s release" +msgstr "" + +#: pkg/git/clone.go:64 pkg/git/clone.go:102 +#, c-format +msgid "git clone %s: cancelled due to interrupt" +msgstr "" + +#: cli/app/upgrade.go:458 +msgid "releasenotes" +msgstr "" + +#: cli/recipe/sync.go:203 +#, c-format +msgid "dry run: not syncing label %s for recipe %s" +msgstr "" + +#: cli/recipe/release.go:400 +msgid "publish new release?" +msgstr "" + +#: cli/updater/updater.go:406 +#, c-format +msgid "don't update %s due to no new version" +msgstr "" + +#: cli/app/logs.go:101 +msgid "since" +msgstr "" + +#: cli/recipe/upgrade.go:296 +#, c-format +msgid "tag upgraded from %s to %s for %s" +msgstr "" + +#: cli/app/new.go:358 +msgid "domain name for app" +msgstr "" + +#: cli/app/services.go:23 +msgid "Display all services of an app" +msgstr "" + +#: cli/catalogue/catalogue.go:223 +#, c-format +msgid "new changes published: %s" +msgstr "" + +#: cli/app/cmd.go:137 +#, c-format +msgid "%s does not exist locally, use /bin/sh as fallback" +msgstr "" + +#: cli/app/upgrade.go:451 cli/app/rollback.go:340 cli/app/deploy.go:351 +#: cli/app/cp.go:30 cli/app/backup.go:135 +msgid "c" +msgstr "" + +#: cli/catalogue/catalogue.go:235 +msgid "Manage the recipe catalogue" +msgstr "" + +#: cli/run.go:25 +msgid "The Co-op Cloud command-line utility belt 🎩🐇" +msgstr "" + +#: cli/server/remove.go:43 +#, c-format +msgid "%s is now lost in time, like tears in rain" +msgstr "" + +#: cli/updater/updater.go:299 +#, c-format +msgid "available updates for %s: %s" +msgstr "" + +#: cli/recipe/fetch.go:133 +msgid "force re-fetch" +msgstr "" + +#: cli/app/deploy.go:28 +msgid "deploy [version] [flags]" +msgstr "" + +#: pkg/recipe/compose.go:38 +#, c-format +msgid "COMPOSE_FILE detected, loading %s" +msgstr "" + +#: cli/upgrade.go:55 +msgid "install release candidate (may contain bugs)" +msgstr "" + +#: cli/recipe/lint.go:37 +msgid "resolve" +msgstr "" + +#: cli/recipe/release.go:128 +msgid "previous git tags detected, assuming this is a new semver release" +msgstr "" + +#: cli/recipe/reset.go:13 +msgid "reset [flags]" +msgstr "" + +#: cli/recipe/reset.go:15 +msgid "Remove all unstaged changes from recipe config" +msgstr "" + +#: pkg/dns/dns.go:18 +#, c-format +msgid "%s: no IPv4 available" +msgstr "" + +#: cli/app/rollback.go:25 +msgid "rollback [version] [flags]" +msgstr "" + +#: cli/upgrade.go:19 +msgid "" +"Upgrade abra in-place with the latest stable or release candidate.\n" +"\n" +"By default, the latest stable release is downloaded.\n" +"\n" +"Use \"--rc/-r\" to install the latest release candidate. Please bear in mind " +"that\n" +"it may contain absolutely catastrophic deal-breaker bugs. Thank you very " +"much\n" +"for the testing efforts 💗" +msgstr "" + +#: cli/recipe/release.go:78 +#, c-format +msgid "main app service version for %s is empty?" +msgstr "" + +#: pkg/client/client.go:97 +#, c-format +msgid "swarm mode not enabled on %s?" +msgstr "" + +#: pkg/upstream/convert/volume.go:96 +msgid "tmpfs options are incompatible with type bind" +msgstr "" + +#: pkg/recipe/recipe.go:368 +#, c-format +msgid "%s: end marker %s not found" +msgstr "" + +#: cli/updater/updater.go:396 +#, c-format +msgid "" +"don't update %s due to disabled auto updates or missing ENABLE_AUTO_UPDATE " +"env" +msgstr "" + +#: pkg/lint/recipe.go:212 +#, c-format +msgid "" +"recipe '%s' failed lint checks:\n" +"%s" +msgstr "" + +#: cli/updater/updater.go:498 +msgid "no-input" +msgstr "" + +#: pkg/upstream/container/tty.go:66 +msgid "failed to resize tty, using default size" +msgstr "" + +#: pkg/config/abra.go:88 +msgid "using default abra dir" +msgstr "" + +#: cli/server/add.go:120 pkg/secret/secret.go:223 pkg/secret/secret.go:243 +#: pkg/server/server.go:21 +#, c-format +msgid "%s already exists" +msgstr "" + +#: cli/recipe/upgrade.go:364 cli/recipe/sync.go:249 cli/recipe/release.go:603 +msgid "increase the patch part of the version" +msgstr "" + +#: cli/recipe/lint.go:14 +msgid "lint [flags]" +msgstr "" + +#: pkg/ui/deploy.go:83 +#, c-format +msgid "err: %v, " +msgstr "" + +#: cli/app/check.go:20 +msgid "" +"Compare env vars in both the app \".env\" and recipe \".env.sample\" file.\n" +"\n" +"The goal is to ensure that recipe \".env.sample\" env vars are defined in " +"your\n" +"app \".env\" file. Only env var definitions in the \".env.sample\" which " +"are\n" +"uncommented, e.g. \"FOO=bar\" are checked. If an app \".env\" file does not " +"include\n" +"these env vars, then \"check\" will complain.\n" +"\n" +"Recipe maintainers may or may not provide defaults for env vars within " +"their\n" +"recipes regardless of commenting or not (e.g. through the use of\n" +"${FOO:} syntax). \"check\" does not confirm or deny this for you." +msgstr "" + +#: cli/app/backup.go:263 +msgid "path" +msgstr "" + +#: pkg/recipe/git.go:251 +#, c-format +msgid "unable to open git work tree in %s: %s" +msgstr "" + +#: cli/app/run.go:23 +msgid "Run a command inside a service container" +msgstr "" + +#: pkg/lint/recipe.go:22 +msgid "critical" +msgstr "" + +#: pkg/lint/recipe.go:104 +msgid "publish a recipe version to the catalogue" +msgstr "" + +#: cli/app/run.go:110 cli/app/cmd.go:256 +msgid "user" +msgstr "" + +#: cli/app/volume.go:88 +msgid "" +" # delete volumes interactively\n" +" abra app volume rm 1312.net\n" +"\n" +" # delete specific volume\n" +" abra app volume rm 1312.net my_volume" +msgstr "" + +#: cli/recipe/lint.go:139 +msgid "only show errors" +msgstr "" + +#: cli/app/secret.go:134 +#, c-format +msgid "generated secrets %s shown again, please take note of them %s" +msgstr "" + +#: cli/recipe/recipe.go:12 +msgid "Manage recipes" +msgstr "" + +#: pkg/secret/secret.go:212 +#, c-format +msgid "attempting to generate and store %s on %s" +msgstr "" + +#: pkg/ui/deploy.go:333 +msgid "rolled back" +msgstr "" + +#: cli/app/backup.go:67 +msgid "Download a snapshot" +msgstr "" + +#: pkg/upstream/convert/service.go:652 +#, c-format +msgid "unknown restart policy: %s" +msgstr "" + +#: pkg/recipe/compose.go:243 +#, c-format +msgid "synced label %s to service %s" +msgstr "" + +#: cli/recipe/upgrade.go:280 +msgid "" +"enter / return to confirm, choose 'skip' to not upgrade this tag, vim mode " +"is enabled" +msgstr "" + +#: cli/internal/deploy.go:159 +#, c-format +msgid "not enough arguments: %s" +msgstr "" + +#: cli/app/rollback.go:27 +msgid "Roll an app back to a previous version" +msgstr "" + +#: cli/app/backup.go:54 +#, c-format +msgid "including TIMESTAMPS=%v in backupbot exec invocation" +msgstr "" + +#: cli/recipe/reset.go:16 +msgid "WARNING: this will delete your changes. Be Careful." +msgstr "" + +#: cli/app/secret.go:262 +msgid "Remove a secret" +msgstr "" + +#: cli/server/add.go:53 +msgid "cannot use [server] and --local together" +msgstr "" + +#: cli/recipe/fetch.go:122 +msgid "ssh" +msgstr "" + +#: pkg/secret/secret.go:130 +#, c-format +msgid "%s not enabled in recipe config, skipping" +msgstr "" + +#: pkg/recipe/recipe.go:555 +#, c-format +msgid "fetching repo metadata from %s" +msgstr "" + +#: cli/app/deploy.go:36 +msgid "" +" # standard deployment\n" +" abra app deploy 1312.net\n" +"\n" +" # chaos deployment\n" +" abra app deploy 1312.net --chaos\n" +" \n" +" # deploy specific version\n" +" abra app deploy 1312.net 2.0.0+1.2.3\n" +"\n" +" # deploy a specific git hash\n" +" abra app deploy 1312.net 886db76d" +msgstr "" + +#: cli/recipe/upgrade.go:377 +msgid "all-tags" +msgstr "" + +#: pkg/lint/recipe.go:496 +#, c-format +msgid "unable to list local tags for %s" +msgstr "" + +#: cli/app/deploy.go:316 +#, c-format +msgid "version: taking new recipe version: %s" +msgstr "" + +#: cli/recipe/upgrade.go:243 +#, c-format +msgid "upgrade to which tag? (service: %s, image: %s, tag: %s)" +msgstr "" + +#: cli/internal/deploy.go:123 +msgid "UNCHAOS DEPLOY" +msgstr "" + +#: cli/server/prune.go:17 +msgid "Prune resources on a server" +msgstr "" + +#: cli/server/add.go:23 +msgid "Add a new server" +msgstr "" + +#: cli/internal/deploy.go:120 +msgid "CHAOS DEPLOY" +msgstr "" + +#: pkg/container/container.go:52 +msgid "which container are you looking for?" +msgstr "" + +#: cli/catalogue/catalogue.go:191 +msgid "chore: publish new catalogue release changes" +msgstr "" + +#: cli/run.go:117 +msgid "don't forget to run 'sudo mandb'" +msgstr "" + +#: pkg/config/env.go:74 pkg/config/env.go:107 +#, c-format +msgid "broken symlink in your abra config folders: %s" +msgstr "" + +#: cli/app/volume.go:190 +msgid "volume [cmd] [args] [flags]" +msgstr "" + +#: cli/run.go:74 +#, c-format +msgid "unsupported --lang: %s (want: es)" +msgstr "" + +#: cli/recipe/upgrade.go:172 +#, c-format +msgid "detected potential upgradable tags %s for %s" +msgstr "" + +#: pkg/recipe/git.go:156 +#, c-format +msgid "attempting to checkout '%s' as chaos commit" +msgstr "" + +#: cli/app/cmd.go:248 cli/server/add.go:199 cli/server/list.go:69 +msgid "local" +msgstr "" + +#: cli/app/remove.go:89 +#, c-format +msgid "removing configs failed: %s" +msgstr "" + +#: pkg/recipe/git.go:458 +#, c-format +msgid "collected %s for %s" +msgstr "" + +#: cli/app/services.go:67 +msgid "SERVICE (LONG)" +msgstr "" + +#: cli/app/volume.go:21 +msgid "List volumes associated with an app" +msgstr "" + +#: cli/run.go:93 +msgid "" +" # generate the man pages into /usr/local/share/man/man1\n" +" abra_path=$(which abra) # pass abra absolute path to sudo below\n" +" sudo $abra_path man\n" +" sudo mandb\n" +"\n" +" # read the man pages\n" +" man abra\n" +" man abra-app-deploy" +msgstr "" + +#: cli/server/prune.go:56 +msgid "removing all images, not only dangling ones" +msgstr "" + +#: cli/recipe/release.go:342 +msgid "dry run: no changes committed" +msgstr "" + +#: pkg/recipe/recipe.go:435 +#, c-format +msgid "detected versions %s for %s" +msgstr "" + +#: cli/app/restart.go:132 +#, c-format +msgid "%s has been scaled to 0" +msgstr "" + +#: cli/catalogue/catalogue.go:89 +msgid "collecting catalogue metadata" +msgstr "" + +#: cli/app/cmd.go:23 +msgid "cmd" +msgstr "" + +#: cli/server/add.go:128 +#, c-format +msgid "serverAdd: cleanUp: cleaning up context for %s" +msgstr "" + +#: cli/recipe/fetch.go:18 +msgid "fetch [recipe | --all] [flags]" +msgstr "" + +#: pkg/git/branch.go:99 +#, c-format +msgid "successfully checked out %v in %s" +msgstr "" + +#: cli/updater/updater.go:76 +msgid "Upgrade apps" +msgstr "" + +#: pkg/git/read.go:31 +#, c-format +msgid "unable to open worktree of %s: %s" +msgstr "" + +#: pkg/git/clone.go:89 +#, c-format +msgid "git clone: %s already exists" +msgstr "" + +#: pkg/container/container.go:69 +msgid "failed to match chosen container" +msgstr "" + +#: cli/app/new.go:70 cli/app/deploy.go:262 +msgid "cannot use [version] and --chaos together" +msgstr "" + +#: cli/internal/validate.go:96 +msgid "no app provided" +msgstr "" + +#: pkg/upstream/convert/service.go:774 +msgid "replicas can only be used with replicated mode" +msgstr "" + +#: pkg/recipe/compose.go:249 +#, c-format +msgid "add '- \"%s\"' manually to the 'app' service in %s" +msgstr "" + +#: pkg/git/push.go:31 +msgid "git changes pushed" +msgstr "" + +#: cli/app/new.go:48 cli/recipe/new.go:35 cli/updater/updater.go:36 +#: cli/updater/updater.go:499 +msgid "n" +msgstr "" + +#: pkg/client/volumes.go:63 +#, c-format +msgid "%d retries failed" +msgstr "" + +#: cli/app/secret.go:444 +msgid "Manage app secrets" +msgstr "" + +#: cli/app/undeploy.go:22 +msgid "undeploy [flags]" +msgstr "" + +#: cli/app/rollback.go:280 cli/app/rollback.go:284 +#, c-format +msgid "%s is not a downgrade for %s?" +msgstr "" + +#: pkg/lint/recipe.go:118 +msgid "upload your recipe to git.coopcloud.tech/coop-cloud/..." +msgstr "" + +#: cli/app/secret.go:25 cli/catalogue/catalogue.go:25 +msgid "g" +msgstr "" + +#: cli/app/restore.go:16 +msgid "restore [flags]" +msgstr "" + +#: cli/recipe/upgrade.go:346 cli/recipe/sync.go:231 cli/recipe/release.go:585 +msgid "x" +msgstr "" + +#: cli/run.go:159 +msgid "force select language (supported: XXX)" +msgstr "" + +#: pkg/upstream/commandconn/commandconn.go:162 +#, c-format +msgid "command %v did not exit after %v: stderr=%q" +msgstr "" + +#: pkg/recipe/recipe.go:208 +#, c-format +msgid "abra.sh: %s}" +msgstr "" + +#: cli/app/services.go:22 +msgid "sr" +msgstr "" + +#: cli/recipe/upgrade.go:249 +#, c-format +msgid "upgrade to which tag? (service: %s, tag: %s)" +msgstr "" + +#: cli/recipe/upgrade.go:380 +msgid "list all tags, not just upgrades" +msgstr "" + +#: cli/app/upgrade.go:329 cli/app/upgrade.go:368 +#, c-format +msgid "parsing recipe version failed: %s" +msgstr "" + +#: cli/app/new.go:207 +msgid "SECRETS OVERVIEW" +msgstr "" + +#: cli/app/config.go:16 +msgid "config [flags]" +msgstr "" + +#: cli/app/list.go:216 cli/internal/deploy.go:76 +msgid "RECIPE" +msgstr "" + +#: cli/recipe/new.go:116 +msgid "N" +msgstr "" + +#: cli/recipe/lint.go:35 +msgid "satisfied" +msgstr "" + +#: pkg/upstream/convert/service.go:780 +#, c-format +msgid "unknown mode: %s" +msgstr "" + +#: cli/run.go:78 +#, c-format +msgid "abra version: %s, commit: %s, lang: %s" +msgstr "" + +#: cli/server/add.go:111 +#, c-format +msgid "%s successfully added" +msgstr "" + +#: pkg/upstream/container/hijack.go:156 +msgid "[hijack] End of stdin" +msgstr "" + +#: pkg/recipe/files.go:36 +#, c-format +msgid "%s release notes:" +msgstr "" + +#: pkg/git/push.go:40 +msgid "git tags pushed" +msgstr "" diff --git a/pkg/integration/integration.go b/pkg/integration/integration.go deleted file mode 100644 index bdb0a531..00000000 --- a/pkg/integration/integration.go +++ /dev/null @@ -1,12 +0,0 @@ -package integration - -import ( - "os" - "testing" -) - -func skipIfNotIntegration(t *testing.T) { - if os.Getenv("ABRA_INTEGRATION") == "" { - t.Skip("missing 'ABRA_INTEGRATION', not running integration tests") - } -} diff --git a/pkg/lang/lang.go b/pkg/lang/lang.go deleted file mode 100644 index a8f456e8..00000000 --- a/pkg/lang/lang.go +++ /dev/null @@ -1,30 +0,0 @@ -package lang - -import ( - "os" - "strings" -) - -func GetLocale() string { - if loc := os.Getenv("LC_MESSAGES"); loc != "" { - return NormalizeLocale(loc) - } - - if loc := os.Getenv("LANG"); loc != "" { - return NormalizeLocale(loc) - } - - return "C.UTF-8" -} - -func NormalizeLocale(loc string) string { - if idx := strings.Index(loc, "."); idx != -1 { - return loc[:idx] - } - - if idx := strings.Index(loc, "@"); idx != -1 { - return loc[:idx] - } - - return loc -} diff --git a/pkg/lint/recipe.go b/pkg/lint/recipe.go index 1855b6e2..82ef3eb8 100644 --- a/pkg/lint/recipe.go +++ b/pkg/lint/recipe.go @@ -1,11 +1,13 @@ package lint import ( + "errors" "fmt" "net/http" "os" "path" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" recipePkg "coopcloud.tech/abra/pkg/recipe" @@ -16,8 +18,8 @@ import ( ) var ( - Warn = "warn" - Critical = "critical" + Warn = i18n.G("warn") + Critical = i18n.G("critical") ) type LintFunction func(recipe.Recipe) (bool, error) @@ -47,10 +49,10 @@ func (l LintRule) Skip(recipe recipe.Recipe) bool { if l.SkipCondition != nil { ok, err := l.SkipCondition(recipe) if err != nil { - log.Debugf("%s: skip condition: %s", l.Ref, err) + log.Debug(i18n.G("%s: skip condition: %s", l.Ref, err)) } if ok { - log.Debugf("skipping %s based on skip condition", l.Ref) + log.Debug(i18n.G("skipping %s based on skip condition", l.Ref)) return true } } @@ -62,117 +64,117 @@ var LintRules = map[string][]LintRule{ "warn": { { Ref: "R001", - Level: "warn", - Description: "compose config has expected version", - HowToResolve: "ensure 'version: \"3.8\"' in compose configs", + Level: i18n.G("warn"), + Description: i18n.G("compose config has expected version"), + HowToResolve: i18n.G("ensure 'version: \"3.8\"' in compose configs"), Function: LintComposeVersion, }, { Ref: "R002", - Level: "warn", - Description: "healthcheck enabled for all services", - HowToResolve: "wire up healthchecks", + Level: i18n.G("warn"), + Description: i18n.G("healthcheck enabled for all services"), + HowToResolve: i18n.G("wire up healthchecks"), Function: LintHealthchecks, }, { Ref: "R003", - Level: "warn", - Description: "all images use a tag", - HowToResolve: "use a tag for all images", + Level: i18n.G("warn"), + Description: i18n.G("all images use a tag"), + HowToResolve: i18n.G("use a tag for all images"), Function: LintAllImagesTagged, }, { Ref: "R004", - Level: "warn", - Description: "no unstable tags", - HowToResolve: "tag all images with stable tags", + Level: i18n.G("warn"), + Description: i18n.G("no unstable tags"), + HowToResolve: i18n.G("tag all images with stable tags"), Function: LintNoUnstableTags, }, { Ref: "R005", - Level: "warn", - Description: "tags use semver-like format", - HowToResolve: "use semver-like tags", + Level: i18n.G("warn"), + Description: i18n.G("tags use semver-like format"), + HowToResolve: i18n.G("use semver-like tags"), Function: LintSemverLikeTags, }, { Ref: "R006", - Level: "warn", - Description: "has published catalogue version", - HowToResolve: "publish a recipe version to the catalogue", + Level: i18n.G("warn"), + Description: i18n.G("has published catalogue version"), + HowToResolve: i18n.G("publish a recipe version to the catalogue"), Function: LintHasPublishedVersion, }, { Ref: "R007", - Level: "warn", - Description: "README.md metadata filled in", - HowToResolve: "fill out all the metadata", + Level: i18n.G("warn"), + Description: i18n.G("README.md metadata filled in"), + HowToResolve: i18n.G("fill out all the metadata"), Function: LintMetadataFilledIn, }, { Ref: "R013", - Level: "warn", - Description: "git.coopcloud.tech repo exists", - HowToResolve: "upload your recipe to git.coopcloud.tech/coop-cloud/...", + Level: i18n.G("warn"), + Description: i18n.G("git.coopcloud.tech repo exists"), + HowToResolve: i18n.G("upload your recipe to git.coopcloud.tech/coop-cloud/..."), Function: LintHasRecipeRepo, }, { Ref: "R015", - Level: "warn", - Description: "long secret names", - HowToResolve: "reduce length of secret names to 12 chars", + Level: i18n.G("warn"), + Description: i18n.G("long secret names"), + HowToResolve: i18n.G("reduce length of secret names to 12 chars"), Function: LintSecretLengths, }, }, "error": { { Ref: "R008", - Level: "error", - Description: ".env.sample provided", - HowToResolve: "create an example .env.sample", + Level: i18n.G("error"), + Description: i18n.G(".env.sample provided"), + HowToResolve: i18n.G("create an example .env.sample"), Function: LintEnvConfigPresent, }, { Ref: "R009", - Level: "error", - Description: "one service named 'app'", - HowToResolve: "name a servce 'app'", + Level: i18n.G("error"), + Description: i18n.G("one service named 'app'"), + HowToResolve: i18n.G("name a servce 'app'"), Function: LintAppService, }, { Ref: "R015", - Level: "error", - Description: "deploy labels stanza present", - HowToResolve: "include \"deploy: labels: ...\" stanza", + Level: i18n.G("error"), + Description: i18n.G("deploy labels stanza present"), + HowToResolve: i18n.G("include \"deploy: labels: ...\" stanza"), Function: LintDeployLabelsPresent, }, { Ref: "R010", - Level: "error", - Description: "traefik routing enabled", - HowToResolve: "include \"traefik.enable=true\" deploy label", + Level: i18n.G("error"), + Description: i18n.G("traefik routing enabled"), + HowToResolve: i18n.G("include \"traefik.enable=true\" deploy label"), Function: LintTraefikEnabled, SkipCondition: LintTraefikEnabledSkipCondition, }, { Ref: "R011", - Level: "error", - Description: "all services have images", - HowToResolve: "ensure \"image: ...\" set on all services", + Level: i18n.G("error"), + Description: i18n.G("all services have images"), + HowToResolve: i18n.G("ensure \"image: ...\" set on all services"), Function: LintImagePresent, }, { Ref: "R012", - Level: "error", - Description: "config version are vendored", - HowToResolve: "vendor config versions in an abra.sh", + Level: i18n.G("error"), + Description: i18n.G("config version are vendored"), + HowToResolve: i18n.G("vendor config versions in an abra.sh"), Function: LintAbraShVendors, }, { Ref: "R014", - Level: "error", - Description: "only annotated tags used for recipe version", - HowToResolve: "replace lightweight tag with annotated tag", + Level: i18n.G("error"), + Description: i18n.G("only annotated tags used for recipe version"), + HowToResolve: i18n.G("replace lightweight tag with annotated tag"), Function: LintValidTags, }, }, @@ -182,9 +184,9 @@ var LintRules = map[string][]LintRule{ // used in code paths such as "app deploy" to avoid nasty surprises but not for // the typical linting commands, which do handle other levels. func LintForErrors(recipe recipe.Recipe) error { - log.Debugf("linting for critical errors in %s configs", recipe.Name) + log.Debug(i18n.G("linting for critical errors in %s configs", recipe.Name)) - var errors string + var errs string for level := range LintRules { if level != "error" { @@ -198,19 +200,19 @@ func LintForErrors(recipe recipe.Recipe) error { ok, err := rule.Function(recipe) if err != nil { - errors += fmt.Sprintf("\nlint %s: %s", rule.Ref, err) + errs += i18n.G("\nlint %s: %s", rule.Ref, err) } if !ok { - errors += fmt.Sprintf("\n * %s (%s)", rule.Description, rule.Ref) + errs += fmt.Sprintf("\n * %s (%s)", rule.Description, rule.Ref) } } } - if len(errors) > 0 { - return fmt.Errorf("recipe '%s' failed lint checks:\n"+errors[1:], recipe.Name) + if len(errs) > 0 { + return errors.New(i18n.G("recipe '%s' failed lint checks:\n%s", recipe.Name, errs[1:])) } - log.Debugf("linting successful, %s is well configured", recipe.Name) + log.Debug(i18n.G("linting successful, %s is well configured", recipe.Name)) return nil } @@ -256,7 +258,7 @@ func LintAppService(recipe recipe.Recipe) (bool, error) { func LintTraefikEnabledSkipCondition(r recipe.Recipe) (bool, error) { sampleEnv, err := r.SampleEnv() if err != nil { - return false, fmt.Errorf("Unable to discover .env.sample for %s", r.Name) + return false, errors.New(i18n.G("unable to discover .env.sample for %s", r.Name)) } if _, ok := sampleEnv["DOMAIN"]; !ok { @@ -476,7 +478,7 @@ func LintSecretLengths(recipe recipe.Recipe) (bool, error) { } for name := range config.Secrets { if len(name) > 12 { - return false, fmt.Errorf("secret %s is longer than 12 characters", name) + return false, errors.New(i18n.G("secret %s is longer than 12 characters", name)) } } @@ -486,12 +488,12 @@ func LintSecretLengths(recipe recipe.Recipe) (bool, error) { func LintValidTags(recipe recipe.Recipe) (bool, error) { repo, err := git.PlainOpen(recipe.Dir) if err != nil { - return false, fmt.Errorf("unable to open %s: %s", recipe.Dir, err) + return false, errors.New(i18n.G("unable to open %s: %s", recipe.Dir, err)) } iter, err := repo.Tags() if err != nil { - log.Fatalf("unable to list local tags for %s", recipe.Name) + log.Fatal(i18n.G("unable to list local tags for %s", recipe.Name)) } if err := iter.ForEach(func(ref *plumbing.Reference) error { @@ -499,7 +501,7 @@ func LintValidTags(recipe recipe.Recipe) (bool, error) { if err != nil { switch err { case plumbing.ErrObjectNotFound: - return fmt.Errorf("invalid lightweight tag detected") + return errors.New(i18n.G("invalid lightweight tag detected")) default: return err } diff --git a/pkg/logs/logs.go b/pkg/logs/logs.go index 0820d9dc..d1bf9bb3 100644 --- a/pkg/logs/logs.go +++ b/pkg/logs/logs.go @@ -3,6 +3,7 @@ package logs import ( "bufio" "context" + "errors" "fmt" "io" "os" @@ -13,6 +14,7 @@ import ( containerTypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" dockerClient "github.com/docker/docker/client" + "coopcloud.tech/abra/pkg/i18n" ) type TailOpts struct { @@ -81,7 +83,7 @@ func TailLogs( } if _, err = io.Copy(os.Stdout, logs); err != nil && err != io.EOF { - errCh <- fmt.Errorf("tailLogs: unable to copy buffer: %s", err) + errCh <- errors.New(i18n.G("tailLogs: unable to copy buffer: %s", err)) } } }(service.ID) diff --git a/pkg/recipe/compose.go b/pkg/recipe/compose.go index 736e5f70..88c7d0c5 100644 --- a/pkg/recipe/compose.go +++ b/pkg/recipe/compose.go @@ -1,6 +1,7 @@ package recipe import ( + "errors" "fmt" "io/ioutil" "os" @@ -13,6 +14,7 @@ import ( loader "coopcloud.tech/abra/pkg/upstream/stack" "github.com/distribution/reference" composetypes "github.com/docker/cli/cli/compose/types" + "coopcloud.tech/abra/pkg/i18n" ) // GetComposeFiles gets the list of compose files for an app (or recipe if you @@ -24,7 +26,7 @@ func (r Recipe) GetComposeFiles(appEnv map[string]string) ([]string, error) { if err := ensurePathExists(r.ComposePath); err != nil { return []string{}, err } - log.Debugf("no COMPOSE_FILE detected, loading default: %s", r.ComposePath) + log.Debug(i18n.G("no COMPOSE_FILE detected, loading default: %s", r.ComposePath)) return []string{r.ComposePath}, nil } @@ -33,7 +35,7 @@ func (r Recipe) GetComposeFiles(appEnv map[string]string) ([]string, error) { if err := ensurePathExists(path); err != nil { return []string{}, err } - log.Debugf("COMPOSE_FILE detected, loading %s", path) + log.Debug(i18n.G("COMPOSE_FILE detected, loading %s", path)) return []string{path}, nil } @@ -42,7 +44,7 @@ func (r Recipe) GetComposeFiles(appEnv map[string]string) ([]string, error) { numComposeFiles := strings.Count(composeFileEnvVar, ":") + 1 envVars := strings.SplitN(composeFileEnvVar, ":", numComposeFiles) if len(envVars) != numComposeFiles { - return composeFiles, fmt.Errorf("COMPOSE_FILE (=\"%s\") parsing failed?", composeFileEnvVar) + return composeFiles, errors.New(i18n.G("COMPOSE_FILE (=\"%s\") parsing failed?", composeFileEnvVar)) } for _, file := range envVars { @@ -53,8 +55,8 @@ func (r Recipe) GetComposeFiles(appEnv map[string]string) ([]string, error) { composeFiles = append(composeFiles, path) } - log.Debugf("COMPOSE_FILE detected (%s), loading %s", composeFileEnvVar, strings.Join(envVars, ", ")) - log.Debugf("retrieved %s configs for %s", strings.Join(composeFiles, ", "), r.Name) + log.Debug(i18n.G("COMPOSE_FILE detected (%s), loading %s", composeFileEnvVar, strings.Join(envVars, ", "))) + log.Debug(i18n.G("retrieved %s configs for %s", strings.Join(composeFiles, ", "), r.Name)) return composeFiles, nil } @@ -67,7 +69,7 @@ func (r Recipe) GetComposeConfig(env map[string]string) (*composetypes.Config, e } if len(composeFiles) == 0 { - return nil, fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", r.Name) + return nil, errors.New(i18n.G("%s is missing a compose.yml or compose.*.yml file?", r.Name)) } if env == nil { @@ -102,7 +104,7 @@ func (r Recipe) GetVersionLabelLocal() (string, error) { } if label == "" { - return label, fmt.Errorf("%s has no version label? try running \"abra recipe sync %s\" first?", r.Name, r.Name) + return label, errors.New(i18n.G("%s has no version label? try running \"abra recipe sync %s\" first?", r.Name, r.Name)) } return label, nil @@ -118,7 +120,7 @@ func (r Recipe) UpdateTag(image, tag string) (bool, error) { return false, err } - log.Debugf("considering %s config(s) for tag update", strings.Join(composeFiles, ", ")) + log.Debug(i18n.G("considering %s config(s) for tag update", strings.Join(composeFiles, ", "))) for _, composeFile := range composeFiles { opts := stack.Deploy{Composefiles: []string{composeFile}} @@ -148,13 +150,13 @@ func (r Recipe) UpdateTag(image, tag string) (bool, error) { case reference.NamedTagged: composeTag = img.(reference.NamedTagged).Tag() default: - log.Debugf("unable to parse %s, skipping", img) + log.Debug(i18n.G("unable to parse %s, skipping", img)) continue } composeImage := formatter.StripTagMeta(reference.Path(img)) - log.Debugf("parsed %s from %s", composeTag, service.Image) + log.Debug(i18n.G("parsed %s from %s", composeTag, service.Image)) if image == composeImage { bytes, err := ioutil.ReadFile(composeFile) @@ -166,7 +168,7 @@ func (r Recipe) UpdateTag(image, tag string) (bool, error) { new := fmt.Sprintf("%s:%s", composeImage, tag) replacedBytes := strings.Replace(string(bytes), old, new, -1) - log.Debugf("updating %s to %s in %s", old, new, compose.Filename) + log.Debug(i18n.G("updating %s to %s in %s", old, new, compose.Filename)) if err := os.WriteFile(compose.Filename, []byte(replacedBytes), 0o764); err != nil { return false, err @@ -186,7 +188,7 @@ func (r Recipe) UpdateLabel(pattern, serviceName, label string) error { return err } - log.Debugf("considering %s config(s) for label update", strings.Join(composeFiles, ", ")) + log.Debug(i18n.G("considering %s config(s) for label update", strings.Join(composeFiles, ", "))) for _, composeFile := range composeFiles { opts := stack.Deploy{Composefiles: []string{composeFile}} @@ -224,27 +226,27 @@ func (r Recipe) UpdateLabel(pattern, serviceName, label string) error { return err } - old := fmt.Sprintf("coop-cloud.${STACK_NAME}.version=%s", value) + old := i18n.G("coop-cloud.${STACK_NAME}.version=%s", value) replacedBytes := strings.Replace(string(bytes), old, label, -1) if old == label { - log.Warnf("%s is already set, nothing to do?", label) + log.Warnf(i18n.G("%s is already set, nothing to do?", label)) return nil } - log.Debugf("updating %s to %s in %s", old, label, compose.Filename) + log.Debug(i18n.G("updating %s to %s in %s", old, label, compose.Filename)) if err := ioutil.WriteFile(compose.Filename, []byte(replacedBytes), 0o764); err != nil { return err } - log.Infof("synced label %s to service %s", label, serviceName) + log.Infof(i18n.G("synced label %s to service %s", label, serviceName)) } } if !discovered { - log.Warn("no existing label found, automagic insertion not supported yet") - log.Fatalf("add '- \"%s\"' manually to the 'app' service in %s", label, composeFile) + log.Warn(i18n.G("no existing label found, automagic insertion not supported yet")) + log.Fatal(i18n.G("add '- \"%s\"' manually to the 'app' service in %s", label, composeFile)) } } diff --git a/pkg/recipe/files.go b/pkg/recipe/files.go index d3408fa4..cfd16942 100644 --- a/pkg/recipe/files.go +++ b/pkg/recipe/files.go @@ -1,18 +1,20 @@ package recipe import ( + "errors" "fmt" "os" "path" "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" ) func (r Recipe) SampleEnv() (map[string]string, error) { sampleEnv, err := envfile.ReadEnv(r.SampleEnvPath) if err != nil { - return sampleEnv, fmt.Errorf("unable to discover .env.sample for %s", r.Name) + return sampleEnv, errors.New(i18n.G("unable to discover .env.sample for %s", r.Name)) } return sampleEnv, nil } @@ -31,7 +33,7 @@ func (r Recipe) GetReleaseNotes(version string) (string, error) { return "", err } - title := formatter.BoldStyle.Render(fmt.Sprintf("%s release notes:", version)) + title := formatter.BoldStyle.Render(i18n.G("%s release notes:", version)) withTitle := fmt.Sprintf("%s\n%s\n", title, releaseNotes) return withTitle, nil diff --git a/pkg/recipe/git.go b/pkg/recipe/git.go index e430d71a..e27e0b8b 100644 --- a/pkg/recipe/git.go +++ b/pkg/recipe/git.go @@ -1,6 +1,7 @@ package recipe import ( + "errors" "fmt" "os" "slices" @@ -15,6 +16,7 @@ import ( "github.com/distribution/reference" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" + "coopcloud.tech/abra/pkg/i18n" ) type EnsureContext struct { @@ -45,9 +47,9 @@ func (r Recipe) Ensure(ctx EnsureContext) error { } if r.EnvVersion != "" && !ctx.IgnoreEnvVersion { - log.Debugf("ensuring env version %s", r.EnvVersion) + log.Debug(i18n.G("ensuring env version %s", r.EnvVersion)) if strings.Contains(r.EnvVersion, "+U") { - return fmt.Errorf("can not redeploy chaos version (%s) without --chaos", r.EnvVersion) + return errors.New(i18n.G("can not redeploy chaos version (%s) without --chaos", r.EnvVersion)) } if _, err := r.EnsureVersion(r.EnvVersion); err != nil { @@ -146,16 +148,16 @@ func (r Recipe) EnsureVersion(version string) (bool, error) { joinedTags := strings.Join(parsedTags, ", ") if joinedTags != "" { - log.Debugf("read %s as tags for recipe %s", joinedTags, r.Name) + log.Debug(i18n.G("read %s as tags for recipe %s", joinedTags, r.Name)) } var opts *git.CheckoutOptions if tagRef.String() == "" { - log.Debugf("attempting to checkout '%s' as chaos commit", version) + log.Debug(i18n.G("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) + log.Fatal(i18n.G("unable to resolve '%s': %s", version, err)) } opts = &git.CheckoutOptions{Hash: *hash, Create: false, Force: true} @@ -173,7 +175,7 @@ func (r Recipe) EnsureVersion(version string) (bool, error) { return isChaosCommit, nil } - log.Debugf("successfully checked %s out to %s in %s", r.Name, tagRef.Short(), r.Dir) + log.Debug(i18n.G("successfully checked %s out to %s in %s", r.Name, tagRef.Short(), r.Dir)) return isChaosCommit, nil } @@ -182,11 +184,11 @@ func (r Recipe) EnsureVersion(version string) (bool, error) { func (r Recipe) EnsureIsClean() error { isClean, err := gitPkg.IsClean(r.Dir) if err != nil { - return fmt.Errorf("unable to check git clean status in %s: %s", r.Dir, err) + return errors.New(i18n.G("unable to check git clean status in %s: %s", r.Dir, err)) } if !isClean { - return fmt.Errorf("%s (%s) has locally unstaged changes?", r.Name, r.Dir) + return errors.New(i18n.G("%s (%s) has locally unstaged changes?", r.Name, r.Dir)) } return nil @@ -220,7 +222,7 @@ func (r Recipe) EnsureLatest() error { } if err := worktree.Checkout(checkOutOpts); err != nil { - log.Debugf("failed to check out %s in %s", branch, r.Dir) + log.Debug(i18n.G("failed to check out %s in %s", branch, r.Dir)) return err } @@ -231,33 +233,33 @@ func (r Recipe) EnsureLatest() error { func (r Recipe) EnsureUpToDate() error { repo, err := git.PlainOpen(r.Dir) if err != nil { - return fmt.Errorf("unable to open %s: %s", r.Dir, err) + return errors.New(i18n.G("unable to open %s: %s", r.Dir, err)) } remotes, err := repo.Remotes() if err != nil { - return fmt.Errorf("unable to read remotes in %s: %s", r.Dir, err) + return errors.New(i18n.G("unable to read remotes in %s: %s", r.Dir, err)) } if len(remotes) == 0 { - log.Debugf("cannot ensure %s is up-to-date, no git remotes configured", r.Name) + log.Debug(i18n.G("cannot ensure %s is up-to-date, no git remotes configured", r.Name)) return nil } worktree, err := repo.Worktree() if err != nil { - return fmt.Errorf("unable to open git work tree in %s: %s", r.Dir, err) + return errors.New(i18n.G("unable to open git work tree in %s: %s", r.Dir, err)) } branch, err := gitPkg.CheckoutDefaultBranch(repo, r.Dir) if err != nil { - return fmt.Errorf("unable to check out default branch in %s: %s", r.Dir, err) + return errors.New(i18n.G("unable to check out default branch in %s: %s", r.Dir, err)) } fetchOpts := &git.FetchOptions{Tags: git.AllTags} if err := repo.Fetch(fetchOpts); err != nil { if !strings.Contains(err.Error(), "already up-to-date") { - return fmt.Errorf("unable to fetch tags in %s: %s", r.Dir, err) + return errors.New(i18n.G("unable to fetch tags in %s: %s", r.Dir, err)) } } @@ -269,11 +271,11 @@ func (r Recipe) EnsureUpToDate() error { if err := worktree.Pull(opts); err != nil { if !strings.Contains(err.Error(), "already up-to-date") { - return fmt.Errorf("unable to git pull in %s: %s", r.Dir, err) + return errors.New(i18n.G("unable to git pull in %s: %s", r.Dir, err)) } } - log.Debugf("fetched latest git changes for %s", r.Name) + log.Debug(i18n.G("fetched latest git changes for %s", r.Name)) return nil } @@ -362,7 +364,7 @@ func (r Recipe) Tags() ([]string, error) { return version1.IsLessThan(version2) }) - log.Debugf("detected %s as tags for recipe %s", strings.Join(tags, ", "), r.Name) + log.Debug(i18n.G("detected %s as tags for recipe %s", strings.Join(tags, ", "), r.Name)) return tags, nil } @@ -373,7 +375,7 @@ func (r Recipe) GetRecipeVersions() (RecipeVersions, []string, error) { versions := RecipeVersions{} - log.Debugf("git: opening repository in %s", r.Dir) + log.Debug(i18n.G("git: opening repository in %s", r.Dir)) repo, err := git.PlainOpen(r.Dir) if err != nil { @@ -393,7 +395,7 @@ func (r Recipe) GetRecipeVersions() (RecipeVersions, []string, error) { if err := gitTags.ForEach(func(ref *plumbing.Reference) (err error) { tag := strings.TrimPrefix(string(ref.Name()), "refs/tags/") - log.Debugf("processing %s for %s", tag, r.Name) + log.Debug(i18n.G("processing %s for %s", tag, r.Name)) checkOutOpts := &git.CheckoutOptions{ Create: false, @@ -401,11 +403,11 @@ func (r Recipe) GetRecipeVersions() (RecipeVersions, []string, error) { Branch: plumbing.ReferenceName(ref.Name()), } if err := worktree.Checkout(checkOutOpts); err != nil { - log.Debugf("failed to check out %s in %s", tag, r.Dir) + log.Debug(i18n.G("failed to check out %s in %s", tag, r.Dir)) return err } - log.Debugf("git checkout: %s in %s", ref.Name(), r.Dir) + log.Debug(i18n.G("git checkout: %s in %s", ref.Name(), r.Dir)) config, err := r.GetComposeConfig(nil) if err != nil { @@ -429,7 +431,7 @@ func (r Recipe) GetRecipeVersions() (RecipeVersions, []string, error) { case reference.NamedTagged: tag = img.(reference.NamedTagged).Tag() case reference.Named: - warnMsg = append(warnMsg, fmt.Sprintf("%s service is missing image tag?", path)) + warnMsg = append(warnMsg, i18n.G("%s service is missing image tag?", path)) continue } @@ -453,7 +455,7 @@ func (r Recipe) GetRecipeVersions() (RecipeVersions, []string, error) { sortRecipeVersions(versions) - log.Debugf("collected %s for %s", versions, r.Dir) + log.Debug(i18n.G("collected %s for %s", versions, r.Dir)) var uniqueWarnings []string for _, w := range warnMsg { diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 728fadca..819cd136 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/go-git/go-git/v5" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/catalogue" "coopcloud.tech/abra/pkg/config" @@ -70,7 +71,7 @@ func (r RecipeMeta) LatestVersion() string { version = tag } - log.Debugf("choosing %s as latest version of %s", version, r.Name) + log.Debug(i18n.G("choosing %s as latest version of %s", version, r.Name)) return version } @@ -126,7 +127,7 @@ func Get(name string) Recipe { if strings.Contains(name, ":") { split := strings.Split(name, ":") if len(split) > 2 { - log.Fatalf("version seems invalid: %s", name) + log.Fatal(i18n.G("version seems invalid: %s", name)) } name = split[0] @@ -134,7 +135,7 @@ func Get(name string) Recipe { versionRaw = version if strings.HasSuffix(version, config.DIRTY_DEFAULT) { version = strings.Replace(split[1], config.DIRTY_DEFAULT, "", 1) - log.Debugf("removed dirty suffix from .env version: %s -> %s", split[1], version) + log.Debug(i18n.G("removed dirty suffix from .env version: %s -> %s", split[1], version)) } } @@ -143,7 +144,7 @@ func Get(name string) Recipe { if strings.Contains(name, "/") { u, err := url.Parse(name) if err != nil { - log.Fatalf("invalid recipe: %s", err) + log.Fatal(i18n.G("invalid recipe: %s", err)) } u.Scheme = "https" gitURL = u.String() + ".git" @@ -171,7 +172,7 @@ func Get(name string) Recipe { dirty, err := r.IsDirty() if err != nil && !errors.Is(err, git.ErrRepositoryNotExists) { - log.Fatalf("failed to check git status of %s: %s", r.Name, err) + log.Fatal(i18n.G("failed to check git status of %s: %s", r.Name, err)) } r.Dirty = dirty @@ -195,16 +196,16 @@ type Recipe struct { // String outputs a human-friendly string representation. func (r Recipe) String() string { - out := fmt.Sprintf("{name: %s, ", r.Name) - out += fmt.Sprintf("version : %s, ", r.EnvVersion) - out += fmt.Sprintf("dirty: %v, ", r.Dirty) - out += fmt.Sprintf("dir: %s, ", r.Dir) - out += fmt.Sprintf("git url: %s, ", r.GitURL) - out += fmt.Sprintf("ssh url: %s, ", r.SSHURL) - out += fmt.Sprintf("compose: %s, ", r.ComposePath) - out += fmt.Sprintf("readme: %s, ", r.ReadmePath) - out += fmt.Sprintf("sample env: %s, ", r.SampleEnvPath) - out += fmt.Sprintf("abra.sh: %s}", r.AbraShPath) + out := i18n.G("{name: %s, ", r.Name) + out += i18n.G("version : %s, ", r.EnvVersion) + out += i18n.G("dirty: %v, ", r.Dirty) + out += i18n.G("dir: %s, ", r.Dir) + out += i18n.G("git url: %s, ", r.GitURL) + out += i18n.G("ssh url: %s, ", r.SSHURL) + out += i18n.G("compose: %s, ", r.ComposePath) + out += i18n.G("readme: %s, ", r.ReadmePath) + out += i18n.G("sample env: %s, ", r.SampleEnvPath) + out += i18n.G("abra.sh: %s}", r.AbraShPath) return out } @@ -233,7 +234,7 @@ func GetRecipeFeaturesAndCategory(r Recipe) (Features, string, []string, error) feat = Features{} ) - log.Debugf("%s: attempt recipe metadata parse", r.ReadmePath) + log.Debug(i18n.G("%s: attempt recipe metadata parse", r.ReadmePath)) readmeFS, err := ioutil.ReadFile(r.ReadmePath) if err != nil { @@ -321,12 +322,12 @@ func GetImageMetadata(imageRowString, recipeName string) (Image, []string, error if imageRowString != "" { warnMsgs = append( warnMsgs, - fmt.Sprintf("%s: image meta has incorrect format: %s", recipeName, imageRowString), + i18n.G("%s: image meta has incorrect format: %s", recipeName, imageRowString), ) } else { warnMsgs = append( warnMsgs, - fmt.Sprintf("%s: image meta is empty?", recipeName), + i18n.G("%s: image meta is empty?", recipeName), ) } @@ -357,14 +358,14 @@ func GetImageMetadata(imageRowString, recipeName string) (Image, []string, error func GetStringInBetween(recipeName, str, start, end string) (result string, err error) { s := strings.Index(str, start) if s == -1 { - return "", fmt.Errorf("%s: marker string %s not found", recipeName, start) + return "", errors.New(i18n.G("%s: marker string %s not found", recipeName, start)) } s += len(start) e := strings.Index(str[s:], end) if e == -1 { - return "", fmt.Errorf("%s: end marker %s not found", recipeName, end) + return "", errors.New(i18n.G("%s: end marker %s not found", recipeName, end)) } return str[s : s+e], nil @@ -402,7 +403,7 @@ func readRecipeCatalogueFS(target interface{}) error { return err } - log.Debugf("read recipe catalogue from file system cache in %s", config.RECIPES_JSON) + log.Debug(i18n.G("read recipe catalogue from file system cache in %s", config.RECIPES_JSON)) return nil } @@ -431,7 +432,7 @@ func VersionsOfService(recipe, serviceName string, offline bool) ([]string, erro } } - log.Debugf("detected versions %s for %s", strings.Join(versions, ", "), recipe) + log.Debug(i18n.G("detected versions %s for %s", strings.Join(versions, ", "), recipe)) return versions, nil } @@ -454,11 +455,11 @@ func GetRecipeMeta(recipeName string, offline bool) (RecipeMeta, error) { recipeMeta, ok := catl[recipeName] if !ok { return RecipeMeta{}, RecipeMissingFromCatalogue{ - err: fmt.Sprintf("recipe %s does not exist?", recipeName), + err: i18n.G("recipe %s does not exist?", recipeName), } } - log.Debugf("recipe metadata retrieved for %s", recipeName) + log.Debug(i18n.G("recipe metadata retrieved for %s", recipeName)) return recipeMeta, nil } @@ -545,13 +546,13 @@ func ReadReposMetadata(debug bool) (RepoCatalogue, error) { reposMeta := make(RepoCatalogue) pageIdx := 1 - bar := formatter.CreateProgressbar(-1, "collecting recipe listing") + bar := formatter.CreateProgressbar(-1, i18n.G("collecting recipe listing")) for { var reposList []RepoMeta pagedURL := fmt.Sprintf("%s?page=%v", ReposMetadataURL, pageIdx) - log.Debugf("fetching repo metadata from %s", pagedURL) + log.Debug(i18n.G("fetching repo metadata from %s", pagedURL)) if err := web.ReadJSON(pagedURL, &reposList); err != nil { return reposMeta, err @@ -655,7 +656,7 @@ func UpdateRepositories(repos RepoCatalogue, recipeName string, debug bool) erro cloneLimiter := limit.New(3) - retrieveBar := formatter.CreateProgressbar(barLength, "retrieving recipes") + retrieveBar := formatter.CreateProgressbar(barLength, i18n.G("retrieving recipes")) ch := make(chan string, barLength) for _, repoMeta := range repos { go func(rm RepoMeta) { diff --git a/pkg/secret/pass.go b/pkg/secret/pass.go index 1763e1f4..83b0926e 100644 --- a/pkg/secret/pass.go +++ b/pkg/secret/pass.go @@ -5,13 +5,14 @@ import ( "fmt" "os/exec" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" ) // PassInsertSecret inserts a secret into a pass store. func PassInsertSecret(secretValue, secretName, appName, server string) error { if _, err := exec.LookPath("pass"); err != nil { - return errors.New("pass command not found on $PATH, is it installed?") + return errors.New(i18n.G("pass command not found on $PATH, is it installed?")) } cmd := fmt.Sprintf( @@ -19,13 +20,13 @@ func PassInsertSecret(secretValue, secretName, appName, server string) error { secretValue, server, appName, secretName, ) - log.Debugf("attempting to run %s", cmd) + log.Debug(i18n.G("attempting to run %s", cmd)) if err := exec.Command("bash", "-c", cmd).Run(); err != nil { return err } - log.Infof("%s inserted into pass store", secretName) + log.Info(i18n.G("%s inserted into pass store", secretName)) return nil } @@ -33,7 +34,7 @@ func PassInsertSecret(secretValue, secretName, appName, server string) error { // PassRmSecret deletes a secret from a pass store. func PassRmSecret(secretName, appName, server string) error { if _, err := exec.LookPath("pass"); err != nil { - return errors.New("pass command not found on $PATH, is it installed?") + return errors.New(i18n.G("pass command not found on $PATH, is it installed?")) } cmd := fmt.Sprintf( @@ -41,13 +42,13 @@ func PassRmSecret(secretName, appName, server string) error { server, appName, secretName, ) - log.Debugf("attempting to run %s", cmd) + log.Debug(i18n.G("attempting to run %s", cmd)) if err := exec.Command("bash", "-c", cmd).Run(); err != nil { return err } - log.Infof("%s removed from pass store", secretName) + log.Info(i18n.G("%s removed from pass store", secretName)) return nil } diff --git a/pkg/secret/secret.go b/pkg/secret/secret.go index f8366c7b..2f9c9529 100644 --- a/pkg/secret/secret.go +++ b/pkg/secret/secret.go @@ -5,6 +5,7 @@ package secret import ( "context" + "errors" "fmt" "slices" "strconv" @@ -15,6 +16,7 @@ import ( "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/envfile" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/upstream/stack" loader "coopcloud.tech/abra/pkg/upstream/stack" @@ -57,7 +59,7 @@ func GeneratePassword(length uint, charset string) (string, error) { return "", err } - log.Debugf("generated %s", strings.Join(passwords, ", ")) + log.Debug(i18n.G("generated %s", strings.Join(passwords, ", "))) return passwords[0], nil } @@ -75,7 +77,7 @@ func GeneratePassphrase() (string, error) { return "", err } - log.Debugf("generated %s", strings.Join(passphrases, ", ")) + log.Debug(i18n.G("generated %s", strings.Join(passphrases, ", "))) return passphrases[0], nil } @@ -114,18 +116,18 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin } if len(enabledSecrets) == 0 { - log.Debugf("not generating app secrets, none enabled in recipe config") + log.Debug(i18n.G("not generating app secrets, none enabled in recipe config")) return nil, nil } secretValues := map[string]Secret{} for secretId, secretConfig := range composeConfig.Secrets { if string(secretConfig.Name[len(secretConfig.Name)-1]) == "_" { - return nil, fmt.Errorf("missing version for secret? (%s)", secretId) + return nil, errors.New(i18n.G("missing version for secret? (%s)", secretId)) } if !(slices.Contains(enabledSecrets, secretId)) { - log.Warnf("%s not enabled in recipe config, skipping", secretId) + log.Warnf(i18n.G("%s not enabled in recipe config, skipping", secretId)) continue } @@ -134,7 +136,7 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin value := Secret{Version: secretVersion, RemoteName: secretConfig.Name} if len(value.RemoteName) > config.MAX_DOCKER_SECRET_LENGTH { - return nil, fmt.Errorf("secret %s is > %d chars when combined with %s", secretId, config.MAX_DOCKER_SECRET_LENGTH, stackName) + return nil, errors.New(i18n.G("secret %s is > %d chars when combined with %s", secretId, config.MAX_DOCKER_SECRET_LENGTH, stackName)) } // Check if the length modifier is set for this secret. @@ -202,12 +204,12 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server defer wg.Done() if secret.SkipGenerate { - log.Debugf("skipping generation of %s (generate=false)", secretName) + log.Debug(i18n.G("skipping generation of %s (generate=false)", secretName)) ch <- nil return } - log.Debugf("attempting to generate and store %s on %s", secret.RemoteName, server) + log.Debug(i18n.G("attempting to generate and store %s on %s", secret.RemoteName, server)) if secret.Length > 0 { password, err := GeneratePassword(uint(secret.Length), secret.Charset) @@ -218,7 +220,7 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server if err := client.StoreSecret(cl, secret.RemoteName, password, server); err != nil { if strings.Contains(err.Error(), "AlreadyExists") { - log.Warnf("%s already exists", secret.RemoteName) + log.Warnf(i18n.G("%s already exists", secret.RemoteName)) ch <- nil } else { ch <- err @@ -238,7 +240,7 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server if err := client.StoreSecret(cl, secret.RemoteName, passphrase, server); err != nil { if strings.Contains(err.Error(), "AlreadyExists") { - log.Warnf("%s already exists", secret.RemoteName) + log.Warnf(i18n.G("%s already exists", secret.RemoteName)) ch <- nil } else { ch <- err @@ -263,7 +265,7 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server } } - log.Debugf("generated and stored %v on %s", secrets, server) + log.Debug(i18n.G("generated and stored %v on %s", secrets, server)) return secretsGenerated, nil } diff --git a/pkg/server/server.go b/pkg/server/server.go index 8f723a69..c312209d 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -6,6 +6,7 @@ import ( "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/log" + "coopcloud.tech/abra/pkg/i18n" ) // CreateServerDir creates a server directory under ~/.abra. @@ -17,11 +18,11 @@ func CreateServerDir(serverName string) error { return err } - log.Debugf("%s already exists", serverPath) + log.Debug(i18n.G("%s already exists", serverPath)) return nil } - log.Debugf("successfully created %s", serverPath) + log.Debug(i18n.G("successfully created %s", serverPath)) return nil } diff --git a/pkg/service/service.go b/pkg/service/service.go index 32d1f8f6..c0eef8a6 100644 --- a/pkg/service/service.go +++ b/pkg/service/service.go @@ -2,10 +2,12 @@ package service import ( "context" + "errors" "fmt" "strings" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/AlecAivazis/survey/v2" "github.com/docker/docker/api/types" @@ -25,7 +27,7 @@ func GetServiceByLabel(c context.Context, cl *client.Client, label string, promp } if len(services) == 0 { - return swarm.Service{}, fmt.Errorf("no services deployed?") + return swarm.Service{}, errors.New(i18n.G("no services deployed?")) } var matchingServices []swarm.Service @@ -36,7 +38,7 @@ func GetServiceByLabel(c context.Context, cl *client.Client, label string, promp } if len(matchingServices) == 0 { - return swarm.Service{}, fmt.Errorf("no services deployed matching label '%s'?", label) + return swarm.Service{}, errors.New(i18n.G("no services deployed matching label '%s'?", label)) } if len(matchingServices) > 1 { @@ -48,15 +50,15 @@ func GetServiceByLabel(c context.Context, cl *client.Client, label string, promp } if !prompt { - err := fmt.Errorf("expected 1 service but found %v: %s", len(matchingServices), strings.Join(servicesRaw, " ")) + err := errors.New(i18n.G("expected 1 service but found %v: %s", len(matchingServices), strings.Join(servicesRaw, " "))) return swarm.Service{}, err } - log.Warnf("ambiguous service list received, prompting for input") + log.Warn(i18n.G("ambiguous service list received, prompting for input")) var response string prompt := &survey.Select{ - Message: "which service are you looking for?", + Message: i18n.G("which service are you looking for?"), Options: servicesRaw, } @@ -72,7 +74,7 @@ func GetServiceByLabel(c context.Context, cl *client.Client, label string, promp } } - log.Fatal("failed to match chosen service") + log.Fatal(i18n.G("failed to match chosen service")) } return matchingServices[0], nil @@ -90,7 +92,7 @@ func GetService(c context.Context, cl *client.Client, filters filters.Args, prom if len(services) == 0 { filter := filters.Get("name")[0] - return swarm.Service{}, fmt.Errorf("no services matching the %v filter found?", filter) + return swarm.Service{}, errors.New(i18n.G("no services matching the %v filter found?", filter)) } if len(services) != 1 { @@ -98,19 +100,19 @@ func GetService(c context.Context, cl *client.Client, filters filters.Args, prom for _, service := range services { serviceName := service.Spec.Name created := formatter.HumanDuration(service.CreatedAt.Unix()) - servicesRaw = append(servicesRaw, fmt.Sprintf("%s (created %v)", serviceName, created)) + servicesRaw = append(servicesRaw, i18n.G("%s (created %v)", serviceName, created)) } if !prompt { - err := fmt.Errorf("expected 1 service but found %v: %s", len(services), strings.Join(servicesRaw, " ")) + err := errors.New(i18n.G("expected 1 service but found %v: %s", len(services), strings.Join(servicesRaw, " "))) return swarm.Service{}, err } - log.Warnf("ambiguous service list received, prompting for input") + log.Warn(i18n.G("ambiguous service list received, prompting for input")) var response string prompt := &survey.Select{ - Message: "which service are you looking for?", + Message: i18n.G("which service are you looking for?"), Options: servicesRaw, } @@ -126,7 +128,7 @@ func GetService(c context.Context, cl *client.Client, filters filters.Args, prom } } - log.Fatal("failed to match chosen service") + log.Fatal(i18n.G("failed to match chosen service")) } return services[0], nil diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index 96489f43..99a46efb 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -1,8 +1,10 @@ package ssh import ( - "fmt" + "errors" "strings" + + "coopcloud.tech/abra/pkg/i18n" ) // Fatal is a error output wrapper which aims to make SSH failures easier to @@ -11,17 +13,17 @@ func Fatal(hostname string, err error) error { out := err.Error() if strings.Contains(out, "Host key verification failed.") { - return fmt.Errorf("SSH host key verification failed for %s", hostname) + return errors.New(i18n.G("SSH host key verification failed for %s", hostname)) } else if strings.Contains(out, "Could not resolve hostname") { - return fmt.Errorf("could not resolve hostname for %s", hostname) + return errors.New(i18n.G("could not resolve hostname for %s", hostname)) } else if strings.Contains(out, "Connection timed out") { - return fmt.Errorf("connection timed out for %s", hostname) + return errors.New(i18n.G("connection timed out for %s", hostname)) } else if strings.Contains(out, "Permission denied") { - return fmt.Errorf("ssh auth: permission denied for %s", hostname) + return errors.New(i18n.G("ssh auth: permission denied for %s", hostname)) } else if strings.Contains(out, "Network is unreachable") { - return fmt.Errorf("unable to connect to %s, please check your SSH config", hostname) + return errors.New(i18n.G("unable to connect to %s, please check your SSH config", hostname)) } else if strings.Contains(out, "Is the docker daemon running") { - return fmt.Errorf("docker: is the daemon running / your user has docker permissions?") + return errors.New(i18n.G("docker: is the daemon running / your user has docker permissions?")) } return err diff --git a/pkg/ui/deploy.go b/pkg/ui/deploy.go index 5b3a8ea8..20a8c87a 100644 --- a/pkg/ui/deploy.go +++ b/pkg/ui/deploy.go @@ -3,13 +3,13 @@ package ui import ( "context" "encoding/json" - "fmt" "io" "sort" "strings" "time" "coopcloud.tech/abra/pkg/formatter" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/logs" tea "github.com/charmbracelet/bubbletea" "github.com/docker/cli/cli/command/service/progress" @@ -79,13 +79,13 @@ type stream struct { } func (s stream) String() string { - out := fmt.Sprintf("{decoder: %v, ", s.decoder) - out += fmt.Sprintf("err: %v, ", s.Err) - out += fmt.Sprintf("id: %s, ", s.id) - out += fmt.Sprintf("name: %s, ", s.Name) - out += fmt.Sprintf("reader: %v, ", s.reader) - out += fmt.Sprintf("writer: %v, ", s.writer) - out += fmt.Sprintf("status: %s, ", s.status) + out := i18n.G("{decoder: %v, ", s.decoder) + out += i18n.G("err: %v, ", s.Err) + out += i18n.G("id: %s, ", s.id) + out += i18n.G("name: %s, ", s.Name) + out += i18n.G("reader: %v, ", s.reader) + out += i18n.G("writer: %v, ", s.writer) + out += i18n.G("status: %s}", s.status) return out } @@ -118,7 +118,7 @@ func (s stream) process() tea.Msg { func (s stream) healthcheck(m Model) tea.Msg { filters := filters.NewArgs() - filters.Add("name", fmt.Sprintf("^%s", s.Name)) + filters.Add("name", i18n.G("^%s", s.Name)) containers, err := m.cl.ContainerList(m.ctx, containerTypes.ListOptions{Filters: filters}) if err != nil { @@ -327,10 +327,10 @@ func (m Model) View() string { status := stream.status if strings.Contains(stream.status, "converged") && !stream.rollback { - status = "succeeded" + status = i18n.G("succeeded") } if strings.Contains(stream.status, "rolled back") { - status = "rolled back" + status = i18n.G("rolled back") } retries := 0 @@ -338,7 +338,7 @@ func (m Model) View() string { retries = stream.retries } - output := fmt.Sprintf("%s: %s (retries: %v, healthcheck: %s)", + output := i18n.G("%s: %s (retries: %v, healthcheck: %s)", formatter.BoldStyle.Render(short), status, retries, diff --git a/pkg/upstream/commandconn/commandconn.go b/pkg/upstream/commandconn/commandconn.go index 9f76c50f..64083500 100644 --- a/pkg/upstream/commandconn/commandconn.go +++ b/pkg/upstream/commandconn/commandconn.go @@ -17,7 +17,6 @@ package commandconn import ( "bytes" "context" - "fmt" "io" "net" "os" @@ -28,6 +27,7 @@ import ( "time" "coopcloud.tech/abra/pkg/log" + "coopcloud.tech/abra/pkg/i18n" "github.com/pkg/errors" exec "golang.org/x/sys/execabs" ) @@ -46,7 +46,7 @@ func New(ctx context.Context, cmd string, args ...string) (net.Conn, error) { ) c.cmd = exec.CommandContext(ctx, cmd, args...) // we assume that args never contains sensitive information - log.Debugf("commandconn: starting %s with %v", cmd, args) + log.Debug(i18n.G("commandconn: starting %s with %v", cmd, args)) c.cmd.Env = os.Environ() c.cmd.SysProcAttr = &syscall.SysProcAttr{} setPdeathsig(c.cmd) @@ -62,7 +62,7 @@ func New(ctx context.Context, cmd string, args ...string) (net.Conn, error) { c.cmd.Stderr = &stderrWriter{ stderrMu: &c.stderrMu, stderr: &c.stderr, - debugPrefix: fmt.Sprintf("commandconn (%s):", cmd), + debugPrefix: i18n.G("commandconn (%s):", cmd), } c.localAddr = dummyAddr{network: "dummy", s: "dummy-0"} c.remoteAddr = dummyAddr{network: "dummy", s: "dummy-1"} @@ -138,7 +138,7 @@ func (c *commandConn) kill() error { return nil } } - return errors.Wrapf(werr, "commandconn: failed to wait") + return errors.Wrap(werr, i18n.G("commandconn: failed to wait")) } func (c *commandConn) onEOF(eof error) error { @@ -159,7 +159,7 @@ func (c *commandConn) onEOF(eof error) error { c.stderrMu.Lock() stderr := c.stderr.String() c.stderrMu.Unlock() - return errors.Errorf("command %v did not exit after %v: stderr=%q", c.cmd.Args, eof, stderr) + return errors.New(i18n.G("command %v did not exit after %v: stderr=%q", c.cmd.Args, eof, stderr)) } } c.cmdMutex.Unlock() @@ -169,7 +169,7 @@ func (c *commandConn) onEOF(eof error) error { c.stderrMu.Lock() stderr := c.stderr.String() c.stderrMu.Unlock() - return errors.Errorf("command %v has exited with %v, please make sure the URL is valid, and Docker 18.09 or later is installed on the remote host: stderr=%s", c.cmd.Args, werr, stderr) + return errors.New(i18n.G("command %v has exited with %v, please make sure the URL is valid, and Docker 18.09 or later is installed on the remote host: stderr=%s", c.cmd.Args, werr, stderr)) } func ignorableCloseError(err error) bool { @@ -236,7 +236,7 @@ func (c *commandConn) Write(p []byte) (int, error) { func (c *commandConn) Close() error { var err error if err = c.CloseRead(); err != nil { - log.Warnf("commandConn.Close: CloseRead: %v", err) + log.Warnf(i18n.G("commandConn.Close: CloseRead: %v", err)) } if err = c.CloseWrite(); err != nil { // muted because https://github.com/docker/compose/issues/8544 @@ -252,15 +252,15 @@ func (c *commandConn) RemoteAddr() net.Addr { return c.remoteAddr } func (c *commandConn) SetDeadline(t time.Time) error { - log.Debugf("unimplemented call: SetDeadline(%v)", t) + log.Debug(i18n.G("unimplemented call: SetDeadline(%v)", t)) return nil } func (c *commandConn) SetReadDeadline(t time.Time) error { - log.Debugf("unimplemented call: SetReadDeadline(%v)", t) + log.Debug(i18n.G("unimplemented call: SetReadDeadline(%v)", t)) return nil } func (c *commandConn) SetWriteDeadline(t time.Time) error { - log.Debugf("unimplemented call: SetWriteDeadline(%v)", t) + log.Debug(i18n.G("unimplemented call: SetWriteDeadline(%v)", t)) return nil } diff --git a/pkg/upstream/commandconn/connection.go b/pkg/upstream/commandconn/connection.go index f48a77af..07badfdf 100644 --- a/pkg/upstream/commandconn/connection.go +++ b/pkg/upstream/commandconn/connection.go @@ -11,6 +11,7 @@ import ( "github.com/docker/cli/cli/context/docker" dCliContextStore "github.com/docker/cli/cli/context/store" dClient "github.com/docker/docker/client" + "coopcloud.tech/abra/pkg/i18n" "github.com/pkg/errors" ) @@ -34,7 +35,7 @@ func getConnectionHelper(daemonURL string, sshFlags []string) (*connhelper.Conne case "ssh": ctxConnDetails, err := ssh.ParseURL(daemonURL) if err != nil { - return nil, errors.Wrap(err, "ssh host connection is not valid") + return nil, errors.Wrap(err, i18n.G("ssh host connection is not valid")) } return &connhelper.ConnectionHelper{ diff --git a/pkg/upstream/container/exec.go b/pkg/upstream/container/exec.go index ff551008..81f6ff95 100644 --- a/pkg/upstream/container/exec.go +++ b/pkg/upstream/container/exec.go @@ -11,6 +11,7 @@ import ( "github.com/docker/cli/cli/command" "github.com/docker/docker/api/types/container" apiclient "github.com/docker/docker/client" + "coopcloud.tech/abra/pkg/i18n" ) // RunExec runs a command on a remote container. io.Writer corresponds to the @@ -39,7 +40,7 @@ func RunExec(dockerCli command.Cli, client *apiclient.Client, containerID string execID := response.ID if execID == "" { - return nil, errors.New("exec ID empty") + return nil, errors.New(i18n.G("exec ID empty")) } if execOptions.Detach { @@ -104,12 +105,12 @@ func interactiveExec(ctx context.Context, dockerCli command.Cli, client *apiclie if execOpts.Tty && dockerCli.In().IsTerminal() { if err := MonitorTtySize(ctx, client, dockerCli, execID, true); err != nil { - fmt.Fprintln(dockerCli.Err(), "Error monitoring TTY size:", err) + fmt.Fprintln(dockerCli.Err(), i18n.G("Error monitoring TTY size:"), err) } } if err := <-errCh; err != nil { - log.Debugf("Error hijack: %s", err) + log.Debug(i18n.G("Error hijack: %s", err)) return out, err } diff --git a/pkg/upstream/container/hijack.go b/pkg/upstream/container/hijack.go index f2a9990e..0eecbb7e 100644 --- a/pkg/upstream/container/hijack.go +++ b/pkg/upstream/container/hijack.go @@ -2,7 +2,7 @@ package container // https://github.com/docker/cli/blob/master/cli/command/conta import ( "context" - "fmt" + "errors" "io" "runtime" "sync" @@ -12,6 +12,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/stdcopy" + "coopcloud.tech/abra/pkg/i18n" "github.com/moby/term" ) @@ -39,7 +40,7 @@ type hijackedIOStreamer struct { func (h *hijackedIOStreamer) stream(ctx context.Context) error { restoreInput, err := h.setupInput() if err != nil { - return fmt.Errorf("unable to setup input stream: %s", err) + return errors.New(i18n.G("unable to setup input stream: %s", err)) } defer restoreInput() @@ -78,7 +79,7 @@ func (h *hijackedIOStreamer) setupInput() (restore func(), err error) { } if err := setRawTerminal(h.streams); err != nil { - return nil, fmt.Errorf("unable to set IO streams as raw terminal: %s", err) + return nil, errors.New(i18n.G("unable to set IO streams as raw terminal: %s", err)) } // Use sync.Once so we may call restore multiple times but ensure we @@ -96,7 +97,7 @@ func (h *hijackedIOStreamer) setupInput() (restore func(), err error) { if h.detachKeys != "" { customEscapeKeys, err := term.ToBytes(h.detachKeys) if err != nil { - log.Warnf("invalid detach escape keys, using default: %s", err) + log.Warnf(i18n.G("invalid detach escape keys, using default: %s", err)) } else { escapeKeys = customEscapeKeys } @@ -128,10 +129,10 @@ func (h *hijackedIOStreamer) beginOutputStream(restoreInput func()) <-chan error _, err = stdcopy.StdCopy(h.outputStream, h.errorStream, h.resp.Reader) } - log.Debug("[hijack] End of stdout") + log.Debug(i18n.G("[hijack] end of stdout")) if err != nil { - log.Debugf("Error receiveStdout: %s", err) + log.Debug(i18n.G("error receiveStdout: %s", err)) } outputDone <- err @@ -152,7 +153,7 @@ func (h *hijackedIOStreamer) beginInputStream(restoreInput func()) (doneC <-chan // messages will be in normal type. restoreInput() - log.Debug("[hijack] End of stdin") + log.Debug(i18n.G("[hijack] End of stdin")) if _, ok := err.(term.EscapeError); ok { detached <- err @@ -163,12 +164,12 @@ func (h *hijackedIOStreamer) beginInputStream(restoreInput func()) (doneC <-chan // This error will also occur on the receive // side (from stdout) where it will be // propagated back to the caller. - log.Debugf("Error sendStdin: %s", err) + log.Debug(i18n.G("error sendStdin: %s", err)) } } if err := h.resp.CloseWrite(); err != nil { - log.Debugf("Couldn't send EOF: %s", err) + log.Debug(i18n.G("couldn't send EOF: %s", err)) } close(inputDone) diff --git a/pkg/upstream/container/tty.go b/pkg/upstream/container/tty.go index 2a5a55ae..0b975c35 100644 --- a/pkg/upstream/container/tty.go +++ b/pkg/upstream/container/tty.go @@ -8,6 +8,7 @@ import ( "runtime" "time" + "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "github.com/docker/cli/cli/command" "github.com/docker/docker/api/types/container" @@ -35,7 +36,7 @@ func resizeTtyTo(ctx context.Context, client client.ContainerAPIClient, id strin } if err != nil { - log.Debugf("Error resize: %s\r", err) + log.Debug(fmt.Sprintf("%s\r", i18n.G("error resize: %s", err))) } return err } @@ -62,7 +63,7 @@ func initTtySize(ctx context.Context, client *apiclient.Client, cli command.Cli, } } if err != nil { - fmt.Fprintln(cli.Err(), "failed to resize tty, using default size") + fmt.Fprintln(cli.Err(), i18n.G("failed to resize tty, using default size")) } }() } diff --git a/pkg/upstream/convert/service.go b/pkg/upstream/convert/service.go index 16cd0cfa..626c9a71 100644 --- a/pkg/upstream/convert/service.go +++ b/pkg/upstream/convert/service.go @@ -18,6 +18,7 @@ import ( "github.com/docker/docker/api/types/versions" "github.com/docker/docker/client" "github.com/docker/go-units" + "coopcloud.tech/abra/pkg/i18n" "github.com/pkg/errors" ) @@ -39,7 +40,7 @@ func ParseSecrets(client client.SecretAPIClient, requestedSecrets []*swarmtypes. for _, secret := range requestedSecrets { if _, exists := secretRefs[secret.File.Name]; exists { - return nil, errors.Errorf("duplicate secret target for %s not allowed", secret.SecretName) + return nil, errors.New(i18n.G("duplicate secret target for %s not allowed", secret.SecretName)) } secretRef := new(swarmtypes.SecretReference) *secretRef = *secret @@ -68,7 +69,7 @@ func ParseSecrets(client client.SecretAPIClient, requestedSecrets []*swarmtypes. for _, ref := range secretRefs { id, ok := foundSecrets[ref.SecretName] if !ok { - return nil, errors.Errorf("secret not found: %s", ref.SecretName) + return nil, errors.New(i18n.G("secret not found: %s", ref.SecretName)) } // set the id for the ref to properly assign in swarm @@ -118,7 +119,7 @@ func ParseConfigs(client client.ConfigAPIClient, requestedConfigs []*swarmtypes. } if _, exists := configRefs[config.File.Name]; exists { - return nil, errors.Errorf("duplicate config target for %s not allowed", config.ConfigName) + return nil, errors.New(i18n.G("duplicate config target for %s not allowed", config.ConfigName)) } configRefs[config.File.Name] = configRef @@ -149,7 +150,7 @@ func ParseConfigs(client client.ConfigAPIClient, requestedConfigs []*swarmtypes. for _, ref := range configRefs { id, ok := foundConfigs[ref.ConfigName] if !ok { - return nil, errors.Errorf("config not found: %s", ref.ConfigName) + return nil, errors.New(i18n.G("config not found: %s", ref.ConfigName)) } // set the id for the ref to properly assign in swarm @@ -164,7 +165,7 @@ func ParseConfigs(client client.ConfigAPIClient, requestedConfigs []*swarmtypes. for _, ref := range runtimeRefs { id, ok := foundConfigs[ref.ConfigName] if !ok { - return nil, errors.Errorf("config not found: %s", ref.ConfigName) + return nil, errors.New(i18n.G("config not found: %s", ref.ConfigName)) } ref.ConfigID = id @@ -371,7 +372,7 @@ func convertServiceNetworks( for networkName, network := range networks { networkConfig, ok := networkConfigs[networkName] if !ok && networkName != defaultNetwork { - return nil, errors.Errorf("undefined network %q", networkName) + return nil, errors.New(i18n.G("undefined network %q", networkName)) } var aliases []string if network != nil { @@ -410,7 +411,7 @@ func convertServiceSecrets( lookup := func(key string) (composetypes.FileObjectConfig, error) { secretSpec, exists := secretSpecs[key] if !exists { - return composetypes.FileObjectConfig{}, errors.Errorf("undefined secret %q", key) + return composetypes.FileObjectConfig{}, errors.New(i18n.G("undefined secret %q", key)) } return composetypes.FileObjectConfig(secretSpec), nil } @@ -458,7 +459,7 @@ func convertServiceConfigObjs( lookup := func(key string) (composetypes.FileObjectConfig, error) { configSpec, exists := configSpecs[key] if !exists { - return composetypes.FileObjectConfig{}, errors.Errorf("undefined config %q", key) + return composetypes.FileObjectConfig{}, errors.New(i18n.G("undefined config %q", key)) } return composetypes.FileObjectConfig(configSpec), nil } @@ -600,7 +601,7 @@ func convertHealthcheck(healthcheck *composetypes.HealthCheckConfig) (*container ) if healthcheck.Disable { if len(healthcheck.Test) != 0 { - return nil, errors.Errorf("test and disable can't be set at the same time") + return nil, errors.New(i18n.G("test and disable can't be set at the same time")) } return &container.HealthConfig{ Test: []string{"NONE"}, @@ -648,7 +649,7 @@ func convertRestartPolicy(restart string, source *composetypes.RestartPolicy) (* MaxAttempts: &attempts, }, nil default: - return nil, errors.Errorf("unknown restart policy: %s", restart) + return nil, errors.New(i18n.G("unknown restart policy: %s", restart)) } } @@ -770,13 +771,13 @@ func convertDeployMode(mode string, replicas *uint64) (swarm.ServiceMode, error) switch mode { case "global": if replicas != nil { - return serviceMode, errors.Errorf("replicas can only be used with replicated mode") + return serviceMode, errors.New(i18n.G("replicas can only be used with replicated mode")) } serviceMode.Global = &swarm.GlobalService{} case "replicated", "": serviceMode.Replicated = &swarm.ReplicatedService{Replicas: replicas} default: - return serviceMode, errors.Errorf("Unknown mode: %s", mode) + return serviceMode, errors.New(i18n.G("unknown mode: %s", mode)) } return serviceMode, nil } @@ -809,9 +810,9 @@ func convertCredentialSpec(namespace Namespace, spec composetypes.CredentialSpec case l == 0: return nil, nil case l == 2: - return nil, errors.Errorf("invalid credential spec: cannot specify both %s and %s", o[0], o[1]) + return nil, errors.New(i18n.G("invalid credential spec: cannot specify both %s and %s", o[0], o[1])) case l > 2: - return nil, errors.Errorf("invalid credential spec: cannot specify both %s, and %s", strings.Join(o[:l-1], ", "), o[l-1]) + return nil, errors.New(i18n.G("invalid credential spec: cannot specify both %s, and %s", strings.Join(o[:l-1], ", "), o[l-1])) } swarmCredSpec := swarm.CredentialSpec(spec) // if we're using a swarm Config for the credential spec, over-write it @@ -830,7 +831,7 @@ func convertCredentialSpec(namespace Namespace, spec composetypes.CredentialSpec return &swarmCredSpec, nil } } - return nil, errors.Errorf("invalid credential spec: spec specifies config %v, but no such config can be found", swarmCredSpec.Config) + return nil, errors.New(i18n.G("invalid credential spec: spec specifies config %v, but no such config can be found", swarmCredSpec.Config)) } return &swarmCredSpec, nil } diff --git a/pkg/upstream/convert/volume.go b/pkg/upstream/convert/volume.go index 387fb727..d7606592 100644 --- a/pkg/upstream/convert/volume.go +++ b/pkg/upstream/convert/volume.go @@ -3,6 +3,7 @@ package convert // https://github.com/docker/cli/blob/master/cli/compose/convert import ( composetypes "github.com/docker/cli/cli/compose/types" "github.com/docker/docker/api/types/mount" + "coopcloud.tech/abra/pkg/i18n" "github.com/pkg/errors" ) @@ -40,10 +41,10 @@ func handleVolumeToMount( result := createMountFromVolume(volume) if volume.Tmpfs != nil { - return mount.Mount{}, errors.New("tmpfs options are incompatible with type volume") + return mount.Mount{}, errors.New(i18n.G("tmpfs options are incompatible with type volume")) } if volume.Bind != nil { - return mount.Mount{}, errors.New("bind options are incompatible with type volume") + return mount.Mount{}, errors.New(i18n.G("bind options are incompatible with type volume")) } // Anonymous volumes if volume.Source == "" { @@ -52,7 +53,7 @@ func handleVolumeToMount( stackVolume, exists := stackVolumes[volume.Source] if !exists { - return mount.Mount{}, errors.Errorf("undefined volume %q", volume.Source) + return mount.Mount{}, errors.New(i18n.G("undefined volume %q", volume.Source)) } result.Source = namespace.Scope(volume.Source) @@ -86,13 +87,13 @@ func handleBindToMount(volume composetypes.ServiceVolumeConfig) (mount.Mount, er result := createMountFromVolume(volume) if volume.Source == "" { - return mount.Mount{}, errors.New("invalid bind source, source cannot be empty") + return mount.Mount{}, errors.New(i18n.G("invalid bind source, source cannot be empty")) } if volume.Volume != nil { - return mount.Mount{}, errors.New("volume options are incompatible with type bind") + return mount.Mount{}, errors.New(i18n.G("volume options are incompatible with type bind")) } if volume.Tmpfs != nil { - return mount.Mount{}, errors.New("tmpfs options are incompatible with type bind") + return mount.Mount{}, errors.New(i18n.G("tmpfs options are incompatible with type bind")) } if volume.Bind != nil { result.BindOptions = &mount.BindOptions{ @@ -106,13 +107,13 @@ func handleTmpfsToMount(volume composetypes.ServiceVolumeConfig) (mount.Mount, e result := createMountFromVolume(volume) if volume.Source != "" { - return mount.Mount{}, errors.New("invalid tmpfs source, source must be empty") + return mount.Mount{}, errors.New(i18n.G("invalid tmpfs source, source must be empty")) } if volume.Bind != nil { - return mount.Mount{}, errors.New("bind options are incompatible with type tmpfs") + return mount.Mount{}, errors.New(i18n.G("bind options are incompatible with type tmpfs")) } if volume.Volume != nil { - return mount.Mount{}, errors.New("volume options are incompatible with type tmpfs") + return mount.Mount{}, errors.New(i18n.G("volume options are incompatible with type tmpfs")) } if volume.Tmpfs != nil { result.TmpfsOptions = &mount.TmpfsOptions{ @@ -126,13 +127,13 @@ func handleNpipeToMount(volume composetypes.ServiceVolumeConfig) (mount.Mount, e result := createMountFromVolume(volume) if volume.Source == "" { - return mount.Mount{}, errors.New("invalid npipe source, source cannot be empty") + return mount.Mount{}, errors.New(i18n.G("invalid npipe source, source cannot be empty")) } if volume.Volume != nil { - return mount.Mount{}, errors.New("volume options are incompatible with type npipe") + return mount.Mount{}, errors.New(i18n.G("volume options are incompatible with type npipe")) } if volume.Tmpfs != nil { - return mount.Mount{}, errors.New("tmpfs options are incompatible with type npipe") + return mount.Mount{}, errors.New(i18n.G("tmpfs options are incompatible with type npipe")) } if volume.Bind != nil { result.BindOptions = &mount.BindOptions{ @@ -158,5 +159,5 @@ func convertVolumeToMount( case "npipe": return handleNpipeToMount(volume) } - return mount.Mount{}, errors.New("volume type must be volume, bind, tmpfs or npipe") + return mount.Mount{}, errors.New(i18n.G("volume type must be volume, bind, tmpfs or npipe")) } diff --git a/pkg/web/web.go b/pkg/web/web.go index b1f871ab..09f764ec 100644 --- a/pkg/web/web.go +++ b/pkg/web/web.go @@ -3,11 +3,13 @@ package web import ( "encoding/json" - "fmt" + "errors" "io" "net/http" "os" "time" + + "coopcloud.tech/abra/pkg/i18n" ) // Timeout is the time it takes before a web request bails out waiting for a @@ -40,7 +42,7 @@ func GetFile(filepath string, url string) (err error) { defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return fmt.Errorf("bad status: %s", resp.Status) + return errors.New(i18n.G("bad status: %s", resp.Status)) } _, err = io.Copy(out, resp.Body) diff --git a/vendor/modules.txt b/vendor/modules.txt index b6d67d59..0595f6a0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -7,8 +7,6 @@ dario.cat/mergo # git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c ## explicit; go 1.12 git.coopcloud.tech/toolshed/godotenv -# github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 -## explicit; go 1.20 # github.com/AlecAivazis/survey/v2 v2.3.7 ## explicit; go 1.13 github.com/AlecAivazis/survey/v2 @@ -237,8 +235,6 @@ github.com/docker/docker/pkg/streamformatter ## explicit; go 1.21 github.com/docker/docker-credential-helpers/client github.com/docker/docker-credential-helpers/credentials -# github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c -## explicit # github.com/docker/go-connections v0.6.0 ## explicit; go 1.18 github.com/docker/go-connections/nat @@ -267,8 +263,6 @@ github.com/erikgeiser/coninput # github.com/felixge/httpsnoop v1.0.4 ## explicit; go 1.13 github.com/felixge/httpsnoop -# github.com/fsnotify/fsnotify v1.6.0 -## explicit; go 1.16 # github.com/fvbommel/sortorder v1.1.0 ## explicit; go 1.13 github.com/fvbommel/sortorder @@ -433,8 +427,6 @@ github.com/mgutz/ansi # github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db ## explicit github.com/mitchellh/colorstring -# github.com/mitchellh/mapstructure v1.5.0 -## explicit; go 1.14 # github.com/moby/docker-image-spec v1.3.1 ## explicit; go 1.18 github.com/moby/docker-image-spec/specs-go/v1 @@ -449,8 +441,6 @@ github.com/moby/patternmatcher # github.com/moby/sys/atomicwriter v0.1.0 ## explicit; go 1.18 github.com/moby/sys/atomicwriter -# github.com/moby/sys/mountinfo v0.7.2 -## explicit; go 1.17 # github.com/moby/sys/sequential v0.6.0 ## explicit; go 1.17 github.com/moby/sys/sequential @@ -494,8 +484,6 @@ github.com/opencontainers/image-spec/specs-go/v1 ## explicit; go 1.18 # github.com/opencontainers/runtime-spec v1.1.0 ## explicit -# github.com/pelletier/go-toml v1.9.5 -## explicit; go 1.12 # github.com/pjbgf/sha1cd v0.4.0 ## explicit; go 1.21 github.com/pjbgf/sha1cd