From 4e4f1bee59873a94ce92f61ba8214c1f69b6c7a0 Mon Sep 17 00:00:00 2001 From: KUOKA Yusuke Date: Sat, 7 Sep 2019 09:40:44 +0900 Subject: [PATCH] feat: Experimental Helm v3 mode (#841) Set `HELMFILE_HELM3=1` and run `helmfile` like `HELMFILE_HELM3=1 helmfile ...`. When `HELMFILE_HELM3` is set, `test`, `template`, `delete`, `destroy` behave differently so that it works with Helm 3. Note that `helmfile diff` doesn't work as `helm-diff` called under the hood doesn't support Helm v3 yet. Ref #668 --- pkg/app/app_test.go | 19 +++++++++++++------ pkg/helmexec/exec.go | 30 +++++++++++++++++++++++++++--- pkg/state/state.go | 16 +++++++++++----- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index 06dea601..057e3ab1 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -1843,11 +1843,12 @@ type mockHelmExec struct { } type mockTemplates struct { - flags []string + name, chart string + flags []string } func (helm *mockHelmExec) TemplateRelease(name, chart string, flags ...string) error { - helm.templated = append(helm.templated, mockTemplates{flags: flags}) + helm.templated = append(helm.templated, mockTemplates{name: name, chart: chart, flags: flags}) return nil } @@ -1906,14 +1907,14 @@ releases: - name: myrelease1 chart: mychart1 - name: myrelease2 - chart: mychart1 + chart: mychart2 `, } var helm = &mockHelmExec{} var wantReleases = []mockTemplates{ - {[]string{"--name", "myrelease1", "--namespace", "testNamespace", "--output-dir", "output/subdir/helmfile-[a-z0-9]{8}-myrelease1"}}, - {[]string{"--name", "myrelease2", "--namespace", "testNamespace", "--output-dir", "output/subdir/helmfile-[a-z0-9]{8}-myrelease2"}}, + {name: "myrelease1", chart: "mychart1", flags: []string{"--namespace", "testNamespace", "--output-dir", "output/subdir/helmfile-[a-z0-9]{8}-myrelease1"}}, + {name: "myrelease2", chart: "mychart2", flags: []string{"--namespace", "testNamespace", "--output-dir", "output/subdir/helmfile-[a-z0-9]{8}-myrelease2"}}, } var buffer bytes.Buffer @@ -1931,8 +1932,14 @@ releases: app.Template(configImpl{}) for i := range wantReleases { + if wantReleases[i].name != helm.templated[i].name { + t.Errorf("name = [%v], want %v", helm.templated[i].name, wantReleases[i].name) + } + if !strings.Contains(helm.templated[i].chart, wantReleases[i].chart) { + t.Errorf("chart = [%v], want %v", helm.templated[i].chart, wantReleases[i].chart) + } for j := range wantReleases[i].flags { - if j == 5 { + if j == 3 { matched, _ := regexp.Match(wantReleases[i].flags[j], []byte(helm.templated[i].flags[j])) if !matched { t.Errorf("HelmState.TemplateReleases() = [%v], want %v", helm.templated[i].flags[j], wantReleases[i].flags[j]) diff --git a/pkg/helmexec/exec.go b/pkg/helmexec/exec.go index e732b477..62d4a881 100644 --- a/pkg/helmexec/exec.go +++ b/pkg/helmexec/exec.go @@ -126,7 +126,14 @@ func (helm *execer) List(context HelmContext, filter string, flags ...string) (s helm.logger.Infof("Listing releases matching %v", filter) preArgs := context.GetTillerlessArgs(helm.helmBinary) env := context.getTillerlessEnv() - out, err := helm.exec(append(append(preArgs, "list", filter), flags...), env) + var args []string + if helm.isHelm3() { + args = []string{"list", "--filter", filter} + } else { + args = []string{"list", filter} + } + + out, err := helm.exec(append(append(preArgs, args...), flags...), env) helm.write(out) return string(out), err } @@ -201,7 +208,14 @@ func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...str func (helm *execer) TemplateRelease(name string, chart string, flags ...string) error { helm.logger.Infof("Templating release=%v, chart=%v", name, chart) - out, err := helm.exec(append([]string{"template", chart, "--name", name}, flags...), map[string]string{}) + var args []string + if helm.isHelm3() { + args = []string{"template", name, chart} + } else { + args = []string{"template", chart, "--name", name} + } + + out, err := helm.exec(append(args, flags...), map[string]string{}) helm.write(out) return err } @@ -261,7 +275,13 @@ func (helm *execer) TestRelease(context HelmContext, name string, flags ...strin helm.logger.Infof("Testing %v", name) preArgs := context.GetTillerlessArgs(helm.helmBinary) env := context.getTillerlessEnv() - out, err := helm.exec(append(append(preArgs, "test", name), flags...), env) + var args []string + if helm.isHelm3() { + args = []string{"test", "run", name} + } else { + args = []string{"test", name} + } + out, err := helm.exec(append(append(preArgs, args...), flags...), env) helm.write(out) return err } @@ -292,3 +312,7 @@ func (helm *execer) write(out []byte) { fmt.Printf("%s\n", out) } } + +func (helm *execer) isHelm3() bool { + return os.Getenv("HELMFILE_HELM3") != "" +} diff --git a/pkg/state/state.go b/pkg/state/state.go index c6fd53f4..cf82d495 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -896,7 +896,7 @@ func (st *HelmState) DeleteReleases(affectedReleases *AffectedReleases, helm hel } flags := []string{} - if purge { + if purge && !st.isHelm3() { flags = append(flags, "--purge") } flags = st.appendConnectionFlags(flags, &release) @@ -930,13 +930,21 @@ func (st *HelmState) TestReleases(helm helmexec.Interface, cleanup bool, timeout if cleanup { flags = append(flags, "--cleanup") } - flags = append(flags, "--timeout", strconv.Itoa(timeout)) + duration := strconv.Itoa(timeout) + if st.isHelm3() { + duration += "s" + } + flags = append(flags, "--timeout", duration) flags = st.appendConnectionFlags(flags, &release) return helm.TestRelease(st.createHelmContext(&release, workerIndex), release.Name, flags...) }) } +func (st *HelmState) isHelm3() bool { + return os.Getenv("HELMFILE_HELM3") != "" +} + // Clean will remove any generated secrets func (st *HelmState) Clean() []error { errs := []error{} @@ -1250,9 +1258,7 @@ func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSp } func (st *HelmState) flagsForTemplate(helm helmexec.Interface, release *ReleaseSpec, workerIndex int) ([]string, error) { - flags := []string{ - "--name", release.Name, - } + flags := []string{} var err error flags, err = st.appendHelmXFlags(flags, release)