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