From 5d59cad687f21777e3dcefee759f3d1e152c32bb Mon Sep 17 00:00:00 2001 From: Jeff Davis Date: Fri, 28 May 2021 15:59:17 -0500 Subject: [PATCH] feat(merge): allow merges to change data type when using mergeNode if the new node is a map type and the original is not, the original node will be converted to a map type Signed-off-by: Jeff Davis --- internal/actions/merge.go | 28 ++++++-- .../instructions/testdata/values/site_a.yaml | 2 +- internal/instructions/values.go | 20 +++--- internal/instructions/values_internal_test.go | 70 +++++++++++-------- 4 files changed, 74 insertions(+), 46 deletions(-) diff --git a/internal/actions/merge.go b/internal/actions/merge.go index 7125b265..874285ea 100644 --- a/internal/actions/merge.go +++ b/internal/actions/merge.go @@ -36,7 +36,7 @@ func MergeNode(nodes ...*yaml.Node) error { } func merge(o, n *yaml.Node, keyName ...string) error { - switch o.Kind { + switch n.Kind { case yaml.DocumentNode: return mergeDocument(o, n) case yaml.MappingNode: @@ -68,10 +68,16 @@ func mergeMap(o, n *yaml.Node) error { for ni := 0; ni < len(n.Content)-1; ni += 2 { resultFound := false + if o.Kind != yaml.MappingNode { + o.Kind = yaml.MappingNode + o.Value = "" + o.Content = []*yaml.Node{} + } + for oi := 0; oi < len(o.Content)-1; oi += 2 { - var formatKey bool + var foundMarker bool - if formatKey = checkForMarkers(n.Content[ni].Value); !formatKey { + if foundMarker = checkForMarkers(n.Content[ni].Value); !foundMarker { if o.Content[oi].Value != n.Content[ni].Value { continue } @@ -88,7 +94,7 @@ func mergeMap(o, n *yaml.Node) error { return err } - if !formatKey { + if !foundMarker { break } @@ -106,7 +112,13 @@ func mergeMap(o, n *yaml.Node) error { } func mergeArray(o, n *yaml.Node) error { - if o.Content != nil && n.Content != nil { + if o.Kind != yaml.SequenceNode { + o.Kind = yaml.SequenceNode + o.Value = "" + o.Content = []*yaml.Node{} + } + + if n.Content != nil { mergeComments(o, n, o.Value) if err := addNode(o, n.Content...); err != nil { @@ -140,6 +152,12 @@ func mergeScalar(o, n *yaml.Node, values ...string) { keyName = values[0] } + if o.Kind != yaml.ScalarNode { + o.Kind = yaml.ScalarNode + o.Value = "" + o.Content = nil + } + o.Value = format(n.Value, value, lc, hc, fc, keyName) } diff --git a/internal/instructions/testdata/values/site_a.yaml b/internal/instructions/testdata/values/site_a.yaml index aa6101b1..5cdf9832 100644 --- a/internal/instructions/testdata/values/site_a.yaml +++ b/internal/instructions/testdata/values/site_a.yaml @@ -9,5 +9,5 @@ foo: - minestrone - chicken noodle - clam chowder -barf: oo +zarf: oo yoo: czar diff --git a/internal/instructions/values.go b/internal/instructions/values.go index 5d202a49..44d2dd16 100644 --- a/internal/instructions/values.go +++ b/internal/instructions/values.go @@ -32,17 +32,19 @@ func getValues(fileNames []string) (interface{}, error) { yamlValues[i] = &yamlValue } - if err := actions.MergeNode(yamlValues...); err != nil { - return nil, fmt.Errorf("failed to merge yaml values: %w", err) - } + if len(yamlValues) != 0 { + if err := actions.MergeNode(yamlValues...); err != nil { + return nil, fmt.Errorf("failed to merge yaml values: %w", err) + } - b, err := yaml.Marshal(yamlValues[0]) - if err != nil { - return nil, fmt.Errorf("failed to marshal yaml values: %w", err) - } + b, err := yaml.Marshal(yamlValues[0]) + if err != nil { + return nil, fmt.Errorf("failed to marshal yaml values: %w", err) + } - if err := yaml.Unmarshal(b, &values); err != nil { - return nil, fmt.Errorf("failed to unmarshal yaml values: %w", err) + if err := yaml.Unmarshal(b, &values); err != nil { + return nil, fmt.Errorf("failed to unmarshal yaml values: %w", err) + } } return values, nil diff --git a/internal/instructions/values_internal_test.go b/internal/instructions/values_internal_test.go index b10a7b38..12c45f69 100644 --- a/internal/instructions/values_internal_test.go +++ b/internal/instructions/values_internal_test.go @@ -6,6 +6,8 @@ package instructions import ( "reflect" "testing" + + "gopkg.in/yaml.v3" ) func Test_getValues(t *testing.T) { @@ -29,13 +31,12 @@ func Test_getValues(t *testing.T) { "testdata/values/on_premise.yml", }, }, - want: map[string]interface{}{ - "too": "bar", - "yoo": "car", - "foo": "you", - "test": "one", - "two": "three", - }, + want: `foo: you +test: one +too: bar +two: three +yoo: car +`, wantErr: false, }, { @@ -46,16 +47,14 @@ func Test_getValues(t *testing.T) { "testdata/values/site_b.yml", }, }, - want: map[string]interface{}{ - "too": "bar", - "foo": "foo", - "values": []interface{}{ - 1, - 2, - 3, - }, - "yoo": "bar", - }, + want: `foo: foo +too: bar +values: + - 1 + - 2 + - 3 +yoo: bar +`, wantErr: false, }, { @@ -68,18 +67,26 @@ func Test_getValues(t *testing.T) { "testdata/values/site_a.yaml", }, }, - want: map[string]interface{}{ - "too": "bar", - "yoo": "czar", - "test": "one", - "two": "three", - "values": []interface{}{ - 1, - 2, - 3, - }, - "barf": "oo", - }, + want: `foo: + bar: + potato: + badayda: + - 1 + - cheese: burger + - soup: + - minestrone + - chicken noodle + - clam chowder +test: one +too: bar +two: three +values: + - 1 + - 2 + - 3 +yoo: czar +zarf: oo +`, }, } @@ -93,8 +100,9 @@ func Test_getValues(t *testing.T) { return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("getValues(%v) = %+v, want %+v", tt.args.fileNames, got, tt.want) + b, _ := yaml.Marshal(got) + if !reflect.DeepEqual(string(b), tt.want) { + t.Errorf("getValues(%v) = %v, want %v", tt.args.fileNames, string(b), tt.want) } }) }