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
This commit is contained in:
		
							parent
							
								
									6dfc9be0d1
								
							
						
					
					
						commit
						4e4f1bee59
					
				| 
						 | 
					@ -1843,11 +1843,12 @@ type mockHelmExec struct {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type mockTemplates struct {
 | 
					type mockTemplates struct {
 | 
				
			||||||
 | 
						name, chart string
 | 
				
			||||||
	flags       []string
 | 
						flags       []string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (helm *mockHelmExec) TemplateRelease(name, chart string, flags ...string) error {
 | 
					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
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1906,14 +1907,14 @@ releases:
 | 
				
			||||||
- name: myrelease1
 | 
					- name: myrelease1
 | 
				
			||||||
  chart: mychart1
 | 
					  chart: mychart1
 | 
				
			||||||
- name: myrelease2
 | 
					- name: myrelease2
 | 
				
			||||||
  chart: mychart1
 | 
					  chart: mychart2
 | 
				
			||||||
`,
 | 
					`,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var helm = &mockHelmExec{}
 | 
						var helm = &mockHelmExec{}
 | 
				
			||||||
	var wantReleases = []mockTemplates{
 | 
						var wantReleases = []mockTemplates{
 | 
				
			||||||
		{[]string{"--name", "myrelease1", "--namespace", "testNamespace", "--output-dir", "output/subdir/helmfile-[a-z0-9]{8}-myrelease1"}},
 | 
							{name: "myrelease1", chart: "mychart1", flags: []string{"--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: "myrelease2", chart: "mychart2", flags: []string{"--namespace", "testNamespace", "--output-dir", "output/subdir/helmfile-[a-z0-9]{8}-myrelease2"}},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var buffer bytes.Buffer
 | 
						var buffer bytes.Buffer
 | 
				
			||||||
| 
						 | 
					@ -1931,8 +1932,14 @@ releases:
 | 
				
			||||||
	app.Template(configImpl{})
 | 
						app.Template(configImpl{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := range wantReleases {
 | 
						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 {
 | 
							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]))
 | 
									matched, _ := regexp.Match(wantReleases[i].flags[j], []byte(helm.templated[i].flags[j]))
 | 
				
			||||||
				if !matched {
 | 
									if !matched {
 | 
				
			||||||
					t.Errorf("HelmState.TemplateReleases() = [%v], want %v", helm.templated[i].flags[j], wantReleases[i].flags[j])
 | 
										t.Errorf("HelmState.TemplateReleases() = [%v], want %v", helm.templated[i].flags[j], wantReleases[i].flags[j])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,7 +126,14 @@ func (helm *execer) List(context HelmContext, filter string, flags ...string) (s
 | 
				
			||||||
	helm.logger.Infof("Listing releases matching %v", filter)
 | 
						helm.logger.Infof("Listing releases matching %v", filter)
 | 
				
			||||||
	preArgs := context.GetTillerlessArgs(helm.helmBinary)
 | 
						preArgs := context.GetTillerlessArgs(helm.helmBinary)
 | 
				
			||||||
	env := context.getTillerlessEnv()
 | 
						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)
 | 
						helm.write(out)
 | 
				
			||||||
	return string(out), err
 | 
						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 {
 | 
					func (helm *execer) TemplateRelease(name string, chart string, flags ...string) error {
 | 
				
			||||||
	helm.logger.Infof("Templating release=%v, chart=%v", name, chart)
 | 
						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)
 | 
						helm.write(out)
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -261,7 +275,13 @@ func (helm *execer) TestRelease(context HelmContext, name string, flags ...strin
 | 
				
			||||||
	helm.logger.Infof("Testing %v", name)
 | 
						helm.logger.Infof("Testing %v", name)
 | 
				
			||||||
	preArgs := context.GetTillerlessArgs(helm.helmBinary)
 | 
						preArgs := context.GetTillerlessArgs(helm.helmBinary)
 | 
				
			||||||
	env := context.getTillerlessEnv()
 | 
						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)
 | 
						helm.write(out)
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -292,3 +312,7 @@ func (helm *execer) write(out []byte) {
 | 
				
			||||||
		fmt.Printf("%s\n", out)
 | 
							fmt.Printf("%s\n", out)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (helm *execer) isHelm3() bool {
 | 
				
			||||||
 | 
						return os.Getenv("HELMFILE_HELM3") != ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -896,7 +896,7 @@ func (st *HelmState) DeleteReleases(affectedReleases *AffectedReleases, helm hel
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		flags := []string{}
 | 
							flags := []string{}
 | 
				
			||||||
		if purge {
 | 
							if purge && !st.isHelm3() {
 | 
				
			||||||
			flags = append(flags, "--purge")
 | 
								flags = append(flags, "--purge")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		flags = st.appendConnectionFlags(flags, &release)
 | 
							flags = st.appendConnectionFlags(flags, &release)
 | 
				
			||||||
| 
						 | 
					@ -930,13 +930,21 @@ func (st *HelmState) TestReleases(helm helmexec.Interface, cleanup bool, timeout
 | 
				
			||||||
		if cleanup {
 | 
							if cleanup {
 | 
				
			||||||
			flags = append(flags, "--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)
 | 
							flags = st.appendConnectionFlags(flags, &release)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return helm.TestRelease(st.createHelmContext(&release, workerIndex), release.Name, flags...)
 | 
							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
 | 
					// Clean will remove any generated secrets
 | 
				
			||||||
func (st *HelmState) Clean() []error {
 | 
					func (st *HelmState) Clean() []error {
 | 
				
			||||||
	errs := []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) {
 | 
					func (st *HelmState) flagsForTemplate(helm helmexec.Interface, release *ReleaseSpec, workerIndex int) ([]string, error) {
 | 
				
			||||||
	flags := []string{
 | 
						flags := []string{}
 | 
				
			||||||
		"--name", release.Name,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	flags, err = st.appendHelmXFlags(flags, release)
 | 
						flags, err = st.appendHelmXFlags(flags, release)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue