forked from coop-cloud/abra
pass all errors to the Command function
This commit is contained in:
parent
9564673a10
commit
5a7fe9971a
|
@ -63,9 +63,15 @@ var Notify = cli.Command{
|
|||
}
|
||||
for _, stackInfo := range stacks {
|
||||
stackName := stackInfo.Name
|
||||
recipeName := getLabel(cl, stackName, "recipe")
|
||||
recipeName, err := getLabel(cl, stackName, "recipe")
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
if recipeName != "" {
|
||||
getLatestUpgrade(cl, stackName, recipeName)
|
||||
_, err = getLatestUpgrade(cl, stackName, recipeName)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -120,47 +126,51 @@ var UpgradeApp = cli.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func getLabel(cl *dockerclient.Client, stackName string, label string) string {
|
||||
// getLabel reads docker label in the format coop-cloud.${STACK_NAME}.${LABEL}
|
||||
func getLabel(cl *dockerclient.Client, stackName string, label string) (string, error) {
|
||||
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)
|
||||
return "", err
|
||||
}
|
||||
for _, service := range services {
|
||||
labelKey := fmt.Sprintf("coop-cloud.%s.%s", stackName, label)
|
||||
if labelValue, ok := service.Spec.Labels[labelKey]; ok {
|
||||
return labelValue
|
||||
return labelValue, nil
|
||||
}
|
||||
}
|
||||
logrus.Debugf("no %s label found for %s", label, stackName)
|
||||
return ""
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func getBoolLabel(cl *dockerclient.Client, stackName string, label string) bool {
|
||||
lableValue := getLabel(cl, stackName, label)
|
||||
// getBoolLabel reads a boolean docker label
|
||||
func getBoolLabel(cl *dockerclient.Client, stackName string, label string) (bool, error) {
|
||||
lableValue, err := getLabel(cl, stackName, label)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if lableValue != "" {
|
||||
value, err := strconv.ParseBool(lableValue)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return false, err
|
||||
}
|
||||
return value
|
||||
return value, nil
|
||||
}
|
||||
return false
|
||||
logrus.Debugf("Boolean label %s could not be found for %s, set default to false.", label, stackName)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func getEnv(cl *dockerclient.Client, stackName string) config.AppEnv {
|
||||
// getEnv reads Env variables from docker services
|
||||
func getEnv(cl *dockerclient.Client, stackName string) (config.AppEnv, error) {
|
||||
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)
|
||||
return nil, err
|
||||
}
|
||||
for _, service := range services {
|
||||
envList := service.Spec.TaskTemplate.ContainerSpec.Env
|
||||
|
@ -176,17 +186,23 @@ func getEnv(cl *dockerclient.Client, stackName string) config.AppEnv {
|
|||
envMap[k] = v
|
||||
}
|
||||
}
|
||||
return envMap
|
||||
return envMap, nil
|
||||
}
|
||||
|
||||
func getLatestUpgrade(cl *dockerclient.Client, stackName string, recipeName string) string {
|
||||
deployedVersion := getDeployedVersion(cl, stackName, recipeName)
|
||||
availableUpgrades := getAvailableUpgrades(cl, stackName, recipeName, deployedVersion)
|
||||
// getLatestUpgrade returns the latest available version for an app regarding to the --major flag
|
||||
// if it is newer than the currently deployed version
|
||||
func getLatestUpgrade(cl *dockerclient.Client, stackName string, recipeName string) (string, error) {
|
||||
deployedVersion, err := getDeployedVersion(cl, stackName, recipeName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
availableUpgrades, err := getAvailableUpgrades(cl, stackName, recipeName, deployedVersion)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(availableUpgrades) == 0 {
|
||||
logrus.Debugf("no available upgrades for %s", stackName)
|
||||
return ""
|
||||
return "", nil
|
||||
}
|
||||
// Uncomment to select the next version instead of the last version
|
||||
// availableUpgrades = internal.ReverseStringList(availableUpgrades)
|
||||
|
@ -195,42 +211,42 @@ func getLatestUpgrade(cl *dockerclient.Client, stackName string, recipeName stri
|
|||
chosenUpgrade = availableUpgrades[len(availableUpgrades)-1]
|
||||
logrus.Infof("%s (%s) can be upgraded from version %s to %s", stackName, recipeName, deployedVersion, chosenUpgrade)
|
||||
}
|
||||
return chosenUpgrade
|
||||
return chosenUpgrade, nil
|
||||
|
||||
}
|
||||
|
||||
func getDeployedVersion(cl *dockerclient.Client, stackName string, recipeName string) string {
|
||||
// getDeployedVersion returns the currently deployed version of an app
|
||||
func getDeployedVersion(cl *dockerclient.Client, stackName string, recipeName string) (string, error) {
|
||||
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)
|
||||
return "", err
|
||||
}
|
||||
if !isDeployed {
|
||||
logrus.Fatalf("%s is not deployed?", stackName)
|
||||
return "", fmt.Errorf("%s is not deployed?", stackName)
|
||||
}
|
||||
if deployedVersion == "unknown" {
|
||||
logrus.Fatalf("failed to determine deployed version of %s", stackName)
|
||||
return "", fmt.Errorf("failed to determine deployed version of %s", stackName)
|
||||
}
|
||||
return deployedVersion
|
||||
return deployedVersion, nil
|
||||
}
|
||||
|
||||
// getAvailableUpgrades returns all available versions of an app that are newer than
|
||||
// the deployed version. It only includes major steps if the --major flag is set.
|
||||
func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName string,
|
||||
deployedVersion string) []string {
|
||||
deployedVersion string) ([]string, error) {
|
||||
catl, err := recipe.ReadRecipeCatalogue()
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
versions, err := recipe.GetRecipeCatalogueVersions(recipeName, catl)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(versions) == 0 {
|
||||
logrus.Fatalf("no published releases for %s in the recipe catalogue?", recipeName)
|
||||
return nil, fmt.Errorf("no published releases for %s in the recipe catalogue?", recipeName)
|
||||
}
|
||||
|
||||
var availableUpgrades []string
|
||||
|
@ -238,15 +254,15 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName
|
|||
for _, version := range versions {
|
||||
parsedDeployedVersion, err := tagcmp.Parse(deployedVersion)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
parsedVersion, err := tagcmp.Parse(version)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
versionDelta, err := parsedDeployedVersion.UpgradeDelta(parsedVersion)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
if 0 < versionDelta.UpgradeType() && (versionDelta.UpgradeType() < 4 || majorUpdate) {
|
||||
availableUpgrades = append(availableUpgrades, version)
|
||||
|
@ -254,87 +270,100 @@ func getAvailableUpgrades(cl *dockerclient.Client, stackName string, recipeName
|
|||
}
|
||||
logrus.Debugf("Available updates for %s: %s", stackName, availableUpgrades)
|
||||
|
||||
return availableUpgrades
|
||||
return availableUpgrades, nil
|
||||
|
||||
}
|
||||
|
||||
func processRecipeRepoVersion(recipeName string, version string) {
|
||||
// processRecipeRepoVersion clones, pulls, checks out the version and lints the recipe repository
|
||||
func processRecipeRepoVersion(recipeName string, version string) error {
|
||||
if err := recipe.EnsureExists(recipeName); err != nil {
|
||||
logrus.Fatal(err)
|
||||
return err
|
||||
}
|
||||
if err := recipe.EnsureUpToDate(recipeName); err != nil {
|
||||
logrus.Fatal(err)
|
||||
return err
|
||||
}
|
||||
if err := recipe.EnsureVersion(recipeName, version); err != nil {
|
||||
logrus.Fatal(err)
|
||||
return err
|
||||
}
|
||||
if r, err := recipe.Get(recipeName); err != nil {
|
||||
logrus.Fatal(err)
|
||||
return err
|
||||
} else if err := lint.LintForErrors(r); err != nil {
|
||||
logrus.Fatal(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func mergeAbraShEnv(recipeName string, env config.AppEnv) {
|
||||
// mergeAbraShEnv merges abra.sh env's into the app env's
|
||||
func mergeAbraShEnv(recipeName string, env config.AppEnv) error {
|
||||
abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, recipeName, "abra.sh")
|
||||
abraShEnv, err := config.ReadAbraShEnvVars(abraShPath)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return err
|
||||
}
|
||||
for k, v := range abraShEnv {
|
||||
logrus.Debugf("read v:%s k: %s", v, k)
|
||||
env[k] = v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createDeployConfig(recipeName string, stackName string, env config.AppEnv) (*composetypes.Config, stack.Deploy) {
|
||||
// createDeployConfig merges and enriches the compose config for the deployment
|
||||
func createDeployConfig(recipeName string, stackName string, env config.AppEnv) (*composetypes.Config, stack.Deploy, error) {
|
||||
// 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,
|
||||
}
|
||||
composeFiles, err := config.GetAppComposeFiles(recipeName, env)
|
||||
if err != nil {
|
||||
return nil, deployOpts, err
|
||||
}
|
||||
deployOpts.Composefiles = composeFiles
|
||||
compose, err := config.GetAppComposeConfig(stackName, deployOpts, env)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
return nil, deployOpts, 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)
|
||||
config.SetUpdateLabel(compose, stackName, env)
|
||||
return compose, deployOpts
|
||||
return compose, deployOpts, nil
|
||||
}
|
||||
}
|
||||
|
||||
func upgrade(cl *dockerclient.Client, stackName string, recipeName string, upgradeVersion string) {
|
||||
// upgrade performs all necessary steps to upgrade an app
|
||||
func upgrade(cl *dockerclient.Client, stackName string, recipeName string, upgradeVersion string) error {
|
||||
env, err := getEnv(cl, stackName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
app := config.App{
|
||||
Name: stackName,
|
||||
Recipe: recipeName,
|
||||
Env: getEnv(cl, stackName),
|
||||
Server: SERVER,
|
||||
Env: env,
|
||||
}
|
||||
|
||||
processRecipeRepoVersion(recipeName, upgradeVersion)
|
||||
if err = processRecipeRepoVersion(recipeName, upgradeVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mergeAbraShEnv(recipeName, app.Env)
|
||||
if err = mergeAbraShEnv(recipeName, app.Env); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
compose, deployOpts := createDeployConfig(recipeName, stackName, app.Env)
|
||||
compose, deployOpts, err := createDeployConfig(recipeName, stackName, app.Env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Infof("Upgrade %s (%s) to version %s", stackName, recipeName, upgradeVersion)
|
||||
if err := stack.RunDeploy(cl, deployOpts, compose, stackName, true); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
err = stack.RunDeploy(cl, deployOpts, compose, stackName, true)
|
||||
return err
|
||||
}
|
||||
|
||||
func newAbraApp(version, commit string) *cli.App {
|
||||
|
|
Loading…
Reference in New Issue