forked from toolshed/abra
		
	refactor: recipe validation
This commit is contained in:
		| @ -9,14 +9,11 @@ import ( | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"coopcloud.tech/abra/config" | ||||
| 	"coopcloud.tech/abra/web" | ||||
| 	"github.com/go-git/go-git/v5" | ||||
| 	"github.com/go-git/go-git/v5/plumbing" | ||||
| ) | ||||
|  | ||||
| // RecipeCatalogueURL is the only current recipe catalogue available. | ||||
| @ -67,62 +64,6 @@ type Recipe struct { | ||||
| 	Website       string                          `json:"website"` | ||||
| } | ||||
|  | ||||
| // EnsureExists checks whether a recipe has been cloned locally or not. | ||||
| func (r Recipe) EnsureExists() error { | ||||
| 	recipeDir := path.Join(config.ABRA_DIR, "apps", strings.ToLower(r.Name)) | ||||
|  | ||||
| 	if _, err := os.Stat(recipeDir); os.IsNotExist(err) { | ||||
| 		url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, r.Name) | ||||
| 		_, err := git.PlainClone(recipeDir, false, &git.CloneOptions{URL: url, Tags: git.AllTags}) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // EnsureVersion checks whether a specific version exists for a recipe. | ||||
| func (r Recipe) EnsureVersion(version string) error { | ||||
| 	recipeDir := path.Join(config.ABRA_DIR, "apps", strings.ToLower(r.Name)) | ||||
|  | ||||
| 	repo, err := git.PlainOpen(recipeDir) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	tags, err := repo.Tags() | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	var tagRef plumbing.ReferenceName | ||||
| 	if err := tags.ForEach(func(ref *plumbing.Reference) (err error) { | ||||
| 		if ref.Name().Short() == version { | ||||
| 			tagRef = ref.Name() | ||||
| 		} | ||||
| 		return nil | ||||
| 	}); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if tagRef.String() == "" { | ||||
| 		return fmt.Errorf("%s is not available?", version) | ||||
| 	} | ||||
|  | ||||
| 	worktree, err := repo.Worktree() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	opts := &git.CheckoutOptions{Branch: tagRef, Keep: true} | ||||
| 	if err := worktree.Checkout(opts); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // LatestVersion returns the latest version of a recipe. | ||||
| func (r Recipe) LatestVersion() string { | ||||
| 	var latestVersion string | ||||
|  | ||||
| @ -9,6 +9,7 @@ import ( | ||||
| 	abraFormatter "coopcloud.tech/abra/cli/formatter" | ||||
| 	"coopcloud.tech/abra/cli/internal" | ||||
| 	"coopcloud.tech/abra/config" | ||||
| 	"coopcloud.tech/abra/recipe" | ||||
| 	"coopcloud.tech/abra/secret" | ||||
| 	"github.com/AlecAivazis/survey/v2" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| @ -87,15 +88,15 @@ func getRecipe(recipeName string) (catalogue.Recipe, error) { | ||||
| 		return catalogue.Recipe{}, err | ||||
| 	} | ||||
|  | ||||
| 	recipe, ok := catl[recipeName] | ||||
| 	rec, ok := catl[recipeName] | ||||
| 	if !ok { | ||||
| 		return catalogue.Recipe{}, fmt.Errorf("recipe '%s' does not exist?", recipeName) | ||||
| 	} | ||||
| 	if err := recipe.EnsureExists(); err != nil { | ||||
| 	if err := recipe.EnsureExists(rec.Name); err != nil { | ||||
| 		return catalogue.Recipe{}, err | ||||
| 	} | ||||
|  | ||||
| 	return recipe, nil | ||||
| 	return rec, nil | ||||
| } | ||||
|  | ||||
| // ensureDomainFlag checks if the domain flag was used. if not, asks the user for it/ | ||||
| @ -180,12 +181,12 @@ func action(c *cli.Context) error { | ||||
| 		logrus.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	recipe, err := getRecipe(recipeName) | ||||
| 	rec, err := getRecipe(recipeName) | ||||
| 	if err != nil { | ||||
| 		logrus.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	latestVersion := recipe.LatestVersion() | ||||
| 	latestVersion := rec.LatestVersion() | ||||
| 	if err := recipe.EnsureVersion(latestVersion); err != nil { | ||||
| 		logrus.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| @ -4,10 +4,6 @@ import ( | ||||
| 	"github.com/urfave/cli/v2" | ||||
| ) | ||||
|  | ||||
| // Flags | ||||
|  | ||||
| // AppName stores the variable from AppNameFlag | ||||
|  | ||||
| // Secrets stores the variable from SecretsFlag | ||||
| var Secrets bool | ||||
|  | ||||
| @ -43,8 +39,10 @@ var ContextFlag = &cli.StringFlag{ | ||||
| 	Destination: &Context, | ||||
| } | ||||
|  | ||||
| // Force force functionality without asking. | ||||
| var Force bool | ||||
|  | ||||
| // ForceFlag turns on/off force functionality. | ||||
| var ForceFlag = &cli.BoolFlag{ | ||||
| 	Name:        "force", | ||||
| 	Value:       false, | ||||
|  | ||||
| @ -7,10 +7,10 @@ import ( | ||||
| 	"github.com/urfave/cli/v2" | ||||
| ) | ||||
|  | ||||
| // ShowSubcommandHelpAndError exits the program on error, logs the error to the terminal, and shows the help command. | ||||
| // ShowSubcommandHelpAndError exits the program on error, logs the error to the | ||||
| // terminal, and shows the help command. | ||||
| func ShowSubcommandHelpAndError(c *cli.Context, err interface{}) { | ||||
| 	if err2 := cli.ShowSubcommandHelp(c); err2 != nil { | ||||
| 		// go-critic wants me to check this error but if this throws an error while we throw an error that would be annoying | ||||
| 		logrus.Error(err2) | ||||
| 	} | ||||
| 	logrus.Error(err) | ||||
|  | ||||
							
								
								
									
										24
									
								
								cli/internal/validate.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								cli/internal/validate.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| package internal | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
|  | ||||
| 	"coopcloud.tech/abra/recipe" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/urfave/cli/v2" | ||||
| ) | ||||
|  | ||||
| // ValidateRecipeArg ensures the recipe arg is valid. | ||||
| func ValidateRecipeArg(c *cli.Context) string { | ||||
| 	recipeName := c.Args().First() | ||||
|  | ||||
| 	if recipeName == "" { | ||||
| 		ShowSubcommandHelpAndError(c, errors.New("no recipe provided")) | ||||
| 	} | ||||
|  | ||||
| 	if err := recipe.EnsureExists(recipeName); err != nil { | ||||
| 		logrus.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	return recipeName | ||||
| } | ||||
| @ -56,10 +56,7 @@ var recipeVersionCommand = &cli.Command{ | ||||
| 	Aliases:   []string{"v"}, | ||||
| 	ArgsUsage: "<recipe>", | ||||
| 	Action: func(c *cli.Context) error { | ||||
| 		recipe := c.Args().First() | ||||
| 		if recipe == "" { | ||||
| 			internal.ShowSubcommandHelpAndError(c, errors.New("no recipe provided")) | ||||
| 		} | ||||
| 		recipe := internal.ValidateRecipeArg(c) | ||||
|  | ||||
| 		catalogue, err := catalogue.ReadRecipeCatalogue() | ||||
| 		if err != nil { | ||||
| @ -173,10 +170,7 @@ This is step 1 of upgrading a recipe. Step 2 is running "abra recipe sync | ||||
| `, | ||||
| 	ArgsUsage: "<recipe>", | ||||
| 	Action: func(c *cli.Context) error { | ||||
| 		recipe := c.Args().First() | ||||
| 		if recipe == "" { | ||||
| 			internal.ShowSubcommandHelpAndError(c, errors.New("no recipe provided")) | ||||
| 		} | ||||
| 		recipe := internal.ValidateRecipeArg(c) | ||||
|  | ||||
| 		appFiles, err := config.LoadAppFiles("") | ||||
| 		if err != nil { | ||||
| @ -304,10 +298,7 @@ the versioning metadata of up-and-running containers are. | ||||
| `, | ||||
| 	ArgsUsage: "<recipe>", | ||||
| 	Action: func(c *cli.Context) error { | ||||
| 		recipe := c.Args().First() | ||||
| 		if recipe == "" { | ||||
| 			internal.ShowSubcommandHelpAndError(c, errors.New("no recipe provided")) | ||||
| 		} | ||||
| 		recipe := internal.ValidateRecipeArg(c) | ||||
|  | ||||
| 		appFiles, err := config.LoadAppFiles("") | ||||
| 		if err != nil { | ||||
| @ -363,10 +354,7 @@ var recipeLintCommand = &cli.Command{ | ||||
| 	Aliases:   []string{"l"}, | ||||
| 	ArgsUsage: "<recipe>", | ||||
| 	Action: func(c *cli.Context) error { | ||||
| 		recipe := c.Args().First() | ||||
| 		if recipe == "" { | ||||
| 			internal.ShowSubcommandHelpAndError(c, errors.New("no recipe provided")) | ||||
| 		} | ||||
| 		recipe := internal.ValidateRecipeArg(c) | ||||
|  | ||||
| 		pattern := fmt.Sprintf("%s/%s/compose**yml", config.APPS_DIR, recipe) | ||||
| 		composeFiles, err := filepath.Glob(pattern) | ||||
|  | ||||
							
								
								
									
										68
									
								
								recipe/recipe.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								recipe/recipe.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | ||||
| package recipe | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"strings" | ||||
|  | ||||
| 	"coopcloud.tech/abra/config" | ||||
| 	"github.com/go-git/go-git/v5" | ||||
| 	"github.com/go-git/go-git/v5/plumbing" | ||||
| ) | ||||
|  | ||||
| // EnsureExists checks whether a recipe has been cloned locally or not. | ||||
| func EnsureExists(recipe string) error { | ||||
| 	recipeDir := path.Join(config.ABRA_DIR, "apps", strings.ToLower(recipe)) | ||||
|  | ||||
| 	if _, err := os.Stat(recipeDir); os.IsNotExist(err) { | ||||
| 		url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, recipe) | ||||
| 		_, err := git.PlainClone(recipeDir, false, &git.CloneOptions{URL: url, Tags: git.AllTags}) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // EnsureVersion checks whether a specific version exists for a recipe. | ||||
| func EnsureVersion(version string) error { | ||||
| 	recipeDir := path.Join(config.ABRA_DIR, "apps", strings.ToLower(version)) | ||||
|  | ||||
| 	repo, err := git.PlainOpen(recipeDir) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	tags, err := repo.Tags() | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	var tagRef plumbing.ReferenceName | ||||
| 	if err := tags.ForEach(func(ref *plumbing.Reference) (err error) { | ||||
| 		if ref.Name().Short() == version { | ||||
| 			tagRef = ref.Name() | ||||
| 		} | ||||
| 		return nil | ||||
| 	}); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if tagRef.String() == "" { | ||||
| 		return fmt.Errorf("%s is not available?", version) | ||||
| 	} | ||||
|  | ||||
| 	worktree, err := repo.Worktree() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	opts := &git.CheckoutOptions{Branch: tagRef, Keep: true} | ||||
| 	if err := worktree.Checkout(opts); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
		Reference in New Issue
	
	Block a user