From 4688cf0132a229c38dadabe81eecca49d78f827a Mon Sep 17 00:00:00 2001 From: Yusuke Kuoka Date: Wed, 4 Jan 2023 18:17:24 +0900 Subject: [PATCH] Use gopkg.in/yaml.v2 for Helmfile v0.x (#609) This should fix #435 for Helmfile v0.x releases since the next v0.150.0. We introduce a new envvar to opt-in to the new YAML library, so that you can give it a shot before upgrading your Helmfile to v1. The same envvar can be used to opt-out of the new YAML library after you upgrade to Helmfile v1, giving you a more flexible migration story. Signed-off-by: Yusuke Kuoka --- .github/workflows/ci.yaml | 13 +++ pkg/app/app_template_test.go | 30 ++++-- pkg/app/app_test.go | 27 ++++- pkg/envvar/const.go | 2 + pkg/remote/remote.go | 4 + pkg/runtime/runtime.go | 22 +++- pkg/state/release.go | 16 ++- pkg/state/state_exec_tmpl_test.go | 2 +- pkg/tmpl/context_funcs.go | 9 +- pkg/tmpl/context_funcs_test.go | 68 +++++++++--- pkg/yaml/yaml.go | 15 +-- pkg/yaml/yaml_test.go | 24 ++++- test/e2e/template/helmfile/snapshot_test.go | 34 +++++- .../output.yaml | 32 +++--- .../testdata/snapshot/oci_need/output.yaml | 4 - .../snapshot/postrenderer/output.yaml | 4 - .../testdata/snapshot/pr_560/config.yaml | 1 - .../testdata/snapshot/pr_560/output.yaml | 101 ------------------ .../release_template_inheritance/config.yaml | 2 + .../release_template_inheritance/input.yaml | 10 +- .../release_template_inheritance/output.yaml | 12 --- test/integration/test-cases/chart-needs.sh | 30 ++++-- test/integration/test-cases/happypath.sh | 54 ++++++---- .../integration/test-cases/postrender-diff.sh | 10 +- test/integration/test-cases/regression.sh | 30 +++++- test/integration/test-cases/secretssops.sh | 15 ++- test/integration/test-cases/yaml-overwrite.sh | 32 +++--- .../{issue.657.yaml => issue.657.yaml.gotmpl} | 0 28 files changed, 357 insertions(+), 246 deletions(-) rename test/integration/test-cases/yaml-overwrite/input/{issue.657.yaml => issue.657.yaml.gotmpl} (100%) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4864377d..1800133b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -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,16 +72,26 @@ 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 @@ -88,6 +99,7 @@ jobs: 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 }} run: make integration e2e_tests: needs: tests diff --git a/pkg/app/app_template_test.go b/pkg/app/app_template_test.go index 1b8ffc66..37c97198 100644 --- a/pkg/app/app_template_test.go +++ b/pkg/app/app_template_test.go @@ -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 + }) + 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) { 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) { diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index 36a28c42..27a07cbd 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -9,7 +9,7 @@ import ( "path/filepath" "reflect" "regexp" - "runtime" + goruntime "runtime" "strings" "sync" "testing" @@ -25,6 +25,7 @@ import ( ffs "github.com/helmfile/helmfile/pkg/filesystem" "github.com/helmfile/helmfile/pkg/helmexec" "github.com/helmfile/helmfile/pkg/remote" + "github.com/helmfile/helmfile/pkg/runtime" "github.com/helmfile/helmfile/pkg/state" "github.com/helmfile/helmfile/pkg/testhelper" "github.com/helmfile/helmfile/pkg/testutil" @@ -4338,7 +4339,15 @@ myrelease4 testNamespace true true id:myrelease1 mychart1 assert.Equal(t, expected, out) } -func TestSetValuesTemplate(t *testing.T) { +func testSetValuesTemplate(t *testing.T, goccyGoYaml bool) { + t.Helper() + + v := runtime.GoccyGoYaml + runtime.GoccyGoYaml = goccyGoYaml + t.Cleanup(func() { + runtime.GoccyGoYaml = v + }) + files := map[string]string{ "/path/to/helmfile.yaml": ` releases: @@ -4357,7 +4366,7 @@ releases: `, } expectedValues := []interface{}{ - map[interface{}]interface{}{"val1": "zipkin"}, + map[string]interface{}{"val1": "zipkin"}, map[string]interface{}{"val2": "val2"}} expectedSetValues := []state.SetValue{ {Name: "name-zipkin", Value: "val-zipkin"}, @@ -4402,7 +4411,17 @@ releases: } } +func TestSetValuesTemplate(t *testing.T) { + t.Run("with goccy/go-yaml", func(t *testing.T) { + testSetValuesTemplate(t, true) + }) + + t.Run("with gopkg.in/yaml.v2", func(t *testing.T) { + testSetValuesTemplate(t, false) + }) +} + func location() string { - _, fn, line, _ := runtime.Caller(1) + _, fn, line, _ := goruntime.Caller(1) return fmt.Sprintf("%s:%d", filepath.Base(fn), line) } diff --git a/pkg/envvar/const.go b/pkg/envvar/const.go index d8ab2de5..349f5653 100644 --- a/pkg/envvar/const.go +++ b/pkg/envvar/const.go @@ -10,4 +10,6 @@ const ( Helm3 = "HELMFILE_HELM3" UpgradeNoticeDisabled = "HELMFILE_UPGRADE_NOTICE_DISABLED" V1Mode = "HELMFILE_V1MODE" + GoccyGoYaml = "HELMFILE_GOCCY_GOYAML" + CacheHome = "HELMFILE_CACHE_HOME" ) diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index 72ace9bb..8968950a 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -27,6 +27,10 @@ func init() { } func CacheDir() string { + if h := os.Getenv(envvar.CacheHome); h != "" { + return h + } + dir, err := os.UserCacheDir() if err != nil { // fall back to relative path with hidden directory diff --git a/pkg/runtime/runtime.go b/pkg/runtime/runtime.go index 7efda582..e2e407b5 100644 --- a/pkg/runtime/runtime.go +++ b/pkg/runtime/runtime.go @@ -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) { + case "true": + GoccyGoYaml = true + case "false": + GoccyGoYaml = false + default: + GoccyGoYaml = V1Mode + } } diff --git a/pkg/state/release.go b/pkg/state/release.go index e1b86731..74b0c644 100644 --- a/pkg/state/release.go +++ b/pkg/state/release.go @@ -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{} 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{}: + 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 } } diff --git a/pkg/state/state_exec_tmpl_test.go b/pkg/state/state_exec_tmpl_test.go index 91b7945e..5a70467b 100644 --- a/pkg/state/state_exec_tmpl_test.go +++ b/pkg/state/state_exec_tmpl_test.go @@ -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"}}, }, }, } diff --git a/pkg/tmpl/context_funcs.go b/pkg/tmpl/context_funcs.go index 9b671d25..f63adc48 100644 --- a/pkg/tmpl/context_funcs.go +++ b/pkg/tmpl/context_funcs.go @@ -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) + if err != nil { + return nil, fmt.Errorf("%s, offending yaml: %s", err, str) + } + return m, nil } diff --git a/pkg/tmpl/context_funcs_test.go b/pkg/tmpl/context_funcs_test.go index b841900a..3c25494f 100644 --- a/pkg/tmpl/context_funcs_test.go +++ b/pkg/tmpl/context_funcs_test.go @@ -5,12 +5,13 @@ import ( "fmt" "io/fs" "path/filepath" - "runtime" + goruntime "runtime" "testing" "github.com/stretchr/testify/require" "github.com/helmfile/helmfile/pkg/filesystem" + "github.com/helmfile/helmfile/pkg/runtime" ) func TestCreateFuncMap(t *testing.T) { @@ -126,7 +127,7 @@ func TestReadDir(t *testing.T) { "sampleDirectory/file3.yaml", } var expectedArray []string - if runtime.GOOS == "windows" { + if goruntime.GOOS == "windows" { expectedArray = expectedArrayWindows } else { expectedArray = expectedArrayUnix @@ -177,16 +178,29 @@ func TestReadFile_PassAbsPath(t *testing.T) { require.Equal(t, actual, expected) } -func TestToYaml_UnsupportedNestedMapKey(t *testing.T) { - expected := "foo:\n bar: BAR\n" +func TestToYaml_NestedMapInterfaceKey(t *testing.T) { + v := runtime.GoccyGoYaml + t.Cleanup(func() { + runtime.GoccyGoYaml = v + }) + // nolint: unconvert vals := Values(map[string]interface{}{ "foo": map[interface{}]interface{}{ "bar": "BAR", }, }) + + runtime.GoccyGoYaml = true + actual, err := ToYaml(vals) - require.Equal(t, expected, actual) + require.Equal(t, "foo:\n bar: BAR\n", actual) + require.NoError(t, err, "expected nil, but got: %v, when type: map[interface {}]interface {}", err) + + runtime.GoccyGoYaml = false + + actual, err = ToYaml(vals) + require.Equal(t, "foo:\n bar: BAR\n", actual) require.NoError(t, err, "expected nil, but got: %v, when type: map[interface {}]interface {}", err) } @@ -205,21 +219,51 @@ func TestToYaml(t *testing.T) { require.Equal(t, expected, actual) } -func TestFromYaml(t *testing.T) { +func testFromYaml(t *testing.T, goccyGoYaml bool, expected Values) { + t.Helper() + + v := runtime.GoccyGoYaml + runtime.GoccyGoYaml = goccyGoYaml + t.Cleanup(func() { + runtime.GoccyGoYaml = v + }) + raw := `foo: bar: BAR ` - // nolint: unconvert - expected := Values(map[string]interface{}{ - "foo": map[string]interface{}{ - "bar": "BAR", - }, - }) actual, err := FromYaml(raw) require.NoError(t, err) require.Equal(t, expected, actual) } +func TestFromYaml(t *testing.T) { + t.Run("with goccy/go-yaml", func(t *testing.T) { + testFromYaml( + t, + true, + // nolint: unconvert + Values(map[string]interface{}{ + "foo": map[string]interface{}{ + "bar": "BAR", + }, + }), + ) + }) + + t.Run("with gopkg.in/yaml.v2", func(t *testing.T) { + testFromYaml( + t, + false, + // nolint: unconvert + Values(map[string]interface{}{ + "foo": map[string]interface{}{ + "bar": "BAR", + }, + }), + ) + }) +} + func TestFromYamlToJson(t *testing.T) { input := `foo: bar: BAR diff --git a/pkg/yaml/yaml.go b/pkg/yaml/yaml.go index 5c88134f..80b48bf9 100644 --- a/pkg/yaml/yaml.go +++ b/pkg/yaml/yaml.go @@ -6,12 +6,8 @@ import ( "github.com/goccy/go-yaml" v2 "gopkg.in/yaml.v2" -) -var ( - // We'll derive the default from the build once - // is merged - GoccyGoYaml bool = true + "github.com/helmfile/helmfile/pkg/runtime" ) type Encoder interface { @@ -21,7 +17,7 @@ type Encoder interface { // NewEncoder creates and returns a function that is used to encode a Go object to a YAML document func NewEncoder(w io.Writer) Encoder { - if GoccyGoYaml { + if runtime.GoccyGoYaml { return yaml.NewEncoder(w) } @@ -29,7 +25,7 @@ func NewEncoder(w io.Writer) Encoder { } func Unmarshal(data []byte, v interface{}) error { - if GoccyGoYaml { + if runtime.GoccyGoYaml { return yaml.Unmarshal(data, v) } @@ -41,7 +37,7 @@ func Unmarshal(data []byte, v interface{}) error { // When strict is true, this function ensures that every field found in the YAML document // to have the corresponding field in the decoded Go struct. func NewDecoder(data []byte, strict bool) func(interface{}) error { - if GoccyGoYaml { + if runtime.GoccyGoYaml { var opts []yaml.DecodeOption if strict { opts = append(opts, yaml.DisallowUnknownField()) @@ -66,11 +62,10 @@ func NewDecoder(data []byte, strict bool) func(interface{}) error { } func Marshal(v interface{}) ([]byte, error) { - if GoccyGoYaml { + if runtime.GoccyGoYaml { var b bytes.Buffer yamlEncoder := yaml.NewEncoder( &b, - yaml.IndentSequence(true), yaml.Indent(2), ) err := yamlEncoder.Encode(v) diff --git a/pkg/yaml/yaml_test.go b/pkg/yaml/yaml_test.go index 758a8bc7..eadeb23d 100644 --- a/pkg/yaml/yaml_test.go +++ b/pkg/yaml/yaml_test.go @@ -4,9 +4,19 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/helmfile/helmfile/pkg/runtime" ) -func TestYamlMarshal(t *testing.T) { +func testYamlMarshal(t *testing.T, goccyGoYaml bool) { + t.Helper() + + v := runtime.GoccyGoYaml + runtime.GoccyGoYaml = goccyGoYaml + t.Cleanup(func() { + runtime.GoccyGoYaml = v + }) + tests := []struct { Name string `yaml:"name"` Info []struct { @@ -22,7 +32,7 @@ func TestYamlMarshal(t *testing.T) { Age int `yaml:"age"` Address string `yaml:"address"` }{{Age: 20, Address: "New York"}}, - expected: "name: John\ninfo:\n - age: 20\n address: New York\n", + expected: "name: John\ninfo:\n- age: 20\n address: New York\n", }, } @@ -32,3 +42,13 @@ func TestYamlMarshal(t *testing.T) { require.Equal(t, tt.expected, string(actual)) } } + +func TestYamlMarshal(t *testing.T) { + t.Run("with goccy/go-yaml", func(t *testing.T) { + testYamlMarshal(t, true) + }) + + t.Run("with gopkg.in/yaml.v2", func(t *testing.T) { + testYamlMarshal(t, false) + }) +} diff --git a/test/e2e/template/helmfile/snapshot_test.go b/test/e2e/template/helmfile/snapshot_test.go index 03d911cd..0d12b409 100644 --- a/test/e2e/template/helmfile/snapshot_test.go +++ b/test/e2e/template/helmfile/snapshot_test.go @@ -8,7 +8,8 @@ import ( "os/exec" "path/filepath" "regexp" - "runtime" + goruntime "runtime" + "strconv" "strings" "testing" "time" @@ -57,6 +58,18 @@ func (f fakeInit) Force() bool { } func TestHelmfileTemplateWithBuildCommand(t *testing.T) { + t.Run("with goccy/go-yaml", func(t *testing.T) { + testHelmfileTemplateWithBuildCommand(t, true) + }) + + t.Run("with gopkg.in/yaml.v2", func(t *testing.T) { + testHelmfileTemplateWithBuildCommand(t, false) + }) +} + +func testHelmfileTemplateWithBuildCommand(t *testing.T, goccyGoYaml bool) { + t.Setenv(envvar.GoccyGoYaml, strconv.FormatBool(goccyGoYaml)) + localChartPortSets := make(map[int]struct{}) logger := helmexec.NewLogger(os.Stderr, "info") @@ -69,10 +82,10 @@ func TestHelmfileTemplateWithBuildCommand(t *testing.T) { err := helmfileInit.CheckHelmPlugins() require.NoError(t, err) - _, filename, _, _ := runtime.Caller(0) + _, filename, _, _ := goruntime.Caller(0) projectRoot := filepath.Join(filepath.Dir(filename), "..", "..", "..", "..") helmfileBin := filepath.Join(projectRoot, "helmfile") - if runtime.GOOS == "windows" { + if goruntime.GOOS == "windows" { helmfileBin = helmfileBin + ".exe" } testdataDir := "testdata/snapshot" @@ -200,6 +213,15 @@ func TestHelmfileTemplateWithBuildCommand(t *testing.T) { } } + tmpDir := t.TempDir() + // HELM_CACHE_HOME contains downloaded chart archives + helmCacheHome := filepath.Join(tmpDir, "helm_cache") + // HELMFILE_CACHE_HOME contains remote charts and manifests downloaded by Helmfile using the go-getter integration + helmfileCacheHome := filepath.Join(tmpDir, "helmfile_cache") + // HELM_CONFIG_HOME contains the registry auth file (registry.json) and the index of all the repos added via helm-repo-add (repositories.yaml). + helmConfigHome := filepath.Join(tmpDir, "helm_config") + t.Logf("Using HELM_CACHE_HOME=%s, HELMFILE_CACHE_HOME=%s, HELM_CONFIG_HOME=%s", helmCacheHome, helmfileCacheHome, helmConfigHome) + inputFile := filepath.Join(testdataDir, name, "input.yaml") outputFile := filepath.Join(testdataDir, name, "output.yaml") @@ -214,6 +236,9 @@ func TestHelmfileTemplateWithBuildCommand(t *testing.T) { cmd.Env, envvar.TempDir+"=/tmp/helmfile", envvar.DisableRunnerUniqueID+"=1", + "HELM_CACHE_HOME="+helmCacheHome, + "HELM_CONFIG_HOME="+helmConfigHome, + "HELMFILE_CACHE_HOME="+helmfileCacheHome, ) got, err := cmd.CombinedOutput() if err != nil { @@ -231,6 +256,9 @@ func TestHelmfileTemplateWithBuildCommand(t *testing.T) { gotStr = chartGitFullPathRegex.ReplaceAllString(gotStr, `chart=$$GoGetterPath`) // Replace helm version with $HelmVersion gotStr = helmShortVersionRegex.ReplaceAllString(gotStr, `$$HelmVersion`) + // Replace all occurrences of HELMFILE_CACHE_HOME with /home/runner/.cache/helmfile + // for stable test result + gotStr = strings.ReplaceAll(gotStr, helmfileCacheHome, "/home/runner/.cache/helmfile") // OCI based helm charts are pulled and exported under temporary directory. // We are not sure the exact name of the temporary directory generated by helmfile, diff --git a/test/e2e/template/helmfile/testdata/snapshot/issue_2098_release_template_needs/output.yaml b/test/e2e/template/helmfile/testdata/snapshot/issue_2098_release_template_needs/output.yaml index eac7d29e..03b8ec8a 100644 --- a/test/e2e/template/helmfile/testdata/snapshot/issue_2098_release_template_needs/output.yaml +++ b/test/e2e/template/helmfile/testdata/snapshot/issue_2098_release_template_needs/output.yaml @@ -6,23 +6,23 @@ helmBinary: helm environments: default: {} repositories: - - name: aservo - url: https://aservo.github.io/charts +- name: aservo + url: https://aservo.github.io/charts releases: - - chart: aservo/util - version: 0.0.1 - name: default-shared-resources - namespace: default - labels: - service: shared-resources - - chart: aservo/util - version: 0.0.1 - needs: - - default/default-shared-resources - name: default-release-resources - namespace: default - labels: - service: release-resources +- chart: aservo/util + version: 0.0.1 + name: default-shared-resources + namespace: default + labels: + service: shared-resources +- chart: aservo/util + version: 0.0.1 + needs: + - default/default-shared-resources + name: default-release-resources + namespace: default + labels: + service: release-resources templates: defaults: name: default-{{ .Release.Labels.service }} diff --git a/test/e2e/template/helmfile/testdata/snapshot/oci_need/output.yaml b/test/e2e/template/helmfile/testdata/snapshot/oci_need/output.yaml index 863188cd..3ff51e69 100644 --- a/test/e2e/template/helmfile/testdata/snapshot/oci_need/output.yaml +++ b/test/e2e/template/helmfile/testdata/snapshot/oci_need/output.yaml @@ -1,8 +1,4 @@ Building dependency release=foo, chart=$WD/temp1/foo -Hang tight while we grab the latest from your chart repositories... -...Successfully got an update from the "myrepo" chart repository -...Successfully got an update from the "istio" chart repository -Update Complete. ⎈Happy Helming!⎈ Saving 1 charts Downloading raw from repo oci://localhost:5000/myrepo Deleting outdated charts diff --git a/test/e2e/template/helmfile/testdata/snapshot/postrenderer/output.yaml b/test/e2e/template/helmfile/testdata/snapshot/postrenderer/output.yaml index 6542e04a..f71b03aa 100644 --- a/test/e2e/template/helmfile/testdata/snapshot/postrenderer/output.yaml +++ b/test/e2e/template/helmfile/testdata/snapshot/postrenderer/output.yaml @@ -1,9 +1,5 @@ Building dependency release=foo, chart=../../charts/raw-0.1.0 Building dependency release=baz, chart=$WD/temp1/baz -Hang tight while we grab the latest from your chart repositories... -...Successfully got an update from the "myrepo" chart repository -...Successfully got an update from the "istio" chart repository -Update Complete. ⎈Happy Helming!⎈ Saving 1 charts Downloading raw from repo oci://localhost:5001/myrepo Deleting outdated charts diff --git a/test/e2e/template/helmfile/testdata/snapshot/pr_560/config.yaml b/test/e2e/template/helmfile/testdata/snapshot/pr_560/config.yaml index caff0181..96355c65 100644 --- a/test/e2e/template/helmfile/testdata/snapshot/pr_560/config.yaml +++ b/test/e2e/template/helmfile/testdata/snapshot/pr_560/config.yaml @@ -1,4 +1,3 @@ helmfileArgs: - template -- --debug - --concurrency=1 diff --git a/test/e2e/template/helmfile/testdata/snapshot/pr_560/output.yaml b/test/e2e/template/helmfile/testdata/snapshot/pr_560/output.yaml index ed9dea41..4c93a8b9 100644 --- a/test/e2e/template/helmfile/testdata/snapshot/pr_560/output.yaml +++ b/test/e2e/template/helmfile/testdata/snapshot/pr_560/output.yaml @@ -1,103 +1,5 @@ -processing file "input.yaml" in directory "testdata/snapshot/pr_560" -changing working directory to "/home/runner/work/helmfile/helmfile/test/e2e/template/helmfile/testdata/snapshot/pr_560" -first-pass rendering starting for "input.yaml.part.0": inherited=&{default map[] map[]}, overrode= -first-pass uses: &{default map[] map[]} -first-pass rendering output of "input.yaml.part.0": - 0: releases: - 1: - name: foo - 2: chart: ../../charts/raw-0.1.0 - 3: values: - 4: - templates: - 5: - | - 6: apiVersion: v1 - 7: kind: ConfigMap - 8: metadata: - 9: name: {{ .Release.Name }}-1 -10: namespace: {{ .Release.Namespace }} -11: data: -12: foo: FOO -13: - git::https://github.com/helmfile/helmfile.git@test/e2e/template/helmfile/testdata/snapshot/pr_560/values.yaml?ref=main -14: secrets: -15: - git::https://github.com/helmfile/helmfile.git@test/e2e/template/helmfile/testdata/snapshot/pr_560/secrets.yaml?ref=main -16: missingFileHandler: Debug -17: - -first-pass produced: &{default map[] map[]} -first-pass rendering result of "input.yaml.part.0": {default map[] map[]} -vals: -map[] -defaultVals:[] -second-pass rendering result of "input.yaml.part.0": - 0: releases: - 1: - name: foo - 2: chart: ../../charts/raw-0.1.0 - 3: values: - 4: - templates: - 5: - | - 6: apiVersion: v1 - 7: kind: ConfigMap - 8: metadata: - 9: name: {{ .Release.Name }}-1 -10: namespace: {{ .Release.Namespace }} -11: data: -12: foo: FOO -13: - git::https://github.com/helmfile/helmfile.git@test/e2e/template/helmfile/testdata/snapshot/pr_560/values.yaml?ref=main -14: secrets: -15: - git::https://github.com/helmfile/helmfile.git@test/e2e/template/helmfile/testdata/snapshot/pr_560/secrets.yaml?ref=main -16: missingFileHandler: Debug -17: - -merged environment: &{default map[] map[]} -helm> $HelmVersion -helm> Building dependency release=foo, chart=../../charts/raw-0.1.0 -exec: helm dependency build ../../charts/raw-0.1.0 -1 release(s) found in input.yaml - -processing 1 groups of releases in this order: -GROUP RELEASES -1 foo - -processing releases in group 1/1: foo -remote> getter: git -remote> scheme: https -remote> user: -remote> host: github.com -remote> dir: /helmfile/helmfile.git -remote> file: test/e2e/template/helmfile/testdata/snapshot/pr_560/values.yaml -remote> home: /home/runner/.cache/helmfile -remote> getter dest: values/https_github_com_helmfile_helmfile_git.ref=main -remote> cached dir: /home/runner/.cache/helmfile/values/https_github_com_helmfile_helmfile_git.ref=main -remote> downloading git::https://github.com/helmfile/helmfile.git?ref=main to values/https_github_com_helmfile_helmfile_git.ref=main -client: {Ctx:context.Background Src:git::https://github.com/helmfile/helmfile.git?ref=main Dst:/home/runner/.cache/helmfile/values/https_github_com_helmfile_helmfile_git.ref=main Pwd:/home/runner/.cache/helmfile Mode:3 Umask:---------- Detectors:[] Decompressors:map[] Getters:map[] Dir:false ProgressListener: Insecure:false DisableSymlinks:false Options:[]} -skipping missing values file matching "git::https://github.com/helmfile/helmfile.git@test/e2e/template/helmfile/testdata/snapshot/pr_560/values.yaml?ref=main" -remote> getter: git -remote> scheme: https -remote> user: -remote> host: github.com -remote> dir: /helmfile/helmfile.git -remote> file: test/e2e/template/helmfile/testdata/snapshot/pr_560/secrets.yaml -remote> home: /home/runner/.cache/helmfile -remote> getter dest: values/https_github_com_helmfile_helmfile_git.ref=main -remote> cached dir: /home/runner/.cache/helmfile/values/https_github_com_helmfile_helmfile_git.ref=main -skipping missing secrets file matching "git::https://github.com/helmfile/helmfile.git@test/e2e/template/helmfile/testdata/snapshot/pr_560/secrets.yaml?ref=main" Templating release=foo, chart=../../charts/raw-0.1.0 -exec: helm template foo ../../charts/raw-0.1.0 --values /tmp/helmfile/foo-values-d459bc67c --debug -helm> install.go:192: [debug] Original chart version: "" -helm> -helm> install.go:209: [debug] CHART PATH: /home/runner/work/helmfile/helmfile/test/e2e/template/helmfile/testdata/charts/raw-0.1.0 -helm> -helm> -helm> --- -helm> # Source: raw/templates/resources.yaml -helm> apiVersion: v1 -helm> kind: ConfigMap -helm> metadata: -helm> name: foo-1 -helm> namespace: default -helm> data: -helm> foo: FOO -helm> --- # Source: raw/templates/resources.yaml apiVersion: v1 @@ -108,6 +10,3 @@ metadata: data: foo: FOO -Removed /tmp/helmfile/foo-values-d459bc67c -Removed /tmp/helmfile -changing working directory back to "/home/runner/work/helmfile/helmfile/test/e2e/template/helmfile" diff --git a/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/config.yaml b/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/config.yaml index a7207392..a724ba39 100644 --- a/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/config.yaml +++ b/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/config.yaml @@ -3,3 +3,5 @@ localChartRepoServer: port: 18084 helmfileArgs: - template +# Prevent two releases foo and bar from racing and randomizing the log +- --concurrency=1 diff --git a/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/input.yaml b/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/input.yaml index f94955ee..6e6cc0ed 100644 --- a/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/input.yaml +++ b/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/input.yaml @@ -12,7 +12,7 @@ templates: values: - template1: template1 valuesTemplate: - - template1Label: "{{` '{{ .Release.Labels.template1 }}' `}}" + - template1Label: "{{`{{ .Release.Labels.template1 }}`}}" labels: template1: template1 inherit: @@ -23,8 +23,8 @@ templates: values: - template2: template2 valuesTemplate: - - inheritedBaseLabel: "{{` '{{ .Release.Labels.base }}' `}}" - template2Label: "{{` '{{ .Release.Labels.template2 }}' `}}" + - inheritedBaseLabel: "{{`{{ .Release.Labels.base }}`}}" + template2Label: "{{`{{ .Release.Labels.template2 }}`}}" labels: template2: template2 inherit: @@ -46,7 +46,7 @@ releases: name: {{`{{ .Release.Name }}`}}-1 namespace: {{`{{ .Release.Namespace }}`}} data: - {{` {{ .Values | toYaml | nindent 2 }} `}} + {{` {{ (unset .Values "templates") | toYaml | nindent 2 }} `}} - name: foo2 chart: ../../charts/raw-0.1.0 inherit: @@ -60,4 +60,4 @@ releases: name: {{`{{ .Release.Name }}`}}-1 namespace: {{`{{ .Release.Namespace }}`}} data: - {{` {{ .Values | toYaml | nindent 2 }} `}} \ No newline at end of file + {{` {{ (unset .Values "templates") | toYaml | nindent 2 }} `}} \ No newline at end of file diff --git a/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/output.yaml b/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/output.yaml index 5cb1b25e..8f4523d9 100644 --- a/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/output.yaml +++ b/test/e2e/template/helmfile/testdata/snapshot/release_template_inheritance/output.yaml @@ -16,9 +16,6 @@ data: base: base template1: template1 template1Label: template1 - templates: - - "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: {{ .Release.Name }}-1\n namespace: - {{ .Release.Namespace }}\ndata:\n {{ .Values | toYaml | nindent 2 }} \n" Templating release=foo2, chart=../../charts/raw-0.1.0 --- @@ -33,13 +30,4 @@ data: inheritedBaseLabel: base template2: template2 template2Label: template2 - templates: - - |- - apiVersion: v1 - kind: ConfigMap - metadata: - name: {{ .Release.Name }}-1 - namespace: {{ .Release.Namespace }} - data: - {{ .Values | toYaml | nindent 2 }} diff --git a/test/integration/test-cases/chart-needs.sh b/test/integration/test-cases/chart-needs.sh index f3a0e47f..9cc3cd8d 100644 --- a/test/integration/test-cases/chart-needs.sh +++ b/test/integration/test-cases/chart-needs.sh @@ -2,6 +2,14 @@ if [[ helm_major_version -eq 3 ]]; then chart_need_case_input_dir="${cases_dir}/chart-needs/input" chart_need_case_output_dir="${cases_dir}/chart-needs/output" + config_file="helmfile.yaml" + if [[ ${HELMFILE_V1MODE} = true ]]; then + pushd "${chart_need_case_input_dir}" + mv "${config_file}" "${config_file}.gotmpl" + config_file="${config_file}.gotmpl" + popd + fi + chart_needs_tmp=$(mktemp -d) chart_needs_template_reverse=${chart_needs_tmp}/chart.needs.template.log chart_needs_lint_reverse=${chart_needs_tmp}/chart.needs.lint.log @@ -20,46 +28,46 @@ if [[ helm_major_version -eq 3 ]]; then for i in $(seq 10); do info "Comparing template/chart-needs #$i" - ${helmfile} -f ${chart_need_case_input_dir}/helmfile.yaml template --include-needs > ${chart_needs_template_reverse} || fail "\"helmfile template\" shouldn't fail" + ${helmfile} -f ${chart_need_case_input_dir}/${config_file} template --include-needs > ${chart_needs_template_reverse} || fail "\"helmfile template\" shouldn't fail" ./dyff between -bs ${chart_need_case_output_dir}/template ${chart_needs_template_reverse} || fail "\"helmfile template\" should be consistent" echo code=$? done for i in $(seq 10); do info "Comparing lint/chart-needs #$i" - ${helmfile} -f ${chart_need_case_input_dir}/helmfile.yaml lint --include-needs | grep -v Linting > ${chart_needs_lint_reverse} || fail "\"helmfile lint\" shouldn't fail" + ${helmfile} -f ${chart_need_case_input_dir}/${config_file} lint --include-needs | grep -v Linting > ${chart_needs_lint_reverse} || fail "\"helmfile lint\" shouldn't fail" diff -u ${lint_out_file} ${chart_needs_lint_reverse} || fail "\"helmfile lint\" should be consistent" echo code=$? done for i in $(seq 10); do info "Comparing diff/chart-needs #$i" - ${helmfile} -f ${chart_need_case_input_dir}/helmfile.yaml diff --include-needs | grep -Ev "Comparing release=azuredisk-csi-storageclass, chart=/tmp/.*/azuredisk-csi-storageclass" > ${chart_needs_diff_reverse} || fail "\"helmfile diff\" shouldn't fail" + ${helmfile} -f ${chart_need_case_input_dir}/${config_file} diff --include-needs | grep -Ev "Comparing release=azuredisk-csi-storageclass, chart=/tmp/.*/azuredisk-csi-storageclass" > ${chart_needs_diff_reverse} || fail "\"helmfile diff\" shouldn't fail" diff -u ${diff_out_file} ${chart_needs_diff_reverse} || fail "\"helmfile diff\" should be consistent" echo code=$? done - info "Applying ${chart_need_case_input_dir}/helmfile.yaml" - ${helmfile} -f ${chart_need_case_input_dir}/helmfile.yaml apply --include-needs + info "Applying ${chart_need_case_input_dir}/${config_file}" + ${helmfile} -f ${chart_need_case_input_dir}/${config_file} apply --include-needs code=$? [ ${code} -eq 0 ] || fail "unexpected exit code returned by helmfile apply: want 0, got ${code}" ${kubectl} get storageclass managed-csi -o yaml | grep -q "provisioner: disk.csi.azure.com" || fail "storageclass managed-csi should be created when applying helmfile.yaml" - info "Destroying ${chart_need_case_input_dir}/helmfile.yaml" - ${helmfile} -f ${chart_need_case_input_dir}/helmfile.yaml destroy + info "Destroying ${chart_need_case_input_dir}/${config_file}" + ${helmfile} -f ${chart_need_case_input_dir}/${config_file} destroy code=$? [ ${code} -eq 0 ] || fail "unexpected exit code returned by helmfile destroy: want 0, got ${code}" - info "Syncing ${chart_need_case_input_dir}/helmfile.yaml" - ${helmfile} -f ${chart_need_case_input_dir}/helmfile.yaml sync --include-needs + info "Syncing ${chart_need_case_input_dir}/${config_file}" + ${helmfile} -f ${chart_need_case_input_dir}/${config_file} sync --include-needs code=$? [ ${code} -eq 0 ] || fail "unexpected exit code returned by helmfile apply: want 0, got ${code}" ${kubectl} get storageclass managed-csi -o yaml | grep -q "provisioner: disk.csi.azure.com" || fail "storageclass managed-csi should be created when syncing helmfile.yaml" - info "Destroying ${chart_need_case_input_dir}/helmfile.yaml" - ${helmfile} -f ${chart_need_case_input_dir}/helmfile.yaml destroy + info "Destroying ${chart_need_case_input_dir}/${config_file}" + ${helmfile} -f ${chart_need_case_input_dir}/${config_file} destroy code=$? [ ${code} -eq 0 ] || fail "unexpected exit code returned by helmfile destroy: want 0, got ${code}" diff --git a/test/integration/test-cases/happypath.sh b/test/integration/test-cases/happypath.sh index d118ba64..3befe66a 100644 --- a/test/integration/test-cases/happypath.sh +++ b/test/integration/test-cases/happypath.sh @@ -2,22 +2,30 @@ test_start "happypath - simple rollout of httpbin chart" happypath_case_input_dir="${cases_dir}/happypath/input" happypath_case_output_dir="${cases_dir}/happypath/output" +config_file="happypath.yaml" -info "Diffing ${happypath_case_input_dir}/happypath.yaml" -bash -c "${helmfile} -f ${happypath_case_input_dir}/happypath.yaml diff --detailed-exitcode; code="'$?'"; [ "'${code}'" -eq 2 ]" || fail "unexpected exit code returned by helmfile diff" +if [[ ${HELMFILE_V1MODE} = true ]]; then + pushd "${happypath_case_input_dir}" + mv "${config_file}" "${config_file}.gotmpl" + config_file="${config_file}.gotmpl" + popd +fi -info "Diffing ${happypath_case_input_dir}/happypath.yaml without color" -bash -c "${helmfile} -f ${happypath_case_input_dir}/happypath.yaml --no-color diff --detailed-exitcode; code="'$?'"; [ "'${code}'" -eq 2 ]" || fail "unexpected exit code returned by helmfile diff" +info "Diffing ${happypath_case_input_dir}/${config_file}" +bash -c "${helmfile} -f ${happypath_case_input_dir}/${config_file} diff --detailed-exitcode; code="'$?'"; [ "'${code}'" -eq 2 ]" || fail "unexpected exit code returned by helmfile diff" -info "Diffing ${happypath_case_input_dir}/happypath.yaml with limited context" -bash -c "${helmfile} -f ${happypath_case_input_dir}/happypath.yaml diff --context 3 --detailed-exitcode; code="'$?'"; [ "'${code}'" -eq 2 ]" || fail "unexpected exit code returned by helmfile diff" +info "Diffing ${happypath_case_input_dir}/${config_file} without color" +bash -c "${helmfile} -f ${happypath_case_input_dir}/${config_file} --no-color diff --detailed-exitcode; code="'$?'"; [ "'${code}'" -eq 2 ]" || fail "unexpected exit code returned by helmfile diff" -info "Diffing ${happypath_case_input_dir}/happypath.yaml with altered output" -bash -c "${helmfile} -f ${happypath_case_input_dir}/happypath.yaml diff --output simple --detailed-exitcode; code="'$?'"; [ "'${code}'" -eq 2 ]" || fail "unexpected exit code returned by helmfile diff" +info "Diffing ${happypath_case_input_dir}/${config_file} with limited context" +bash -c "${helmfile} -f ${happypath_case_input_dir}/${config_file} diff --context 3 --detailed-exitcode; code="'$?'"; [ "'${code}'" -eq 2 ]" || fail "unexpected exit code returned by helmfile diff" -info "Templating ${happypath_case_input_dir}/happypath.yaml" +info "Diffing ${happypath_case_input_dir}/${config_file} with altered output" +bash -c "${helmfile} -f ${happypath_case_input_dir}/${config_file} diff --output simple --detailed-exitcode; code="'$?'"; [ "'${code}'" -eq 2 ]" || fail "unexpected exit code returned by helmfile diff" + +info "Templating ${happypath_case_input_dir}/${config_file}" rm -rf ${dir}/tmp -${helmfile} -f ${happypath_case_input_dir}/happypath.yaml --debug template --output-dir tmp +${helmfile} -f ${happypath_case_input_dir}/${config_file} --debug template --output-dir tmp code=$? [ ${code} -eq 0 ] || fail "unexpected exit code returned by helmfile template: ${code}" for output in $(ls -d ${dir}/tmp/*); do @@ -30,39 +38,39 @@ for output in $(ls -d ${dir}/tmp/*); do done done -info "Applying ${happypath_case_input_dir}/happypath.yaml" -bash -c "${helmfile} -f ${happypath_case_input_dir}/happypath.yaml apply --detailed-exitcode; code="'$?'"; echo Code: "'$code'"; [ "'${code}'" -eq 2 ]" || fail "unexpected exit code returned by helmfile apply" +info "Applying ${happypath_case_input_dir}/${config_file}" +bash -c "${helmfile} -f ${happypath_case_input_dir}/${config_file} apply --detailed-exitcode; code="'$?'"; echo Code: "'$code'"; [ "'${code}'" -eq 2 ]" || fail "unexpected exit code returned by helmfile apply" -info "Syncing ${happypath_case_input_dir}/happypath.yaml" -${helmfile} -f ${happypath_case_input_dir}/happypath.yaml sync +info "Syncing ${happypath_case_input_dir}/${config_file}" +${helmfile} -f ${happypath_case_input_dir}/${config_file} sync wait_deploy_ready httpbin-httpbin retry 5 "curl --fail $(minikube service --url --namespace=${test_ns} httpbin-httpbin)/status/200" [ ${retry_result} -eq 0 ] || fail "httpbin failed to return 200 OK" -info "Applying ${happypath_case_input_dir}/happypath.yaml" -${helmfile} -f ${happypath_case_input_dir}/happypath.yaml apply --detailed-exitcode +info "Applying ${happypath_case_input_dir}/${config_file}" +${helmfile} -f ${happypath_case_input_dir}/${config_file} apply --detailed-exitcode code=$? [ ${code} -eq 0 ] || fail "unexpected exit code returned by helmfile apply: want 0, got ${code}" info "Locking dependencies" -${helmfile} -f ${happypath_case_input_dir}/happypath.yaml deps +${helmfile} -f ${happypath_case_input_dir}/${config_file} deps code=$? [ ${code} -eq 0 ] || fail "unexpected exit code returned by helmfile deps: ${code}" -info "Applying ${happypath_case_input_dir}/happypath.yaml with locked dependencies" -${helmfile} -f ${happypath_case_input_dir}/happypath.yaml apply +info "Applying ${happypath_case_input_dir}/${config_file} with locked dependencies" +${helmfile} -f ${happypath_case_input_dir}/${config_file} apply code=$? [ ${code} -eq 0 ] || fail "unexpected exit code returned by helmfile apply: ${code}" ${helm} list --namespace=${test_ns} || fail "unable to list releases" info "Deleting release" -${helmfile} -f ${happypath_case_input_dir}/happypath.yaml delete +${helmfile} -f ${happypath_case_input_dir}/${config_file} destroy ${helm} status --namespace=${test_ns} httpbin &> /dev/null && fail "release should not exist anymore after a delete" -info "Ensuring \"helmfile delete\" doesn't fail when no releases installed" -${helmfile} -f ${happypath_case_input_dir}/happypath.yaml delete || fail "\"helmfile delete\" shouldn't fail when there are no installed releases" +info "Ensuring \"helmfile destroy\" doesn't fail when no releases installed" +${helmfile} -f ${happypath_case_input_dir}/${config_file} destroy || fail "\"helmfile delete\" shouldn't fail when there are no installed releases" info "Ensuring \"helmfile template\" output does contain only YAML docs" -(${helmfile} -f ${happypath_case_input_dir}/happypath.yaml template | kubectl apply -f -) || fail "\"helmfile template | kubectl apply -f -\" shouldn't fail" +(${helmfile} -f ${happypath_case_input_dir}/${config_file} template | kubectl apply -f -) || fail "\"helmfile template | kubectl apply -f -\" shouldn't fail" test_pass "happypath" \ No newline at end of file diff --git a/test/integration/test-cases/postrender-diff.sh b/test/integration/test-cases/postrender-diff.sh index 2b416d89..d1fb8a0b 100644 --- a/test/integration/test-cases/postrender-diff.sh +++ b/test/integration/test-cases/postrender-diff.sh @@ -2,6 +2,14 @@ if [[ helm_major_version -eq 3 ]]; then postrender_diff_case_input_dir="${cases_dir}/postrender-diff/input" postrender_diff_case_output_dir="${cases_dir}/postrender-diff/output" + config_file="helmfile.yaml" + if [[ ${HELMFILE_V1MODE} = true ]]; then + pushd "${postrender_diff_case_input_dir}" + mv "${config_file}" "${config_file}.gotmpl" + config_file="${config_file}.gotmpl" + popd + fi + postrender_diff_out_file=${postrender_diff_case_output_dir}/result if [[ $EXTRA_HELMFILE_FLAGS == *--enable-live-output* ]]; then postrender_diff_out_file=${postrender_diff_case_output_dir}/result-live @@ -14,7 +22,7 @@ if [[ helm_major_version -eq 3 ]]; then info "Comparing postrender diff output ${postrender_diff_reverse} with ${postrender_diff_case_output_dir}/result.yaml" for i in $(seq 10); do info "Comparing build/postrender-diff #$i" - ${helmfile} -f ${postrender_diff_case_input_dir}/helmfile.yaml diff --concurrency 1 &> ${postrender_diff_reverse} || fail "\"helmfile diff\" shouldn't fail" + ${helmfile} -f ${postrender_diff_case_input_dir}/${config_file} diff --concurrency 1 &> ${postrender_diff_reverse} || fail "\"helmfile diff\" shouldn't fail" diff -u ${postrender_diff_out_file} ${postrender_diff_reverse} || fail "\"helmfile diff\" should be consistent" echo code=$? done diff --git a/test/integration/test-cases/regression.sh b/test/integration/test-cases/regression.sh index 675fff35..2831de1f 100644 --- a/test/integration/test-cases/regression.sh +++ b/test/integration/test-cases/regression.sh @@ -3,15 +3,37 @@ test_start "regression tests" if [[ helm_major_version -eq 3 ]]; then regression_case_input_dir="${cases_dir}/regression/input" + info "https://github.com/roboll/helmfile/issues/1857" - (${helmfile} -f ${regression_case_input_dir}/issue.1857.yaml --state-values-set grafanaEnabled=true template | grep grafana 1>/dev/null) || fail "\"helmfile template\" shouldn't include grafana" - ! (${helmfile} -f ${regression_case_input_dir}/issue.1857.yaml --state-values-set grafanaEnabled=false template | grep grafana) || fail "\"helmfile template\" shouldn't include grafana" + config_file="issue.1857.yaml" + if [[ ${HELMFILE_V1MODE} = true ]]; then + pushd "${regression_case_input_dir}" + mv "${config_file}" "${config_file}.gotmpl" + config_file="${config_file}.gotmpl" + popd + fi + (${helmfile} -f ${regression_case_input_dir}/${config_file} --state-values-set grafanaEnabled=true template | grep grafana 1>/dev/null) || fail "\"helmfile template\" shouldn't include grafana" + ! (${helmfile} -f ${regression_case_input_dir}/${config_file} --state-values-set grafanaEnabled=false template | grep grafana) || fail "\"helmfile template\" shouldn't include grafana" info "https://github.com/roboll/helmfile/issues/1867" - (${helmfile} -f ${regression_case_input_dir}/issue.1867.yaml template 1>/dev/null) || fail "\"helmfile template\" shouldn't fail" + config_file="issue.1867.yaml" + if [[ ${HELMFILE_V1MODE} = true ]]; then + pushd "${regression_case_input_dir}" + mv "${config_file}" "${config_file}.gotmpl" + config_file="${config_file}.gotmpl" + popd + fi + (${helmfile} -f ${regression_case_input_dir}/${config_file} template 1>/dev/null) || fail "\"helmfile template\" shouldn't fail" info "https://github.com/roboll/helmfile/issues/2118" - (${helmfile} -f ${regression_case_input_dir}/issue.2118.yaml template 1>/dev/null) || fail "\"helmfile template\" shouldn't fail" + config_file="issue.2118.yaml" + if [[ ${HELMFILE_V1MODE} = true ]]; then + pushd "${regression_case_input_dir}" + mv "${config_file}" "${config_file}.gotmpl" + config_file="${config_file}.gotmpl" + popd + fi + (${helmfile} -f ${regression_case_input_dir}/${config_file} template 1>/dev/null) || fail "\"helmfile template\" shouldn't fail" else info "There are no regression tests for helm 2 because all the target charts have dropped helm 2 support." fi diff --git a/test/integration/test-cases/secretssops.sh b/test/integration/test-cases/secretssops.sh index a9f77b91..47171a17 100644 --- a/test/integration/test-cases/secretssops.sh +++ b/test/integration/test-cases/secretssops.sh @@ -5,6 +5,13 @@ if [[ helm_major_version -eq 3 ]]; then secretssops_case_input_dir="${cases_dir}/secretssops/input" secretssops_case_output_dir="${cases_dir}/secretssops/output" + config_file="secretssops.yaml" + if [[ ${HELMFILE_V1MODE} = true ]]; then + pushd "${secretssops_case_input_dir}" + mv "${config_file}" "${config_file}.gotmpl" + config_file="${config_file}.gotmpl" + popd + fi mkdir -p ${secretssops_case_input_dir}/tmp @@ -19,7 +26,7 @@ if [[ helm_major_version -eq 3 ]]; then info "Ensure helmfile fails when no helm-secrets is installed" unset code - ${helmfile} -f ${secretssops_case_input_dir}/secretssops.yaml -e direct build || code="$?"; code="${code:-0}" + ${helmfile} -f ${secretssops_case_input_dir}/${config_file} -e direct build || code="$?"; code="${code:-0}" echo Code: "${code}" [ "${code}" -ne 0 ] || fail "\"helmfile build\" should fail without secrets plugin" @@ -31,7 +38,7 @@ if [[ helm_major_version -eq 3 ]]; then ${helm} plugin install https://github.com/jkroepke/helm-secrets --version v${HELM_SECRETS_VERSION} info "Ensure helmfile succeed when helm-secrets is installed" - ${helmfile} -f ${secretssops_case_input_dir}/secretssops.yaml -e direct build || fail "\"helmfile build\" shouldn't fail" + ${helmfile} -f ${secretssops_case_input_dir}/${config_file} -e direct build || fail "\"helmfile build\" shouldn't fail" test_pass "secretssops.2" @@ -46,7 +53,7 @@ if [[ helm_major_version -eq 3 ]]; then info "Comparing build/direct output ${direct} with ${secretssops_case_output_dir}" for i in $(seq 10); do info "Comparing build/direct #$i" - ${helmfile} -f ${secretssops_case_input_dir}/secretssops.yaml -e direct template --skip-deps > ${direct} || fail "\"helmfile template\" shouldn't fail" + ${helmfile} -f ${secretssops_case_input_dir}/${config_file} -e direct template --skip-deps > ${direct} || fail "\"helmfile template\" shouldn't fail" ./dyff between -bs ${secretssops_case_output_dir}/direct.build.yaml ${direct} || fail "\"helmfile template\" should be consistent" echo code=$? done @@ -54,7 +61,7 @@ if [[ helm_major_version -eq 3 ]]; then info "Comparing build/reverse output ${direct} with ${secretssops_case_output_dir}" for i in $(seq 10); do info "Comparing build/reverse #$i" - ${helmfile} -f ${secretssops_case_input_dir}/secretssops.yaml -e reverse template --skip-deps > ${reverse} || fail "\"helmfile template\" shouldn't fail" + ${helmfile} -f ${secretssops_case_input_dir}/${config_file} -e reverse template --skip-deps > ${reverse} || fail "\"helmfile template\" shouldn't fail" ./dyff between -bs ${secretssops_case_output_dir}/reverse.build.yaml ${reverse} || fail "\"helmfile template\" should be consistent" echo code=$? done diff --git a/test/integration/test-cases/yaml-overwrite.sh b/test/integration/test-cases/yaml-overwrite.sh index 83d7bbde..aa0a5c14 100644 --- a/test/integration/test-cases/yaml-overwrite.sh +++ b/test/integration/test-cases/yaml-overwrite.sh @@ -1,17 +1,21 @@ if [[ helm_major_version -eq 3 ]]; then - yaml_overwrite_case_input_dir="${cases_dir}/yaml-overwrite/input" - yaml_overwrite_case_output_dir="${cases_dir}/yaml-overwrite/output" + if [[ ${HELMFILE_V1MODE} = true ]]; then + yaml_overwrite_case_input_dir="${cases_dir}/yaml-overwrite/input" + yaml_overwrite_case_output_dir="${cases_dir}/yaml-overwrite/output" - yaml_overwrite_tmp=$(mktemp -d) - yaml_overwrite_reverse=${yaml_overwrite_tmp}/yaml.override.build.yaml + yaml_overwrite_tmp=$(mktemp -d) + yaml_overwrite_reverse=${yaml_overwrite_tmp}/yaml.override.build.yaml - test_start "yaml overwrite feature" - info "Comparing yaml overwrite feature output ${yaml_overwrite_reverse} with ${yaml_overwrite_case_output_dir}/overwritten.yaml" - for i in $(seq 10); do - info "Comparing build/yaml-overwrite #$i" - ${helmfile} -f ${yaml_overwrite_case_input_dir}/issue.657.yaml template --skip-deps > ${yaml_overwrite_reverse} || fail "\"helmfile template\" shouldn't fail" - ./dyff between -bs ${yaml_overwrite_case_output_dir}/overwritten.yaml ${yaml_overwrite_reverse} || fail "\"helmfile template\" should be consistent" - echo code=$? - done - test_pass "yaml overwrite feature" -fi \ No newline at end of file + test_start "yaml overwrite feature" + info "Comparing yaml overwrite feature output ${yaml_overwrite_reverse} with ${yaml_overwrite_case_output_dir}/overwritten.yaml" + for i in $(seq 10); do + info "Comparing build/yaml-overwrite #$i" + ${helmfile} -f ${yaml_overwrite_case_input_dir}/issue.657.yaml.gotmpl template --skip-deps > ${yaml_overwrite_reverse} || fail "\"helmfile template\" shouldn't fail" + ./dyff between -bs ${yaml_overwrite_case_output_dir}/overwritten.yaml ${yaml_overwrite_reverse} || fail "\"helmfile template\" should be consistent" + echo code=$? + done + test_pass "yaml overwrite feature" + else + test_pass "[skipped] yaml overwrite feature" + fi +fi diff --git a/test/integration/test-cases/yaml-overwrite/input/issue.657.yaml b/test/integration/test-cases/yaml-overwrite/input/issue.657.yaml.gotmpl similarity index 100% rename from test/integration/test-cases/yaml-overwrite/input/issue.657.yaml rename to test/integration/test-cases/yaml-overwrite/input/issue.657.yaml.gotmpl