From e73b0cc2fc4f4c39db16a591044f1098d74c6cdc Mon Sep 17 00:00:00 2001 From: 3wc <3wc@doesthisthing.work> Date: Mon, 8 Sep 2025 11:57:22 -0400 Subject: [PATCH] refactor: don't reinvent the wheel --- pkg/deploy/utils.go | 33 ++++++--------- pkg/deploy/utils_test.go | 87 ---------------------------------------- 2 files changed, 13 insertions(+), 107 deletions(-) delete mode 100644 pkg/deploy/utils_test.go diff --git a/pkg/deploy/utils.go b/pkg/deploy/utils.go index 2e67c325..e8e53e23 100644 --- a/pkg/deploy/utils.go +++ b/pkg/deploy/utils.go @@ -2,19 +2,19 @@ package deploy import ( "context" - "errors" "fmt" - "regexp" "sort" "strings" appPkg "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/envfile" + "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/abra/pkg/secret" + "github.com/distribution/reference" composetypes "github.com/docker/cli/cli/compose/types" "github.com/docker/docker/api/types/swarm" dockerClient "github.com/docker/docker/client" @@ -82,19 +82,6 @@ func GetConfigsForStack(cl *dockerClient.Client, app appPkg.App) (map[string]str return configs, nil } -func GetImageNameAndTag(imageName string) (string, string, error) { - imageParts := regexp.MustCompile("^([^:]*):([^@]*)@?").FindSubmatch([]byte(imageName)) - - if len(imageParts) == 0 { - return "", "", errors.New("can't determine image version for image '%s'") - } - - imageBaseName := string(imageParts[1]) - imageTag := string(imageParts[2]) - - return imageBaseName, imageTag, nil -} - // GetImagesForStack retrieves all Docker images for services in a given stack. func GetImagesForStack(cl *dockerClient.Client, app appPkg.App) (map[string]string, error) { filters, err := app.Filters(false, false) @@ -116,12 +103,15 @@ func GetImagesForStack(cl *dockerClient.Client, app appPkg.App) (map[string]stri if service.Spec.TaskTemplate.ContainerSpec != nil { imageName := service.Spec.TaskTemplate.ContainerSpec.Image - imageBaseName, imageTag, err := GetImageNameAndTag(imageName) + imageParsed, err := reference.ParseNormalizedNamed(imageName) if err != nil { log.Warn(err) continue } + imageBaseName := reference.Path(imageParsed) + imageTag := imageParsed.(reference.NamedTagged).Tag() + existingImageVersion, ok := images[imageBaseName] if !ok { // First time seeing this, add to map @@ -210,7 +200,10 @@ func GatherImagesForDeploy(cl *dockerClient.Client, app appPkg.App, compose *com newImages := make(map[string]string) for _, service := range compose.Services { - imageBaseName, imageTag, err := GetImageNameAndTag(service.Image) + imageParsed, err := reference.ParseNormalizedNamed(service.Image) + imageBaseName := reference.Path(imageParsed) + imageTag := imageParsed.(reference.NamedTagged).Tag() + if err != nil { log.Warn(err) continue @@ -233,13 +226,13 @@ func GatherImagesForDeploy(cl *dockerClient.Client, app appPkg.App, compose *com if currentVersion, exists := currentImages[newImageName]; exists { if currentVersion == newImageVersion { if showUnchanged { - imageInfo = append(imageInfo, fmt.Sprintf("%s: %s (unchanged)", newImageName, newImageVersion)) + imageInfo = append(imageInfo, fmt.Sprintf("%s: %s (unchanged)", formatter.StripTagMeta(newImageName), newImageVersion)) } } else { - imageInfo = append(imageInfo, fmt.Sprintf("%s: %s → %s", newImageName, currentVersion, newImageVersion)) + imageInfo = append(imageInfo, fmt.Sprintf("%s: %s → %s", formatter.StripTagMeta(newImageName), currentVersion, newImageVersion)) } } else { - imageInfo = append(imageInfo, fmt.Sprintf("%s: %s (new)", newImageName, newImageVersion)) + imageInfo = append(imageInfo, fmt.Sprintf("%s: %s (new)", formatter.StripTagMeta(newImageName), newImageVersion)) } } diff --git a/pkg/deploy/utils_test.go b/pkg/deploy/utils_test.go deleted file mode 100644 index a0735d14..00000000 --- a/pkg/deploy/utils_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package deploy - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestGetImageNameAndTag(t *testing.T) { - tests := []struct { - name string - imageName string - expectedName string - expectedTag string - expectError bool - description string - }{ - { - name: "standard image with tag", - imageName: "nginx:1.23", - expectedName: "nginx", - expectedTag: "1.23", - expectError: false, - description: "should parse standard image name with tag", - }, - { - name: "image with digest", - imageName: "nginx:1.23@sha256:abc123", - expectedName: "nginx", - expectedTag: "1.23", - expectError: false, - description: "should parse image with digest, ignoring digest part", - }, - { - name: "image with latest tag", - imageName: "redis:latest", - expectedName: "redis", - expectedTag: "latest", - expectError: false, - description: "should parse image with latest tag", - }, - { - name: "image with numeric tag", - imageName: "postgres:14", - expectedName: "postgres", - expectedTag: "14", - expectError: false, - description: "should parse image with numeric tag", - }, - { - name: "image with complex name", - imageName: "registry.example.com/myapp/api:v1.2.3", - expectedName: "registry.example.com/myapp/api", - expectedTag: "v1.2.3", - expectError: false, - description: "should parse image with registry prefix and complex name", - }, - { - name: "image without tag", - imageName: "nginx", - expectError: true, - description: "should error when no tag present", - }, - { - name: "empty image name", - imageName: "", - expectError: true, - description: "should error on empty image name", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - name, tag, err := GetImageNameAndTag(tt.imageName) - - if tt.expectError { - assert.Error(t, err) - assert.Empty(t, name) - assert.Empty(t, tag) - } else { - assert.NoError(t, err) - assert.Equal(t, tt.expectedName, name) - assert.Equal(t, tt.expectedTag, tag) - } - }) - } -}