diff --git a/go.mod b/go.mod index 781b803f..a9f5516a 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/bradleyfalzon/ghinstallation/v2 v2.12.0 github.com/distribution/distribution/v3 v3.0.0-20230722181636-7b502560cad4 github.com/go-git/go-git/v5 v5.13.2 + github.com/goccy/go-yaml v1.15.22 github.com/google/uuid v1.6.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/prometheus/client_golang v1.20.5 @@ -26,7 +27,6 @@ require ( golang.org/x/oauth2 v0.25.0 golang.org/x/sync v0.10.0 google.golang.org/grpc v1.70.0 - gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.31.0 k8s.io/apimachinery v0.31.0 k8s.io/client-go v0.31.0 @@ -154,6 +154,7 @@ require ( gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.31.2 // indirect k8s.io/apiserver v0.31.0 // indirect diff --git a/go.sum b/go.sum index f0e80ad3..dd32f8a0 100644 --- a/go.sum +++ b/go.sum @@ -192,6 +192,8 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/goccy/go-yaml v1.15.22 h1:iQI1hvCoiYYiVFq76P4AI8ImgDOfgiyKnl/AWjK8/gA= +github.com/goccy/go-yaml v1.15.22/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gogits/go-gogs-client v0.0.0-20200905025246-8bb8a50cb355 h1:HTVNOdTWO/gHYeFnr/HwpYwY6tgMcYd+Rgf1XrHnORY= github.com/gogits/go-gogs-client v0.0.0-20200905025246-8bb8a50cb355/go.mod h1:cY2AIrMgHm6oOHmR7jY+9TtjzSjQ3iG7tURJG3Y6XH0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= diff --git a/pkg/argocd/argocd.go b/pkg/argocd/argocd.go index de540f68..535ecfd1 100644 --- a/pkg/argocd/argocd.go +++ b/pkg/argocd/argocd.go @@ -336,7 +336,7 @@ func getHelmParamNamesFromAnnotation(annotations map[string]string, img *image.C // Get a named helm parameter from a list of parameters func getHelmParam(params []v1alpha1.HelmParameter, name string) *v1alpha1.HelmParameter { for _, param := range params { - if param.Name == name { + if param.Name == strings.Trim(name, "'\"") { return ¶m } } diff --git a/pkg/argocd/update.go b/pkg/argocd/update.go index f7055cfa..a3bf3bfc 100644 --- a/pkg/argocd/update.go +++ b/pkg/argocd/update.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "path/filepath" + "regexp" "strings" "sync" "text/template" @@ -21,7 +22,11 @@ import ( "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" - "gopkg.in/yaml.v2" + + "github.com/goccy/go-yaml" + "github.com/goccy/go-yaml/ast" + "github.com/goccy/go-yaml/parser" + "github.com/goccy/go-yaml/token" ) // Stores some statistics about the results of a run @@ -459,8 +464,7 @@ func marshalParamsOverride(app *v1alpha1.Application, originalData []byte) ([]by if strings.HasPrefix(app.Annotations[common.WriteBackTargetAnnotation], common.HelmPrefix) { images := GetImagesAndAliasesFromApplication(app) - helmNewValues := yaml.MapSlice{} - err = yaml.Unmarshal(originalData, &helmNewValues) + helmNewValues, err := parser.ParseBytes(originalData, parser.ParseComments) if err != nil { return nil, err } @@ -488,7 +492,7 @@ func marshalParamsOverride(app *v1alpha1.Application, originalData []byte) ([]by if helmParamVersion == nil { return nil, fmt.Errorf("%s parameter not found", helmAnnotationParamVersion) } - err = setHelmValue(&helmNewValues, helmAnnotationParamVersion, helmParamVersion.Value) + err = setHelmValue(helmNewValues, helmAnnotationParamVersion, helmParamVersion.Value) if err != nil { return nil, fmt.Errorf("failed to set image parameter version value: %v", err) } @@ -499,13 +503,13 @@ func marshalParamsOverride(app *v1alpha1.Application, originalData []byte) ([]by return nil, fmt.Errorf("%s parameter not found", helmAnnotationParamName) } - err = setHelmValue(&helmNewValues, helmAnnotationParamName, helmParamName.Value) + err = setHelmValue(helmNewValues, helmAnnotationParamName, helmParamName.Value) if err != nil { return nil, fmt.Errorf("failed to set image parameter name value: %v", err) } } - override, err = yaml.Marshal(helmNewValues) + override = []byte(helmNewValues.String()) } else { var params helmOverride newParams := helmOverride{ @@ -561,76 +565,118 @@ func mergeKustomizeOverride(t *kustomizeOverride, o *kustomizeOverride) { } } -// Check if a key exists in a MapSlice and return its index and value -func findHelmValuesKey(m yaml.MapSlice, key string) (int, bool) { - for i, item := range m { - if item.Key == key { - return i, true +func splitKeys(input string) []string { + // Regular expression to match quoted and unquoted segments + re := regexp.MustCompile(`'([^']*)'|"([^"]*)"|([^.".]+)`) + matches := re.FindAllStringSubmatch(input, -1) + + var result []string + for _, match := range matches { + if match[1] != "" { // Single-quoted string + result = append(result, match[1]) + } else if match[2] != "" { // Double-quoted string + result = append(result, match[2]) + } else if match[3] != "" { // Unquoted segment + result = append(result, match[3]) } } - return -1, false + + return result } // set value of the parameter passed from the annotations. -func setHelmValue(currentValues *yaml.MapSlice, key string, value interface{}) error { - // Check if the full key exists - if idx, found := findHelmValuesKey(*currentValues, key); found { - (*currentValues)[idx].Value = value - return nil +func setHelmValue(file *ast.File, keyPath, value string) error { + path := splitKeys(keyPath) + if len(path) == 0 { + return fmt.Errorf("empty key provided") } - var err error - keys := strings.Split(key, ".") - current := currentValues - var parent *yaml.MapSlice - parentIdx := -1 - - for i, k := range keys { - if idx, found := findHelmValuesKey(*current, k); found { - if i == len(keys)-1 { - // If we're at the final key, set the value and return - (*current)[idx].Value = value - return nil - } else { - // Navigate deeper into the map - if nestedMap, ok := (*current)[idx].Value.(yaml.MapSlice); ok { - parent = current - parentIdx = idx - current = &nestedMap - } else { - return fmt.Errorf("unexpected type %T for key %s", (*current)[idx].Value, k) + var mapping *ast.MappingNode + if file.Docs[0].Body == nil { + tk := token.New("$", "$", &token.Position{}) + mapping = ast.Mapping(tk, false) + file.Docs[0].Body = mapping + } else { + mapping, _ = file.Docs[0].Body.(*ast.MappingNode) + if mapping == nil { + return fmt.Errorf("yaml is invalid") + } + } + + // Traverse the path + var lastNode *ast.MappingValueNode + for index, key := range path { + found := false + var currentNode *ast.MappingValueNode + + for _, v := range mapping.Values { + if v.Key.GetToken().Value == key { + currentNode = v + if index == len(path)-1 { + lastNode = currentNode + found = true + break + } + // Move deeper into the structure + if nextMapping, ok := v.Value.(*ast.MappingNode); ok { + mapping = nextMapping + found = true + break } } - } else { - newCurrent := yaml.MapSlice{} - var newParent yaml.MapSlice + } - if i == len(keys)-1 { - newParent = append(*current, yaml.MapItem{Key: k, Value: value}) - } else { - newParent = append(*current, yaml.MapItem{Key: k, Value: newCurrent}) - } + // If key does not exist, create it + if !found { + // Create a token with proper position (assuming default line/column) + keyToken := token.New(key, key, &token.Position{Column: index*2 + 1}) + newKey := ast.String(keyToken) // Create key node + mappingToken := token.New(key, key, &token.Position{}) + newMapping := ast.Mapping(mappingToken, false) // Create empty mapping - if parent == nil { - *currentValues = newParent - } else { - // if parentIdx has not been set (parent element is also new), set it to the last element - if parentIdx == -1 { - parentIdx = len(*parent) - 1 - if parentIdx < 0 { - parentIdx = 0 - } + if currentNode != nil { + comment := currentNode.Value.GetComment() + currentNode.Value = newMapping + err := currentNode.Value.SetComment(comment) + if err != nil { + return err } - (*parent)[parentIdx].Value = newParent + lastNode = currentNode + } else { + // Add the new mapping to the parent mapping + lastNode = ast.MappingValue(mappingToken, newKey, newMapping) + mapping.Values = append(mapping.Values, lastNode) } - - parent = &newParent - current = &newCurrent - parentIdx = -1 + mapping = newMapping } } - return err + if lastNode == nil { + return fmt.Errorf("key not found") + } + + var valueToken *token.Token + if token.IsNeedQuoted(value) { + valueToken = token.SingleQuote(value, value, &token.Position{}) + } else { + valueToken = token.New(value, value, &token.Position{}) + } + newValue := ast.String(valueToken) + comment := lastNode.Value.GetComment() + if comment == nil { + comment = lastNode.Key.GetComment() + } + lastNode.Value = newValue + err := lastNode.Key.SetComment(nil) + if err != nil { + return err + } + err = lastNode.Value.SetComment(comment) + if err != nil { + return err + } + + return nil } func getWriteBackConfig(app *v1alpha1.Application, kubeClient *kube.ImageUpdaterKubernetesClient, argoClient ArgoCD) (*WriteBackConfig, error) { diff --git a/pkg/argocd/update_test.go b/pkg/argocd/update_test.go index 21cd62a0..718c678e 100644 --- a/pkg/argocd/update_test.go +++ b/pkg/argocd/update_test.go @@ -9,8 +9,6 @@ import ( "testing" "time" - "gopkg.in/yaml.v2" - "github.com/argoproj-labs/argocd-image-updater/ext/git" gitmock "github.com/argoproj-labs/argocd-image-updater/ext/git/mocks" argomock "github.com/argoproj-labs/argocd-image-updater/pkg/argocd/mocks" @@ -28,6 +26,7 @@ import ( "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/distribution/distribution/v3/manifest/schema1" //nolint:staticcheck + "github.com/goccy/go-yaml/parser" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -1251,13 +1250,12 @@ helm: parameters: - name: baz value: baz - forcestring: false - name: foo value: bar - forcestring: true + forceString: true - name: bar value: foo - forcestring: true + forceString: true ` app := v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ @@ -1297,7 +1295,7 @@ helm: parameters: - name: baz value: baz - forcestring: false + forceString: false `) yaml, err := marshalParamsOverride(&app, originalData) require.NoError(t, err) @@ -1311,10 +1309,10 @@ helm: parameters: - name: foo value: bar - forcestring: true + forceString: true - name: bar value: foo - forcestring: true + forceString: true ` app := v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ @@ -1362,10 +1360,10 @@ helm: parameters: - name: foo value: bar - forcestring: true + forceString: true - name: bar value: foo - forcestring: true + forceString: true ` app := v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ @@ -1445,8 +1443,8 @@ replicas: 1 "argocd-image-updater.argoproj.io/image-list": "nginx", "argocd-image-updater.argoproj.io/write-back-method": "git", "argocd-image-updater.argoproj.io/write-back-target": "helmvalues:./test-values.yaml", - "argocd-image-updater.argoproj.io/nginx.helm.image-name": "image.name", - "argocd-image-updater.argoproj.io/nginx.helm.image-tag": "image.tag", + "argocd-image-updater.argoproj.io/nginx.helm.image-name": "'image.name'", + "argocd-image-updater.argoproj.io/nginx.helm.image-tag": "'image.tag'", }, }, Spec: v1alpha1.ApplicationSpec{ @@ -1502,7 +1500,7 @@ replicas: 1 "argocd-image-updater.argoproj.io/image-list": "nginx", "argocd-image-updater.argoproj.io/write-back-method": "git", "argocd-image-updater.argoproj.io/write-back-target": "helmvalues:./test-values.yaml", - "argocd-image-updater.argoproj.io/nginx.helm.image-spec": "image.spec.foo", + "argocd-image-updater.argoproj.io/nginx.helm.image-spec": "'image.spec.foo'", }, }, Spec: v1alpha1.ApplicationSpec{ @@ -1538,20 +1536,6 @@ replicas: 1 require.NoError(t, err) assert.NotEmpty(t, yaml) assert.Equal(t, strings.TrimSpace(strings.ReplaceAll(expected, "\t", " ")), strings.TrimSpace(string(yaml))) - - // when image.spec.foo fields are missing in the target helm value file, - // they should be auto created without corrupting any other pre-existing elements. - originalData = []byte("test-value1: one") - expected = ` -test-value1: one -image: - spec: - foo: nginx:v1.0.0 -` - yaml, err = marshalParamsOverride(&app, originalData) - require.NoError(t, err) - assert.NotEmpty(t, yaml) - assert.Equal(t, strings.TrimSpace(strings.ReplaceAll(expected, "\t", " ")), strings.TrimSpace(string(yaml))) }) t.Run("Valid Helm source with Helm values file with multiple images", func(t *testing.T) { @@ -1569,10 +1553,10 @@ replicas: 1 "argocd-image-updater.argoproj.io/image-list": "nginx=nginx, redis=redis", "argocd-image-updater.argoproj.io/write-back-method": "git", "argocd-image-updater.argoproj.io/write-back-target": "helmvalues:./test-values.yaml", - "argocd-image-updater.argoproj.io/nginx.helm.image-name": "nginx.image.name", - "argocd-image-updater.argoproj.io/nginx.helm.image-tag": "nginx.image.tag", - "argocd-image-updater.argoproj.io/redis.helm.image-name": "redis.image.name", - "argocd-image-updater.argoproj.io/redis.helm.image-tag": "redis.image.tag", + "argocd-image-updater.argoproj.io/nginx.helm.image-name": "'nginx.image.name'", + "argocd-image-updater.argoproj.io/nginx.helm.image-tag": "'nginx.image.tag'", + "argocd-image-updater.argoproj.io/redis.helm.image-name": "'redis.image.name'", + "argocd-image-updater.argoproj.io/redis.helm.image-tag": "'redis.image.tag'", }, }, Spec: v1alpha1.ApplicationSpec{ @@ -1640,25 +1624,6 @@ replicas: 1 require.NoError(t, err) assert.NotEmpty(t, yaml) assert.Equal(t, strings.TrimSpace(strings.ReplaceAll(expected, "\t", " ")), strings.TrimSpace(string(yaml))) - - // when nginx.* and redis.* fields are missing in the target helm value file, - // they should be auto created without corrupting any other pre-existing elements. - originalData = []byte("test-value1: one") - expected = ` -test-value1: one -nginx: - image: - tag: v1.0.0 - name: nginx -redis: - image: - tag: v1.0.0 - name: redis -` - yaml, err = marshalParamsOverride(&app, originalData) - require.NoError(t, err) - assert.NotEmpty(t, yaml) - assert.Equal(t, strings.TrimSpace(strings.ReplaceAll(expected, "\t", " ")), strings.TrimSpace(string(yaml))) }) t.Run("Valid Helm source with Helm values file with multiple aliases", func(t *testing.T) { @@ -1678,12 +1643,12 @@ replicas: 1 "argocd-image-updater.argoproj.io/image-list": "foo=nginx, bar=nginx, bbb=nginx", "argocd-image-updater.argoproj.io/write-back-method": "git", "argocd-image-updater.argoproj.io/write-back-target": "helmvalues:./test-values.yaml", - "argocd-image-updater.argoproj.io/foo.helm.image-name": "foo.image.name", - "argocd-image-updater.argoproj.io/foo.helm.image-tag": "foo.image.tag", - "argocd-image-updater.argoproj.io/bar.helm.image-name": "bar.image.name", - "argocd-image-updater.argoproj.io/bar.helm.image-tag": "bar.image.tag", - "argocd-image-updater.argoproj.io/bbb.helm.image-name": "bbb.image.name", - "argocd-image-updater.argoproj.io/bbb.helm.image-tag": "bbb.image.tag", + "argocd-image-updater.argoproj.io/foo.helm.image-name": "'foo.image.name'", + "argocd-image-updater.argoproj.io/foo.helm.image-tag": "'foo.image.tag'", + "argocd-image-updater.argoproj.io/bar.helm.image-name": "'bar.image.name'", + "argocd-image-updater.argoproj.io/bar.helm.image-tag": "'bar.image.tag'", + "argocd-image-updater.argoproj.io/bbb.helm.image-name": "'bbb.image.name'", + "argocd-image-updater.argoproj.io/bbb.helm.image-tag": "'bbb.image.tag'", }, }, Spec: v1alpha1.ApplicationSpec{ @@ -2156,122 +2121,156 @@ replicas: 1 func Test_SetHelmValue(t *testing.T) { t.Run("Update existing Key", func(t *testing.T) { - expected := yaml.MapSlice{ - {Key: "image", Value: yaml.MapSlice{ - {Key: "attributes", Value: yaml.MapSlice{ - {Key: "name", Value: "repo-name"}, - {Key: "tag", Value: "v2.0.0"}, - }}, - }}, - } - - input := yaml.MapSlice{ - {Key: "image", Value: yaml.MapSlice{ - {Key: "attributes", Value: yaml.MapSlice{ - {Key: "name", Value: "repo-name"}, - {Key: "tag", Value: "v1.0.0"}, - }}, - }}, - } - key := "image.attributes.tag" + expected := ` +image: + name: repo-name + tag: v2.0.0 +` + + input := ` +image: + name: repo-name + tag: v1.0.0 +` + + key := "image.tag" value := "v2.0.0" - err := setHelmValue(&input, key, value) + file, err := parser.ParseBytes([]byte(input), parser.ParseComments) require.NoError(t, err) - assert.Equal(t, expected, input) + err = setHelmValue(file, key, value) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(file.String())) }) t.Run("Update Key with dots", func(t *testing.T) { - expected := yaml.MapSlice{ - {Key: "image.attributes.tag", Value: "v2.0.0"}, - } - - input := yaml.MapSlice{ - {Key: "image.attributes.tag", Value: "v1.0.0"}, - } - key := "image.attributes.tag" + expected := `image.tag: v2.0.0` + input := `image.tag: v1.0.0` + key := "'image.tag'" value := "v2.0.0" - err := setHelmValue(&input, key, value) + file, err := parser.ParseBytes([]byte(input), parser.ParseComments) require.NoError(t, err) - assert.Equal(t, expected, input) + err = setHelmValue(file, key, value) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(file.String())) }) t.Run("Key not found", func(t *testing.T) { - expected := yaml.MapSlice{ - {Key: "image", Value: yaml.MapSlice{ - {Key: "attributes", Value: yaml.MapSlice{ - {Key: "name", Value: "repo-name"}, - {Key: "tag", Value: "v2.0.0"}, - }}, - }}, - } + expected := ` +image: + name: repo-name + tag: v2.0.0 +` - input := yaml.MapSlice{ - {Key: "image", Value: yaml.MapSlice{ - {Key: "attributes", Value: yaml.MapSlice{ - {Key: "name", Value: "repo-name"}, - }}, - }}, - } + input := ` +image: + name: repo-name +` - key := "image.attributes.tag" + key := "image.tag" value := "v2.0.0" - err := setHelmValue(&input, key, value) + file, err := parser.ParseBytes([]byte(input), parser.ParseComments) + require.NoError(t, err) + err = setHelmValue(file, key, value) require.NoError(t, err) - assert.Equal(t, expected, input) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(file.String())) }) t.Run("Root key not found", func(t *testing.T) { - expected := yaml.MapSlice{ - {Key: "name", Value: "repo-name"}, - {Key: "tag", Value: "v2.0.0"}, - } + expected := ` +name: repo-name +tag: v2.0.0 +` - input := yaml.MapSlice{ - {Key: "name", Value: "repo-name"}, - } + input := `name: repo-name` key := "tag" value := "v2.0.0" - err := setHelmValue(&input, key, value) + file, err := parser.ParseBytes([]byte(input), parser.ParseComments) require.NoError(t, err) - assert.Equal(t, expected, input) + err = setHelmValue(file, key, value) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(file.String())) }) t.Run("Empty values with deep key", func(t *testing.T) { - expected := yaml.MapSlice{ - {Key: "image", Value: yaml.MapSlice{ - {Key: "attributes", Value: yaml.MapSlice{ - {Key: "tag", Value: "v2.0.0"}, - }}, - }}, - } + expected := ` +image: + tag: v2.0.0 +` - input := yaml.MapSlice{} + input := "" - key := "image.attributes.tag" + key := "image.tag" value := "v2.0.0" - err := setHelmValue(&input, key, value) + file, err := parser.ParseBytes([]byte(input), parser.ParseComments) + require.NoError(t, err) + err = setHelmValue(file, key, value) require.NoError(t, err) - assert.Equal(t, expected, input) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(file.String())) }) - t.Run("Unexpected type for key", func(t *testing.T) { - input := yaml.MapSlice{ - {Key: "image", Value: yaml.MapSlice{ - {Key: "attributes", Value: "v1.0.0"}, - }}, - } - key := "image.attributes.tag" + t.Run("Override key type", func(t *testing.T) { + expected := ` +image: + tag: v2.0.0 +` + input := ` +image: v1.0.0 +` + + key := "image.tag" value := "v2.0.0" - err := setHelmValue(&input, key, value) - assert.Error(t, err) - assert.Equal(t, "unexpected type string for key attributes", err.Error()) + file, err := parser.ParseBytes([]byte(input), parser.ParseComments) + require.NoError(t, err) + err = setHelmValue(file, key, value) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(file.String())) + }) + + t.Run("Preserve comments and formatting", func(t *testing.T) { + expected := ` +# top comment +k: 111 +a: + m: # m key comment + g1: g value + b: # another comment + c: "existing value" # comment + d: new value + ver1: 2.0.0 # image version 1 + ver2: '2.0' # image version 2 +# bottom comment +` + input := ` +# top comment +k: 111 +a: + m: # m key comment + b: # another comment + c: "existing value" # comment + ver1: 1.0.0 # image version 1 + ver2: '1.0' # image version 2 +# bottom comment +` + + file, err := parser.ParseBytes([]byte(input), parser.ParseComments) + require.NoError(t, err) + err = setHelmValue(file, "a.b.d", "new value") + require.NoError(t, err) + err = setHelmValue(file, "a.m.g1", "g value") + require.NoError(t, err) + err = setHelmValue(file, "a.ver1", "2.0.0") + require.NoError(t, err) + err = setHelmValue(file, "a.ver2", "2.0") + require.NoError(t, err) + + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(file.String())) }) } @@ -3213,7 +3212,7 @@ helm: parameters: - name: foo value: foo - forcestring: true + forceString: true `), os.ModePerm)) gitMock.On("Checkout", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { @@ -3238,13 +3237,13 @@ helm: parameters: - name: foo value: foo - forcestring: true + forceString: true - name: bar value: bar - forcestring: true + forceString: true - name: baz value: baz - forcestring: true + forceString: true `, string(override)) }) @@ -3265,7 +3264,7 @@ helm: parameters: - name: foo value: foo - forcestring: true + forceString: true `), os.ModePerm)) gitMock.On("Checkout", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { @@ -3290,13 +3289,13 @@ helm: parameters: - name: foo value: foo - forcestring: true + forceString: true - name: bar value: bar - forcestring: true + forceString: true - name: baz value: baz - forcestring: true + forceString: true `, string(override)) }) @@ -3317,7 +3316,7 @@ helm: parameters: - name: foo value: foo - forcestring: true + forceString: true `), os.ModePerm)) gitMock.On("Checkout", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { @@ -3342,13 +3341,13 @@ helm: parameters: - name: foo value: foo - forcestring: true + forceString: true - name: bar value: bar - forcestring: true + forceString: true - name: baz value: baz - forcestring: true + forceString: true `, string(override)) })