parent
03041b88d0
commit
6fe5aed408
|
@ -85,12 +85,12 @@ version.
|
||||||
logrus.Fatalf("could not retrieve deployed version (%s) from recipe catalogue?", deployedVersion)
|
logrus.Fatalf("could not retrieve deployed version (%s) from recipe catalogue?", deployedVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
tableCol := []string{"version", "service", "image", "digest"}
|
tableCol := []string{"version", "service", "image"}
|
||||||
table := formatter.CreateTable(tableCol)
|
table := formatter.CreateTable(tableCol)
|
||||||
table.SetAutoMergeCellsByColumnIndex([]int{0})
|
table.SetAutoMergeCellsByColumnIndex([]int{0})
|
||||||
|
|
||||||
for serviceName, versionMeta := range versionsMeta {
|
for serviceName, versionMeta := range versionsMeta {
|
||||||
table.Append([]string{deployedVersion, serviceName, versionMeta.Image, versionMeta.Digest})
|
table.Append([]string{deployedVersion, serviceName, versionMeta.Image})
|
||||||
}
|
}
|
||||||
|
|
||||||
table.Render()
|
table.Render()
|
||||||
|
|
|
@ -32,13 +32,13 @@ var recipeVersionCommand = cli.Command{
|
||||||
logrus.Fatalf("%s recipe doesn't exist?", recipe.Name)
|
logrus.Fatalf("%s recipe doesn't exist?", recipe.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
tableCol := []string{"Version", "Service", "Image", "Tag", "Digest"}
|
tableCol := []string{"Version", "Service", "Image", "Tag"}
|
||||||
table := formatter.CreateTable(tableCol)
|
table := formatter.CreateTable(tableCol)
|
||||||
|
|
||||||
for i := len(recipeMeta.Versions) - 1; i >= 0; i-- {
|
for i := len(recipeMeta.Versions) - 1; i >= 0; i-- {
|
||||||
for tag, meta := range recipeMeta.Versions[i] {
|
for tag, meta := range recipeMeta.Versions[i] {
|
||||||
for service, serviceMeta := range meta {
|
for service, serviceMeta := range meta {
|
||||||
table.Append([]string{tag, service, serviceMeta.Image, serviceMeta.Tag, serviceMeta.Digest})
|
table.Append([]string{tag, service, serviceMeta.Image, serviceMeta.Tag})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/config"
|
"coopcloud.tech/abra/pkg/config"
|
||||||
"coopcloud.tech/abra/pkg/upstream/stack"
|
|
||||||
apiclient "github.com/docker/docker/client"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,45 +33,6 @@ type deployedServiceSpec struct {
|
||||||
// VersionSpec represents a deployed app and associated metadata.
|
// VersionSpec represents a deployed app and associated metadata.
|
||||||
type VersionSpec map[string]deployedServiceSpec
|
type VersionSpec map[string]deployedServiceSpec
|
||||||
|
|
||||||
// DeployedVersions lists metadata (e.g. versions) for deployed
|
|
||||||
func DeployedVersions(ctx context.Context, cl *apiclient.Client, app config.App) (VersionSpec, bool, error) {
|
|
||||||
services, err := stack.GetStackServices(ctx, cl, app.StackName())
|
|
||||||
if err != nil {
|
|
||||||
return VersionSpec{}, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
appSpec := make(VersionSpec)
|
|
||||||
for _, service := range services {
|
|
||||||
serviceName := ParseServiceName(service.Spec.Name)
|
|
||||||
label := fmt.Sprintf("coop-cloud.%s.%s.version", app.StackName(), serviceName)
|
|
||||||
if deployLabel, ok := service.Spec.Labels[label]; ok {
|
|
||||||
version, _ := ParseVersionLabel(deployLabel)
|
|
||||||
appSpec[serviceName] = deployedServiceSpec{Name: serviceName, Version: version}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deployed := len(services) > 0
|
|
||||||
|
|
||||||
if deployed {
|
|
||||||
logrus.Debugf("detected %s as deployed versions of %s", appSpec, app.Name)
|
|
||||||
} else {
|
|
||||||
logrus.Debugf("detected %s as not deployed", app.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return appSpec, len(services) > 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseVersionLabel parses a $VERSION-$DIGEST app service label.
|
|
||||||
func ParseVersionLabel(label string) (string, string) {
|
|
||||||
// versions may look like v4.2-abcd or v4.2-alpine-abcd
|
|
||||||
idx := strings.LastIndex(label, "-")
|
|
||||||
version := label[:idx]
|
|
||||||
digest := label[idx+1:]
|
|
||||||
logrus.Debugf("parsed %s as version from %s", version, label)
|
|
||||||
logrus.Debugf("parsed %s as digest from %s", digest, label)
|
|
||||||
return version, digest
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseServiceName parses a $STACK_NAME_$SERVICE_NAME service label.
|
// ParseServiceName parses a $STACK_NAME_$SERVICE_NAME service label.
|
||||||
func ParseServiceName(label string) string {
|
func ParseServiceName(label string) string {
|
||||||
idx := strings.LastIndex(label, "_")
|
idx := strings.LastIndex(label, "_")
|
||||||
|
|
|
@ -3,13 +3,10 @@ package client
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containers/image/docker"
|
"github.com/containers/image/docker"
|
||||||
"github.com/containers/image/types"
|
"github.com/containers/image/types"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/docker/docker/client"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetRegistryTags retrieves all tags of an image from a container registry.
|
// GetRegistryTags retrieves all tags of an image from a container registry.
|
||||||
|
@ -29,29 +26,3 @@ func GetRegistryTags(img reference.Named) ([]string, error) {
|
||||||
|
|
||||||
return tags, nil
|
return tags, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTagDigest retrieves an image digest from a container registry.
|
|
||||||
func GetTagDigest(cl *client.Client, image reference.Named) (string, error) {
|
|
||||||
target := fmt.Sprintf("//%s", reference.Path(image))
|
|
||||||
|
|
||||||
ref, err := docker.ParseReference(target)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to parse image %s, saw: %s", image, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
img, err := ref.NewImage(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Debugf("failed to query remote registry for %s, saw: %s", image, err.Error())
|
|
||||||
return "", fmt.Errorf("unable to read digest for %s", image)
|
|
||||||
}
|
|
||||||
defer img.Close()
|
|
||||||
|
|
||||||
digest := img.ConfigInfo().Digest.String()
|
|
||||||
|
|
||||||
if digest == "" {
|
|
||||||
return digest, fmt.Errorf("unable to read digest for %s", image)
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Split(digest, ":")[1][:7], nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/client"
|
|
||||||
"coopcloud.tech/abra/pkg/compose"
|
"coopcloud.tech/abra/pkg/compose"
|
||||||
"coopcloud.tech/abra/pkg/config"
|
"coopcloud.tech/abra/pkg/config"
|
||||||
"coopcloud.tech/abra/pkg/formatter"
|
"coopcloud.tech/abra/pkg/formatter"
|
||||||
|
@ -41,9 +40,8 @@ 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"`
|
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.
|
||||||
|
@ -992,12 +990,6 @@ func GetRecipeVersions(recipeName string) (RecipeVersions, error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cl, err := client.New("default") // only required for container registry calls
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
queryCache := make(map[reference.Named]string)
|
|
||||||
versionMeta := make(map[string]ServiceMeta)
|
versionMeta := make(map[string]ServiceMeta)
|
||||||
for _, service := range recipe.Config.Services {
|
for _, service := range recipe.Config.Services {
|
||||||
|
|
||||||
|
@ -1019,28 +1011,9 @@ func GetRecipeVersions(recipeName string) (RecipeVersions, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var exists bool
|
|
||||||
var digest string
|
|
||||||
if digest, exists = queryCache[img]; !exists {
|
|
||||||
logrus.Debugf("cache miss: querying for image: %s, tag: %s", path, tag)
|
|
||||||
|
|
||||||
var err error
|
|
||||||
digest, err = client.GetTagDigest(cl, img)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Warn(err)
|
|
||||||
digest = "unknown"
|
|
||||||
}
|
|
||||||
|
|
||||||
queryCache[img] = digest
|
|
||||||
logrus.Debugf("cached insert: %s, tag: %s, digest: %s", path, tag, digest)
|
|
||||||
} else {
|
|
||||||
logrus.Debugf("cache hit: image: %s, tag: %s, digest: %s", path, tag, digest)
|
|
||||||
}
|
|
||||||
|
|
||||||
versionMeta[service.Name] = ServiceMeta{
|
versionMeta[service.Name] = ServiceMeta{
|
||||||
Digest: digest,
|
Image: path,
|
||||||
Image: path,
|
Tag: tag,
|
||||||
Tag: img.(reference.NamedTagged).Tag(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue