From b72db9e783316f1676e411c36c3cc6d00389d520 Mon Sep 17 00:00:00 2001 From: Phillip Wittrock Date: Thu, 9 Apr 2020 09:23:30 -0700 Subject: [PATCH] ByteReader/Writer support for serializing ResourceList.results field --- kyaml/kio/byteio_reader.go | 12 +- kyaml/kio/byteio_reader_test.go | 485 ++++++++++++++++------------ kyaml/kio/byteio_readwriter_test.go | 263 +++++++++++++++ kyaml/kio/byteio_writer.go | 7 + kyaml/kio/byteio_writer_test.go | 312 ++++++++---------- 5 files changed, 683 insertions(+), 396 deletions(-) create mode 100644 kyaml/kio/byteio_readwriter_test.go diff --git a/kyaml/kio/byteio_reader.go b/kyaml/kio/byteio_reader.go index f7b627c7d..670fb96f5 100644 --- a/kyaml/kio/byteio_reader.go +++ b/kyaml/kio/byteio_reader.go @@ -41,6 +41,8 @@ type ByteReadWriter struct { FunctionConfig *yaml.RNode + Results *yaml.RNode + WrappingAPIVersion string WrappingKind string } @@ -52,6 +54,7 @@ func (rw *ByteReadWriter) Read() ([]*yaml.RNode, error) { } val, err := b.Read() rw.FunctionConfig = b.FunctionConfig + rw.Results = b.Results rw.WrappingAPIVersion = b.WrappingAPIVersion rw.WrappingKind = b.WrappingKind return val, errors.Wrap(err) @@ -63,6 +66,7 @@ func (rw *ByteReadWriter) Write(nodes []*yaml.RNode) error { KeepReaderAnnotations: rw.KeepReaderAnnotations, Style: rw.Style, FunctionConfig: rw.FunctionConfig, + Results: rw.Results, WrappingAPIVersion: rw.WrappingAPIVersion, WrappingKind: rw.WrappingKind, }.Write(nodes) @@ -85,6 +89,8 @@ type ByteReader struct { FunctionConfig *yaml.RNode + Results *yaml.RNode + // DisableUnwrapping prevents Resources in Lists and ResourceLists from being unwrapped DisableUnwrapping bool @@ -142,10 +148,12 @@ func (r *ByteReader) Read() ([]*yaml.RNode, error) { r.WrappingAPIVersion = meta.APIVersion // unwrap the list - fc := node.Field("functionConfig") - if fc != nil { + if fc := node.Field("functionConfig"); fc != nil { r.FunctionConfig = fc.Value } + if res := node.Field("results"); res != nil { + r.Results = res.Value + } items := node.Field("items") if items != nil { diff --git a/kyaml/kio/byteio_reader_test.go b/kyaml/kio/byteio_reader_test.go index e6de127a7..0bfca4b42 100644 --- a/kyaml/kio/byteio_reader_test.go +++ b/kyaml/kio/byteio_reader_test.go @@ -5,36 +5,64 @@ package kio_test import ( "bytes" + "strings" "testing" "github.com/stretchr/testify/assert" . "sigs.k8s.io/kustomize/kyaml/kio" ) -// getByteReaderTestInput returns test input -func getByteReaderTestInput(t *testing.T) *bytes.Buffer { - b := &bytes.Buffer{} - _, err := b.WriteString(` ---- -a: b # first resource -c: d ---- -# second resource -e: f -g: -- h ---- ---- -i: j -`) - if !assert.NoError(t, err) { - assert.FailNow(t, "") +func TestByteReader(t *testing.T) { + type testCase struct { + name string + input string + err string + expectedItems []string + expectedFunctionConfig string + expectedResults string + wrappingAPIVersion string + wrappingAPIKind string + instance ByteReader } - return b -} -func TestByteReader_Read_wrappedResourceßßList(t *testing.T) { - r := &ByteReader{Reader: bytes.NewBufferString(`apiVersion: config.kubernetes.io/v1alpha1 + testCases := []testCase{ + // + // + // + { + name: "wrapped_resource_list", + input: `apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- kind: Deployment + spec: + replicas: 1 +- kind: Service + spec: + selectors: + foo: bar +`, + expectedItems: []string{ + `kind: Deployment +spec: + replicas: 1 +`, + `kind: Service +spec: + selectors: + foo: bar +`, + }, + wrappingAPIVersion: ResourceListAPIVersion, + wrappingAPIKind: ResourceListKind, + }, + + // + // + // + { + name: "wrapped_resource_list_function_config", + input: `apiVersion: config.kubernetes.io/v1alpha1 kind: ResourceList functionConfig: foo: bar @@ -50,109 +78,87 @@ items: spec: selectors: foo: bar -`)} - nodes, err := r.Read() - if !assert.NoError(t, err) { - return - } - - // verify the contents - if !assert.Len(t, nodes, 2) { - return - } - expected := []string{ - `kind: Deployment +`, + expectedItems: []string{ + `kind: Deployment spec: replicas: 1 `, - `kind: Service + `kind: Service spec: selectors: foo: bar `, - } - for i := range nodes { - if !assert.Equal(t, expected[i], nodes[i].MustString()) { - return - } - } - - // verify the function config - assert.Equal(t, `foo: bar + }, + expectedFunctionConfig: `foo: bar elems: - a - b -- c -`, r.FunctionConfig.MustString()) +- c`, + wrappingAPIVersion: ResourceListAPIVersion, + wrappingAPIKind: ResourceListKind, + }, - assert.Equal(t, ResourceListKind, r.WrappingKind) - assert.Equal(t, ResourceListAPIVersion, r.WrappingAPIVersion) -} - -func TestByteReader_Read_wrappedList(t *testing.T) { - r := &ByteReader{Reader: bytes.NewBufferString(`apiVersion: v1 + // + // + // + { + name: "wrapped_list", + input: ` +apiVersion: v1 kind: List items: -- kind: Deployment - spec: - replicas: 1 +- kind: Deployment + spec: + replicas: 1 - kind: Service spec: selectors: foo: bar -`)} - nodes, err := r.Read() - if !assert.NoError(t, err) { - return - } - - // verify the contents - if !assert.Len(t, nodes, 2) { - return - } - expected := []string{ - `kind: Deployment +`, + expectedItems: []string{ + ` +kind: Deployment spec: replicas: 1 `, - `kind: Service + ` +kind: Service spec: selectors: foo: bar `, - } - for i := range nodes { - if !assert.Equal(t, expected[i], nodes[i].MustString()) { - return - } - } + }, + wrappingAPIKind: "List", + wrappingAPIVersion: "v1", + }, - // verify the function config - assert.Nil(t, r.FunctionConfig) - assert.Equal(t, "List", r.WrappingKind) - assert.Equal(t, "v1", r.WrappingAPIVersion) -} - -// TestByteReader_Read tests the default Read behavior -// - Resources are read into a slice -// - ReaderAnnotations are set on the ResourceNodes -func TestByteReader_Read(t *testing.T) { - nodes, err := (&ByteReader{Reader: getByteReaderTestInput(t)}).Read() - if !assert.NoError(t, err) { - return - } - - if !assert.Len(t, nodes, 3) { - return - } - expected := []string{ - `a: b # first resource + // + // + // + { + name: "unwrapped_items", + input: ` +--- +a: b # first resource +c: d +--- +# second resource +e: f +g: +- h +--- +--- +i: j +`, + expectedItems: []string{ + `a: b # first resource c: d metadata: annotations: config.kubernetes.io/index: '0' `, - `# second resource + `# second resource e: f g: - h @@ -160,150 +166,209 @@ metadata: annotations: config.kubernetes.io/index: '1' `, - `i: j + `i: j metadata: annotations: config.kubernetes.io/index: '2' `, - } - for i := range nodes { - val, err := nodes[i].String() - if !assert.NoError(t, err) { - return - } - if !assert.Equal(t, expected[i], val) { - return - } - } -} + }, + }, -// TestByteReader_Read_omitReaderAnnotations tests -// - Resources are read into a slice -// - ReaderAnnotations are not set on the ResourceNodes -func TestByteReader_Read_omitReaderAnnotations(t *testing.T) { - nodes, err := (&ByteReader{ - Reader: getByteReaderTestInput(t), - OmitReaderAnnotations: true}).Read() - if !assert.NoError(t, err) { - return - } - - // should have parsed 3 resources - if !assert.Len(t, nodes, 3) { - return - } - expected := []string{ - "a: b # first resource\nc: d\n", - "# second resource\ne: f\ng:\n- h\n", - "i: j\n", - } - for i := range nodes { - val, err := nodes[i].String() - if !assert.NoError(t, err) { - return - } - if !assert.Equal(t, expected[i], val) { - return - } - } -} - -// TestByteReader_Read_omitReaderAnnotations tests -// - Resources are read into a slice -// - ReaderAnnotations are NOT set on the ResourceNodes -// - Additional annotations ARE set on the ResourceNodes -func TestByteReader_Read_setAnnotationsOmitReaderAnnotations(t *testing.T) { - nodes, err := (&ByteReader{ - Reader: getByteReaderTestInput(t), - SetAnnotations: map[string]string{"foo": "bar"}, - OmitReaderAnnotations: true, - }).Read() - if !assert.NoError(t, err) { - return - } - - if !assert.Len(t, nodes, 3) { - return - } - expected := []string{ - `a: b # first resource + // + // + // + { + name: "omit_annotations", + input: ` +--- +a: b # first resource c: d -metadata: - annotations: - foo: 'bar' -`, - `# second resource +--- +# second resource e: f g: - h -metadata: - annotations: - foo: 'bar' +--- +--- +i: j `, - `i: j -metadata: - annotations: - foo: 'bar' + expectedItems: []string{ + ` +a: b # first resource +c: d `, - } - for i := range nodes { - val, err := nodes[i].String() - if !assert.NoError(t, err) { - return - } - if !assert.Equal(t, expected[i], val) { - return - } - } -} + ` +# second resource +e: f +g: +- h +`, + ` +i: j +`, + }, + instance: ByteReader{OmitReaderAnnotations: true}, + }, -// TestByteReader_Read_omitReaderAnnotations tests -// - Resources are read into a slice -// - ReaderAnnotations ARE set on the ResourceNodes -// - Additional annotations ARE set on the ResourceNodes -func TestByteReader_Read_setAnnotations(t *testing.T) { - nodes, err := (&ByteReader{ - Reader: getByteReaderTestInput(t), - SetAnnotations: map[string]string{"foo": "bar"}, - }).Read() - if !assert.NoError(t, err) { - return - } - - if !assert.Len(t, nodes, 3) { - return - } - expected := []string{ - `a: b # first resource + // + // + // + { + name: "no_omit_annotations", + input: ` +--- +a: b # first resource +c: d +--- +# second resource +e: f +g: +- h +--- +--- +i: j +`, + expectedItems: []string{ + ` +a: b # first resource c: d metadata: annotations: config.kubernetes.io/index: '0' - foo: 'bar' `, - `# second resource + ` +# second resource e: f g: - h metadata: annotations: config.kubernetes.io/index: '1' - foo: 'bar' `, - `i: j + ` +i: j metadata: annotations: config.kubernetes.io/index: '2' +`, + }, + instance: ByteReader{}, + }, + + // + // + // + { + name: "set_annotation", + input: ` +--- +a: b # first resource +c: d +--- +# second resource +e: f +g: +- h +--- +--- +i: j +`, + expectedItems: []string{ + `a: b # first resource +c: d +metadata: + annotations: foo: 'bar' `, + `# second resource +e: f +g: +- h +metadata: + annotations: + foo: 'bar' +`, + `i: j +metadata: + annotations: + foo: 'bar' +`, + }, + instance: ByteReader{ + OmitReaderAnnotations: true, + SetAnnotations: map[string]string{"foo": "bar"}}, + }, } - for i := range nodes { - val, err := nodes[i].String() - if !assert.NoError(t, err) { - return - } - if !assert.Equal(t, expected[i], val) { - return - } + + for i := range testCases { + tc := testCases[i] + t.Run(tc.name, func(t *testing.T) { + r := tc.instance + r.Reader = bytes.NewBufferString(tc.input) + nodes, err := r.Read() + if tc.err != "" { + if !assert.EqualError(t, err, tc.err) { + t.FailNow() + } + return + } + + if !assert.NoError(t, err) { + t.FailNow() + } + + // verify the contents + if !assert.Len(t, nodes, len(tc.expectedItems)) { + t.FailNow() + } + for i := range nodes { + actual, err := nodes[i].String() + if !assert.NoError(t, err) { + t.FailNow() + } + if !assert.Equal(t, + strings.TrimSpace(tc.expectedItems[i]), + strings.TrimSpace(actual)) { + t.FailNow() + } + } + + // verify the function config + if tc.expectedFunctionConfig != "" { + actual, err := r.FunctionConfig.String() + if !assert.NoError(t, err) { + t.FailNow() + } + if !assert.Equal(t, + strings.TrimSpace(tc.expectedFunctionConfig), + strings.TrimSpace(actual)) { + t.FailNow() + } + } else if !assert.Nil(t, r.FunctionConfig) { + t.FailNow() + } + + if tc.expectedResults != "" { + actual, err := r.Results.String() + actual = strings.TrimSpace(actual) + if !assert.NoError(t, err) { + t.FailNow() + } + + tc.expectedResults = strings.TrimSpace(tc.expectedResults) + if !assert.Equal(t, tc.expectedResults, actual) { + t.FailNow() + } + } else if !assert.Nil(t, r.Results) { + t.FailNow() + } + + if !assert.Equal(t, tc.wrappingAPIKind, r.WrappingKind) { + t.FailNow() + } + if !assert.Equal(t, tc.wrappingAPIVersion, r.WrappingAPIVersion) { + t.FailNow() + } + }) } } diff --git a/kyaml/kio/byteio_readwriter_test.go b/kyaml/kio/byteio_readwriter_test.go new file mode 100644 index 000000000..e7cea1b2b --- /dev/null +++ b/kyaml/kio/byteio_readwriter_test.go @@ -0,0 +1,263 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package kio_test + +import ( + "bytes" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "sigs.k8s.io/kustomize/kyaml/kio" +) + +func TestByteReadWriter(t *testing.T) { + type testCase struct { + name string + err string + input string + expectedOutput string + instance kio.ByteReadWriter + } + + testCases := []testCase{ + { + name: "round_trip", + input: ` +apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- kind: Deployment + spec: + replicas: 1 +- kind: Service + spec: + selectors: + foo: bar +`, + expectedOutput: ` +apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- kind: Deployment + spec: + replicas: 1 +- kind: Service + spec: + selectors: + foo: bar +`, + }, + + { + name: "function_config", + input: ` +apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- kind: Deployment + spec: + replicas: 1 +- kind: Service + spec: + selectors: + foo: bar +functionConfig: + a: b # something +`, + expectedOutput: ` +apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- kind: Deployment + spec: + replicas: 1 +- kind: Service + spec: + selectors: + foo: bar +functionConfig: + a: b # something +`, + }, + + { + name: "results", + input: ` +apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- kind: Deployment + spec: + replicas: 1 +- kind: Service + spec: + selectors: + foo: bar +results: + a: b # something +`, + expectedOutput: ` +apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- kind: Deployment + spec: + replicas: 1 +- kind: Service + spec: + selectors: + foo: bar +results: + a: b # something +`, + }, + + { + name: "drop_invalid_resource_list_field", + input: ` +apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- kind: Deployment + spec: + replicas: 1 +- kind: Service + spec: + selectors: + foo: bar +foo: + a: b # something +`, + expectedOutput: ` +apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- kind: Deployment + spec: + replicas: 1 +- kind: Service + spec: + selectors: + foo: bar +`, + }, + + { + name: "list", + input: ` +apiVersion: v1 +kind: List +items: +- kind: Deployment + spec: + replicas: 1 +- kind: Service + spec: + selectors: + foo: bar +`, + expectedOutput: ` +apiVersion: v1 +kind: List +items: +- kind: Deployment + spec: + replicas: 1 +- kind: Service + spec: + selectors: + foo: bar +`, + }, + + { + name: "multiple_documents", + input: ` +kind: Deployment +spec: + replicas: 1 +--- +kind: Service +spec: + selectors: + foo: bar +`, + expectedOutput: ` +kind: Deployment +spec: + replicas: 1 +--- +kind: Service +spec: + selectors: + foo: bar +`, + }, + + { + name: "keep_annotations", + input: ` +kind: Deployment +spec: + replicas: 1 +--- +kind: Service +spec: + selectors: + foo: bar +`, + expectedOutput: ` +kind: Deployment +spec: + replicas: 1 +metadata: + annotations: + config.kubernetes.io/index: '0' +--- +kind: Service +spec: + selectors: + foo: bar +metadata: + annotations: + config.kubernetes.io/index: '1' +`, + instance: kio.ByteReadWriter{KeepReaderAnnotations: true}, + }, + } + + for i := range testCases { + tc := testCases[i] + t.Run(tc.name, func(t *testing.T) { + var in, out bytes.Buffer + in.WriteString(tc.input) + w := tc.instance + w.Writer = &out + w.Reader = &in + + nodes, err := w.Read() + if !assert.NoError(t, err) { + t.FailNow() + } + + err = w.Write(nodes) + if !assert.NoError(t, err) { + t.FailNow() + } + + if tc.err != "" { + if !assert.EqualError(t, err, tc.err) { + t.FailNow() + } + return + } + + if !assert.Equal(t, + strings.TrimSpace(tc.expectedOutput), strings.TrimSpace(out.String())) { + t.FailNow() + } + }) + } +} diff --git a/kyaml/kio/byteio_writer.go b/kyaml/kio/byteio_writer.go index 330634252..1d03cfb1d 100644 --- a/kyaml/kio/byteio_writer.go +++ b/kyaml/kio/byteio_writer.go @@ -30,6 +30,8 @@ type ByteWriter struct { // wrap the results in an ResourceList. FunctionConfig *yaml.RNode + Results *yaml.RNode + // WrappingKind if set will cause ByteWriter to wrap the Resources in // an 'items' field in this kind. e.g. if WrappingKind is 'List', // ByteWriter will wrap the Resources in a List .items field. @@ -112,6 +114,11 @@ func (w ByteWriter) Write(nodes []*yaml.RNode) error { &yaml.Node{Kind: yaml.ScalarNode, Value: "functionConfig"}, w.FunctionConfig.YNode()) } + if w.Results != nil { + list.Content = append(list.Content, + &yaml.Node{Kind: yaml.ScalarNode, Value: "results"}, + w.Results.YNode()) + } doc := &yaml.Node{ Kind: yaml.DocumentNode, Content: []*yaml.Node{list}} diff --git a/kyaml/kio/byteio_writer_test.go b/kyaml/kio/byteio_writer_test.go index e301dbfc8..ed331fbfd 100644 --- a/kyaml/kio/byteio_writer_test.go +++ b/kyaml/kio/byteio_writer_test.go @@ -1,96 +1,84 @@ // Copyright 2019 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0 -package kio +package kio_test import ( "bytes" + "strings" "testing" "github.com/stretchr/testify/assert" + "sigs.k8s.io/kustomize/kyaml/kio" + . "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/yaml" ) -// TestByteWriter_Write_withoutAnnotations tests: -// - Resource Config ordering is preserved if no annotations are present -func TestByteWriter_Write_wrapped(t *testing.T) { - node1, err := yaml.Parse(`a: b #first -`) - if !assert.NoError(t, err) { - return +func TestByteWriter(t *testing.T) { + type testCase struct { + name string + err string + items []string + functionConfig string + results string + expectedOutput string + instance kio.ByteWriter } - node2, err := yaml.Parse(`c: d # second -`) - if !assert.NoError(t, err) { - return - } - node3, err := yaml.Parse(`e: f + + testCases := []testCase{ + // + // + // + { + name: "wrap_resource_list", + instance: ByteWriter{ + Sort: true, + WrappingKind: ResourceListKind, + WrappingAPIVersion: ResourceListAPIVersion, + }, + items: []string{ + `a: b #first`, + `c: d # second`, + }, + functionConfig: ` +e: f g: h: - i # has a list - - j -`) - if !assert.NoError(t, err) { - return - } - - buff := &bytes.Buffer{} - err = ByteWriter{ - Sort: true, - Writer: buff, - FunctionConfig: node3, - WrappingKind: ResourceListKind, - WrappingAPIVersion: ResourceListAPIVersion}. - Write([]*yaml.RNode{node2, node1}) - if !assert.NoError(t, err) { - return - } - assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1 + - j`, + expectedOutput: `apiVersion: config.kubernetes.io/v1alpha1 kind: ResourceList items: -- c: d # second - a: b #first +- c: d # second functionConfig: e: f g: h: - i # has a list - j -`, buff.String()) -} +`, + }, -// TestByteWriter_Write_withoutAnnotations tests: -// - Resource Config ordering is preserved if no annotations are present -func TestByteWriter_Write_withoutAnnotations(t *testing.T) { - node1, err := yaml.Parse(`a: b #first -`) - if !assert.NoError(t, err) { - return - } - node2, err := yaml.Parse(`c: d # second -`) - if !assert.NoError(t, err) { - return - } - node3, err := yaml.Parse(`e: f + // + // + // + { + name: "multiple_items", + items: []string{ + `c: d # second`, + `e: f g: h: # has a list - i : [i1, i2] # line comment # has a list 2 - j : j1 -`) - if !assert.NoError(t, err) { - return - } - - buff := &bytes.Buffer{} - err = ByteWriter{Writer: buff}. - Write([]*yaml.RNode{node2, node3, node1}) - if !assert.NoError(t, err) { - return - } - assert.Equal(t, `c: d # second +`, + `a: b #first`, + }, + expectedOutput: ` +c: d # second --- e: f g: @@ -101,32 +89,23 @@ g: - j: j1 --- a: b #first -`, buff.String()) -} +`, + }, -// TestByteWriter_Write_withAnnotationsKeepAnnotations tests: -// - Resource Config is sorted by annotations if present -// - IndexAnnotations are retained -func TestByteWriter_Write_withAnnotationsKeepAnnotations(t *testing.T) { - node1, err := yaml.Parse(`a: b #first + // + // Test Case + // + { + name: "sort_keep_annotation", + instance: ByteWriter{Sort: true, KeepReaderAnnotations: true}, + items: []string{ + `a: b #first metadata: annotations: config.kubernetes.io/index: 0 config.kubernetes.io/path: "a/b/a_test.yaml" -`) - if !assert.NoError(t, err) { - return - } - node2, err := yaml.Parse(`c: d # second -metadata: - annotations: - config.kubernetes.io/index: 1 - config.kubernetes.io/path: "a/b/a_test.yaml" -`) - if !assert.NoError(t, err) { - return - } - node3, err := yaml.Parse(`e: f +`, + `e: f g: h: - i # has a list @@ -135,18 +114,16 @@ metadata: annotations: config.kubernetes.io/index: 0 config.kubernetes.io/path: "a/b/b_test.yaml" -`) - if !assert.NoError(t, err) { - return - } +`, + `c: d # second +metadata: + annotations: + config.kubernetes.io/index: 1 + config.kubernetes.io/path: "a/b/a_test.yaml" +`, + }, - buff := &bytes.Buffer{} - err = ByteWriter{Sort: true, Writer: buff, KeepReaderAnnotations: true}. - Write([]*yaml.RNode{node2, node3, node1}) - if !assert.NoError(t, err) { - return - } - assert.Equal(t, `a: b #first + expectedOutput: `a: b #first metadata: annotations: config.kubernetes.io/index: 0 @@ -167,109 +144,36 @@ metadata: annotations: config.kubernetes.io/index: 0 config.kubernetes.io/path: "a/b/b_test.yaml" -`, buff.String()) -} +`, + }, -// TestByteWriter_Write_withAnnotations tests: -// - Resource Config is sorted by annotations if present -// - IndexAnnotations are pruned -func TestByteWriter_Write_withAnnotations(t *testing.T) { - node1, err := yaml.Parse(`a: b #first + // + // Test Case + // + { + name: "sort_partial_annotations", + instance: ByteWriter{Sort: true}, + items: []string{ + `a: b #first metadata: annotations: - config.kubernetes.io/index: 0 config.kubernetes.io/path: "a/b/a_test.yaml" -`) - if !assert.NoError(t, err) { - return - } - node2, err := yaml.Parse(`c: d # second +`, + `c: d # second metadata: annotations: config.kubernetes.io/index: 1 config.kubernetes.io/path: "a/b/a_test.yaml" -`) - if !assert.NoError(t, err) { - return - } - node3, err := yaml.Parse(`e: f +`, + `e: f g: h: - i # has a list - j -metadata: - annotations: - config.kubernetes.io/index: 0 - config.kubernetes.io/path: "a/b/b_test.yaml" -`) - if !assert.NoError(t, err) { - return - } +`, + }, - buff := &bytes.Buffer{} - err = ByteWriter{Sort: true, Writer: buff}. - Write([]*yaml.RNode{node2, node3, node1}) - if !assert.NoError(t, err) { - return - } - assert.Equal(t, `a: b #first -metadata: - annotations: - config.kubernetes.io/path: "a/b/a_test.yaml" ---- -c: d # second -metadata: - annotations: - config.kubernetes.io/path: "a/b/a_test.yaml" ---- -e: f -g: - h: - - i # has a list - - j -metadata: - annotations: - config.kubernetes.io/path: "a/b/b_test.yaml" -`, buff.String()) -} - -// TestByteWriter_Write_partialValues tests: -// - Resource Config is sorted when annotations are present on some but not all ResourceNodes -func TestByteWriter_Write_partialAnnotations(t *testing.T) { - node1, err := yaml.Parse(`a: b #first -metadata: - annotations: - config.kubernetes.io/path: "a/b/a_test.yaml" -`) - if !assert.NoError(t, err) { - return - } - node2, err := yaml.Parse(`c: d # second -metadata: - annotations: - config.kubernetes.io/index: 1 - config.kubernetes.io/path: "a/b/a_test.yaml" -`) - if !assert.NoError(t, err) { - return - } - node3, err := yaml.Parse(`e: f -g: - h: - - i # has a list - - j -`) - if !assert.NoError(t, err) { - return - } - - buff := &bytes.Buffer{} - rw := ByteWriter{Sort: true, Writer: buff} - err = rw.Write([]*yaml.RNode{node2, node3, node1}) - if !assert.NoError(t, err) { - return - } - assert.Equal(t, `e: f + expectedOutput: `e: f g: h: - i # has a list @@ -284,5 +188,45 @@ c: d # second metadata: annotations: config.kubernetes.io/path: "a/b/a_test.yaml" -`, buff.String()) +`, + }, + } + + for i := range testCases { + tc := testCases[i] + t.Run(tc.name, func(t *testing.T) { + actual := &bytes.Buffer{} + w := tc.instance + w.Writer = actual + + if tc.functionConfig != "" { + w.FunctionConfig = yaml.MustParse(tc.functionConfig) + } + + if tc.results != "" { + w.Results = yaml.MustParse(tc.results) + } + + var items []*yaml.RNode + for i := range tc.items { + items = append(items, yaml.MustParse(tc.items[i])) + } + err := w.Write(items) + + if tc.err != "" { + if !assert.EqualError(t, err, tc.err) { + t.FailNow() + } + return + } + + if !assert.NoError(t, err) { + t.FailNow() + } + if !assert.Equal(t, + strings.TrimSpace(tc.expectedOutput), strings.TrimSpace(actual.String())) { + t.FailNow() + } + }) + } }