fix: teach app version command to read new versions

This commit is contained in:
decentral1se 2021-10-14 11:29:57 +02:00
parent b69aed3bcf
commit d0828c4d8d
No known key found for this signature in database
GPG Key ID: 5E2EF5A63E3718CC
3 changed files with 57 additions and 53 deletions

View File

@ -2,12 +2,12 @@ package app
import ( import (
"fmt" "fmt"
"sort"
"strings" "strings"
abraFormatter "coopcloud.tech/abra/cli/formatter" abraFormatter "coopcloud.tech/abra/cli/formatter"
"coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/cli/internal"
appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/catalogue"
"coopcloud.tech/abra/pkg/client"
"coopcloud.tech/abra/pkg/client/stack" "coopcloud.tech/abra/pkg/client/stack"
"coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/config"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
@ -32,65 +32,56 @@ func getImagePath(image string) (string, error) {
var appVersionCommand = &cli.Command{ var appVersionCommand = &cli.Command{
Name: "version", Name: "version",
Aliases: []string{"v"}, Aliases: []string{"v"},
Usage: "Show version of all services in app", Usage: "Show app version",
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
app := internal.ValidateApp(c) app := internal.ValidateApp(c)
stackName := app.StackName()
composeFiles, err := config.GetAppComposeFiles(app.Type, app.Env) cl, err := client.New(app.Server)
if err != nil {
logrus.Fatal(err)
}
opts := stack.Deploy{Composefiles: composeFiles}
compose, err := config.GetAppComposeConfig(app.Type, opts, app.Env)
if err != nil { if err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
ch := make(chan stack.StackStatus, len(compose.Services)) logrus.Debugf("checking whether '%s' is already deployed", stackName)
for _, service := range compose.Services {
label := fmt.Sprintf("coop-cloud.%s.%s.version", app.StackName(), service.Name) isDeployed, deployedVersion, err := stack.IsDeployed(c.Context, cl, stackName)
go func(s string, l string) { if err != nil {
ch <- stack.GetDeployedServicesByLabel(s, l) logrus.Fatal(err)
}(app.Server, label)
} }
tableCol := []string{"name", "image", "version", "digest"} if deployedVersion == "" {
logrus.Fatalf("failed to determine version of deployed '%s'", app.Name)
}
if !isDeployed {
logrus.Fatalf("'%s' is not deployed?", app.Name)
}
recipeMeta, err := catalogue.GetRecipeMeta(app.Type)
if err != nil {
logrus.Fatal(err)
}
versionsMeta := make(map[string]catalogue.ServiceMeta)
for _, recipeVersion := range recipeMeta.Versions {
if currentVersion, exists := recipeVersion[deployedVersion]; exists {
versionsMeta = currentVersion
}
}
if len(versionsMeta) == 0 {
logrus.Fatalf("PANIC: could not retrieve deployed version ('%s') from recipe catalogue?", deployedVersion)
}
tableCol := []string{"name", "image", "version", "tag", "digest"}
table := abraFormatter.CreateTable(tableCol) table := abraFormatter.CreateTable(tableCol)
statuses := make(map[string]stack.StackStatus) for serviceName, versionMeta := range versionsMeta {
for range compose.Services { table.Append([]string{serviceName, versionMeta.Image, deployedVersion, versionMeta.Tag, versionMeta.Digest})
status := <-ch
if len(status.Services) > 0 {
serviceName := appPkg.ParseServiceName(status.Services[0].Spec.Name)
statuses[serviceName] = status
}
}
sort.SliceStable(compose.Services, func(i, j int) bool {
return compose.Services[i].Name < compose.Services[j].Name
})
for _, service := range compose.Services {
if status, ok := statuses[service.Name]; ok {
statusService := status.Services[0]
label := fmt.Sprintf("coop-cloud.%s.%s.version", app.StackName(), service.Name)
version, digest := appPkg.ParseVersionLabel(statusService.Spec.Labels[label])
image, err := getImagePath(statusService.Spec.Labels["com.docker.stack.image"])
if err != nil {
logrus.Fatal(err)
}
table.Append([]string{service.Name, image, version, digest})
continue
}
image, err := getImagePath(service.Image)
if err != nil {
logrus.Fatal(err)
}
table.Append([]string{service.Name, image, "?", "?"})
} }
table.Render() table.Render()
return nil return nil
}, },
BashComplete: func(c *cli.Context) { BashComplete: func(c *cli.Context) {

View File

@ -54,15 +54,15 @@ type tag = string
// service represents a service within a recipe. // service represents a service within a recipe.
type service = string type service = string
// serviceMeta represents meta info associated with a service. // ServiceMeta represents meta info associated with a service.
type serviceMeta struct { type ServiceMeta struct {
Digest string `json:"digest"` Digest string `json:"digest"`
Image string `json:"image"` Image string `json:"image"`
Tag string `json:"tag"` Tag string `json:"tag"`
} }
// RecipeVersions are the versions associated with a recipe. // RecipeVersions are the versions associated with a recipe.
type RecipeVersions []map[tag]map[service]serviceMeta type RecipeVersions []map[tag]map[service]ServiceMeta
// RecipeMeta represents metadata for a recipe in the abra catalogue. // RecipeMeta represents metadata for a recipe in the abra catalogue.
type RecipeMeta struct { type RecipeMeta struct {
@ -420,7 +420,7 @@ func GetRecipeVersions(recipeName string) (RecipeVersions, error) {
return err return err
} }
versionMeta := make(map[string]serviceMeta) versionMeta := make(map[string]ServiceMeta)
for _, service := range recipe.Config.Services { for _, service := range recipe.Config.Services {
img, err := reference.ParseNormalizedNamed(service.Image) img, err := reference.ParseNormalizedNamed(service.Image)
@ -438,7 +438,7 @@ func GetRecipeVersions(recipeName string) (RecipeVersions, error) {
return err return err
} }
versionMeta[service.Name] = serviceMeta{ versionMeta[service.Name] = ServiceMeta{
Digest: digest, Digest: digest,
Image: path, Image: path,
Tag: img.(reference.NamedTagged).Tag(), Tag: img.(reference.NamedTagged).Tag(),
@ -447,7 +447,7 @@ func GetRecipeVersions(recipeName string) (RecipeVersions, error) {
logrus.Debugf("collecting digest: '%s', image: '%s', tag: '%s'", digest, path, tag) logrus.Debugf("collecting digest: '%s', image: '%s', tag: '%s'", digest, path, tag)
} }
versions = append(versions, map[string]map[string]serviceMeta{tag: versionMeta}) versions = append(versions, map[string]map[string]ServiceMeta{tag: versionMeta})
return nil return nil
}); err != nil { }); err != nil {

View File

@ -93,6 +93,19 @@ func GetAllDeployedServices(contextName string) StackStatus {
return StackStatus{services, nil} return StackStatus{services, nil}
} }
// GetDeployedServicesByName filters services by name
func GetDeployedServicesByName(ctx context.Context, cl *dockerclient.Client, stackName, serviceName string) StackStatus {
filters := filters.NewArgs()
filters.Add("name", fmt.Sprintf("%s_%s", stackName, serviceName))
services, err := cl.ServiceList(ctx, types.ServiceListOptions{Filters: filters})
if err != nil {
return StackStatus{[]swarm.Service{}, err}
}
return StackStatus{services, nil}
}
// IsDeployed chekcks whether an appp is deployed or not. // IsDeployed chekcks whether an appp is deployed or not.
func IsDeployed(ctx context.Context, cl *dockerclient.Client, stackName string) (bool, string, error) { func IsDeployed(ctx context.Context, cl *dockerclient.Client, stackName string) (bool, string, error) {
version := "" version := ""