From 9f06376ab2103f33f08d8dc8411f46ca501cd33a Mon Sep 17 00:00:00 2001 From: Natasha Sarkar Date: Thu, 5 Nov 2020 17:11:37 -0800 Subject: [PATCH] updated associative sequence --- kyaml/yaml/fns.go | 43 +++---------------------- kyaml/yaml/fns_test.go | 34 +++++++++---------- kyaml/yaml/merge2/smpdirective.go | 4 +-- kyaml/yaml/walk/associative_sequence.go | 23 ++++++++++--- 4 files changed, 42 insertions(+), 62 deletions(-) diff --git a/kyaml/yaml/fns.go b/kyaml/yaml/fns.go index fa1ad609b..940db9ba0 100644 --- a/kyaml/yaml/fns.go +++ b/kyaml/yaml/fns.go @@ -54,35 +54,6 @@ type ElementSetter struct { // Element is the new value to set -- remove the existing element if nil Element *Node - // Key is a field on the elements. It is used to find the matching element to - // update / delete. - Key string `yaml:"key,omitempty"` - - // Value is a field value on the elements. It is used to find matching elements to - // update / delete. - Value string `yaml:"value,omitempty"` -} - -func (e ElementSetter) Filter(rn *RNode) (*RNode, error) { - return rn.Pipe(ElementSetterList{ - Kind: e.Kind, - Element: e.Element, - Keys: []string{e.Key}, - Values: []string{e.Value}, - }) -} - -// ElementSetterList sets the value for an Element in an associative list. -// It behaves identically to ElementSetter, except that it uses multiple -// key-value pairs (in the form of a list of keys and a corresponding list -// of values) in order to find a matching element, whereas ElementSetter -// uses only one key-value pair. -type ElementSetterList struct { - Kind string `yaml:"kind,omitempty"` - - // Element is the new value to set -- remove the existing element if nil - Element *Node - // Key is a list of fields on the elements. It is used to find matching elements to // update / delete Keys []string @@ -93,19 +64,17 @@ type ElementSetterList struct { } // isMappingNode returns whether node is a mapping node -func (e ElementSetterList) isMappingNode(node *RNode) bool { +func (e ElementSetter) isMappingNode(node *RNode) bool { return ErrorIfInvalid(node, yaml.MappingNode) == nil } // isMappingSetter returns is this setter intended to set a mapping node -func (e ElementSetterList) isMappingSetter() bool { +func (e ElementSetter) isMappingSetter() bool { return len(e.Keys) > 0 && e.Keys[0] != "" && len(e.Values) > 0 && e.Values[0] != "" } -// the main difference between this Filter and the ElementSetter Filter -// is that here we must iterate through all the key-value pairs -func (e ElementSetterList) Filter(rn *RNode) (*RNode, error) { +func (e ElementSetter) Filter(rn *RNode) (*RNode, error) { if len(e.Keys) == 0 { e.Keys = append(e.Keys, "") } @@ -143,11 +112,7 @@ func (e ElementSetterList) Filter(rn *RNode) (*RNode, error) { var err error found := true for j := range e.Keys { - if j >= len(e.Values) { - val, err = newNode.Pipe(Get(e.Keys[j])) - } else { - val, err = newNode.Pipe(FieldMatcher{Name: e.Keys[j], StringValue: e.Values[j]}) - } + val, err = newNode.Pipe(FieldMatcher{Name: e.Keys[j], StringValue: e.Values[j]}) if err != nil { return nil, err } diff --git a/kyaml/yaml/fns_test.go b/kyaml/yaml/fns_test.go index 9f976883f..f9dc606bd 100644 --- a/kyaml/yaml/fns_test.go +++ b/kyaml/yaml/fns_test.go @@ -109,7 +109,7 @@ func TestElementSetter(t *testing.T) { // ElementSetter will update node, so make a copy node := orig.Copy() // Remove an element, because ElementSetter.Element is left nil. - rn, err := node.Pipe(ElementSetterList{Keys: []string{"a"}, Values: []string{"b"}}) + rn, err := node.Pipe(ElementSetter{Keys: []string{"a"}, Values: []string{"b"}}) assert.NoError(t, err) assert.Nil(t, rn) assert.Equal(t, `- scalarValue @@ -118,7 +118,7 @@ func TestElementSetter(t *testing.T) { node = orig.Copy() // Nothing happens because no element is matched - rn, err = node.Pipe(ElementSetterList{Keys: []string{"a"}, Values: []string{"zebra"}}) + rn, err = node.Pipe(ElementSetter{Keys: []string{"a"}, Values: []string{"zebra"}}) assert.NoError(t, err) assert.Nil(t, rn) assert.Equal(t, `- a: b @@ -129,7 +129,7 @@ func TestElementSetter(t *testing.T) { node = orig.Copy() // Return error because ElementSetter doesn't support a single key // when there is a scalar value in the list - _, err = node.Pipe(ElementSetterList{Keys: []string{"a"}}) + _, err = node.Pipe(ElementSetter{Keys: []string{"a"}}) assert.EqualError(t, err, "wrong Node Kind for expected: MappingNode was ScalarNode: value: {scalarValue}") node = MustParse(` @@ -138,7 +138,7 @@ func TestElementSetter(t *testing.T) { `) // {a: b} is removed since the value is omitted and only key is used // to match and no Element specified. - rn, err = node.Pipe(ElementSetterList{Keys: []string{"a"}}) + rn, err = node.Pipe(ElementSetter{Keys: []string{"a"}}) assert.NoError(t, err) assert.Nil(t, rn) assert.Equal(t, `- c: d @@ -150,7 +150,7 @@ func TestElementSetter(t *testing.T) { `) // Return error because ElementSetter will assume all elements are scalar when // there is only value provided. - _, err = node.Pipe(ElementSetterList{Values: []string{"b"}}) + _, err = node.Pipe(ElementSetter{Values: []string{"b"}}) assert.EqualError(t, err, "wrong Node Kind for expected: ScalarNode was MappingNode: value: {a: b}") node = MustParse(` @@ -159,7 +159,7 @@ func TestElementSetter(t *testing.T) { `) // b is removed since ElementSetter use the value "b" to match the // scalar values. - rn, err = node.Pipe(ElementSetterList{Values: []string{"b"}}) + rn, err = node.Pipe(ElementSetter{Values: []string{"b"}}) assert.NoError(t, err) assert.Nil(t, rn) assert.Equal(t, `- a @@ -170,7 +170,7 @@ func TestElementSetter(t *testing.T) { newElement := NewMapRNode(&map[string]string{ "e": "f", }) - rn, err = node.Pipe(ElementSetterList{ + rn, err = node.Pipe(ElementSetter{ Keys: []string{"a"}, Values: []string{"b"}, Element: newElement.YNode(), @@ -185,7 +185,7 @@ func TestElementSetter(t *testing.T) { node = orig.Copy() // Set an element with scalar, {"a": "b"} to "foo" newElement = NewScalarRNode("foo") - rn, err = node.Pipe(ElementSetterList{ + rn, err = node.Pipe(ElementSetter{ Keys: []string{"a"}, Values: []string{"b"}, Element: newElement.YNode(), @@ -203,7 +203,7 @@ func TestElementSetter(t *testing.T) { newElement = NewMapRNode(&map[string]string{ "e": "f", }) - rn, err = node.Pipe(ElementSetterList{ + rn, err = node.Pipe(ElementSetter{ Keys: []string{"x"}, Values: []string{"y"}, Element: newElement.YNode(), @@ -231,7 +231,7 @@ func TestElementSetterMultipleKeys(t *testing.T) { node := orig.Copy() // Remove an element using one key-value pair, // because ElementSetter.Element is left nil. - rn, err := node.Pipe(ElementSetterList{ + rn, err := node.Pipe(ElementSetter{ Keys: []string{"a"}, Values: []string{"b"}, }) @@ -244,7 +244,7 @@ func TestElementSetterMultipleKeys(t *testing.T) { node = orig.Copy() // Remove an element using multiple key-value pairs, // because ElementSetter.Element is left nil. - rn, err = node.Pipe(ElementSetterList{ + rn, err = node.Pipe(ElementSetter{ Keys: []string{"a", "c"}, Values: []string{"b", "d"}, }) @@ -258,7 +258,7 @@ func TestElementSetterMultipleKeys(t *testing.T) { // Should do nothing, because Element is nil // and there is no element which matches all // give key-value pairs - rn, err = node.Pipe(ElementSetterList{ + rn, err = node.Pipe(ElementSetter{ Keys: []string{"a", "c"}, Values: []string{"b", "wrong value"}, }) @@ -276,7 +276,7 @@ func TestElementSetterMultipleKeys(t *testing.T) { newElement := NewMapRNode(&map[string]string{ "g": "h", }) - rn, err = node.Pipe(ElementSetterList{ + rn, err = node.Pipe(ElementSetter{ Keys: []string{"a"}, Values: []string{"b"}, Element: newElement.YNode(), @@ -294,7 +294,7 @@ func TestElementSetterMultipleKeys(t *testing.T) { newElement = NewMapRNode(&map[string]string{ "g": "h", }) - rn, err = node.Pipe(ElementSetterList{ + rn, err = node.Pipe(ElementSetter{ Keys: []string{"a", "c"}, Values: []string{"b", "d"}, Element: newElement.YNode(), @@ -310,7 +310,7 @@ func TestElementSetterMultipleKeys(t *testing.T) { // Set an element scalar, // {'a: b, c: d'} to "foo" newElement = NewScalarRNode("foo") - rn, err = node.Pipe(ElementSetterList{ + rn, err = node.Pipe(ElementSetter{ Keys: []string{"a", "c"}, Values: []string{"b", "d"}, Element: newElement.YNode(), @@ -329,7 +329,7 @@ func TestElementSetterMultipleKeys(t *testing.T) { newElement = NewMapRNode(&map[string]string{ "g": "h", }) - rn, err = node.Pipe(ElementSetterList{ + rn, err = node.Pipe(ElementSetter{ Keys: []string{"a", "c"}, Values: []string{"b", "wrong value"}, Element: newElement.YNode(), @@ -349,7 +349,7 @@ func TestElementSetterMultipleKeys(t *testing.T) { newElement = NewMapRNode(&map[string]string{ "g": "h", }) - rn, err = node.Pipe(ElementSetterList{ + rn, err = node.Pipe(ElementSetter{ Keys: []string{"a", "c"}, Values: []string{"b"}, Element: newElement.YNode(), diff --git a/kyaml/yaml/merge2/smpdirective.go b/kyaml/yaml/merge2/smpdirective.go index b5b2fbb7e..f38b188ea 100644 --- a/kyaml/yaml/merge2/smpdirective.go +++ b/kyaml/yaml/merge2/smpdirective.go @@ -95,7 +95,7 @@ func elideMappingPatchDirective(patch *yaml.RNode) error { func elideSequencePatchDirective(patch *yaml.RNode, value string) error { return patch.PipeE(yaml.ElementSetter{ Element: nil, - Key: strategicMergePatchDirectiveKey, - Value: value, + Keys: []string{strategicMergePatchDirectiveKey}, + Values: []string{value}, }) } diff --git a/kyaml/yaml/walk/associative_sequence.go b/kyaml/yaml/walk/associative_sequence.go index 66ead3dcc..6f3e25cd8 100644 --- a/kyaml/yaml/walk/associative_sequence.go +++ b/kyaml/yaml/walk/associative_sequence.go @@ -21,7 +21,11 @@ func appendListNode(dst, src *yaml.RNode, key string) (*yaml.RNode, error) { // If key is empty, we know this is a scalar value and we can directly set the // node if key == "" { - _, err := dst.Pipe(yaml.ElementSetter{Element: elem, Key: key, Value: elem.Value}) + _, err := dst.Pipe(yaml.ElementSetter{ + Element: elem, + Keys: []string{key}, + Values: []string{elem.Value}, + }) if err != nil { return nil, err } @@ -46,7 +50,11 @@ func appendListNode(dst, src *yaml.RNode, key string) (*yaml.RNode, error) { // We use the key and value from elem to find the corresponding element in dst. // Then we will use ElementSetter to replace the element with elem. If we cannot // find the item, the element will be appended. - _, err = dst.Pipe(yaml.ElementSetter{Element: elem, Key: key, Value: v}) + _, err = dst.Pipe(yaml.ElementSetter{ + Element: elem, + Keys: []string{key}, + Values: []string{v}, + }) if err != nil { return nil, err } @@ -76,7 +84,10 @@ func (l *Walker) setAssociativeSequenceElements(values []string, key string, des } // delete the node from **dest** if it's null or empty if yaml.IsMissingOrNull(val) || yaml.IsEmptyMap(val) { - _, err = dest.Pipe(yaml.ElementSetter{Key: key, Value: value}) + _, err = dest.Pipe(yaml.ElementSetter{ + Keys: []string{key}, + Values: []string{value}, + }) if err != nil { return nil, err } @@ -94,7 +105,11 @@ func (l *Walker) setAssociativeSequenceElements(values []string, key string, des // Add the val to the sequence. val will replace the item in the sequence if // there is an item that matches the key-value pair. Otherwise val will be appended // the the sequence. - _, err = itemsToBeAdded.Pipe(yaml.ElementSetter{Element: val.YNode(), Key: key, Value: value}) + _, err = itemsToBeAdded.Pipe(yaml.ElementSetter{ + Element: val.YNode(), + Keys: []string{key}, + Values: []string{value}, + }) if err != nil { return nil, err }