From 950f85e2b4597fd943dfab7e69b4660af6f5ae18 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Sun, 7 Jul 2024 12:35:09 +0200 Subject: [PATCH 01/19] refactor(recipe): introduce new recipe struct and move some methods --- cli/app/backup.go | 36 +++++---- cli/app/check.go | 10 +-- cli/app/cmd.go | 19 ++--- cli/app/deploy.go | 15 ++-- cli/app/logs.go | 3 +- cli/app/new.go | 11 +-- cli/app/ps.go | 3 +- cli/app/restore.go | 9 ++- cli/app/rollback.go | 13 ++-- cli/app/secret.go | 27 ++++--- cli/app/upgrade.go | 11 +-- cli/recipe/fetch.go | 6 +- cli/recipe/lint.go | 9 ++- cli/recipe/upgrade.go | 9 ++- cli/updater/updater.go | 14 ++-- pkg/recipe/recipe.go | 169 ++++++++++++++++++++++------------------- 16 files changed, 197 insertions(+), 167 deletions(-) diff --git a/cli/app/backup.go b/cli/app/backup.go index c7067941..75d9eb6b 100644 --- a/cli/app/backup.go +++ b/cli/app/backup.go @@ -47,22 +47,23 @@ var appBackupListCommand = cli.Command{ Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - if err := recipe.EnsureExists(app.Recipe); err != nil { + r := recipe.Get2(app.Recipe) + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } @@ -109,23 +110,24 @@ var appBackupDownloadCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } @@ -179,23 +181,24 @@ var appBackupCreateCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } @@ -237,23 +240,24 @@ var appBackupSnapshotsCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } diff --git a/cli/app/check.go b/cli/app/check.go index 53f68901..002a2978 100644 --- a/cli/app/check.go +++ b/cli/app/check.go @@ -7,7 +7,6 @@ import ( "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" - recipePkg "coopcloud.tech/abra/pkg/recipe" "github.com/urfave/cli" ) @@ -37,23 +36,24 @@ ${FOO:} syntax). "check" does not confirm or deny this for you.`, BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipePkg.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipePkg.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } diff --git a/cli/app/cmd.go b/cli/app/cmd.go index c8215d28..a92dc946 100644 --- a/cli/app/cmd.go +++ b/cli/app/cmd.go @@ -17,7 +17,6 @@ import ( "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" - recipePkg "coopcloud.tech/abra/pkg/recipe" "github.com/urfave/cli" ) @@ -60,23 +59,24 @@ Example: }, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Name) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipePkg.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipePkg.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } @@ -228,23 +228,24 @@ var appCmdListCommand = cli.Command{ Before: internal.SubCommandBefore, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Name) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipePkg.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipePkg.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } diff --git a/cli/app/deploy.go b/cli/app/deploy.go index e7c3d5fd..27716276 100644 --- a/cli/app/deploy.go +++ b/cli/app/deploy.go @@ -52,28 +52,29 @@ recipes. Action: func(c *cli.Context) error { app := internal.ValidateApp(c) stackName := app.StackName() + r2 := recipe.Get2(app.Recipe) specificVersion := c.Args().Get(1) if specificVersion != "" && internal.Chaos { log.Fatal("cannot use and --chaos together") } - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r2.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := r2.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := r2.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := r2.EnsureLatest(); err != nil { log.Fatal(err) } } @@ -107,7 +108,7 @@ recipes. if specificVersion != "" { version = specificVersion log.Debugf("choosing %s as version to deploy", version) - if err := recipe.EnsureVersion(app.Recipe, version); err != nil { + if err := r2.EnsureVersion(version); err != nil { log.Fatal(err) } } @@ -157,7 +158,7 @@ recipes. if len(versions) > 0 && !internal.Chaos { version = versions[len(versions)-1] log.Debugf("choosing %s as version to deploy", version) - if err := recipe.EnsureVersion(app.Recipe, version); err != nil { + if err := r2.EnsureVersion(version); err != nil { log.Fatal(err) } } else { @@ -173,7 +174,7 @@ recipes. if internal.Chaos { log.Warnf("chaos mode engaged") var err error - version, err = recipe.ChaosVersion(app.Recipe) + version, err = r2.ChaosVersion() if err != nil { log.Fatal(err) } diff --git a/cli/app/logs.go b/cli/app/logs.go index c98d62b5..346e4ed3 100644 --- a/cli/app/logs.go +++ b/cli/app/logs.go @@ -38,8 +38,9 @@ var appLogsCommand = cli.Command{ Action: func(c *cli.Context) error { app := internal.ValidateApp(c) stackName := app.StackName() + r := recipe.Get2(app.Recipe) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } diff --git a/cli/app/new.go b/cli/app/new.go index 5011af63..63aff1de 100644 --- a/cli/app/new.go +++ b/cli/app/new.go @@ -67,13 +67,14 @@ var appNewCommand = cli.Command{ }, Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) + r := recipePkg.Get2(recipe.Name) if !internal.Chaos { - if err := recipePkg.EnsureIsClean(recipe.Name); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } @@ -93,16 +94,16 @@ var appNewCommand = cli.Command{ version = tag } - if err := recipePkg.EnsureVersion(recipe.Name, version); err != nil { + if err := r.EnsureVersion(version); err != nil { log.Fatal(err) } } else { - if err := recipePkg.EnsureLatest(recipe.Name); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } } else { - if err := recipePkg.EnsureVersion(recipe.Name, c.Args().Get(1)); err != nil { + if err := r.EnsureVersion(c.Args().Get(1)); err != nil { log.Fatal(err) } } diff --git a/cli/app/ps.go b/cli/app/ps.go index 162c6f1c..0db7a7dc 100644 --- a/cli/app/ps.go +++ b/cli/app/ps.go @@ -35,6 +35,7 @@ var appPsCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) cl, err := client.New(app.Server) if err != nil { @@ -53,7 +54,7 @@ var appPsCommand = cli.Command{ statuses, err := appPkg.GetAppStatuses([]appPkg.App{app}, true) if statusMeta, ok := statuses[app.StackName()]; ok { if _, exists := statusMeta["chaos"]; !exists { - if err := recipe.EnsureVersion(app.Recipe, deployedVersion); err != nil { + if err := r.EnsureVersion(deployedVersion); err != nil { log.Fatal(err) } } diff --git a/cli/app/restore.go b/cli/app/restore.go index f95b497d..b6605d29 100644 --- a/cli/app/restore.go +++ b/cli/app/restore.go @@ -32,23 +32,24 @@ var appRestoreCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } diff --git a/cli/app/rollback.go b/cli/app/rollback.go index 6dbf449c..82eae9cc 100644 --- a/cli/app/rollback.go +++ b/cli/app/rollback.go @@ -52,28 +52,29 @@ recipes. Action: func(c *cli.Context) error { app := internal.ValidateApp(c) stackName := app.StackName() + r2 := recipe.Get2(app.Recipe) specificVersion := c.Args().Get(1) if specificVersion != "" && internal.Chaos { log.Fatal("cannot use and --chaos together") } - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r2.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := r2.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := r2.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := r2.EnsureLatest(); err != nil { log.Fatal(err) } } @@ -185,7 +186,7 @@ recipes. } if !internal.Chaos { - if err := recipe.EnsureVersion(app.Recipe, chosenDowngrade); err != nil { + if err := r2.EnsureVersion(chosenDowngrade); err != nil { log.Fatal(err) } } @@ -193,7 +194,7 @@ recipes. if internal.Chaos { log.Warn("chaos mode engaged") var err error - chosenDowngrade, err = recipe.ChaosVersion(app.Recipe) + chosenDowngrade, err = r2.ChaosVersion() if err != nil { log.Fatal(err) } diff --git a/cli/app/secret.go b/cli/app/secret.go index 672496f1..0f995fd0 100644 --- a/cli/app/secret.go +++ b/cli/app/secret.go @@ -56,23 +56,24 @@ var appSecretGenerateCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } @@ -263,23 +264,24 @@ Example: `, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } @@ -371,23 +373,24 @@ var appSecretLsCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) - if err := recipe.EnsureExists(app.Recipe); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } diff --git a/cli/app/upgrade.go b/cli/app/upgrade.go index 4f54a481..f4d2bf85 100644 --- a/cli/app/upgrade.go +++ b/cli/app/upgrade.go @@ -58,6 +58,7 @@ recipes. Action: func(c *cli.Context) error { app := internal.ValidateApp(c) stackName := app.StackName() + r := recipe.Get2(app.Name) specificVersion := c.Args().Get(1) if specificVersion != "" && internal.Chaos { @@ -65,17 +66,17 @@ recipes. } if !internal.Chaos { - if err := recipe.EnsureIsClean(app.Recipe); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipe.EnsureUpToDate(app.Recipe); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipe.EnsureLatest(app.Recipe); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } @@ -219,7 +220,7 @@ recipes. } if !internal.Chaos { - if err := recipePkg.EnsureVersion(app.Recipe, chosenUpgrade); err != nil { + if err := r.EnsureVersion(chosenUpgrade); err != nil { log.Fatal(err) } } @@ -227,7 +228,7 @@ recipes. if internal.Chaos { log.Warn("chaos mode engaged") var err error - chosenUpgrade, err = recipePkg.ChaosVersion(app.Recipe) + chosenUpgrade, err = r.ChaosVersion() if err != nil { log.Fatal(err) } diff --git a/cli/recipe/fetch.go b/cli/recipe/fetch.go index 4bb0cb28..877700c7 100644 --- a/cli/recipe/fetch.go +++ b/cli/recipe/fetch.go @@ -24,9 +24,10 @@ var recipeFetchCommand = cli.Command{ BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipeName := c.Args().First() + r := recipe.Get2(recipeName) if recipeName != "" { internal.ValidateRecipe(c) - if err := recipe.Ensure(recipeName); err != nil { + if err := r.Ensure(); err != nil { log.Fatal(err) } return nil @@ -39,7 +40,8 @@ var recipeFetchCommand = cli.Command{ catlBar := formatter.CreateProgressbar(len(catalogue), "fetching latest recipes...") for recipeName := range catalogue { - if err := recipe.Ensure(recipeName); err != nil { + r := recipe.Get2(recipeName) + if err := r.Ensure(); err != nil { log.Error(err) } catlBar.Add(1) diff --git a/cli/recipe/lint.go b/cli/recipe/lint.go index 41a78db5..ecddc12b 100644 --- a/cli/recipe/lint.go +++ b/cli/recipe/lint.go @@ -28,23 +28,24 @@ var recipeLintCommand = cli.Command{ BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) + r := recipePkg.Get2(recipe.Name) - if err := recipePkg.EnsureExists(recipe.Name); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := recipePkg.EnsureIsClean(recipe.Name); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := recipePkg.EnsureLatest(recipe.Name); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } } diff --git a/cli/recipe/upgrade.go b/cli/recipe/upgrade.go index f6011b62..f51d5a96 100644 --- a/cli/recipe/upgrade.go +++ b/cli/recipe/upgrade.go @@ -72,20 +72,21 @@ You may invoke this command in "wizard" mode and be prompted for input: BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) + r := recipePkg.Get2(recipe.Name) - if err := recipePkg.EnsureIsClean(recipe.Name); err != nil { + if err := r.EnsureIsClean(); err != nil { log.Fatal(err) } - if err := recipePkg.EnsureExists(recipe.Name); err != nil { + if err := r.EnsureExists(); err != nil { log.Fatal(err) } - if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil { + if err := r.EnsureUpToDate(); err != nil { log.Fatal(err) } - if err := recipePkg.EnsureLatest(recipe.Name); err != nil { + if err := r.EnsureLatest(); err != nil { log.Fatal(err) } diff --git a/cli/updater/updater.go b/cli/updater/updater.go index 7fb7a2bd..49d0e854 100644 --- a/cli/updater/updater.go +++ b/cli/updater/updater.go @@ -318,20 +318,20 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName // processRecipeRepoVersion clones, pulls, checks out the version and lints the // recipe repository. -func processRecipeRepoVersion(recipeName, version string) error { - if err := recipe.EnsureExists(recipeName); err != nil { +func processRecipeRepoVersion(r recipe.Recipe2, version string) error { + if err := r.EnsureExists(); err != nil { return err } - if err := recipe.EnsureUpToDate(recipeName); err != nil { + if err := r.EnsureUpToDate(); err != nil { return err } - if err := recipe.EnsureVersion(recipeName, version); err != nil { + if err := r.EnsureVersion(version); err != nil { return err } - if r, err := recipe.Get(recipeName, internal.Offline); err != nil { + if r, err := recipe.Get(r.Name, internal.Offline); err != nil { return err } else if err := lint.LintForErrors(r); err != nil { return err @@ -445,7 +445,9 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName, Env: env, } - if err = processRecipeRepoVersion(recipeName, upgradeVersion); err != nil { + r := recipe.Get2(recipeName) + + if err = processRecipeRepoVersion(r, upgradeVersion); err != nil { return err } diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index a112a256..bc343984 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -213,21 +213,22 @@ func (r Recipe) Tags() ([]string, error) { // Get retrieves a recipe. func Get(recipeName string, offline bool) (Recipe, error) { - if err := EnsureExists(recipeName); err != nil { + r := Get2(recipeName) + if err := r.EnsureExists(); err != nil { return Recipe{}, err } - pattern := fmt.Sprintf("%s/%s/compose**yml", config.RECIPES_DIR, recipeName) + pattern := fmt.Sprintf("%s/%s/compose**yml", config.RECIPES_DIR, r.Name) composeFiles, err := filepath.Glob(pattern) if err != nil { return Recipe{}, err } if len(composeFiles) == 0 { - return Recipe{}, fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", recipeName) + return Recipe{}, fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", r.Name) } - envSamplePath := path.Join(config.RECIPES_DIR, recipeName, ".env.sample") + envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample") sampleEnv, err := envfile.ReadEnv(envSamplePath) if err != nil { return Recipe{}, err @@ -239,7 +240,7 @@ func Get(recipeName string, offline bool) (Recipe, error) { return Recipe{}, err } - meta, err := GetRecipeMeta(recipeName, offline) + meta, err := GetRecipeMeta(r.Name, offline) if err != nil { switch err.(type) { case RecipeMissingFromCatalogue: @@ -265,27 +266,35 @@ func (r Recipe) SampleEnv() (map[string]string, error) { return sampleEnv, nil } +func Get2(name string) Recipe2 { + return Recipe2{Name: name} +} + +type Recipe2 struct { + Name string +} + // Ensure makes sure the recipe exists, is up to date and has the latest version checked out. -func Ensure(recipeName string) error { - if err := EnsureExists(recipeName); err != nil { +func (r Recipe2) Ensure() error { + if err := r.EnsureExists(); err != nil { return err } - if err := EnsureUpToDate(recipeName); err != nil { + if err := r.EnsureUpToDate(); err != nil { return err } - if err := EnsureLatest(recipeName); err != nil { + if err := r.EnsureLatest(); err != nil { return err } return nil } -// EnsureExists ensures that a recipe is locally cloned -func EnsureExists(recipeName string) error { - recipeDir := path.Join(config.RECIPES_DIR, recipeName) +// EnsureExists ensures that the recipe is locally cloned +func (r Recipe2) EnsureExists() error { + recipeDir := path.Join(config.RECIPES_DIR, r.Name) if _, err := os.Stat(recipeDir); os.IsNotExist(err) { log.Debugf("%s does not exist, attemmpting to clone", recipeDir) - url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, recipeName) + url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, r.Name) if err := gitPkg.Clone(recipeDir, url); err != nil { return err } @@ -299,8 +308,8 @@ func EnsureExists(recipeName string) error { } // EnsureVersion checks whether a specific version exists for a recipe. -func EnsureVersion(recipeName, version string) error { - recipeDir := path.Join(config.RECIPES_DIR, recipeName) +func (r Recipe2) EnsureVersion(version string) error { + recipeDir := path.Join(config.RECIPES_DIR, r.Name) if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { return err @@ -330,11 +339,11 @@ func EnsureVersion(recipeName, version string) error { joinedTags := strings.Join(parsedTags, ", ") if joinedTags != "" { - log.Debugf("read %s as tags for recipe %s", joinedTags, recipeName) + log.Debugf("read %s as tags for recipe %s", joinedTags, r.Name) } if tagRef.String() == "" { - return fmt.Errorf("the local copy of %s doesn't seem to have version %s available?", recipeName, version) + return fmt.Errorf("the local copy of %s doesn't seem to have version %s available?", r.Name, version) } worktree, err := repo.Worktree() @@ -351,14 +360,14 @@ func EnsureVersion(recipeName, version string) error { return err } - log.Debugf("successfully checked %s out to %s in %s", recipeName, tagRef.Short(), recipeDir) + log.Debugf("successfully checked %s out to %s in %s", r.Name, tagRef.Short(), recipeDir) return nil } // EnsureIsClean makes sure that the recipe repository has no unstaged changes. -func EnsureIsClean(recipeName string) error { - recipeDir := path.Join(config.RECIPES_DIR, recipeName) +func (r Recipe2) EnsureIsClean() error { + recipeDir := path.Join(config.RECIPES_DIR, r.Name) isClean, err := gitPkg.IsClean(recipeDir) if err != nil { @@ -367,15 +376,15 @@ func EnsureIsClean(recipeName string) error { if !isClean { msg := "%s (%s) has locally unstaged changes? please commit/remove your changes before proceeding" - return fmt.Errorf(msg, recipeName, recipeDir) + return fmt.Errorf(msg, r.Name, recipeDir) } return nil } -// EnsureLatest makes sure the latest commit is checked out for a local recipe repository -func EnsureLatest(recipeName string) error { - recipeDir := path.Join(config.RECIPES_DIR, recipeName) +// EnsureLatest makes sure the latest commit is checked out for the local recipe repository +func (r Recipe2) EnsureLatest() error { + recipeDir := path.Join(config.RECIPES_DIR, r.Name) if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { return err @@ -410,18 +419,71 @@ func EnsureLatest(recipeName string) error { return nil } +// EnsureUpToDate ensures that the local repo is synced to the remote +func (r Recipe2) EnsureUpToDate() error { + recipeDir := path.Join(config.RECIPES_DIR, r.Name) + + repo, err := git.PlainOpen(recipeDir) + if err != nil { + return fmt.Errorf("unable to open %s: %s", recipeDir, err) + } + + remotes, err := repo.Remotes() + if err != nil { + return fmt.Errorf("unable to read remotes in %s: %s", recipeDir, err) + } + + if len(remotes) == 0 { + log.Debugf("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", recipeDir, err) + } + + branch, err := gitPkg.CheckoutDefaultBranch(repo, recipeDir) + if err != nil { + return fmt.Errorf("unable to check out default branch in %s: %s", recipeDir, 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", recipeDir, err) + } + } + + opts := &git.PullOptions{ + Force: true, + ReferenceName: branch, + SingleBranch: true, + } + + 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", recipeDir, err) + } + } + + log.Debugf("fetched latest git changes for %s", r.Name) + + return nil +} + // ChaosVersion constructs a chaos mode recipe version. -func ChaosVersion(recipeName string) (string, error) { +func (r Recipe2) ChaosVersion() (string, error) { var version string - head, err := gitPkg.GetRecipeHead(recipeName) + head, err := gitPkg.GetRecipeHead(r.Name) if err != nil { return version, err } version = formatter.SmallSHA(head.String()) - recipeDir := path.Join(config.RECIPES_DIR, recipeName) + recipeDir := path.Join(config.RECIPES_DIR, r.Name) isClean, err := gitPkg.IsClean(recipeDir) if err != nil { return version, err @@ -597,59 +659,6 @@ func GetStringInBetween(recipeName, str, start, end string) (result string, err return str[s : s+e], nil } -// EnsureUpToDate ensures that the local repo is synced to the remote -func EnsureUpToDate(recipeName string) error { - recipeDir := path.Join(config.RECIPES_DIR, recipeName) - - repo, err := git.PlainOpen(recipeDir) - if err != nil { - return fmt.Errorf("unable to open %s: %s", recipeDir, err) - } - - remotes, err := repo.Remotes() - if err != nil { - return fmt.Errorf("unable to read remotes in %s: %s", recipeDir, err) - } - - if len(remotes) == 0 { - log.Debugf("cannot ensure %s is up-to-date, no git remotes configured", recipeName) - return nil - } - - worktree, err := repo.Worktree() - if err != nil { - return fmt.Errorf("unable to open git work tree in %s: %s", recipeDir, err) - } - - branch, err := gitPkg.CheckoutDefaultBranch(repo, recipeDir) - if err != nil { - return fmt.Errorf("unable to check out default branch in %s: %s", recipeDir, 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", recipeDir, err) - } - } - - opts := &git.PullOptions{ - Force: true, - ReferenceName: branch, - SingleBranch: true, - } - - 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", recipeDir, err) - } - } - - log.Debugf("fetched latest git changes for %s", recipeName) - - return nil -} - // ReadRecipeCatalogue reads the recipe catalogue. func ReadRecipeCatalogue(offline bool) (RecipeCatalogue, error) { recipes := make(RecipeCatalogue) From eee2ecda0677eee78a3ba2ea55a28168de9c2a2e Mon Sep 17 00:00:00 2001 From: p4u1 Date: Sun, 7 Jul 2024 12:39:02 +0200 Subject: [PATCH 02/19] refactor(recipe): add offline and chaos options to Ensure method --- cli/recipe/fetch.go | 4 ++-- pkg/recipe/recipe.go | 20 ++++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/cli/recipe/fetch.go b/cli/recipe/fetch.go index 877700c7..62db1256 100644 --- a/cli/recipe/fetch.go +++ b/cli/recipe/fetch.go @@ -27,7 +27,7 @@ var recipeFetchCommand = cli.Command{ r := recipe.Get2(recipeName) if recipeName != "" { internal.ValidateRecipe(c) - if err := r.Ensure(); err != nil { + if err := r.Ensure(false, false); err != nil { log.Fatal(err) } return nil @@ -41,7 +41,7 @@ var recipeFetchCommand = cli.Command{ catlBar := formatter.CreateProgressbar(len(catalogue), "fetching latest recipes...") for recipeName := range catalogue { r := recipe.Get2(recipeName) - if err := r.Ensure(); err != nil { + if err := r.Ensure(false, false); err != nil { log.Error(err) } catlBar.Add(1) diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index bc343984..0ac5a85c 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -275,15 +275,23 @@ type Recipe2 struct { } // Ensure makes sure the recipe exists, is up to date and has the latest version checked out. -func (r Recipe2) Ensure() error { +func (r Recipe2) Ensure(chaos bool, offline bool) error { if err := r.EnsureExists(); err != nil { return err } - if err := r.EnsureUpToDate(); err != nil { - return err - } - if err := r.EnsureLatest(); err != nil { - return err + + if !chaos { + if err := r.EnsureIsClean(); err != nil { + return err + } + if !offline { + if err := r.EnsureUpToDate(); err != nil { + log.Fatal(err) + } + } + if err := r.EnsureLatest(); err != nil { + return err + } } return nil } From 01f3f4be173e11883e314ddaacb8c18be98e2424 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Sun, 7 Jul 2024 12:46:32 +0200 Subject: [PATCH 03/19] refactor(recipe): use new recipe.Ensure method --- cli/app/backup.go | 18 +----------------- cli/app/check.go | 20 ++------------------ cli/app/cmd.go | 20 ++------------------ cli/app/deploy.go | 20 ++------------------ cli/app/restore.go | 20 ++------------------ cli/app/rollback.go | 20 ++------------------ cli/app/secret.go | 20 ++------------------ cli/app/upgrade.go | 18 +++--------------- cli/recipe/lint.go | 20 ++------------------ cli/recipe/upgrade.go | 16 ++-------------- 10 files changed, 20 insertions(+), 172 deletions(-) diff --git a/cli/app/backup.go b/cli/app/backup.go index 75d9eb6b..a44609a2 100644 --- a/cli/app/backup.go +++ b/cli/app/backup.go @@ -48,26 +48,10 @@ var appBackupListCommand = cli.Command{ app := internal.ValidateApp(c) r := recipe.Get2(app.Recipe) - if err := r.EnsureExists(); err != nil { + if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } - if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { - log.Fatal(err) - } - - if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { - log.Fatal(err) - } - } - - if err := r.EnsureLatest(); err != nil { - log.Fatal(err) - } - } - cl, err := client.New(app.Server) if err != nil { log.Fatal(err) diff --git a/cli/app/check.go b/cli/app/check.go index 002a2978..fe87298e 100644 --- a/cli/app/check.go +++ b/cli/app/check.go @@ -36,28 +36,12 @@ ${FOO:} syntax). "check" does not confirm or deny this for you.`, BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) - - if err := r.EnsureExists(); err != nil { + if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } - if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { - log.Fatal(err) - } - - if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { - log.Fatal(err) - } - } - - if err := r.EnsureLatest(); err != nil { - log.Fatal(err) - } - } - tableCol := []string{"recipe env sample", "app env"} table := formatter.CreateTable(tableCol) diff --git a/cli/app/cmd.go b/cli/app/cmd.go index a92dc946..33cec9a8 100644 --- a/cli/app/cmd.go +++ b/cli/app/cmd.go @@ -59,28 +59,12 @@ Example: }, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Name) - if err := r.EnsureExists(); err != nil { + r := recipe.Get2(app.Recipe) + if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } - if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { - log.Fatal(err) - } - - if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { - log.Fatal(err) - } - } - - if err := r.EnsureLatest(); err != nil { - log.Fatal(err) - } - } - if internal.LocalCmd && internal.RemoteUser != "" { internal.ShowSubcommandHelpAndError(c, errors.New("cannot use --local & --user together")) } diff --git a/cli/app/deploy.go b/cli/app/deploy.go index 27716276..138e0330 100644 --- a/cli/app/deploy.go +++ b/cli/app/deploy.go @@ -52,33 +52,17 @@ recipes. Action: func(c *cli.Context) error { app := internal.ValidateApp(c) stackName := app.StackName() - r2 := recipe.Get2(app.Recipe) specificVersion := c.Args().Get(1) if specificVersion != "" && internal.Chaos { log.Fatal("cannot use and --chaos together") } - if err := r2.EnsureExists(); err != nil { + r2 := recipe.Get2(app.Recipe) + if err := r2.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } - if !internal.Chaos { - if err := r2.EnsureIsClean(); err != nil { - log.Fatal(err) - } - - if !internal.Offline { - if err := r2.EnsureUpToDate(); err != nil { - log.Fatal(err) - } - } - - if err := r2.EnsureLatest(); err != nil { - log.Fatal(err) - } - } - r, err := recipe.Get(app.Recipe, internal.Offline) if err != nil { log.Fatal(err) diff --git a/cli/app/restore.go b/cli/app/restore.go index b6605d29..5f3c30ce 100644 --- a/cli/app/restore.go +++ b/cli/app/restore.go @@ -32,28 +32,12 @@ var appRestoreCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) - - if err := r.EnsureExists(); err != nil { + if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } - if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { - log.Fatal(err) - } - - if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { - log.Fatal(err) - } - } - - if err := r.EnsureLatest(); err != nil { - log.Fatal(err) - } - } - cl, err := client.New(app.Server) if err != nil { log.Fatal(err) diff --git a/cli/app/rollback.go b/cli/app/rollback.go index 82eae9cc..edade3d0 100644 --- a/cli/app/rollback.go +++ b/cli/app/rollback.go @@ -52,33 +52,17 @@ recipes. Action: func(c *cli.Context) error { app := internal.ValidateApp(c) stackName := app.StackName() - r2 := recipe.Get2(app.Recipe) specificVersion := c.Args().Get(1) if specificVersion != "" && internal.Chaos { log.Fatal("cannot use and --chaos together") } - if err := r2.EnsureExists(); err != nil { + r2 := recipe.Get2(app.Recipe) + if err := r2.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } - if !internal.Chaos { - if err := r2.EnsureIsClean(); err != nil { - log.Fatal(err) - } - - if !internal.Offline { - if err := r2.EnsureUpToDate(); err != nil { - log.Fatal(err) - } - } - - if err := r2.EnsureLatest(); err != nil { - log.Fatal(err) - } - } - r, err := recipe.Get(app.Recipe, internal.Offline) if err != nil { log.Fatal(err) diff --git a/cli/app/secret.go b/cli/app/secret.go index 0f995fd0..22ad9e9d 100644 --- a/cli/app/secret.go +++ b/cli/app/secret.go @@ -56,28 +56,12 @@ var appSecretGenerateCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) + r := recipe.Get2(app.Recipe) - - if err := r.EnsureExists(); err != nil { + if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } - if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { - log.Fatal(err) - } - - if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { - log.Fatal(err) - } - } - - if err := r.EnsureLatest(); err != nil { - log.Fatal(err) - } - } - if len(c.Args()) == 1 && !allSecrets { err := errors.New("missing arguments / or '--all'") internal.ShowSubcommandHelpAndError(c, err) diff --git a/cli/app/upgrade.go b/cli/app/upgrade.go index f4d2bf85..fe61d5be 100644 --- a/cli/app/upgrade.go +++ b/cli/app/upgrade.go @@ -58,27 +58,15 @@ recipes. Action: func(c *cli.Context) error { app := internal.ValidateApp(c) stackName := app.StackName() - r := recipe.Get2(app.Name) specificVersion := c.Args().Get(1) if specificVersion != "" && internal.Chaos { log.Fatal("cannot use and --chaos together") } - if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { - log.Fatal(err) - } - - if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { - log.Fatal(err) - } - } - - if err := r.EnsureLatest(); err != nil { - log.Fatal(err) - } + r := recipe.Get2(app.Recipe) + if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { + log.Fatal(err) } recipe, err := recipePkg.Get(app.Recipe, internal.Offline) diff --git a/cli/recipe/lint.go b/cli/recipe/lint.go index ecddc12b..079a0a53 100644 --- a/cli/recipe/lint.go +++ b/cli/recipe/lint.go @@ -28,28 +28,12 @@ var recipeLintCommand = cli.Command{ BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) + r := recipePkg.Get2(recipe.Name) - - if err := r.EnsureExists(); err != nil { + if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } - if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { - log.Fatal(err) - } - - if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { - log.Fatal(err) - } - } - - if err := r.EnsureLatest(); err != nil { - log.Fatal(err) - } - } - tableCol := []string{"ref", "rule", "severity", "satisfied", "skipped", "resolve"} table := formatter.CreateTable(tableCol) diff --git a/cli/recipe/upgrade.go b/cli/recipe/upgrade.go index f51d5a96..bd8f339a 100644 --- a/cli/recipe/upgrade.go +++ b/cli/recipe/upgrade.go @@ -72,21 +72,9 @@ You may invoke this command in "wizard" mode and be prompted for input: BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) + r := recipePkg.Get2(recipe.Name) - - if err := r.EnsureIsClean(); err != nil { - log.Fatal(err) - } - - if err := r.EnsureExists(); err != nil { - log.Fatal(err) - } - - if err := r.EnsureUpToDate(); err != nil { - log.Fatal(err) - } - - if err := r.EnsureLatest(); err != nil { + if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } From 4cf6155fb8c43f2546194f61596f3e17879c1b50 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Sun, 7 Jul 2024 12:54:50 +0200 Subject: [PATCH 04/19] refactor(recipe): introduce Dir var --- pkg/recipe/recipe.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 0ac5a85c..d172a1f5 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -267,11 +267,15 @@ func (r Recipe) SampleEnv() (map[string]string, error) { } func Get2(name string) Recipe2 { - return Recipe2{Name: name} + return Recipe2{ + Name: name, + Dir: path.Join(config.RECIPES_DIR, name), + } } type Recipe2 struct { Name string + Dir string } // Ensure makes sure the recipe exists, is up to date and has the latest version checked out. From 47013c63d612cdc68c10eb77b774700e6e0421bd Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 10:32:36 +0200 Subject: [PATCH 05/19] refactor(recipe): use template for ssh url --- cli/recipe/release.go | 24 ++++++++++++---------- pkg/recipe/recipe.go | 48 ++++++++++++++++++++++--------------------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/cli/recipe/release.go b/cli/recipe/release.go index ad403c33..df3c5bd4 100644 --- a/cli/recipe/release.go +++ b/cli/recipe/release.go @@ -20,6 +20,7 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/distribution/reference" "github.com/go-git/go-git/v5" + "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -62,6 +63,7 @@ your SSH keys configured on your account. BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) + r := recipePkg.Get2(recipe.Name) imagesTmp, err := getImageVersions(recipe) if err != nil { @@ -90,7 +92,7 @@ your SSH keys configured on your account. } if tagString != "" { - if err := createReleaseFromTag(recipe, tagString, mainAppVersion); err != nil { + if err := createReleaseFromTag(r, tagString, mainAppVersion); err != nil { log.Fatal(err) } } @@ -121,14 +123,14 @@ your SSH keys configured on your account. } if len(tags) > 0 { - log.Warnf("previous git tags detected, assuming this is a new semver release") - if err := createReleaseFromPreviousTag(tagString, mainAppVersion, recipe, tags); err != nil { + logrus.Warnf("previous git tags detected, assuming this is a new semver release") + if err := createReleaseFromPreviousTag(tagString, mainAppVersion, r, 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) - if err := createReleaseFromTag(recipe, tagString, mainAppVersion); err != nil { + if err := createReleaseFromTag(r, tagString, mainAppVersion); err != nil { if cleanUpErr := cleanUpTag(tagString, recipe.Name); err != nil { log.Fatal(cleanUpErr) } @@ -181,7 +183,7 @@ func getImageVersions(recipe recipe.Recipe) (map[string]string, error) { } // createReleaseFromTag creates a new release based on a supplied recipe version string -func createReleaseFromTag(recipe recipe.Recipe, tagString, mainAppVersion string) error { +func createReleaseFromTag(recipe recipe.Recipe2, tagString, mainAppVersion string) error { var err error directory := path.Join(config.RECIPES_DIR, recipe.Name) @@ -245,7 +247,7 @@ func getTagCreateOptions(tag string) (git.CreateTagOptions, error) { // addReleaseNotes checks if the release/next release note exists and moves the // file to release/. -func addReleaseNotes(recipe recipe.Recipe, tag string) error { +func addReleaseNotes(recipe recipe.Recipe2, tag string) error { repoPath := path.Join(config.RECIPES_DIR, recipe.Name) tagReleaseNotePath := path.Join(repoPath, "release", tag) if _, err := os.Stat(tagReleaseNotePath); err == nil { @@ -319,20 +321,20 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error { return nil } -func commitRelease(recipe recipe.Recipe, tag string) error { +func commitRelease(recipe recipe.Recipe2, tag string) error { if internal.Dry { log.Debugf("dry run: no changes committed") return nil } - isClean, err := gitPkg.IsClean(recipe.Dir()) + isClean, err := gitPkg.IsClean(recipe.Dir) if err != nil { return err } if isClean { if !internal.Dry { - return fmt.Errorf("no changes discovered in %s, nothing to publish?", recipe.Dir()) + return fmt.Errorf("no changes discovered in %s, nothing to publish?", recipe.Dir) } } @@ -372,7 +374,7 @@ func tagRelease(tagString string, repo *git.Repository) error { return nil } -func pushRelease(recipe recipe.Recipe, tagString string) error { +func pushRelease(recipe recipe.Recipe2, tagString string) error { if internal.Dry { log.Info("dry run: no changes published") return nil @@ -401,7 +403,7 @@ func pushRelease(recipe recipe.Recipe, tagString string) error { return nil } -func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recipe.Recipe, tags []string) error { +func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recipe.Recipe2, tags []string) error { directory := path.Join(config.RECIPES_DIR, recipe.Name) repo, err := git.PlainOpen(directory) if err != nil { diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index d172a1f5..21b1df00 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -138,25 +138,6 @@ type Recipe struct { Meta RecipeMeta } -// Push pushes the latest changes to a SSH URL remote. You need to have your -// local SSH configuration for git.coopcloud.tech working for this to work -func (r Recipe) Push(dryRun bool) error { - repo, err := git.PlainOpen(r.Dir()) - if err != nil { - return err - } - - if err := gitPkg.CreateRemote(repo, "origin-ssh", r.Meta.SSHURL, dryRun); err != nil { - return err - } - - if err := gitPkg.Push(r.Dir(), "origin-ssh", true, dryRun); err != nil { - return err - } - - return nil -} - // Dir retrieves the recipe repository path func (r Recipe) Dir() string { return path.Join(config.RECIPES_DIR, r.Name) @@ -268,14 +249,16 @@ func (r Recipe) SampleEnv() (map[string]string, error) { func Get2(name string) Recipe2 { return Recipe2{ - Name: name, - Dir: path.Join(config.RECIPES_DIR, name), + Name: name, + Dir: path.Join(config.RECIPES_DIR, name), + SSHURL: fmt.Sprintf(config.SSH_URL_TEMPLATE, name), } } type Recipe2 struct { - Name string - Dir string + Name string + Dir string + SSHURL string } // Ensure makes sure the recipe exists, is up to date and has the latest version checked out. @@ -508,6 +491,25 @@ func (r Recipe2) ChaosVersion() (string, error) { return version, nil } +// Push pushes the latest changes to a SSH URL remote. You need to have your +// local SSH configuration for git.coopcloud.tech working for this to work +func (r Recipe2) Push(dryRun bool) error { + repo, err := git.PlainOpen(r.Dir) + if err != nil { + return err + } + + if err := gitPkg.CreateRemote(repo, "origin-ssh", r.SSHURL, dryRun); err != nil { + return err + } + + if err := gitPkg.Push(r.Dir, "origin-ssh", true, dryRun); err != nil { + return err + } + + return nil +} + // GetRecipesLocal retrieves all local recipe directories func GetRecipesLocal() ([]string, error) { var recipes []string From f268e5893b14df893258ec039fcc187cf9492948 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 11:00:50 +0200 Subject: [PATCH 06/19] refactor(recipe): move functions that operate on the git repo to new file --- pkg/recipe/git.go | 264 +++++++++++++++++++++++++++++++++++++++++++ pkg/recipe/recipe.go | 249 ---------------------------------------- 2 files changed, 264 insertions(+), 249 deletions(-) create mode 100644 pkg/recipe/git.go diff --git a/pkg/recipe/git.go b/pkg/recipe/git.go new file mode 100644 index 00000000..ba1b0972 --- /dev/null +++ b/pkg/recipe/git.go @@ -0,0 +1,264 @@ +package recipe + +import ( + "fmt" + "os" + "path" + "strings" + + "coopcloud.tech/abra/pkg/config" + "coopcloud.tech/abra/pkg/formatter" + gitPkg "coopcloud.tech/abra/pkg/git" + "coopcloud.tech/abra/pkg/log" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" +) + +// Ensure makes sure the recipe exists, is up to date and has the latest version checked out. +func (r Recipe2) Ensure(chaos bool, offline bool) error { + if err := r.EnsureExists(); err != nil { + return err + } + + if !chaos { + if err := r.EnsureIsClean(); err != nil { + return err + } + if !offline { + if err := r.EnsureUpToDate(); err != nil { + log.Fatal(err) + } + } + if err := r.EnsureLatest(); err != nil { + return err + } + } + return nil +} + +// EnsureExists ensures that the recipe is locally cloned +func (r Recipe2) EnsureExists() error { + recipeDir := path.Join(config.RECIPES_DIR, r.Name) + + if _, err := os.Stat(recipeDir); os.IsNotExist(err) { + log.Debugf("%s does not exist, attemmpting to clone", recipeDir) + url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, r.Name) + if err := gitPkg.Clone(recipeDir, url); err != nil { + return err + } + } + + if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { + return err + } + + return nil +} + +// EnsureVersion checks whether a specific version exists for a recipe. +func (r Recipe2) EnsureVersion(version string) error { + recipeDir := path.Join(config.RECIPES_DIR, r.Name) + + if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { + return err + } + + repo, err := git.PlainOpen(recipeDir) + if err != nil { + return err + } + + tags, err := repo.Tags() + if err != nil { + return nil + } + + var parsedTags []string + var tagRef plumbing.ReferenceName + if err := tags.ForEach(func(ref *plumbing.Reference) (err error) { + parsedTags = append(parsedTags, ref.Name().Short()) + if ref.Name().Short() == version { + tagRef = ref.Name() + } + return nil + }); err != nil { + return err + } + + joinedTags := strings.Join(parsedTags, ", ") + if joinedTags != "" { + log.Debugf("read %s as tags for recipe %s", joinedTags, r.Name) + } + + if tagRef.String() == "" { + return fmt.Errorf("the local copy of %s doesn't seem to have version %s available?", r.Name, version) + } + + worktree, err := repo.Worktree() + if err != nil { + return err + } + + opts := &git.CheckoutOptions{ + Branch: tagRef, + Create: false, + Force: true, + } + if err := worktree.Checkout(opts); err != nil { + return err + } + + log.Debugf("successfully checked %s out to %s in %s", r.Name, tagRef.Short(), recipeDir) + + return nil +} + +// EnsureIsClean makes sure that the recipe repository has no unstaged changes. +func (r Recipe2) EnsureIsClean() error { + recipeDir := path.Join(config.RECIPES_DIR, r.Name) + + isClean, err := gitPkg.IsClean(recipeDir) + if err != nil { + return fmt.Errorf("unable to check git clean status in %s: %s", recipeDir, err) + } + + if !isClean { + msg := "%s (%s) has locally unstaged changes? please commit/remove your changes before proceeding" + return fmt.Errorf(msg, r.Name, recipeDir) + } + + return nil +} + +// EnsureLatest makes sure the latest commit is checked out for the local recipe repository +func (r Recipe2) EnsureLatest() error { + recipeDir := path.Join(config.RECIPES_DIR, r.Name) + + if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { + return err + } + + repo, err := git.PlainOpen(recipeDir) + if err != nil { + return err + } + + worktree, err := repo.Worktree() + if err != nil { + return err + } + + branch, err := gitPkg.GetDefaultBranch(repo, recipeDir) + if err != nil { + return err + } + + checkOutOpts := &git.CheckoutOptions{ + Create: false, + Force: true, + Branch: plumbing.ReferenceName(branch), + } + + if err := worktree.Checkout(checkOutOpts); err != nil { + log.Debugf("failed to check out %s in %s", branch, recipeDir) + return err + } + + return nil +} + +// EnsureUpToDate ensures that the local repo is synced to the remote +func (r Recipe2) EnsureUpToDate() error { + recipeDir := path.Join(config.RECIPES_DIR, r.Name) + + repo, err := git.PlainOpen(recipeDir) + if err != nil { + return fmt.Errorf("unable to open %s: %s", recipeDir, err) + } + + remotes, err := repo.Remotes() + if err != nil { + return fmt.Errorf("unable to read remotes in %s: %s", recipeDir, err) + } + + if len(remotes) == 0 { + log.Debugf("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", recipeDir, err) + } + + branch, err := gitPkg.CheckoutDefaultBranch(repo, recipeDir) + if err != nil { + return fmt.Errorf("unable to check out default branch in %s: %s", recipeDir, 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", recipeDir, err) + } + } + + opts := &git.PullOptions{ + Force: true, + ReferenceName: branch, + SingleBranch: true, + } + + 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", recipeDir, err) + } + } + + log.Debugf("fetched latest git changes for %s", r.Name) + + return nil +} + +// ChaosVersion constructs a chaos mode recipe version. +func (r Recipe2) ChaosVersion() (string, error) { + var version string + + head, err := gitPkg.GetRecipeHead(r.Name) + if err != nil { + return version, err + } + + version = formatter.SmallSHA(head.String()) + + recipeDir := path.Join(config.RECIPES_DIR, r.Name) + isClean, err := gitPkg.IsClean(recipeDir) + if err != nil { + return version, err + } + + if !isClean { + version = fmt.Sprintf("%s + unstaged changes", version) + } + + return version, nil +} + +// Push pushes the latest changes to a SSH URL remote. You need to have your +// local SSH configuration for git.coopcloud.tech working for this to work +func (r Recipe2) Push(dryRun bool) error { + repo, err := git.PlainOpen(r.Dir) + if err != nil { + return err + } + + if err := gitPkg.CreateRemote(repo, "origin-ssh", r.SSHURL, dryRun); err != nil { + return err + } + + if err := gitPkg.Push(r.Dir, "origin-ssh", true, dryRun); err != nil { + return err + } + + return nil +} diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 21b1df00..0d0d2ba4 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -261,255 +261,6 @@ type Recipe2 struct { SSHURL string } -// Ensure makes sure the recipe exists, is up to date and has the latest version checked out. -func (r Recipe2) Ensure(chaos bool, offline bool) error { - if err := r.EnsureExists(); err != nil { - return err - } - - if !chaos { - if err := r.EnsureIsClean(); err != nil { - return err - } - if !offline { - if err := r.EnsureUpToDate(); err != nil { - log.Fatal(err) - } - } - if err := r.EnsureLatest(); err != nil { - return err - } - } - return nil -} - -// EnsureExists ensures that the recipe is locally cloned -func (r Recipe2) EnsureExists() error { - recipeDir := path.Join(config.RECIPES_DIR, r.Name) - - if _, err := os.Stat(recipeDir); os.IsNotExist(err) { - log.Debugf("%s does not exist, attemmpting to clone", recipeDir) - url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, r.Name) - if err := gitPkg.Clone(recipeDir, url); err != nil { - return err - } - } - - if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { - return err - } - - return nil -} - -// EnsureVersion checks whether a specific version exists for a recipe. -func (r Recipe2) EnsureVersion(version string) error { - recipeDir := path.Join(config.RECIPES_DIR, r.Name) - - if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { - return err - } - - repo, err := git.PlainOpen(recipeDir) - if err != nil { - return err - } - - tags, err := repo.Tags() - if err != nil { - return nil - } - - var parsedTags []string - var tagRef plumbing.ReferenceName - if err := tags.ForEach(func(ref *plumbing.Reference) (err error) { - parsedTags = append(parsedTags, ref.Name().Short()) - if ref.Name().Short() == version { - tagRef = ref.Name() - } - return nil - }); err != nil { - return err - } - - joinedTags := strings.Join(parsedTags, ", ") - if joinedTags != "" { - log.Debugf("read %s as tags for recipe %s", joinedTags, r.Name) - } - - if tagRef.String() == "" { - return fmt.Errorf("the local copy of %s doesn't seem to have version %s available?", r.Name, version) - } - - worktree, err := repo.Worktree() - if err != nil { - return err - } - - opts := &git.CheckoutOptions{ - Branch: tagRef, - Create: false, - Force: true, - } - if err := worktree.Checkout(opts); err != nil { - return err - } - - log.Debugf("successfully checked %s out to %s in %s", r.Name, tagRef.Short(), recipeDir) - - return nil -} - -// EnsureIsClean makes sure that the recipe repository has no unstaged changes. -func (r Recipe2) EnsureIsClean() error { - recipeDir := path.Join(config.RECIPES_DIR, r.Name) - - isClean, err := gitPkg.IsClean(recipeDir) - if err != nil { - return fmt.Errorf("unable to check git clean status in %s: %s", recipeDir, err) - } - - if !isClean { - msg := "%s (%s) has locally unstaged changes? please commit/remove your changes before proceeding" - return fmt.Errorf(msg, r.Name, recipeDir) - } - - return nil -} - -// EnsureLatest makes sure the latest commit is checked out for the local recipe repository -func (r Recipe2) EnsureLatest() error { - recipeDir := path.Join(config.RECIPES_DIR, r.Name) - - if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { - return err - } - - repo, err := git.PlainOpen(recipeDir) - if err != nil { - return err - } - - worktree, err := repo.Worktree() - if err != nil { - return err - } - - branch, err := gitPkg.GetDefaultBranch(repo, recipeDir) - if err != nil { - return err - } - - checkOutOpts := &git.CheckoutOptions{ - Create: false, - Force: true, - Branch: plumbing.ReferenceName(branch), - } - - if err := worktree.Checkout(checkOutOpts); err != nil { - log.Debugf("failed to check out %s in %s", branch, recipeDir) - return err - } - - return nil -} - -// EnsureUpToDate ensures that the local repo is synced to the remote -func (r Recipe2) EnsureUpToDate() error { - recipeDir := path.Join(config.RECIPES_DIR, r.Name) - - repo, err := git.PlainOpen(recipeDir) - if err != nil { - return fmt.Errorf("unable to open %s: %s", recipeDir, err) - } - - remotes, err := repo.Remotes() - if err != nil { - return fmt.Errorf("unable to read remotes in %s: %s", recipeDir, err) - } - - if len(remotes) == 0 { - log.Debugf("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", recipeDir, err) - } - - branch, err := gitPkg.CheckoutDefaultBranch(repo, recipeDir) - if err != nil { - return fmt.Errorf("unable to check out default branch in %s: %s", recipeDir, 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", recipeDir, err) - } - } - - opts := &git.PullOptions{ - Force: true, - ReferenceName: branch, - SingleBranch: true, - } - - 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", recipeDir, err) - } - } - - log.Debugf("fetched latest git changes for %s", r.Name) - - return nil -} - -// ChaosVersion constructs a chaos mode recipe version. -func (r Recipe2) ChaosVersion() (string, error) { - var version string - - head, err := gitPkg.GetRecipeHead(r.Name) - if err != nil { - return version, err - } - - version = formatter.SmallSHA(head.String()) - - recipeDir := path.Join(config.RECIPES_DIR, r.Name) - isClean, err := gitPkg.IsClean(recipeDir) - if err != nil { - return version, err - } - - if !isClean { - version = fmt.Sprintf("%s + unstaged changes", version) - } - - return version, nil -} - -// Push pushes the latest changes to a SSH URL remote. You need to have your -// local SSH configuration for git.coopcloud.tech working for this to work -func (r Recipe2) Push(dryRun bool) error { - repo, err := git.PlainOpen(r.Dir) - if err != nil { - return err - } - - if err := gitPkg.CreateRemote(repo, "origin-ssh", r.SSHURL, dryRun); err != nil { - return err - } - - if err := gitPkg.Push(r.Dir, "origin-ssh", true, dryRun); err != nil { - return err - } - - return nil -} - // GetRecipesLocal retrieves all local recipe directories func GetRecipesLocal() ([]string, error) { var recipes []string From 73e9b818b46e7c15adbcce9b58c3fdf7fde03d89 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 11:02:43 +0200 Subject: [PATCH 07/19] refactor(recipe): move SampleEnv method to new struct --- cli/app/new.go | 2 +- pkg/recipe/files.go | 18 ++++++++++++++++++ pkg/recipe/recipe.go | 9 --------- 3 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 pkg/recipe/files.go diff --git a/cli/app/new.go b/cli/app/new.go index 63aff1de..d0de12b3 100644 --- a/cli/app/new.go +++ b/cli/app/new.go @@ -132,7 +132,7 @@ var appNewCommand = cli.Command{ var secrets AppSecrets var secretTable *jsontable.JSONTable if internal.Secrets { - sampleEnv, err := recipe.SampleEnv() + sampleEnv, err := r.SampleEnv() if err != nil { log.Fatal(err) } diff --git a/pkg/recipe/files.go b/pkg/recipe/files.go new file mode 100644 index 00000000..6177458f --- /dev/null +++ b/pkg/recipe/files.go @@ -0,0 +1,18 @@ +package recipe + +import ( + "fmt" + "path" + + "coopcloud.tech/abra/pkg/config" + "coopcloud.tech/abra/pkg/envfile" +) + +func (r Recipe2) SampleEnv() (map[string]string, error) { + envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample") + sampleEnv, err := envfile.ReadEnv(envSamplePath) + if err != nil { + return sampleEnv, fmt.Errorf("unable to discover .env.sample for %s", r.Name) + } + return sampleEnv, nil +} diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 0d0d2ba4..6bc75f4a 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -238,15 +238,6 @@ func Get(recipeName string, offline bool) (Recipe, error) { }, nil } -func (r Recipe) SampleEnv() (map[string]string, error) { - envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample") - sampleEnv, err := envfile.ReadEnv(envSamplePath) - if err != nil { - return sampleEnv, fmt.Errorf("unable to discover .env.sample for %s", r.Name) - } - return sampleEnv, nil -} - func Get2(name string) Recipe2 { return Recipe2{ Name: name, From 2f41b6d8b43b3967cd9f7682783b40257dc000d5 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 11:07:23 +0200 Subject: [PATCH 08/19] refactor(recipe): store sample env path in new struct --- pkg/recipe/recipe.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 6bc75f4a..c4ac38d4 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -239,10 +239,12 @@ func Get(recipeName string, offline bool) (Recipe, error) { } func Get2(name string) Recipe2 { + dir := path.Join(config.RECIPES_DIR, name) return Recipe2{ - Name: name, - Dir: path.Join(config.RECIPES_DIR, name), - SSHURL: fmt.Sprintf(config.SSH_URL_TEMPLATE, name), + Name: name, + Dir: dir, + SSHURL: fmt.Sprintf(config.SSH_URL_TEMPLATE, name), + SampleEnvPath: path.Join(dir, ".env.sample"), } } @@ -250,6 +252,8 @@ type Recipe2 struct { Name string Dir string SSHURL string + + SampleEnvPath string } // GetRecipesLocal retrieves all local recipe directories From c861c09cce0e618f4fd60626f700a612c9b1d122 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 11:26:01 +0200 Subject: [PATCH 09/19] refactor(recipe): use method or variable for .env.sample --- cli/app/new.go | 6 ++---- cli/recipe/new.go | 4 +++- cli/recipe/sync.go | 4 +++- cli/recipe/upgrade.go | 2 +- cli/recipe/version.go | 8 ++++---- pkg/app/app.go | 20 ++++++-------------- pkg/envfile/envfile_test.go | 17 ++++++++--------- pkg/lint/recipe.go | 15 +++++++-------- pkg/{compose => recipe}/compose.go | 23 +++++++++++------------ pkg/recipe/files.go | 5 +---- pkg/recipe/recipe.go | 28 +--------------------------- 11 files changed, 47 insertions(+), 85 deletions(-) rename pkg/{compose => recipe}/compose.go (86%) diff --git a/cli/app/new.go b/cli/app/new.go index d0de12b3..823609d9 100644 --- a/cli/app/new.go +++ b/cli/app/new.go @@ -2,7 +2,6 @@ package app import ( "fmt" - "path" "coopcloud.tech/abra/cli/internal" appPkg "coopcloud.tech/abra/pkg/app" @@ -121,7 +120,7 @@ var appNewCommand = cli.Command{ log.Debugf("%s sanitised as %s for new app", internal.Domain, sanitisedAppName) if err := appPkg.TemplateAppEnvSample( - recipe.Name, + r, internal.Domain, internal.NewAppServer, internal.Domain, @@ -142,8 +141,7 @@ var appNewCommand = cli.Command{ log.Fatal(err) } - envSamplePath := path.Join(config.RECIPES_DIR, recipe.Name, ".env.sample") - secretsConfig, err := secret.ReadSecretsConfig(envSamplePath, composeFiles, appPkg.StackName(internal.Domain)) + secretsConfig, err := secret.ReadSecretsConfig(r.SampleEnvPath, composeFiles, appPkg.StackName(internal.Domain)) if err != nil { return err } diff --git a/cli/recipe/new.go b/cli/recipe/new.go index 9d6346f2..57de11fa 100644 --- a/cli/recipe/new.go +++ b/cli/recipe/new.go @@ -12,6 +12,7 @@ import ( "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/git" "coopcloud.tech/abra/pkg/log" + "coopcloud.tech/abra/pkg/recipe" "github.com/urfave/cli" ) @@ -55,6 +56,7 @@ recipe and domain in the sample environment config). `, Action: func(c *cli.Context) error { recipeName := c.Args().First() + r := recipe.Get2(recipeName) if recipeName == "" { internal.ShowSubcommandHelpAndError(c, errors.New("no recipe name provided")) @@ -80,7 +82,7 @@ recipe and domain in the sample environment config). toParse := []string{ path.Join(config.RECIPES_DIR, recipeName, "README.md"), - path.Join(config.RECIPES_DIR, recipeName, ".env.sample"), + r.SampleEnvPath, } for _, path := range toParse { tpl, err := template.ParseFiles(path) diff --git a/cli/recipe/sync.go b/cli/recipe/sync.go index c49b8726..0e0ef874 100644 --- a/cli/recipe/sync.go +++ b/cli/recipe/sync.go @@ -10,6 +10,7 @@ import ( "coopcloud.tech/abra/pkg/config" gitPkg "coopcloud.tech/abra/pkg/git" "coopcloud.tech/abra/pkg/log" + recipePkg "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/tagcmp" "github.com/AlecAivazis/survey/v2" "github.com/go-git/go-git/v5" @@ -44,6 +45,7 @@ local file system. BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) + r := recipePkg.Get2(recipe.Name) mainApp, err := internal.GetMainAppImage(recipe) if err != nil { @@ -192,7 +194,7 @@ likely to change. mainService := "app" label := fmt.Sprintf("coop-cloud.${STACK_NAME}.version=%s", nextTag) if !internal.Dry { - if err := recipe.UpdateLabel("compose.y*ml", mainService, label); err != nil { + if err := r.UpdateLabel("compose.y*ml", mainService, label); err != nil { log.Fatal(err) } } else { diff --git a/cli/recipe/upgrade.go b/cli/recipe/upgrade.go index bd8f339a..05d44f2c 100644 --- a/cli/recipe/upgrade.go +++ b/cli/recipe/upgrade.go @@ -294,7 +294,7 @@ You may invoke this command in "wizard" mode and be prompted for input: } } if upgradeTag != "skip" { - ok, err := recipe.UpdateTag(image, upgradeTag) + ok, err := r.UpdateTag(image, upgradeTag) if err != nil { log.Fatal(err) } diff --git a/cli/recipe/version.go b/cli/recipe/version.go index 86ecc917..edad6c26 100644 --- a/cli/recipe/version.go +++ b/cli/recipe/version.go @@ -7,9 +7,9 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/formatter" - "coopcloud.tech/abra/pkg/log" recipePkg "coopcloud.tech/abra/pkg/recipe" "github.com/olekukonko/tablewriter" + "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -42,16 +42,16 @@ var recipeVersionCommand = cli.Command{ catl, err := recipePkg.ReadRecipeCatalogue(internal.Offline) if err != nil { - log.Fatal(err) + logrus.Fatal(err) } recipeMeta, ok := catl[recipe.Name] if !ok { - log.Fatalf("%s is not published on the catalogue?", recipe.Name) + logrus.Fatalf("%s is not published on the catalogue?", recipe.Name) } if len(recipeMeta.Versions) == 0 { - log.Fatalf("%s has no catalogue published versions?", recipe.Name) + logrus.Fatalf("%s has no catalogue published versions?", recipe.Name) } tableCols := []string{"version", "service", "image", "tag"} diff --git a/pkg/app/app.go b/pkg/app/app.go index 3c2ee619..dbff9be9 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -358,9 +358,8 @@ func GetAppNames() ([]string, error) { // TemplateAppEnvSample copies the example env file for the app into the users // env files. -func TemplateAppEnvSample(recipeName, appName, server, domain string) error { - envSamplePath := path.Join(config.RECIPES_DIR, recipeName, ".env.sample") - envSample, err := os.ReadFile(envSamplePath) +func TemplateAppEnvSample(r recipe.Recipe2, appName, server, domain string) error { + envSample, err := os.ReadFile(r.SampleEnvPath) if err != nil { return err } @@ -380,14 +379,14 @@ func TemplateAppEnvSample(recipeName, appName, server, domain string) error { return err } - newContents := strings.Replace(string(read), recipeName+".example.com", domain, -1) + newContents := strings.Replace(string(read), r.Name+".example.com", domain, -1) err = os.WriteFile(appEnvPath, []byte(newContents), 0) if err != nil { return err } - log.Debugf("copied & templated %s to %s", envSamplePath, appEnvPath) + log.Debugf("copied & templated %s to %s", r.SampleEnvPath, appEnvPath) return nil } @@ -511,15 +510,8 @@ func ExposeAllEnv(stackName string, compose *composetypes.Config, appEnv envfile func CheckEnv(app App) ([]envfile.EnvVar, error) { var envVars []envfile.EnvVar - envSamplePath := path.Join(config.RECIPES_DIR, app.Recipe, ".env.sample") - if _, err := os.Stat(envSamplePath); err != nil { - if os.IsNotExist(err) { - return envVars, fmt.Errorf("%s does not exist?", envSamplePath) - } - return envVars, err - } - - envSample, err := envfile.ReadEnv(envSamplePath) + r := recipe.Get2(app.Recipe) + envSample, err := r.SampleEnv() if err != nil { return envVars, err } diff --git a/pkg/envfile/envfile_test.go b/pkg/envfile/envfile_test.go index 2ecd12a3..6dc47136 100644 --- a/pkg/envfile/envfile_test.go +++ b/pkg/envfile/envfile_test.go @@ -2,7 +2,6 @@ package envfile_test import ( "fmt" - "path" "reflect" "slices" "strings" @@ -117,8 +116,8 @@ func TestCheckEnv(t *testing.T) { t.Fatal(err) } - envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample") - envSample, err := envfile.ReadEnv(envSamplePath) + r2 := recipe.Get2(r.Name) + envSample, err := r2.SampleEnv() if err != nil { t.Fatal(err) } @@ -151,8 +150,8 @@ func TestCheckEnvError(t *testing.T) { t.Fatal(err) } - envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample") - envSample, err := envfile.ReadEnv(envSamplePath) + r2 := recipe.Get2(r.Name) + envSample, err := r2.SampleEnv() if err != nil { t.Fatal(err) } @@ -187,8 +186,8 @@ func TestEnvVarCommentsRemoved(t *testing.T) { t.Fatal(err) } - envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample") - envSample, err := envfile.ReadEnv(envSamplePath) + r2 := recipe.Get2(r.Name) + envSample, err := r2.SampleEnv() if err != nil { t.Fatal(err) } @@ -219,8 +218,8 @@ func TestEnvVarModifiersIncluded(t *testing.T) { t.Fatal(err) } - envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample") - envSample, modifiers, err := envfile.ReadEnvWithModifiers(envSamplePath) + r2 := recipe.Get2(r.Name) + envSample, modifiers, err := envfile.ReadEnvWithModifiers(r2.SampleEnvPath) if err != nil { t.Fatal(err) } diff --git a/pkg/lint/recipe.go b/pkg/lint/recipe.go index 52f24522..fce04f20 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/envfile" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" recipePkg "coopcloud.tech/abra/pkg/recipe" @@ -210,9 +209,9 @@ func LintComposeVersion(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintEnvConfigPresent(recipe recipe.Recipe) (bool, error) { - envSample := fmt.Sprintf("%s/%s/.env.sample", config.RECIPES_DIR, recipe.Name) - if _, err := os.Stat(envSample); !os.IsNotExist(err) { +func LintEnvConfigPresent(r recipe.Recipe) (bool, error) { + r2 := recipe.Get2(r.Name) + if _, err := os.Stat(r2.SampleEnvPath); !os.IsNotExist(err) { return true, nil } @@ -233,11 +232,11 @@ 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) { - envSamplePath := path.Join(config.RECIPES_DIR, recipe.Name, ".env.sample") - sampleEnv, err := envfile.ReadEnv(envSamplePath) +func LintTraefikEnabledSkipCondition(r recipe.Recipe) (bool, error) { + r2 := recipe.Get2(r.Name) + sampleEnv, err := r2.SampleEnv() if err != nil { - return false, fmt.Errorf("Unable to discover .env.sample for %s", recipe.Name) + return false, fmt.Errorf("Unable to discover .env.sample for %s", r2.Name) } if _, ok := sampleEnv["DOMAIN"]; !ok { diff --git a/pkg/compose/compose.go b/pkg/recipe/compose.go similarity index 86% rename from pkg/compose/compose.go rename to pkg/recipe/compose.go index db7a7746..7e6384ba 100644 --- a/pkg/compose/compose.go +++ b/pkg/recipe/compose.go @@ -1,14 +1,11 @@ -package compose +package recipe import ( "fmt" "io/ioutil" - "path" "path/filepath" "strings" - "coopcloud.tech/abra/pkg/config" - "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/upstream/stack" @@ -18,8 +15,11 @@ import ( ) // UpdateTag updates an image tag in-place on file system local compose files. -func UpdateTag(pattern, image, tag, recipeName string) (bool, error) { - composeFiles, err := filepath.Glob(pattern) +func (r Recipe2) UpdateTag(image, tag string) (bool, error) { + fullPattern := fmt.Sprintf("%s/compose**yml", r.Dir) + image = formatter.StripTagMeta(image) + + composeFiles, err := filepath.Glob(fullPattern) if err != nil { return false, err } @@ -29,8 +29,7 @@ func UpdateTag(pattern, image, tag, recipeName string) (bool, error) { for _, composeFile := range composeFiles { opts := stack.Deploy{Composefiles: []string{composeFile}} - envSamplePath := path.Join(config.RECIPES_DIR, recipeName, ".env.sample") - sampleEnv, err := envfile.ReadEnv(envSamplePath) + sampleEnv, err := r.SampleEnv() if err != nil { return false, err } @@ -86,8 +85,9 @@ func UpdateTag(pattern, image, tag, recipeName string) (bool, error) { } // UpdateLabel updates a label in-place on file system local compose files. -func UpdateLabel(pattern, serviceName, label, recipeName string) error { - composeFiles, err := filepath.Glob(pattern) +func (r Recipe2) UpdateLabel(pattern, serviceName, label string) error { + fullPattern := fmt.Sprintf("%s/%s", r.Dir, pattern) + composeFiles, err := filepath.Glob(fullPattern) if err != nil { return err } @@ -97,8 +97,7 @@ func UpdateLabel(pattern, serviceName, label, recipeName string) error { for _, composeFile := range composeFiles { opts := stack.Deploy{Composefiles: []string{composeFile}} - envSamplePath := path.Join(config.RECIPES_DIR, recipeName, ".env.sample") - sampleEnv, err := envfile.ReadEnv(envSamplePath) + sampleEnv, err := r.SampleEnv() if err != nil { return err } diff --git a/pkg/recipe/files.go b/pkg/recipe/files.go index 6177458f..8bc76b25 100644 --- a/pkg/recipe/files.go +++ b/pkg/recipe/files.go @@ -2,15 +2,12 @@ package recipe import ( "fmt" - "path" - "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/envfile" ) func (r Recipe2) SampleEnv() (map[string]string, error) { - envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample") - sampleEnv, err := envfile.ReadEnv(envSamplePath) + sampleEnv, err := envfile.ReadEnv(r.SampleEnvPath) if err != nil { return sampleEnv, fmt.Errorf("unable to discover .env.sample for %s", r.Name) } diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index c4ac38d4..7f23b7c1 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -13,9 +13,7 @@ import ( "strings" "coopcloud.tech/abra/pkg/catalogue" - "coopcloud.tech/abra/pkg/compose" "coopcloud.tech/abra/pkg/config" - "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/formatter" gitPkg "coopcloud.tech/abra/pkg/git" "coopcloud.tech/abra/pkg/limit" @@ -143,29 +141,6 @@ func (r Recipe) Dir() string { return path.Join(config.RECIPES_DIR, r.Name) } -// UpdateLabel updates a recipe label -func (r Recipe) UpdateLabel(pattern, serviceName, label string) error { - fullPattern := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, r.Name, pattern) - if err := compose.UpdateLabel(fullPattern, serviceName, label, r.Name); err != nil { - return err - } - return nil -} - -// UpdateTag updates a recipe tag -func (r Recipe) UpdateTag(image, tag string) (bool, error) { - pattern := fmt.Sprintf("%s/%s/compose**yml", config.RECIPES_DIR, r.Name) - - image = formatter.StripTagMeta(image) - - ok, err := compose.UpdateTag(pattern, image, tag, r.Name) - if err != nil { - return false, err - } - - return ok, nil -} - // Tags list the recipe tags func (r Recipe) Tags() ([]string, error) { var tags []string @@ -209,8 +184,7 @@ func Get(recipeName string, offline bool) (Recipe, error) { return Recipe{}, fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", r.Name) } - envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample") - sampleEnv, err := envfile.ReadEnv(envSamplePath) + sampleEnv, err := r.SampleEnv() if err != nil { return Recipe{}, err } From 6f90fc3025a4390d141d96a2d4f7f428d127585d Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 11:29:20 +0200 Subject: [PATCH 10/19] refactor(recipe): don't use README.md path directly --- cli/catalogue/catalogue.go | 3 ++- cli/recipe/new.go | 6 +----- pkg/lint/recipe.go | 3 ++- pkg/recipe/recipe.go | 21 +++++++++++---------- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/cli/catalogue/catalogue.go b/cli/catalogue/catalogue.go index 52ee6923..ae319c93 100644 --- a/cli/catalogue/catalogue.go +++ b/cli/catalogue/catalogue.go @@ -57,6 +57,7 @@ keys configured on your account. BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipeName := c.Args().First() + r := recipe.Get2(recipeName) if recipeName != "" { internal.ValidateRecipe(c) @@ -103,7 +104,7 @@ keys configured on your account. log.Warn(err) } - features, category, err := recipe.GetRecipeFeaturesAndCategory(recipeMeta.Name) + features, category, err := recipe.GetRecipeFeaturesAndCategory(r) if err != nil { log.Warn(err) } diff --git a/cli/recipe/new.go b/cli/recipe/new.go index 57de11fa..39f63a6e 100644 --- a/cli/recipe/new.go +++ b/cli/recipe/new.go @@ -80,11 +80,7 @@ recipe and domain in the sample environment config). meta := newRecipeMeta(recipeName) - toParse := []string{ - path.Join(config.RECIPES_DIR, recipeName, "README.md"), - r.SampleEnvPath, - } - for _, path := range toParse { + for _, path := range []string{r.ReadmePath, r.SampleEnvPath} { tpl, err := template.ParseFiles(path) if err != nil { log.Fatal(err) diff --git a/pkg/lint/recipe.go b/pkg/lint/recipe.go index fce04f20..85e7783c 100644 --- a/pkg/lint/recipe.go +++ b/pkg/lint/recipe.go @@ -358,7 +358,8 @@ func LintHasPublishedVersion(recipe recipe.Recipe) (bool, error) { } func LintMetadataFilledIn(r recipe.Recipe) (bool, error) { - features, category, err := recipe.GetRecipeFeaturesAndCategory(r.Name) + r2 := recipe.Get2(r.Name) + features, category, err := recipe.GetRecipeFeaturesAndCategory(r2) if err != nil { return false, err } diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 7f23b7c1..3a3d83d5 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -215,9 +215,11 @@ func Get(recipeName string, offline bool) (Recipe, error) { func Get2(name string) Recipe2 { dir := path.Join(config.RECIPES_DIR, name) return Recipe2{ - Name: name, - Dir: dir, - SSHURL: fmt.Sprintf(config.SSH_URL_TEMPLATE, name), + Name: name, + Dir: dir, + SSHURL: fmt.Sprintf(config.SSH_URL_TEMPLATE, name), + + ReadmePath: path.Join(dir, "README.md"), SampleEnvPath: path.Join(dir, ".env.sample"), } } @@ -227,6 +229,7 @@ type Recipe2 struct { Dir string SSHURL string + ReadmePath string SampleEnvPath string } @@ -261,22 +264,20 @@ func GetVersionLabelLocal(recipe Recipe) (string, error) { return label, nil } -func GetRecipeFeaturesAndCategory(recipeName string) (Features, string, error) { +func GetRecipeFeaturesAndCategory(r Recipe2) (Features, string, error) { feat := Features{} var category string - readmePath := path.Join(config.RECIPES_DIR, recipeName, "README.md") + log.Debugf("attempting to open %s for recipe metadata parsing", r.ReadmePath) - log.Debugf("attempting to open %s for recipe metadata parsing", readmePath) - - readmeFS, err := ioutil.ReadFile(readmePath) + readmeFS, err := ioutil.ReadFile(r.ReadmePath) if err != nil { return feat, category, err } readmeMetadata, err := GetStringInBetween( // Find text between delimiters - recipeName, + r.Name, string(readmeFS), "", "", ) @@ -327,7 +328,7 @@ func GetRecipeFeaturesAndCategory(recipeName string) (Features, string, error) { if strings.Contains(val, "**Image**") { imageMetadata, err := GetImageMetadata(strings.TrimSpace( strings.TrimPrefix(val, "* **Image**:"), - ), recipeName) + ), r.Name) if err != nil { continue } From eb62e0ecc325e5c0a51268f963d60bc49ae4d23c Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 11:45:47 +0200 Subject: [PATCH 11/19] refactor(recipe): move Tags method to new struct --- cli/recipe/release.go | 2 +- cli/recipe/sync.go | 2 +- pkg/recipe/git.go | 26 ++++++++++++++++++++++++++ pkg/recipe/recipe.go | 26 -------------------------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/cli/recipe/release.go b/cli/recipe/release.go index df3c5bd4..fb3d22e7 100644 --- a/cli/recipe/release.go +++ b/cli/recipe/release.go @@ -97,7 +97,7 @@ your SSH keys configured on your account. } } - tags, err := recipe.Tags() + tags, err := r.Tags() if err != nil { log.Fatal(err) } diff --git a/cli/recipe/sync.go b/cli/recipe/sync.go index 0e0ef874..b671f028 100644 --- a/cli/recipe/sync.go +++ b/cli/recipe/sync.go @@ -59,7 +59,7 @@ local file system. mainAppVersion := imagesTmp[mainApp] - tags, err := recipe.Tags() + tags, err := r.Tags() if err != nil { log.Fatal(err) } diff --git a/pkg/recipe/git.go b/pkg/recipe/git.go index ba1b0972..9df862e4 100644 --- a/pkg/recipe/git.go +++ b/pkg/recipe/git.go @@ -262,3 +262,29 @@ func (r Recipe2) Push(dryRun bool) error { return nil } + +// Tags list the recipe tags +func (r Recipe2) Tags() ([]string, error) { + var tags []string + + repo, err := git.PlainOpen(r.Dir) + if err != nil { + return tags, err + } + + gitTags, err := repo.Tags() + if err != nil { + return tags, err + } + + if err := gitTags.ForEach(func(ref *plumbing.Reference) (err error) { + tags = append(tags, strings.TrimPrefix(string(ref.Name()), "refs/tags/")) + return nil + }); err != nil { + return tags, err + } + + log.Debugf("detected %s as tags for recipe %s", strings.Join(tags, ", "), r.Name) + + return tags, nil +} diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 3a3d83d5..976b0a71 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -141,32 +141,6 @@ func (r Recipe) Dir() string { return path.Join(config.RECIPES_DIR, r.Name) } -// Tags list the recipe tags -func (r Recipe) Tags() ([]string, error) { - var tags []string - - repo, err := git.PlainOpen(r.Dir()) - if err != nil { - return tags, err - } - - gitTags, err := repo.Tags() - if err != nil { - return tags, err - } - - if err := gitTags.ForEach(func(ref *plumbing.Reference) (err error) { - tags = append(tags, strings.TrimPrefix(string(ref.Name()), "refs/tags/")) - return nil - }); err != nil { - return tags, err - } - - log.Debugf("detected %s as tags for recipe %s", strings.Join(tags, ", "), r.Name) - - return tags, nil -} - // Get retrieves a recipe. func Get(recipeName string, offline bool) (Recipe, error) { r := Get2(recipeName) From ca1db33e9783b0d10e5a83522b9de1f32b185991 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 11:48:53 +0200 Subject: [PATCH 12/19] refactor(recipe): remove Dir method on old struct --- cli/recipe/release.go | 4 ++-- cli/recipe/sync.go | 4 ++-- pkg/recipe/recipe.go | 5 ----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/cli/recipe/release.go b/cli/recipe/release.go index fb3d22e7..1c2b4d92 100644 --- a/cli/recipe/release.go +++ b/cli/recipe/release.go @@ -110,14 +110,14 @@ your SSH keys configured on your account. } } - isClean, err := gitPkg.IsClean(recipe.Dir()) + isClean, err := gitPkg.IsClean(r.Dir) if err != nil { log.Fatal(err) } if !isClean { log.Infof("%s currently has these unstaged changes 👇", recipe.Name) - if err := gitPkg.DiffUnstaged(recipe.Dir()); err != nil { + if err := gitPkg.DiffUnstaged(r.Dir); err != nil { log.Fatal(err) } } diff --git a/cli/recipe/sync.go b/cli/recipe/sync.go index b671f028..565650f8 100644 --- a/cli/recipe/sync.go +++ b/cli/recipe/sync.go @@ -201,13 +201,13 @@ likely to change. log.Infof("dry run: not syncing label %s for recipe %s", nextTag, recipe.Name) } - isClean, err := gitPkg.IsClean(recipe.Dir()) + isClean, err := gitPkg.IsClean(r.Dir) if err != nil { log.Fatal(err) } if !isClean { log.Infof("%s currently has these unstaged changes 👇", recipe.Name) - if err := gitPkg.DiffUnstaged(recipe.Dir()); err != nil { + if err := gitPkg.DiffUnstaged(r.Dir); err != nil { log.Fatal(err) } } diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 976b0a71..0010cd3a 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -136,11 +136,6 @@ type Recipe struct { Meta RecipeMeta } -// Dir retrieves the recipe repository path -func (r Recipe) Dir() string { - return path.Join(config.RECIPES_DIR, r.Name) -} - // Get retrieves a recipe. func Get(recipeName string, offline bool) (Recipe, error) { r := Get2(recipeName) From 99da8d4e573e0d150656a3be0f95d5530ce2c259 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 12:06:58 +0200 Subject: [PATCH 13/19] refactor(recipe): move GetComposeFiles to new struct --- cli/app/deploy.go | 2 +- cli/app/new.go | 2 +- cli/app/ps.go | 3 ++- cli/app/rollback.go | 2 +- cli/app/secret.go | 4 ++-- cli/app/upgrade.go | 2 +- cli/updater/updater.go | 8 +++---- pkg/app/app.go | 6 ++++-- pkg/app/app_test.go | 6 ++++-- pkg/recipe/compose.go | 47 +++++++++++++++++++++++++++++++++++++++- pkg/recipe/recipe.go | 49 ++---------------------------------------- pkg/secret/secret.go | 3 ++- 12 files changed, 70 insertions(+), 64 deletions(-) diff --git a/cli/app/deploy.go b/cli/app/deploy.go index 138e0330..b272918b 100644 --- a/cli/app/deploy.go +++ b/cli/app/deploy.go @@ -173,7 +173,7 @@ recipes. app.Env[k] = v } - composeFiles, err := recipe.GetComposeFiles(app.Recipe, app.Env) + composeFiles, err := r2.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } diff --git a/cli/app/new.go b/cli/app/new.go index 823609d9..0453650d 100644 --- a/cli/app/new.go +++ b/cli/app/new.go @@ -136,7 +136,7 @@ var appNewCommand = cli.Command{ log.Fatal(err) } - composeFiles, err := recipePkg.GetComposeFiles(recipe.Name, sampleEnv) + composeFiles, err := r.GetComposeFiles(sampleEnv) if err != nil { log.Fatal(err) } diff --git a/cli/app/ps.go b/cli/app/ps.go index 0db7a7dc..c6e62705 100644 --- a/cli/app/ps.go +++ b/cli/app/ps.go @@ -68,7 +68,8 @@ var appPsCommand = cli.Command{ // showPSOutput renders ps output. func showPSOutput(app appPkg.App, cl *dockerClient.Client) { - composeFiles, err := recipe.GetComposeFiles(app.Recipe, app.Env) + r := recipe.Get2(app.Name) + composeFiles, err := r.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) return diff --git a/cli/app/rollback.go b/cli/app/rollback.go index edade3d0..afe1b23e 100644 --- a/cli/app/rollback.go +++ b/cli/app/rollback.go @@ -193,7 +193,7 @@ recipes. app.Env[k] = v } - composeFiles, err := recipe.GetComposeFiles(app.Recipe, app.Env) + composeFiles, err := r2.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } diff --git a/cli/app/secret.go b/cli/app/secret.go index 22ad9e9d..9618742c 100644 --- a/cli/app/secret.go +++ b/cli/app/secret.go @@ -72,7 +72,7 @@ var appSecretGenerateCommand = cli.Command{ internal.ShowSubcommandHelpAndError(c, err) } - composeFiles, err := recipe.GetComposeFiles(app.Recipe, app.Env) + composeFiles, err := r.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } @@ -270,7 +270,7 @@ Example: } } - composeFiles, err := recipe.GetComposeFiles(app.Recipe, app.Env) + composeFiles, err := r.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } diff --git a/cli/app/upgrade.go b/cli/app/upgrade.go index fe61d5be..5f2a129c 100644 --- a/cli/app/upgrade.go +++ b/cli/app/upgrade.go @@ -231,7 +231,7 @@ recipes. app.Env[k] = v } - composeFiles, err := recipePkg.GetComposeFiles(app.Recipe, app.Env) + composeFiles, err := r.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } diff --git a/cli/updater/updater.go b/cli/updater/updater.go index 49d0e854..8565f5d5 100644 --- a/cli/updater/updater.go +++ b/cli/updater/updater.go @@ -357,7 +357,7 @@ func mergeAbraShEnv(recipeName string, env envfile.AppEnv) error { } // createDeployConfig merges and enriches the compose config for the deployment. -func createDeployConfig(recipeName string, stackName string, env envfile.AppEnv) (*composetypes.Config, stack.Deploy, error) { +func createDeployConfig(r recipe.Recipe2, stackName string, env envfile.AppEnv) (*composetypes.Config, stack.Deploy, error) { env["STACK_NAME"] = stackName deployOpts := stack.Deploy{ @@ -367,7 +367,7 @@ func createDeployConfig(recipeName string, stackName string, env envfile.AppEnv) Detach: false, } - composeFiles, err := recipe.GetComposeFiles(recipeName, env) + composeFiles, err := r.GetComposeFiles(env) if err != nil { return nil, deployOpts, err } @@ -382,7 +382,7 @@ func createDeployConfig(recipeName string, stackName string, env envfile.AppEnv) // after the upgrade the deployment won't be in chaos state anymore appPkg.SetChaosLabel(compose, stackName, false) - appPkg.SetRecipeLabel(compose, stackName, recipeName) + appPkg.SetRecipeLabel(compose, stackName, r.Name) appPkg.SetUpdateLabel(compose, stackName, env) return compose, deployOpts, nil @@ -455,7 +455,7 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName, return err } - compose, deployOpts, err := createDeployConfig(recipeName, stackName, app.Env) + compose, deployOpts, err := createDeployConfig(r, stackName, app.Env) if err != nil { return err } diff --git a/pkg/app/app.go b/pkg/app/app.go index dbff9be9..09618341 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -161,7 +161,8 @@ func (a App) Filters(appendServiceNames, exactMatch bool, services ...string) (f return filters, nil } - composeFiles, err := recipe.GetComposeFiles(a.Recipe, a.Env) + r := recipe.Get2(a.Recipe) + composeFiles, err := r.GetComposeFiles(a.Env) if err != nil { return filters, err } @@ -317,7 +318,8 @@ func GetAppServiceNames(appName string) ([]string, error) { return serviceNames, err } - composeFiles, err := recipe.GetComposeFiles(app.Recipe, app.Env) + r := recipe.Get2(app.Recipe) + composeFiles, err := r.GetComposeFiles(app.Env) if err != nil { return serviceNames, err } diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index 3f32e985..23828143 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -85,7 +85,8 @@ func TestGetComposeFiles(t *testing.T) { } for _, test := range tests { - composeFiles, err := recipe.GetComposeFiles(r.Name, test.appEnv) + r2 := recipe.Get2(r.Name) + composeFiles, err := r2.GetComposeFiles(test.appEnv) if err != nil { t.Fatal(err) } @@ -106,7 +107,8 @@ func TestGetComposeFilesError(t *testing.T) { } for _, test := range tests { - _, err := recipe.GetComposeFiles(r.Name, test.appEnv) + r2 := recipe.Get2(r.Name) + _, err := r2.GetComposeFiles(test.appEnv) if err == nil { t.Fatalf("should have failed: %v", test.appEnv) } diff --git a/pkg/recipe/compose.go b/pkg/recipe/compose.go index 7e6384ba..6e7c9264 100644 --- a/pkg/recipe/compose.go +++ b/pkg/recipe/compose.go @@ -3,6 +3,7 @@ package recipe import ( "fmt" "io/ioutil" + "os" "path/filepath" "strings" @@ -14,6 +15,50 @@ import ( composetypes "github.com/docker/cli/cli/compose/types" ) +// GetComposeFiles gets the list of compose files for an app (or recipe if you +// don't already have an app) which should be merged into a composetypes.Config +// while respecting the COMPOSE_FILE env var. +func (r Recipe2) GetComposeFiles(appEnv map[string]string) ([]string, error) { + composeFileEnvVar, ok := appEnv["COMPOSE_FILE"] + if !ok { + if err := ensurePathExists(r.ComposePath); err != nil { + return []string{}, err + } + log.Debugf("no COMPOSE_FILE detected, loading default: %s", r.ComposePath) + return []string{r.ComposePath}, nil + } + + if !strings.Contains(composeFileEnvVar, ":") { + path := fmt.Sprintf("%s/%s", r.Dir, composeFileEnvVar) + if err := ensurePathExists(path); err != nil { + return []string{}, err + } + log.Debugf("COMPOSE_FILE detected, loading %s", path) + return []string{path}, nil + } + + var composeFiles []string + + numComposeFiles := strings.Count(composeFileEnvVar, ":") + 1 + envVars := strings.SplitN(composeFileEnvVar, ":", numComposeFiles) + if len(envVars) != numComposeFiles { + return composeFiles, fmt.Errorf("COMPOSE_FILE (=\"%s\") parsing failed?", composeFileEnvVar) + } + + for _, file := range envVars { + path := fmt.Sprintf("%s/%s", r.Dir, file) + if err := ensurePathExists(path); err != nil { + return composeFiles, err + } + 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) + + return composeFiles, nil +} + // UpdateTag updates an image tag in-place on file system local compose files. func (r Recipe2) UpdateTag(image, tag string) (bool, error) { fullPattern := fmt.Sprintf("%s/compose**yml", r.Dir) @@ -74,7 +119,7 @@ func (r Recipe2) UpdateTag(image, tag string) (bool, error) { log.Debugf("updating %s to %s in %s", old, new, compose.Filename) - if err := ioutil.WriteFile(compose.Filename, []byte(replacedBytes), 0764); err != nil { + if err := os.WriteFile(compose.Filename, []byte(replacedBytes), 0764); err != nil { return false, err } } diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 0010cd3a..46998d29 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -188,6 +188,7 @@ func Get2(name string) Recipe2 { Dir: dir, SSHURL: fmt.Sprintf(config.SSH_URL_TEMPLATE, name), + ComposePath: path.Join(dir, "compose.yml"), ReadmePath: path.Join(dir, "README.md"), SampleEnvPath: path.Join(dir, ".env.sample"), } @@ -198,6 +199,7 @@ type Recipe2 struct { Dir string SSHURL string + ComposePath string ReadmePath string SampleEnvPath string } @@ -776,50 +778,3 @@ func ensurePathExists(path string) error { } return nil } - -// GetComposeFiles gets the list of compose files for an app (or recipe if you -// don't already have an app) which should be merged into a composetypes.Config -// while respecting the COMPOSE_FILE env var. -func GetComposeFiles(recipe string, appEnv map[string]string) ([]string, error) { - var composeFiles []string - - composeFileEnvVar, ok := appEnv["COMPOSE_FILE"] - if !ok { - path := fmt.Sprintf("%s/%s/compose.yml", config.RECIPES_DIR, recipe) - if err := ensurePathExists(path); err != nil { - return composeFiles, err - } - log.Debugf("no COMPOSE_FILE detected, loading default: %s", path) - composeFiles = append(composeFiles, path) - return composeFiles, nil - } - - if !strings.Contains(composeFileEnvVar, ":") { - path := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, recipe, composeFileEnvVar) - if err := ensurePathExists(path); err != nil { - return composeFiles, err - } - log.Debugf("COMPOSE_FILE detected, loading %s", path) - composeFiles = append(composeFiles, path) - return composeFiles, nil - } - - numComposeFiles := strings.Count(composeFileEnvVar, ":") + 1 - envVars := strings.SplitN(composeFileEnvVar, ":", numComposeFiles) - if len(envVars) != numComposeFiles { - return composeFiles, fmt.Errorf("COMPOSE_FILE (=\"%s\") parsing failed?", composeFileEnvVar) - } - - for _, file := range envVars { - path := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, recipe, file) - if err := ensurePathExists(path); err != nil { - return composeFiles, err - } - 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, ", "), recipe) - - return composeFiles, nil -} diff --git a/pkg/secret/secret.go b/pkg/secret/secret.go index fd69508a..0f1d6d7b 100644 --- a/pkg/secret/secret.go +++ b/pkg/secret/secret.go @@ -246,7 +246,8 @@ type secretStatuses []secretStatus func PollSecretsStatus(cl *dockerClient.Client, app appPkg.App) (secretStatuses, error) { var secStats secretStatuses - composeFiles, err := recipe.GetComposeFiles(app.Recipe, app.Env) + r := recipe.Get2(app.Name) + composeFiles, err := r.GetComposeFiles(app.Env) if err != nil { return secStats, err } From c1b03bcbd743c0656c0a9b763ea4c8ba21c9b2d4 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 12:31:39 +0200 Subject: [PATCH 14/19] refactor(recipe): load load compoes config where its used --- cli/app/deploy.go | 19 ++--- cli/app/new.go | 2 +- cli/app/rollback.go | 17 ++--- cli/app/upgrade.go | 10 +-- cli/catalogue/catalogue.go | 2 +- cli/internal/recipe.go | 8 +- cli/recipe/lint.go | 4 +- cli/recipe/release.go | 18 +++-- cli/recipe/sync.go | 4 +- cli/recipe/upgrade.go | 7 +- cli/updater/updater.go | 4 +- pkg/lint/recipe.go | 102 +++++++++++++++++-------- pkg/recipe/compose.go | 53 ++++++++++++- pkg/recipe/git.go | 89 ++++++++++++++++++++++ pkg/recipe/recipe.go | 147 +------------------------------------ pkg/recipe/recipe_test.go | 7 +- 16 files changed, 263 insertions(+), 230 deletions(-) diff --git a/cli/app/deploy.go b/cli/app/deploy.go index b272918b..10744056 100644 --- a/cli/app/deploy.go +++ b/cli/app/deploy.go @@ -58,13 +58,8 @@ recipes. log.Fatal("cannot use and --chaos together") } - r2 := recipe.Get2(app.Recipe) - if err := r2.Ensure(internal.Chaos, internal.Offline); err != nil { - log.Fatal(err) - } - - r, err := recipe.Get(app.Recipe, internal.Offline) - if err != nil { + r := recipe.Get2(app.Recipe) + if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } @@ -92,7 +87,7 @@ recipes. if specificVersion != "" { version = specificVersion log.Debugf("choosing %s as version to deploy", version) - if err := r2.EnsureVersion(version); err != nil { + if err := r.EnsureVersion(version); err != nil { log.Fatal(err) } } @@ -128,7 +123,7 @@ recipes. if len(versions) == 0 && !internal.Chaos { log.Warn("no published versions in catalogue, trying local recipe repository") - recipeVersions, err := recipe.GetRecipeVersions(app.Recipe, internal.Offline) + recipeVersions, err := r.GetRecipeVersions(internal.Offline) if err != nil { log.Warn(err) } @@ -142,7 +137,7 @@ recipes. if len(versions) > 0 && !internal.Chaos { version = versions[len(versions)-1] log.Debugf("choosing %s as version to deploy", version) - if err := r2.EnsureVersion(version); err != nil { + if err := r.EnsureVersion(version); err != nil { log.Fatal(err) } } else { @@ -158,7 +153,7 @@ recipes. if internal.Chaos { log.Warnf("chaos mode engaged") var err error - version, err = r2.ChaosVersion() + version, err = r.ChaosVersion() if err != nil { log.Fatal(err) } @@ -173,7 +168,7 @@ recipes. app.Env[k] = v } - composeFiles, err := r2.GetComposeFiles(app.Env) + composeFiles, err := r.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } diff --git a/cli/app/new.go b/cli/app/new.go index 0453650d..7ee1fde5 100644 --- a/cli/app/new.go +++ b/cli/app/new.go @@ -80,7 +80,7 @@ var appNewCommand = cli.Command{ if c.Args().Get(1) == "" { var version string - recipeVersions, err := recipePkg.GetRecipeVersions(recipe.Name, internal.Offline) + recipeVersions, err := r.GetRecipeVersions(internal.Offline) if err != nil { log.Fatal(err) } diff --git a/cli/app/rollback.go b/cli/app/rollback.go index afe1b23e..da4ba251 100644 --- a/cli/app/rollback.go +++ b/cli/app/rollback.go @@ -58,13 +58,8 @@ recipes. log.Fatal("cannot use and --chaos together") } - r2 := recipe.Get2(app.Recipe) - if err := r2.Ensure(internal.Chaos, internal.Offline); err != nil { - log.Fatal(err) - } - - r, err := recipe.Get(app.Recipe, internal.Offline) - if err != nil { + r := recipe.Get2(app.Recipe) + if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } @@ -100,7 +95,7 @@ recipes. if len(versions) == 0 && !internal.Chaos { log.Warn("no published versions in catalogue, trying local recipe repository") - recipeVersions, err := recipe.GetRecipeVersions(app.Recipe, internal.Offline) + recipeVersions, err := r.GetRecipeVersions(internal.Offline) if err != nil { log.Warn(err) } @@ -170,7 +165,7 @@ recipes. } if !internal.Chaos { - if err := r2.EnsureVersion(chosenDowngrade); err != nil { + if err := r.EnsureVersion(chosenDowngrade); err != nil { log.Fatal(err) } } @@ -178,7 +173,7 @@ recipes. if internal.Chaos { log.Warn("chaos mode engaged") var err error - chosenDowngrade, err = r2.ChaosVersion() + chosenDowngrade, err = r.ChaosVersion() if err != nil { log.Fatal(err) } @@ -193,7 +188,7 @@ recipes. app.Env[k] = v } - composeFiles, err := r2.GetComposeFiles(app.Env) + composeFiles, err := r.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } diff --git a/cli/app/upgrade.go b/cli/app/upgrade.go index 5f2a129c..6a8e4712 100644 --- a/cli/app/upgrade.go +++ b/cli/app/upgrade.go @@ -69,12 +69,8 @@ recipes. log.Fatal(err) } - recipe, err := recipePkg.Get(app.Recipe, internal.Offline) - if err != nil { - log.Fatal(err) - } - - if err := lint.LintForErrors(recipe); err != nil { + r2 := recipePkg.Get2(app.Recipe) + if err := lint.LintForErrors(r2); err != nil { log.Fatal(err) } @@ -106,7 +102,7 @@ recipes. if len(versions) == 0 && !internal.Chaos { log.Warn("no published versions in catalogue, trying local recipe repository") - recipeVersions, err := recipePkg.GetRecipeVersions(app.Recipe, internal.Offline) + recipeVersions, err := r2.GetRecipeVersions(internal.Offline) if err != nil { log.Warn(err) } diff --git a/cli/catalogue/catalogue.go b/cli/catalogue/catalogue.go index ae319c93..c5bf3c3b 100644 --- a/cli/catalogue/catalogue.go +++ b/cli/catalogue/catalogue.go @@ -99,7 +99,7 @@ keys configured on your account. continue } - versions, err := recipe.GetRecipeVersions(recipeMeta.Name, internal.Offline) + versions, err := r.GetRecipeVersions(internal.Offline) if err != nil { log.Warn(err) } diff --git a/cli/internal/recipe.go b/cli/internal/recipe.go index 9c87cce2..5e8fb887 100644 --- a/cli/internal/recipe.go +++ b/cli/internal/recipe.go @@ -85,10 +85,14 @@ func SetBumpType(bumpType string) { } // GetMainAppImage retrieves the main 'app' image name -func GetMainAppImage(recipe recipe.Recipe) (string, error) { +func GetMainAppImage(recipe recipe.Recipe2) (string, error) { var path string - for _, service := range recipe.Config.Services { + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return "", err + } + for _, service := range config.Services { if service.Name == "app" { img, err := reference.ParseNormalizedNamed(service.Image) if err != nil { diff --git a/cli/recipe/lint.go b/cli/recipe/lint.go index 079a0a53..cc73a8a3 100644 --- a/cli/recipe/lint.go +++ b/cli/recipe/lint.go @@ -47,7 +47,7 @@ var recipeLintCommand = cli.Command{ } skipped := false - if rule.Skip(recipe) { + if rule.Skip(r) { skipped = true } @@ -58,7 +58,7 @@ var recipeLintCommand = cli.Command{ satisfied := false if !skipped { - ok, err := rule.Function(recipe) + ok, err := rule.Function(r) if err != nil { log.Warn(err) } diff --git a/cli/recipe/release.go b/cli/recipe/release.go index 1c2b4d92..f639d9f0 100644 --- a/cli/recipe/release.go +++ b/cli/recipe/release.go @@ -65,12 +65,12 @@ your SSH keys configured on your account. recipe := internal.ValidateRecipe(c) r := recipePkg.Get2(recipe.Name) - imagesTmp, err := getImageVersions(recipe) + imagesTmp, err := getImageVersions(r) if err != nil { log.Fatal(err) } - mainApp, err := internal.GetMainAppImage(recipe) + mainApp, err := internal.GetMainAppImage(r) if err != nil { log.Fatal(err) } @@ -104,7 +104,7 @@ your SSH keys configured on your account. if tagString == "" && (!internal.Major && !internal.Minor && !internal.Patch) { var err error - tagString, err = getLabelVersion(recipe, false) + tagString, err = getLabelVersion(r, false) if err != nil { log.Fatal(err) } @@ -143,11 +143,15 @@ your SSH keys configured on your account. } // getImageVersions retrieves image versions for a recipe -func getImageVersions(recipe recipe.Recipe) (map[string]string, error) { +func getImageVersions(recipe recipe.Recipe2) (map[string]string, error) { services := make(map[string]string) + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return nil, err + } missingTag := false - for _, service := range recipe.Config.Services { + for _, service := range config.Services { if service.Image == "" { continue } @@ -526,8 +530,8 @@ func cleanUpTag(tag, recipeName string) error { return nil } -func getLabelVersion(recipe recipe.Recipe, prompt bool) (string, error) { - initTag, err := recipePkg.GetVersionLabelLocal(recipe) +func getLabelVersion(recipe recipe.Recipe2, prompt bool) (string, error) { + initTag, err := recipe.GetVersionLabelLocal() if err != nil { return "", err } diff --git a/cli/recipe/sync.go b/cli/recipe/sync.go index 565650f8..1d2e2897 100644 --- a/cli/recipe/sync.go +++ b/cli/recipe/sync.go @@ -47,12 +47,12 @@ local file system. recipe := internal.ValidateRecipe(c) r := recipePkg.Get2(recipe.Name) - mainApp, err := internal.GetMainAppImage(recipe) + mainApp, err := internal.GetMainAppImage(r) if err != nil { log.Fatal(err) } - imagesTmp, err := getImageVersions(recipe) + imagesTmp, err := getImageVersions(r) if err != nil { log.Fatal(err) } diff --git a/cli/recipe/upgrade.go b/cli/recipe/upgrade.go index 05d44f2c..f49ec182 100644 --- a/cli/recipe/upgrade.go +++ b/cli/recipe/upgrade.go @@ -130,7 +130,12 @@ You may invoke this command in "wizard" mode and be prompted for input: log.Debugf("did not find versions file for %s", recipe.Name) } - for _, service := range recipe.Config.Services { + config, err := r.GetComposeConfig(nil) + if err != nil { + log.Fatal(err) + } + + for _, service := range config.Services { img, err := reference.ParseNormalizedNamed(service.Image) if err != nil { log.Fatal(err) diff --git a/cli/updater/updater.go b/cli/updater/updater.go index 8565f5d5..04906247 100644 --- a/cli/updater/updater.go +++ b/cli/updater/updater.go @@ -331,9 +331,7 @@ func processRecipeRepoVersion(r recipe.Recipe2, version string) error { return err } - if r, err := recipe.Get(r.Name, internal.Offline); err != nil { - return err - } else if err := lint.LintForErrors(r); err != nil { + if err := lint.LintForErrors(r); err != nil { return err } diff --git a/pkg/lint/recipe.go b/pkg/lint/recipe.go index 85e7783c..d4d366cb 100644 --- a/pkg/lint/recipe.go +++ b/pkg/lint/recipe.go @@ -19,13 +19,13 @@ import ( var Warn = "warn" var Critical = "critical" -type LintFunction func(recipe.Recipe) (bool, error) +type LintFunction func(recipe.Recipe2) (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(recipe.Recipe2) (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 +42,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 recipe.Recipe2) bool { if l.SkipCondition != nil { ok, err := l.SkipCondition(recipe) if err != nil { @@ -173,7 +173,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 recipe.Recipe2) error { log.Debugf("linting for critical errors in %s configs", recipe.Name) for level := range LintRules { @@ -201,15 +201,19 @@ func LintForErrors(recipe recipe.Recipe) error { return nil } -func LintComposeVersion(recipe recipe.Recipe) (bool, error) { - if recipe.Config.Version == "3.8" { +func LintComposeVersion(recipe recipe.Recipe2) (bool, error) { + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return false, err + } + if config.Version == "3.8" { return true, nil } return true, nil } -func LintEnvConfigPresent(r recipe.Recipe) (bool, error) { +func LintEnvConfigPresent(r recipe.Recipe2) (bool, error) { r2 := recipe.Get2(r.Name) if _, err := os.Stat(r2.SampleEnvPath); !os.IsNotExist(err) { return true, nil @@ -218,8 +222,12 @@ func LintEnvConfigPresent(r recipe.Recipe) (bool, error) { return false, nil } -func LintAppService(recipe recipe.Recipe) (bool, error) { - for _, service := range recipe.Config.Services { +func LintAppService(recipe recipe.Recipe2) (bool, error) { + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return false, err + } + for _, service := range config.Services { if service.Name == "app" { return true, nil } @@ -232,7 +240,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(r recipe.Recipe) (bool, error) { +func LintTraefikEnabledSkipCondition(r recipe.Recipe2) (bool, error) { r2 := recipe.Get2(r.Name) sampleEnv, err := r2.SampleEnv() if err != nil { @@ -246,8 +254,12 @@ func LintTraefikEnabledSkipCondition(r recipe.Recipe) (bool, error) { return false, nil } -func LintTraefikEnabled(recipe recipe.Recipe) (bool, error) { - for _, service := range recipe.Config.Services { +func LintTraefikEnabled(recipe recipe.Recipe2) (bool, error) { + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return false, err + } + for _, service := range config.Services { for label := range service.Deploy.Labels { if label == "traefik.enable" { if service.Deploy.Labels[label] == "true" { @@ -260,8 +272,12 @@ func LintTraefikEnabled(recipe recipe.Recipe) (bool, error) { return false, nil } -func LintHealthchecks(recipe recipe.Recipe) (bool, error) { - for _, service := range recipe.Config.Services { +func LintHealthchecks(recipe recipe.Recipe2) (bool, error) { + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return false, err + } + for _, service := range config.Services { if service.HealthCheck == nil { return false, nil } @@ -270,8 +286,12 @@ func LintHealthchecks(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintAllImagesTagged(recipe recipe.Recipe) (bool, error) { - for _, service := range recipe.Config.Services { +func LintAllImagesTagged(recipe recipe.Recipe2) (bool, error) { + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return false, err + } + for _, service := range config.Services { img, err := reference.ParseNormalizedNamed(service.Image) if err != nil { return false, err @@ -284,8 +304,12 @@ func LintAllImagesTagged(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintNoUnstableTags(recipe recipe.Recipe) (bool, error) { - for _, service := range recipe.Config.Services { +func LintNoUnstableTags(recipe recipe.Recipe2) (bool, error) { + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return false, err + } + for _, service := range config.Services { img, err := reference.ParseNormalizedNamed(service.Image) if err != nil { return false, err @@ -307,8 +331,12 @@ func LintNoUnstableTags(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintSemverLikeTags(recipe recipe.Recipe) (bool, error) { - for _, service := range recipe.Config.Services { +func LintSemverLikeTags(recipe recipe.Recipe2) (bool, error) { + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return false, err + } + for _, service := range config.Services { img, err := reference.ParseNormalizedNamed(service.Image) if err != nil { return false, err @@ -330,8 +358,12 @@ func LintSemverLikeTags(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintImagePresent(recipe recipe.Recipe) (bool, error) { - for _, service := range recipe.Config.Services { +func LintImagePresent(recipe recipe.Recipe2) (bool, error) { + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return false, err + } + for _, service := range config.Services { if service.Image == "" { return false, nil } @@ -339,7 +371,7 @@ func LintImagePresent(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintHasPublishedVersion(recipe recipe.Recipe) (bool, error) { +func LintHasPublishedVersion(recipe recipe.Recipe2) (bool, error) { catl, err := recipePkg.ReadRecipeCatalogue(false) if err != nil { log.Fatal(err) @@ -357,7 +389,7 @@ func LintHasPublishedVersion(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintMetadataFilledIn(r recipe.Recipe) (bool, error) { +func LintMetadataFilledIn(r recipe.Recipe2) (bool, error) { r2 := recipe.Get2(r.Name) features, category, err := recipe.GetRecipeFeaturesAndCategory(r2) if err != nil { @@ -379,10 +411,14 @@ func LintMetadataFilledIn(r recipe.Recipe) (bool, error) { return true, nil } -func LintAbraShVendors(recipe recipe.Recipe) (bool, error) { - for _, service := range recipe.Config.Services { +func LintAbraShVendors(recipe recipe.Recipe2) (bool, error) { + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return false, err + } + for _, service := range config.Services { if len(service.Configs) > 0 { - abraSh := path.Join(config.RECIPES_DIR, recipe.Name, "abra.sh") + abraSh := path.Join(recipe.Dir, "abra.sh") if _, err := os.Stat(abraSh); err != nil { if os.IsNotExist(err) { return false, err @@ -394,7 +430,7 @@ func LintAbraShVendors(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintHasRecipeRepo(recipe recipe.Recipe) (bool, error) { +func LintHasRecipeRepo(recipe recipe.Recipe2) (bool, error) { url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, recipe.Name) res, err := http.Get(url) @@ -409,8 +445,12 @@ func LintHasRecipeRepo(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintSecretLengths(recipe recipe.Recipe) (bool, error) { - for name := range recipe.Config.Secrets { +func LintSecretLengths(recipe recipe.Recipe2) (bool, error) { + config, err := recipe.GetComposeConfig(nil) + if err != nil { + return false, err + } + for name := range config.Secrets { if len(name) > 12 { return false, fmt.Errorf("secret %s is longer than 12 characters", name) } @@ -419,7 +459,7 @@ func LintSecretLengths(recipe recipe.Recipe) (bool, error) { return true, nil } -func LintValidTags(recipe recipe.Recipe) (bool, error) { +func LintValidTags(recipe recipe.Recipe2) (bool, error) { recipeDir := path.Join(config.RECIPES_DIR, recipe.Name) repo, err := git.PlainOpen(recipeDir) diff --git a/pkg/recipe/compose.go b/pkg/recipe/compose.go index 6e7c9264..5312263a 100644 --- a/pkg/recipe/compose.go +++ b/pkg/recipe/compose.go @@ -59,6 +59,55 @@ func (r Recipe2) GetComposeFiles(appEnv map[string]string) ([]string, error) { return composeFiles, nil } +func (r Recipe2) GetComposeConfig(env map[string]string) (*composetypes.Config, error) { + pattern := fmt.Sprintf("%s/compose**yml", r.Dir) + composeFiles, err := filepath.Glob(pattern) + if err != nil { + return nil, err + } + + if len(composeFiles) == 0 { + return nil, fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", r.Name) + } + + if env == nil { + env, err = r.SampleEnv() + if err != nil { + return nil, err + } + } + + opts := stack.Deploy{Composefiles: composeFiles} + config, err := loader.LoadComposefile(opts, env) + if err != nil { + return nil, err + } + return config, nil +} + +// GetVersionLabelLocal retrieves the version label on the local recipe config +func (r Recipe2) GetVersionLabelLocal() (string, error) { + var label string + config, err := r.GetComposeConfig(nil) + if err != nil { + return "", err + } + + for _, service := range config.Services { + for label, value := range service.Deploy.Labels { + if strings.HasPrefix(label, "coop-cloud") && strings.Contains(label, "version") { + return value, nil + } + } + } + + if label == "" { + return label, fmt.Errorf("%s has no version label? try running \"abra recipe sync %s\" first?", r.Name, r.Name) + } + + return label, nil +} + // UpdateTag updates an image tag in-place on file system local compose files. func (r Recipe2) UpdateTag(image, tag string) (bool, error) { fullPattern := fmt.Sprintf("%s/compose**yml", r.Dir) @@ -119,7 +168,7 @@ func (r Recipe2) UpdateTag(image, tag string) (bool, error) { log.Debugf("updating %s to %s in %s", old, new, compose.Filename) - if err := os.WriteFile(compose.Filename, []byte(replacedBytes), 0764); err != nil { + if err := os.WriteFile(compose.Filename, []byte(replacedBytes), 0o764); err != nil { return false, err } } @@ -185,7 +234,7 @@ func (r Recipe2) UpdateLabel(pattern, serviceName, label string) error { log.Debugf("updating %s to %s in %s", old, label, compose.Filename) - if err := ioutil.WriteFile(compose.Filename, []byte(replacedBytes), 0764); err != nil { + if err := ioutil.WriteFile(compose.Filename, []byte(replacedBytes), 0o764); err != nil { return err } diff --git a/pkg/recipe/git.go b/pkg/recipe/git.go index 9df862e4..d41fa498 100644 --- a/pkg/recipe/git.go +++ b/pkg/recipe/git.go @@ -10,6 +10,7 @@ import ( "coopcloud.tech/abra/pkg/formatter" gitPkg "coopcloud.tech/abra/pkg/git" "coopcloud.tech/abra/pkg/log" + "github.com/distribution/reference" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" ) @@ -288,3 +289,91 @@ func (r Recipe2) Tags() ([]string, error) { return tags, nil } + +// GetRecipeVersions retrieves all recipe versions. +func (r Recipe2) GetRecipeVersions(offline bool) (RecipeVersions, error) { + versions := RecipeVersions{} + log.Debugf("attempting to open git repository in %s", r.Dir) + + repo, err := git.PlainOpen(r.Dir) + if err != nil { + return versions, err + } + + worktree, err := repo.Worktree() + if err != nil { + return versions, err + } + + gitTags, err := repo.Tags() + if err != nil { + return versions, err + } + + 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) + + checkOutOpts := &git.CheckoutOptions{ + Create: false, + Force: true, + Branch: plumbing.ReferenceName(ref.Name()), + } + if err := worktree.Checkout(checkOutOpts); err != nil { + log.Debugf("failed to check out %s in %s", tag, r.Dir) + return err + } + + log.Debugf("successfully checked out %s in %s", ref.Name(), r.Dir) + + config, err := r.GetComposeConfig(nil) + if err != nil { + return err + } + + versionMeta := make(map[string]ServiceMeta) + for _, service := range config.Services { + + img, err := reference.ParseNormalizedNamed(service.Image) + if err != nil { + return err + } + + path := reference.Path(img) + + path = formatter.StripTagMeta(path) + + var tag string + switch img.(type) { + case reference.NamedTagged: + tag = img.(reference.NamedTagged).Tag() + case reference.Named: + log.Warnf("%s service is missing image tag?", path) + continue + } + + versionMeta[service.Name] = ServiceMeta{ + Image: path, + Tag: tag, + } + } + + versions = append(versions, map[string]map[string]ServiceMeta{tag: versionMeta}) + + return nil + }); err != nil { + return versions, err + } + + _, err = gitPkg.CheckoutDefaultBranch(repo, r.Dir) + if err != nil { + return versions, err + } + + sortRecipeVersions(versions) + + log.Debugf("collected %s for %s", versions, r.Dir) + + return versions, nil +} diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 46998d29..4affadd8 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -6,7 +6,6 @@ import ( "io/ioutil" "os" "path" - "path/filepath" "slices" "sort" "strconv" @@ -18,14 +17,8 @@ import ( gitPkg "coopcloud.tech/abra/pkg/git" "coopcloud.tech/abra/pkg/limit" "coopcloud.tech/abra/pkg/log" - "coopcloud.tech/abra/pkg/upstream/stack" - loader "coopcloud.tech/abra/pkg/upstream/stack" "coopcloud.tech/abra/pkg/web" "coopcloud.tech/tagcmp" - "github.com/distribution/reference" - composetypes "github.com/docker/cli/cli/compose/types" - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" ) // RecipeCatalogueURL is the only current recipe catalogue available. @@ -131,9 +124,8 @@ type Features struct { // Recipe represents a recipe. type Recipe struct { - Name string - Config *composetypes.Config - Meta RecipeMeta + Name string + Meta RecipeMeta } // Get retrieves a recipe. @@ -143,27 +135,6 @@ func Get(recipeName string, offline bool) (Recipe, error) { return Recipe{}, err } - pattern := fmt.Sprintf("%s/%s/compose**yml", config.RECIPES_DIR, r.Name) - composeFiles, err := filepath.Glob(pattern) - if err != nil { - return Recipe{}, err - } - - if len(composeFiles) == 0 { - return Recipe{}, fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", r.Name) - } - - sampleEnv, err := r.SampleEnv() - if err != nil { - return Recipe{}, err - } - - opts := stack.Deploy{Composefiles: composeFiles} - config, err := loader.LoadComposefile(opts, sampleEnv) - if err != nil { - return Recipe{}, err - } - meta, err := GetRecipeMeta(r.Name, offline) if err != nil { switch err.(type) { @@ -175,9 +146,8 @@ func Get(recipeName string, offline bool) (Recipe, error) { } return Recipe{ - Name: recipeName, - Config: config, - Meta: meta, + Name: recipeName, + Meta: meta, }, nil } @@ -216,25 +186,6 @@ func GetRecipesLocal() ([]string, error) { return recipes, nil } -// GetVersionLabelLocal retrieves the version label on the local recipe config -func GetVersionLabelLocal(recipe Recipe) (string, error) { - var label string - - for _, service := range recipe.Config.Services { - for label, value := range service.Deploy.Labels { - if strings.HasPrefix(label, "coop-cloud") && strings.Contains(label, "version") { - return value, nil - } - } - } - - if label == "" { - return label, fmt.Errorf("%s has no version label? try running \"abra recipe sync %s\" first?", recipe.Name, recipe.Name) - } - - return label, nil -} - func GetRecipeFeaturesAndCategory(r Recipe2) (Features, string, error) { feat := Features{} @@ -579,96 +530,6 @@ func ReadReposMetadata() (RepoCatalogue, error) { return reposMeta, nil } -// GetRecipeVersions retrieves all recipe versions. -func GetRecipeVersions(recipeName string, offline bool) (RecipeVersions, error) { - versions := RecipeVersions{} - recipeDir := path.Join(config.RECIPES_DIR, recipeName) - - log.Debugf("attempting to open git repository in %s", recipeDir) - - repo, err := git.PlainOpen(recipeDir) - if err != nil { - return versions, err - } - - worktree, err := repo.Worktree() - if err != nil { - return versions, err - } - - gitTags, err := repo.Tags() - if err != nil { - return versions, err - } - - 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, recipeName) - - checkOutOpts := &git.CheckoutOptions{ - Create: false, - Force: true, - Branch: plumbing.ReferenceName(ref.Name()), - } - if err := worktree.Checkout(checkOutOpts); err != nil { - log.Debugf("failed to check out %s in %s", tag, recipeDir) - return err - } - - log.Debugf("successfully checked out %s in %s", ref.Name(), recipeDir) - - recipe, err := Get(recipeName, offline) - if err != nil { - return err - } - - versionMeta := make(map[string]ServiceMeta) - for _, service := range recipe.Config.Services { - - img, err := reference.ParseNormalizedNamed(service.Image) - if err != nil { - return err - } - - path := reference.Path(img) - - path = formatter.StripTagMeta(path) - - var tag string - switch img.(type) { - case reference.NamedTagged: - tag = img.(reference.NamedTagged).Tag() - case reference.Named: - log.Warnf("%s service is missing image tag?", path) - continue - } - - versionMeta[service.Name] = ServiceMeta{ - Image: path, - Tag: tag, - } - } - - versions = append(versions, map[string]map[string]ServiceMeta{tag: versionMeta}) - - return nil - }); err != nil { - return versions, err - } - - _, err = gitPkg.CheckoutDefaultBranch(repo, recipeDir) - if err != nil { - return versions, err - } - - sortRecipeVersions(versions) - - log.Debugf("collected %s for %s", versions, recipeName) - - return versions, nil -} - // sortRecipeVersions sorts the recipe semver versions func sortRecipeVersions(versions RecipeVersions) { sort.Slice(versions, func(i, j int) bool { diff --git a/pkg/recipe/recipe_test.go b/pkg/recipe/recipe_test.go index 01b0f093..08e23a07 100644 --- a/pkg/recipe/recipe_test.go +++ b/pkg/recipe/recipe_test.go @@ -14,13 +14,10 @@ func TestGetVersionLabelLocalDoesNotUseTimeoutLabel(t *testing.T) { t.Fatal(err) } - r, err := Get("traefik", offline) - if err != nil { - t.Fatal(err) - } + r := Get2("traefik") for i := 1; i < 1000; i++ { - label, err := GetVersionLabelLocal(r) + label, err := r.GetVersionLabelLocal() if err != nil { t.Fatal(err) } From 5617a9ba072dcf5f42493e4f67cf00d999b83429 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 13:15:20 +0200 Subject: [PATCH 15/19] refactor(recipe): remove remaining usage of old recipe struct --- cli/app/backup.go | 31 ++++++++++------------ cli/app/check.go | 4 +-- cli/app/cmd.go | 9 +++---- cli/app/deploy.go | 21 +++++++-------- cli/app/list.go | 52 +++++++++++++++++++++---------------- cli/app/logs.go | 4 +-- cli/app/new.go | 23 ++++++++-------- cli/app/ps.go | 3 +-- cli/app/restore.go | 4 +-- cli/app/rollback.go | 17 ++++++------ cli/app/secret.go | 26 ++++++++----------- cli/app/upgrade.go | 21 +++++++-------- cli/app/version.go | 2 +- cli/internal/deploy.go | 8 +++--- cli/internal/validate.go | 9 +++++-- cli/recipe/lint.go | 8 +++--- cli/recipe/release.go | 20 +++++++------- cli/recipe/sync.go | 14 +++++----- cli/recipe/upgrade.go | 9 +++---- cli/updater/updater.go | 2 +- pkg/app/app.go | 27 +++++++++---------- pkg/app/app_test.go | 8 +++--- pkg/envfile/envfile_test.go | 31 +++++++++++----------- pkg/test/test.go | 3 ++- 24 files changed, 167 insertions(+), 189 deletions(-) diff --git a/cli/app/backup.go b/cli/app/backup.go index a44609a2..5c3e1029 100644 --- a/cli/app/backup.go +++ b/cli/app/backup.go @@ -7,7 +7,6 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/log" - "coopcloud.tech/abra/pkg/recipe" "github.com/urfave/cli" ) @@ -47,8 +46,7 @@ var appBackupListCommand = cli.Command{ Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Recipe) - if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { + if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } @@ -94,24 +92,23 @@ var appBackupDownloadCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Recipe) - if err := r.EnsureExists(); err != nil { + if err := app.Recipe.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { + if err := app.Recipe.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { + if err := app.Recipe.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := r.EnsureLatest(); err != nil { + if err := app.Recipe.EnsureLatest(); err != nil { log.Fatal(err) } } @@ -165,24 +162,23 @@ var appBackupCreateCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Recipe) - if err := r.EnsureExists(); err != nil { + if err := app.Recipe.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { + if err := app.Recipe.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { + if err := app.Recipe.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := r.EnsureLatest(); err != nil { + if err := app.Recipe.EnsureLatest(); err != nil { log.Fatal(err) } } @@ -224,24 +220,23 @@ var appBackupSnapshotsCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Recipe) - if err := r.EnsureExists(); err != nil { + if err := app.Recipe.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { + if err := app.Recipe.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { + if err := app.Recipe.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := r.EnsureLatest(); err != nil { + if err := app.Recipe.EnsureLatest(); err != nil { log.Fatal(err) } } diff --git a/cli/app/check.go b/cli/app/check.go index fe87298e..b5eca951 100644 --- a/cli/app/check.go +++ b/cli/app/check.go @@ -6,7 +6,6 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/log" - "coopcloud.tech/abra/pkg/recipe" "github.com/urfave/cli" ) @@ -37,8 +36,7 @@ ${FOO:} syntax). "check" does not confirm or deny this for you.`, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Recipe) - if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { + if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } diff --git a/cli/app/cmd.go b/cli/app/cmd.go index 33cec9a8..ee230c3d 100644 --- a/cli/app/cmd.go +++ b/cli/app/cmd.go @@ -60,8 +60,7 @@ Example: Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Recipe) - if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { + if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } @@ -71,7 +70,7 @@ Example: hasCmdArgs, parsedCmdArgs := parseCmdArgs(c.Args(), internal.LocalCmd) - abraSh := path.Join(config.RECIPES_DIR, app.Recipe, "abra.sh") + abraSh := path.Join(config.RECIPES_DIR, app.Recipe.Name, "abra.sh") if _, err := os.Stat(abraSh); err != nil { if os.IsNotExist(err) { log.Fatalf("%s does not exist for %s?", abraSh, app.Name) @@ -85,7 +84,7 @@ Example: } cmdName := c.Args().Get(1) - if err := internal.EnsureCommand(abraSh, app.Recipe, cmdName); err != nil { + if err := internal.EnsureCommand(abraSh, app.Recipe.Name, cmdName); err != nil { log.Fatal(err) } @@ -123,7 +122,7 @@ Example: targetServiceName := c.Args().Get(1) cmdName := c.Args().Get(2) - if err := internal.EnsureCommand(abraSh, app.Recipe, cmdName); err != nil { + if err := internal.EnsureCommand(abraSh, app.Recipe.Name, cmdName); err != nil { log.Fatal(err) } diff --git a/cli/app/deploy.go b/cli/app/deploy.go index 10744056..9d3bc950 100644 --- a/cli/app/deploy.go +++ b/cli/app/deploy.go @@ -58,12 +58,11 @@ recipes. log.Fatal("cannot use and --chaos together") } - r := recipe.Get2(app.Recipe) - if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { + if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } - if err := lint.LintForErrors(r); err != nil { + if err := lint.LintForErrors(app.Recipe); err != nil { log.Fatal(err) } @@ -87,7 +86,7 @@ recipes. if specificVersion != "" { version = specificVersion log.Debugf("choosing %s as version to deploy", version) - if err := r.EnsureVersion(version); err != nil { + if err := app.Recipe.EnsureVersion(version); err != nil { log.Fatal(err) } } @@ -116,14 +115,14 @@ recipes. if err != nil { log.Fatal(err) } - versions, err := recipe.GetRecipeCatalogueVersions(app.Recipe, catl) + versions, err := recipe.GetRecipeCatalogueVersions(app.Recipe.Name, catl) if err != nil { log.Fatal(err) } if len(versions) == 0 && !internal.Chaos { log.Warn("no published versions in catalogue, trying local recipe repository") - recipeVersions, err := r.GetRecipeVersions(internal.Offline) + recipeVersions, err := app.Recipe.GetRecipeVersions(internal.Offline) if err != nil { log.Warn(err) } @@ -137,11 +136,11 @@ recipes. if len(versions) > 0 && !internal.Chaos { version = versions[len(versions)-1] log.Debugf("choosing %s as version to deploy", version) - if err := r.EnsureVersion(version); err != nil { + if err := app.Recipe.EnsureVersion(version); err != nil { log.Fatal(err) } } else { - head, err := git.GetRecipeHead(app.Recipe) + head, err := git.GetRecipeHead(app.Recipe.Name) if err != nil { log.Fatal(err) } @@ -153,7 +152,7 @@ recipes. if internal.Chaos { log.Warnf("chaos mode engaged") var err error - version, err = r.ChaosVersion() + version, err = app.Recipe.ChaosVersion() if err != nil { log.Fatal(err) } @@ -168,7 +167,7 @@ recipes. app.Env[k] = v } - composeFiles, err := r.GetComposeFiles(app.Env) + composeFiles, err := app.Recipe.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } @@ -186,7 +185,7 @@ recipes. } appPkg.ExposeAllEnv(stackName, compose, app.Env) - appPkg.SetRecipeLabel(compose, stackName, app.Recipe) + appPkg.SetRecipeLabel(compose, stackName, app.Recipe.Name) appPkg.SetChaosLabel(compose, stackName, internal.Chaos) appPkg.SetChaosVersionLabel(compose, stackName, version) appPkg.SetUpdateLabel(compose, stackName, app.Env) diff --git a/cli/app/list.go b/cli/app/list.go index 422461e3..0ddea59f 100644 --- a/cli/app/list.go +++ b/cli/app/list.go @@ -16,28 +16,34 @@ import ( "github.com/urfave/cli" ) -var status bool -var statusFlag = &cli.BoolFlag{ - Name: "status, S", - Usage: "Show app deployment status", - Destination: &status, -} +var ( + status bool + statusFlag = &cli.BoolFlag{ + Name: "status, S", + Usage: "Show app deployment status", + Destination: &status, + } +) -var recipeFilter string -var recipeFlag = &cli.StringFlag{ - Name: "recipe, r", - Value: "", - Usage: "Show apps of a specific recipe", - Destination: &recipeFilter, -} +var ( + recipeFilter string + recipeFlag = &cli.StringFlag{ + Name: "recipe, r", + Value: "", + Usage: "Show apps of a specific recipe", + Destination: &recipeFilter, + } +) -var listAppServer string -var listAppServerFlag = &cli.StringFlag{ - Name: "server, s", - Value: "", - Usage: "Show apps of a specific server", - Destination: &listAppServer, -} +var ( + listAppServer string + listAppServerFlag = &cli.StringFlag{ + Name: "server, s", + Value: "", + Usage: "Show apps of a specific server", + Destination: &listAppServer, + } +) type appStatus struct { Server string `json:"server"` @@ -130,7 +136,7 @@ can take some time. } } - if app.Recipe == recipeFilter || recipeFilter == "" { + if app.Recipe.Name == recipeFilter || recipeFilter == "" { if recipeFilter != "" { // only count server if matches filter totalServersCount++ @@ -177,7 +183,7 @@ can take some time. var newUpdates []string if version != "unknown" { - updates, err := recipe.GetRecipeCatalogueVersions(app.Recipe, catl) + updates, err := recipe.GetRecipeCatalogueVersions(app.Recipe.Name, catl) if err != nil { log.Fatal(err) } @@ -214,7 +220,7 @@ can take some time. } appStats.Server = app.Server - appStats.Recipe = app.Recipe + appStats.Recipe = app.Recipe.Name appStats.AppName = app.Name appStats.Domain = app.Domain diff --git a/cli/app/logs.go b/cli/app/logs.go index 346e4ed3..c0682033 100644 --- a/cli/app/logs.go +++ b/cli/app/logs.go @@ -13,7 +13,6 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/log" - "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/abra/pkg/upstream/stack" "github.com/docker/docker/api/types" containerTypes "github.com/docker/docker/api/types/container" @@ -38,9 +37,8 @@ var appLogsCommand = cli.Command{ Action: func(c *cli.Context) error { app := internal.ValidateApp(c) stackName := app.StackName() - r := recipe.Get2(app.Recipe) - if err := r.EnsureExists(); err != nil { + if err := app.Recipe.EnsureExists(); err != nil { log.Fatal(err) } diff --git a/cli/app/new.go b/cli/app/new.go index 7ee1fde5..5978f39e 100644 --- a/cli/app/new.go +++ b/cli/app/new.go @@ -66,21 +66,20 @@ var appNewCommand = cli.Command{ }, Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) - r := recipePkg.Get2(recipe.Name) if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { + if err := recipe.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { + if err := recipe.EnsureUpToDate(); err != nil { log.Fatal(err) } } if c.Args().Get(1) == "" { var version string - recipeVersions, err := r.GetRecipeVersions(internal.Offline) + recipeVersions, err := recipe.GetRecipeVersions(internal.Offline) if err != nil { log.Fatal(err) } @@ -93,16 +92,16 @@ var appNewCommand = cli.Command{ version = tag } - if err := r.EnsureVersion(version); err != nil { + if err := recipe.EnsureVersion(version); err != nil { log.Fatal(err) } } else { - if err := r.EnsureLatest(); err != nil { + if err := recipe.EnsureLatest(); err != nil { log.Fatal(err) } } } else { - if err := r.EnsureVersion(c.Args().Get(1)); err != nil { + if err := recipe.EnsureVersion(c.Args().Get(1)); err != nil { log.Fatal(err) } } @@ -120,7 +119,7 @@ var appNewCommand = cli.Command{ log.Debugf("%s sanitised as %s for new app", internal.Domain, sanitisedAppName) if err := appPkg.TemplateAppEnvSample( - r, + recipe, internal.Domain, internal.NewAppServer, internal.Domain, @@ -131,17 +130,17 @@ var appNewCommand = cli.Command{ var secrets AppSecrets var secretTable *jsontable.JSONTable if internal.Secrets { - sampleEnv, err := r.SampleEnv() + sampleEnv, err := recipe.SampleEnv() if err != nil { log.Fatal(err) } - composeFiles, err := r.GetComposeFiles(sampleEnv) + composeFiles, err := recipe.GetComposeFiles(sampleEnv) if err != nil { log.Fatal(err) } - secretsConfig, err := secret.ReadSecretsConfig(r.SampleEnvPath, composeFiles, appPkg.StackName(internal.Domain)) + secretsConfig, err := secret.ReadSecretsConfig(recipe.SampleEnvPath, composeFiles, appPkg.StackName(internal.Domain)) if err != nil { return err } @@ -231,7 +230,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 recipePkg.Recipe, server string) error { +func ensureDomainFlag(recipe recipePkg.Recipe2, server string) error { if internal.Domain == "" && !internal.NoInput { prompt := &survey.Input{ Message: "Specify app domain", diff --git a/cli/app/ps.go b/cli/app/ps.go index c6e62705..6e485bd5 100644 --- a/cli/app/ps.go +++ b/cli/app/ps.go @@ -35,7 +35,6 @@ var appPsCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Recipe) cl, err := client.New(app.Server) if err != nil { @@ -54,7 +53,7 @@ var appPsCommand = cli.Command{ statuses, err := appPkg.GetAppStatuses([]appPkg.App{app}, true) if statusMeta, ok := statuses[app.StackName()]; ok { if _, exists := statusMeta["chaos"]; !exists { - if err := r.EnsureVersion(deployedVersion); err != nil { + if err := app.Recipe.EnsureVersion(deployedVersion); err != nil { log.Fatal(err) } } diff --git a/cli/app/restore.go b/cli/app/restore.go index 5f3c30ce..b31cc097 100644 --- a/cli/app/restore.go +++ b/cli/app/restore.go @@ -7,7 +7,6 @@ import ( "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/log" - "coopcloud.tech/abra/pkg/recipe" "github.com/urfave/cli" ) @@ -33,8 +32,7 @@ var appRestoreCommand = cli.Command{ Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Recipe) - if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { + if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } diff --git a/cli/app/rollback.go b/cli/app/rollback.go index da4ba251..ae65346d 100644 --- a/cli/app/rollback.go +++ b/cli/app/rollback.go @@ -58,12 +58,11 @@ recipes. log.Fatal("cannot use and --chaos together") } - r := recipe.Get2(app.Recipe) - if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { + if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } - if err := lint.LintForErrors(r); err != nil { + if err := lint.LintForErrors(app.Recipe); err != nil { log.Fatal(err) } @@ -88,14 +87,14 @@ recipes. log.Fatal(err) } - versions, err := recipe.GetRecipeCatalogueVersions(app.Recipe, catl) + versions, err := recipe.GetRecipeCatalogueVersions(app.Recipe.Name, catl) if err != nil { log.Fatal(err) } if len(versions) == 0 && !internal.Chaos { log.Warn("no published versions in catalogue, trying local recipe repository") - recipeVersions, err := r.GetRecipeVersions(internal.Offline) + recipeVersions, err := app.Recipe.GetRecipeVersions(internal.Offline) if err != nil { log.Warn(err) } @@ -165,7 +164,7 @@ recipes. } if !internal.Chaos { - if err := r.EnsureVersion(chosenDowngrade); err != nil { + if err := app.Recipe.EnsureVersion(chosenDowngrade); err != nil { log.Fatal(err) } } @@ -173,7 +172,7 @@ recipes. if internal.Chaos { log.Warn("chaos mode engaged") var err error - chosenDowngrade, err = r.ChaosVersion() + chosenDowngrade, err = app.Recipe.ChaosVersion() if err != nil { log.Fatal(err) } @@ -188,7 +187,7 @@ recipes. app.Env[k] = v } - composeFiles, err := r.GetComposeFiles(app.Env) + composeFiles, err := app.Recipe.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } @@ -204,7 +203,7 @@ recipes. log.Fatal(err) } appPkg.ExposeAllEnv(stackName, compose, app.Env) - appPkg.SetRecipeLabel(compose, stackName, app.Recipe) + appPkg.SetRecipeLabel(compose, stackName, app.Recipe.Name) appPkg.SetChaosLabel(compose, stackName, internal.Chaos) appPkg.SetChaosVersionLabel(compose, stackName, chosenDowngrade) appPkg.SetUpdateLabel(compose, stackName, app.Env) diff --git a/cli/app/secret.go b/cli/app/secret.go index 9618742c..28554979 100644 --- a/cli/app/secret.go +++ b/cli/app/secret.go @@ -14,7 +14,6 @@ import ( "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/log" - "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/abra/pkg/secret" "github.com/docker/docker/api/types" dockerClient "github.com/docker/docker/client" @@ -57,8 +56,7 @@ var appSecretGenerateCommand = cli.Command{ Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Recipe) - if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { + if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } @@ -72,7 +70,7 @@ var appSecretGenerateCommand = cli.Command{ internal.ShowSubcommandHelpAndError(c, err) } - composeFiles, err := r.GetComposeFiles(app.Env) + composeFiles, err := app.Recipe.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } @@ -248,29 +246,28 @@ Example: `, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Recipe) - if err := r.EnsureExists(); err != nil { + if err := app.Recipe.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { + if err := app.Recipe.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { + if err := app.Recipe.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := r.EnsureLatest(); err != nil { + if err := app.Recipe.EnsureLatest(); err != nil { log.Fatal(err) } } - composeFiles, err := r.GetComposeFiles(app.Env) + composeFiles, err := app.Recipe.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } @@ -357,24 +354,23 @@ var appSecretLsCommand = cli.Command{ BashComplete: autocomplete.AppNameComplete, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Recipe) - if err := r.EnsureExists(); err != nil { + if err := app.Recipe.EnsureExists(); err != nil { log.Fatal(err) } if !internal.Chaos { - if err := r.EnsureIsClean(); err != nil { + if err := app.Recipe.EnsureIsClean(); err != nil { log.Fatal(err) } if !internal.Offline { - if err := r.EnsureUpToDate(); err != nil { + if err := app.Recipe.EnsureUpToDate(); err != nil { log.Fatal(err) } } - if err := r.EnsureLatest(); err != nil { + if err := app.Recipe.EnsureLatest(); err != nil { log.Fatal(err) } } diff --git a/cli/app/upgrade.go b/cli/app/upgrade.go index 6a8e4712..d1cb5101 100644 --- a/cli/app/upgrade.go +++ b/cli/app/upgrade.go @@ -12,7 +12,6 @@ import ( "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/lint" "coopcloud.tech/abra/pkg/log" - "coopcloud.tech/abra/pkg/recipe" recipePkg "coopcloud.tech/abra/pkg/recipe" stack "coopcloud.tech/abra/pkg/upstream/stack" "coopcloud.tech/tagcmp" @@ -64,13 +63,11 @@ recipes. log.Fatal("cannot use and --chaos together") } - r := recipe.Get2(app.Recipe) - if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { + if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } - r2 := recipePkg.Get2(app.Recipe) - if err := lint.LintForErrors(r2); err != nil { + if err := lint.LintForErrors(app.Recipe); err != nil { log.Fatal(err) } @@ -95,14 +92,14 @@ recipes. log.Fatal(err) } - versions, err := recipePkg.GetRecipeCatalogueVersions(app.Recipe, catl) + versions, err := recipePkg.GetRecipeCatalogueVersions(app.Recipe.Name, catl) if err != nil { log.Fatal(err) } if len(versions) == 0 && !internal.Chaos { log.Warn("no published versions in catalogue, trying local recipe repository") - recipeVersions, err := r2.GetRecipeVersions(internal.Offline) + recipeVersions, err := app.Recipe.GetRecipeVersions(internal.Offline) if err != nil { log.Warn(err) } @@ -192,7 +189,7 @@ recipes. log.Fatal(err) } if parsedVersion.IsGreaterThan(parsedDeployedVersion) && parsedVersion.IsLessThan(parsedChosenUpgrade) { - note, err := internal.GetReleaseNotes(app.Recipe, version) + note, err := internal.GetReleaseNotes(app.Recipe.Name, version) if err != nil { return err } @@ -204,7 +201,7 @@ recipes. } if !internal.Chaos { - if err := r.EnsureVersion(chosenUpgrade); err != nil { + if err := app.Recipe.EnsureVersion(chosenUpgrade); err != nil { log.Fatal(err) } } @@ -212,7 +209,7 @@ recipes. if internal.Chaos { log.Warn("chaos mode engaged") var err error - chosenUpgrade, err = r.ChaosVersion() + chosenUpgrade, err = app.Recipe.ChaosVersion() if err != nil { log.Fatal(err) } @@ -227,7 +224,7 @@ recipes. app.Env[k] = v } - composeFiles, err := r.GetComposeFiles(app.Env) + composeFiles, err := app.Recipe.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) } @@ -243,7 +240,7 @@ recipes. log.Fatal(err) } appPkg.ExposeAllEnv(stackName, compose, app.Env) - appPkg.SetRecipeLabel(compose, stackName, app.Recipe) + appPkg.SetRecipeLabel(compose, stackName, app.Recipe.Name) appPkg.SetChaosLabel(compose, stackName, internal.Chaos) appPkg.SetChaosVersionLabel(compose, stackName, chosenUpgrade) appPkg.SetUpdateLabel(compose, stackName, app.Env) diff --git a/cli/app/version.go b/cli/app/version.go index 4c5b4667..4ef6469f 100644 --- a/cli/app/version.go +++ b/cli/app/version.go @@ -78,7 +78,7 @@ var appVersionCommand = cli.Command{ log.Fatalf("failed to determine version of deployed %s", app.Name) } - recipeMeta, err := recipe.GetRecipeMeta(app.Recipe, internal.Offline) + recipeMeta, err := recipe.GetRecipeMeta(app.Recipe.Name, internal.Offline) if err != nil { log.Fatal(err) } diff --git a/cli/internal/deploy.go b/cli/internal/deploy.go index 9262fd32..cbca45f4 100644 --- a/cli/internal/deploy.go +++ b/cli/internal/deploy.go @@ -30,7 +30,7 @@ func NewVersionOverview(app appPkg.App, currentVersion, newVersion, releaseNotes server = "local" } - table.Append([]string{server, app.Recipe, deployConfig, app.Domain, currentVersion, newVersion}) + table.Append([]string{server, app.Recipe.Name, deployConfig, app.Domain, currentVersion, newVersion}) table.Render() if releaseNotes != "" && newVersion != "" { @@ -84,7 +84,7 @@ func GetReleaseNotes(recipeName, version string) (string, error) { // the commands string must have the following format: // " | |... " func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error { - abraSh := path.Join(config.RECIPES_DIR, app.Recipe, "abra.sh") + abraSh := path.Join(config.RECIPES_DIR, app.Recipe.Name, "abra.sh") if _, err := os.Stat(abraSh); err != nil { if os.IsNotExist(err) { return fmt.Errorf(fmt.Sprintf("%s does not exist for %s?", abraSh, app.Name)) @@ -105,7 +105,7 @@ func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error { } log.Infof("running post-command '%s %s' in container %s", cmdName, parsedCmdArgs, targetServiceName) - if err := EnsureCommand(abraSh, app.Recipe, cmdName); err != nil { + if err := EnsureCommand(abraSh, app.Recipe.Name, cmdName); err != nil { return err } @@ -150,7 +150,7 @@ func DeployOverview(app appPkg.App, version, message string) error { server = "local" } - table.Append([]string{server, app.Recipe, deployConfig, app.Domain, version}) + table.Append([]string{server, app.Recipe.Name, deployConfig, app.Domain, version}) table.Render() if NoInput { diff --git a/cli/internal/validate.go b/cli/internal/validate.go index 92a0ba3a..ab111864 100644 --- a/cli/internal/validate.go +++ b/cli/internal/validate.go @@ -13,7 +13,7 @@ import ( ) // ValidateRecipe ensures the recipe arg is valid. -func ValidateRecipe(c *cli.Context) recipe.Recipe { +func ValidateRecipe(c *cli.Context) recipe.Recipe2 { recipeName := c.Args().First() if recipeName == "" && !NoInput { @@ -57,7 +57,12 @@ func ValidateRecipe(c *cli.Context) recipe.Recipe { ShowSubcommandHelpAndError(c, errors.New("no recipe name provided")) } - chosenRecipe, err := recipe.Get(recipeName, Offline) + chosenRecipe := recipe.Get2(recipeName) + err := chosenRecipe.EnsureExists() + if err != nil { + log.Fatal(err) + } + _, err = chosenRecipe.GetComposeConfig(nil) if err != nil { if c.Command.Name == "generate" { if strings.Contains(err.Error(), "missing a compose") { diff --git a/cli/recipe/lint.go b/cli/recipe/lint.go index cc73a8a3..4de8be2d 100644 --- a/cli/recipe/lint.go +++ b/cli/recipe/lint.go @@ -8,7 +8,6 @@ import ( "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/lint" "coopcloud.tech/abra/pkg/log" - recipePkg "coopcloud.tech/abra/pkg/recipe" "github.com/urfave/cli" ) @@ -29,8 +28,7 @@ var recipeLintCommand = cli.Command{ Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) - r := recipePkg.Get2(recipe.Name) - if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { + if err := recipe.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } @@ -47,7 +45,7 @@ var recipeLintCommand = cli.Command{ } skipped := false - if rule.Skip(r) { + if rule.Skip(recipe) { skipped = true } @@ -58,7 +56,7 @@ var recipeLintCommand = cli.Command{ satisfied := false if !skipped { - ok, err := rule.Function(r) + ok, err := rule.Function(recipe) if err != nil { log.Warn(err) } diff --git a/cli/recipe/release.go b/cli/recipe/release.go index f639d9f0..90069570 100644 --- a/cli/recipe/release.go +++ b/cli/recipe/release.go @@ -15,7 +15,6 @@ import ( gitPkg "coopcloud.tech/abra/pkg/git" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" - recipePkg "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/tagcmp" "github.com/AlecAivazis/survey/v2" "github.com/distribution/reference" @@ -63,14 +62,13 @@ your SSH keys configured on your account. BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) - r := recipePkg.Get2(recipe.Name) - imagesTmp, err := getImageVersions(r) + imagesTmp, err := getImageVersions(recipe) if err != nil { log.Fatal(err) } - mainApp, err := internal.GetMainAppImage(r) + mainApp, err := internal.GetMainAppImage(recipe) if err != nil { log.Fatal(err) } @@ -92,45 +90,45 @@ your SSH keys configured on your account. } if tagString != "" { - if err := createReleaseFromTag(r, tagString, mainAppVersion); err != nil { + if err := createReleaseFromTag(recipe, tagString, mainAppVersion); err != nil { log.Fatal(err) } } - tags, err := r.Tags() + tags, err := recipe.Tags() if err != nil { log.Fatal(err) } if tagString == "" && (!internal.Major && !internal.Minor && !internal.Patch) { var err error - tagString, err = getLabelVersion(r, false) + tagString, err = getLabelVersion(recipe, false) if err != nil { log.Fatal(err) } } - isClean, err := gitPkg.IsClean(r.Dir) + isClean, err := gitPkg.IsClean(recipe.Dir) if err != nil { log.Fatal(err) } if !isClean { log.Infof("%s currently has these unstaged changes 👇", recipe.Name) - if err := gitPkg.DiffUnstaged(r.Dir); err != nil { + if err := gitPkg.DiffUnstaged(recipe.Dir); err != nil { log.Fatal(err) } } if len(tags) > 0 { logrus.Warnf("previous git tags detected, assuming this is a new semver release") - if err := createReleaseFromPreviousTag(tagString, mainAppVersion, r, tags); err != nil { + 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) - if err := createReleaseFromTag(r, tagString, mainAppVersion); err != nil { + if err := createReleaseFromTag(recipe, tagString, mainAppVersion); err != nil { if cleanUpErr := cleanUpTag(tagString, recipe.Name); err != nil { log.Fatal(cleanUpErr) } diff --git a/cli/recipe/sync.go b/cli/recipe/sync.go index 1d2e2897..10710af8 100644 --- a/cli/recipe/sync.go +++ b/cli/recipe/sync.go @@ -10,7 +10,6 @@ import ( "coopcloud.tech/abra/pkg/config" gitPkg "coopcloud.tech/abra/pkg/git" "coopcloud.tech/abra/pkg/log" - recipePkg "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/tagcmp" "github.com/AlecAivazis/survey/v2" "github.com/go-git/go-git/v5" @@ -45,21 +44,20 @@ local file system. BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) - r := recipePkg.Get2(recipe.Name) - mainApp, err := internal.GetMainAppImage(r) + mainApp, err := internal.GetMainAppImage(recipe) if err != nil { log.Fatal(err) } - imagesTmp, err := getImageVersions(r) + imagesTmp, err := getImageVersions(recipe) if err != nil { log.Fatal(err) } mainAppVersion := imagesTmp[mainApp] - tags, err := r.Tags() + tags, err := recipe.Tags() if err != nil { log.Fatal(err) } @@ -194,20 +192,20 @@ likely to change. mainService := "app" label := fmt.Sprintf("coop-cloud.${STACK_NAME}.version=%s", nextTag) if !internal.Dry { - if err := r.UpdateLabel("compose.y*ml", mainService, label); err != nil { + 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) } - isClean, err := gitPkg.IsClean(r.Dir) + isClean, err := gitPkg.IsClean(recipe.Dir) if err != nil { log.Fatal(err) } if !isClean { log.Infof("%s currently has these unstaged changes 👇", recipe.Name) - if err := gitPkg.DiffUnstaged(r.Dir); err != nil { + if err := gitPkg.DiffUnstaged(recipe.Dir); err != nil { log.Fatal(err) } } diff --git a/cli/recipe/upgrade.go b/cli/recipe/upgrade.go index f49ec182..0887bfbe 100644 --- a/cli/recipe/upgrade.go +++ b/cli/recipe/upgrade.go @@ -73,8 +73,7 @@ You may invoke this command in "wizard" mode and be prompted for input: Action: func(c *cli.Context) error { recipe := internal.ValidateRecipe(c) - r := recipePkg.Get2(recipe.Name) - if err := r.Ensure(internal.Chaos, internal.Offline); err != nil { + if err := recipe.Ensure(internal.Chaos, internal.Offline); err != nil { log.Fatal(err) } @@ -97,7 +96,7 @@ You may invoke this command in "wizard" mode and be prompted for input: versionsPresent := false recipeDir := path.Join(config.RECIPES_DIR, recipe.Name) versionsPath := path.Join(recipeDir, "versions") - var servicePins = make(map[string]imgPin) + servicePins := make(map[string]imgPin) if _, err := os.Stat(versionsPath); err == nil { log.Debugf("found versions file for %s", recipe.Name) file, err := os.Open(versionsPath) @@ -130,7 +129,7 @@ You may invoke this command in "wizard" mode and be prompted for input: log.Debugf("did not find versions file for %s", recipe.Name) } - config, err := r.GetComposeConfig(nil) + config, err := recipe.GetComposeConfig(nil) if err != nil { log.Fatal(err) } @@ -299,7 +298,7 @@ You may invoke this command in "wizard" mode and be prompted for input: } } if upgradeTag != "skip" { - ok, err := r.UpdateTag(image, upgradeTag) + ok, err := recipe.UpdateTag(image, upgradeTag) if err != nil { log.Fatal(err) } diff --git a/cli/updater/updater.go b/cli/updater/updater.go index 04906247..a6721a8b 100644 --- a/cli/updater/updater.go +++ b/cli/updater/updater.go @@ -438,7 +438,7 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName, app := appPkg.App{ Name: stackName, - Recipe: recipeName, + Recipe: recipe.Get2(recipeName), Server: SERVER, Env: env, } diff --git a/pkg/app/app.go b/pkg/app/app.go index 09618341..e7c42e79 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -70,7 +70,7 @@ func GetApps(appFiles AppFiles, recipeFilter string) ([]App, error) { } if recipeFilter != "" { - if app.Recipe == recipeFilter { + if app.Recipe.Name == recipeFilter { apps = append(apps, app) } } else { @@ -84,7 +84,7 @@ func GetApps(appFiles AppFiles, recipeFilter string) ([]App, error) { // App reprents an app with its env file read into memory type App struct { Name AppName - Recipe string + Recipe recipe.Recipe2 Domain string Env envfile.AppEnv Server string @@ -161,14 +161,13 @@ func (a App) Filters(appendServiceNames, exactMatch bool, services ...string) (f return filters, nil } - r := recipe.Get2(a.Recipe) - composeFiles, err := r.GetComposeFiles(a.Env) + composeFiles, err := a.Recipe.GetComposeFiles(a.Env) if err != nil { return filters, err } opts := stack.Deploy{Composefiles: composeFiles} - compose, err := GetAppComposeConfig(a.Recipe, opts, a.Env) + compose, err := GetAppComposeConfig(a.Recipe.Name, opts, a.Env) if err != nil { return filters, err } @@ -207,7 +206,7 @@ func (a ByServerAndRecipe) Len() int { return len(a) } func (a ByServerAndRecipe) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByServerAndRecipe) Less(i, j int) bool { if a[i].Server == a[j].Server { - return strings.ToLower(a[i].Recipe) < strings.ToLower(a[j].Recipe) + return strings.ToLower(a[i].Recipe.Name) < strings.ToLower(a[j].Recipe.Name) } return strings.ToLower(a[i].Server) < strings.ToLower(a[j].Server) } @@ -218,7 +217,7 @@ type ByRecipe []App func (a ByRecipe) Len() int { return len(a) } func (a ByRecipe) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByRecipe) Less(i, j int) bool { - return strings.ToLower(a[i].Recipe) < strings.ToLower(a[j].Recipe) + return strings.ToLower(a[i].Recipe.Name) < strings.ToLower(a[j].Recipe.Name) } // ByName sort a slice of Apps @@ -250,9 +249,9 @@ func ReadAppEnvFile(appFile AppFile, name AppName) (App, error) { func NewApp(env envfile.AppEnv, name string, appFile AppFile) (App, error) { domain := env["DOMAIN"] - recipe, exists := env["RECIPE"] + recipeName, exists := env["RECIPE"] if !exists { - recipe, exists = env["TYPE"] + recipeName, exists = env["TYPE"] if !exists { return App{}, fmt.Errorf("%s is missing the TYPE env var?", name) } @@ -261,7 +260,7 @@ func NewApp(env envfile.AppEnv, name string, appFile AppFile) (App, error) { return App{ Name: name, Domain: domain, - Recipe: recipe, + Recipe: recipe.Get2(recipeName), Env: env, Server: appFile.Server, Path: appFile.Path, @@ -318,14 +317,13 @@ func GetAppServiceNames(appName string) ([]string, error) { return serviceNames, err } - r := recipe.Get2(app.Recipe) - composeFiles, err := r.GetComposeFiles(app.Env) + composeFiles, err := app.Recipe.GetComposeFiles(app.Env) if err != nil { return serviceNames, err } opts := stack.Deploy{Composefiles: composeFiles} - compose, err := GetAppComposeConfig(app.Recipe, opts, app.Env) + compose, err := GetAppComposeConfig(app.Recipe.Name, opts, app.Env) if err != nil { return serviceNames, err } @@ -512,8 +510,7 @@ func ExposeAllEnv(stackName string, compose *composetypes.Config, appEnv envfile func CheckEnv(app App) ([]envfile.EnvVar, error) { var envVars []envfile.EnvVar - r := recipe.Get2(app.Recipe) - envSample, err := r.SampleEnv() + envSample, err := app.Recipe.SampleEnv() if err != nil { return envVars, err } diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index 23828143..d5b07058 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -47,8 +47,8 @@ func TestGetApp(t *testing.T) { } func TestGetComposeFiles(t *testing.T) { - offline := true - r, err := recipe.Get("abra-test-recipe", offline) + r := recipe.Get2("abra-test-recipe") + err := r.EnsureExists() if err != nil { t.Fatal(err) } @@ -95,8 +95,8 @@ func TestGetComposeFiles(t *testing.T) { } func TestGetComposeFilesError(t *testing.T) { - offline := true - r, err := recipe.Get("abra-test-recipe", offline) + r := recipe.Get2("abra-test-recipe") + err := r.EnsureExists() if err != nil { t.Fatal(err) } diff --git a/pkg/envfile/envfile_test.go b/pkg/envfile/envfile_test.go index 6dc47136..2ba67b76 100644 --- a/pkg/envfile/envfile_test.go +++ b/pkg/envfile/envfile_test.go @@ -55,8 +55,8 @@ func TestReadEnv(t *testing.T) { } func TestReadAbraShEnvVars(t *testing.T) { - offline := true - r, err := recipe.Get("abra-test-recipe", offline) + r := recipe.Get2("abra-test-recipe") + err := r.EnsureExists() if err != nil { t.Fatal(err) } @@ -85,8 +85,8 @@ func TestReadAbraShEnvVars(t *testing.T) { } func TestReadAbraShCmdNames(t *testing.T) { - offline := true - r, err := recipe.Get("abra-test-recipe", offline) + r := recipe.Get2("abra-test-recipe") + err := r.EnsureExists() if err != nil { t.Fatal(err) } @@ -110,8 +110,8 @@ func TestReadAbraShCmdNames(t *testing.T) { } func TestCheckEnv(t *testing.T) { - offline := true - r, err := recipe.Get("abra-test-recipe", offline) + r := recipe.Get2("abra-test-recipe") + err := r.EnsureExists() if err != nil { t.Fatal(err) } @@ -124,7 +124,7 @@ func TestCheckEnv(t *testing.T) { app := appPkg.App{ Name: "test-app", - Recipe: r.Name, + Recipe: recipe.Get2(r.Name), Domain: "example.com", Env: envSample, Path: "example.com.env", @@ -144,8 +144,8 @@ func TestCheckEnv(t *testing.T) { } func TestCheckEnvError(t *testing.T) { - offline := true - r, err := recipe.Get("abra-test-recipe", offline) + r := recipe.Get2("abra-test-recipe") + err := r.EnsureExists() if err != nil { t.Fatal(err) } @@ -160,7 +160,7 @@ func TestCheckEnvError(t *testing.T) { app := appPkg.App{ Name: "test-app", - Recipe: r.Name, + Recipe: recipe.Get2(r.Name), Domain: "example.com", Env: envSample, Path: "example.com.env", @@ -180,8 +180,8 @@ func TestCheckEnvError(t *testing.T) { } func TestEnvVarCommentsRemoved(t *testing.T) { - offline := true - r, err := recipe.Get("abra-test-recipe", offline) + r := recipe.Get2("abra-test-recipe") + err := r.EnsureExists() if err != nil { t.Fatal(err) } @@ -212,14 +212,13 @@ func TestEnvVarCommentsRemoved(t *testing.T) { } func TestEnvVarModifiersIncluded(t *testing.T) { - offline := true - r, err := recipe.Get("abra-test-recipe", offline) + r := recipe.Get2("abra-test-recipe") + err := r.EnsureExists() if err != nil { t.Fatal(err) } - r2 := recipe.Get2(r.Name) - envSample, modifiers, err := envfile.ReadEnvWithModifiers(r2.SampleEnvPath) + envSample, modifiers, err := envfile.ReadEnvWithModifiers(r.SampleEnvPath) if err != nil { t.Fatal(err) } diff --git a/pkg/test/test.go b/pkg/test/test.go index a9f2593a..d0860aef 100644 --- a/pkg/test/test.go +++ b/pkg/test/test.go @@ -7,6 +7,7 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/log" + "coopcloud.tech/abra/pkg/recipe" ) var ( @@ -32,7 +33,7 @@ var ExpectedAppEnv = envfile.AppEnv{ var ExpectedApp = appPkg.App{ Name: AppName, - Recipe: ExpectedAppEnv["RECIPE"], + Recipe: recipe.Get2(ExpectedAppEnv["RECIPE"]), Domain: ExpectedAppEnv["DOMAIN"], Env: ExpectedAppEnv, Path: ExpectedAppFile.Path, From f638b6a16b8bb7de073a43df55444ccc8e96aa90 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 13:16:47 +0200 Subject: [PATCH 16/19] refator(recipe): remove old struct --- pkg/recipe/recipe.go | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 4affadd8..46d618ef 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -122,35 +122,6 @@ type Features struct { SSO string `json:"sso"` } -// Recipe represents a recipe. -type Recipe struct { - Name string - Meta RecipeMeta -} - -// Get retrieves a recipe. -func Get(recipeName string, offline bool) (Recipe, error) { - r := Get2(recipeName) - if err := r.EnsureExists(); err != nil { - return Recipe{}, err - } - - meta, err := GetRecipeMeta(r.Name, offline) - if err != nil { - switch err.(type) { - case RecipeMissingFromCatalogue: - meta = RecipeMeta{} - default: - return Recipe{}, err - } - } - - return Recipe{ - Name: recipeName, - Meta: meta, - }, nil -} - func Get2(name string) Recipe2 { dir := path.Join(config.RECIPES_DIR, name) return Recipe2{ From f14d49cc6415a7111e968f4ffea925f46b3cf3d4 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 13:19:40 +0200 Subject: [PATCH 17/19] refactor(recipe): rename Recipe2 -> Recipe --- cli/app/cmd.go | 2 +- cli/app/new.go | 2 +- cli/app/ps.go | 2 +- cli/catalogue/catalogue.go | 2 +- cli/internal/recipe.go | 2 +- cli/internal/validate.go | 4 ++-- cli/recipe/fetch.go | 4 ++-- cli/recipe/new.go | 2 +- cli/recipe/release.go | 14 +++++------ cli/updater/updater.go | 8 +++---- pkg/app/app.go | 6 ++--- pkg/app/app_test.go | 8 +++---- pkg/envfile/envfile_test.go | 22 +++++++++--------- pkg/lint/recipe.go | 46 ++++++++++++++++++------------------- pkg/recipe/compose.go | 10 ++++---- pkg/recipe/files.go | 2 +- pkg/recipe/git.go | 20 ++++++++-------- pkg/recipe/recipe.go | 8 +++---- pkg/recipe/recipe_test.go | 2 +- pkg/secret/secret.go | 2 +- pkg/test/test.go | 2 +- 21 files changed, 85 insertions(+), 85 deletions(-) diff --git a/cli/app/cmd.go b/cli/app/cmd.go index ee230c3d..6bad0a57 100644 --- a/cli/app/cmd.go +++ b/cli/app/cmd.go @@ -211,7 +211,7 @@ var appCmdListCommand = cli.Command{ Before: internal.SubCommandBefore, Action: func(c *cli.Context) error { app := internal.ValidateApp(c) - r := recipe.Get2(app.Name) + r := recipe.Get(app.Name) if err := r.EnsureExists(); err != nil { log.Fatal(err) diff --git a/cli/app/new.go b/cli/app/new.go index 5978f39e..c9e8e9bf 100644 --- a/cli/app/new.go +++ b/cli/app/new.go @@ -230,7 +230,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 recipePkg.Recipe2, 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/ps.go b/cli/app/ps.go index 6e485bd5..5ed15f6b 100644 --- a/cli/app/ps.go +++ b/cli/app/ps.go @@ -67,7 +67,7 @@ var appPsCommand = cli.Command{ // showPSOutput renders ps output. func showPSOutput(app appPkg.App, cl *dockerClient.Client) { - r := recipe.Get2(app.Name) + r := recipe.Get(app.Name) composeFiles, err := r.GetComposeFiles(app.Env) if err != nil { log.Fatal(err) diff --git a/cli/catalogue/catalogue.go b/cli/catalogue/catalogue.go index c5bf3c3b..e3a81e02 100644 --- a/cli/catalogue/catalogue.go +++ b/cli/catalogue/catalogue.go @@ -57,7 +57,7 @@ keys configured on your account. BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipeName := c.Args().First() - r := recipe.Get2(recipeName) + r := recipe.Get(recipeName) if recipeName != "" { internal.ValidateRecipe(c) diff --git a/cli/internal/recipe.go b/cli/internal/recipe.go index 5e8fb887..2e209ae1 100644 --- a/cli/internal/recipe.go +++ b/cli/internal/recipe.go @@ -85,7 +85,7 @@ func SetBumpType(bumpType string) { } // GetMainAppImage retrieves the main 'app' image name -func GetMainAppImage(recipe recipe.Recipe2) (string, error) { +func GetMainAppImage(recipe recipe.Recipe) (string, error) { var path string config, err := recipe.GetComposeConfig(nil) diff --git a/cli/internal/validate.go b/cli/internal/validate.go index ab111864..9f416e91 100644 --- a/cli/internal/validate.go +++ b/cli/internal/validate.go @@ -13,7 +13,7 @@ import ( ) // ValidateRecipe ensures the recipe arg is valid. -func ValidateRecipe(c *cli.Context) recipe.Recipe2 { +func ValidateRecipe(c *cli.Context) recipe.Recipe { recipeName := c.Args().First() if recipeName == "" && !NoInput { @@ -57,7 +57,7 @@ func ValidateRecipe(c *cli.Context) recipe.Recipe2 { ShowSubcommandHelpAndError(c, errors.New("no recipe name provided")) } - chosenRecipe := recipe.Get2(recipeName) + chosenRecipe := recipe.Get(recipeName) err := chosenRecipe.EnsureExists() if err != nil { log.Fatal(err) diff --git a/cli/recipe/fetch.go b/cli/recipe/fetch.go index 62db1256..102f6fb4 100644 --- a/cli/recipe/fetch.go +++ b/cli/recipe/fetch.go @@ -24,7 +24,7 @@ var recipeFetchCommand = cli.Command{ BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipeName := c.Args().First() - r := recipe.Get2(recipeName) + r := recipe.Get(recipeName) if recipeName != "" { internal.ValidateRecipe(c) if err := r.Ensure(false, false); err != nil { @@ -40,7 +40,7 @@ var recipeFetchCommand = cli.Command{ catlBar := formatter.CreateProgressbar(len(catalogue), "fetching latest recipes...") for recipeName := range catalogue { - r := recipe.Get2(recipeName) + r := recipe.Get(recipeName) if err := r.Ensure(false, false); err != nil { log.Error(err) } diff --git a/cli/recipe/new.go b/cli/recipe/new.go index 39f63a6e..d25792cc 100644 --- a/cli/recipe/new.go +++ b/cli/recipe/new.go @@ -56,7 +56,7 @@ recipe and domain in the sample environment config). `, Action: func(c *cli.Context) error { recipeName := c.Args().First() - r := recipe.Get2(recipeName) + r := recipe.Get(recipeName) if recipeName == "" { internal.ShowSubcommandHelpAndError(c, errors.New("no recipe name provided")) diff --git a/cli/recipe/release.go b/cli/recipe/release.go index 90069570..779acea6 100644 --- a/cli/recipe/release.go +++ b/cli/recipe/release.go @@ -141,7 +141,7 @@ your SSH keys configured on your account. } // getImageVersions retrieves image versions for a recipe -func getImageVersions(recipe recipe.Recipe2) (map[string]string, error) { +func getImageVersions(recipe recipe.Recipe) (map[string]string, error) { services := make(map[string]string) config, err := recipe.GetComposeConfig(nil) @@ -185,7 +185,7 @@ func getImageVersions(recipe recipe.Recipe2) (map[string]string, error) { } // createReleaseFromTag creates a new release based on a supplied recipe version string -func createReleaseFromTag(recipe recipe.Recipe2, tagString, mainAppVersion string) error { +func createReleaseFromTag(recipe recipe.Recipe, tagString, mainAppVersion string) error { var err error directory := path.Join(config.RECIPES_DIR, recipe.Name) @@ -249,7 +249,7 @@ func getTagCreateOptions(tag string) (git.CreateTagOptions, error) { // addReleaseNotes checks if the release/next release note exists and moves the // file to release/. -func addReleaseNotes(recipe recipe.Recipe2, tag string) error { +func addReleaseNotes(recipe recipe.Recipe, tag string) error { repoPath := path.Join(config.RECIPES_DIR, recipe.Name) tagReleaseNotePath := path.Join(repoPath, "release", tag) if _, err := os.Stat(tagReleaseNotePath); err == nil { @@ -323,7 +323,7 @@ func addReleaseNotes(recipe recipe.Recipe2, tag string) error { return nil } -func commitRelease(recipe recipe.Recipe2, tag string) error { +func commitRelease(recipe recipe.Recipe, tag string) error { if internal.Dry { log.Debugf("dry run: no changes committed") return nil @@ -376,7 +376,7 @@ func tagRelease(tagString string, repo *git.Repository) error { return nil } -func pushRelease(recipe recipe.Recipe2, tagString string) error { +func pushRelease(recipe recipe.Recipe, tagString string) error { if internal.Dry { log.Info("dry run: no changes published") return nil @@ -405,7 +405,7 @@ func pushRelease(recipe recipe.Recipe2, tagString string) error { return nil } -func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recipe.Recipe2, tags []string) error { +func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recipe.Recipe, tags []string) error { directory := path.Join(config.RECIPES_DIR, recipe.Name) repo, err := git.PlainOpen(directory) if err != nil { @@ -528,7 +528,7 @@ func cleanUpTag(tag, recipeName string) error { return nil } -func getLabelVersion(recipe recipe.Recipe2, prompt bool) (string, error) { +func getLabelVersion(recipe recipe.Recipe, prompt bool) (string, error) { initTag, err := recipe.GetVersionLabelLocal() if err != nil { return "", err diff --git a/cli/updater/updater.go b/cli/updater/updater.go index a6721a8b..94086819 100644 --- a/cli/updater/updater.go +++ b/cli/updater/updater.go @@ -318,7 +318,7 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName // processRecipeRepoVersion clones, pulls, checks out the version and lints the // recipe repository. -func processRecipeRepoVersion(r recipe.Recipe2, version string) error { +func processRecipeRepoVersion(r recipe.Recipe, version string) error { if err := r.EnsureExists(); err != nil { return err } @@ -355,7 +355,7 @@ func mergeAbraShEnv(recipeName string, env envfile.AppEnv) error { } // createDeployConfig merges and enriches the compose config for the deployment. -func createDeployConfig(r recipe.Recipe2, stackName string, env envfile.AppEnv) (*composetypes.Config, stack.Deploy, error) { +func createDeployConfig(r recipe.Recipe, stackName string, env envfile.AppEnv) (*composetypes.Config, stack.Deploy, error) { env["STACK_NAME"] = stackName deployOpts := stack.Deploy{ @@ -438,12 +438,12 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName, app := appPkg.App{ Name: stackName, - Recipe: recipe.Get2(recipeName), + Recipe: recipe.Get(recipeName), Server: SERVER, Env: env, } - r := recipe.Get2(recipeName) + r := recipe.Get(recipeName) if err = processRecipeRepoVersion(r, upgradeVersion); err != nil { return err diff --git a/pkg/app/app.go b/pkg/app/app.go index e7c42e79..41bb2259 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -84,7 +84,7 @@ func GetApps(appFiles AppFiles, recipeFilter string) ([]App, error) { // App reprents an app with its env file read into memory type App struct { Name AppName - Recipe recipe.Recipe2 + Recipe recipe.Recipe Domain string Env envfile.AppEnv Server string @@ -260,7 +260,7 @@ func NewApp(env envfile.AppEnv, name string, appFile AppFile) (App, error) { return App{ Name: name, Domain: domain, - Recipe: recipe.Get2(recipeName), + Recipe: recipe.Get(recipeName), Env: env, Server: appFile.Server, Path: appFile.Path, @@ -358,7 +358,7 @@ func GetAppNames() ([]string, error) { // TemplateAppEnvSample copies the example env file for the app into the users // env files. -func TemplateAppEnvSample(r recipe.Recipe2, appName, server, domain string) error { +func TemplateAppEnvSample(r recipe.Recipe, appName, server, domain string) error { envSample, err := os.ReadFile(r.SampleEnvPath) if err != nil { return err diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index d5b07058..509b0702 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -47,7 +47,7 @@ func TestGetApp(t *testing.T) { } func TestGetComposeFiles(t *testing.T) { - r := recipe.Get2("abra-test-recipe") + r := recipe.Get("abra-test-recipe") err := r.EnsureExists() if err != nil { t.Fatal(err) @@ -85,7 +85,7 @@ func TestGetComposeFiles(t *testing.T) { } for _, test := range tests { - r2 := recipe.Get2(r.Name) + r2 := recipe.Get(r.Name) composeFiles, err := r2.GetComposeFiles(test.appEnv) if err != nil { t.Fatal(err) @@ -95,7 +95,7 @@ func TestGetComposeFiles(t *testing.T) { } func TestGetComposeFilesError(t *testing.T) { - r := recipe.Get2("abra-test-recipe") + r := recipe.Get("abra-test-recipe") err := r.EnsureExists() if err != nil { t.Fatal(err) @@ -107,7 +107,7 @@ func TestGetComposeFilesError(t *testing.T) { } for _, test := range tests { - r2 := recipe.Get2(r.Name) + r2 := recipe.Get(r.Name) _, err := r2.GetComposeFiles(test.appEnv) if err == nil { t.Fatalf("should have failed: %v", test.appEnv) diff --git a/pkg/envfile/envfile_test.go b/pkg/envfile/envfile_test.go index 2ba67b76..dca7a792 100644 --- a/pkg/envfile/envfile_test.go +++ b/pkg/envfile/envfile_test.go @@ -55,7 +55,7 @@ func TestReadEnv(t *testing.T) { } func TestReadAbraShEnvVars(t *testing.T) { - r := recipe.Get2("abra-test-recipe") + r := recipe.Get("abra-test-recipe") err := r.EnsureExists() if err != nil { t.Fatal(err) @@ -85,7 +85,7 @@ func TestReadAbraShEnvVars(t *testing.T) { } func TestReadAbraShCmdNames(t *testing.T) { - r := recipe.Get2("abra-test-recipe") + r := recipe.Get("abra-test-recipe") err := r.EnsureExists() if err != nil { t.Fatal(err) @@ -110,13 +110,13 @@ func TestReadAbraShCmdNames(t *testing.T) { } func TestCheckEnv(t *testing.T) { - r := recipe.Get2("abra-test-recipe") + r := recipe.Get("abra-test-recipe") err := r.EnsureExists() if err != nil { t.Fatal(err) } - r2 := recipe.Get2(r.Name) + r2 := recipe.Get(r.Name) envSample, err := r2.SampleEnv() if err != nil { t.Fatal(err) @@ -124,7 +124,7 @@ func TestCheckEnv(t *testing.T) { app := appPkg.App{ Name: "test-app", - Recipe: recipe.Get2(r.Name), + Recipe: recipe.Get(r.Name), Domain: "example.com", Env: envSample, Path: "example.com.env", @@ -144,13 +144,13 @@ func TestCheckEnv(t *testing.T) { } func TestCheckEnvError(t *testing.T) { - r := recipe.Get2("abra-test-recipe") + r := recipe.Get("abra-test-recipe") err := r.EnsureExists() if err != nil { t.Fatal(err) } - r2 := recipe.Get2(r.Name) + r2 := recipe.Get(r.Name) envSample, err := r2.SampleEnv() if err != nil { t.Fatal(err) @@ -160,7 +160,7 @@ func TestCheckEnvError(t *testing.T) { app := appPkg.App{ Name: "test-app", - Recipe: recipe.Get2(r.Name), + Recipe: recipe.Get(r.Name), Domain: "example.com", Env: envSample, Path: "example.com.env", @@ -180,13 +180,13 @@ func TestCheckEnvError(t *testing.T) { } func TestEnvVarCommentsRemoved(t *testing.T) { - r := recipe.Get2("abra-test-recipe") + r := recipe.Get("abra-test-recipe") err := r.EnsureExists() if err != nil { t.Fatal(err) } - r2 := recipe.Get2(r.Name) + r2 := recipe.Get(r.Name) envSample, err := r2.SampleEnv() if err != nil { t.Fatal(err) @@ -212,7 +212,7 @@ func TestEnvVarCommentsRemoved(t *testing.T) { } func TestEnvVarModifiersIncluded(t *testing.T) { - r := recipe.Get2("abra-test-recipe") + r := recipe.Get("abra-test-recipe") err := r.EnsureExists() if err != nil { t.Fatal(err) diff --git a/pkg/lint/recipe.go b/pkg/lint/recipe.go index d4d366cb..ae371e32 100644 --- a/pkg/lint/recipe.go +++ b/pkg/lint/recipe.go @@ -19,13 +19,13 @@ import ( var Warn = "warn" var Critical = "critical" -type LintFunction func(recipe.Recipe2) (bool, error) +type LintFunction func(recipe.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.Recipe2) (bool, error) +type SkipFunction func(recipe.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 +42,7 @@ type LintRule struct { } // Skip implements the SkipFunction for the lint rule. -func (l LintRule) Skip(recipe recipe.Recipe2) bool { +func (l LintRule) Skip(recipe recipe.Recipe) bool { if l.SkipCondition != nil { ok, err := l.SkipCondition(recipe) if err != nil { @@ -173,7 +173,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.Recipe2) error { +func LintForErrors(recipe recipe.Recipe) error { log.Debugf("linting for critical errors in %s configs", recipe.Name) for level := range LintRules { @@ -201,7 +201,7 @@ func LintForErrors(recipe recipe.Recipe2) error { return nil } -func LintComposeVersion(recipe recipe.Recipe2) (bool, error) { +func LintComposeVersion(recipe recipe.Recipe) (bool, error) { config, err := recipe.GetComposeConfig(nil) if err != nil { return false, err @@ -213,8 +213,8 @@ func LintComposeVersion(recipe recipe.Recipe2) (bool, error) { return true, nil } -func LintEnvConfigPresent(r recipe.Recipe2) (bool, error) { - r2 := recipe.Get2(r.Name) +func LintEnvConfigPresent(r recipe.Recipe) (bool, error) { + r2 := recipe.Get(r.Name) if _, err := os.Stat(r2.SampleEnvPath); !os.IsNotExist(err) { return true, nil } @@ -222,7 +222,7 @@ func LintEnvConfigPresent(r recipe.Recipe2) (bool, error) { return false, nil } -func LintAppService(recipe recipe.Recipe2) (bool, error) { +func LintAppService(recipe recipe.Recipe) (bool, error) { config, err := recipe.GetComposeConfig(nil) if err != nil { return false, err @@ -240,8 +240,8 @@ func LintAppService(recipe recipe.Recipe2) (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(r recipe.Recipe2) (bool, error) { - r2 := recipe.Get2(r.Name) +func LintTraefikEnabledSkipCondition(r recipe.Recipe) (bool, error) { + r2 := recipe.Get(r.Name) sampleEnv, err := r2.SampleEnv() if err != nil { return false, fmt.Errorf("Unable to discover .env.sample for %s", r2.Name) @@ -254,7 +254,7 @@ func LintTraefikEnabledSkipCondition(r recipe.Recipe2) (bool, error) { return false, nil } -func LintTraefikEnabled(recipe recipe.Recipe2) (bool, error) { +func LintTraefikEnabled(recipe recipe.Recipe) (bool, error) { config, err := recipe.GetComposeConfig(nil) if err != nil { return false, err @@ -272,7 +272,7 @@ func LintTraefikEnabled(recipe recipe.Recipe2) (bool, error) { return false, nil } -func LintHealthchecks(recipe recipe.Recipe2) (bool, error) { +func LintHealthchecks(recipe recipe.Recipe) (bool, error) { config, err := recipe.GetComposeConfig(nil) if err != nil { return false, err @@ -286,7 +286,7 @@ func LintHealthchecks(recipe recipe.Recipe2) (bool, error) { return true, nil } -func LintAllImagesTagged(recipe recipe.Recipe2) (bool, error) { +func LintAllImagesTagged(recipe recipe.Recipe) (bool, error) { config, err := recipe.GetComposeConfig(nil) if err != nil { return false, err @@ -304,7 +304,7 @@ func LintAllImagesTagged(recipe recipe.Recipe2) (bool, error) { return true, nil } -func LintNoUnstableTags(recipe recipe.Recipe2) (bool, error) { +func LintNoUnstableTags(recipe recipe.Recipe) (bool, error) { config, err := recipe.GetComposeConfig(nil) if err != nil { return false, err @@ -331,7 +331,7 @@ func LintNoUnstableTags(recipe recipe.Recipe2) (bool, error) { return true, nil } -func LintSemverLikeTags(recipe recipe.Recipe2) (bool, error) { +func LintSemverLikeTags(recipe recipe.Recipe) (bool, error) { config, err := recipe.GetComposeConfig(nil) if err != nil { return false, err @@ -358,7 +358,7 @@ func LintSemverLikeTags(recipe recipe.Recipe2) (bool, error) { return true, nil } -func LintImagePresent(recipe recipe.Recipe2) (bool, error) { +func LintImagePresent(recipe recipe.Recipe) (bool, error) { config, err := recipe.GetComposeConfig(nil) if err != nil { return false, err @@ -371,7 +371,7 @@ func LintImagePresent(recipe recipe.Recipe2) (bool, error) { return true, nil } -func LintHasPublishedVersion(recipe recipe.Recipe2) (bool, error) { +func LintHasPublishedVersion(recipe recipe.Recipe) (bool, error) { catl, err := recipePkg.ReadRecipeCatalogue(false) if err != nil { log.Fatal(err) @@ -389,8 +389,8 @@ func LintHasPublishedVersion(recipe recipe.Recipe2) (bool, error) { return true, nil } -func LintMetadataFilledIn(r recipe.Recipe2) (bool, error) { - r2 := recipe.Get2(r.Name) +func LintMetadataFilledIn(r recipe.Recipe) (bool, error) { + r2 := recipe.Get(r.Name) features, category, err := recipe.GetRecipeFeaturesAndCategory(r2) if err != nil { return false, err @@ -411,7 +411,7 @@ func LintMetadataFilledIn(r recipe.Recipe2) (bool, error) { return true, nil } -func LintAbraShVendors(recipe recipe.Recipe2) (bool, error) { +func LintAbraShVendors(recipe recipe.Recipe) (bool, error) { config, err := recipe.GetComposeConfig(nil) if err != nil { return false, err @@ -430,7 +430,7 @@ func LintAbraShVendors(recipe recipe.Recipe2) (bool, error) { return true, nil } -func LintHasRecipeRepo(recipe recipe.Recipe2) (bool, error) { +func LintHasRecipeRepo(recipe recipe.Recipe) (bool, error) { url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, recipe.Name) res, err := http.Get(url) @@ -445,7 +445,7 @@ func LintHasRecipeRepo(recipe recipe.Recipe2) (bool, error) { return true, nil } -func LintSecretLengths(recipe recipe.Recipe2) (bool, error) { +func LintSecretLengths(recipe recipe.Recipe) (bool, error) { config, err := recipe.GetComposeConfig(nil) if err != nil { return false, err @@ -459,7 +459,7 @@ func LintSecretLengths(recipe recipe.Recipe2) (bool, error) { return true, nil } -func LintValidTags(recipe recipe.Recipe2) (bool, error) { +func LintValidTags(recipe recipe.Recipe) (bool, error) { recipeDir := path.Join(config.RECIPES_DIR, recipe.Name) repo, err := git.PlainOpen(recipeDir) diff --git a/pkg/recipe/compose.go b/pkg/recipe/compose.go index 5312263a..736e5f70 100644 --- a/pkg/recipe/compose.go +++ b/pkg/recipe/compose.go @@ -18,7 +18,7 @@ import ( // GetComposeFiles gets the list of compose files for an app (or recipe if you // don't already have an app) which should be merged into a composetypes.Config // while respecting the COMPOSE_FILE env var. -func (r Recipe2) GetComposeFiles(appEnv map[string]string) ([]string, error) { +func (r Recipe) GetComposeFiles(appEnv map[string]string) ([]string, error) { composeFileEnvVar, ok := appEnv["COMPOSE_FILE"] if !ok { if err := ensurePathExists(r.ComposePath); err != nil { @@ -59,7 +59,7 @@ func (r Recipe2) GetComposeFiles(appEnv map[string]string) ([]string, error) { return composeFiles, nil } -func (r Recipe2) GetComposeConfig(env map[string]string) (*composetypes.Config, error) { +func (r Recipe) GetComposeConfig(env map[string]string) (*composetypes.Config, error) { pattern := fmt.Sprintf("%s/compose**yml", r.Dir) composeFiles, err := filepath.Glob(pattern) if err != nil { @@ -86,7 +86,7 @@ func (r Recipe2) GetComposeConfig(env map[string]string) (*composetypes.Config, } // GetVersionLabelLocal retrieves the version label on the local recipe config -func (r Recipe2) GetVersionLabelLocal() (string, error) { +func (r Recipe) GetVersionLabelLocal() (string, error) { var label string config, err := r.GetComposeConfig(nil) if err != nil { @@ -109,7 +109,7 @@ func (r Recipe2) GetVersionLabelLocal() (string, error) { } // UpdateTag updates an image tag in-place on file system local compose files. -func (r Recipe2) UpdateTag(image, tag string) (bool, error) { +func (r Recipe) UpdateTag(image, tag string) (bool, error) { fullPattern := fmt.Sprintf("%s/compose**yml", r.Dir) image = formatter.StripTagMeta(image) @@ -179,7 +179,7 @@ func (r Recipe2) UpdateTag(image, tag string) (bool, error) { } // UpdateLabel updates a label in-place on file system local compose files. -func (r Recipe2) UpdateLabel(pattern, serviceName, label string) error { +func (r Recipe) UpdateLabel(pattern, serviceName, label string) error { fullPattern := fmt.Sprintf("%s/%s", r.Dir, pattern) composeFiles, err := filepath.Glob(fullPattern) if err != nil { diff --git a/pkg/recipe/files.go b/pkg/recipe/files.go index 8bc76b25..88ab5e59 100644 --- a/pkg/recipe/files.go +++ b/pkg/recipe/files.go @@ -6,7 +6,7 @@ import ( "coopcloud.tech/abra/pkg/envfile" ) -func (r Recipe2) SampleEnv() (map[string]string, error) { +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) diff --git a/pkg/recipe/git.go b/pkg/recipe/git.go index d41fa498..0d6ddc63 100644 --- a/pkg/recipe/git.go +++ b/pkg/recipe/git.go @@ -16,7 +16,7 @@ import ( ) // Ensure makes sure the recipe exists, is up to date and has the latest version checked out. -func (r Recipe2) Ensure(chaos bool, offline bool) error { +func (r Recipe) Ensure(chaos bool, offline bool) error { if err := r.EnsureExists(); err != nil { return err } @@ -38,7 +38,7 @@ func (r Recipe2) Ensure(chaos bool, offline bool) error { } // EnsureExists ensures that the recipe is locally cloned -func (r Recipe2) EnsureExists() error { +func (r Recipe) EnsureExists() error { recipeDir := path.Join(config.RECIPES_DIR, r.Name) if _, err := os.Stat(recipeDir); os.IsNotExist(err) { @@ -57,7 +57,7 @@ func (r Recipe2) EnsureExists() error { } // EnsureVersion checks whether a specific version exists for a recipe. -func (r Recipe2) EnsureVersion(version string) error { +func (r Recipe) EnsureVersion(version string) error { recipeDir := path.Join(config.RECIPES_DIR, r.Name) if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { @@ -115,7 +115,7 @@ func (r Recipe2) EnsureVersion(version string) error { } // EnsureIsClean makes sure that the recipe repository has no unstaged changes. -func (r Recipe2) EnsureIsClean() error { +func (r Recipe) EnsureIsClean() error { recipeDir := path.Join(config.RECIPES_DIR, r.Name) isClean, err := gitPkg.IsClean(recipeDir) @@ -132,7 +132,7 @@ func (r Recipe2) EnsureIsClean() error { } // EnsureLatest makes sure the latest commit is checked out for the local recipe repository -func (r Recipe2) EnsureLatest() error { +func (r Recipe) EnsureLatest() error { recipeDir := path.Join(config.RECIPES_DIR, r.Name) if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { @@ -169,7 +169,7 @@ func (r Recipe2) EnsureLatest() error { } // EnsureUpToDate ensures that the local repo is synced to the remote -func (r Recipe2) EnsureUpToDate() error { +func (r Recipe) EnsureUpToDate() error { recipeDir := path.Join(config.RECIPES_DIR, r.Name) repo, err := git.PlainOpen(recipeDir) @@ -222,7 +222,7 @@ func (r Recipe2) EnsureUpToDate() error { } // ChaosVersion constructs a chaos mode recipe version. -func (r Recipe2) ChaosVersion() (string, error) { +func (r Recipe) ChaosVersion() (string, error) { var version string head, err := gitPkg.GetRecipeHead(r.Name) @@ -247,7 +247,7 @@ func (r Recipe2) ChaosVersion() (string, error) { // Push pushes the latest changes to a SSH URL remote. You need to have your // local SSH configuration for git.coopcloud.tech working for this to work -func (r Recipe2) Push(dryRun bool) error { +func (r Recipe) Push(dryRun bool) error { repo, err := git.PlainOpen(r.Dir) if err != nil { return err @@ -265,7 +265,7 @@ func (r Recipe2) Push(dryRun bool) error { } // Tags list the recipe tags -func (r Recipe2) Tags() ([]string, error) { +func (r Recipe) Tags() ([]string, error) { var tags []string repo, err := git.PlainOpen(r.Dir) @@ -291,7 +291,7 @@ func (r Recipe2) Tags() ([]string, error) { } // GetRecipeVersions retrieves all recipe versions. -func (r Recipe2) GetRecipeVersions(offline bool) (RecipeVersions, error) { +func (r Recipe) GetRecipeVersions(offline bool) (RecipeVersions, error) { versions := RecipeVersions{} log.Debugf("attempting to open git repository in %s", r.Dir) diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index 46d618ef..bbf63668 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -122,9 +122,9 @@ type Features struct { SSO string `json:"sso"` } -func Get2(name string) Recipe2 { +func Get(name string) Recipe { dir := path.Join(config.RECIPES_DIR, name) - return Recipe2{ + return Recipe{ Name: name, Dir: dir, SSHURL: fmt.Sprintf(config.SSH_URL_TEMPLATE, name), @@ -135,7 +135,7 @@ func Get2(name string) Recipe2 { } } -type Recipe2 struct { +type Recipe struct { Name string Dir string SSHURL string @@ -157,7 +157,7 @@ func GetRecipesLocal() ([]string, error) { return recipes, nil } -func GetRecipeFeaturesAndCategory(r Recipe2) (Features, string, error) { +func GetRecipeFeaturesAndCategory(r Recipe) (Features, string, error) { feat := Features{} var category string diff --git a/pkg/recipe/recipe_test.go b/pkg/recipe/recipe_test.go index 08e23a07..37453c4d 100644 --- a/pkg/recipe/recipe_test.go +++ b/pkg/recipe/recipe_test.go @@ -14,7 +14,7 @@ func TestGetVersionLabelLocalDoesNotUseTimeoutLabel(t *testing.T) { t.Fatal(err) } - r := Get2("traefik") + r := Get("traefik") for i := 1; i < 1000; i++ { label, err := r.GetVersionLabelLocal() diff --git a/pkg/secret/secret.go b/pkg/secret/secret.go index 0f1d6d7b..d320816b 100644 --- a/pkg/secret/secret.go +++ b/pkg/secret/secret.go @@ -246,7 +246,7 @@ type secretStatuses []secretStatus func PollSecretsStatus(cl *dockerClient.Client, app appPkg.App) (secretStatuses, error) { var secStats secretStatuses - r := recipe.Get2(app.Name) + r := recipe.Get(app.Name) composeFiles, err := r.GetComposeFiles(app.Env) if err != nil { return secStats, err diff --git a/pkg/test/test.go b/pkg/test/test.go index d0860aef..1109a5dd 100644 --- a/pkg/test/test.go +++ b/pkg/test/test.go @@ -33,7 +33,7 @@ var ExpectedAppEnv = envfile.AppEnv{ var ExpectedApp = appPkg.App{ Name: AppName, - Recipe: recipe.Get2(ExpectedAppEnv["RECIPE"]), + Recipe: recipe.Get(ExpectedAppEnv["RECIPE"]), Domain: ExpectedAppEnv["DOMAIN"], Env: ExpectedAppEnv, Path: ExpectedAppFile.Path, From 87ecc05962be36b12fe2d44192556e619adee80e Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 13:38:29 +0200 Subject: [PATCH 18/19] refactor(recipe): remove direct usage of config.RECIPE_DIR --- cli/app/cmd.go | 20 ++++++++------------ cli/app/deploy.go | 5 +---- cli/app/rollback.go | 4 +--- cli/app/upgrade.go | 6 ++---- cli/internal/deploy.go | 32 ++++---------------------------- cli/recipe/diff.go | 8 +++----- cli/recipe/new.go | 16 +++++++--------- cli/recipe/release.go | 27 +++++++++++---------------- cli/recipe/reset.go | 8 +++----- cli/recipe/sync.go | 5 +---- cli/recipe/upgrade.go | 8 +++----- cli/updater/updater.go | 8 +++----- pkg/app/app_test.go | 10 +++++----- pkg/envfile/envfile_test.go | 9 +++------ pkg/lint/recipe.go | 6 ++---- pkg/recipe/files.go | 22 ++++++++++++++++++++++ pkg/recipe/recipe.go | 5 +++-- 17 files changed, 82 insertions(+), 117 deletions(-) diff --git a/cli/app/cmd.go b/cli/app/cmd.go index 6bad0a57..52dc03eb 100644 --- a/cli/app/cmd.go +++ b/cli/app/cmd.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "os/exec" - "path" "sort" "strings" @@ -14,7 +13,6 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" - "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" "github.com/urfave/cli" @@ -70,10 +68,9 @@ Example: hasCmdArgs, parsedCmdArgs := parseCmdArgs(c.Args(), internal.LocalCmd) - abraSh := path.Join(config.RECIPES_DIR, app.Recipe.Name, "abra.sh") - if _, err := os.Stat(abraSh); err != nil { + if _, err := os.Stat(app.Recipe.AbraShPath); err != nil { if os.IsNotExist(err) { - log.Fatalf("%s does not exist for %s?", abraSh, app.Name) + log.Fatalf("%s does not exist for %s?", app.Recipe.AbraShPath, app.Name) } log.Fatal(err) } @@ -84,7 +81,7 @@ Example: } cmdName := c.Args().Get(1) - if err := internal.EnsureCommand(abraSh, app.Recipe.Name, cmdName); err != nil { + if err := internal.EnsureCommand(app.Recipe.AbraShPath, app.Recipe.Name, cmdName); err != nil { log.Fatal(err) } @@ -98,10 +95,10 @@ Example: var sourceAndExec string if hasCmdArgs { log.Debugf("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, abraSh, cmdName, 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") - sourceAndExec = fmt.Sprintf("TARGET=local; APP_NAME=%s; STACK_NAME=%s; %s . %s; %s", app.Name, app.StackName(), exportEnv, abraSh, cmdName) + 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" @@ -122,7 +119,7 @@ Example: targetServiceName := c.Args().Get(1) cmdName := c.Args().Get(2) - if err := internal.EnsureCommand(abraSh, app.Recipe.Name, cmdName); err != nil { + if err := internal.EnsureCommand(app.Recipe.AbraShPath, app.Recipe.Name, cmdName); err != nil { log.Fatal(err) } @@ -155,7 +152,7 @@ Example: log.Fatal(err) } - if err := internal.RunCmdRemote(cl, app, abraSh, targetServiceName, cmdName, parsedCmdArgs); err != nil { + if err := internal.RunCmdRemote(cl, app, app.Recipe.AbraShPath, targetServiceName, cmdName, parsedCmdArgs); err != nil { log.Fatal(err) } } @@ -247,8 +244,7 @@ var appCmdListCommand = cli.Command{ } func getShCmdNames(app appPkg.App) ([]string, error) { - abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, app.Recipe, "abra.sh") - cmdNames, err := appPkg.ReadAbraShCmdNames(abraShPath) + cmdNames, err := appPkg.ReadAbraShCmdNames(app.Recipe.AbraShPath) if err != nil { return nil, err } diff --git a/cli/app/deploy.go b/cli/app/deploy.go index 9d3bc950..cdbca1af 100644 --- a/cli/app/deploy.go +++ b/cli/app/deploy.go @@ -2,7 +2,6 @@ package app import ( "context" - "fmt" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" @@ -11,7 +10,6 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/client" - "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/dns" "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/git" @@ -158,8 +156,7 @@ recipes. } } - abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, app.Recipe, "abra.sh") - abraShEnv, err := envfile.ReadAbraShEnvVars(abraShPath) + abraShEnv, err := envfile.ReadAbraShEnvVars(app.Recipe.AbraShPath) if err != nil { log.Fatal(err) } diff --git a/cli/app/rollback.go b/cli/app/rollback.go index ae65346d..b552d2b1 100644 --- a/cli/app/rollback.go +++ b/cli/app/rollback.go @@ -6,7 +6,6 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/autocomplete" - "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/lint" "coopcloud.tech/abra/pkg/recipe" @@ -178,8 +177,7 @@ recipes. } } - abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, app.Recipe, "abra.sh") - abraShEnv, err := envfile.ReadAbraShEnvVars(abraShPath) + abraShEnv, err := envfile.ReadAbraShEnvVars(app.Recipe.AbraShPath) if err != nil { log.Fatal(err) } diff --git a/cli/app/upgrade.go b/cli/app/upgrade.go index d1cb5101..b663526b 100644 --- a/cli/app/upgrade.go +++ b/cli/app/upgrade.go @@ -8,7 +8,6 @@ import ( appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" - "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/lint" "coopcloud.tech/abra/pkg/log" @@ -189,7 +188,7 @@ recipes. log.Fatal(err) } if parsedVersion.IsGreaterThan(parsedDeployedVersion) && parsedVersion.IsLessThan(parsedChosenUpgrade) { - note, err := internal.GetReleaseNotes(app.Recipe.Name, version) + note, err := app.Recipe.GetReleaseNotes(version) if err != nil { return err } @@ -215,8 +214,7 @@ recipes. } } - abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, app.Recipe, "abra.sh") - abraShEnv, err := envfile.ReadAbraShEnvVars(abraShPath) + abraShEnv, err := envfile.ReadAbraShEnvVars(app.Recipe.AbraShPath) if err != nil { log.Fatal(err) } diff --git a/cli/internal/deploy.go b/cli/internal/deploy.go index cbca45f4..698aab05 100644 --- a/cli/internal/deploy.go +++ b/cli/internal/deploy.go @@ -2,13 +2,10 @@ package internal import ( "fmt" - "io/ioutil" "os" - "path" "strings" appPkg "coopcloud.tech/abra/pkg/app" - "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/log" "github.com/AlecAivazis/survey/v2" @@ -60,34 +57,13 @@ func NewVersionOverview(app appPkg.App, currentVersion, newVersion, releaseNotes return nil } -// GetReleaseNotes prints release notes for a recipe version -func GetReleaseNotes(recipeName, version string) (string, error) { - if version == "" { - return "", nil - } - - fpath := path.Join(config.RECIPES_DIR, recipeName, "release", version) - - if _, err := os.Stat(fpath); !os.IsNotExist(err) { - releaseNotes, err := ioutil.ReadFile(fpath) - if err != nil { - return "", err - } - withTitle := fmt.Sprintf("%s release notes:\n%s", version, string(releaseNotes)) - return withTitle, nil - } - - return "", nil -} - // PostCmds parses a string of commands and executes them inside of the respective services // the commands string must have the following format: // " | |... " func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error { - abraSh := path.Join(config.RECIPES_DIR, app.Recipe.Name, "abra.sh") - if _, err := os.Stat(abraSh); err != nil { + if _, err := os.Stat(app.Recipe.AbraShPath); err != nil { if os.IsNotExist(err) { - return fmt.Errorf(fmt.Sprintf("%s does not exist for %s?", abraSh, app.Name)) + return fmt.Errorf(fmt.Sprintf("%s does not exist for %s?", app.Recipe.AbraShPath, app.Name)) } return err } @@ -105,7 +81,7 @@ func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error { } log.Infof("running post-command '%s %s' in container %s", cmdName, parsedCmdArgs, targetServiceName) - if err := EnsureCommand(abraSh, app.Recipe.Name, cmdName); err != nil { + if err := EnsureCommand(app.Recipe.AbraShPath, app.Recipe.Name, cmdName); err != nil { return err } @@ -128,7 +104,7 @@ func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error { log.Debugf("running command %s %s within the context of %s_%s", cmdName, parsedCmdArgs, app.StackName(), targetServiceName) Tty = true - if err := RunCmdRemote(cl, app, abraSh, targetServiceName, cmdName, parsedCmdArgs); err != nil { + if err := RunCmdRemote(cl, app, app.Recipe.AbraShPath, targetServiceName, cmdName, parsedCmdArgs); err != nil { return err } } diff --git a/cli/recipe/diff.go b/cli/recipe/diff.go index 67278746..fa687650 100644 --- a/cli/recipe/diff.go +++ b/cli/recipe/diff.go @@ -1,13 +1,11 @@ package recipe import ( - "path" - "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" - "coopcloud.tech/abra/pkg/config" gitPkg "coopcloud.tech/abra/pkg/git" "coopcloud.tech/abra/pkg/log" + "coopcloud.tech/abra/pkg/recipe" "github.com/urfave/cli" ) @@ -25,13 +23,13 @@ var recipeDiffCommand = cli.Command{ BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipeName := c.Args().First() + r := recipe.Get(recipeName) if recipeName != "" { internal.ValidateRecipe(c) } - recipeDir := path.Join(config.RECIPES_DIR, recipeName) - if err := gitPkg.DiffUnstaged(recipeDir); err != nil { + if err := gitPkg.DiffUnstaged(r.Dir); err != nil { log.Fatal(err) } diff --git a/cli/recipe/new.go b/cli/recipe/new.go index d25792cc..f55335f5 100644 --- a/cli/recipe/new.go +++ b/cli/recipe/new.go @@ -62,17 +62,16 @@ recipe and domain in the sample environment config). internal.ShowSubcommandHelpAndError(c, errors.New("no recipe name provided")) } - directory := path.Join(config.RECIPES_DIR, recipeName) - if _, err := os.Stat(directory); !os.IsNotExist(err) { - log.Fatalf("%s recipe directory already exists?", directory) + if _, err := os.Stat(r.Dir); !os.IsNotExist(err) { + log.Fatalf("%s recipe directory already exists?", r.Dir) } url := fmt.Sprintf("%s/example.git", config.REPOS_BASE_URL) - if err := git.Clone(directory, url); err != nil { + if err := git.Clone(r.Dir, url); err != nil { log.Fatal(err) } - gitRepo := path.Join(config.RECIPES_DIR, recipeName, ".git") + gitRepo := path.Join(r.Dir, ".git") if err := os.RemoveAll(gitRepo); err != nil { log.Fatal(err) } @@ -91,14 +90,13 @@ recipe and domain in the sample environment config). log.Fatal(err) } - if err := os.WriteFile(path, templated.Bytes(), 0644); err != nil { + if err := os.WriteFile(path, templated.Bytes(), 0o644); err != nil { log.Fatal(err) } } - newGitRepo := path.Join(config.RECIPES_DIR, recipeName) - if err := git.Init(newGitRepo, true, internal.GitName, internal.GitEmail); err != nil { + if err := git.Init(r.Dir, true, internal.GitName, internal.GitEmail); err != nil { log.Fatal(err) } @@ -117,7 +115,7 @@ See "abra recipe -h" for additional recipe maintainer commands. Happy Hacking! -`, recipeName, path.Join(config.RECIPES_DIR, recipeName), recipeName)) +`, recipeName, path.Join(r.Dir), recipeName)) return nil }, diff --git a/cli/recipe/release.go b/cli/recipe/release.go index 779acea6..e7270d51 100644 --- a/cli/recipe/release.go +++ b/cli/recipe/release.go @@ -129,7 +129,7 @@ your SSH keys configured on your account. log.Warnf("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(tagString, recipe.Name); err != nil { + if cleanUpErr := cleanUpTag(recipe, tagString); err != nil { log.Fatal(cleanUpErr) } log.Fatal(err) @@ -188,8 +188,7 @@ func getImageVersions(recipe recipe.Recipe) (map[string]string, error) { func createReleaseFromTag(recipe recipe.Recipe, tagString, mainAppVersion string) error { var err error - directory := path.Join(config.RECIPES_DIR, recipe.Name) - repo, err := git.PlainOpen(directory) + repo, err := git.PlainOpen(recipe.Dir) if err != nil { return err } @@ -250,8 +249,7 @@ func getTagCreateOptions(tag string) (git.CreateTagOptions, error) { // addReleaseNotes checks if the release/next release note exists and moves the // file to release/. func addReleaseNotes(recipe recipe.Recipe, tag string) error { - repoPath := path.Join(config.RECIPES_DIR, recipe.Name) - tagReleaseNotePath := path.Join(repoPath, "release", tag) + tagReleaseNotePath := path.Join(recipe.Dir, "release", tag) if _, err := os.Stat(tagReleaseNotePath); err == nil { // Release note for current tag already exist exists. return nil @@ -259,7 +257,7 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error { return err } - nextReleaseNotePath := path.Join(repoPath, "release", "next") + nextReleaseNotePath := path.Join(recipe.Dir, "release", "next") if _, err := os.Stat(nextReleaseNotePath); err == nil { // release/next note exists. Move it to release/ if internal.Dry { @@ -282,11 +280,11 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error { if err != nil { return err } - err = gitPkg.Add(repoPath, path.Join("release", "next"), internal.Dry) + err = gitPkg.Add(recipe.Dir, path.Join("release", "next"), internal.Dry) if err != nil { return err } - err = gitPkg.Add(repoPath, path.Join("release", tag), internal.Dry) + err = gitPkg.Add(recipe.Dir, path.Join("release", tag), internal.Dry) if err != nil { return err } @@ -315,7 +313,7 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error { if err != nil { return err } - err = gitPkg.Add(repoPath, path.Join("release", tag), internal.Dry) + err = gitPkg.Add(recipe.Dir, path.Join("release", tag), internal.Dry) if err != nil { return err } @@ -341,8 +339,7 @@ func commitRelease(recipe recipe.Recipe, tag string) error { } msg := fmt.Sprintf("chore: publish %s release", tag) - repoPath := path.Join(config.RECIPES_DIR, recipe.Name) - if err := gitPkg.Commit(repoPath, msg, internal.Dry); err != nil { + if err := gitPkg.Commit(recipe.Dir, msg, internal.Dry); err != nil { return err } @@ -406,8 +403,7 @@ func pushRelease(recipe recipe.Recipe, tagString string) error { } func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recipe.Recipe, tags []string) error { - directory := path.Join(config.RECIPES_DIR, recipe.Name) - repo, err := git.PlainOpen(directory) + repo, err := git.PlainOpen(recipe.Dir) if err != nil { return err } @@ -510,9 +506,8 @@ func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recip } // cleanUpTag removes a freshly created tag -func cleanUpTag(tag, recipeName string) error { - directory := path.Join(config.RECIPES_DIR, recipeName) - repo, err := git.PlainOpen(directory) +func cleanUpTag(recipe recipe.Recipe, tag string) error { + repo, err := git.PlainOpen(recipe.Dir) if err != nil { return err } diff --git a/cli/recipe/reset.go b/cli/recipe/reset.go index 3c403219..915f3382 100644 --- a/cli/recipe/reset.go +++ b/cli/recipe/reset.go @@ -1,12 +1,10 @@ package recipe import ( - "path" - "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" - "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/log" + "coopcloud.tech/abra/pkg/recipe" "github.com/go-git/go-git/v5" "github.com/urfave/cli" ) @@ -25,13 +23,13 @@ var recipeResetCommand = cli.Command{ BashComplete: autocomplete.RecipeNameComplete, Action: func(c *cli.Context) error { recipeName := c.Args().First() + r := recipe.Get(recipeName) if recipeName != "" { internal.ValidateRecipe(c) } - repoPath := path.Join(config.RECIPES_DIR, recipeName) - repo, err := git.PlainOpen(repoPath) + repo, err := git.PlainOpen(r.Dir) if err != nil { log.Fatal(err) } diff --git a/cli/recipe/sync.go b/cli/recipe/sync.go index 10710af8..f7432380 100644 --- a/cli/recipe/sync.go +++ b/cli/recipe/sync.go @@ -2,12 +2,10 @@ package recipe import ( "fmt" - "path" "strconv" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" - "coopcloud.tech/abra/pkg/config" gitPkg "coopcloud.tech/abra/pkg/git" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/tagcmp" @@ -107,8 +105,7 @@ likely to change. } if nextTag == "" { - recipeDir := path.Join(config.RECIPES_DIR, recipe.Name) - repo, err := git.PlainOpen(recipeDir) + repo, err := git.PlainOpen(recipe.Dir) if err != nil { log.Fatal(err) } diff --git a/cli/recipe/upgrade.go b/cli/recipe/upgrade.go index 0887bfbe..4defb186 100644 --- a/cli/recipe/upgrade.go +++ b/cli/recipe/upgrade.go @@ -12,7 +12,6 @@ import ( "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" - "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/formatter" gitPkg "coopcloud.tech/abra/pkg/git" "coopcloud.tech/abra/pkg/log" @@ -94,8 +93,7 @@ You may invoke this command in "wizard" mode and be prompted for input: // check for versions file and load pinned versions versionsPresent := false - recipeDir := path.Join(config.RECIPES_DIR, recipe.Name) - versionsPath := path.Join(recipeDir, "versions") + 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) @@ -332,13 +330,13 @@ You may invoke this command in "wizard" mode and be prompted for input: } } - isClean, err := gitPkg.IsClean(recipeDir) + isClean, err := gitPkg.IsClean(recipe.Dir) if err != nil { log.Fatal(err) } if !isClean { log.Infof("%s currently has these unstaged changes 👇", recipe.Name) - if err := gitPkg.DiffUnstaged(recipeDir); err != nil { + if err := gitPkg.DiffUnstaged(recipe.Dir); err != nil { log.Fatal(err) } } diff --git a/cli/updater/updater.go b/cli/updater/updater.go index 94086819..352ececc 100644 --- a/cli/updater/updater.go +++ b/cli/updater/updater.go @@ -10,7 +10,6 @@ import ( "coopcloud.tech/abra/cli/internal" appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/client" - "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/envfile" "coopcloud.tech/abra/pkg/lint" "coopcloud.tech/abra/pkg/recipe" @@ -339,9 +338,8 @@ func processRecipeRepoVersion(r recipe.Recipe, version string) error { } // mergeAbraShEnv merges abra.sh env vars into the app env vars. -func mergeAbraShEnv(recipeName string, env envfile.AppEnv) error { - abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, recipeName, "abra.sh") - abraShEnv, err := envfile.ReadAbraShEnvVars(abraShPath) +func mergeAbraShEnv(recipe recipe.Recipe, env envfile.AppEnv) error { + abraShEnv, err := envfile.ReadAbraShEnvVars(recipe.AbraShPath) if err != nil { return err } @@ -449,7 +447,7 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName, return err } - if err = mergeAbraShEnv(recipeName, app.Env); err != nil { + if err = mergeAbraShEnv(app.Recipe, app.Env); err != nil { return err } diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index 509b0702..a10cc753 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -60,26 +60,26 @@ func TestGetComposeFiles(t *testing.T) { { map[string]string{}, []string{ - fmt.Sprintf("%s/%s/compose.yml", config.RECIPES_DIR, r.Name), + fmt.Sprintf("%s/compose.yml", r.Dir), }, }, { map[string]string{"COMPOSE_FILE": "compose.yml"}, []string{ - fmt.Sprintf("%s/%s/compose.yml", config.RECIPES_DIR, r.Name), + fmt.Sprintf("%s/compose.yml", r.Dir), }, }, { map[string]string{"COMPOSE_FILE": "compose.extra_secret.yml"}, []string{ - fmt.Sprintf("%s/%s/compose.extra_secret.yml", config.RECIPES_DIR, r.Name), + fmt.Sprintf("%s/compose.extra_secret.yml", r.Dir), }, }, { map[string]string{"COMPOSE_FILE": "compose.yml:compose.extra_secret.yml"}, []string{ - fmt.Sprintf("%s/%s/compose.yml", config.RECIPES_DIR, r.Name), - fmt.Sprintf("%s/%s/compose.extra_secret.yml", config.RECIPES_DIR, r.Name), + fmt.Sprintf("%s/compose.yml", r.Dir), + fmt.Sprintf("%s/compose.extra_secret.yml", r.Dir), }, }, } diff --git a/pkg/envfile/envfile_test.go b/pkg/envfile/envfile_test.go index dca7a792..3c15555b 100644 --- a/pkg/envfile/envfile_test.go +++ b/pkg/envfile/envfile_test.go @@ -1,7 +1,6 @@ package envfile_test import ( - "fmt" "reflect" "slices" "strings" @@ -61,8 +60,7 @@ func TestReadAbraShEnvVars(t *testing.T) { t.Fatal(err) } - abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, r.Name, "abra.sh") - abraShEnv, err := envfile.ReadAbraShEnvVars(abraShPath) + abraShEnv, err := envfile.ReadAbraShEnvVars(r.AbraShPath) if err != nil { t.Fatal(err) } @@ -91,8 +89,7 @@ func TestReadAbraShCmdNames(t *testing.T) { t.Fatal(err) } - abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, r.Name, "abra.sh") - cmdNames, err := appPkg.ReadAbraShCmdNames(abraShPath) + cmdNames, err := appPkg.ReadAbraShCmdNames(r.AbraShPath) if err != nil { t.Fatal(err) } @@ -104,7 +101,7 @@ func TestReadAbraShCmdNames(t *testing.T) { expectedCmdNames := []string{"test_cmd", "test_cmd_args"} for _, cmdName := range expectedCmdNames { if !slices.Contains(cmdNames, cmdName) { - t.Fatalf("%s should have been found in %s", cmdName, abraShPath) + t.Fatalf("%s should have been found in %s", cmdName, r.AbraShPath) } } } diff --git a/pkg/lint/recipe.go b/pkg/lint/recipe.go index ae371e32..7c7c6ac9 100644 --- a/pkg/lint/recipe.go +++ b/pkg/lint/recipe.go @@ -460,11 +460,9 @@ func LintSecretLengths(recipe recipe.Recipe) (bool, error) { } func LintValidTags(recipe recipe.Recipe) (bool, error) { - recipeDir := path.Join(config.RECIPES_DIR, recipe.Name) - - repo, err := git.PlainOpen(recipeDir) + repo, err := git.PlainOpen(recipe.Dir) if err != nil { - return false, fmt.Errorf("unable to open %s: %s", recipeDir, err) + return false, fmt.Errorf("unable to open %s: %s", recipe.Dir, err) } iter, err := repo.Tags() diff --git a/pkg/recipe/files.go b/pkg/recipe/files.go index 88ab5e59..f092fff3 100644 --- a/pkg/recipe/files.go +++ b/pkg/recipe/files.go @@ -2,6 +2,8 @@ package recipe import ( "fmt" + "os" + "path" "coopcloud.tech/abra/pkg/envfile" ) @@ -13,3 +15,23 @@ func (r Recipe) SampleEnv() (map[string]string, error) { } return sampleEnv, nil } + +// GetReleaseNotes prints release notes for the recipe version +func (r Recipe) GetReleaseNotes(version string) (string, error) { + if version == "" { + return "", nil + } + + fpath := path.Join(r.Dir, "release", version) + + if _, err := os.Stat(fpath); !os.IsNotExist(err) { + releaseNotes, err := os.ReadFile(fpath) + if err != nil { + return "", err + } + withTitle := fmt.Sprintf("%s release notes:\n%s", version, string(releaseNotes)) + return withTitle, nil + } + + return "", nil +} diff --git a/pkg/recipe/recipe.go b/pkg/recipe/recipe.go index bbf63668..5a33dabc 100644 --- a/pkg/recipe/recipe.go +++ b/pkg/recipe/recipe.go @@ -132,6 +132,7 @@ func Get(name string) Recipe { ComposePath: path.Join(dir, "compose.yml"), ReadmePath: path.Join(dir, "README.md"), SampleEnvPath: path.Join(dir, ".env.sample"), + AbraShPath: path.Join(dir, "abra.sh"), } } @@ -143,6 +144,7 @@ type Recipe struct { ComposePath string ReadmePath string SampleEnvPath string + AbraShPath string } // GetRecipesLocal retrieves all local recipe directories @@ -581,8 +583,7 @@ func UpdateRepositories(repos RepoCatalogue, recipeName string) error { return } - recipeDir := path.Join(config.RECIPES_DIR, rm.Name) - if err := gitPkg.Clone(recipeDir, rm.CloneURL); err != nil { + if err := gitPkg.Clone(Get(rm.Name).Dir, rm.CloneURL); err != nil { log.Fatal(err) } From 41c16db67058c98c45085326a2502784d7906f84 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 8 Jul 2024 14:09:54 +0200 Subject: [PATCH 19/19] test: fix test failure --- pkg/recipe/recipe_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/recipe/recipe_test.go b/pkg/recipe/recipe_test.go index 37453c4d..f73d613b 100644 --- a/pkg/recipe/recipe_test.go +++ b/pkg/recipe/recipe_test.go @@ -15,6 +15,10 @@ func TestGetVersionLabelLocalDoesNotUseTimeoutLabel(t *testing.T) { } r := Get("traefik") + err = r.EnsureExists() + if err != nil { + t.Fatal(err) + } for i := 1; i < 1000; i++ { label, err := r.GetVersionLabelLocal()