diff --git a/cli/app/check.go b/cli/app/check.go index 6b0e8455..7b57b9cb 100644 --- a/cli/app/check.go +++ b/cli/app/check.go @@ -5,7 +5,6 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/formatter" - "coopcloud.tech/abra/pkg/recipe" recipePkg "coopcloud.tech/abra/pkg/recipe" "github.com/sirupsen/logrus" "github.com/urfave/cli" @@ -38,7 +37,7 @@ ${FOO:} syntax). "check" does not confirm or deny this for you.`, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := recipePkg.EnsureExists(app.Recipe); err != nil { logrus.Fatal(err) } @@ -68,9 +67,9 @@ ${FOO:} syntax). "check" does not confirm or deny this for you.`, for _, envVar := range envVars { if envVar.Present { - table.Append([]string{envVar.Name, "✅"}) + table.Append([]string{envVar.Name, "✅ OK"}) } else { - table.Append([]string{envVar.Name, "❌"}) + table.Append([]string{envVar.Name, "❌ Missing"}) } } diff --git a/cli/app/cmd.go b/cli/app/cmd.go index 002eecfa..dcbe2835 100644 --- a/cli/app/cmd.go +++ b/cli/app/cmd.go @@ -14,7 +14,6 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/config" - "coopcloud.tech/abra/pkg/recipe" recipePkg "coopcloud.tech/abra/pkg/recipe" "github.com/sirupsen/logrus" "github.com/urfave/cli" @@ -60,7 +59,7 @@ Example: Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := recipePkg.EnsureExists(app.Recipe); err != nil { logrus.Fatal(err) } @@ -228,7 +227,7 @@ var appCmdListCommand = cli.Command{ Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := recipePkg.EnsureExists(app.Recipe); err != nil { logrus.Fatal(err) } diff --git a/cli/app/list.go b/cli/app/list.go index 08dff6f2..c5e4ed30 100644 --- a/cli/app/list.go +++ b/cli/app/list.go @@ -270,17 +270,17 @@ can take some time. table.Render() if status { - fmt.Println(fmt.Sprintf( - "server: %s | total apps: %v | versioned: %v | unversioned: %v | latest: %v | upgrade: %v", + fmt.Printf( + "server: %s | total apps: %v | versioned: %v | unversioned: %v | latest: %v | upgrade: %v\n", app.Server, serverStat.AppCount, serverStat.VersionCount, serverStat.UnversionedCount, serverStat.LatestCount, serverStat.UpgradeCount, - )) + ) } else { - fmt.Println(fmt.Sprintf("server: %s | total apps: %v", app.Server, serverStat.AppCount)) + fmt.Printf("server: %s | total apps: %v\n", app.Server, serverStat.AppCount) } } @@ -292,7 +292,7 @@ can take some time. } if len(allStats) > 1 { - fmt.Println(fmt.Sprintf("total servers: %v | total apps: %v ", totalServersCount, totalAppsCount)) + fmt.Printf("total servers: %v | total apps: %v\n", totalServersCount, totalAppsCount) } return nil diff --git a/cli/app/new.go b/cli/app/new.go index 22f51fd2..c989b1f4 100644 --- a/cli/app/new.go +++ b/cli/app/new.go @@ -10,7 +10,6 @@ import ( "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/jsontable" - "coopcloud.tech/abra/pkg/recipe" recipePkg "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/abra/pkg/secret" "github.com/AlecAivazis/survey/v2" @@ -142,15 +141,15 @@ var appNewCommand = cli.Command{ table := formatter.CreateTable(tableCol) table.Append([]string{internal.NewAppServer, recipe.Name, internal.Domain}) - fmt.Println(fmt.Sprintf("A new %s app has been created! Here is an overview:", recipe.Name)) + fmt.Printf("A new %s app has been created! Here is an overview:\n", recipe.Name) fmt.Println("") table.Render() fmt.Println("") fmt.Println("You can configure this app by running the following:") - fmt.Println(fmt.Sprintf("\n abra app config %s", internal.Domain)) + fmt.Printf("\n abra app config %s\n", internal.Domain) fmt.Println("") fmt.Println("You can deploy this app by running the following:") - fmt.Println(fmt.Sprintf("\n abra app deploy %s", internal.Domain)) + fmt.Printf("\n abra app deploy %s\n", internal.Domain) if len(secrets) > 0 { fmt.Println("") @@ -192,7 +191,7 @@ func createSecrets(cl *dockerClient.Client, secretsConfig map[string]secret.Secr } // ensureDomainFlag checks if the domain flag was used. if not, asks the user for it/ -func ensureDomainFlag(recipe recipe.Recipe, server string) error { +func ensureDomainFlag(recipe recipePkg.Recipe, server string) error { if internal.Domain == "" && !internal.NoInput { prompt := &survey.Input{ Message: "Specify app domain", diff --git a/cli/app/remove.go b/cli/app/remove.go index ea4efedf..f8e0bfd5 100644 --- a/cli/app/remove.go +++ b/cli/app/remove.go @@ -110,7 +110,7 @@ flag. logrus.Fatal(err) } - volumeListOptions := volume.ListOptions{fs} + volumeListOptions := volume.ListOptions{Filters: fs} volumeListOKBody, err := cl.VolumeList(context.Background(), volumeListOptions) volumeList := volumeListOKBody.Volumes if err != nil { diff --git a/cli/app/restore.go b/cli/app/restore.go index 1bf9c840..d988d50a 100644 --- a/cli/app/restore.go +++ b/cli/app/restore.go @@ -11,7 +11,6 @@ import ( "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/config" containerPkg "coopcloud.tech/abra/pkg/container" - "coopcloud.tech/abra/pkg/recipe" recipePkg "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/abra/pkg/upstream/container" "github.com/docker/cli/cli/command" @@ -60,7 +59,7 @@ Example: Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - recipe, err := recipe.Get(app.Recipe, internal.Offline) + recipe, err := recipePkg.Get(app.Recipe, internal.Offline) if err != nil { logrus.Fatal(err) } diff --git a/cli/app/upgrade.go b/cli/app/upgrade.go index 8c10337b..cbae99cb 100644 --- a/cli/app/upgrade.go +++ b/cli/app/upgrade.go @@ -9,7 +9,6 @@ import ( "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/lint" - "coopcloud.tech/abra/pkg/recipe" recipePkg "coopcloud.tech/abra/pkg/recipe" stack "coopcloud.tech/abra/pkg/upstream/stack" "coopcloud.tech/tagcmp" @@ -62,17 +61,17 @@ recipes. } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := recipePkg.EnsureIsClean(app.Recipe); err != nil { logrus.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil { logrus.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := recipePkg.EnsureLatest(app.Recipe); err != nil { logrus.Fatal(err) } } diff --git a/cli/cli.go b/cli/cli.go index e338d390..e33a4d12 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -80,29 +80,26 @@ Example: switch shellType { case "bash": - fmt.Println(fmt.Sprintf(` -# Run the following commands to install auto-completion + fmt.Printf(`# Run the following commands to install auto-completion sudo mkdir /etc/bash_completion.d/ sudo cp %s /etc/bash_completion.d/abra echo "source /etc/bash_completion.d/abra" >> ~/.bashrc # To test, run the following: "abra app " - you should see command completion! -`, autocompletionFile)) +`, autocompletionFile) case "zsh": - fmt.Println(fmt.Sprintf(` -# Run the following commands to install auto-completion + fmt.Printf(`# Run the following commands to install auto-completion sudo mkdir /etc/zsh/completion.d/ sudo cp %s /etc/zsh/completion.d/abra echo "PROG=abra\n_CLI_ZSH_AUTOCOMPLETE_HACK=1\nsource /etc/zsh/completion.d/abra" >> ~/.zshrc # To test, run the following: "abra app " - you should see command completion! -`, autocompletionFile)) +`, autocompletionFile) case "fish": - fmt.Println(fmt.Sprintf(` -# Run the following commands to install auto-completion + fmt.Printf(`# Run the following commands to install auto-completion sudo mkdir -p /etc/fish/completions sudo cp %s /etc/fish/completions/abra echo "source /etc/fish/completions/abra" >> ~/.config/fish/config.fish # To test, run the following: "abra app " - you should see command completion! -`, autocompletionFile)) +`, autocompletionFile) } return nil @@ -117,6 +114,10 @@ var UpgradeCommand = cli.Command{ Description: ` Upgrade Abra in-place with the latest stable or release candidate. +This command uses wget and bash. The install script is pulled from: + - default stable release: https://install.abra.coopcloud.tech + - release candidate: https://git.coopcloud.tech/coop-cloud/abra/ + Pass "-r/--rc" to install the latest release candidate. Please bear in mind that it may contain catastrophic bugs. Thank you very much for the testing efforts! diff --git a/cli/internal/cli.go b/cli/internal/cli.go index b7555bdc..9ad86766 100644 --- a/cli/internal/cli.go +++ b/cli/internal/cli.go @@ -162,7 +162,7 @@ var NewAppServer string var NewAppServerFlag = &cli.StringFlag{ Name: "server, s", Value: "", - Usage: "Show apps of a specific server", + Usage: "Use a specific server", Destination: &NewAppServer, } diff --git a/cli/internal/recipe.go b/cli/internal/recipe.go index ede34464..b3ad37f1 100644 --- a/cli/internal/recipe.go +++ b/cli/internal/recipe.go @@ -40,7 +40,7 @@ Here is a semver cheat sheet (more on https://semver.org): var chosenBumpType string prompt := &survey.Select{ - Message: fmt.Sprintf("select recipe version increment type"), + Message: "select recipe version increment type", Options: []string{"major", "minor", "patch"}, } diff --git a/cli/recipe/new.go b/cli/recipe/new.go index 87e84d87..346a5426 100644 --- a/cli/recipe/new.go +++ b/cli/recipe/new.go @@ -103,7 +103,7 @@ recipe and domain in the sample environment config). logrus.Fatal(err) } - fmt.Print(fmt.Sprintf(` + fmt.Printf(` Your new %s recipe has been created in %s. In order to share your recipe, you can upload it the git repository to: @@ -118,7 +118,7 @@ See "abra recipe -h" for additional recipe maintainer commands. Happy Hacking! -`, recipeName, path.Join(config.RECIPES_DIR, recipeName), recipeName)) +`, recipeName, path.Join(config.RECIPES_DIR, recipeName), recipeName) return nil }, diff --git a/cli/recipe/sync.go b/cli/recipe/sync.go index d5b4ad00..a89b917d 100644 --- a/cli/recipe/sync.go +++ b/cli/recipe/sync.go @@ -68,7 +68,7 @@ local file system. if internal.NoInput { logrus.Fatalf("unable to continue, input required for initial version") } - fmt.Println(fmt.Sprintf(` + fmt.Printf(` 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 @@ -85,7 +85,7 @@ If you want people to be able alpha test your current config for %s but don't think it is quite reliable, go with 0.1.0 and people will know that things are likely to change. -`, recipe.Name, recipe.Name)) +`, recipe.Name, recipe.Name) var chosenVersion string edPrompt := &survey.Select{ Message: "which version do you want to begin with?", diff --git a/pkg/client/volumes.go b/pkg/client/volumes.go index 4afd60c2..524785d0 100644 --- a/pkg/client/volumes.go +++ b/pkg/client/volumes.go @@ -9,7 +9,7 @@ import ( ) func GetVolumes(cl *client.Client, ctx context.Context, server string, fs filters.Args) ([]*volume.Volume, error) { - volumeListOptions := volume.ListOptions{fs} + volumeListOptions := volume.ListOptions{Filters: fs} volumeListOKBody, err := cl.VolumeList(ctx, volumeListOptions) volumeList := volumeListOKBody.Volumes if err != nil { diff --git a/pkg/limit/limit.go b/pkg/limit/limit.go index 187f9bef..951a34aa 100644 --- a/pkg/limit/limit.go +++ b/pkg/limit/limit.go @@ -6,7 +6,7 @@ type Limiter struct{ sem chan struct{} } // New returns a new Limiter. The limit param is the maximum number of // concurrent operations. func New(limit int) *Limiter { - return &Limiter{make(chan struct{}, limit)} + return &Limiter{sem: make(chan struct{}, limit)} } // Begin an operation. diff --git a/pkg/lint/recipe.go b/pkg/lint/recipe.go index cae797f3..69af968d 100644 --- a/pkg/lint/recipe.go +++ b/pkg/lint/recipe.go @@ -7,7 +7,6 @@ import ( "path" "coopcloud.tech/abra/pkg/config" - "coopcloud.tech/abra/pkg/recipe" recipePkg "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/tagcmp" "github.com/docker/distribution/reference" @@ -19,13 +18,13 @@ import ( var Warn = "warn" var Critical = "critical" -type LintFunction func(recipe.Recipe) (bool, error) +type LintFunction func(recipePkg.Recipe) (bool, error) // SkipFunction determines whether the LintFunction is run or not. It should // not take the lint rule level into account because some rules are always an // error but may depend on some additional context of the recipe configuration. // This function aims to cover those additional cases. -type SkipFunction func(recipe.Recipe) (bool, error) +type SkipFunction func(recipePkg.Recipe) (bool, error) // LintRule is a linting rule which helps a recipe maintainer avoid common // problems in their recipe configurations. We aim to highlight things that @@ -42,7 +41,7 @@ type LintRule struct { } // Skip implements the SkipFunction for the lint rule. -func (l LintRule) Skip(recipe recipe.Recipe) bool { +func (l LintRule) Skip(recipe recipePkg.Recipe) bool { if l.SkipCondition != nil { ok, err := l.SkipCondition(recipe) if err != nil { @@ -166,7 +165,7 @@ var LintRules = map[string][]LintRule{ // LintForErrors lints specifically for errors and not other levels. This is // 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 { +func LintForErrors(recipe recipePkg.Recipe) error { logrus.Debugf("linting for critical errors in %s configs", recipe.Name) for level := range LintRules { @@ -194,7 +193,7 @@ func LintForErrors(recipe recipe.Recipe) error { return nil } -func LintComposeVersion(recipe recipe.Recipe) (bool, error) { +func LintComposeVersion(recipe recipePkg.Recipe) (bool, error) { if recipe.Config.Version == "3.8" { return true, nil } @@ -202,7 +201,7 @@ func LintComposeVersion(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintEnvConfigPresent(recipe recipe.Recipe) (bool, error) { +func LintEnvConfigPresent(recipe recipePkg.Recipe) (bool, error) { envSample := fmt.Sprintf("%s/%s/.env.sample", config.RECIPES_DIR, recipe.Name) if _, err := os.Stat(envSample); !os.IsNotExist(err) { return true, nil @@ -211,7 +210,7 @@ func LintEnvConfigPresent(recipe recipe.Recipe) (bool, error) { return false, nil } -func LintAppService(recipe recipe.Recipe) (bool, error) { +func LintAppService(recipe recipePkg.Recipe) (bool, error) { for _, service := range recipe.Config.Services { if service.Name == "app" { return true, nil @@ -225,7 +224,7 @@ func LintAppService(recipe recipe.Recipe) (bool, error) { // confirms that there is no "DOMAIN=..." in the .env.sample configuration of // the recipe. This typically means that no domain is required to deploy and // therefore no matching traefik deploy label will be present. -func LintTraefikEnabledSkipCondition(recipe recipe.Recipe) (bool, error) { +func LintTraefikEnabledSkipCondition(recipe recipePkg.Recipe) (bool, error) { envSamplePath := path.Join(config.RECIPES_DIR, recipe.Name, ".env.sample") sampleEnv, err := config.ReadEnv(envSamplePath) if err != nil { @@ -239,7 +238,7 @@ func LintTraefikEnabledSkipCondition(recipe recipe.Recipe) (bool, error) { return false, nil } -func LintTraefikEnabled(recipe recipe.Recipe) (bool, error) { +func LintTraefikEnabled(recipe recipePkg.Recipe) (bool, error) { for _, service := range recipe.Config.Services { for label := range service.Deploy.Labels { if label == "traefik.enable" { @@ -253,7 +252,7 @@ func LintTraefikEnabled(recipe recipe.Recipe) (bool, error) { return false, nil } -func LintHealthchecks(recipe recipe.Recipe) (bool, error) { +func LintHealthchecks(recipe recipePkg.Recipe) (bool, error) { for _, service := range recipe.Config.Services { if service.HealthCheck == nil { return false, nil @@ -263,7 +262,7 @@ func LintHealthchecks(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintAllImagesTagged(recipe recipe.Recipe) (bool, error) { +func LintAllImagesTagged(recipe recipePkg.Recipe) (bool, error) { for _, service := range recipe.Config.Services { img, err := reference.ParseNormalizedNamed(service.Image) if err != nil { @@ -277,7 +276,7 @@ func LintAllImagesTagged(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintNoUnstableTags(recipe recipe.Recipe) (bool, error) { +func LintNoUnstableTags(recipe recipePkg.Recipe) (bool, error) { for _, service := range recipe.Config.Services { img, err := reference.ParseNormalizedNamed(service.Image) if err != nil { @@ -300,7 +299,7 @@ func LintNoUnstableTags(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintSemverLikeTags(recipe recipe.Recipe) (bool, error) { +func LintSemverLikeTags(recipe recipePkg.Recipe) (bool, error) { for _, service := range recipe.Config.Services { img, err := reference.ParseNormalizedNamed(service.Image) if err != nil { @@ -323,7 +322,7 @@ func LintSemverLikeTags(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintImagePresent(recipe recipe.Recipe) (bool, error) { +func LintImagePresent(recipe recipePkg.Recipe) (bool, error) { for _, service := range recipe.Config.Services { if service.Image == "" { return false, nil @@ -332,7 +331,7 @@ func LintImagePresent(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintHasPublishedVersion(recipe recipe.Recipe) (bool, error) { +func LintHasPublishedVersion(recipe recipePkg.Recipe) (bool, error) { catl, err := recipePkg.ReadRecipeCatalogue(false) if err != nil { logrus.Fatal(err) @@ -350,8 +349,8 @@ func LintHasPublishedVersion(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintMetadataFilledIn(r recipe.Recipe) (bool, error) { - features, category, err := recipe.GetRecipeFeaturesAndCategory(r.Name) +func LintMetadataFilledIn(recipe recipePkg.Recipe) (bool, error) { + features, category, err := recipePkg.GetRecipeFeaturesAndCategory(recipe.Name) if err != nil { return false, err } @@ -371,7 +370,7 @@ func LintMetadataFilledIn(r recipe.Recipe) (bool, error) { return true, nil } -func LintAbraShVendors(recipe recipe.Recipe) (bool, error) { +func LintAbraShVendors(recipe recipePkg.Recipe) (bool, error) { for _, service := range recipe.Config.Services { if len(service.Configs) > 0 { abraSh := path.Join(config.RECIPES_DIR, recipe.Name, "abra.sh") @@ -386,7 +385,7 @@ func LintAbraShVendors(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintHasRecipeRepo(recipe recipe.Recipe) (bool, error) { +func LintHasRecipeRepo(recipe recipePkg.Recipe) (bool, error) { url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, recipe.Name) res, err := http.Get(url) @@ -401,7 +400,7 @@ func LintHasRecipeRepo(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintValidTags(recipe recipe.Recipe) (bool, error) { +func LintValidTags(recipe recipePkg.Recipe) (bool, error) { recipeDir := path.Join(config.RECIPES_DIR, recipe.Name) repo, err := git.PlainOpen(recipeDir) diff --git a/pkg/upstream/stack/stack.go b/pkg/upstream/stack/stack.go index c2d1e214..94821412 100644 --- a/pkg/upstream/stack/stack.go +++ b/pkg/upstream/stack/stack.go @@ -66,19 +66,19 @@ func GetDeployedServicesByLabel(cl *dockerClient.Client, contextName string, lab filters.Add("label", label) services, err := cl.ServiceList(context.Background(), types.ServiceListOptions{Filters: filters}) if err != nil { - return StackStatus{[]swarm.Service{}, err} + return StackStatus{Services: []swarm.Service{}, Err: err} } - return StackStatus{services, nil} + return StackStatus{Services: services, Err: nil} } func GetAllDeployedServices(cl *dockerClient.Client, contextName string) StackStatus { services, err := cl.ServiceList(context.Background(), types.ServiceListOptions{Filters: getAllStacksFilter()}) if err != nil { - return StackStatus{[]swarm.Service{}, err} + return StackStatus{Services: []swarm.Service{}, Err: err} } - return StackStatus{services, nil} + return StackStatus{Services: services, Err: nil} } // GetDeployedServicesByName filters services by name @@ -88,10 +88,10 @@ func GetDeployedServicesByName(ctx context.Context, cl *dockerClient.Client, sta services, err := cl.ServiceList(ctx, types.ServiceListOptions{Filters: filters}) if err != nil { - return StackStatus{[]swarm.Service{}, err} + return StackStatus{Services: []swarm.Service{}, Err: err} } - return StackStatus{services, nil} + return StackStatus{Services: services, Err: nil} } // IsDeployed chekcks whether an appp is deployed or not.