forked from toolshed/abra
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			private-re
			...
			refactor-r
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 89e1046882 | |||
| cbab9b5907 | |||
| b688ddc4b1 | 
| @ -47,22 +47,26 @@ var appBackupListCommand = cli.Command{ | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipe.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipe.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -110,22 +114,26 @@ var appBackupDownloadCommand = cli.Command{ | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipe.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipe.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -180,22 +188,27 @@ var appBackupCreateCommand = cli.Command{ | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipe.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipe.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -238,22 +251,27 @@ var appBackupSnapshotsCommand = cli.Command{ | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipe.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipe.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -6,7 +6,6 @@ import ( | |||||||
| 	"coopcloud.tech/abra/pkg/config" | 	"coopcloud.tech/abra/pkg/config" | ||||||
| 	"coopcloud.tech/abra/pkg/formatter" | 	"coopcloud.tech/abra/pkg/formatter" | ||||||
| 	"coopcloud.tech/abra/pkg/recipe" | 	"coopcloud.tech/abra/pkg/recipe" | ||||||
| 	recipePkg "coopcloud.tech/abra/pkg/recipe" |  | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| 	"github.com/urfave/cli" | 	"github.com/urfave/cli" | ||||||
| ) | ) | ||||||
| @ -38,22 +37,26 @@ ${FOO:<default>} syntax). "check" does not confirm or deny this for you.`, | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipePkg.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipePkg.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -15,7 +15,6 @@ import ( | |||||||
| 	"coopcloud.tech/abra/pkg/client" | 	"coopcloud.tech/abra/pkg/client" | ||||||
| 	"coopcloud.tech/abra/pkg/config" | 	"coopcloud.tech/abra/pkg/config" | ||||||
| 	"coopcloud.tech/abra/pkg/recipe" | 	"coopcloud.tech/abra/pkg/recipe" | ||||||
| 	recipePkg "coopcloud.tech/abra/pkg/recipe" |  | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| 	"github.com/urfave/cli" | 	"github.com/urfave/cli" | ||||||
| ) | ) | ||||||
| @ -60,22 +59,27 @@ Example: | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipePkg.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipePkg.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -228,22 +232,27 @@ var appCmdListCommand = cli.Command{ | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipePkg.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipePkg.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -56,28 +56,32 @@ recipes. | |||||||
| 			logrus.Fatal("cannot use <version> and --chaos together") | 			logrus.Fatal("cannot use <version> and --chaos together") | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipe.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipe.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		r, err := recipe.Get(app.Recipe, internal.Offline) | 		if err := r.LoadConfig(); err != nil { | ||||||
| 		if err != nil { |  | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -105,7 +109,7 @@ recipes. | |||||||
| 		if specificVersion != "" { | 		if specificVersion != "" { | ||||||
| 			version = specificVersion | 			version = specificVersion | ||||||
| 			logrus.Debugf("choosing %s as version to deploy", version) | 			logrus.Debugf("choosing %s as version to deploy", version) | ||||||
| 			if err := recipe.EnsureVersion(app.Recipe, version); err != nil { | 			if err := r.EnsureVersion(version); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -141,7 +145,7 @@ recipes. | |||||||
|  |  | ||||||
| 			if len(versions) == 0 && !internal.Chaos { | 			if len(versions) == 0 && !internal.Chaos { | ||||||
| 				logrus.Warn("no published versions in catalogue, trying local recipe repository") | 				logrus.Warn("no published versions in catalogue, trying local recipe repository") | ||||||
| 				recipeVersions, err := recipe.GetRecipeVersions(app.Recipe, internal.Offline) | 				recipeVersions, err := r.GetVersions(internal.Offline) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					logrus.Warn(err) | 					logrus.Warn(err) | ||||||
| 				} | 				} | ||||||
| @ -155,11 +159,11 @@ recipes. | |||||||
| 			if len(versions) > 0 && !internal.Chaos { | 			if len(versions) > 0 && !internal.Chaos { | ||||||
| 				version = versions[len(versions)-1] | 				version = versions[len(versions)-1] | ||||||
| 				logrus.Debugf("choosing %s as version to deploy", version) | 				logrus.Debugf("choosing %s as version to deploy", version) | ||||||
| 				if err := recipe.EnsureVersion(app.Recipe, version); err != nil { | 				if err := r.EnsureVersion(version); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				head, err := git.GetRecipeHead(app.Recipe) | 				head, err := git.GetHead(app.Recipe) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| @ -171,7 +175,7 @@ recipes. | |||||||
| 		if internal.Chaos { | 		if internal.Chaos { | ||||||
| 			logrus.Warnf("chaos mode engaged") | 			logrus.Warnf("chaos mode engaged") | ||||||
| 			var err error | 			var err error | ||||||
| 			version, err = recipe.ChaosVersion(app.Recipe) | 			version, err = r.ChaosVersion() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -88,12 +88,15 @@ the logs. | |||||||
| } | } | ||||||
|  |  | ||||||
| func checkErrors(c *cli.Context, cl *dockerClient.Client, app config.App) error { | func checkErrors(c *cli.Context, cl *dockerClient.Client, app config.App) error { | ||||||
| 	recipe, err := recipe.Get(app.Recipe, internal.Offline) | 	r, err := recipe.Get(app.Recipe) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | 		logrus.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	if err := r.LoadConfig(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, service := range recipe.Config.Services { | 	for _, service := range r.Config.Services { | ||||||
| 		filters := filters.NewArgs() | 		filters := filters.NewArgs() | ||||||
| 		filters.Add("name", fmt.Sprintf("^%s_%s", app.StackName(), service.Name)) | 		filters.Add("name", fmt.Sprintf("^%s_%s", app.StackName(), service.Name)) | ||||||
|  |  | ||||||
|  | |||||||
| @ -39,7 +39,12 @@ var appLogsCommand = cli.Command{ | |||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
| 		stackName := app.StackName() | 		stackName := app.StackName() | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | |||||||
| @ -10,7 +10,6 @@ import ( | |||||||
| 	"coopcloud.tech/abra/pkg/config" | 	"coopcloud.tech/abra/pkg/config" | ||||||
| 	"coopcloud.tech/abra/pkg/formatter" | 	"coopcloud.tech/abra/pkg/formatter" | ||||||
| 	"coopcloud.tech/abra/pkg/jsontable" | 	"coopcloud.tech/abra/pkg/jsontable" | ||||||
| 	recipePkg "coopcloud.tech/abra/pkg/recipe" |  | ||||||
| 	"coopcloud.tech/abra/pkg/secret" | 	"coopcloud.tech/abra/pkg/secret" | ||||||
| 	"github.com/AlecAivazis/survey/v2" | 	"github.com/AlecAivazis/survey/v2" | ||||||
| 	dockerClient "github.com/docker/docker/client" | 	dockerClient "github.com/docker/docker/client" | ||||||
| @ -65,21 +64,21 @@ var appNewCommand = cli.Command{ | |||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		recipe := internal.ValidateRecipe(c) | 		r := internal.ValidateRecipe(c) | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipePkg.EnsureIsClean(recipe.Name); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			if c.Args().Get(1) == "" { | 			if c.Args().Get(1) == "" { | ||||||
| 				var version string | 				var version string | ||||||
|  |  | ||||||
| 				recipeVersions, err := recipePkg.GetRecipeVersions(recipe.Name, internal.Offline) | 				recipeVersions, err := r.GetVersions(internal.Offline) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| @ -92,16 +91,16 @@ var appNewCommand = cli.Command{ | |||||||
| 						version = tag | 						version = tag | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					if err := recipePkg.EnsureVersion(recipe.Name, version); err != nil { | 					if err := r.EnsureVersion(version); err != nil { | ||||||
| 						logrus.Fatal(err) | 						logrus.Fatal(err) | ||||||
| 					} | 					} | ||||||
| 				} else { | 				} else { | ||||||
| 					if err := recipePkg.EnsureLatest(recipe.Name); err != nil { | 					if err := r.EnsureLatest(); err != nil { | ||||||
| 						logrus.Fatal(err) | 						logrus.Fatal(err) | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				if err := recipePkg.EnsureVersion(recipe.Name, c.Args().Get(1)); err != nil { | 				if err := r.EnsureVersion(c.Args().Get(1)); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @ -111,7 +110,7 @@ var appNewCommand = cli.Command{ | |||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if err := ensureDomainFlag(recipe, internal.NewAppServer); err != nil { | 		if err := ensureDomainFlag(r.Name, internal.NewAppServer); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -119,7 +118,7 @@ var appNewCommand = cli.Command{ | |||||||
| 		logrus.Debugf("%s sanitised as %s for new app", internal.Domain, sanitisedAppName) | 		logrus.Debugf("%s sanitised as %s for new app", internal.Domain, sanitisedAppName) | ||||||
|  |  | ||||||
| 		if err := config.TemplateAppEnvSample( | 		if err := config.TemplateAppEnvSample( | ||||||
| 			recipe.Name, | 			r.Name, | ||||||
| 			internal.Domain, | 			internal.Domain, | ||||||
| 			internal.NewAppServer, | 			internal.NewAppServer, | ||||||
| 			internal.Domain, | 			internal.Domain, | ||||||
| @ -130,23 +129,23 @@ var appNewCommand = cli.Command{ | |||||||
| 		var secrets AppSecrets | 		var secrets AppSecrets | ||||||
| 		var secretTable *jsontable.JSONTable | 		var secretTable *jsontable.JSONTable | ||||||
| 		if internal.Secrets { | 		if internal.Secrets { | ||||||
| 			sampleEnv, err := recipe.SampleEnv() | 			sampleEnv, err := r.SampleEnv() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			composeFiles, err := config.GetComposeFiles(recipe.Name, sampleEnv) | 			composeFiles, err := config.GetComposeFiles(r.NameEscaped, sampleEnv) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			envSamplePath := path.Join(config.RECIPES_DIR, recipe.Name, ".env.sample") | 			envSamplePath := path.Join(r.Dir, ".env.sample") | ||||||
| 			secretsConfig, err := secret.ReadSecretsConfig(envSamplePath, composeFiles, config.StackName(internal.Domain)) | 			secretsConfig, err := secret.ReadSecretsConfig(envSamplePath, composeFiles, config.StackName(internal.Domain)) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := promptForSecrets(recipe.Name, secretsConfig); err != nil { | 			if err := promptForSecrets(r.Name, secretsConfig); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| @ -173,9 +172,9 @@ var appNewCommand = cli.Command{ | |||||||
|  |  | ||||||
| 		tableCol := []string{"server", "recipe", "domain"} | 		tableCol := []string{"server", "recipe", "domain"} | ||||||
| 		table := formatter.CreateTable(tableCol) | 		table := formatter.CreateTable(tableCol) | ||||||
| 		table.Append([]string{internal.NewAppServer, recipe.Name, internal.Domain}) | 		table.Append([]string{internal.NewAppServer, r.Name, internal.Domain}) | ||||||
|  |  | ||||||
| 		fmt.Println(fmt.Sprintf("A new %s app has been created! Here is an overview:", recipe.Name)) | 		fmt.Println(fmt.Sprintf("A new %s app has been created! Here is an overview:", r.Name)) | ||||||
| 		fmt.Println("") | 		fmt.Println("") | ||||||
| 		table.Render() | 		table.Render() | ||||||
| 		fmt.Println("") | 		fmt.Println("") | ||||||
| @ -231,11 +230,11 @@ 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/ | // 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(recipeName string, server string) error { | ||||||
| 	if internal.Domain == "" && !internal.NoInput { | 	if internal.Domain == "" && !internal.NoInput { | ||||||
| 		prompt := &survey.Input{ | 		prompt := &survey.Input{ | ||||||
| 			Message: "Specify app domain", | 			Message: "Specify app domain", | ||||||
| 			Default: fmt.Sprintf("%s.%s", recipe.Name, server), | 			Default: fmt.Sprintf("%s.%s", recipeName, server), | ||||||
| 		} | 		} | ||||||
| 		if err := survey.AskOne(prompt, &internal.Domain); err != nil { | 		if err := survey.AskOne(prompt, &internal.Domain); err != nil { | ||||||
| 			return err | 			return err | ||||||
|  | |||||||
| @ -39,6 +39,11 @@ var appPsCommand = cli.Command{ | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
|  | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		cl, err := client.New(app.Server) | 		cl, err := client.New(app.Server) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| @ -56,7 +61,7 @@ var appPsCommand = cli.Command{ | |||||||
| 		statuses, err := config.GetAppStatuses([]config.App{app}, true) | 		statuses, err := config.GetAppStatuses([]config.App{app}, true) | ||||||
| 		if statusMeta, ok := statuses[app.StackName()]; ok { | 		if statusMeta, ok := statuses[app.StackName()]; ok { | ||||||
| 			if _, exists := statusMeta["chaos"]; !exists { | 			if _, exists := statusMeta["chaos"]; !exists { | ||||||
| 				if err := recipe.EnsureVersion(app.Recipe, deployedVersion); err != nil { | 				if err := r.EnsureVersion(deployedVersion); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -33,22 +33,27 @@ var appRestoreCommand = cli.Command{ | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipe.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipe.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -51,33 +51,37 @@ recipes. | |||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
| 		stackName := app.StackName() | 		stackName := app.StackName() | ||||||
|  |  | ||||||
|  | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		specificVersion := c.Args().Get(1) | 		specificVersion := c.Args().Get(1) | ||||||
| 		if specificVersion != "" && internal.Chaos { | 		if specificVersion != "" && internal.Chaos { | ||||||
| 			logrus.Fatal("cannot use <version> and --chaos together") | 			logrus.Fatal("cannot use <version> and --chaos together") | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipe.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipe.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		r, err := recipe.Get(app.Recipe, internal.Offline) | 		if err := r.LoadConfig(); err != nil { | ||||||
| 		if err != nil { |  | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -113,7 +117,7 @@ recipes. | |||||||
|  |  | ||||||
| 		if len(versions) == 0 && !internal.Chaos { | 		if len(versions) == 0 && !internal.Chaos { | ||||||
| 			logrus.Warn("no published versions in catalogue, trying local recipe repository") | 			logrus.Warn("no published versions in catalogue, trying local recipe repository") | ||||||
| 			recipeVersions, err := recipe.GetRecipeVersions(app.Recipe, internal.Offline) | 			recipeVersions, err := r.GetVersions(internal.Offline) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logrus.Warn(err) | 				logrus.Warn(err) | ||||||
| 			} | 			} | ||||||
| @ -183,7 +187,7 @@ recipes. | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipe.EnsureVersion(app.Recipe, chosenDowngrade); err != nil { | 			if err := r.EnsureVersion(chosenDowngrade); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -191,13 +195,13 @@ recipes. | |||||||
| 		if internal.Chaos { | 		if internal.Chaos { | ||||||
| 			logrus.Warn("chaos mode engaged") | 			logrus.Warn("chaos mode engaged") | ||||||
| 			var err error | 			var err error | ||||||
| 			chosenDowngrade, err = recipe.ChaosVersion(app.Recipe) | 			chosenDowngrade, err = r.ChaosVersion() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, app.Recipe, "abra.sh") | 		abraShPath := fmt.Sprintf("%s/%s/%s", r.Dir, "abra.sh") | ||||||
| 		abraShEnv, err := config.ReadAbraShEnvVars(abraShPath) | 		abraShEnv, err := config.ReadAbraShEnvVars(abraShPath) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
|  | |||||||
| @ -57,22 +57,27 @@ var appSecretGenerateCommand = cli.Command{ | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipe.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipe.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -264,22 +269,27 @@ Example: | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipe.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipe.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -372,22 +382,27 @@ var appSecretLsCommand = cli.Command{ | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
|  |  | ||||||
| 		if err := recipe.EnsureExists(app.Recipe); err != nil { | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipe.EnsureIsClean(app.Recipe); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipe.EnsureLatest(app.Recipe); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -62,28 +62,32 @@ recipes. | |||||||
| 			logrus.Fatal("cannot use <version> and --chaos together") | 			logrus.Fatal("cannot use <version> and --chaos together") | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		r, err := recipe.Get(app.Recipe) | ||||||
| 			if err := recipe.EnsureIsClean(app.Recipe); err != nil { |  | ||||||
| 				logrus.Fatal(err) |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			if !internal.Offline { |  | ||||||
| 				if err := recipe.EnsureUpToDate(app.Recipe); err != nil { |  | ||||||
| 					logrus.Fatal(err) |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			if err := recipe.EnsureLatest(app.Recipe); err != nil { |  | ||||||
| 				logrus.Fatal(err) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		recipe, err := recipePkg.Get(app.Recipe, internal.Offline) |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if err := lint.LintForErrors(recipe); err != nil { | 		if !internal.Chaos { | ||||||
|  | 			if err := r.EnsureIsClean(); err != nil { | ||||||
|  | 				logrus.Fatal(err) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if !internal.Offline { | ||||||
|  | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
|  | 					logrus.Fatal(err) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if err := r.EnsureLatest(); err != nil { | ||||||
|  | 				logrus.Fatal(err) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := r.LoadConfig(); err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := lint.LintForErrors(r); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -115,7 +119,7 @@ recipes. | |||||||
|  |  | ||||||
| 		if len(versions) == 0 && !internal.Chaos { | 		if len(versions) == 0 && !internal.Chaos { | ||||||
| 			logrus.Warn("no published versions in catalogue, trying local recipe repository") | 			logrus.Warn("no published versions in catalogue, trying local recipe repository") | ||||||
| 			recipeVersions, err := recipePkg.GetRecipeVersions(app.Recipe, internal.Offline) | 			recipeVersions, err := r.GetVersions(internal.Offline) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logrus.Warn(err) | 				logrus.Warn(err) | ||||||
| 			} | 			} | ||||||
| @ -217,7 +221,7 @@ recipes. | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipePkg.EnsureVersion(app.Recipe, chosenUpgrade); err != nil { | 			if err := r.EnsureVersion(chosenUpgrade); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -225,13 +229,13 @@ recipes. | |||||||
| 		if internal.Chaos { | 		if internal.Chaos { | ||||||
| 			logrus.Warn("chaos mode engaged") | 			logrus.Warn("chaos mode engaged") | ||||||
| 			var err error | 			var err error | ||||||
| 			chosenUpgrade, err = recipePkg.ChaosVersion(app.Recipe) | 			chosenUpgrade, err = r.ChaosVersion() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, app.Recipe, "abra.sh") | 		abraShPath := fmt.Sprintf("%s/%s/%s", r.Dir, "abra.sh") | ||||||
| 		abraShEnv, err := config.ReadAbraShEnvVars(abraShPath) | 		abraShEnv, err := config.ReadAbraShEnvVars(abraShPath) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
|  | |||||||
| @ -58,6 +58,11 @@ var appVersionCommand = cli.Command{ | |||||||
| 		app := internal.ValidateApp(c) | 		app := internal.ValidateApp(c) | ||||||
| 		stackName := app.StackName() | 		stackName := app.StackName() | ||||||
|  |  | ||||||
|  | 		r, err := recipe.Get(app.Recipe) | ||||||
|  | 		if err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		cl, err := client.New(app.Server) | 		cl, err := client.New(app.Server) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| @ -78,7 +83,7 @@ var appVersionCommand = cli.Command{ | |||||||
| 			logrus.Fatalf("failed to determine version of deployed %s", app.Name) | 			logrus.Fatalf("failed to determine version of deployed %s", app.Name) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		recipeMeta, err := recipe.GetRecipeMeta(app.Recipe, internal.Offline) | 		recipeMeta, err := r.GetRecipeMeta(internal.Offline) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ import ( | |||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
|  | 	"os" | ||||||
| 	"path" | 	"path" | ||||||
|  |  | ||||||
| 	"coopcloud.tech/abra/cli/internal" | 	"coopcloud.tech/abra/cli/internal" | ||||||
| @ -57,9 +58,10 @@ keys configured on your account. | |||||||
| 	BashComplete: autocomplete.RecipeNameComplete, | 	BashComplete: autocomplete.RecipeNameComplete, | ||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		recipeName := c.Args().First() | 		recipeName := c.Args().First() | ||||||
|  | 		r := recipe.Recipe{} | ||||||
|  |  | ||||||
| 		if recipeName != "" { | 		if recipeName != "" { | ||||||
| 			internal.ValidateRecipe(c) | 			r = internal.ValidateRecipe(c) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| @ -98,12 +100,12 @@ keys configured on your account. | |||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			versions, err := recipe.GetRecipeVersions(recipeMeta.Name, internal.Offline) | 			versions, err := r.GetVersions(internal.Offline) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logrus.Warn(err) | 				logrus.Warn(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			features, category, err := recipe.GetRecipeFeaturesAndCategory(recipeMeta.Name) | 			features, category, err := r.GetRecipeFeaturesAndCategory() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logrus.Warn(err) | 				logrus.Warn(err) | ||||||
| 			} | 			} | ||||||
| @ -130,7 +132,7 @@ keys configured on your account. | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if recipeName == "" { | 		if recipeName == "" { | ||||||
| 			if err := ioutil.WriteFile(config.RECIPES_JSON, recipesJSON, 0764); err != nil { | 			if err := os.WriteFile(config.RECIPES_JSON, recipesJSON, 0764); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
|  | |||||||
| @ -57,7 +57,10 @@ func ValidateRecipe(c *cli.Context) recipe.Recipe { | |||||||
| 		ShowSubcommandHelpAndError(c, errors.New("no recipe name provided")) | 		ShowSubcommandHelpAndError(c, errors.New("no recipe name provided")) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	chosenRecipe, err := recipe.Get(recipeName, Offline) | 	r, err := recipe.Get(recipeName) | ||||||
|  | 	if err != nil { | ||||||
|  | 		logrus.Fatal(err) | ||||||
|  | 	} | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if c.Command.Name == "generate" { | 		if c.Command.Name == "generate" { | ||||||
| 			if strings.Contains(err.Error(), "missing a compose") { | 			if strings.Contains(err.Error(), "missing a compose") { | ||||||
| @ -74,7 +77,7 @@ func ValidateRecipe(c *cli.Context) recipe.Recipe { | |||||||
|  |  | ||||||
| 	logrus.Debugf("validated %s as recipe argument", recipeName) | 	logrus.Debugf("validated %s as recipe argument", recipeName) | ||||||
|  |  | ||||||
| 	return chosenRecipe | 	return r | ||||||
| } | } | ||||||
|  |  | ||||||
| // ValidateApp ensures the app name arg is valid. | // ValidateApp ensures the app name arg is valid. | ||||||
|  | |||||||
| @ -24,9 +24,14 @@ var recipeFetchCommand = cli.Command{ | |||||||
| 	BashComplete: autocomplete.RecipeNameComplete, | 	BashComplete: autocomplete.RecipeNameComplete, | ||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		recipeName := c.Args().First() | 		recipeName := c.Args().First() | ||||||
|  |  | ||||||
| 		if recipeName != "" { | 		if recipeName != "" { | ||||||
| 			internal.ValidateRecipe(c) | 			internal.ValidateRecipe(c) | ||||||
| 			if err := recipe.Ensure(recipeName); err != nil { | 			r, err := recipe.Get(recipeName) | ||||||
|  | 			if err != nil { | ||||||
|  | 				logrus.Fatal(err) | ||||||
|  | 			} | ||||||
|  | 			if err := r.Ensure(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 			return nil | 			return nil | ||||||
| @ -39,7 +44,11 @@ var recipeFetchCommand = cli.Command{ | |||||||
|  |  | ||||||
| 		catlBar := formatter.CreateProgressbar(len(catalogue), "fetching latest recipes...") | 		catlBar := formatter.CreateProgressbar(len(catalogue), "fetching latest recipes...") | ||||||
| 		for recipeName := range catalogue { | 		for recipeName := range catalogue { | ||||||
| 			if err := recipe.Ensure(recipeName); err != nil { | 			r, err := recipe.Get(recipeName) | ||||||
|  | 			if err != nil { | ||||||
|  | 				logrus.Fatal(err) | ||||||
|  | 			} | ||||||
|  | 			if err := r.Ensure(); err != nil { | ||||||
| 				logrus.Error(err) | 				logrus.Error(err) | ||||||
| 			} | 			} | ||||||
| 			catlBar.Add(1) | 			catlBar.Add(1) | ||||||
|  | |||||||
| @ -7,7 +7,6 @@ import ( | |||||||
| 	"coopcloud.tech/abra/pkg/autocomplete" | 	"coopcloud.tech/abra/pkg/autocomplete" | ||||||
| 	"coopcloud.tech/abra/pkg/formatter" | 	"coopcloud.tech/abra/pkg/formatter" | ||||||
| 	"coopcloud.tech/abra/pkg/lint" | 	"coopcloud.tech/abra/pkg/lint" | ||||||
| 	recipePkg "coopcloud.tech/abra/pkg/recipe" |  | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| 	"github.com/urfave/cli" | 	"github.com/urfave/cli" | ||||||
| ) | ) | ||||||
| @ -27,24 +26,27 @@ var recipeLintCommand = cli.Command{ | |||||||
| 	Before:       internal.SubCommandBefore, | 	Before:       internal.SubCommandBefore, | ||||||
| 	BashComplete: autocomplete.RecipeNameComplete, | 	BashComplete: autocomplete.RecipeNameComplete, | ||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		recipe := internal.ValidateRecipe(c) | 		r := internal.ValidateRecipe(c) | ||||||
|  | 		if err := r.LoadConfig(); err != nil { | ||||||
|  | 			logrus.Fatal(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if err := recipePkg.EnsureExists(recipe.Name); err != nil { | 		if err := r.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !internal.Chaos { | 		if !internal.Chaos { | ||||||
| 			if err := recipePkg.EnsureIsClean(recipe.Name); err != nil { | 			if err := r.EnsureIsClean(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if !internal.Offline { | 			if !internal.Offline { | ||||||
| 				if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil { | 				if err := r.EnsureUpToDate(); err != nil { | ||||||
| 					logrus.Fatal(err) | 					logrus.Fatal(err) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err := recipePkg.EnsureLatest(recipe.Name); err != nil { | 			if err := r.EnsureLatest(); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -62,7 +64,7 @@ var recipeLintCommand = cli.Command{ | |||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				skipped := false | 				skipped := false | ||||||
| 				if rule.Skip(recipe) { | 				if rule.Skip(r) { | ||||||
| 					skipped = true | 					skipped = true | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| @ -73,7 +75,7 @@ var recipeLintCommand = cli.Command{ | |||||||
|  |  | ||||||
| 				satisfied := false | 				satisfied := false | ||||||
| 				if !skipped { | 				if !skipped { | ||||||
| 					ok, err := rule.Function(recipe) | 					ok, err := rule.Function(r) | ||||||
| 					if err != nil { | 					if err != nil { | ||||||
| 						logrus.Warn(err) | 						logrus.Warn(err) | ||||||
| 					} | 					} | ||||||
|  | |||||||
| @ -108,14 +108,14 @@ your SSH keys configured on your account. | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		isClean, err := gitPkg.IsClean(recipe.Dir()) | 		isClean, err := gitPkg.IsClean(recipe.Dir) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !isClean { | 		if !isClean { | ||||||
| 			logrus.Infof("%s currently has these unstaged changes 👇", recipe.Name) | 			logrus.Infof("%s currently has these unstaged changes 👇", recipe.Name) | ||||||
| 			if err := gitPkg.DiffUnstaged(recipe.Dir()); err != nil { | 			if err := gitPkg.DiffUnstaged(recipe.Dir); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -184,7 +184,7 @@ func getImageVersions(recipe recipe.Recipe) (map[string]string, error) { | |||||||
| func createReleaseFromTag(recipe recipe.Recipe, tagString, mainAppVersion string) error { | func createReleaseFromTag(recipe recipe.Recipe, tagString, mainAppVersion string) error { | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	directory := path.Join(config.RECIPES_DIR, recipe.Name) | 	directory := path.Join(recipe.Dir) | ||||||
| 	repo, err := git.PlainOpen(directory) | 	repo, err := git.PlainOpen(directory) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| @ -246,8 +246,7 @@ func getTagCreateOptions(tag string) (git.CreateTagOptions, error) { | |||||||
| // addReleaseNotes checks if the release/next release note exists and moves the | // addReleaseNotes checks if the release/next release note exists and moves the | ||||||
| // file to release/<tag>. | // file to release/<tag>. | ||||||
| func addReleaseNotes(recipe recipe.Recipe, tag string) error { | func addReleaseNotes(recipe recipe.Recipe, tag string) error { | ||||||
| 	repoPath := path.Join(config.RECIPES_DIR, recipe.Name) | 	tagReleaseNotePath := path.Join(recipe.Dir, "release", tag) | ||||||
| 	tagReleaseNotePath := path.Join(repoPath, "release", tag) |  | ||||||
| 	if _, err := os.Stat(tagReleaseNotePath); err == nil { | 	if _, err := os.Stat(tagReleaseNotePath); err == nil { | ||||||
| 		// Release note for current tag already exist exists. | 		// Release note for current tag already exist exists. | ||||||
| 		return nil | 		return nil | ||||||
| @ -255,7 +254,7 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	nextReleaseNotePath := path.Join(repoPath, "release", "next") | 	nextReleaseNotePath := path.Join(recipe.Dir, "release", "next") | ||||||
| 	if _, err := os.Stat(nextReleaseNotePath); err == nil { | 	if _, err := os.Stat(nextReleaseNotePath); err == nil { | ||||||
| 		// release/next note exists. Move it to release/<tag> | 		// release/next note exists. Move it to release/<tag> | ||||||
| 		if internal.Dry { | 		if internal.Dry { | ||||||
| @ -278,11 +277,11 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error { | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			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 { | 		if err != nil { | ||||||
| 			return err | 			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 { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| @ -311,7 +310,7 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		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 { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @ -325,14 +324,14 @@ func commitRelease(recipe recipe.Recipe, tag string) error { | |||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	isClean, err := gitPkg.IsClean(recipe.Dir()) | 	isClean, err := gitPkg.IsClean(recipe.Dir) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if isClean { | 	if isClean { | ||||||
| 		if !internal.Dry { | 		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) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -402,8 +401,7 @@ func pushRelease(recipe recipe.Recipe, tagString string) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recipe.Recipe, 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(recipe.Dir) | ||||||
| 	repo, err := git.PlainOpen(directory) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -199,13 +199,13 @@ likely to change. | |||||||
| 			logrus.Infof("dry run: not syncing label %s for recipe %s", nextTag, recipe.Name) | 			logrus.Infof("dry run: not syncing label %s for recipe %s", nextTag, recipe.Name) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		isClean, err := gitPkg.IsClean(recipe.Dir()) | 		isClean, err := gitPkg.IsClean(recipe.Dir) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
| 		if !isClean { | 		if !isClean { | ||||||
| 			logrus.Infof("%s currently has these unstaged changes 👇", recipe.Name) | 			logrus.Infof("%s currently has these unstaged changes 👇", recipe.Name) | ||||||
| 			if err := gitPkg.DiffUnstaged(recipe.Dir()); err != nil { | 			if err := gitPkg.DiffUnstaged(recipe.Dir); err != nil { | ||||||
| 				logrus.Fatal(err) | 				logrus.Fatal(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -73,19 +73,19 @@ You may invoke this command in "wizard" mode and be prompted for input: | |||||||
| 	Action: func(c *cli.Context) error { | 	Action: func(c *cli.Context) error { | ||||||
| 		recipe := internal.ValidateRecipe(c) | 		recipe := internal.ValidateRecipe(c) | ||||||
|  |  | ||||||
| 		if err := recipePkg.EnsureIsClean(recipe.Name); err != nil { | 		if err := recipe.EnsureIsClean(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if err := recipePkg.EnsureExists(recipe.Name); err != nil { | 		if err := recipe.EnsureExists(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil { | 		if err := recipe.EnsureUpToDate(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if err := recipePkg.EnsureLatest(recipe.Name); err != nil { | 		if err := recipe.EnsureLatest(); err != nil { | ||||||
| 			logrus.Fatal(err) | 			logrus.Fatal(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | |||||||
| @ -316,22 +316,23 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName | |||||||
|  |  | ||||||
| // processRecipeRepoVersion clones, pulls, checks out the version and lints the | // processRecipeRepoVersion clones, pulls, checks out the version and lints the | ||||||
| // recipe repository. | // recipe repository. | ||||||
| func processRecipeRepoVersion(recipeName, version string) error { | func processRecipeRepoVersion(recipe recipe.Recipe, version string) error { | ||||||
| 	if err := recipe.EnsureExists(recipeName); err != nil { | 	if err := recipe.EnsureExists(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := recipe.EnsureUpToDate(recipeName); err != nil { | 	if err := recipe.EnsureUpToDate(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := recipe.EnsureVersion(recipeName, version); err != nil { | 	if err := recipe.EnsureVersion(version); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if r, err := recipe.Get(recipeName, internal.Offline); err != nil { | 	if err := recipe.LoadConfig(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} else if err := lint.LintForErrors(r); err != nil { | 	} | ||||||
|  | 	if err := lint.LintForErrors(recipe); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -442,7 +443,12 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName, | |||||||
| 		Env:    env, | 		Env:    env, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err = processRecipeRepoVersion(recipeName, upgradeVersion); err != nil { | 	recipe, err := recipe.Get(recipeName) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err = processRecipeRepoVersion(recipe, upgradeVersion); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | |||||||
| @ -45,7 +45,7 @@ func TestGetApp(t *testing.T) { | |||||||
|  |  | ||||||
| func TestGetComposeFiles(t *testing.T) { | func TestGetComposeFiles(t *testing.T) { | ||||||
| 	offline := true | 	offline := true | ||||||
| 	r, err := recipe.Get("abra-test-recipe", offline) | 	r, err := recipe.Get2("abra-test-recipe", offline) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| @ -92,7 +92,7 @@ func TestGetComposeFiles(t *testing.T) { | |||||||
|  |  | ||||||
| func TestGetComposeFilesError(t *testing.T) { | func TestGetComposeFilesError(t *testing.T) { | ||||||
| 	offline := true | 	offline := true | ||||||
| 	r, err := recipe.Get("abra-test-recipe", offline) | 	r, err := recipe.Get2("abra-test-recipe", offline) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -94,7 +94,7 @@ func TestReadEnv(t *testing.T) { | |||||||
|  |  | ||||||
| func TestReadAbraShEnvVars(t *testing.T) { | func TestReadAbraShEnvVars(t *testing.T) { | ||||||
| 	offline := true | 	offline := true | ||||||
| 	r, err := recipe.Get("abra-test-recipe", offline) | 	r, err := recipe.Get2("abra-test-recipe", offline) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| @ -124,7 +124,7 @@ func TestReadAbraShEnvVars(t *testing.T) { | |||||||
|  |  | ||||||
| func TestReadAbraShCmdNames(t *testing.T) { | func TestReadAbraShCmdNames(t *testing.T) { | ||||||
| 	offline := true | 	offline := true | ||||||
| 	r, err := recipe.Get("abra-test-recipe", offline) | 	r, err := recipe.Get2("abra-test-recipe", offline) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| @ -149,7 +149,7 @@ func TestReadAbraShCmdNames(t *testing.T) { | |||||||
|  |  | ||||||
| func TestCheckEnv(t *testing.T) { | func TestCheckEnv(t *testing.T) { | ||||||
| 	offline := true | 	offline := true | ||||||
| 	r, err := recipe.Get("abra-test-recipe", offline) | 	r, err := recipe.Get2("abra-test-recipe", offline) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| @ -183,7 +183,7 @@ func TestCheckEnv(t *testing.T) { | |||||||
|  |  | ||||||
| func TestCheckEnvError(t *testing.T) { | func TestCheckEnvError(t *testing.T) { | ||||||
| 	offline := true | 	offline := true | ||||||
| 	r, err := recipe.Get("abra-test-recipe", offline) | 	r, err := recipe.Get2("abra-test-recipe", offline) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| @ -219,7 +219,7 @@ func TestCheckEnvError(t *testing.T) { | |||||||
|  |  | ||||||
| func TestEnvVarCommentsRemoved(t *testing.T) { | func TestEnvVarCommentsRemoved(t *testing.T) { | ||||||
| 	offline := true | 	offline := true | ||||||
| 	r, err := recipe.Get("abra-test-recipe", offline) | 	r, err := recipe.Get2("abra-test-recipe", offline) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| @ -251,7 +251,7 @@ func TestEnvVarCommentsRemoved(t *testing.T) { | |||||||
|  |  | ||||||
| func TestEnvVarModifiersIncluded(t *testing.T) { | func TestEnvVarModifiersIncluded(t *testing.T) { | ||||||
| 	offline := true | 	offline := true | ||||||
| 	r, err := recipe.Get("abra-test-recipe", offline) | 	r, err := recipe.Get2("abra-test-recipe", offline) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -4,11 +4,9 @@ import ( | |||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/user" | 	"os/user" | ||||||
| 	"path" |  | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"coopcloud.tech/abra/pkg/config" |  | ||||||
| 	"github.com/go-git/go-git/v5" | 	"github.com/go-git/go-git/v5" | ||||||
| 	gitConfigPkg "github.com/go-git/go-git/v5/config" | 	gitConfigPkg "github.com/go-git/go-git/v5/config" | ||||||
| 	"github.com/go-git/go-git/v5/plumbing" | 	"github.com/go-git/go-git/v5/plumbing" | ||||||
| @ -16,11 +14,9 @@ import ( | |||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // GetRecipeHead retrieves latest HEAD metadata. | // GetHead retrieves latest HEAD metadata. | ||||||
| func GetRecipeHead(recipeName string) (*plumbing.Reference, error) { | func GetHead(dir string) (*plumbing.Reference, error) { | ||||||
| 	recipeDir := path.Join(config.RECIPES_DIR, recipeName) | 	repo, err := git.PlainOpen(dir) | ||||||
|  |  | ||||||
| 	repo, err := git.PlainOpen(recipeDir) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -210,7 +210,7 @@ func LintComposeVersion(recipe recipe.Recipe) (bool, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func LintEnvConfigPresent(recipe recipe.Recipe) (bool, error) { | func LintEnvConfigPresent(recipe recipe.Recipe) (bool, error) { | ||||||
| 	envSample := fmt.Sprintf("%s/%s/.env.sample", config.RECIPES_DIR, recipe.Name) | 	envSample := fmt.Sprintf("%s/%s/.env.sample", recipe.Dir) | ||||||
| 	if _, err := os.Stat(envSample); !os.IsNotExist(err) { | 	if _, err := os.Stat(envSample); !os.IsNotExist(err) { | ||||||
| 		return true, nil | 		return true, nil | ||||||
| 	} | 	} | ||||||
| @ -233,7 +233,7 @@ func LintAppService(recipe recipe.Recipe) (bool, error) { | |||||||
| // the recipe. This typically means that no domain is required to deploy and | // the recipe. This typically means that no domain is required to deploy and | ||||||
| // therefore no matching traefik deploy label will be present. | // therefore no matching traefik deploy label will be present. | ||||||
| func LintTraefikEnabledSkipCondition(recipe recipe.Recipe) (bool, error) { | func LintTraefikEnabledSkipCondition(recipe recipe.Recipe) (bool, error) { | ||||||
| 	envSamplePath := path.Join(config.RECIPES_DIR, recipe.Name, ".env.sample") | 	envSamplePath := path.Join(recipe.Dir, ".env.sample") | ||||||
| 	sampleEnv, err := config.ReadEnv(envSamplePath) | 	sampleEnv, err := config.ReadEnv(envSamplePath) | ||||||
| 	if err != nil { | 	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", recipe.Name) | ||||||
| @ -358,7 +358,7 @@ func LintHasPublishedVersion(recipe recipe.Recipe) (bool, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func LintMetadataFilledIn(r recipe.Recipe) (bool, error) { | func LintMetadataFilledIn(r recipe.Recipe) (bool, error) { | ||||||
| 	features, category, err := recipe.GetRecipeFeaturesAndCategory(r.Name) | 	features, category, err := r.GetRecipeFeaturesAndCategory() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return false, err | 		return false, err | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ package recipe | |||||||
| import ( | import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"net/url" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path" | 	"path" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| @ -130,17 +130,10 @@ type Features struct { | |||||||
| 	SSO         string `json:"sso"` | 	SSO         string `json:"sso"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // Recipe represents a recipe. |  | ||||||
| type Recipe struct { |  | ||||||
| 	Name   string |  | ||||||
| 	Config *composetypes.Config |  | ||||||
| 	Meta   RecipeMeta |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Push pushes the latest changes to a SSH URL remote. You need to have your | // 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 | // local SSH configuration for git.coopcloud.tech working for this to work | ||||||
| func (r Recipe) Push(dryRun bool) error { | func (r Recipe) Push(dryRun bool) error { | ||||||
| 	repo, err := git.PlainOpen(r.Dir()) | 	repo, err := git.PlainOpen(r.Dir) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @ -149,21 +142,16 @@ func (r Recipe) Push(dryRun bool) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := gitPkg.Push(r.Dir(), "origin-ssh", true, dryRun); err != nil { | 	if err := gitPkg.Push(r.Dir, "origin-ssh", true, dryRun); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // Dir retrieves the recipe repository path |  | ||||||
| func (r Recipe) Dir() string { |  | ||||||
| 	return path.Join(config.RECIPES_DIR, r.Name) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // UpdateLabel updates a recipe label | // UpdateLabel updates a recipe label | ||||||
| func (r Recipe) UpdateLabel(pattern, serviceName, label string) error { | func (r Recipe) UpdateLabel(pattern, serviceName, label string) error { | ||||||
| 	fullPattern := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, r.Name, pattern) | 	fullPattern := fmt.Sprintf("%s/%s", r.Dir, pattern) | ||||||
| 	if err := compose.UpdateLabel(fullPattern, serviceName, label, r.Name); err != nil { | 	if err := compose.UpdateLabel(fullPattern, serviceName, label, r.Name); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @ -172,7 +160,7 @@ func (r Recipe) UpdateLabel(pattern, serviceName, label string) error { | |||||||
|  |  | ||||||
| // UpdateTag updates a recipe tag | // UpdateTag updates a recipe tag | ||||||
| func (r Recipe) UpdateTag(image, tag string) (bool, error) { | func (r Recipe) UpdateTag(image, tag string) (bool, error) { | ||||||
| 	pattern := fmt.Sprintf("%s/%s/compose**yml", config.RECIPES_DIR, r.Name) | 	pattern := fmt.Sprintf("%s/compose**yml", r.Dir) | ||||||
|  |  | ||||||
| 	image = formatter.StripTagMeta(image) | 	image = formatter.StripTagMeta(image) | ||||||
|  |  | ||||||
| @ -188,7 +176,7 @@ func (r Recipe) UpdateTag(image, tag string) (bool, error) { | |||||||
| func (r Recipe) Tags() ([]string, error) { | func (r Recipe) Tags() ([]string, error) { | ||||||
| 	var tags []string | 	var tags []string | ||||||
|  |  | ||||||
| 	repo, err := git.PlainOpen(r.Dir()) | 	repo, err := git.PlainOpen(r.Dir) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return tags, err | 		return tags, err | ||||||
| 	} | 	} | ||||||
| @ -210,49 +198,51 @@ func (r Recipe) Tags() ([]string, error) { | |||||||
| 	return tags, nil | 	return tags, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // Get retrieves a recipe. | // // Get2 retrieves a recipe. | ||||||
| func Get(recipeName string, offline bool) (Recipe, error) { | // func (r Recipe) Load(offline bool) (Recipe2, error) { | ||||||
| 	if err := EnsureExists(recipeName); err != nil { | // | ||||||
| 		return Recipe{}, err | // 	meta, err := r.GetRecipeMeta(offline) | ||||||
|  | // 	if err != nil { | ||||||
|  | // 		switch err.(type) { | ||||||
|  | // 		case RecipeMissingFromCatalogue: | ||||||
|  | // 			meta = RecipeMeta{} | ||||||
|  | // 		default: | ||||||
|  | // 			return Recipe2{}, err | ||||||
|  | // 		} | ||||||
|  | // 	} | ||||||
|  | // | ||||||
|  | // 	return Recipe2{ | ||||||
|  | // 		Name:   r.Name, | ||||||
|  | // 		Config: config, | ||||||
|  | // 		Meta:   meta, | ||||||
|  | // 	}, nil | ||||||
|  | // } | ||||||
|  |  | ||||||
|  | func (r Recipe) LoadConfig() error { | ||||||
|  | 	if err := r.EnsureExists(); err != nil { | ||||||
|  | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	pattern := fmt.Sprintf("%s/%s/compose**yml", config.RECIPES_DIR, recipeName) | 	pattern := fmt.Sprintf("%s/compose**yml", r.Dir) | ||||||
| 	composeFiles, err := filepath.Glob(pattern) | 	composeFiles, err := filepath.Glob(pattern) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return Recipe{}, err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(composeFiles) == 0 { | 	if len(composeFiles) == 0 { | ||||||
| 		return Recipe{}, fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", recipeName) | 		return fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", r.Name) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	envSamplePath := path.Join(config.RECIPES_DIR, recipeName, ".env.sample") |  | ||||||
| 	sampleEnv, err := config.ReadEnv(envSamplePath) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return Recipe{}, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	opts := stack.Deploy{Composefiles: composeFiles} | 	opts := stack.Deploy{Composefiles: composeFiles} | ||||||
|  | 	sampleEnv, err := r.SampleEnv() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
| 	config, err := loader.LoadComposefile(opts, sampleEnv) | 	config, err := loader.LoadComposefile(opts, sampleEnv) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return Recipe{}, err | 		return err | ||||||
| 	} | 	} | ||||||
|  | 	r.Config = config | ||||||
| 	meta, err := GetRecipeMeta(recipeName, offline) | 	return nil | ||||||
| 	if err != nil { |  | ||||||
| 		switch err.(type) { |  | ||||||
| 		case RecipeMissingFromCatalogue: |  | ||||||
| 			meta = RecipeMeta{} |  | ||||||
| 		default: |  | ||||||
| 			return Recipe{}, err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return Recipe{ |  | ||||||
| 		Name:   recipeName, |  | ||||||
| 		Config: config, |  | ||||||
| 		Meta:   meta, |  | ||||||
| 	}, nil |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (r Recipe) SampleEnv() (map[string]string, error) { | func (r Recipe) SampleEnv() (map[string]string, error) { | ||||||
| @ -264,33 +254,71 @@ func (r Recipe) SampleEnv() (map[string]string, error) { | |||||||
| 	return sampleEnv, nil | 	return sampleEnv, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type Recipe struct { | ||||||
|  | 	Name        string | ||||||
|  | 	NameEscaped string | ||||||
|  | 	Dir         string | ||||||
|  | 	GitURL      string | ||||||
|  |  | ||||||
|  | 	Config *composetypes.Config | ||||||
|  | 	Meta   RecipeMeta | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Get(recipeName string) (Recipe, error) { | ||||||
|  | 	if !strings.Contains(recipeName, "/") { | ||||||
|  | 		return Recipe{ | ||||||
|  | 			Name:   recipeName, | ||||||
|  | 			GitURL: fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, recipeName), | ||||||
|  | 		}, nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	u, err := url.Parse(recipeName) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return Recipe{}, err | ||||||
|  | 	} | ||||||
|  | 	u.Scheme = "https" | ||||||
|  | 	u.RawPath, err = url.JoinPath(u.RawPath, ".git") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return Recipe{}, err | ||||||
|  | 	} | ||||||
|  | 	return Recipe{ | ||||||
|  | 		Name:        recipeName, | ||||||
|  | 		NameEscaped: escapeRecipeName(recipeName), | ||||||
|  | 		Dir:         path.Join(config.RECIPES_DIR, escapeRecipeName(recipeName)), | ||||||
|  | 		GitURL:      u.String(), | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func escapeRecipeName(recipeName string) string { | ||||||
|  | 	recipeName = strings.ReplaceAll(recipeName, "/", "_") | ||||||
|  | 	recipeName = strings.ReplaceAll(recipeName, ".", "_") | ||||||
|  | 	return recipeName | ||||||
|  | } | ||||||
|  |  | ||||||
| // Ensure makes sure the recipe exists, is up to date and has the latest version checked out. | // Ensure makes sure the recipe exists, is up to date and has the latest version checked out. | ||||||
| func Ensure(recipeName string) error { | func (r Recipe) Ensure() error { | ||||||
| 	if err := EnsureExists(recipeName); err != nil { | 	if err := r.EnsureExists(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	if err := EnsureUpToDate(recipeName); err != nil { | 	if err := r.EnsureUpToDate(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	if err := EnsureLatest(recipeName); err != nil { | 	if err := r.EnsureLatest(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // EnsureExists ensures that a recipe is locally cloned | // EnsureExists ensures that the recipe is locally cloned | ||||||
| func EnsureExists(recipeName string) error { | func (r Recipe) EnsureExists() error { | ||||||
| 	recipeDir := path.Join(config.RECIPES_DIR, recipeName) | 	if _, err := os.Stat(r.Dir); os.IsNotExist(err) { | ||||||
|  | 		logrus.Debugf("%s does not exist, attemmpting to clone", r.Dir) | ||||||
| 	if _, err := os.Stat(recipeDir); os.IsNotExist(err) { | 		if err := gitPkg.Clone(r.Dir, r.GitURL); err != nil { | ||||||
| 		logrus.Debugf("%s does not exist, attemmpting to clone", recipeDir) |  | ||||||
| 		url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, recipeName) |  | ||||||
| 		if err := gitPkg.Clone(recipeDir, url); err != nil { |  | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { | 	if err := gitPkg.EnsureGitRepo(r.Dir); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -298,14 +326,12 @@ func EnsureExists(recipeName string) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| // EnsureVersion checks whether a specific version exists for a recipe. | // EnsureVersion checks whether a specific version exists for a recipe. | ||||||
| func EnsureVersion(recipeName, version string) error { | func (r Recipe) EnsureVersion(version string) error { | ||||||
| 	recipeDir := path.Join(config.RECIPES_DIR, recipeName) | 	if err := gitPkg.EnsureGitRepo(r.Dir); err != nil { | ||||||
|  |  | ||||||
| 	if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { |  | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	repo, err := git.PlainOpen(recipeDir) | 	repo, err := git.PlainOpen(r.Dir) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @ -329,11 +355,11 @@ func EnsureVersion(recipeName, version string) error { | |||||||
|  |  | ||||||
| 	joinedTags := strings.Join(parsedTags, ", ") | 	joinedTags := strings.Join(parsedTags, ", ") | ||||||
| 	if joinedTags != "" { | 	if joinedTags != "" { | ||||||
| 		logrus.Debugf("read %s as tags for recipe %s", joinedTags, recipeName) | 		logrus.Debugf("read %s as tags for recipe %s", joinedTags, r.Name) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if tagRef.String() == "" { | 	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() | 	worktree, err := repo.Worktree() | ||||||
| @ -350,37 +376,33 @@ func EnsureVersion(recipeName, version string) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	logrus.Debugf("successfully checked %s out to %s in %s", recipeName, tagRef.Short(), recipeDir) | 	logrus.Debugf("successfully checked %s out to %s in %s", r.Name, tagRef.Short(), r.Dir) | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // EnsureIsClean makes sure that the recipe repository has no unstaged changes. | // EnsureIsClean makes sure that the recipe repository has no unstaged changes. | ||||||
| func EnsureIsClean(recipeName string) error { | func (r Recipe) EnsureIsClean() error { | ||||||
| 	recipeDir := path.Join(config.RECIPES_DIR, recipeName) | 	isClean, err := gitPkg.IsClean(r.Dir) | ||||||
|  |  | ||||||
| 	isClean, err := gitPkg.IsClean(recipeDir) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to check git clean status in %s: %s", recipeDir, err) | 		return fmt.Errorf("unable to check git clean status in %s: %s", r.Dir, err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if !isClean { | 	if !isClean { | ||||||
| 		msg := "%s (%s) has locally unstaged changes? please commit/remove your changes before proceeding" | 		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, r.Dir) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // EnsureLatest makes sure the latest commit is checked out for a local recipe repository | // EnsureLatest makes sure the latest commit is checked out for the local recipe repository | ||||||
| func EnsureLatest(recipeName string) error { | func (r Recipe) EnsureLatest() error { | ||||||
| 	recipeDir := path.Join(config.RECIPES_DIR, recipeName) | 	if err := gitPkg.EnsureGitRepo(r.Dir); err != nil { | ||||||
|  |  | ||||||
| 	if err := gitPkg.EnsureGitRepo(recipeDir); err != nil { |  | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	repo, err := git.PlainOpen(recipeDir) | 	repo, err := git.PlainOpen(r.Dir) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @ -390,7 +412,7 @@ func EnsureLatest(recipeName string) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	branch, err := gitPkg.GetDefaultBranch(repo, recipeDir) | 	branch, err := gitPkg.GetDefaultBranch(repo, r.Dir) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @ -402,7 +424,7 @@ func EnsureLatest(recipeName string) error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := worktree.Checkout(checkOutOpts); err != nil { | 	if err := worktree.Checkout(checkOutOpts); err != nil { | ||||||
| 		logrus.Debugf("failed to check out %s in %s", branch, recipeDir) | 		logrus.Debugf("failed to check out %s in %s", branch, r.Dir) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -410,18 +432,17 @@ func EnsureLatest(recipeName string) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| // ChaosVersion constructs a chaos mode recipe version. | // ChaosVersion constructs a chaos mode recipe version. | ||||||
| func ChaosVersion(recipeName string) (string, error) { | func (r Recipe) ChaosVersion() (string, error) { | ||||||
| 	var version string | 	var version string | ||||||
|  |  | ||||||
| 	head, err := gitPkg.GetRecipeHead(recipeName) | 	head, err := gitPkg.GetHead(r.Dir) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return version, err | 		return version, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	version = formatter.SmallSHA(head.String()) | 	version = formatter.SmallSHA(head.String()) | ||||||
|  |  | ||||||
| 	recipeDir := path.Join(config.RECIPES_DIR, recipeName) | 	isClean, err := gitPkg.IsClean(r.Dir) | ||||||
| 	isClean, err := gitPkg.IsClean(recipeDir) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return version, err | 		return version, err | ||||||
| 	} | 	} | ||||||
| @ -464,22 +485,22 @@ func GetVersionLabelLocal(recipe Recipe) (string, error) { | |||||||
| 	return label, nil | 	return label, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func GetRecipeFeaturesAndCategory(recipeName string) (Features, string, error) { | func (r Recipe) GetRecipeFeaturesAndCategory() (Features, string, error) { | ||||||
| 	feat := Features{} | 	feat := Features{} | ||||||
|  |  | ||||||
| 	var category string | 	var category string | ||||||
|  |  | ||||||
| 	readmePath := path.Join(config.RECIPES_DIR, recipeName, "README.md") | 	readmePath := path.Join(r.Dir, "README.md") | ||||||
|  |  | ||||||
| 	logrus.Debugf("attempting to open %s for recipe metadata parsing", readmePath) | 	logrus.Debugf("attempting to open %s for recipe metadata parsing", readmePath) | ||||||
|  |  | ||||||
| 	readmeFS, err := ioutil.ReadFile(readmePath) | 	readmeFS, err := os.ReadFile(readmePath) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return feat, category, err | 		return feat, category, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	readmeMetadata, err := GetStringInBetween( // Find text between delimiters | 	readmeMetadata, err := GetStringInBetween( // Find text between delimiters | ||||||
| 		recipeName, | 		r.Name, | ||||||
| 		string(readmeFS), | 		string(readmeFS), | ||||||
| 		"<!-- metadata -->", "<!-- endmetadata -->", | 		"<!-- metadata -->", "<!-- endmetadata -->", | ||||||
| 	) | 	) | ||||||
| @ -530,7 +551,7 @@ func GetRecipeFeaturesAndCategory(recipeName string) (Features, string, error) { | |||||||
| 		if strings.Contains(val, "**Image**") { | 		if strings.Contains(val, "**Image**") { | ||||||
| 			imageMetadata, err := GetImageMetadata(strings.TrimSpace( | 			imageMetadata, err := GetImageMetadata(strings.TrimSpace( | ||||||
| 				strings.TrimPrefix(val, "* **Image**:"), | 				strings.TrimPrefix(val, "* **Image**:"), | ||||||
| 			), recipeName) | 			), r.Name) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| @ -597,38 +618,36 @@ func GetStringInBetween(recipeName, str, start, end string) (result string, err | |||||||
| } | } | ||||||
|  |  | ||||||
| // EnsureUpToDate ensures that the local repo is synced to the remote | // EnsureUpToDate ensures that the local repo is synced to the remote | ||||||
| func EnsureUpToDate(recipeName string) error { | func (r Recipe) EnsureUpToDate() error { | ||||||
| 	recipeDir := path.Join(config.RECIPES_DIR, recipeName) | 	repo, err := git.PlainOpen(r.Dir) | ||||||
|  |  | ||||||
| 	repo, err := git.PlainOpen(recipeDir) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to open %s: %s", recipeDir, err) | 		return fmt.Errorf("unable to open %s: %s", r.Dir, err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	remotes, err := repo.Remotes() | 	remotes, err := repo.Remotes() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to read remotes in %s: %s", recipeDir, err) | 		return fmt.Errorf("unable to read remotes in %s: %s", r.Dir, err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(remotes) == 0 { | 	if len(remotes) == 0 { | ||||||
| 		logrus.Debugf("cannot ensure %s is up-to-date, no git remotes configured", recipeName) | 		logrus.Debugf("cannot ensure %s is up-to-date, no git remotes configured", r.Name) | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	worktree, err := repo.Worktree() | 	worktree, err := repo.Worktree() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to open git work tree in %s: %s", recipeDir, err) | 		return fmt.Errorf("unable to open git work tree in %s: %s", r.Dir, err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	branch, err := gitPkg.CheckoutDefaultBranch(repo, recipeDir) | 	branch, err := gitPkg.CheckoutDefaultBranch(repo, r.Dir) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("unable to check out default branch in %s: %s", recipeDir, err) | 		return fmt.Errorf("unable to check out default branch in %s: %s", r.Dir, err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	fetchOpts := &git.FetchOptions{Tags: git.AllTags} | 	fetchOpts := &git.FetchOptions{Tags: git.AllTags} | ||||||
| 	if err := repo.Fetch(fetchOpts); err != nil { | 	if err := repo.Fetch(fetchOpts); err != nil { | ||||||
| 		if !strings.Contains(err.Error(), "already up-to-date") { | 		if !strings.Contains(err.Error(), "already up-to-date") { | ||||||
| 			return fmt.Errorf("unable to fetch tags in %s: %s", recipeDir, err) | 			return fmt.Errorf("unable to fetch tags in %s: %s", r.Dir, err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -640,11 +659,11 @@ func EnsureUpToDate(recipeName string) error { | |||||||
|  |  | ||||||
| 	if err := worktree.Pull(opts); err != nil { | 	if err := worktree.Pull(opts); err != nil { | ||||||
| 		if !strings.Contains(err.Error(), "already up-to-date") { | 		if !strings.Contains(err.Error(), "already up-to-date") { | ||||||
| 			return fmt.Errorf("unable to git pull in %s: %s", recipeDir, err) | 			return fmt.Errorf("unable to git pull in %s: %s", r.Dir, err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	logrus.Debugf("fetched latest git changes for %s", recipeName) | 	logrus.Debugf("fetched latest git changes for %s", r.Name) | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @ -672,7 +691,7 @@ func ReadRecipeCatalogue(offline bool) (RecipeCatalogue, error) { | |||||||
|  |  | ||||||
| // readRecipeCatalogueFS reads the catalogue from the file system. | // readRecipeCatalogueFS reads the catalogue from the file system. | ||||||
| func readRecipeCatalogueFS(target interface{}) error { | func readRecipeCatalogueFS(target interface{}) error { | ||||||
| 	recipesJSONFS, err := ioutil.ReadFile(config.RECIPES_JSON) | 	recipesJSONFS, err := os.ReadFile(config.RECIPES_JSON) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @ -724,20 +743,20 @@ func (r RecipeMissingFromCatalogue) Error() string { | |||||||
| } | } | ||||||
|  |  | ||||||
| // GetRecipeMeta retrieves the recipe metadata from the recipe catalogue. | // GetRecipeMeta retrieves the recipe metadata from the recipe catalogue. | ||||||
| func GetRecipeMeta(recipeName string, offline bool) (RecipeMeta, error) { | func (r Recipe) GetRecipeMeta(offline bool) (RecipeMeta, error) { | ||||||
| 	catl, err := ReadRecipeCatalogue(offline) | 	catl, err := ReadRecipeCatalogue(offline) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return RecipeMeta{}, err | 		return RecipeMeta{}, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	recipeMeta, ok := catl[recipeName] | 	recipeMeta, ok := catl[r.Name] | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return RecipeMeta{}, RecipeMissingFromCatalogue{ | 		return RecipeMeta{}, RecipeMissingFromCatalogue{ | ||||||
| 			err: fmt.Sprintf("recipe %s does not exist?", recipeName), | 			err: fmt.Sprintf("recipe %s does not exist?", r.Name), | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	logrus.Debugf("recipe metadata retrieved for %s", recipeName) | 	logrus.Debugf("recipe metadata retrieved for %s", r.Name) | ||||||
|  |  | ||||||
| 	return recipeMeta, nil | 	return recipeMeta, nil | ||||||
| } | } | ||||||
| @ -864,13 +883,12 @@ func ReadReposMetadata() (RepoCatalogue, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // GetRecipeVersions retrieves all recipe versions. | // GetRecipeVersions retrieves all recipe versions. | ||||||
| func GetRecipeVersions(recipeName string, offline bool) (RecipeVersions, error) { | func (r Recipe) GetVersions(offline bool) (RecipeVersions, error) { | ||||||
| 	versions := RecipeVersions{} | 	versions := RecipeVersions{} | ||||||
| 	recipeDir := path.Join(config.RECIPES_DIR, recipeName) |  | ||||||
|  |  | ||||||
| 	logrus.Debugf("attempting to open git repository in %s", recipeDir) | 	logrus.Debugf("attempting to open git repository in %s", r.Dir) | ||||||
|  |  | ||||||
| 	repo, err := git.PlainOpen(recipeDir) | 	repo, err := git.PlainOpen(r.Dir) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return versions, err | 		return versions, err | ||||||
| 	} | 	} | ||||||
| @ -888,7 +906,7 @@ func GetRecipeVersions(recipeName string, offline bool) (RecipeVersions, error) | |||||||
| 	if err := gitTags.ForEach(func(ref *plumbing.Reference) (err error) { | 	if err := gitTags.ForEach(func(ref *plumbing.Reference) (err error) { | ||||||
| 		tag := strings.TrimPrefix(string(ref.Name()), "refs/tags/") | 		tag := strings.TrimPrefix(string(ref.Name()), "refs/tags/") | ||||||
|  |  | ||||||
| 		logrus.Debugf("processing %s for %s", tag, recipeName) | 		logrus.Debugf("processing %s for %s", tag, r.Name) | ||||||
|  |  | ||||||
| 		checkOutOpts := &git.CheckoutOptions{ | 		checkOutOpts := &git.CheckoutOptions{ | ||||||
| 			Create: false, | 			Create: false, | ||||||
| @ -896,19 +914,18 @@ func GetRecipeVersions(recipeName string, offline bool) (RecipeVersions, error) | |||||||
| 			Branch: plumbing.ReferenceName(ref.Name()), | 			Branch: plumbing.ReferenceName(ref.Name()), | ||||||
| 		} | 		} | ||||||
| 		if err := worktree.Checkout(checkOutOpts); err != nil { | 		if err := worktree.Checkout(checkOutOpts); err != nil { | ||||||
| 			logrus.Debugf("failed to check out %s in %s", tag, recipeDir) | 			logrus.Debugf("failed to check out %s in %s", tag, r.Dir) | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		logrus.Debugf("successfully checked out %s in %s", ref.Name(), recipeDir) | 		logrus.Debugf("successfully checked out %s in %s", ref.Name(), r.Dir) | ||||||
|  |  | ||||||
| 		recipe, err := Get(recipeName, offline) | 		if err := r.LoadConfig(); err != nil { | ||||||
| 		if err != nil { |  | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		versionMeta := make(map[string]ServiceMeta) | 		versionMeta := make(map[string]ServiceMeta) | ||||||
| 		for _, service := range recipe.Config.Services { | 		for _, service := range r.Config.Services { | ||||||
|  |  | ||||||
| 			img, err := reference.ParseNormalizedNamed(service.Image) | 			img, err := reference.ParseNormalizedNamed(service.Image) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| @ -941,14 +958,14 @@ func GetRecipeVersions(recipeName string, offline bool) (RecipeVersions, error) | |||||||
| 		return versions, err | 		return versions, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	_, err = gitPkg.CheckoutDefaultBranch(repo, recipeDir) | 	_, err = gitPkg.CheckoutDefaultBranch(repo, r.Dir) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return versions, err | 		return versions, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	sortRecipeVersions(versions) | 	sortRecipeVersions(versions) | ||||||
|  |  | ||||||
| 	logrus.Debugf("collected %s for %s", versions, recipeName) | 	logrus.Debugf("collected %s for %s", versions, r.Name) | ||||||
|  |  | ||||||
| 	return versions, nil | 	return versions, nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ import ( | |||||||
|  |  | ||||||
| func TestGetVersionLabelLocalDoesNotUseTimeoutLabel(t *testing.T) { | func TestGetVersionLabelLocalDoesNotUseTimeoutLabel(t *testing.T) { | ||||||
| 	offline := true | 	offline := true | ||||||
| 	recipe, err := Get("traefik", offline) | 	recipe, err := Get2("traefik", offline) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user