feat: translation support
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
See #483
This commit is contained in:
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user