forked from coop-cloud/abra
Compare commits
14 Commits
74fd954ac4
...
72c807e31a
Author | SHA1 | Date |
---|---|---|
Moritz | 72c807e31a | |
Moritz | 8e16d2f350 | |
Moritz | b62b46a1c6 | |
Moritz | fe62b677e0 | |
Moritz | d02a049dde | |
Moritz | df42585490 | |
Moritz | ddead5dac6 | |
Moritz | 1931a9b74d | |
Moritz | 76717531bd | |
Moritz | 6774893412 | |
moritz | ebb86391af | |
moritz | 50db39424c | |
moritz | ca1ea32c46 | |
Moritz | 32851d4d99 |
|
@ -3,6 +3,7 @@
|
||||||
.envrc
|
.envrc
|
||||||
.vscode/
|
.vscode/
|
||||||
abra
|
abra
|
||||||
|
/kadabra
|
||||||
dist/
|
dist/
|
||||||
tests/integration/.abra/catalogue
|
tests/integration/.abra/catalogue
|
||||||
vendor/
|
vendor/
|
||||||
|
|
3
Makefile
3
Makefile
|
@ -1,4 +1,5 @@
|
||||||
ABRA := ./cmd/abra
|
ABRA := ./cmd/abra
|
||||||
|
KADABRA := ./cmd/kadabra
|
||||||
COMMIT := $(shell git rev-list -1 HEAD)
|
COMMIT := $(shell git rev-list -1 HEAD)
|
||||||
GOPATH := $(shell go env GOPATH)
|
GOPATH := $(shell go env GOPATH)
|
||||||
LDFLAGS := "-X 'main.Commit=$(COMMIT)'"
|
LDFLAGS := "-X 'main.Commit=$(COMMIT)'"
|
||||||
|
@ -18,9 +19,11 @@ build-dev:
|
||||||
|
|
||||||
build:
|
build:
|
||||||
@go build -ldflags=$(DIST_LDFLAGS) $(ABRA)
|
@go build -ldflags=$(DIST_LDFLAGS) $(ABRA)
|
||||||
|
@go build -ldflags=$(DIST_LDFLAGS) $(KADABRA)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm '$(GOPATH)/bin/abra'
|
@rm '$(GOPATH)/bin/abra'
|
||||||
|
@rm '$(GOPATH)/bin/kadabra'
|
||||||
|
|
||||||
format:
|
format:
|
||||||
@gofmt -s -w .
|
@gofmt -s -w .
|
||||||
|
|
|
@ -178,6 +178,10 @@ recipes.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
|
config.ExposeAllEnv(stackName, compose, app.Env)
|
||||||
|
config.SetRecipeLabel(compose, stackName, app.Recipe)
|
||||||
|
config.SetChaosLabel(compose, stackName, internal.Chaos)
|
||||||
|
config.SetUpdateLabel(compose, stackName, app.Env)
|
||||||
|
|
||||||
if !internal.Force {
|
if !internal.Force {
|
||||||
if err := internal.NewVersionOverview(app, deployedVersion, chosenDowngrade, ""); err != nil {
|
if err := internal.NewVersionOverview(app, deployedVersion, chosenDowngrade, ""); err != nil {
|
||||||
|
|
|
@ -189,6 +189,10 @@ recipes.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
|
config.ExposeAllEnv(stackName, compose, app.Env)
|
||||||
|
config.SetRecipeLabel(compose, stackName, app.Recipe)
|
||||||
|
config.SetChaosLabel(compose, stackName, internal.Chaos)
|
||||||
|
config.SetUpdateLabel(compose, stackName, app.Env)
|
||||||
|
|
||||||
if err := internal.NewVersionOverview(app, deployedVersion, chosenUpgrade, releaseNotes); err != nil {
|
if err := internal.NewVersionOverview(app, deployedVersion, chosenUpgrade, releaseNotes); err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
|
|
|
@ -134,6 +134,10 @@ func DeployAction(c *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
|
config.ExposeAllEnv(app.StackName(), compose, app.Env)
|
||||||
|
config.SetRecipeLabel(compose, app.StackName(), app.Recipe)
|
||||||
|
config.SetChaosLabel(compose, app.StackName(), Chaos)
|
||||||
|
config.SetUpdateLabel(compose, app.StackName(), app.Env)
|
||||||
|
|
||||||
if err := DeployOverview(app, version, "continue with deployment?"); err != nil {
|
if err := DeployOverview(app, version, "continue with deployment?"); err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
|
|
|
@ -0,0 +1,329 @@
|
||||||
|
package updater
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"coopcloud.tech/abra/cli/internal"
|
||||||
|
"coopcloud.tech/abra/pkg/client"
|
||||||
|
"coopcloud.tech/abra/pkg/config"
|
||||||
|
"coopcloud.tech/abra/pkg/lint"
|
||||||
|
"coopcloud.tech/abra/pkg/recipe"
|
||||||
|
"coopcloud.tech/abra/pkg/upstream/convert"
|
||||||
|
"coopcloud.tech/abra/pkg/upstream/stack"
|
||||||
|
"coopcloud.tech/tagcmp"
|
||||||
|
composetypes "github.com/docker/cli/cli/compose/types"
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
dockerclient "github.com/docker/docker/client"
|
||||||
|
|
||||||
|
// "github.com/docker/cli/cli/command/stack/swarm"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Upgrade a specific app
|
||||||
|
var UpgradeApp = cli.Command{
|
||||||
|
Name: "appupgrade",
|
||||||
|
Aliases: []string{"a"},
|
||||||
|
Usage: "Upgrade an app",
|
||||||
|
ArgsUsage: "<stack_name> <recipe>",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
internal.DebugFlag,
|
||||||
|
internal.ForceFlag,
|
||||||
|
},
|
||||||
|
Before: internal.SubCommandBefore,
|
||||||
|
Description: `Upgrade an app`,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
stackName := c.Args().Get(0)
|
||||||
|
recipeName := c.Args().Get(1)
|
||||||
|
cl, err := client.New("default")
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
upgrade(cl, stackName, recipeName)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upgrade all appS
|
||||||
|
var UpgradeAll = cli.Command{
|
||||||
|
Name: "upgrade",
|
||||||
|
Aliases: []string{"u"},
|
||||||
|
Usage: "Upgrade all apps",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
internal.DebugFlag,
|
||||||
|
internal.ForceFlag,
|
||||||
|
internal.DontWaitConvergeFlag,
|
||||||
|
},
|
||||||
|
Before: internal.SubCommandBefore,
|
||||||
|
Description: `Upgrade all deployed apps`,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
|
||||||
|
cl, err := client.New("default")
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
// can't import this lib:
|
||||||
|
// stacks := swarm.GetStacks(cl)
|
||||||
|
stacks, err := stack.GetStacks(cl)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, stackInfo := range stacks {
|
||||||
|
stackName := stackInfo.Name
|
||||||
|
recipeName := getLabel(cl, stackName, "recipe")
|
||||||
|
chaos := getBoolLabel(cl, stackName, "chaos")
|
||||||
|
updatesEnabled := getBoolLabel(cl, stackName, "autoupdate")
|
||||||
|
if recipeName != "" && updatesEnabled && (!chaos || internal.Force) {
|
||||||
|
upgrade(cl, stackName, recipeName)
|
||||||
|
} else {
|
||||||
|
logrus.Infof("Don't update %s due to missing recipe name, disabled updates or chaos deployment", stackName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read docker label in the format coop-cloud.${STACK_NAME}.${LABEL}
|
||||||
|
func getLabel(cl *dockerclient.Client, stackName string, label string) string {
|
||||||
|
filter := filters.NewArgs()
|
||||||
|
filter.Add("label", fmt.Sprintf("%s=%s", convert.LabelNamespace, stackName))
|
||||||
|
|
||||||
|
services, err := cl.ServiceList(context.Background(), types.ServiceListOptions{Filters: filter})
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, service := range services {
|
||||||
|
labelKey := fmt.Sprintf("coop-cloud.%s.%s", stackName, label)
|
||||||
|
if labelValue, ok := service.Spec.Labels[labelKey]; ok {
|
||||||
|
return labelValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logrus.Debugf("no %s label found for %s", label, stackName)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read boolean docker label
|
||||||
|
func getBoolLabel(cl *dockerclient.Client, stackName string, label string) bool {
|
||||||
|
lableValue := getLabel(cl, stackName, label)
|
||||||
|
if lableValue != "" {
|
||||||
|
value, err := strconv.ParseBool(lableValue)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Env variables from docker services
|
||||||
|
func getEnv(cl *dockerclient.Client, stackName string) config.AppEnv {
|
||||||
|
envMap := make(map[string]string)
|
||||||
|
filter := filters.NewArgs()
|
||||||
|
filter.Add("label", fmt.Sprintf("%s=%s", convert.LabelNamespace, stackName))
|
||||||
|
|
||||||
|
services, err := cl.ServiceList(context.Background(), types.ServiceListOptions{Filters: filter})
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, service := range services {
|
||||||
|
envList := service.Spec.TaskTemplate.ContainerSpec.Env
|
||||||
|
for _, envString := range envList {
|
||||||
|
splitString := strings.SplitN(envString, "=", 2)
|
||||||
|
if len(splitString) != 2 {
|
||||||
|
logrus.Debugf("can't separate key from value: %s (this variable is probably unset)", envString)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
k := splitString[0]
|
||||||
|
v := splitString[1]
|
||||||
|
logrus.Debugf("Env Key: %s Value: %s", k, v)
|
||||||
|
envMap[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return envMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName string) []string {
|
||||||
|
logrus.Debugf("Retrieve deployed version whether %s is already deployed", stackName)
|
||||||
|
isDeployed, deployedVersion, err := stack.IsDeployed(context.Background(), cl, stackName)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isDeployed {
|
||||||
|
logrus.Fatalf("%s is not deployed?", stackName)
|
||||||
|
}
|
||||||
|
|
||||||
|
catl, err := recipe.ReadRecipeCatalogue()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
versions, err := recipe.GetRecipeCatalogueVersions(recipeName, catl)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(versions) == 0 {
|
||||||
|
logrus.Fatalf("no published releases for %s in the recipe catalogue?", recipeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
var availableUpgrades []string
|
||||||
|
if deployedVersion == "unknown" {
|
||||||
|
availableUpgrades = versions
|
||||||
|
logrus.Fatalf("failed to determine deployed version of %s", stackName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if deployedVersion != "unknown" {
|
||||||
|
logrus.Infof("%s is deployed on %s with version %s", recipeName, stackName, deployedVersion)
|
||||||
|
for _, version := range versions {
|
||||||
|
parsedDeployedVersion, err := tagcmp.Parse(deployedVersion)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
parsedVersion, err := tagcmp.Parse(version)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
versionDelta, err := parsedDeployedVersion.UpgradeDelta(parsedVersion)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
// Only update Patch/Minor updates
|
||||||
|
if 0 < versionDelta.UpgradeType() && versionDelta.UpgradeType() < 4 {
|
||||||
|
availableUpgrades = append(availableUpgrades, version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
logrus.Warnf("Could not determine the deployed version for %s", stackName)
|
||||||
|
}
|
||||||
|
return availableUpgrades
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// clone, pull, checkout version and lint the recipe repository
|
||||||
|
func processRecipeRepoVersion(recipeName string, version string) {
|
||||||
|
if err := recipe.EnsureExists(recipeName); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := recipe.EnsureUpToDate(recipeName); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := recipe.EnsureVersion(recipeName, version); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
if r, err := recipe.Get(recipeName); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
} else if err := lint.LintForErrors(r); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge abra.sh env's into app env's
|
||||||
|
func mergeAbraShEnv(recipeName string, env config.AppEnv) {
|
||||||
|
abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, recipeName, "abra.sh")
|
||||||
|
abraShEnv, err := config.ReadAbraShEnvVars(abraShPath)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
for k, v := range abraShEnv {
|
||||||
|
logrus.Debugf("read v:%s k: %s", v, k)
|
||||||
|
env[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDeployConfig(recipeName string, stackName string, env config.AppEnv) (*composetypes.Config, stack.Deploy) {
|
||||||
|
// Workaround, is there a better way?
|
||||||
|
env["STACK_NAME"] = stackName
|
||||||
|
|
||||||
|
composeFiles, err := config.GetAppComposeFiles(recipeName, env)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
deployOpts := stack.Deploy{
|
||||||
|
Composefiles: composeFiles,
|
||||||
|
Namespace: stackName,
|
||||||
|
Prune: false,
|
||||||
|
ResolveImage: stack.ResolveImageAlways,
|
||||||
|
}
|
||||||
|
compose, err := config.GetAppComposeConfig(stackName, deployOpts, env)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
config.ExposeAllEnv(stackName, compose, env)
|
||||||
|
// after the upgrade the deployment won't be in chaos state anymore
|
||||||
|
config.SetChaosLabel(compose, stackName, false)
|
||||||
|
config.SetRecipeLabel(compose, stackName, recipeName)
|
||||||
|
return compose, deployOpts
|
||||||
|
}
|
||||||
|
|
||||||
|
func upgrade(cl *dockerclient.Client, stackName string, recipeName string) {
|
||||||
|
logrus.Debugf("Upgrade StackName: %s \n Recipe: %s", stackName, recipeName)
|
||||||
|
app := config.App{
|
||||||
|
Name: stackName,
|
||||||
|
Recipe: recipeName,
|
||||||
|
Server: "localhost",
|
||||||
|
Env: getEnv(cl, stackName),
|
||||||
|
}
|
||||||
|
|
||||||
|
availableUpgrades := getAvailableUpgrades(cl, stackName, recipeName)
|
||||||
|
if len(availableUpgrades) == 0 {
|
||||||
|
logrus.Infof("no available upgrades for %s", stackName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
availableUpgrades = internal.ReverseStringList(availableUpgrades)
|
||||||
|
var chosenUpgrade string
|
||||||
|
if len(availableUpgrades) > 0 {
|
||||||
|
chosenUpgrade = availableUpgrades[len(availableUpgrades)-1]
|
||||||
|
logrus.Infof("choosing %s as version to upgrade to", chosenUpgrade)
|
||||||
|
}
|
||||||
|
|
||||||
|
processRecipeRepoVersion(recipeName, chosenUpgrade)
|
||||||
|
|
||||||
|
mergeAbraShEnv(recipeName, app.Env)
|
||||||
|
|
||||||
|
compose, deployOpts := createDeployConfig(recipeName, stackName, app.Env)
|
||||||
|
|
||||||
|
if err := stack.RunDeploy(cl, deployOpts, compose, stackName, true); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newAbraApp(version, commit string) *cli.App {
|
||||||
|
app := &cli.App{
|
||||||
|
Name: "kadabra",
|
||||||
|
Usage: `The Co-op Cloud autoupdater
|
||||||
|
____ ____ _ _
|
||||||
|
/ ___|___ ___ _ __ / ___| | ___ _ _ __| |
|
||||||
|
| | / _ \ _____ / _ \| '_ \ | | | |/ _ \| | | |/ _' |
|
||||||
|
| |__| (_) |_____| (_) | |_) | | |___| | (_) | |_| | (_| |
|
||||||
|
\____\___/ \___/| .__/ \____|_|\___/ \__,_|\__,_|
|
||||||
|
|_|
|
||||||
|
`,
|
||||||
|
Version: fmt.Sprintf("%s-%s", version, commit[:7]),
|
||||||
|
Commands: []cli.Command{
|
||||||
|
UpgradeApp,
|
||||||
|
UpgradeAll,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Before = func(c *cli.Context) error {
|
||||||
|
logrus.Debugf("abra version %s, commit %s", version, commit)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunApp runs CLI abra app.
|
||||||
|
func RunApp(version, commit string) {
|
||||||
|
app := newAbraApp(version, commit)
|
||||||
|
|
||||||
|
if err := app.Run(os.Args); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Package main provides the command-line entrypoint.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"coopcloud.tech/abra/cli/updater"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Version is the current version of Abra
|
||||||
|
var Version string
|
||||||
|
|
||||||
|
// Commit is the current git commit of Abra
|
||||||
|
var Commit string
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if Version == "" {
|
||||||
|
Version = "dev"
|
||||||
|
}
|
||||||
|
if Commit == "" {
|
||||||
|
Commit = " "
|
||||||
|
}
|
||||||
|
|
||||||
|
updater.RunApp(Version, Commit)
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/schollz/progressbar/v3"
|
"github.com/schollz/progressbar/v3"
|
||||||
|
@ -447,3 +448,61 @@ func GetAppComposeConfig(recipe string, opts stack.Deploy, appEnv AppEnv) (*comp
|
||||||
|
|
||||||
return compose, nil
|
return compose, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExposeAllEnv exposes all env variables to the app container
|
||||||
|
func ExposeAllEnv(stackName string, compose *composetypes.Config, appEnv AppEnv) {
|
||||||
|
for _, service := range compose.Services {
|
||||||
|
if service.Name == "app" {
|
||||||
|
logrus.Debugf("Add the following environment to the app service config of %s:", stackName)
|
||||||
|
for k, v := range appEnv {
|
||||||
|
_, exists := service.Environment[k]
|
||||||
|
if !exists {
|
||||||
|
value := v
|
||||||
|
service.Environment[k] = &value
|
||||||
|
logrus.Debugf("Add Key: %s Value: %s to %s", k, value, stackName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRecipeLabel adds the label 'coop-cloud.${STACK_NAME}.recipe=${RECIPE}' to the app container
|
||||||
|
// to signal which recipe is connected to the deployed app
|
||||||
|
func SetRecipeLabel(compose *composetypes.Config, stackName string, recipe string) {
|
||||||
|
for _, service := range compose.Services {
|
||||||
|
if service.Name == "app" {
|
||||||
|
logrus.Debugf("set recipe label 'coop-cloud.%s.recipe' to %s for %s", stackName, recipe, stackName)
|
||||||
|
labelKey := fmt.Sprintf("coop-cloud.%s.recipe", stackName)
|
||||||
|
service.Deploy.Labels[labelKey] = recipe
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetChaosLabel adds the label 'coop-cloud.${STACK_NAME}.chaos=true/false' to the app container
|
||||||
|
// to signal if the app is deployed in chaos mode
|
||||||
|
func SetChaosLabel(compose *composetypes.Config, stackName string, chaos bool) {
|
||||||
|
for _, service := range compose.Services {
|
||||||
|
if service.Name == "app" {
|
||||||
|
logrus.Debugf("set label 'coop-cloud.%s.chaos' to %s for %s", stackName, chaos, stackName)
|
||||||
|
labelKey := fmt.Sprintf("coop-cloud.%s.chaos", stackName)
|
||||||
|
service.Deploy.Labels[labelKey] = strconv.FormatBool(chaos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUpdateLabel adds env ENABLE_AUTO_UPDATE as label to enable/disable the
|
||||||
|
// auto update process for this app. The default if this variable is not set is to disable
|
||||||
|
// the auto update process.
|
||||||
|
func SetUpdateLabel(compose *composetypes.Config, stackName string, appEnv AppEnv) {
|
||||||
|
for _, service := range compose.Services {
|
||||||
|
if service.Name == "app" {
|
||||||
|
enable_auto_update, exists := appEnv["ENABLE_AUTO_UPDATE"]
|
||||||
|
if !exists {
|
||||||
|
enable_auto_update = "false"
|
||||||
|
}
|
||||||
|
logrus.Debugf("set label 'coop-cloud.%s.autoupdate' to %s for %s", stackName, enable_auto_update, stackName)
|
||||||
|
labelKey := fmt.Sprintf("coop-cloud.%s.autoupdate", stackName)
|
||||||
|
service.Deploy.Labels[labelKey] = enable_auto_update
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -309,8 +309,7 @@ func EnsureVersion(recipeName, version string) error {
|
||||||
logrus.Debugf("read %s as tags for recipe %s", strings.Join(parsedTags, ", "), recipeName)
|
logrus.Debugf("read %s as tags for recipe %s", strings.Join(parsedTags, ", "), recipeName)
|
||||||
|
|
||||||
if tagRef.String() == "" {
|
if tagRef.String() == "" {
|
||||||
logrus.Warnf("no published release discovered for %s", recipeName)
|
return fmt.Errorf("no published release discovered for %s", recipeName)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
worktree, err := repo.Worktree()
|
worktree, err := repo.Worktree()
|
||||||
|
@ -616,6 +615,11 @@ func EnsureUpToDate(recipeName string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchOpts := &git.FetchOptions{
|
||||||
|
Tags: git.AllTags,
|
||||||
|
}
|
||||||
|
repo.Fetch(fetchOpts)
|
||||||
|
|
||||||
opts := &git.PullOptions{
|
opts := &git.PullOptions{
|
||||||
Force: true,
|
Force: true,
|
||||||
ReferenceName: branch,
|
ReferenceName: branch,
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
abraClient "coopcloud.tech/abra/pkg/client"
|
abraClient "coopcloud.tech/abra/pkg/client"
|
||||||
"coopcloud.tech/abra/pkg/upstream/convert"
|
"coopcloud.tech/abra/pkg/upstream/convert"
|
||||||
"github.com/docker/cli/cli/command/service/progress"
|
"github.com/docker/cli/cli/command/service/progress"
|
||||||
|
"github.com/docker/cli/cli/command/stack/formatter"
|
||||||
composetypes "github.com/docker/cli/cli/compose/types"
|
composetypes "github.com/docker/cli/cli/compose/types"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
|
@ -507,3 +508,37 @@ If a service is failing to even start, try smoke out the error with:
|
||||||
`, appName, timeout, appName, appName, appName))
|
`, appName, timeout, appName, appName, appName))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Copypasta from https://github.com/docker/cli/blob/master/cli/command/stack/swarm/list.go because I could't import "github.com/docker/cli/cli/command/stack/swarm"
|
||||||
|
// GetStacks lists the swarm stacks.
|
||||||
|
func GetStacks(cl *dockerclient.Client) ([]*formatter.Stack, error) {
|
||||||
|
services, err := cl.ServiceList(
|
||||||
|
context.Background(),
|
||||||
|
types.ServiceListOptions{Filters: getAllStacksFilter()})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m := make(map[string]*formatter.Stack)
|
||||||
|
for _, service := range services {
|
||||||
|
labels := service.Spec.Labels
|
||||||
|
name, ok := labels[convert.LabelNamespace]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.Errorf("cannot get label %s for service %s",
|
||||||
|
convert.LabelNamespace, service.ID)
|
||||||
|
}
|
||||||
|
ztack, ok := m[name]
|
||||||
|
if !ok {
|
||||||
|
m[name] = &formatter.Stack{
|
||||||
|
Name: name,
|
||||||
|
Services: 1,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ztack.Services++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var stacks []*formatter.Stack
|
||||||
|
for _, stack := range m {
|
||||||
|
stacks = append(stacks, stack)
|
||||||
|
}
|
||||||
|
return stacks, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue