0
0
forked from toolshed/abra

Compare commits

..

1 Commits

Author SHA1 Message Date
bd80599114 secret: allow inserting secret from file and add trim flag 2024-06-22 17:28:13 +02:00
33 changed files with 309 additions and 454 deletions

View File

@ -47,26 +47,22 @@ var appBackupListCommand = cli.Command{
Action: func(c *cli.Context) error {
app := internal.ValidateApp(c)
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipe.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipe.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
@ -114,26 +110,22 @@ var appBackupDownloadCommand = cli.Command{
Action: func(c *cli.Context) error {
app := internal.ValidateApp(c)
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipe.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipe.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
@ -188,27 +180,22 @@ var appBackupCreateCommand = cli.Command{
Action: func(c *cli.Context) error {
app := internal.ValidateApp(c)
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipe.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipe.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
@ -251,27 +238,22 @@ var appBackupSnapshotsCommand = cli.Command{
Action: func(c *cli.Context) error {
app := internal.ValidateApp(c)
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipe.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipe.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}

View File

@ -6,6 +6,7 @@ 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"
)
@ -37,26 +38,22 @@ ${FOO:<default>} syntax). "check" does not confirm or deny this for you.`,
Action: func(c *cli.Context) error {
app := internal.ValidateApp(c)
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipePkg.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipePkg.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}

View File

@ -15,6 +15,7 @@ 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"
)
@ -59,27 +60,22 @@ Example:
Action: func(c *cli.Context) error {
app := internal.ValidateApp(c)
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipePkg.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipePkg.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
@ -232,27 +228,22 @@ var appCmdListCommand = cli.Command{
Action: func(c *cli.Context) error {
app := internal.ValidateApp(c)
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipePkg.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipePkg.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}

View File

@ -56,32 +56,28 @@ recipes.
logrus.Fatal("cannot use <version> and --chaos together")
}
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipe.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipe.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.LoadConfig(); err != nil {
r, err := recipe.Get(app.Recipe, internal.Offline)
if err != nil {
logrus.Fatal(err)
}
@ -109,7 +105,7 @@ recipes.
if specificVersion != "" {
version = specificVersion
logrus.Debugf("choosing %s as version to deploy", version)
if err := r.EnsureVersion(version); err != nil {
if err := recipe.EnsureVersion(app.Recipe, version); err != nil {
logrus.Fatal(err)
}
}
@ -145,7 +141,7 @@ recipes.
if len(versions) == 0 && !internal.Chaos {
logrus.Warn("no published versions in catalogue, trying local recipe repository")
recipeVersions, err := r.GetVersions(internal.Offline)
recipeVersions, err := recipe.GetRecipeVersions(app.Recipe, internal.Offline)
if err != nil {
logrus.Warn(err)
}
@ -159,11 +155,11 @@ recipes.
if len(versions) > 0 && !internal.Chaos {
version = versions[len(versions)-1]
logrus.Debugf("choosing %s as version to deploy", version)
if err := r.EnsureVersion(version); err != nil {
if err := recipe.EnsureVersion(app.Recipe, version); err != nil {
logrus.Fatal(err)
}
} else {
head, err := git.GetHead(app.Recipe)
head, err := git.GetRecipeHead(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
@ -175,7 +171,7 @@ recipes.
if internal.Chaos {
logrus.Warnf("chaos mode engaged")
var err error
version, err = r.ChaosVersion()
version, err = recipe.ChaosVersion(app.Recipe)
if err != nil {
logrus.Fatal(err)
}

View File

@ -88,15 +88,12 @@ the logs.
}
func checkErrors(c *cli.Context, cl *dockerClient.Client, app config.App) error {
r, err := recipe.Get(app.Recipe)
recipe, err := recipe.Get(app.Recipe, internal.Offline)
if err != nil {
logrus.Fatal(err)
}
if err := r.LoadConfig(); err != nil {
return err
}
for _, service := range r.Config.Services {
for _, service := range recipe.Config.Services {
filters := filters.NewArgs()
filters.Add("name", fmt.Sprintf("^%s_%s", app.StackName(), service.Name))

View File

@ -39,12 +39,7 @@ var appLogsCommand = cli.Command{
app := internal.ValidateApp(c)
stackName := app.StackName()
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}

View File

@ -10,6 +10,7 @@ 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"
@ -64,21 +65,21 @@ var appNewCommand = cli.Command{
}
},
Action: func(c *cli.Context) error {
r := internal.ValidateRecipe(c)
recipe := internal.ValidateRecipe(c)
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipePkg.EnsureIsClean(recipe.Name); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil {
logrus.Fatal(err)
}
}
if c.Args().Get(1) == "" {
var version string
recipeVersions, err := r.GetVersions(internal.Offline)
recipeVersions, err := recipePkg.GetRecipeVersions(recipe.Name, internal.Offline)
if err != nil {
logrus.Fatal(err)
}
@ -91,16 +92,16 @@ var appNewCommand = cli.Command{
version = tag
}
if err := r.EnsureVersion(version); err != nil {
if err := recipePkg.EnsureVersion(recipe.Name, version); err != nil {
logrus.Fatal(err)
}
} else {
if err := r.EnsureLatest(); err != nil {
if err := recipePkg.EnsureLatest(recipe.Name); err != nil {
logrus.Fatal(err)
}
}
} else {
if err := r.EnsureVersion(c.Args().Get(1)); err != nil {
if err := recipePkg.EnsureVersion(recipe.Name, c.Args().Get(1)); err != nil {
logrus.Fatal(err)
}
}
@ -110,7 +111,7 @@ var appNewCommand = cli.Command{
logrus.Fatal(err)
}
if err := ensureDomainFlag(r.Name, internal.NewAppServer); err != nil {
if err := ensureDomainFlag(recipe, internal.NewAppServer); err != nil {
logrus.Fatal(err)
}
@ -118,7 +119,7 @@ var appNewCommand = cli.Command{
logrus.Debugf("%s sanitised as %s for new app", internal.Domain, sanitisedAppName)
if err := config.TemplateAppEnvSample(
r.Name,
recipe.Name,
internal.Domain,
internal.NewAppServer,
internal.Domain,
@ -129,23 +130,23 @@ var appNewCommand = cli.Command{
var secrets AppSecrets
var secretTable *jsontable.JSONTable
if internal.Secrets {
sampleEnv, err := r.SampleEnv()
sampleEnv, err := recipe.SampleEnv()
if err != nil {
logrus.Fatal(err)
}
composeFiles, err := config.GetComposeFiles(r.NameEscaped, sampleEnv)
composeFiles, err := config.GetComposeFiles(recipe.Name, sampleEnv)
if err != nil {
logrus.Fatal(err)
}
envSamplePath := path.Join(r.Dir, ".env.sample")
envSamplePath := path.Join(config.RECIPES_DIR, recipe.Name, ".env.sample")
secretsConfig, err := secret.ReadSecretsConfig(envSamplePath, composeFiles, config.StackName(internal.Domain))
if err != nil {
return err
}
if err := promptForSecrets(r.Name, secretsConfig); err != nil {
if err := promptForSecrets(recipe.Name, secretsConfig); err != nil {
logrus.Fatal(err)
}
@ -172,9 +173,9 @@ var appNewCommand = cli.Command{
tableCol := []string{"server", "recipe", "domain"}
table := formatter.CreateTable(tableCol)
table.Append([]string{internal.NewAppServer, r.Name, internal.Domain})
table.Append([]string{internal.NewAppServer, recipe.Name, internal.Domain})
fmt.Println(fmt.Sprintf("A new %s app has been created! Here is an overview:", r.Name))
fmt.Println(fmt.Sprintf("A new %s app has been created! Here is an overview:", recipe.Name))
fmt.Println("")
table.Render()
fmt.Println("")
@ -230,11 +231,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(recipeName string, server string) error {
func ensureDomainFlag(recipe recipePkg.Recipe, server string) error {
if internal.Domain == "" && !internal.NoInput {
prompt := &survey.Input{
Message: "Specify app domain",
Default: fmt.Sprintf("%s.%s", recipeName, server),
Default: fmt.Sprintf("%s.%s", recipe.Name, server),
}
if err := survey.AskOne(prompt, &internal.Domain); err != nil {
return err

View File

@ -39,11 +39,6 @@ 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)
@ -61,7 +56,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 := r.EnsureVersion(deployedVersion); err != nil {
if err := recipe.EnsureVersion(app.Recipe, deployedVersion); err != nil {
logrus.Fatal(err)
}
}

View File

@ -33,27 +33,22 @@ var appRestoreCommand = cli.Command{
Action: func(c *cli.Context) error {
app := internal.ValidateApp(c)
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipe.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipe.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}

View File

@ -51,37 +51,33 @@ 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 := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipe.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipe.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.LoadConfig(); err != nil {
r, err := recipe.Get(app.Recipe, internal.Offline)
if err != nil {
logrus.Fatal(err)
}
@ -117,7 +113,7 @@ recipes.
if len(versions) == 0 && !internal.Chaos {
logrus.Warn("no published versions in catalogue, trying local recipe repository")
recipeVersions, err := r.GetVersions(internal.Offline)
recipeVersions, err := recipe.GetRecipeVersions(app.Recipe, internal.Offline)
if err != nil {
logrus.Warn(err)
}
@ -187,7 +183,7 @@ recipes.
}
if !internal.Chaos {
if err := r.EnsureVersion(chosenDowngrade); err != nil {
if err := recipe.EnsureVersion(app.Recipe, chosenDowngrade); err != nil {
logrus.Fatal(err)
}
}
@ -195,13 +191,13 @@ recipes.
if internal.Chaos {
logrus.Warn("chaos mode engaged")
var err error
chosenDowngrade, err = r.ChaosVersion()
chosenDowngrade, err = recipe.ChaosVersion(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
}
abraShPath := fmt.Sprintf("%s/%s/%s", r.Dir, "abra.sh")
abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, app.Recipe, "abra.sh")
abraShEnv, err := config.ReadAbraShEnvVars(abraShPath)
if err != nil {
logrus.Fatal(err)

View File

@ -57,27 +57,22 @@ var appSecretGenerateCommand = cli.Command{
Action: func(c *cli.Context) error {
app := internal.ValidateApp(c)
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipe.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipe.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
@ -269,27 +264,22 @@ Example:
Action: func(c *cli.Context) error {
app := internal.ValidateApp(c)
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipe.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipe.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
@ -382,27 +372,22 @@ var appSecretLsCommand = cli.Command{
Action: func(c *cli.Context) error {
app := internal.ValidateApp(c)
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if err := r.EnsureExists(); err != nil {
if err := recipe.EnsureExists(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipe.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipe.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}

View File

@ -62,32 +62,28 @@ recipes.
logrus.Fatal("cannot use <version> and --chaos together")
}
r, err := recipe.Get(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipe.EnsureIsClean(app.Recipe); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipe.EnsureLatest(app.Recipe); err != nil {
logrus.Fatal(err)
}
}
if err := r.LoadConfig(); err != nil {
recipe, err := recipePkg.Get(app.Recipe, internal.Offline)
if err != nil {
logrus.Fatal(err)
}
if err := lint.LintForErrors(r); err != nil {
if err := lint.LintForErrors(recipe); err != nil {
logrus.Fatal(err)
}
@ -119,7 +115,7 @@ recipes.
if len(versions) == 0 && !internal.Chaos {
logrus.Warn("no published versions in catalogue, trying local recipe repository")
recipeVersions, err := r.GetVersions(internal.Offline)
recipeVersions, err := recipePkg.GetRecipeVersions(app.Recipe, internal.Offline)
if err != nil {
logrus.Warn(err)
}
@ -221,7 +217,7 @@ recipes.
}
if !internal.Chaos {
if err := r.EnsureVersion(chosenUpgrade); err != nil {
if err := recipePkg.EnsureVersion(app.Recipe, chosenUpgrade); err != nil {
logrus.Fatal(err)
}
}
@ -229,13 +225,13 @@ recipes.
if internal.Chaos {
logrus.Warn("chaos mode engaged")
var err error
chosenUpgrade, err = r.ChaosVersion()
chosenUpgrade, err = recipePkg.ChaosVersion(app.Recipe)
if err != nil {
logrus.Fatal(err)
}
}
abraShPath := fmt.Sprintf("%s/%s/%s", r.Dir, "abra.sh")
abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, app.Recipe, "abra.sh")
abraShEnv, err := config.ReadAbraShEnvVars(abraShPath)
if err != nil {
logrus.Fatal(err)

View File

@ -58,11 +58,6 @@ 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)
@ -83,7 +78,7 @@ var appVersionCommand = cli.Command{
logrus.Fatalf("failed to determine version of deployed %s", app.Name)
}
recipeMeta, err := r.GetRecipeMeta(internal.Offline)
recipeMeta, err := recipe.GetRecipeMeta(app.Recipe, internal.Offline)
if err != nil {
logrus.Fatal(err)
}

View File

@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
"coopcloud.tech/abra/cli/internal"
@ -58,10 +57,9 @@ keys configured on your account.
BashComplete: autocomplete.RecipeNameComplete,
Action: func(c *cli.Context) error {
recipeName := c.Args().First()
r := recipe.Recipe{}
if recipeName != "" {
r = internal.ValidateRecipe(c)
internal.ValidateRecipe(c)
}
if !internal.Chaos {
@ -100,12 +98,12 @@ keys configured on your account.
continue
}
versions, err := r.GetVersions(internal.Offline)
versions, err := recipe.GetRecipeVersions(recipeMeta.Name, internal.Offline)
if err != nil {
logrus.Warn(err)
}
features, category, err := r.GetRecipeFeaturesAndCategory()
features, category, err := recipe.GetRecipeFeaturesAndCategory(recipeMeta.Name)
if err != nil {
logrus.Warn(err)
}
@ -132,7 +130,7 @@ keys configured on your account.
}
if recipeName == "" {
if err := os.WriteFile(config.RECIPES_JSON, recipesJSON, 0764); err != nil {
if err := ioutil.WriteFile(config.RECIPES_JSON, recipesJSON, 0764); err != nil {
logrus.Fatal(err)
}
} else {

View File

@ -262,22 +262,6 @@ var RemoteUserFlag = &cli.StringFlag{
Destination: &RemoteUser,
}
var GitName string
var GitNameFlag = &cli.StringFlag{
Name: "git-name, gn",
Value: "",
Usage: "Git (user) name to do commits with",
Destination: &GitName,
}
var GitEmail string
var GitEmailFlag = &cli.StringFlag{
Name: "git-email, ge",
Value: "",
Usage: "Git email name to do commits with",
Destination: &GitEmail,
}
// SubCommandBefore wires up pre-action machinery (e.g. --debug handling).
func SubCommandBefore(c *cli.Context) error {
if Debug {

View File

@ -57,10 +57,7 @@ func ValidateRecipe(c *cli.Context) recipe.Recipe {
ShowSubcommandHelpAndError(c, errors.New("no recipe name provided"))
}
r, err := recipe.Get(recipeName)
if err != nil {
logrus.Fatal(err)
}
chosenRecipe, err := recipe.Get(recipeName, Offline)
if err != nil {
if c.Command.Name == "generate" {
if strings.Contains(err.Error(), "missing a compose") {
@ -77,7 +74,7 @@ func ValidateRecipe(c *cli.Context) recipe.Recipe {
logrus.Debugf("validated %s as recipe argument", recipeName)
return r
return chosenRecipe
}
// ValidateApp ensures the app name arg is valid.

View File

@ -24,14 +24,9 @@ var recipeFetchCommand = cli.Command{
BashComplete: autocomplete.RecipeNameComplete,
Action: func(c *cli.Context) error {
recipeName := c.Args().First()
if recipeName != "" {
internal.ValidateRecipe(c)
r, err := recipe.Get(recipeName)
if err != nil {
logrus.Fatal(err)
}
if err := r.Ensure(); err != nil {
if err := recipe.Ensure(recipeName); err != nil {
logrus.Fatal(err)
}
return nil
@ -44,11 +39,7 @@ var recipeFetchCommand = cli.Command{
catlBar := formatter.CreateProgressbar(len(catalogue), "fetching latest recipes...")
for recipeName := range catalogue {
r, err := recipe.Get(recipeName)
if err != nil {
logrus.Fatal(err)
}
if err := r.Ensure(); err != nil {
if err := recipe.Ensure(recipeName); err != nil {
logrus.Error(err)
}
catlBar.Add(1)

View File

@ -7,6 +7,7 @@ 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"
)
@ -26,27 +27,24 @@ var recipeLintCommand = cli.Command{
Before: internal.SubCommandBefore,
BashComplete: autocomplete.RecipeNameComplete,
Action: func(c *cli.Context) error {
r := internal.ValidateRecipe(c)
if err := r.LoadConfig(); err != nil {
logrus.Fatal(err)
}
recipe := internal.ValidateRecipe(c)
if err := r.EnsureExists(); err != nil {
if err := recipePkg.EnsureExists(recipe.Name); err != nil {
logrus.Fatal(err)
}
if !internal.Chaos {
if err := r.EnsureIsClean(); err != nil {
if err := recipePkg.EnsureIsClean(recipe.Name); err != nil {
logrus.Fatal(err)
}
if !internal.Offline {
if err := r.EnsureUpToDate(); err != nil {
if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil {
logrus.Fatal(err)
}
}
if err := r.EnsureLatest(); err != nil {
if err := recipePkg.EnsureLatest(recipe.Name); err != nil {
logrus.Fatal(err)
}
}
@ -64,7 +62,7 @@ var recipeLintCommand = cli.Command{
}
skipped := false
if rule.Skip(r) {
if rule.Skip(recipe) {
skipped = true
}
@ -75,7 +73,7 @@ var recipeLintCommand = cli.Command{
satisfied := false
if !skipped {
ok, err := rule.Function(r)
ok, err := rule.Function(recipe)
if err != nil {
logrus.Warn(err)
}

View File

@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"path"
"text/template"
@ -36,8 +37,6 @@ var recipeNewCommand = cli.Command{
internal.DebugFlag,
internal.NoInputFlag,
internal.OfflineFlag,
internal.GitNameFlag,
internal.GitEmailFlag,
},
Before: internal.SubCommandBefore,
Usage: "Create a new recipe",
@ -93,14 +92,14 @@ recipe and domain in the sample environment config).
logrus.Fatal(err)
}
if err := os.WriteFile(path, templated.Bytes(), 0644); err != nil {
if err := ioutil.WriteFile(path, templated.Bytes(), 0644); err != nil {
logrus.Fatal(err)
}
}
newGitRepo := path.Join(config.RECIPES_DIR, recipeName)
if err := git.Init(newGitRepo, true, internal.GitName, internal.GitEmail); err != nil {
if err := git.Init(newGitRepo, true); err != nil {
logrus.Fatal(err)
}

View File

@ -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(recipe.Dir)
directory := path.Join(config.RECIPES_DIR, recipe.Name)
repo, err := git.PlainOpen(directory)
if err != nil {
return err
@ -246,7 +246,8 @@ 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 {
tagReleaseNotePath := path.Join(recipe.Dir, "release", tag)
repoPath := path.Join(config.RECIPES_DIR, recipe.Name)
tagReleaseNotePath := path.Join(repoPath, "release", tag)
if _, err := os.Stat(tagReleaseNotePath); err == nil {
// Release note for current tag already exist exists.
return nil
@ -254,7 +255,7 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error {
return err
}
nextReleaseNotePath := path.Join(recipe.Dir, "release", "next")
nextReleaseNotePath := path.Join(repoPath, "release", "next")
if _, err := os.Stat(nextReleaseNotePath); err == nil {
// release/next note exists. Move it to release/<tag>
if internal.Dry {
@ -277,11 +278,11 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error {
if err != nil {
return err
}
err = gitPkg.Add(recipe.Dir, path.Join("release", "next"), internal.Dry)
err = gitPkg.Add(repoPath, path.Join("release", "next"), internal.Dry)
if err != nil {
return err
}
err = gitPkg.Add(recipe.Dir, path.Join("release", tag), internal.Dry)
err = gitPkg.Add(repoPath, path.Join("release", tag), internal.Dry)
if err != nil {
return err
}
@ -310,7 +311,7 @@ func addReleaseNotes(recipe recipe.Recipe, tag string) error {
if err != nil {
return err
}
err = gitPkg.Add(recipe.Dir, path.Join("release", tag), internal.Dry)
err = gitPkg.Add(repoPath, path.Join("release", tag), internal.Dry)
if err != nil {
return err
}
@ -324,14 +325,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())
}
}
@ -401,7 +402,8 @@ func pushRelease(recipe recipe.Recipe, tagString string) error {
}
func createReleaseFromPreviousTag(tagString, mainAppVersion string, recipe recipe.Recipe, tags []string) error {
repo, err := git.PlainOpen(recipe.Dir)
directory := path.Join(config.RECIPES_DIR, recipe.Name)
repo, err := git.PlainOpen(directory)
if err != nil {
return err
}

View File

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

View File

@ -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 := recipe.EnsureIsClean(); err != nil {
if err := recipePkg.EnsureIsClean(recipe.Name); err != nil {
logrus.Fatal(err)
}
if err := recipe.EnsureExists(); err != nil {
if err := recipePkg.EnsureExists(recipe.Name); err != nil {
logrus.Fatal(err)
}
if err := recipe.EnsureUpToDate(); err != nil {
if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil {
logrus.Fatal(err)
}
if err := recipe.EnsureLatest(); err != nil {
if err := recipePkg.EnsureLatest(recipe.Name); err != nil {
logrus.Fatal(err)
}

View File

@ -316,23 +316,22 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName
// processRecipeRepoVersion clones, pulls, checks out the version and lints the
// recipe repository.
func processRecipeRepoVersion(recipe recipe.Recipe, version string) error {
if err := recipe.EnsureExists(); err != nil {
func processRecipeRepoVersion(recipeName, version string) error {
if err := recipe.EnsureExists(recipeName); err != nil {
return err
}
if err := recipe.EnsureUpToDate(); err != nil {
if err := recipe.EnsureUpToDate(recipeName); err != nil {
return err
}
if err := recipe.EnsureVersion(version); err != nil {
if err := recipe.EnsureVersion(recipeName, version); err != nil {
return err
}
if err := recipe.LoadConfig(); err != nil {
if r, err := recipe.Get(recipeName, internal.Offline); err != nil {
return err
}
if err := lint.LintForErrors(recipe); err != nil {
} else if err := lint.LintForErrors(r); err != nil {
return err
}
@ -443,12 +442,7 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName,
Env: env,
}
recipe, err := recipe.Get(recipeName)
if err != nil {
return err
}
if err = processRecipeRepoVersion(recipe, upgradeVersion); err != nil {
if err = processRecipeRepoVersion(recipeName, upgradeVersion); err != nil {
return err
}

View File

@ -45,7 +45,7 @@ func TestGetApp(t *testing.T) {
func TestGetComposeFiles(t *testing.T) {
offline := true
r, err := recipe.Get2("abra-test-recipe", offline)
r, err := recipe.Get("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.Get2("abra-test-recipe", offline)
r, err := recipe.Get("abra-test-recipe", offline)
if err != nil {
t.Fatal(err)
}

View File

@ -94,7 +94,7 @@ func TestReadEnv(t *testing.T) {
func TestReadAbraShEnvVars(t *testing.T) {
offline := true
r, err := recipe.Get2("abra-test-recipe", offline)
r, err := recipe.Get("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.Get2("abra-test-recipe", offline)
r, err := recipe.Get("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.Get2("abra-test-recipe", offline)
r, err := recipe.Get("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.Get2("abra-test-recipe", offline)
r, err := recipe.Get("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.Get2("abra-test-recipe", offline)
r, err := recipe.Get("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.Get2("abra-test-recipe", offline)
r, err := recipe.Get("abra-test-recipe", offline)
if err != nil {
t.Fatal(err)
}

View File

@ -1,41 +1,35 @@
package git
import (
"fmt"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
gitPkg "github.com/go-git/go-git/v5"
"github.com/sirupsen/logrus"
)
// Init inits a new repo and commits all the stuff if you want
func Init(repoPath string, commit bool, gitName, gitEmail string) error {
if _, err := git.PlainInit(repoPath, false); err != nil {
return fmt.Errorf("git init: %s", err)
func Init(repoPath string, commit bool) error {
if _, err := gitPkg.PlainInit(repoPath, false); err != nil {
logrus.Fatal(err)
}
logrus.Debugf("initialised new git repo in %s", repoPath)
if commit {
commitRepo, err := git.PlainOpen(repoPath)
if err != nil {
return fmt.Errorf("git open: %s", err)
logrus.Fatal(err)
}
commitWorktree, err := commitRepo.Worktree()
if err != nil {
return fmt.Errorf("git worktree: %s", err)
logrus.Fatal(err)
}
if err := commitWorktree.AddWithOptions(&git.AddOptions{All: true}); err != nil {
return fmt.Errorf("git add: %s", err)
return err
}
var author *object.Signature
if gitName != "" && gitEmail != "" {
author = &object.Signature{Name: gitName, Email: gitEmail}
}
if _, err = commitWorktree.Commit("init", &git.CommitOptions{Author: author}); err != nil {
return fmt.Errorf("git commit: %s", err)
if _, err = commitWorktree.Commit("init", &git.CommitOptions{}); err != nil {
return err
}
logrus.Debugf("init committed all files for new git repo in %s", repoPath)
}

View File

@ -4,9 +4,11 @@ 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"
@ -14,9 +16,11 @@ import (
"github.com/sirupsen/logrus"
)
// GetHead retrieves latest HEAD metadata.
func GetHead(dir string) (*plumbing.Reference, error) {
repo, err := git.PlainOpen(dir)
// GetRecipeHead retrieves latest HEAD metadata.
func GetRecipeHead(recipeName string) (*plumbing.Reference, error) {
recipeDir := path.Join(config.RECIPES_DIR, recipeName)
repo, err := git.PlainOpen(recipeDir)
if err != nil {
return nil, err
}

View File

@ -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", recipe.Dir)
envSample := fmt.Sprintf("%s/%s/.env.sample", config.RECIPES_DIR, recipe.Name)
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(recipe.Dir, ".env.sample")
envSamplePath := path.Join(config.RECIPES_DIR, recipe.Name, ".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 := r.GetRecipeFeaturesAndCategory()
features, category, err := recipe.GetRecipeFeaturesAndCategory(r.Name)
if err != nil {
return false, err
}

View File

@ -3,7 +3,7 @@ package recipe
import (
"encoding/json"
"fmt"
"net/url"
"io/ioutil"
"os"
"path"
"path/filepath"
@ -130,10 +130,17 @@ 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
}
@ -142,16 +149,21 @@ 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", r.Dir, pattern)
fullPattern := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, r.Name, pattern)
if err := compose.UpdateLabel(fullPattern, serviceName, label, r.Name); err != nil {
return err
}
@ -160,7 +172,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/compose**yml", r.Dir)
pattern := fmt.Sprintf("%s/%s/compose**yml", config.RECIPES_DIR, r.Name)
image = formatter.StripTagMeta(image)
@ -176,7 +188,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
}
@ -198,51 +210,49 @@ func (r Recipe) Tags() ([]string, error) {
return tags, nil
}
// // 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
// Get retrieves a recipe.
func Get(recipeName string, offline bool) (Recipe, error) {
if err := EnsureExists(recipeName); err != nil {
return Recipe{}, err
}
pattern := fmt.Sprintf("%s/compose**yml", r.Dir)
pattern := fmt.Sprintf("%s/%s/compose**yml", config.RECIPES_DIR, recipeName)
composeFiles, err := filepath.Glob(pattern)
if err != nil {
return err
return Recipe{}, err
}
if len(composeFiles) == 0 {
return fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", r.Name)
return Recipe{}, fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", recipeName)
}
opts := stack.Deploy{Composefiles: composeFiles}
sampleEnv, err := r.SampleEnv()
envSamplePath := path.Join(config.RECIPES_DIR, recipeName, ".env.sample")
sampleEnv, err := config.ReadEnv(envSamplePath)
if err != nil {
return err
return Recipe{}, err
}
opts := stack.Deploy{Composefiles: composeFiles}
config, err := loader.LoadComposefile(opts, sampleEnv)
if err != nil {
return err
return Recipe{}, err
}
r.Config = config
return nil
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
}
func (r Recipe) SampleEnv() (map[string]string, error) {
@ -254,71 +264,33 @@ 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 (r Recipe) Ensure() error {
if err := r.EnsureExists(); err != nil {
func Ensure(recipeName string) error {
if err := EnsureExists(recipeName); err != nil {
return err
}
if err := r.EnsureUpToDate(); err != nil {
if err := EnsureUpToDate(recipeName); err != nil {
return err
}
if err := r.EnsureLatest(); err != nil {
if err := EnsureLatest(recipeName); err != nil {
return err
}
return 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 {
// 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 {
return err
}
}
if err := gitPkg.EnsureGitRepo(r.Dir); err != nil {
if err := gitPkg.EnsureGitRepo(recipeDir); err != nil {
return err
}
@ -326,12 +298,14 @@ func (r Recipe) EnsureExists() error {
}
// EnsureVersion checks whether a specific version exists for a recipe.
func (r Recipe) EnsureVersion(version string) error {
if err := gitPkg.EnsureGitRepo(r.Dir); err != nil {
func EnsureVersion(recipeName, version string) error {
recipeDir := path.Join(config.RECIPES_DIR, recipeName)
if err := gitPkg.EnsureGitRepo(recipeDir); err != nil {
return err
}
repo, err := git.PlainOpen(r.Dir)
repo, err := git.PlainOpen(recipeDir)
if err != nil {
return err
}
@ -355,11 +329,11 @@ func (r Recipe) EnsureVersion(version string) error {
joinedTags := strings.Join(parsedTags, ", ")
if joinedTags != "" {
logrus.Debugf("read %s as tags for recipe %s", joinedTags, r.Name)
logrus.Debugf("read %s as tags for recipe %s", joinedTags, recipeName)
}
if tagRef.String() == "" {
return fmt.Errorf("the local copy of %s doesn't seem to have version %s available?", r.Name, version)
return fmt.Errorf("the local copy of %s doesn't seem to have version %s available?", recipeName, version)
}
worktree, err := repo.Worktree()
@ -376,33 +350,37 @@ func (r Recipe) EnsureVersion(version string) error {
return err
}
logrus.Debugf("successfully checked %s out to %s in %s", r.Name, tagRef.Short(), r.Dir)
logrus.Debugf("successfully checked %s out to %s in %s", recipeName, tagRef.Short(), recipeDir)
return nil
}
// EnsureIsClean makes sure that the recipe repository has no unstaged changes.
func (r Recipe) EnsureIsClean() error {
isClean, err := gitPkg.IsClean(r.Dir)
func EnsureIsClean(recipeName string) error {
recipeDir := path.Join(config.RECIPES_DIR, recipeName)
isClean, err := gitPkg.IsClean(recipeDir)
if err != nil {
return fmt.Errorf("unable to check git clean status in %s: %s", r.Dir, err)
return fmt.Errorf("unable to check git clean status in %s: %s", recipeDir, err)
}
if !isClean {
msg := "%s (%s) has locally unstaged changes? please commit/remove your changes before proceeding"
return fmt.Errorf(msg, r.Name, r.Dir)
return fmt.Errorf(msg, recipeName, recipeDir)
}
return 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 {
// 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 {
return err
}
repo, err := git.PlainOpen(r.Dir)
repo, err := git.PlainOpen(recipeDir)
if err != nil {
return err
}
@ -412,7 +390,7 @@ func (r Recipe) EnsureLatest() error {
return err
}
branch, err := gitPkg.GetDefaultBranch(repo, r.Dir)
branch, err := gitPkg.GetDefaultBranch(repo, recipeDir)
if err != nil {
return err
}
@ -424,7 +402,7 @@ func (r Recipe) EnsureLatest() error {
}
if err := worktree.Checkout(checkOutOpts); err != nil {
logrus.Debugf("failed to check out %s in %s", branch, r.Dir)
logrus.Debugf("failed to check out %s in %s", branch, recipeDir)
return err
}
@ -432,17 +410,18 @@ func (r Recipe) EnsureLatest() error {
}
// ChaosVersion constructs a chaos mode recipe version.
func (r Recipe) ChaosVersion() (string, error) {
func ChaosVersion(recipeName string) (string, error) {
var version string
head, err := gitPkg.GetHead(r.Dir)
head, err := gitPkg.GetRecipeHead(recipeName)
if err != nil {
return version, err
}
version = formatter.SmallSHA(head.String())
isClean, err := gitPkg.IsClean(r.Dir)
recipeDir := path.Join(config.RECIPES_DIR, recipeName)
isClean, err := gitPkg.IsClean(recipeDir)
if err != nil {
return version, err
}
@ -485,22 +464,22 @@ func GetVersionLabelLocal(recipe Recipe) (string, error) {
return label, nil
}
func (r Recipe) GetRecipeFeaturesAndCategory() (Features, string, error) {
func GetRecipeFeaturesAndCategory(recipeName string) (Features, string, error) {
feat := Features{}
var category string
readmePath := path.Join(r.Dir, "README.md")
readmePath := path.Join(config.RECIPES_DIR, recipeName, "README.md")
logrus.Debugf("attempting to open %s for recipe metadata parsing", readmePath)
readmeFS, err := os.ReadFile(readmePath)
readmeFS, err := ioutil.ReadFile(readmePath)
if err != nil {
return feat, category, err
}
readmeMetadata, err := GetStringInBetween( // Find text between delimiters
r.Name,
recipeName,
string(readmeFS),
"<!-- metadata -->", "<!-- endmetadata -->",
)
@ -551,7 +530,7 @@ func (r Recipe) GetRecipeFeaturesAndCategory() (Features, string, error) {
if strings.Contains(val, "**Image**") {
imageMetadata, err := GetImageMetadata(strings.TrimSpace(
strings.TrimPrefix(val, "* **Image**:"),
), r.Name)
), recipeName)
if err != nil {
continue
}
@ -618,36 +597,38 @@ func GetStringInBetween(recipeName, str, start, end string) (result string, err
}
// EnsureUpToDate ensures that the local repo is synced to the remote
func (r Recipe) EnsureUpToDate() error {
repo, err := git.PlainOpen(r.Dir)
func EnsureUpToDate(recipeName string) error {
recipeDir := path.Join(config.RECIPES_DIR, recipeName)
repo, err := git.PlainOpen(recipeDir)
if err != nil {
return fmt.Errorf("unable to open %s: %s", r.Dir, err)
return fmt.Errorf("unable to open %s: %s", recipeDir, err)
}
remotes, err := repo.Remotes()
if err != nil {
return fmt.Errorf("unable to read remotes in %s: %s", r.Dir, err)
return fmt.Errorf("unable to read remotes in %s: %s", recipeDir, err)
}
if len(remotes) == 0 {
logrus.Debugf("cannot ensure %s is up-to-date, no git remotes configured", r.Name)
logrus.Debugf("cannot ensure %s is up-to-date, no git remotes configured", recipeName)
return nil
}
worktree, err := repo.Worktree()
if err != nil {
return fmt.Errorf("unable to open git work tree in %s: %s", r.Dir, err)
return fmt.Errorf("unable to open git work tree in %s: %s", recipeDir, err)
}
branch, err := gitPkg.CheckoutDefaultBranch(repo, r.Dir)
branch, err := gitPkg.CheckoutDefaultBranch(repo, recipeDir)
if err != nil {
return fmt.Errorf("unable to check out default branch in %s: %s", r.Dir, err)
return fmt.Errorf("unable to check out default branch in %s: %s", recipeDir, 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", r.Dir, err)
return fmt.Errorf("unable to fetch tags in %s: %s", recipeDir, err)
}
}
@ -659,11 +640,11 @@ func (r Recipe) EnsureUpToDate() 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", r.Dir, err)
return fmt.Errorf("unable to git pull in %s: %s", recipeDir, err)
}
}
logrus.Debugf("fetched latest git changes for %s", r.Name)
logrus.Debugf("fetched latest git changes for %s", recipeName)
return nil
}
@ -691,7 +672,7 @@ func ReadRecipeCatalogue(offline bool) (RecipeCatalogue, error) {
// readRecipeCatalogueFS reads the catalogue from the file system.
func readRecipeCatalogueFS(target interface{}) error {
recipesJSONFS, err := os.ReadFile(config.RECIPES_JSON)
recipesJSONFS, err := ioutil.ReadFile(config.RECIPES_JSON)
if err != nil {
return err
}
@ -743,20 +724,20 @@ func (r RecipeMissingFromCatalogue) Error() string {
}
// GetRecipeMeta retrieves the recipe metadata from the recipe catalogue.
func (r Recipe) GetRecipeMeta(offline bool) (RecipeMeta, error) {
func GetRecipeMeta(recipeName string, offline bool) (RecipeMeta, error) {
catl, err := ReadRecipeCatalogue(offline)
if err != nil {
return RecipeMeta{}, err
}
recipeMeta, ok := catl[r.Name]
recipeMeta, ok := catl[recipeName]
if !ok {
return RecipeMeta{}, RecipeMissingFromCatalogue{
err: fmt.Sprintf("recipe %s does not exist?", r.Name),
err: fmt.Sprintf("recipe %s does not exist?", recipeName),
}
}
logrus.Debugf("recipe metadata retrieved for %s", r.Name)
logrus.Debugf("recipe metadata retrieved for %s", recipeName)
return recipeMeta, nil
}
@ -883,12 +864,13 @@ func ReadReposMetadata() (RepoCatalogue, error) {
}
// GetRecipeVersions retrieves all recipe versions.
func (r Recipe) GetVersions(offline bool) (RecipeVersions, error) {
func GetRecipeVersions(recipeName string, offline bool) (RecipeVersions, error) {
versions := RecipeVersions{}
recipeDir := path.Join(config.RECIPES_DIR, recipeName)
logrus.Debugf("attempting to open git repository in %s", r.Dir)
logrus.Debugf("attempting to open git repository in %s", recipeDir)
repo, err := git.PlainOpen(r.Dir)
repo, err := git.PlainOpen(recipeDir)
if err != nil {
return versions, err
}
@ -906,7 +888,7 @@ func (r Recipe) GetVersions(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, r.Name)
logrus.Debugf("processing %s for %s", tag, recipeName)
checkOutOpts := &git.CheckoutOptions{
Create: false,
@ -914,18 +896,19 @@ func (r Recipe) GetVersions(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, r.Dir)
logrus.Debugf("failed to check out %s in %s", tag, recipeDir)
return err
}
logrus.Debugf("successfully checked out %s in %s", ref.Name(), r.Dir)
logrus.Debugf("successfully checked out %s in %s", ref.Name(), recipeDir)
if err := r.LoadConfig(); err != nil {
recipe, err := Get(recipeName, offline)
if err != nil {
return err
}
versionMeta := make(map[string]ServiceMeta)
for _, service := range r.Config.Services {
for _, service := range recipe.Config.Services {
img, err := reference.ParseNormalizedNamed(service.Image)
if err != nil {
@ -958,14 +941,14 @@ func (r Recipe) GetVersions(offline bool) (RecipeVersions, error) {
return versions, err
}
_, err = gitPkg.CheckoutDefaultBranch(repo, r.Dir)
_, err = gitPkg.CheckoutDefaultBranch(repo, recipeDir)
if err != nil {
return versions, err
}
sortRecipeVersions(versions)
logrus.Debugf("collected %s for %s", versions, r.Name)
logrus.Debugf("collected %s for %s", versions, recipeName)
return versions, nil
}

View File

@ -8,7 +8,7 @@ import (
func TestGetVersionLabelLocalDoesNotUseTimeoutLabel(t *testing.T) {
offline := true
recipe, err := Get2("traefik", offline)
recipe, err := Get("traefik", offline)
if err != nil {
t.Fatal(err)
}

View File

@ -50,7 +50,9 @@ teardown(){
assert_success
assert_exists "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
assert_equal $(_get_tag_hash 0.1.1+1.20.2) $(_get_current_hash)
_get_tag_hash 0.1.1+1.20.2
_get_current_hash
assert_equal "$tagHash" "$currentHash"
}
@test "does not overwrite existing env files" {
@ -111,12 +113,13 @@ teardown(){
@test "ensure recipe up to date if no --offline" {
_reset_recipe
wantHash=$(_get_n_hash 3)
_get_n_hash 3
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" reset --hard HEAD~3
assert_success
assert_equal $(_get_current_hash) "$wantHash"
_get_current_hash
assert_equal "$currentHash" "$nHash"
run $ABRA app new "$TEST_RECIPE" \
--no-input \
@ -125,19 +128,22 @@ teardown(){
assert_success
assert_exists "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
assert_equal $(_get_head_hash) $(_get_current_hash)
_get_head_hash
_get_current_hash
assert_equal "$HEAD_HASH" "$CURRENT_HASH"
_reset_recipe
}
@test "ensure recipe not up to date if --offline" {
_reset_recipe
wantHash=$(_get_n_hash 3)
_get_n_hash 3
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" reset --hard HEAD~3
assert_success
assert_equal $(_get_current_hash) "$wantHash"
_get_current_hash
assert_equal "$currentHash" "$nHash"
# NOTE(d1): need to use --chaos to force same commit
run $ABRA app new "$TEST_RECIPE" \
@ -149,7 +155,8 @@ teardown(){
assert_success
assert_exists "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
assert_equal $(_get_current_hash) "$wantHash"
_get_current_hash
assert_equal "$currentHash" "$nHash"
_reset_recipe
}

View File

@ -48,23 +48,19 @@ _git_commit() {
_get_tag_hash() {
tagHash=$(git -C "$ABRA_DIR/recipes/$TEST_RECIPE" rev-list -n 1 "$1")
assert_success
echo "$tagHash"
}
_get_head_hash() {
headHash=$(git -C "$ABRA_DIR/recipes/$TEST_RECIPE" show -s --format="%H" HEAD)
assert_success
echo "$headHash"
}
_get_current_hash() {
currentHash=$(git -C "$ABRA_DIR/recipes/$TEST_RECIPE" show -s --format="%H")
assert_success
echo "$currentHash"
}
_get_n_hash() {
nHash=$(git -C "$ABRA_DIR/recipes/$TEST_RECIPE" show -s --format="%H" "HEAD~$1")
assert_success
echo "$nHash"
}

View File

@ -40,16 +40,3 @@ teardown(){
assert_success
assert_output --partial 'A new foobar app has been created!'
}
@test "create new recipe with git credentials" {
run $ABRA recipe new foobar --git-name fooUser --git-email foo@example.com
assert_success
assert_output --partial 'Your new foobar recipe has been created'
assert_exists "$ABRA_DIR/recipes/foobar"
run bash -c 'git -C "$ABRA_DIR/recipes/foobar" log -n 1'
assert_success
assert_output --partial 'fooUser'
assert_output --partial 'foo@example.com'
}