From 5557e1ff3cf2db88fbf7bfb34aad407a021ef146 Mon Sep 17 00:00:00 2001 From: Phillip Wittrock Date: Thu, 12 Nov 2020 08:29:07 -0800 Subject: [PATCH] Retain element ordering when merge resources --- kyaml/kio/filters/merge.go | 7 +- kyaml/kio/filters/merge_test.go | 115 ++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 kyaml/kio/filters/merge_test.go diff --git a/kyaml/kio/filters/merge.go b/kyaml/kio/filters/merge.go index 9a59b5102..5159052cc 100644 --- a/kyaml/kio/filters/merge.go +++ b/kyaml/kio/filters/merge.go @@ -41,6 +41,8 @@ func (c MergeFilter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) { // index the Resources by G/V/K/NS/N index := map[mergeKey][]*yaml.RNode{} + // retain the original ordering + var order []mergeKey for i := range input { meta, err := input[i].GetMeta() if err != nil { @@ -52,13 +54,16 @@ func (c MergeFilter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) { namespace: meta.Namespace, name: meta.Name, } + if _, found := index[key]; !found { + order = append(order, key) + } index[key] = append(index[key], input[i]) } // merge each of the G/V/K/NS/N lists var output []*yaml.RNode var err error - for k := range index { + for _, k := range order { var merged *yaml.RNode resources := index[k] for i := range resources { diff --git a/kyaml/kio/filters/merge_test.go b/kyaml/kio/filters/merge_test.go new file mode 100644 index 000000000..51b5d71d4 --- /dev/null +++ b/kyaml/kio/filters/merge_test.go @@ -0,0 +1,115 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package filters_test + +import ( + "bytes" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "sigs.k8s.io/kustomize/kyaml/kio" + "sigs.k8s.io/kustomize/kyaml/kio/filters" + "sigs.k8s.io/kustomize/kyaml/yaml" +) + +// TestMerge_Merge_order tests that the original order of elements +// retained after merge +func TestMerge_Merge_order(t *testing.T) { + r1, err := yaml.Parse(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: foo-1 + namespace: bar-1 +spec: + template: + spec: {} +`) + if !assert.NoError(t, err) { + t.FailNow() + } + + r2, err := yaml.Parse(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: foo-2 + namespace: bar-2 +spec: + template: + spec: {} +`) + if !assert.NoError(t, err) { + t.FailNow() + } + + var b bytes.Buffer + err = kio.Pipeline{ + Inputs: []kio.Reader{&kio.PackageBuffer{Nodes: []*yaml.RNode{r1, r2}}}, + Filters: []kio.Filter{filters.MatchFilter{}}, + Outputs: []kio.Writer{&kio.ByteWriter{Writer: &b}}, + }.Execute() + if !assert.NoError(t, err) { + t.FailNow() + } + + expected := strings.TrimSpace(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: foo-1 + namespace: bar-1 +spec: + template: + spec: {} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: foo-2 + namespace: bar-2 +spec: + template: + spec: {} +`) + + if !assert.Equal(t, expected, strings.TrimSpace(b.String())) { + t.FailNow() + } + + b.Reset() + err = kio.Pipeline{ + Inputs: []kio.Reader{&kio.PackageBuffer{Nodes: []*yaml.RNode{r2, r1}}}, + Filters: []kio.Filter{filters.MatchFilter{}}, + Outputs: []kio.Writer{&kio.ByteWriter{Writer: &b}}, + }.Execute() + if !assert.NoError(t, err) { + t.FailNow() + } + + expected = strings.TrimSpace(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: foo-2 + namespace: bar-2 +spec: + template: + spec: {} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: foo-1 + namespace: bar-1 +spec: + template: + spec: {} +`) + + if !assert.Equal(t, expected, strings.TrimSpace(b.String())) { + t.FailNow() + } +}