forked from toolshed/abra
		
	refactor(recipe): introduce new recipe struct and move some methods
This commit is contained in:
		@ -47,22 +47,23 @@ var appBackupListCommand = cli.Command{
 | 
				
			|||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							r := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipe.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -109,23 +110,24 @@ var appBackupDownloadCommand = cli.Command{
 | 
				
			|||||||
	BashComplete: autocomplete.AppNameComplete,
 | 
						BashComplete: autocomplete.AppNameComplete,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipe.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -179,23 +181,24 @@ var appBackupCreateCommand = cli.Command{
 | 
				
			|||||||
	BashComplete: autocomplete.AppNameComplete,
 | 
						BashComplete: autocomplete.AppNameComplete,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipe.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -237,23 +240,24 @@ var appBackupSnapshotsCommand = cli.Command{
 | 
				
			|||||||
	BashComplete: autocomplete.AppNameComplete,
 | 
						BashComplete: autocomplete.AppNameComplete,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipe.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,6 @@ import (
 | 
				
			|||||||
	"coopcloud.tech/abra/pkg/formatter"
 | 
						"coopcloud.tech/abra/pkg/formatter"
 | 
				
			||||||
	"coopcloud.tech/abra/pkg/log"
 | 
						"coopcloud.tech/abra/pkg/log"
 | 
				
			||||||
	"coopcloud.tech/abra/pkg/recipe"
 | 
						"coopcloud.tech/abra/pkg/recipe"
 | 
				
			||||||
	recipePkg "coopcloud.tech/abra/pkg/recipe"
 | 
					 | 
				
			||||||
	"github.com/urfave/cli"
 | 
						"github.com/urfave/cli"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -37,23 +36,24 @@ ${FOO:<default>} syntax). "check" does not confirm or deny this for you.`,
 | 
				
			|||||||
	BashComplete: autocomplete.AppNameComplete,
 | 
						BashComplete: autocomplete.AppNameComplete,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipePkg.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipePkg.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,6 @@ import (
 | 
				
			|||||||
	"coopcloud.tech/abra/pkg/config"
 | 
						"coopcloud.tech/abra/pkg/config"
 | 
				
			||||||
	"coopcloud.tech/abra/pkg/log"
 | 
						"coopcloud.tech/abra/pkg/log"
 | 
				
			||||||
	"coopcloud.tech/abra/pkg/recipe"
 | 
						"coopcloud.tech/abra/pkg/recipe"
 | 
				
			||||||
	recipePkg "coopcloud.tech/abra/pkg/recipe"
 | 
					 | 
				
			||||||
	"github.com/urfave/cli"
 | 
						"github.com/urfave/cli"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -60,23 +59,24 @@ Example:
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipePkg.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipePkg.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -228,23 +228,24 @@ var appCmdListCommand = cli.Command{
 | 
				
			|||||||
	Before:       internal.SubCommandBefore,
 | 
						Before:       internal.SubCommandBefore,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipePkg.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipePkg.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipePkg.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -52,28 +52,29 @@ recipes.
 | 
				
			|||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
		stackName := app.StackName()
 | 
							stackName := app.StackName()
 | 
				
			||||||
 | 
							r2 := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		specificVersion := c.Args().Get(1)
 | 
							specificVersion := c.Args().Get(1)
 | 
				
			||||||
		if specificVersion != "" && internal.Chaos {
 | 
							if specificVersion != "" && internal.Chaos {
 | 
				
			||||||
			log.Fatal("cannot use <version> and --chaos together")
 | 
								log.Fatal("cannot use <version> and --chaos together")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r2.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r2.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r2.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipe.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r2.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -107,7 +108,7 @@ recipes.
 | 
				
			|||||||
		if specificVersion != "" {
 | 
							if specificVersion != "" {
 | 
				
			||||||
			version = specificVersion
 | 
								version = specificVersion
 | 
				
			||||||
			log.Debugf("choosing %s as version to deploy", version)
 | 
								log.Debugf("choosing %s as version to deploy", version)
 | 
				
			||||||
			if err := recipe.EnsureVersion(app.Recipe, version); err != nil {
 | 
								if err := r2.EnsureVersion(version); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -157,7 +158,7 @@ recipes.
 | 
				
			|||||||
			if len(versions) > 0 && !internal.Chaos {
 | 
								if len(versions) > 0 && !internal.Chaos {
 | 
				
			||||||
				version = versions[len(versions)-1]
 | 
									version = versions[len(versions)-1]
 | 
				
			||||||
				log.Debugf("choosing %s as version to deploy", version)
 | 
									log.Debugf("choosing %s as version to deploy", version)
 | 
				
			||||||
				if err := recipe.EnsureVersion(app.Recipe, version); err != nil {
 | 
									if err := r2.EnsureVersion(version); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
@ -173,7 +174,7 @@ recipes.
 | 
				
			|||||||
		if internal.Chaos {
 | 
							if internal.Chaos {
 | 
				
			||||||
			log.Warnf("chaos mode engaged")
 | 
								log.Warnf("chaos mode engaged")
 | 
				
			||||||
			var err error
 | 
								var err error
 | 
				
			||||||
			version, err = recipe.ChaosVersion(app.Recipe)
 | 
								version, err = r2.ChaosVersion()
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
				
			|||||||
@ -38,8 +38,9 @@ var appLogsCommand = cli.Command{
 | 
				
			|||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
		stackName := app.StackName()
 | 
							stackName := app.StackName()
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -67,13 +67,14 @@ var appNewCommand = cli.Command{
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		recipe := internal.ValidateRecipe(c)
 | 
							recipe := internal.ValidateRecipe(c)
 | 
				
			||||||
 | 
							r := recipePkg.Get2(recipe.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipePkg.EnsureIsClean(recipe.Name); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -93,16 +94,16 @@ var appNewCommand = cli.Command{
 | 
				
			|||||||
						version = tag
 | 
											version = tag
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if err := recipePkg.EnsureVersion(recipe.Name, version); err != nil {
 | 
										if err := r.EnsureVersion(version); err != nil {
 | 
				
			||||||
						log.Fatal(err)
 | 
											log.Fatal(err)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					if err := recipePkg.EnsureLatest(recipe.Name); err != nil {
 | 
										if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
						log.Fatal(err)
 | 
											log.Fatal(err)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				if err := recipePkg.EnsureVersion(recipe.Name, c.Args().Get(1)); err != nil {
 | 
									if err := r.EnsureVersion(c.Args().Get(1)); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
				
			|||||||
@ -35,6 +35,7 @@ var appPsCommand = cli.Command{
 | 
				
			|||||||
	BashComplete: autocomplete.AppNameComplete,
 | 
						BashComplete: autocomplete.AppNameComplete,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		cl, err := client.New(app.Server)
 | 
							cl, err := client.New(app.Server)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@ -53,7 +54,7 @@ var appPsCommand = cli.Command{
 | 
				
			|||||||
		statuses, err := appPkg.GetAppStatuses([]appPkg.App{app}, true)
 | 
							statuses, err := appPkg.GetAppStatuses([]appPkg.App{app}, true)
 | 
				
			||||||
		if statusMeta, ok := statuses[app.StackName()]; ok {
 | 
							if statusMeta, ok := statuses[app.StackName()]; ok {
 | 
				
			||||||
			if _, exists := statusMeta["chaos"]; !exists {
 | 
								if _, exists := statusMeta["chaos"]; !exists {
 | 
				
			||||||
				if err := recipe.EnsureVersion(app.Recipe, deployedVersion); err != nil {
 | 
									if err := r.EnsureVersion(deployedVersion); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
				
			|||||||
@ -32,23 +32,24 @@ var appRestoreCommand = cli.Command{
 | 
				
			|||||||
	BashComplete: autocomplete.AppNameComplete,
 | 
						BashComplete: autocomplete.AppNameComplete,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipe.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -52,28 +52,29 @@ recipes.
 | 
				
			|||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
		stackName := app.StackName()
 | 
							stackName := app.StackName()
 | 
				
			||||||
 | 
							r2 := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		specificVersion := c.Args().Get(1)
 | 
							specificVersion := c.Args().Get(1)
 | 
				
			||||||
		if specificVersion != "" && internal.Chaos {
 | 
							if specificVersion != "" && internal.Chaos {
 | 
				
			||||||
			log.Fatal("cannot use <version> and --chaos together")
 | 
								log.Fatal("cannot use <version> and --chaos together")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r2.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r2.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r2.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipe.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r2.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -185,7 +186,7 @@ recipes.
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureVersion(app.Recipe, chosenDowngrade); err != nil {
 | 
								if err := r2.EnsureVersion(chosenDowngrade); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -193,7 +194,7 @@ recipes.
 | 
				
			|||||||
		if internal.Chaos {
 | 
							if internal.Chaos {
 | 
				
			||||||
			log.Warn("chaos mode engaged")
 | 
								log.Warn("chaos mode engaged")
 | 
				
			||||||
			var err error
 | 
								var err error
 | 
				
			||||||
			chosenDowngrade, err = recipe.ChaosVersion(app.Recipe)
 | 
								chosenDowngrade, err = r2.ChaosVersion()
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
				
			|||||||
@ -56,23 +56,24 @@ var appSecretGenerateCommand = cli.Command{
 | 
				
			|||||||
	BashComplete: autocomplete.AppNameComplete,
 | 
						BashComplete: autocomplete.AppNameComplete,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipe.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -263,23 +264,24 @@ Example:
 | 
				
			|||||||
`,
 | 
					`,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipe.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -371,23 +373,24 @@ var appSecretLsCommand = cli.Command{
 | 
				
			|||||||
	BashComplete: autocomplete.AppNameComplete,
 | 
						BashComplete: autocomplete.AppNameComplete,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Recipe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipe.EnsureExists(app.Recipe); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipe.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -58,6 +58,7 @@ recipes.
 | 
				
			|||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		app := internal.ValidateApp(c)
 | 
							app := internal.ValidateApp(c)
 | 
				
			||||||
		stackName := app.StackName()
 | 
							stackName := app.StackName()
 | 
				
			||||||
 | 
							r := recipe.Get2(app.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		specificVersion := c.Args().Get(1)
 | 
							specificVersion := c.Args().Get(1)
 | 
				
			||||||
		if specificVersion != "" && internal.Chaos {
 | 
							if specificVersion != "" && internal.Chaos {
 | 
				
			||||||
@ -65,17 +66,17 @@ recipes.
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipe.EnsureIsClean(app.Recipe); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipe.EnsureUpToDate(app.Recipe); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipe.EnsureLatest(app.Recipe); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -219,7 +220,7 @@ recipes.
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipePkg.EnsureVersion(app.Recipe, chosenUpgrade); err != nil {
 | 
								if err := r.EnsureVersion(chosenUpgrade); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -227,7 +228,7 @@ recipes.
 | 
				
			|||||||
		if internal.Chaos {
 | 
							if internal.Chaos {
 | 
				
			||||||
			log.Warn("chaos mode engaged")
 | 
								log.Warn("chaos mode engaged")
 | 
				
			||||||
			var err error
 | 
								var err error
 | 
				
			||||||
			chosenUpgrade, err = recipePkg.ChaosVersion(app.Recipe)
 | 
								chosenUpgrade, err = r.ChaosVersion()
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
				
			|||||||
@ -24,9 +24,10 @@ var recipeFetchCommand = cli.Command{
 | 
				
			|||||||
	BashComplete: autocomplete.RecipeNameComplete,
 | 
						BashComplete: autocomplete.RecipeNameComplete,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		recipeName := c.Args().First()
 | 
							recipeName := c.Args().First()
 | 
				
			||||||
 | 
							r := recipe.Get2(recipeName)
 | 
				
			||||||
		if recipeName != "" {
 | 
							if recipeName != "" {
 | 
				
			||||||
			internal.ValidateRecipe(c)
 | 
								internal.ValidateRecipe(c)
 | 
				
			||||||
			if err := recipe.Ensure(recipeName); err != nil {
 | 
								if err := r.Ensure(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
@ -39,7 +40,8 @@ var recipeFetchCommand = cli.Command{
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		catlBar := formatter.CreateProgressbar(len(catalogue), "fetching latest recipes...")
 | 
							catlBar := formatter.CreateProgressbar(len(catalogue), "fetching latest recipes...")
 | 
				
			||||||
		for recipeName := range catalogue {
 | 
							for recipeName := range catalogue {
 | 
				
			||||||
			if err := recipe.Ensure(recipeName); err != nil {
 | 
								r := recipe.Get2(recipeName)
 | 
				
			||||||
 | 
								if err := r.Ensure(); err != nil {
 | 
				
			||||||
				log.Error(err)
 | 
									log.Error(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			catlBar.Add(1)
 | 
								catlBar.Add(1)
 | 
				
			||||||
 | 
				
			|||||||
@ -28,23 +28,24 @@ var recipeLintCommand = cli.Command{
 | 
				
			|||||||
	BashComplete: autocomplete.RecipeNameComplete,
 | 
						BashComplete: autocomplete.RecipeNameComplete,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		recipe := internal.ValidateRecipe(c)
 | 
							recipe := internal.ValidateRecipe(c)
 | 
				
			||||||
 | 
							r := recipePkg.Get2(recipe.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipePkg.EnsureExists(recipe.Name); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !internal.Chaos {
 | 
							if !internal.Chaos {
 | 
				
			||||||
			if err := recipePkg.EnsureIsClean(recipe.Name); err != nil {
 | 
								if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if !internal.Offline {
 | 
								if !internal.Offline {
 | 
				
			||||||
				if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil {
 | 
									if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
					log.Fatal(err)
 | 
										log.Fatal(err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := recipePkg.EnsureLatest(recipe.Name); err != nil {
 | 
								if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
				log.Fatal(err)
 | 
									log.Fatal(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -72,20 +72,21 @@ You may invoke this command in "wizard" mode and be prompted for input:
 | 
				
			|||||||
	BashComplete: autocomplete.RecipeNameComplete,
 | 
						BashComplete: autocomplete.RecipeNameComplete,
 | 
				
			||||||
	Action: func(c *cli.Context) error {
 | 
						Action: func(c *cli.Context) error {
 | 
				
			||||||
		recipe := internal.ValidateRecipe(c)
 | 
							recipe := internal.ValidateRecipe(c)
 | 
				
			||||||
 | 
							r := recipePkg.Get2(recipe.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipePkg.EnsureIsClean(recipe.Name); err != nil {
 | 
							if err := r.EnsureIsClean(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipePkg.EnsureExists(recipe.Name); err != nil {
 | 
							if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil {
 | 
							if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := recipePkg.EnsureLatest(recipe.Name); err != nil {
 | 
							if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
			log.Fatal(err)
 | 
								log.Fatal(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -318,20 +318,20 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// processRecipeRepoVersion clones, pulls, checks out the version and lints the
 | 
					// processRecipeRepoVersion clones, pulls, checks out the version and lints the
 | 
				
			||||||
// recipe repository.
 | 
					// recipe repository.
 | 
				
			||||||
func processRecipeRepoVersion(recipeName, version string) error {
 | 
					func processRecipeRepoVersion(r recipe.Recipe2, version string) error {
 | 
				
			||||||
	if err := recipe.EnsureExists(recipeName); err != nil {
 | 
						if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := recipe.EnsureUpToDate(recipeName); err != nil {
 | 
						if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := recipe.EnsureVersion(recipeName, version); err != nil {
 | 
						if err := r.EnsureVersion(version); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if r, err := recipe.Get(recipeName, internal.Offline); err != nil {
 | 
						if r, err := recipe.Get(r.Name, internal.Offline); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	} else if err := lint.LintForErrors(r); err != nil {
 | 
						} else if err := lint.LintForErrors(r); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@ -445,7 +445,9 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName,
 | 
				
			|||||||
		Env:    env,
 | 
							Env:    env,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = processRecipeRepoVersion(recipeName, upgradeVersion); err != nil {
 | 
						r := recipe.Get2(recipeName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = processRecipeRepoVersion(r, upgradeVersion); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -213,21 +213,22 @@ func (r Recipe) Tags() ([]string, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Get retrieves a recipe.
 | 
					// Get retrieves a recipe.
 | 
				
			||||||
func Get(recipeName string, offline bool) (Recipe, error) {
 | 
					func Get(recipeName string, offline bool) (Recipe, error) {
 | 
				
			||||||
	if err := EnsureExists(recipeName); err != nil {
 | 
						r := Get2(recipeName)
 | 
				
			||||||
 | 
						if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
		return Recipe{}, err
 | 
							return Recipe{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pattern := fmt.Sprintf("%s/%s/compose**yml", config.RECIPES_DIR, recipeName)
 | 
						pattern := fmt.Sprintf("%s/%s/compose**yml", config.RECIPES_DIR, r.Name)
 | 
				
			||||||
	composeFiles, err := filepath.Glob(pattern)
 | 
						composeFiles, err := filepath.Glob(pattern)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return Recipe{}, err
 | 
							return Recipe{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(composeFiles) == 0 {
 | 
						if len(composeFiles) == 0 {
 | 
				
			||||||
		return Recipe{}, fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", recipeName)
 | 
							return Recipe{}, fmt.Errorf("%s is missing a compose.yml or compose.*.yml file?", r.Name)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	envSamplePath := path.Join(config.RECIPES_DIR, recipeName, ".env.sample")
 | 
						envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample")
 | 
				
			||||||
	sampleEnv, err := envfile.ReadEnv(envSamplePath)
 | 
						sampleEnv, err := envfile.ReadEnv(envSamplePath)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return Recipe{}, err
 | 
							return Recipe{}, err
 | 
				
			||||||
@ -239,7 +240,7 @@ func Get(recipeName string, offline bool) (Recipe, error) {
 | 
				
			|||||||
		return Recipe{}, err
 | 
							return Recipe{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	meta, err := GetRecipeMeta(recipeName, offline)
 | 
						meta, err := GetRecipeMeta(r.Name, offline)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		switch err.(type) {
 | 
							switch err.(type) {
 | 
				
			||||||
		case RecipeMissingFromCatalogue:
 | 
							case RecipeMissingFromCatalogue:
 | 
				
			||||||
@ -265,27 +266,35 @@ func (r Recipe) SampleEnv() (map[string]string, error) {
 | 
				
			|||||||
	return sampleEnv, nil
 | 
						return sampleEnv, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Get2(name string) Recipe2 {
 | 
				
			||||||
 | 
						return Recipe2{Name: name}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Recipe2 struct {
 | 
				
			||||||
 | 
						Name string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Ensure makes sure the recipe exists, is up to date and has the latest version checked out.
 | 
					// Ensure makes sure the recipe exists, is up to date and has the latest version checked out.
 | 
				
			||||||
func Ensure(recipeName string) error {
 | 
					func (r Recipe2) Ensure() error {
 | 
				
			||||||
	if err := EnsureExists(recipeName); err != nil {
 | 
						if err := r.EnsureExists(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := EnsureUpToDate(recipeName); err != nil {
 | 
						if err := r.EnsureUpToDate(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := EnsureLatest(recipeName); err != nil {
 | 
						if err := r.EnsureLatest(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EnsureExists ensures that a recipe is locally cloned
 | 
					// EnsureExists ensures that the recipe is locally cloned
 | 
				
			||||||
func EnsureExists(recipeName string) error {
 | 
					func (r Recipe2) EnsureExists() error {
 | 
				
			||||||
	recipeDir := path.Join(config.RECIPES_DIR, recipeName)
 | 
						recipeDir := path.Join(config.RECIPES_DIR, r.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, err := os.Stat(recipeDir); os.IsNotExist(err) {
 | 
						if _, err := os.Stat(recipeDir); os.IsNotExist(err) {
 | 
				
			||||||
		log.Debugf("%s does not exist, attemmpting to clone", recipeDir)
 | 
							log.Debugf("%s does not exist, attemmpting to clone", recipeDir)
 | 
				
			||||||
		url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, recipeName)
 | 
							url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, r.Name)
 | 
				
			||||||
		if err := gitPkg.Clone(recipeDir, url); err != nil {
 | 
							if err := gitPkg.Clone(recipeDir, url); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -299,8 +308,8 @@ func EnsureExists(recipeName string) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EnsureVersion checks whether a specific version exists for a recipe.
 | 
					// EnsureVersion checks whether a specific version exists for a recipe.
 | 
				
			||||||
func EnsureVersion(recipeName, version string) error {
 | 
					func (r Recipe2) EnsureVersion(version string) error {
 | 
				
			||||||
	recipeDir := path.Join(config.RECIPES_DIR, recipeName)
 | 
						recipeDir := path.Join(config.RECIPES_DIR, r.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := gitPkg.EnsureGitRepo(recipeDir); err != nil {
 | 
						if err := gitPkg.EnsureGitRepo(recipeDir); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@ -330,11 +339,11 @@ func EnsureVersion(recipeName, version string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	joinedTags := strings.Join(parsedTags, ", ")
 | 
						joinedTags := strings.Join(parsedTags, ", ")
 | 
				
			||||||
	if joinedTags != "" {
 | 
						if joinedTags != "" {
 | 
				
			||||||
		log.Debugf("read %s as tags for recipe %s", joinedTags, recipeName)
 | 
							log.Debugf("read %s as tags for recipe %s", joinedTags, r.Name)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if tagRef.String() == "" {
 | 
						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()
 | 
						worktree, err := repo.Worktree()
 | 
				
			||||||
@ -351,14 +360,14 @@ func EnsureVersion(recipeName, version string) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Debugf("successfully checked %s out to %s in %s", recipeName, tagRef.Short(), recipeDir)
 | 
						log.Debugf("successfully checked %s out to %s in %s", r.Name, tagRef.Short(), recipeDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EnsureIsClean makes sure that the recipe repository has no unstaged changes.
 | 
					// EnsureIsClean makes sure that the recipe repository has no unstaged changes.
 | 
				
			||||||
func EnsureIsClean(recipeName string) error {
 | 
					func (r Recipe2) EnsureIsClean() error {
 | 
				
			||||||
	recipeDir := path.Join(config.RECIPES_DIR, recipeName)
 | 
						recipeDir := path.Join(config.RECIPES_DIR, r.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	isClean, err := gitPkg.IsClean(recipeDir)
 | 
						isClean, err := gitPkg.IsClean(recipeDir)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -367,15 +376,15 @@ func EnsureIsClean(recipeName string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if !isClean {
 | 
						if !isClean {
 | 
				
			||||||
		msg := "%s (%s) has locally unstaged changes? please commit/remove your changes before proceeding"
 | 
							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, recipeDir)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EnsureLatest makes sure the latest commit is checked out for a local recipe repository
 | 
					// EnsureLatest makes sure the latest commit is checked out for the local recipe repository
 | 
				
			||||||
func EnsureLatest(recipeName string) error {
 | 
					func (r Recipe2) EnsureLatest() error {
 | 
				
			||||||
	recipeDir := path.Join(config.RECIPES_DIR, recipeName)
 | 
						recipeDir := path.Join(config.RECIPES_DIR, r.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := gitPkg.EnsureGitRepo(recipeDir); err != nil {
 | 
						if err := gitPkg.EnsureGitRepo(recipeDir); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@ -410,18 +419,71 @@ func EnsureLatest(recipeName string) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EnsureUpToDate ensures that the local repo is synced to the remote
 | 
				
			||||||
 | 
					func (r Recipe2) EnsureUpToDate() error {
 | 
				
			||||||
 | 
						recipeDir := path.Join(config.RECIPES_DIR, r.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						repo, err := git.PlainOpen(recipeDir)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							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", recipeDir, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(remotes) == 0 {
 | 
				
			||||||
 | 
							log.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)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						branch, err := gitPkg.CheckoutDefaultBranch(repo, recipeDir)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							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", recipeDir, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opts := &git.PullOptions{
 | 
				
			||||||
 | 
							Force:         true,
 | 
				
			||||||
 | 
							ReferenceName: branch,
 | 
				
			||||||
 | 
							SingleBranch:  true,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Debugf("fetched latest git changes for %s", r.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ChaosVersion constructs a chaos mode recipe version.
 | 
					// ChaosVersion constructs a chaos mode recipe version.
 | 
				
			||||||
func ChaosVersion(recipeName string) (string, error) {
 | 
					func (r Recipe2) ChaosVersion() (string, error) {
 | 
				
			||||||
	var version string
 | 
						var version string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	head, err := gitPkg.GetRecipeHead(recipeName)
 | 
						head, err := gitPkg.GetRecipeHead(r.Name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return version, err
 | 
							return version, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	version = formatter.SmallSHA(head.String())
 | 
						version = formatter.SmallSHA(head.String())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	recipeDir := path.Join(config.RECIPES_DIR, recipeName)
 | 
						recipeDir := path.Join(config.RECIPES_DIR, r.Name)
 | 
				
			||||||
	isClean, err := gitPkg.IsClean(recipeDir)
 | 
						isClean, err := gitPkg.IsClean(recipeDir)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return version, err
 | 
							return version, err
 | 
				
			||||||
@ -597,59 +659,6 @@ func GetStringInBetween(recipeName, str, start, end string) (result string, err
 | 
				
			|||||||
	return str[s : s+e], nil
 | 
						return str[s : s+e], nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		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", recipeDir, err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if len(remotes) == 0 {
 | 
					 | 
				
			||||||
		log.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", recipeDir, err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	branch, err := gitPkg.CheckoutDefaultBranch(repo, recipeDir)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		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", recipeDir, err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	opts := &git.PullOptions{
 | 
					 | 
				
			||||||
		Force:         true,
 | 
					 | 
				
			||||||
		ReferenceName: branch,
 | 
					 | 
				
			||||||
		SingleBranch:  true,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	log.Debugf("fetched latest git changes for %s", recipeName)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ReadRecipeCatalogue reads the recipe catalogue.
 | 
					// ReadRecipeCatalogue reads the recipe catalogue.
 | 
				
			||||||
func ReadRecipeCatalogue(offline bool) (RecipeCatalogue, error) {
 | 
					func ReadRecipeCatalogue(offline bool) (RecipeCatalogue, error) {
 | 
				
			||||||
	recipes := make(RecipeCatalogue)
 | 
						recipes := make(RecipeCatalogue)
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user