summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaye Doepke <jtdoepke@users.noreply.github.com>2024-07-17 14:57:15 -0500
committerGitHub <noreply@github.com>2024-07-17 15:57:15 -0400
commit50360e994a8141fc0aeaafae126a74a9b833fe31 (patch)
tree9dce663940778a13b9849d3a81ddf026bff6032e
parent2bf4b0aee7680b93ced3c5ee14b27527f9a1920a (diff)
Preserve field order when updating kustomization.yaml file (#666)
Signed-off-by: Jaye Doepke <jdoepke@mintel.com>
-rw-r--r--pkg/argocd/git.go34
-rw-r--r--pkg/argocd/git_test.go72
2 files changed, 104 insertions, 2 deletions
diff --git a/pkg/argocd/git.go b/pkg/argocd/git.go
index d3216d9..f984790 100644
--- a/pkg/argocd/git.go
+++ b/pkg/argocd/git.go
@@ -12,6 +12,7 @@ import (
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/types"
+ "sigs.k8s.io/kustomize/kyaml/order"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
"github.com/argoproj-labs/argocd-image-updater/pkg/image"
@@ -327,14 +328,43 @@ func writeKustomization(app *v1alpha1.Application, wbc *WriteBackConfig, gitC gi
if err != nil {
return err, false
}
- err = kyaml.UpdateFile(filterFunc, kustFile)
- if err != nil {
+
+ if err = updateKustomizeFile(filterFunc, kustFile); err != nil {
return err, false
}
return nil, false
}
+// updateKustomizeFile reads the kustomization file at path, applies the filter to it, and writes the result back
+// to the file. This is the same behavior as kyaml.UpdateFile, but it preserves the original order
+// of YAML fields to minimize git diffs.
+func updateKustomizeFile(filter kyaml.Filter, path string) error {
+ // Read the yaml
+ y, err := kyaml.ReadFile(path)
+ if err != nil {
+ return err
+ }
+
+ // Update the yaml
+ yCpy := y.Copy()
+ if err := yCpy.PipeE(filter); err != nil {
+ return err
+ }
+
+ // Preserve the original order of fields
+ if err := order.SyncOrder(y, yCpy); err != nil {
+ return err
+ }
+
+ // Write the yaml
+ if err := kyaml.WriteFile(yCpy, path); err != nil {
+ return err
+ }
+
+ return nil
+}
+
func imagesFilter(images v1alpha1.KustomizeImages) (kyaml.Filter, error) {
var overrides []kyaml.Filter
for _, img := range images {
diff --git a/pkg/argocd/git_test.go b/pkg/argocd/git_test.go
index 69f7027..2b6ce2c 100644
--- a/pkg/argocd/git_test.go
+++ b/pkg/argocd/git_test.go
@@ -1,6 +1,7 @@
package argocd
import (
+ "os"
"testing"
"text/template"
"time"
@@ -215,3 +216,74 @@ images:
})
}
}
+
+func Test_updateKustomizeFile(t *testing.T) {
+ makeTmpKustomization := func(t *testing.T, content []byte) string {
+ f, err := os.CreateTemp("", "kustomization-*.yaml")
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = f.Write(content)
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.Close()
+ t.Cleanup(func() {
+ os.Remove(f.Name())
+ })
+ return f.Name()
+ }
+
+ filter, err := imagesFilter(v1alpha1.KustomizeImages{"foo@sha23456"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ tests := []struct {
+ name string
+ content string
+ wantContent string
+ filter kyaml.Filter
+ wantErr bool
+ }{
+ {
+ name: "sorted",
+ content: `images:
+- digest: sha12345
+ name: foo
+`,
+ wantContent: `images:
+- digest: sha23456
+ name: foo
+`,
+ filter: filter,
+ },
+ {
+ name: "not-sorted",
+ content: `images:
+- name: foo
+ digest: sha12345
+`,
+ wantContent: `images:
+- name: foo
+ digest: sha23456
+`,
+ filter: filter,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ path := makeTmpKustomization(t, []byte(tt.content))
+ err := updateKustomizeFile(tt.filter, path)
+ if tt.wantErr {
+ assert.Error(t, err)
+ } else {
+ got, err := os.ReadFile(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ assert.Equal(t, tt.wantContent, string(got))
+ }
+ })
+ }
+}