From a8b5ec2c616364b95d26444a34db42054dac4569 Mon Sep 17 00:00:00 2001 From: Phani Teja Marupaka Date: Mon, 24 Feb 2020 12:35:14 -0800 Subject: [PATCH 1/3] Suggested Changes and Unit Tests --- .../settersutil/substitutioncreator.go | 39 +++-- .../settersutil/substitutioncreator_test.go | 154 ++++++++++++++++++ 2 files changed, 175 insertions(+), 18 deletions(-) create mode 100644 kyaml/setters2/settersutil/substitutioncreator_test.go diff --git a/kyaml/setters2/settersutil/substitutioncreator.go b/kyaml/setters2/settersutil/substitutioncreator.go index 15059abd0..4134f4271 100644 --- a/kyaml/setters2/settersutil/substitutioncreator.go +++ b/kyaml/setters2/settersutil/substitutioncreator.go @@ -109,10 +109,13 @@ func (c SubstitutionCreator) CreateSettersForSubstitution(openAPIPath string) er sd := setters2.SetterDefinition{ // get the setter name from ref. Ex: from #/definitions/io.k8s.cli.setters.image_setter // extract image_setter - Name: strings.Split(value.Ref, ".")[4], - Value: m[value.Marker], + Name: strings.TrimPrefix(value.Ref, "#/definitions/io.k8s.cli.setters."), + Value: m[value.Marker], + } + err := sd.AddToFile(openAPIPath) + if err != nil { + return err } - sd.AddToFile(openAPIPath) } } return nil @@ -126,23 +129,23 @@ func (c SubstitutionCreator) GetValuesForMarkers() (map[string]string, error) { if err != nil { return nil, err } - s:=c.FieldValue - p:=c.Pattern - i:=0 - j:=0 + s := c.FieldValue + p := c.Pattern + i := 0 + j := 0 // iterate s, p with indices i, j respectively and when j hits the index of a marker, freeze j and iterate // i and capture string till we find the substring just after current marker and before next marker // Ex: s = "something/ubuntu:0.1.0", p = "something/IMAGE::VERSION", till j reaches 10 // just proceed i and j and check if s[i]==p[j] // when j is 10, freeze j and move i till it sees substring '::' which derives IMAGE = ubuntu and so on. - for i< len(s) && j< len(p) { + for i < len(s) && j < len(p) { if marker, ok := indices[j]; ok { value := "" - e := j+len(marker) + e := j + len(marker) - for i j { res = min(k-j, res) } @@ -201,8 +204,8 @@ func lenToNextMarker(m map[int]string, j int) int { } func min(a int, b int) int { - if a Date: Mon, 24 Feb 2020 13:34:16 -0800 Subject: [PATCH 2/3] Update go files --- kyaml/go.mod | 5 +- kyaml/go.sum | 10 ++- .../settersutil/substitutioncreator.go | 87 ++++++++++--------- .../settersutil/substitutioncreator_test.go | 78 +++++------------ 4 files changed, 75 insertions(+), 105 deletions(-) diff --git a/kyaml/go.mod b/kyaml/go.mod index de2170cd8..33eefaad1 100644 --- a/kyaml/go.mod +++ b/kyaml/go.mod @@ -9,6 +9,7 @@ require ( github.com/sergi/go-diff v1.1.0 github.com/stretchr/testify v1.4.0 github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca - gopkg.in/yaml.v2 v2.2.4 - gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d + golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 // indirect + gopkg.in/yaml.v2 v2.2.7 + gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 ) diff --git a/kyaml/go.sum b/kyaml/go.sum index 98d3f4c1c..05b1b96aa 100644 --- a/kyaml/go.sum +++ b/kyaml/go.sum @@ -39,18 +39,20 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d h1:LCPbGQ34PMrwad11aMZ+dbz5SAsq/0ySjRwQ8I9Qwd8= -gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 h1:XZx7nhd5GMaZpmDaEHFVafUZC7ya0fuo7cSJ3UCKYmM= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/kyaml/setters2/settersutil/substitutioncreator.go b/kyaml/setters2/settersutil/substitutioncreator.go index 4134f4271..4acef990f 100644 --- a/kyaml/setters2/settersutil/substitutioncreator.go +++ b/kyaml/setters2/settersutil/substitutioncreator.go @@ -4,11 +4,10 @@ package settersutil import ( - "io/ioutil" "math" "strings" - "sigs.k8s.io/kind/pkg/errors" + "sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/openapi" "sigs.k8s.io/kustomize/kyaml/setters2" @@ -78,13 +77,7 @@ func (c SubstitutionCreator) Create(openAPIPath, resourcesPath string) error { // CreateSettersForSubstitution creates the setters for all the references in the substitution // values if they don't already exist in openAPIPath file. func (c SubstitutionCreator) CreateSettersForSubstitution(openAPIPath string) error { - b, err := ioutil.ReadFile(openAPIPath) - if err != nil { - return err - } - - // parse the yaml file - y, err := yaml.Parse(string(b)) + y, err := yaml.ReadFile(openAPIPath) if err != nil { return err } @@ -129,58 +122,55 @@ func (c SubstitutionCreator) GetValuesForMarkers() (map[string]string, error) { if err != nil { return nil, err } - s := c.FieldValue - p := c.Pattern - i := 0 - j := 0 - // iterate s, p with indices i, j respectively and when j hits the index of a marker, freeze j and iterate - // i and capture string till we find the substring just after current marker and before next marker + fv := c.FieldValue + pattern := c.Pattern + fvInd := 0 + patternInd := 0 + // iterate fv, pattern with indices fvInd, patternInd respectively and when patternInd hits the index of a marker, + // freeze patternInd and iterate fvInd and capture string till we find the substring just after current marker + // and before next marker - // Ex: s = "something/ubuntu:0.1.0", p = "something/IMAGE::VERSION", till j reaches 10 - // just proceed i and j and check if s[i]==p[j] - // when j is 10, freeze j and move i till it sees substring '::' which derives IMAGE = ubuntu and so on. - for i < len(s) && j < len(p) { - if marker, ok := indices[j]; ok { - value := "" - e := j + len(marker) - - for i < len(s) && (e == len(p) || - s[i:min(len(s), i+lenToNextMarker(indices, e))] != p[e:min(e+lenToNextMarker(indices, e), len(p))]) { - value += string(s[i]) - i++ - } + // Ex: fv = "something/ubuntu:0.1.0", pattern = "something/IMAGE:VERSION", till patternInd reaches 10 + // just proceed fvInd and patternInd and check if fv[fvInd]==pattern[patternInd] when patternInd is 10, + // freeze patternInd and move fvInd till it sees substring ':' which derives IMAGE = ubuntu and so on. + for fvInd < len(fv) && patternInd < len(pattern) { + // if we hit marker index, extract its corresponding value + if marker, ok := indices[patternInd]; ok { + // increment the patternInd to end of marker. This helps us to extract the substring before next marker. + patternInd += len(marker) + value := c.extractValueForMarker(&fvInd, fv, patternInd, indices) // if marker is repeated in the pattern, make sure that the corresponding values // are same and throw error if not. if prevValue, ok := m[marker]; ok && prevValue != value { - return nil, errors.Errorf("Same marker is found to have different values in field value.") + return nil, errors.Errorf("same marker is found to have different values in field value") } m[marker] = value - j += len(marker) } else { - if s[i] != p[j] { - return nil, errors.Errorf("Unable to derive values for markers. Create setters for all markers and then try again.") + // Ex: fv = "samething/ubuntu:0.1.0" pattern = "something/IMAGE:VERSION". Error out at 'a' in fv. + if fv[fvInd] != pattern[patternInd] { + return nil, errors.Errorf("unable to derive values for markers, create setters for all markers and then try again") } - i++ - j++ + fvInd++ + patternInd++ } } // check if both strings are completely visited or throw error - if i < len(s) || j < len(p) { - return nil, errors.Errorf("Unable to derive values for markers. Create setters for all markers and then try again.") + if fvInd < len(fv) || patternInd < len(pattern) { + return nil, errors.Errorf("unable to derive values for markers, create setters for all markers and then try again") } return m, nil } // GetStartIndices returns the start indices of all the markers in the pattern func (c SubstitutionCreator) GetStartIndices() (map[int]string, error) { - inds := make(map[int]string) + indices := make(map[int]string) p := c.Pattern for _, value := range c.Values { m := value.Marker found := false for i := range p { if strings.HasPrefix(p[i:], m) { - inds[i] = m + indices[i] = m found = true } } @@ -188,12 +178,27 @@ func (c SubstitutionCreator) GetStartIndices() (map[int]string, error) { return nil, errors.Errorf("Unable to find marker " + m + " in the pattern") } } - return inds, nil + return indices, nil +} + +func (c SubstitutionCreator) extractValueForMarker(fvInd *int, fv string, patternInd int, indices map[int]string) string { + value := "" + lm := lenTillNextMarker(indices, patternInd) + + // keep appending chars to value till we find the substring between 2 markers in fv + // In example fv = "something/ubuntu:0.1.0", pattern = "something/IMAGE:VERSION", + // proceed till we find substring ":" in fv which makes value = ubuntu for marker IMAGE + for *fvInd < len(fv) && (patternInd == len(c.Pattern) || + fv[*fvInd:min(len(fv), *fvInd+lm)] != c.Pattern[patternInd:min(patternInd+lm, len(c.Pattern))]) { + value += string(fv[*fvInd]) + *fvInd++ + } + return value } // lenToNextMarker takes in the indices map, an index and returns the distance to -// next greater index -func lenToNextMarker(m map[int]string, j int) int { +// next marker start index in indices map +func lenTillNextMarker(m map[int]string, j int) int { res := math.MaxInt32 for k := range m { if k > j { diff --git a/kyaml/setters2/settersutil/substitutioncreator_test.go b/kyaml/setters2/settersutil/substitutioncreator_test.go index 9909d4254..c39956424 100644 --- a/kyaml/setters2/settersutil/substitutioncreator_test.go +++ b/kyaml/setters2/settersutil/substitutioncreator_test.go @@ -11,19 +11,9 @@ import ( ) func TestGetValuesForMarkersPositive(t *testing.T) { - value1 := setters2.Value{ - Marker: "IMAGE", - } - - value2 := setters2.Value{ - Marker: "VERSION", - } - - values := []setters2.Value{value1, value2} - c := SubstitutionCreator{ Pattern: "something/IMAGE::VERSION/otherthing/IMAGE::VERSION/", - Values: values, + Values: Values(), FieldValue: "something/nginx::0.1.0/otherthing/nginx::0.1.0/", } @@ -38,19 +28,9 @@ func TestGetValuesForMarkersPositive(t *testing.T) { } func TestGetValuesForMarkersDiffMarkerValues(t *testing.T) { - value1 := setters2.Value{ - Marker: "IMAGE", - } - - value2 := setters2.Value{ - Marker: "VERSION", - } - - values := []setters2.Value{value1, value2} - c := SubstitutionCreator{ Pattern: "something/IMAGE:VERSION/IMAGE", - Values: values, + Values: Values(), FieldValue: "something/nginx:0.1.0/ubuntu", } @@ -60,25 +40,15 @@ func TestGetValuesForMarkersDiffMarkerValues(t *testing.T) { t.FailNow() } - if !assert.Equal(t, err.Error(), "Same marker is found to have different values in field value.") { + if !assert.Equal(t, err.Error(), "same marker is found to have different values in field value") { t.FailNow() } } func TestGetValuesForMarkersNoMatch(t *testing.T) { - value1 := setters2.Value{ - Marker: "IMAGE", - } - - value2 := setters2.Value{ - Marker: "VERSION", - } - - values := []setters2.Value{value1, value2} - c := SubstitutionCreator{ Pattern: "something/IMAGE:VERSION", - Values: values, + Values: Values(), FieldValue: "otherthing/nginx:0.1.0", } @@ -88,25 +58,15 @@ func TestGetValuesForMarkersNoMatch(t *testing.T) { t.FailNow() } - if !assert.Equal(t, err.Error(), "Unable to derive values for markers. Create setters for all markers and then try again.") { + if !assert.Equal(t, err.Error(), "unable to derive values for markers, create setters for all markers and then try again") { t.FailNow() } } func TestGetValuesForMarkersNoMatch2(t *testing.T) { - value1 := setters2.Value{ - Marker: "IMAGE", - } - - value2 := setters2.Value{ - Marker: "VERSION", - } - - values := []setters2.Value{value1, value2} - c := SubstitutionCreator{ Pattern: "something/IMAGE:VERSION/abc", - Values: values, + Values: Values(), FieldValue: "something/nginx:0.1.0/abcd", } @@ -116,29 +76,19 @@ func TestGetValuesForMarkersNoMatch2(t *testing.T) { t.FailNow() } - if !assert.Equal(t, err.Error(), "Unable to derive values for markers. Create setters for all markers and then try again.") { + if !assert.Equal(t, err.Error(), "unable to derive values for markers, create setters for all markers and then try again") { t.FailNow() } } func TestGetValuesForMarkersSubStngMarkers(t *testing.T) { - value1 := setters2.Value{ - Marker: "IMAGE", - } - - value2 := setters2.Value{ - Marker: "VERSION", - } - value3 := setters2.Value{ Marker: "MAGE", } - values := []setters2.Value{value1, value2, value3} - c := SubstitutionCreator{ Pattern: "something/IMAGE:VERSION/abc/MAGE", - Values: values, + Values: append(Values(), value3), FieldValue: "something/nginx:0.1.0/abc/ubuntu", } @@ -152,3 +102,15 @@ func TestGetValuesForMarkersSubStngMarkers(t *testing.T) { assert.Equal(t, m["VERSION"], "0.1.0") assert.Equal(t, m["MAGE"], "ubuntu") } + +func Values() []setters2.Value { + value1 := setters2.Value{ + Marker: "IMAGE", + } + + value2 := setters2.Value{ + Marker: "VERSION", + } + + return []setters2.Value{value1, value2} +} From 275bf05ae242ef8491977396163d07c714a72fe1 Mon Sep 17 00:00:00 2001 From: Phani Teja Marupaka Date: Tue, 25 Feb 2020 17:15:24 -0800 Subject: [PATCH 3/3] Refactoring and Table tests --- .../settersutil/substitutioncreator.go | 110 ++++++---- .../settersutil/substitutioncreator_test.go | 191 +++++++++--------- 2 files changed, 169 insertions(+), 132 deletions(-) diff --git a/kyaml/setters2/settersutil/substitutioncreator.go b/kyaml/setters2/settersutil/substitutioncreator.go index 4acef990f..fc187c63e 100644 --- a/kyaml/setters2/settersutil/substitutioncreator.go +++ b/kyaml/setters2/settersutil/substitutioncreator.go @@ -4,7 +4,6 @@ package settersutil import ( - "math" "strings" "sigs.k8s.io/kustomize/kyaml/errors" @@ -138,17 +137,23 @@ func (c SubstitutionCreator) GetValuesForMarkers() (map[string]string, error) { if marker, ok := indices[patternInd]; ok { // increment the patternInd to end of marker. This helps us to extract the substring before next marker. patternInd += len(marker) - value := c.extractValueForMarker(&fvInd, fv, patternInd, indices) + var value string + if value, fvInd, err = c.extractValueForMarker(fvInd, fv, patternInd, indices); err != nil { + return nil, err + } // if marker is repeated in the pattern, make sure that the corresponding values // are same and throw error if not. if prevValue, ok := m[marker]; ok && prevValue != value { - return nil, errors.Errorf("same marker is found to have different values in field value") + return nil, errors.Errorf( + "marker %s is found to have different values %s and %s", marker, prevValue, value) } m[marker] = value } else { // Ex: fv = "samething/ubuntu:0.1.0" pattern = "something/IMAGE:VERSION". Error out at 'a' in fv. if fv[fvInd] != pattern[patternInd] { - return nil, errors.Errorf("unable to derive values for markers, create setters for all markers and then try again") + return nil, errors.Errorf( + "unable to derive values for markers, " + + "create setters for all markers and then try again") } fvInd++ patternInd++ @@ -156,7 +161,9 @@ func (c SubstitutionCreator) GetValuesForMarkers() (map[string]string, error) { } // check if both strings are completely visited or throw error if fvInd < len(fv) || patternInd < len(pattern) { - return nil, errors.Errorf("unable to derive values for markers, create setters for all markers and then try again") + return nil, errors.Errorf( + "unable to derive values for markers, " + + "create setters for all markers and then try again") } return m, nil } @@ -164,48 +171,83 @@ func (c SubstitutionCreator) GetValuesForMarkers() (map[string]string, error) { // GetStartIndices returns the start indices of all the markers in the pattern func (c SubstitutionCreator) GetStartIndices() (map[int]string, error) { indices := make(map[int]string) - p := c.Pattern for _, value := range c.Values { - m := value.Marker found := false - for i := range p { - if strings.HasPrefix(p[i:], m) { - indices[i] = m + for i := range c.Pattern { + if strings.HasPrefix(c.Pattern[i:], value.Marker) { + indices[i] = value.Marker found = true } } if !found { - return nil, errors.Errorf("Unable to find marker " + m + " in the pattern") + return nil, errors.Errorf("unable to find marker " + value.Marker + " in the pattern") } } + if err := validateMarkers(indices); err != nil { + return nil, err + } return indices, nil } -func (c SubstitutionCreator) extractValueForMarker(fvInd *int, fv string, patternInd int, indices map[int]string) string { - value := "" - lm := lenTillNextMarker(indices, patternInd) - - // keep appending chars to value till we find the substring between 2 markers in fv - // In example fv = "something/ubuntu:0.1.0", pattern = "something/IMAGE:VERSION", - // proceed till we find substring ":" in fv which makes value = ubuntu for marker IMAGE - for *fvInd < len(fv) && (patternInd == len(c.Pattern) || - fv[*fvInd:min(len(fv), *fvInd+lm)] != c.Pattern[patternInd:min(patternInd+lm, len(c.Pattern))]) { - value += string(fv[*fvInd]) - *fvInd++ - } - return value -} - -// lenToNextMarker takes in the indices map, an index and returns the distance to -// next marker start index in indices map -func lenTillNextMarker(m map[int]string, j int) int { - res := math.MaxInt32 - for k := range m { - if k > j { - res = min(k-j, res) +// validateMarkers takes the indices map, checks if any of 2 markers not have delimiters, +// checks if any marker is substring of other and returns error +func validateMarkers(indices map[int]string) error { + for k1, v1 := range indices { + for k2, v2 := range indices { + if k1 != k2 && k1+len(v1) == k2 { + return errors.Errorf( + "markers %s and %s are found to have no delimiters between them,"+ + " pre-create setters and try again", v1, v2) + } + if v1 != v2 && strings.Contains(v1, v2) { + return errors.Errorf( + "markers %s is substring of %s,"+ + " no marker should be substring of other", v2, v1) + } } } - return res + return nil +} + +// extractValueForMarker returns the value string for a marker and the incremented index +func (c SubstitutionCreator) extractValueForMarker(fvInd int, fv string, patternInd int, indices map[int]string) (string, int, error) { + nonMarkerStr := strTillNextMarker(indices, patternInd, c.Pattern) + + // return the remaining string of fv till end if patternInd is at end of pattern + if patternInd == len(c.Pattern) { + return fv[fvInd:], len(fv), nil + } + + // split remaining fv starting from fvInd with the non marker substring delimiter and get the first value + // In example fv = "something/ubuntu::0.1.0", pattern = "something/IMAGE::VERSION", + // split with "::" delimiter in fv which gives markerValue = ubuntu for marker IMAGE + // increment fvInd by length of extracted marker value and return fvInd + if markerValues := strings.Split(fv[fvInd:], nonMarkerStr); len(markerValues) > 0 { + return markerValues[0], fvInd + len(markerValues[0]), nil + } + + return "", -1, errors.Errorf( + "unable to derive values for markers," + + " create setters for all markers and then try again") +} + +// substrOfLen takes a string, start index and length and returns substring of given length +// or till end of string +func substrOfLen(str string, startInd int, length int) string { + return str[startInd:min(len(str), startInd+length)] +} + +// strTillNextMarker takes in the indices map, a start index and returns the substring till +// start of next marker +func strTillNextMarker(indices map[int]string, startInd int, pattern string) string { + // initialize with max value which is length of pattern + nextMarkerStartInd := len(pattern) + for ind := range indices { + if ind > startInd { + nextMarkerStartInd = min(ind-startInd, nextMarkerStartInd) + } + } + return substrOfLen(pattern, startInd, nextMarkerStartInd) } func min(a int, b int) int { diff --git a/kyaml/setters2/settersutil/substitutioncreator_test.go b/kyaml/setters2/settersutil/substitutioncreator_test.go index c39956424..9c6b2951b 100644 --- a/kyaml/setters2/settersutil/substitutioncreator_test.go +++ b/kyaml/setters2/settersutil/substitutioncreator_test.go @@ -7,110 +7,105 @@ import ( "testing" "github.com/stretchr/testify/assert" + "sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/setters2" ) -func TestGetValuesForMarkersPositive(t *testing.T) { - c := SubstitutionCreator{ - Pattern: "something/IMAGE::VERSION/otherthing/IMAGE::VERSION/", - Values: Values(), - FieldValue: "something/nginx::0.1.0/otherthing/nginx::0.1.0/", +func TestGetValuesForMarkers(t *testing.T) { + var tests = []struct { + name string + pattern string + fieldValue string + markers []string + expectedError error + expectedOutput map[string]string + }{ + { + name: "positive example", + markers: []string{"IMAGE", "VERSION"}, + pattern: "something/IMAGE::VERSION/otherthing/IMAGE::VERSION/", + fieldValue: "something/nginx::0.1.0/otherthing/nginx::0.1.0/", + expectedOutput: map[string]string{"IMAGE": "nginx", "VERSION": "0.1.0"}, + }, + { + name: "marker with different values", + markers: []string{"IMAGE", "VERSION"}, + pattern: "something/IMAGE:VERSION/IMAGE", + fieldValue: "something/nginx:0.1.0/ubuntu", + expectedError: errors.Errorf("marker IMAGE is found to have different values nginx and ubuntu"), + }, + { + name: "unmatched pattern", + markers: []string{"IMAGE", "VERSION"}, + pattern: "something/IMAGE:VERSION", + fieldValue: "otherthing/nginx:0.1.0", + expectedError: errors.Errorf("unable to derive values for markers"), + }, + { + name: "unmatched pattern at the end", + markers: []string{"IMAGE", "VERSION"}, + pattern: "something/IMAGE:VERSION/abc", + fieldValue: "something/nginx:0.1.0/abcd", + expectedError: errors.Errorf("unable to derive values for markers"), + }, + { + name: "substring markers", + markers: []string{"IMAGE", "VERSION", "MAGE"}, + pattern: "something/IMAGE:VERSION/abc/MAGE", + fieldValue: "something/nginx:0.1.0/abc/ubuntu", + expectedError: errors.Errorf("no marker should be substring of other"), + }, + { + name: "markers with no delimiters", + markers: []string{"IMAGE", "VERSION"}, + pattern: "something/IMAGEVERSION/", + fieldValue: "something/nginx0.1.0/", + expectedError: errors.Errorf("no delimiters between them"), + }, + { + name: "unmatched delimiter", + markers: []string{"IMAGE", "VERSION"}, + pattern: "something/IMAGE:^VERSION/otherthing/IMAGE::VERSION/", + fieldValue: "something/nginx::0.1.0/otherthing/nginx::0.1.0/", + expectedError: errors.Errorf("unable to derive values for markers"), + }, } + for i := range tests { + test := tests[i] + t.Run(test.name, func(t *testing.T) { + values := []setters2.Value{} + for _, marker := range test.markers { + value := setters2.Value{ + Marker: marker, + } + values = append(values, value) + } - m, err := c.GetValuesForMarkers() + sc := SubstitutionCreator{ + Pattern: test.pattern, + Values: values, + FieldValue: test.fieldValue, + } - if !assert.NoError(t, err) { - t.FailNow() - } + m, err := sc.GetValuesForMarkers() - assert.Equal(t, m["IMAGE"], "nginx") - assert.Equal(t, m["VERSION"], "0.1.0") -} - -func TestGetValuesForMarkersDiffMarkerValues(t *testing.T) { - c := SubstitutionCreator{ - Pattern: "something/IMAGE:VERSION/IMAGE", - Values: Values(), - FieldValue: "something/nginx:0.1.0/ubuntu", - } - - _, err := c.GetValuesForMarkers() - - if !assert.Error(t, err) { - t.FailNow() - } - - if !assert.Equal(t, err.Error(), "same marker is found to have different values in field value") { - t.FailNow() + if test.expectedError == nil { + // fail if expectedError is nil but actual error is not + if !assert.NoError(t, err) { + t.FailNow() + } + // check if all the expected markers and values are present in actual map + for k, v := range test.expectedOutput { + if val, ok := m[k]; ok { + assert.Equal(t, v, val) + } else { + t.FailNow() + } + } + } else { + //if expectedError is not nil, check for correctness of error message + assert.Contains(t, err.Error(), test.expectedError.Error()) + } + }) } } - -func TestGetValuesForMarkersNoMatch(t *testing.T) { - c := SubstitutionCreator{ - Pattern: "something/IMAGE:VERSION", - Values: Values(), - FieldValue: "otherthing/nginx:0.1.0", - } - - _, err := c.GetValuesForMarkers() - - if !assert.Error(t, err) { - t.FailNow() - } - - if !assert.Equal(t, err.Error(), "unable to derive values for markers, create setters for all markers and then try again") { - t.FailNow() - } -} - -func TestGetValuesForMarkersNoMatch2(t *testing.T) { - c := SubstitutionCreator{ - Pattern: "something/IMAGE:VERSION/abc", - Values: Values(), - FieldValue: "something/nginx:0.1.0/abcd", - } - - _, err := c.GetValuesForMarkers() - - if !assert.Error(t, err) { - t.FailNow() - } - - if !assert.Equal(t, err.Error(), "unable to derive values for markers, create setters for all markers and then try again") { - t.FailNow() - } -} - -func TestGetValuesForMarkersSubStngMarkers(t *testing.T) { - value3 := setters2.Value{ - Marker: "MAGE", - } - - c := SubstitutionCreator{ - Pattern: "something/IMAGE:VERSION/abc/MAGE", - Values: append(Values(), value3), - FieldValue: "something/nginx:0.1.0/abc/ubuntu", - } - - m, err := c.GetValuesForMarkers() - - if !assert.NoError(t, err) { - t.FailNow() - } - - assert.Equal(t, m["IMAGE"], "nginx") - assert.Equal(t, m["VERSION"], "0.1.0") - assert.Equal(t, m["MAGE"], "ubuntu") -} - -func Values() []setters2.Value { - value1 := setters2.Value{ - Marker: "IMAGE", - } - - value2 := setters2.Value{ - Marker: "VERSION", - } - - return []setters2.Value{value1, value2} -}