-
-
Notifications
You must be signed in to change notification settings - Fork 352
Use gopkg.in/yaml.v2 for Helmfile v0.x #609
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
cf0d5b9
299d504
a3d5f27
d12c768
fb8f40e
397b5e7
98b1550
e95c08b
619c204
756e830
bea859c
cc24502
74e5358
f4af106
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -61,6 +61,7 @@ jobs: | |
| plugin-secrets-version: 3.15.0 | ||
| plugin-diff-version: 3.5.0 | ||
| extra-helmfile-flags: | ||
| v1mode: | ||
| - helm-version: v3.9.4 | ||
| kustomize-version: v4.5.7 | ||
| # We assume that the helm-secrets plugin is supposed to | ||
|
|
@@ -71,23 +72,34 @@ jobs: | |
| plugin-secrets-version: 4.0.0 | ||
| plugin-diff-version: 3.6.0 | ||
| extra-helmfile-flags: | ||
| v1mode: | ||
| - helm-version: v3.10.3 | ||
| kustomize-version: v4.4.1 | ||
| plugin-secrets-version: 3.15.0 | ||
| plugin-diff-version: 3.5.0 | ||
| extra-helmfile-flags: | ||
| v1mode: | ||
| - helm-version: v3.10.3 | ||
| kustomize-version: v4.5.7 | ||
| plugin-secrets-version: 4.0.0 | ||
| plugin-diff-version: 3.6.0 | ||
| extra-helmfile-flags: | ||
| v1mode: | ||
| # Helmfile v1 | ||
| - helm-version: v3.10.3 | ||
| kustomize-version: v4.5.7 | ||
| plugin-secrets-version: 4.0.0 | ||
| plugin-diff-version: 3.6.0 | ||
| extra-helmfile-flags: | ||
| v1mode: "true" | ||
| # In case you need to test some optional helmfile features, | ||
| # enable it via extra-helmfile-flags below. | ||
| - helm-version: v3.10.3 | ||
| kustomize-version: v4.5.7 | ||
| plugin-secrets-version: 4.0.0 | ||
| plugin-diff-version: 3.6.0 | ||
| extra-helmfile-flags: "--enable-live-output" | ||
| v1mode: | ||
| steps: | ||
| - uses: actions/checkout@v2 | ||
| - name: Cache libraries | ||
|
|
@@ -131,6 +143,7 @@ jobs: | |
| HELMFILE_HELM3: 1 | ||
| TERM: xterm | ||
| EXTRA_HELMFILE_FLAGS: ${{ matrix.extra-helmfile-flags }} | ||
| HELMFILE_V1MODE: ${{ matrix.v1mode }} | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI, |
||
| run: make integration | ||
| e2e_tests: | ||
| needs: tests | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,8 +15,8 @@ import ( | |
| "github.com/helmfile/helmfile/pkg/exectest" | ||
| ffs "github.com/helmfile/helmfile/pkg/filesystem" | ||
| "github.com/helmfile/helmfile/pkg/helmexec" | ||
| "github.com/helmfile/helmfile/pkg/runtime" | ||
| "github.com/helmfile/helmfile/pkg/testhelper" | ||
| "github.com/helmfile/helmfile/pkg/yaml" | ||
| ) | ||
|
|
||
| func TestTemplate(t *testing.T) { | ||
|
|
@@ -309,20 +309,21 @@ releases: | |
| } | ||
|
|
||
| func TestTemplate_StrictParsing(t *testing.T) { | ||
| v := yaml.GoccyGoYaml | ||
| yaml.GoccyGoYaml = true | ||
| t.Cleanup(func() { | ||
| yaml.GoccyGoYaml = v | ||
| }) | ||
|
|
||
| type testcase struct { | ||
| ns string | ||
| error string | ||
| goccyGoYaml bool | ||
| ns string | ||
| error string | ||
| } | ||
|
|
||
| check := func(t *testing.T, tc testcase) { | ||
| t.Helper() | ||
|
|
||
| v := runtime.GoccyGoYaml | ||
| runtime.GoccyGoYaml = tc.goccyGoYaml | ||
| t.Cleanup(func() { | ||
| runtime.GoccyGoYaml = v | ||
| }) | ||
|
Comment on lines
+321
to
+325
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an idiom I used widely across many test sources to ensure we modify the GoccyGoYaml runtime variable only while running the (sub-)test. |
||
|
|
||
| var helm = &exectest.Helm{ | ||
| FailOnUnexpectedList: true, | ||
| FailOnUnexpectedDiff: true, | ||
|
|
@@ -381,8 +382,9 @@ releases: | |
| }) | ||
| } | ||
|
|
||
| t.Run("fail due to known field", func(t *testing.T) { | ||
| t.Run("fail due to unknown field with goccy/go-yaml", func(t *testing.T) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might also see this idiom, the same test is run |
||
| check(t, testcase{ | ||
| goccyGoYaml: true, | ||
| error: `in ./helmfile.yaml: failed to read helmfile.yaml: reading document at index 1: [4:3] unknown field "foobar" | ||
| 2 | releases: | ||
| 3 | - name: app1 | ||
|
|
@@ -391,6 +393,14 @@ releases: | |
| 5 | chart: incubator/raw`, | ||
| }) | ||
| }) | ||
|
|
||
| t.Run("fail due to unknown field with gopkg.in/yaml.v2", func(t *testing.T) { | ||
| check(t, testcase{ | ||
| goccyGoYaml: false, | ||
| error: `in ./helmfile.yaml: failed to read helmfile.yaml: reading document at index 1: yaml: unmarshal errors: | ||
| line 4: field foobar not found in type state.ReleaseSpec`, | ||
| }) | ||
| }) | ||
| } | ||
|
|
||
| func TestTemplate_CyclicInheritance(t *testing.T) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,4 +10,6 @@ const ( | |
| Helm3 = "HELMFILE_HELM3" | ||
| UpgradeNoticeDisabled = "HELMFILE_UPGRADE_NOTICE_DISABLED" | ||
| V1Mode = "HELMFILE_V1MODE" | ||
| GoccyGoYaml = "HELMFILE_GOCCY_GOYAML" | ||
| CacheHome = "HELMFILE_CACHE_HOME" | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't strictly necessary to change our yaml library. However I added this because this helped tidy up our e2e/snapshot test to be runnable with/without v1 mode. |
||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,13 +13,23 @@ import ( | |
| var ( | ||
| V1Mode bool | ||
|
|
||
| // GoccyGoYaml is set to true in order to let Helmfile use | ||
| // goccy/go-yaml instead of gopkg.in/yaml.v2. | ||
| // It's false by default in Helmfile v0.x and true by default for Helmfile v1.x. | ||
| GoccyGoYaml bool | ||
|
|
||
| // We set this via ldflags at build-time so that we can use the | ||
| // value specified at the build time as the runtime default. | ||
| v1Mode string | ||
| ) | ||
|
|
||
| func Info() string { | ||
| return fmt.Sprintf("V1 mode = %v", V1Mode) | ||
| yamlLib := "gopkg.in/yaml.v2" | ||
| if GoccyGoYaml { | ||
| yamlLib = "goccy/go-yaml" | ||
| } | ||
|
|
||
| return fmt.Sprintf("V1 mode = %v\nYAML library = %v", V1Mode, yamlLib) | ||
| } | ||
|
|
||
| func init() { | ||
|
|
@@ -34,4 +44,14 @@ func init() { | |
| default: | ||
| V1Mode, _ = strconv.ParseBool(v1Mode) | ||
| } | ||
|
|
||
| // You can switch the YAML library at runtime via an envvar: | ||
| switch os.Getenv(envvar.GoccyGoYaml) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although goccy/go-yaml is the default for v1, you can opt in/out in both v0 and v1, by setting this envvar. |
||
| case "true": | ||
| GoccyGoYaml = true | ||
| case "false": | ||
| GoccyGoYaml = false | ||
| default: | ||
| GoccyGoYaml = V1Mode | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ package state | |
| import ( | ||
| "fmt" | ||
|
|
||
| "github.com/helmfile/helmfile/pkg/maputil" | ||
| "github.com/helmfile/helmfile/pkg/tmpl" | ||
| "github.com/helmfile/helmfile/pkg/yaml" | ||
| ) | ||
|
|
@@ -107,13 +108,18 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R | |
| return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, string(serialized), err) | ||
| } | ||
|
|
||
| var deserialized map[interface{}]interface{} | ||
| var deserialized map[string]interface{} | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yaml.v2 deserializes nested yaml dict to |
||
|
|
||
| if err := yaml.Unmarshal(s.Bytes(), &deserialized); err != nil { | ||
| return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, ts, err) | ||
| } | ||
|
|
||
| result.ValuesTemplate[i] = deserialized | ||
| m, err := maputil.CastKeysToStrings(deserialized) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, ts, err) | ||
| } | ||
|
|
||
| result.ValuesTemplate[i] = m | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -130,6 +136,12 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R | |
| return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%s\": %v", r.Name, i, ts, err) | ||
| } | ||
| result.Values[i] = s.String() | ||
| case map[interface{}]interface{}: | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| m, err := maputil.CastKeysToStrings(ts) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%s\": %v", r.Name, i, ts, err) | ||
| } | ||
| result.Values[i] = m | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,7 +121,7 @@ func TestHelmState_executeTemplates(t *testing.T) { | |
| Verify: nil, | ||
| Name: "app", | ||
| Namespace: "dev", | ||
| Values: []interface{}{map[interface{}]interface{}{"key": "app-val0"}}, | ||
| Values: []interface{}{map[string]interface{}{"key": "app-val0"}}, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| }, | ||
| }, | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,7 @@ import ( | |
|
|
||
| "github.com/helmfile/helmfile/pkg/envvar" | ||
| "github.com/helmfile/helmfile/pkg/helmexec" | ||
| "github.com/helmfile/helmfile/pkg/maputil" | ||
| "github.com/helmfile/helmfile/pkg/yaml" | ||
| ) | ||
|
|
||
|
|
@@ -286,11 +287,17 @@ func ToYaml(v interface{}) (string, error) { | |
| } | ||
|
|
||
| func FromYaml(str string) (Values, error) { | ||
| m := Values{} | ||
| m := map[string]interface{}{} | ||
|
|
||
| if err := yaml.Unmarshal([]byte(str), &m); err != nil { | ||
| return nil, fmt.Errorf("%s, offending yaml: %s", err, str) | ||
| } | ||
|
|
||
| m, err := maputil.CastKeysToStrings(m) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is especially important here because this function is supposed to be used like |
||
| if err != nil { | ||
| return nil, fmt.Errorf("%s, offending yaml: %s", err, str) | ||
| } | ||
|
|
||
| return m, nil | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yxxhero We now run the integration test suite for the v1 mode once per build, with the representative versions of helmfile dependencies, so that we won't break any v1 functionality until we finally stop maintaining v0.