diff --git a/catalogue/catalogue.go b/catalogue/catalogue.go index f9cdebd9..94b154d7 100644 --- a/catalogue/catalogue.go +++ b/catalogue/catalogue.go @@ -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 diff --git a/cli/app/new.go b/cli/app/new.go index 1132b35f..2a3fe201 100644 --- a/cli/app/new.go +++ b/cli/app/new.go @@ -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) } diff --git a/cli/internal/common.go b/cli/internal/common.go index a77784f9..e1c928fa 100644 --- a/cli/internal/common.go +++ b/cli/internal/common.go @@ -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, diff --git a/cli/internal/errors.go b/cli/internal/errors.go index d51f7e77..ccd6e3fb 100644 --- a/cli/internal/errors.go +++ b/cli/internal/errors.go @@ -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) diff --git a/cli/internal/validate.go b/cli/internal/validate.go new file mode 100644 index 00000000..ed19092a --- /dev/null +++ b/cli/internal/validate.go @@ -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 +} diff --git a/cli/recipe/recipe.go b/cli/recipe/recipe.go index 6e180a8a..0675fe01 100644 --- a/cli/recipe/recipe.go +++ b/cli/recipe/recipe.go @@ -56,10 +56,7 @@ var recipeVersionCommand = &cli.Command{ Aliases: []string{"v"}, ArgsUsage: "", 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: "", 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: "", 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: "", 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) diff --git a/recipe/recipe.go b/recipe/recipe.go new file mode 100644 index 00000000..1f398f0d --- /dev/null +++ b/recipe/recipe.go @@ -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 +}