Skip to content

Commit

Permalink
feat(directives): set all images without explicit config
Browse files Browse the repository at this point in the history
Signed-off-by: Hidde Beydals <[email protected]>
  • Loading branch information
hiddeco committed Dec 10, 2024
1 parent 622a656 commit e075ca2
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 20 deletions.
40 changes: 37 additions & 3 deletions internal/directives/kustomize_image_setter.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,15 @@ func (k *kustomizeImageSetter) runPromotionStep(
fmt.Errorf("could not discover kustomization file: %w", err)
}

// Discover image origins and collect target images.
targetImages, err := k.buildTargetImages(ctx, stepCtx, cfg.Images)
var targetImages map[string]kustypes.Image
switch {
case len(cfg.Images) > 0:
// Discover image origins and collect target images.
targetImages, err = k.buildTargetImagesFromConfig(ctx, stepCtx, cfg.Images)
default:
// Attempt to automatically set target images based on the Freight references.
targetImages, err = k.buildTargetImagesAutomatically(stepCtx)
}
if err != nil {
return PromotionStepResult{Status: kargoapi.PromotionPhaseErrored}, err
}
Expand All @@ -111,7 +118,7 @@ func (k *kustomizeImageSetter) runPromotionStep(
return result, nil
}

func (k *kustomizeImageSetter) buildTargetImages(
func (k *kustomizeImageSetter) buildTargetImagesFromConfig(
ctx context.Context,
stepCtx *PromotionStepContext,
images []KustomizeSetImageConfigImage,
Expand Down Expand Up @@ -159,6 +166,33 @@ func (k *kustomizeImageSetter) buildTargetImages(
return targetImages, nil
}

func (k *kustomizeImageSetter) buildTargetImagesAutomatically(
stepCtx *PromotionStepContext,
) (map[string]kustypes.Image, error) {
var images = make(map[string]kustypes.Image)
for _, freightRef := range stepCtx.Freight.References() {
if len(freightRef.Images) == 0 {
continue
}

for _, img := range freightRef.Images {
if _, ok := images[img.RepoURL]; ok {
return nil, fmt.Errorf(
"manual configuration required due to ambiguous result: found multiple images for repository %q",
img.RepoURL,
)
}

images[img.RepoURL] = kustypes.Image{
Name: img.RepoURL,
NewTag: img.Tag,
Digest: img.Digest,
}
}
}
return images, nil
}

func (k *kustomizeImageSetter) generateCommitMessage(path string, images map[string]kustypes.Image) string {
if len(images) == 0 {
return ""
Expand Down
133 changes: 116 additions & 17 deletions internal/directives/kustomize_image_setter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,6 @@ func Test_kustomizeImageSetter_validate(t *testing.T) {
"path: String length must be greater than or equal to 1",
},
},
{
name: "images is null",
config: Config{},
expectedProblems: []string{
"(root): images is required",
},
},
{
name: "images is empty",
config: Config{
"images": []Config{},
},
expectedProblems: []string{
"images: Array must have at least 1 items",
},
},
{
name: "image not specified",
config: Config{
Expand Down Expand Up @@ -259,6 +243,51 @@ kind: Kustomization
assert.Contains(t, string(b), "newTag: 1.21.0")
},
},
{
name: "automatically sets image",
setupFiles: func(t *testing.T) string {
tempDir := t.TempDir()
kustomizationContent := `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`
err := os.WriteFile(filepath.Join(tempDir, "kustomization.yaml"), []byte(kustomizationContent), 0o600)
require.NoError(t, err)
return tempDir
},
cfg: KustomizeSetImageConfig{
Path: ".",
Images: nil, // Automatically set all images
},
setupStepCtx: func(_ *testing.T, workDir string) *PromotionStepContext {
return &PromotionStepContext{
WorkDir: workDir,
Freight: kargoapi.FreightCollection{
Freight: map[string]kargoapi.FreightReference{
"Warehouse/warehouse1": {
Images: []kargoapi.Image{{RepoURL: "nginx", Digest: "sha256:123"}},
},
"Warehouse/warehouse2": {
Images: []kargoapi.Image{{RepoURL: "redis", Tag: "6.2.5"}},
},
},
},
}
},
assertions: func(t *testing.T, workDir string, result PromotionStepResult, err error) {
require.NoError(t, err)
assert.Equal(t, PromotionStepResult{
Status: kargoapi.PromotionPhaseSucceeded,
Output: map[string]any{
"commitMessage": "Updated . to use new images\n\n- nginx@sha256:123\n- redis:6.2.5",
},
}, result)

b, err := os.ReadFile(filepath.Join(workDir, "kustomization.yaml"))
require.NoError(t, err)
assert.Contains(t, string(b), "newTag: 6.2.5")
assert.Contains(t, string(b), "digest: sha256:123")
},
},
{
name: "Kustomization file not found",
setupFiles: func(t *testing.T) string {
Expand Down Expand Up @@ -555,7 +584,77 @@ func Test_kustomizeImageSetter_buildTargetImages(t *testing.T) {
},
}

result, err := runner.buildTargetImages(context.Background(), stepCtx, tt.images)
result, err := runner.buildTargetImagesFromConfig(context.Background(), stepCtx, tt.images)
tt.assertions(t, result, err)
})
}
}

func Test_kustomizeImageSetter_buildTargetImagesAutomatically(t *testing.T) {
tests := []struct {
name string
freightReferences map[string]kargoapi.FreightReference
assertions func(*testing.T, map[string]kustypes.Image, error)
}{
{
name: "successfully builds target images",
freightReferences: map[string]kargoapi.FreightReference{
"Warehouse/warehouse1": {
Images: []kargoapi.Image{
{RepoURL: "nginx", Tag: "1.21.0", Digest: "sha256:abcdef1234567890"},
},
},
"Warehouse/warehouse2": {
Images: []kargoapi.Image{
{RepoURL: "redis", Tag: "6.2.5"},
},
},
"Warehouse/warehouse3": {
Images: []kargoapi.Image{
{RepoURL: "postgres", Digest: "sha256:abcdef1234567890"},
},
},
},
assertions: func(t *testing.T, result map[string]kustypes.Image, err error) {
require.NoError(t, err)
assert.Equal(t, map[string]kustypes.Image{
"nginx": {Name: "nginx", NewTag: "1.21.0", Digest: "sha256:abcdef1234567890"},
"redis": {Name: "redis", NewTag: "6.2.5"},
"postgres": {Name: "postgres", Digest: "sha256:abcdef1234567890"},
}, result)
},
},
{
name: "error on ambiguous image match",
freightReferences: map[string]kargoapi.FreightReference{
"Warehouse/warehouse1": {
Images: []kargoapi.Image{
{RepoURL: "nginx", Tag: "1.21.0", Digest: "sha256:abcdef1234567890"},
},
},
"Warehouse/warehouse2": {
Images: []kargoapi.Image{
{RepoURL: "nginx", Tag: "1.21.0", Digest: "sha256:abcdef1234567890"},
},
},
},
assertions: func(t *testing.T, _ map[string]kustypes.Image, err error) {
require.ErrorContains(t, err, "manual configuration required due to ambiguous result")
},
},
}

runner := &kustomizeImageSetter{}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
stepCtx := &PromotionStepContext{
Freight: kargoapi.FreightCollection{
Freight: tt.freightReferences,
},
}

result, err := runner.buildTargetImagesAutomatically(stepCtx)
tt.assertions(t, result, err)
})
}
Expand Down

0 comments on commit e075ca2

Please sign in to comment.