refactor: recipe validation
continuous-integration/drone/push Build is passing Details

This commit is contained in:
decentral1se 2021-09-05 01:55:10 +02:00
parent 317be4cc01
commit c99f0fc908
No known key found for this signature in database
GPG Key ID: 5E2EF5A63E3718CC
7 changed files with 106 additions and 86 deletions

View File

@ -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

View File

@ -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)
}

View File

@ -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,

View File

@ -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
View 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
}

View File

@ -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
View 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
}