Compare commits
	
		
			2 Commits
		
	
	
		
			0.7.0-beta
			...
			prune
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0d8191bc3e | |||
| 20cdfe7a72 | 
| @ -5,12 +5,9 @@ | ||||
|  | ||||
| - 3wordchant | ||||
| - cassowary | ||||
| - codegod100 | ||||
| - decentral1se | ||||
| - frando | ||||
| - kawaiipunk | ||||
| - knoflook | ||||
| - moritz | ||||
| - roxxers | ||||
| - vera | ||||
| - yksflip | ||||
|  | ||||
| @ -53,7 +53,7 @@ recipes. | ||||
| 		conf := runtime.New() | ||||
|  | ||||
| 		if !internal.Chaos { | ||||
| 			if err := recipe.EnsureUpToDate(app.Recipe, conf); err != nil { | ||||
| 			if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | ||||
| 				logrus.Fatal(err) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @ -8,11 +8,8 @@ import ( | ||||
| 	"coopcloud.tech/abra/cli/internal" | ||||
| 	"coopcloud.tech/abra/pkg/autocomplete" | ||||
| 	"coopcloud.tech/abra/pkg/client" | ||||
| 	"coopcloud.tech/abra/pkg/config" | ||||
| 	"coopcloud.tech/abra/pkg/formatter" | ||||
| 	stack "coopcloud.tech/abra/pkg/upstream/stack" | ||||
| 	"github.com/docker/docker/api/types/filters" | ||||
| 	dockerClient "github.com/docker/docker/client" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/urfave/cli" | ||||
| ) | ||||
| @ -25,56 +22,47 @@ var pruneFlag = &cli.BoolFlag{ | ||||
| 	Usage:       "Prunes unused containers, networks, and dangling images for an app", | ||||
| } | ||||
|  | ||||
| // pruneApp runs the equivalent of a "docker system prune" but only filtering | ||||
| // against resources connected with the app deployment. It is not a system wide | ||||
| // prune. Volumes are not pruned to avoid unwated data loss. | ||||
| func pruneApp(c *cli.Context, cl *dockerClient.Client, app config.App) error { | ||||
| 	stackName := app.StackName() | ||||
| 	ctx := context.Background() | ||||
|  | ||||
| func cleanup(c *cli.Context) error { | ||||
| 	for { | ||||
| 		logrus.Debugf("polling for %s stack, waiting to be undeployed...", stackName) | ||||
|  | ||||
| 		services, err := stack.GetStackServices(ctx, cl, stackName) | ||||
| 		if !prune { | ||||
| 			return nil | ||||
| 		} | ||||
| 		app := internal.ValidateApp(c) | ||||
| 		stackName := app.StackName() | ||||
| 		cl, err := client.New(app.Server) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
| 		ctx := context.Background() | ||||
|  | ||||
| 		if len(services) == 0 { | ||||
| 			logrus.Debugf("%s undeployed, moving on with pruning logic", stackName) | ||||
| 			time.Sleep(time.Second) // give runtime more time to tear down related state | ||||
| 			break | ||||
| 		pruneFilters := filters.NewArgs() | ||||
| 		stackSearch := fmt.Sprintf("%s*", stackName) | ||||
| 		pruneFilters.Add("label", stackSearch) | ||||
| 		cr, err := cl.ContainersPrune(ctx, pruneFilters) | ||||
| 		if err != nil { | ||||
| 			logrus.Errorf(err.Error()) | ||||
| 			time.Sleep(time.Second) | ||||
| 			continue | ||||
| 		} | ||||
| 		logrus.Infof("Containers deleted: %s; Space reclaimed: %v", cr.ContainersDeleted, cr.SpaceReclaimed) | ||||
|  | ||||
| 		time.Sleep(time.Second) | ||||
| 		nr, err := cl.NetworksPrune(ctx, pruneFilters) | ||||
| 		if err != nil { | ||||
| 			logrus.Errorf(err.Error()) | ||||
| 			time.Sleep(time.Second) | ||||
| 			continue | ||||
| 		} | ||||
| 		logrus.Infof("Networks deleted %s", nr.NetworksDeleted) | ||||
|  | ||||
| 		ir, err := cl.ImagesPrune(ctx, pruneFilters) | ||||
| 		if err != nil { | ||||
| 			logrus.Errorf(err.Error()) | ||||
| 			time.Sleep(time.Second) | ||||
| 			continue | ||||
| 		} | ||||
| 		logrus.Infof("Images deleted: %s; Space reclaimed: %v", ir.ImagesDeleted, ir.SpaceReclaimed) | ||||
| 		break | ||||
| 	} | ||||
|  | ||||
| 	pruneFilters := filters.NewArgs() | ||||
| 	stackSearch := fmt.Sprintf("%s*", stackName) | ||||
| 	pruneFilters.Add("label", stackSearch) | ||||
| 	cr, err := cl.ContainersPrune(ctx, pruneFilters) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	cntSpaceReclaimed := formatter.ByteCountSI(cr.SpaceReclaimed) | ||||
| 	logrus.Infof("containers pruned: %d; space reclaimed: %s", len(cr.ContainersDeleted), cntSpaceReclaimed) | ||||
|  | ||||
| 	nr, err := cl.NetworksPrune(ctx, pruneFilters) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	logrus.Infof("networks pruned: %d", len(nr.NetworksDeleted)) | ||||
|  | ||||
| 	ir, err := cl.ImagesPrune(ctx, pruneFilters) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	imgSpaceReclaimed := formatter.ByteCountSI(ir.SpaceReclaimed) | ||||
| 	logrus.Infof("images pruned: %d; space reclaimed: %s", len(ir.ImagesDeleted), imgSpaceReclaimed) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @ -87,16 +75,12 @@ var appUndeployCommand = cli.Command{ | ||||
| 		internal.NoInputFlag, | ||||
| 		pruneFlag, | ||||
| 	}, | ||||
| 	Before:       internal.SubCommandBefore, | ||||
| 	Usage:        "Undeploy an app", | ||||
| 	BashComplete: autocomplete.AppNameComplete, | ||||
| 	Before: internal.SubCommandBefore, | ||||
| 	Usage:  "Undeploy an app", | ||||
| 	Description: ` | ||||
| This does not destroy any of the application data. | ||||
|  | ||||
| However, you should remain vigilant, as your swarm installation will consider | ||||
| any previously attached volumes as eligible for pruning once undeployed. | ||||
|  | ||||
| Passing "-p/--prune" does not remove those volumes. | ||||
| This does not destroy any of the application data. However, you should remain | ||||
| vigilant, as your swarm installation will consider any previously attached | ||||
| volumes as eligible for pruning once undeployed. | ||||
| `, | ||||
| 	Action: func(c *cli.Context) error { | ||||
| 		app := internal.ValidateApp(c) | ||||
| @ -125,13 +109,8 @@ Passing "-p/--prune" does not remove those volumes. | ||||
| 		if err := stack.RunRemove(context.Background(), cl, rmOpts); err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if prune { | ||||
| 			if err := pruneApp(c, cl, app); err != nil { | ||||
| 				logrus.Fatal(err) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		cleanup(c) | ||||
| 		return nil | ||||
| 	}, | ||||
| 	BashComplete: autocomplete.AppNameComplete, | ||||
| } | ||||
|  | ||||
| @ -61,7 +61,7 @@ recipes. | ||||
| 		} | ||||
|  | ||||
| 		if !internal.Chaos { | ||||
| 			if err := recipe.EnsureUpToDate(app.Recipe, conf); err != nil { | ||||
| 			if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | ||||
| 				logrus.Fatal(err) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @ -13,7 +13,6 @@ import ( | ||||
| 	"coopcloud.tech/abra/pkg/formatter" | ||||
| 	gitPkg "coopcloud.tech/abra/pkg/git" | ||||
| 	"coopcloud.tech/abra/pkg/recipe" | ||||
| 	"coopcloud.tech/abra/pkg/runtime" | ||||
| 	"github.com/go-git/go-git/v5" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/urfave/cli" | ||||
| @ -55,8 +54,6 @@ keys configured on your account. | ||||
| 	ArgsUsage: "[<recipe>]", | ||||
| 	Action: func(c *cli.Context) error { | ||||
| 		recipeName := c.Args().First() | ||||
| 		conf := runtime.New() | ||||
|  | ||||
| 		if recipeName != "" { | ||||
| 			internal.ValidateRecipe(c) | ||||
| 		} | ||||
| @ -82,7 +79,7 @@ keys configured on your account. | ||||
|  | ||||
| 		if !internal.SkipUpdates { | ||||
| 			logrus.Warn(logMsg) | ||||
| 			if err := recipe.UpdateRepositories(repos, recipeName, conf); err != nil { | ||||
| 			if err := recipe.UpdateRepositories(repos, recipeName); err != nil { | ||||
| 				logrus.Fatal(err) | ||||
| 			} | ||||
| 		} | ||||
| @ -100,7 +97,7 @@ keys configured on your account. | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			versions, err := recipe.GetRecipeVersions(recipeMeta.Name, conf) | ||||
| 			versions, err := recipe.GetRecipeVersions(recipeMeta.Name) | ||||
| 			if err != nil { | ||||
| 				logrus.Warn(err) | ||||
| 			} | ||||
|  | ||||
| @ -33,7 +33,7 @@ func DeployAction(c *cli.Context) error { | ||||
| 	} | ||||
|  | ||||
| 	if !Chaos { | ||||
| 		if err := recipe.EnsureUpToDate(app.Recipe, conf); err != nil { | ||||
| 		if err := recipe.EnsureUpToDate(app.Recipe); err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -122,8 +122,7 @@ func ensureServerFlag() error { | ||||
| func NewAction(c *cli.Context) error { | ||||
| 	recipe := ValidateRecipeWithPrompt(c, runtime.WithEnsureRecipeLatest(false)) | ||||
|  | ||||
| 	conf := runtime.New(runtime.WithEnsureRecipeLatest(false)) | ||||
| 	if err := recipePkg.EnsureUpToDate(recipe.Name, conf); err != nil { | ||||
| 	if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil { | ||||
| 		logrus.Fatal(err) | ||||
| 	} | ||||
|  | ||||
|  | ||||
| @ -42,8 +42,10 @@ func ValidateRecipe(c *cli.Context, opts ...runtime.Option) recipe.Recipe { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err := recipe.EnsureLatest(recipeName, conf); err != nil { | ||||
| 		logrus.Fatal(err) | ||||
| 	if conf.EnsureRecipeLatest { | ||||
| 		if err := recipe.EnsureLatest(recipeName, conf); err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf("validated %s as recipe argument", recipeName) | ||||
| @ -108,8 +110,10 @@ func ValidateRecipeWithPrompt(c *cli.Context, opts ...runtime.Option) recipe.Rec | ||||
| 		logrus.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	if err := recipe.EnsureLatest(recipeName, conf); err != nil { | ||||
| 		logrus.Fatal(err) | ||||
| 	if conf.EnsureRecipeLatest { | ||||
| 		if err := recipe.EnsureLatest(recipeName, conf); err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	logrus.Debugf("validated %s as recipe argument", recipeName) | ||||
|  | ||||
| @ -4,7 +4,6 @@ import ( | ||||
| 	"coopcloud.tech/abra/cli/internal" | ||||
| 	"coopcloud.tech/abra/pkg/autocomplete" | ||||
| 	"coopcloud.tech/abra/pkg/recipe" | ||||
| 	"coopcloud.tech/abra/pkg/runtime" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/urfave/cli" | ||||
| ) | ||||
| @ -22,8 +21,6 @@ var recipeFetchCommand = cli.Command{ | ||||
| 	BashComplete: autocomplete.RecipeNameComplete, | ||||
| 	Action: func(c *cli.Context) error { | ||||
| 		recipeName := c.Args().First() | ||||
| 		conf := runtime.New() | ||||
|  | ||||
| 		if recipeName != "" { | ||||
| 			internal.ValidateRecipe(c) | ||||
| 			return nil // ValidateRecipe ensures latest checkout | ||||
| @ -34,7 +31,7 @@ var recipeFetchCommand = cli.Command{ | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		if err := recipe.UpdateRepositories(repos, recipeName, conf); err != nil { | ||||
| 		if err := recipe.UpdateRepositories(repos, recipeName); err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
|  | ||||
|  | ||||
| @ -8,7 +8,6 @@ import ( | ||||
| 	"coopcloud.tech/abra/pkg/formatter" | ||||
| 	"coopcloud.tech/abra/pkg/lint" | ||||
| 	recipePkg "coopcloud.tech/abra/pkg/recipe" | ||||
| 	"coopcloud.tech/abra/pkg/runtime" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/urfave/cli" | ||||
| ) | ||||
| @ -26,9 +25,8 @@ var recipeLintCommand = cli.Command{ | ||||
| 	BashComplete: autocomplete.RecipeNameComplete, | ||||
| 	Action: func(c *cli.Context) error { | ||||
| 		recipe := internal.ValidateRecipe(c) | ||||
| 		conf := runtime.New() | ||||
|  | ||||
| 		if err := recipePkg.EnsureUpToDate(recipe.Name, conf); err != nil { | ||||
| 		if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
|  | ||||
|  | ||||
| @ -14,7 +14,6 @@ import ( | ||||
| 	"coopcloud.tech/abra/pkg/config" | ||||
| 	"coopcloud.tech/abra/pkg/formatter" | ||||
| 	recipePkg "coopcloud.tech/abra/pkg/recipe" | ||||
| 	"coopcloud.tech/abra/pkg/runtime" | ||||
| 	"coopcloud.tech/tagcmp" | ||||
| 	"github.com/AlecAivazis/survey/v2" | ||||
| 	"github.com/docker/distribution/reference" | ||||
| @ -61,9 +60,8 @@ You may invoke this command in "wizard" mode and be prompted for input: | ||||
| 	Before: internal.SubCommandBefore, | ||||
| 	Action: func(c *cli.Context) error { | ||||
| 		recipe := internal.ValidateRecipeWithPrompt(c) | ||||
| 		conf := runtime.New() | ||||
|  | ||||
| 		if err := recipePkg.EnsureUpToDate(recipe.Name, conf); err != nil { | ||||
| 		if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
|  | ||||
|  | ||||
| @ -39,7 +39,11 @@ var serverListCommand = cli.Command{ | ||||
|  | ||||
| 		tableColumns := []string{"name", "host", "user", "port"} | ||||
| 		table := formatter.CreateTable(tableColumns) | ||||
|  | ||||
| 		if internal.MachineReadable { | ||||
| 			defer table.JSONRender() | ||||
| 		} else { | ||||
| 			defer table.Render() | ||||
| 		} | ||||
| 		serverNames, err := config.ReadServerNames() | ||||
| 		if err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| @ -80,16 +84,6 @@ var serverListCommand = cli.Command{ | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if internal.MachineReadable { | ||||
| 			table.JSONRender() | ||||
| 		} else { | ||||
| 			if problemsFilter && table.NumLines() == 0 { | ||||
| 				logrus.Info("all servers wired up correctly 👏") | ||||
| 			} else { | ||||
| 				table.Render() | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| @ -4,9 +4,7 @@ import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"coopcloud.tech/abra/cli/internal" | ||||
| 	"coopcloud.tech/abra/pkg/autocomplete" | ||||
| 	"coopcloud.tech/abra/pkg/client" | ||||
| 	"coopcloud.tech/abra/pkg/formatter" | ||||
| 	"github.com/docker/docker/api/types/filters" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/urfave/cli" | ||||
| @ -24,75 +22,60 @@ var volunesFilter bool | ||||
|  | ||||
| var volumesFilterFlag = &cli.BoolFlag{ | ||||
| 	Name:        "volumes, v", | ||||
| 	Usage:       "Prune volumes. This will remove app data, Be Careful!", | ||||
| 	Usage:       "Prune volumes", | ||||
| 	Destination: &volunesFilter, | ||||
| } | ||||
|  | ||||
| var serverPruneCommand = cli.Command{ | ||||
| 	Name:    "prune", | ||||
| 	Aliases: []string{"p"}, | ||||
| 	Usage:   "Prune a managed server; Runs a docker system prune", | ||||
| 	Description: ` | ||||
| Prunes unused containers, networks, and dangling images. | ||||
|  | ||||
| If passing "-v/--volumes" then volumes not connected with a deployed app will | ||||
| also be removed. This can result in unwanted data loss if not used carefully. | ||||
| 	`, | ||||
| 	ArgsUsage: "[<server>]", | ||||
| 	Name:        "prune", | ||||
| 	Aliases:     []string{"p"}, | ||||
| 	Usage:       "Prune a managed server; Runs a docker system prune", | ||||
| 	Description: "Prunes unused containers, networks, and dangling images", | ||||
| 	ArgsUsage:   "[<server>]", | ||||
| 	Flags: []cli.Flag{ | ||||
| 		allFilterFlag, | ||||
| 		volumesFilterFlag, | ||||
| 		internal.DebugFlag, | ||||
| 	}, | ||||
| 	Before:       internal.SubCommandBefore, | ||||
| 	BashComplete: autocomplete.ServerNameComplete, | ||||
| 	Before: internal.SubCommandBefore, | ||||
| 	Action: func(c *cli.Context) error { | ||||
| 		// Leaving filters empty for now | ||||
| 		var args filters.Args | ||||
|  | ||||
| 		serverName := internal.ValidateServer(c) | ||||
|  | ||||
| 		cl, err := client.New(serverName) | ||||
| 		if err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		ctx := context.Background() | ||||
| 		cr, err := cl.ContainersPrune(ctx, args) | ||||
| 		if err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		cntSpaceReclaimed := formatter.ByteCountSI(cr.SpaceReclaimed) | ||||
| 		logrus.Infof("containers pruned: %d; space reclaimed: %s", len(cr.ContainersDeleted), cntSpaceReclaimed) | ||||
| 		logrus.Infof("Containers deleted: %s; Space reclaimed: %v", cr.ContainersDeleted, cr.SpaceReclaimed) | ||||
|  | ||||
| 		nr, err := cl.NetworksPrune(ctx, args) | ||||
| 		if err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		logrus.Infof("networks pruned: %d", len(nr.NetworksDeleted)) | ||||
| 		logrus.Infof("Networks deleted %s", nr.NetworksDeleted) | ||||
|  | ||||
| 		pruneFilters := filters.NewArgs() | ||||
| 		if allFilter { | ||||
| 			pruneFilters.Add("dangling", "false") | ||||
| 		} | ||||
|  | ||||
| 		ir, err := cl.ImagesPrune(ctx, pruneFilters) | ||||
| 		if err != nil { | ||||
| 			logrus.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		imgSpaceReclaimed := formatter.ByteCountSI(ir.SpaceReclaimed) | ||||
| 		logrus.Infof("images pruned: %d; space reclaimed: %s", len(ir.ImagesDeleted), imgSpaceReclaimed) | ||||
| 		logrus.Infof("Images deleted: %s; Space reclaimed: %v", ir.ImagesDeleted, ir.SpaceReclaimed) | ||||
|  | ||||
| 		if volunesFilter { | ||||
| 			vr, err := cl.VolumesPrune(ctx, args) | ||||
| 			if err != nil { | ||||
| 				logrus.Fatal(err) | ||||
| 			} | ||||
|  | ||||
| 			volSpaceReclaimed := formatter.ByteCountSI(vr.SpaceReclaimed) | ||||
| 			logrus.Infof("volumes pruned: %d; space reclaimed: %s", len(vr.VolumesDeleted), volSpaceReclaimed) | ||||
| 			logrus.Infof("Volumes deleted: %s; Space reclaimed: %v", vr.VolumesDeleted, vr.SpaceReclaimed) | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
|  | ||||
| @ -7,7 +7,6 @@ import ( | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"coopcloud.tech/abra/cli/internal" | ||||
| 	"coopcloud.tech/abra/pkg/autocomplete" | ||||
| 	"coopcloud.tech/abra/pkg/client" | ||||
| 	"coopcloud.tech/abra/pkg/config" | ||||
| 	"coopcloud.tech/abra/pkg/formatter" | ||||
| @ -125,8 +124,7 @@ like tears in rain. | ||||
| 		internal.HetznerCloudNameFlag, | ||||
| 		internal.HetznerCloudAPITokenFlag, | ||||
| 	}, | ||||
| 	Before:       internal.SubCommandBefore, | ||||
| 	BashComplete: autocomplete.ServerNameComplete, | ||||
| 	Before: internal.SubCommandBefore, | ||||
| 	Action: func(c *cli.Context) error { | ||||
| 		serverName := internal.ValidateServer(c) | ||||
|  | ||||
|  | ||||
| @ -321,7 +321,7 @@ func processRecipeRepoVersion(recipeName, version string, conf *runtime.Config) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if err := recipe.EnsureUpToDate(recipeName, conf); err != nil { | ||||
| 	if err := recipe.EnsureUpToDate(recipeName); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
|  | ||||
| @ -9,7 +9,7 @@ import ( | ||||
| 	"github.com/urfave/cli" | ||||
| ) | ||||
|  | ||||
| // AppNameComplete copletes app names. | ||||
| // AppNameComplete copletes app names | ||||
| func AppNameComplete(c *cli.Context) { | ||||
| 	appNames, err := config.GetAppNames() | ||||
| 	if err != nil { | ||||
| @ -25,7 +25,7 @@ func AppNameComplete(c *cli.Context) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // RecipeNameComplete completes recipe names. | ||||
| // RecipeNameComplete completes recipe names | ||||
| func RecipeNameComplete(c *cli.Context) { | ||||
| 	catl, err := recipe.ReadRecipeCatalogue() | ||||
| 	if err != nil { | ||||
| @ -41,23 +41,7 @@ func RecipeNameComplete(c *cli.Context) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ServerNameComplete completes server names. | ||||
| func ServerNameComplete(c *cli.Context) { | ||||
| 	files, err := config.LoadAppFiles("") | ||||
| 	if err != nil { | ||||
| 		logrus.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	if c.NArg() > 0 { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	for _, appFile := range files { | ||||
| 		fmt.Println(appFile.Server) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // SubcommandComplete completes sub-commands. | ||||
| // SubcommandComplete completes subcommands. | ||||
| func SubcommandComplete(c *cli.Context) { | ||||
| 	if c.NArg() > 0 { | ||||
| 		return | ||||
|  | ||||
| @ -1,7 +1,6 @@ | ||||
| package formatter | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| @ -71,21 +70,3 @@ func StripTagMeta(image string) string { | ||||
|  | ||||
| 	return image | ||||
| } | ||||
|  | ||||
| // ByteCountSI presents a human friendly representation of a byte count. See | ||||
| // https://yourbasic.org/golang/formatting-byte-size-to-human-readable-format. | ||||
| func ByteCountSI(b uint64) string { | ||||
| 	const unit = 1000 | ||||
|  | ||||
| 	if b < unit { | ||||
| 		return fmt.Sprintf("%d B", b) | ||||
| 	} | ||||
|  | ||||
| 	div, exp := uint64(unit), 0 | ||||
| 	for n := b / unit; n >= unit; n /= unit { | ||||
| 		div *= unit | ||||
| 		exp++ | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp]) | ||||
| } | ||||
|  | ||||
| @ -339,10 +339,6 @@ func EnsureVersion(recipeName, version string) error { | ||||
|  | ||||
| // EnsureLatest makes sure the latest commit is checked out for a local recipe repository | ||||
| func EnsureLatest(recipeName string, conf *runtime.Config) error { | ||||
| 	if !conf.EnsureRecipeLatest { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	recipeDir := path.Join(config.RECIPES_DIR, recipeName) | ||||
|  | ||||
| 	isClean, err := gitPkg.IsClean(recipeDir) | ||||
| @ -587,11 +583,7 @@ func GetStringInBetween(recipeName, str, start, end string) (result string, err | ||||
| } | ||||
|  | ||||
| // EnsureUpToDate ensures that the local repo is synced to the remote | ||||
| func EnsureUpToDate(recipeName string, conf *runtime.Config) error { | ||||
| 	if !conf.EnsureRecipeLatest { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| func EnsureUpToDate(recipeName string) error { | ||||
| 	recipeDir := path.Join(config.RECIPES_DIR, recipeName) | ||||
|  | ||||
| 	isClean, err := gitPkg.IsClean(recipeDir) | ||||
| @ -936,8 +928,10 @@ func ReadReposMetadata() (RepoCatalogue, error) { | ||||
| } | ||||
|  | ||||
| // GetRecipeVersions retrieves all recipe versions. | ||||
| func GetRecipeVersions(recipeName string, conf *runtime.Config) (RecipeVersions, error) { | ||||
| func GetRecipeVersions(recipeName string, opts ...runtime.Option) (RecipeVersions, error) { | ||||
| 	versions := RecipeVersions{} | ||||
| 	conf := runtime.New(opts...) | ||||
|  | ||||
| 	recipeDir := path.Join(config.RECIPES_DIR, recipeName) | ||||
|  | ||||
| 	logrus.Debugf("attempting to open git repository in %s", recipeDir) | ||||
| @ -1039,7 +1033,7 @@ func GetRecipeCatalogueVersions(recipeName string, catl RecipeCatalogue) ([]stri | ||||
| } | ||||
|  | ||||
| // UpdateRepositories clones and updates all recipe repositories locally. | ||||
| func UpdateRepositories(repos RepoCatalogue, recipeName string, conf *runtime.Config) error { | ||||
| func UpdateRepositories(repos RepoCatalogue, recipeName string) error { | ||||
| 	var barLength int | ||||
| 	if recipeName != "" { | ||||
| 		barLength = 1 | ||||
| @ -1073,7 +1067,7 @@ func UpdateRepositories(repos RepoCatalogue, recipeName string, conf *runtime.Co | ||||
| 				logrus.Fatal(err) | ||||
| 			} | ||||
|  | ||||
| 			if err := EnsureUpToDate(rm.Name, conf); err != nil { | ||||
| 			if err := EnsureUpToDate(rm.Name); err != nil { | ||||
| 				logrus.Fatal(err) | ||||
| 			} | ||||
|  | ||||
|  | ||||
| @ -11,10 +11,7 @@ type Config struct { | ||||
| 	EnsureRecipeLatest bool // ensure the local recipe has latest changes | ||||
| } | ||||
|  | ||||
| // Option modified a Config. The convetion for passing Options to functions is | ||||
| // so far, only used in internal/validate.go. A Config is then constructed and | ||||
| // passed down further into the code. This may change in the future but this is | ||||
| // at least the abstraction so far. | ||||
| // Option modified a Config. | ||||
| type Option func(c *Config) | ||||
|  | ||||
| // New instantiates a new Config. | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| ABRA_VERSION="0.7.0-beta" | ||||
| ABRA_VERSION="0.6.0-beta" | ||||
| ABRA_RELEASE_URL="https://git.coopcloud.tech/api/v1/repos/coop-cloud/abra/releases/tags/$ABRA_VERSION" | ||||
| RC_VERSION="0.7.0-beta" | ||||
| RC_VERSION="0.7.0-rc2-beta" | ||||
| RC_VERSION_URL="https://git.coopcloud.tech/api/v1/repos/coop-cloud/abra/releases/tags/$RC_VERSION" | ||||
|  | ||||
| for arg in "$@"; do | ||||
|  | ||||
		Reference in New Issue
	
	Block a user