Only run preapply or presync
Signed-off-by: Anton Bretting <sajfer@gmail.com>
This commit is contained in:
		
							parent
							
								
									1a3c11dffd
								
							
						
					
					
						commit
						db81f18095
					
				|  | @ -1330,6 +1330,7 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, bool, []error) { | ||||||
| 			for _, hook := range release.Hooks { | 			for _, hook := range release.Hooks { | ||||||
| 				if slices.Contains(hook.Events, "preapply") { | 				if slices.Contains(hook.Events, "preapply") { | ||||||
| 					releasesWithPreApply = append(releasesWithPreApply, release) | 					releasesWithPreApply = append(releasesWithPreApply, release) | ||||||
|  | 					break | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -1380,6 +1381,7 @@ Do you really want to apply? | ||||||
| 			a.Logger.Infof("\nRunning preapply hook for %s:", release.Name) | 			a.Logger.Infof("\nRunning preapply hook for %s:", release.Name) | ||||||
| 			if _, err := st.TriggerPreapplyEvent(&release, "apply"); err != nil { | 			if _, err := st.TriggerPreapplyEvent(&release, "apply"); err != nil { | ||||||
| 				syncErrs = append(syncErrs, err) | 				syncErrs = append(syncErrs, err) | ||||||
|  | 				continue | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -213,7 +213,38 @@ releases: | ||||||
|   labels: |   labels: | ||||||
|     app: test |     app: test | ||||||
|   hooks: |   hooks: | ||||||
|   - events: ["preapply", "presync"] |   - events: ["prepare", "preapply", "presync"] | ||||||
|  |     command: echo | ||||||
|  |     showlogs: true | ||||||
|  |     args: ["foo"] | ||||||
|  | `, | ||||||
|  | 			}, | ||||||
|  | 			selectors: []string{"name=foo"}, | ||||||
|  | 			upgraded: []exectest.Release{ | ||||||
|  | 				{Name: "foo"}, | ||||||
|  | 			}, | ||||||
|  | 			diffs: map[exectest.DiffKey]error{ | ||||||
|  | 				{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode"}: helmexec.ExitError{Code: 2}, | ||||||
|  | 			}, | ||||||
|  | 			error: "", | ||||||
|  | 			// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
 | ||||||
|  | 			concurrency: 1, | ||||||
|  | 			logLevel:    "info", | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("apply release with preapply hook", func(t *testing.T) { | ||||||
|  | 		check(t, testcase{ | ||||||
|  | 			files: map[string]string{ | ||||||
|  | 				"/path/to/helmfile.yaml": ` | ||||||
|  | releases: | ||||||
|  | - name: foo | ||||||
|  |   chart: incubator/raw | ||||||
|  |   namespace: default | ||||||
|  |   labels: | ||||||
|  |     app: test | ||||||
|  |   hooks: | ||||||
|  |   - events: ["presync"] | ||||||
|     command: echo |     command: echo | ||||||
|     showlogs: true |     showlogs: true | ||||||
|     args: ["foo"] |     args: ["foo"] | ||||||
|  |  | ||||||
|  | @ -1340,34 +1340,4 @@ foo 	4       	Fri Nov  1 08:40:07 2019	DEPLOYED	raw-3.1.0	3.1.0      	default | ||||||
| 			concurrency: 1, | 			concurrency: 1, | ||||||
| 		}) | 		}) | ||||||
| 	}) | 	}) | ||||||
| 
 |  | ||||||
| 	t.Run("apply release with preapply hook", func(t *testing.T) { |  | ||||||
| 		check(t, testcase{ |  | ||||||
| 			files: map[string]string{ |  | ||||||
| 				"/path/to/helmfile.yaml": ` |  | ||||||
| releases: |  | ||||||
| - name: foo |  | ||||||
|   chart: incubator/raw |  | ||||||
|   namespace: default |  | ||||||
|   labels: |  | ||||||
|     app: test |  | ||||||
|   hooks: |  | ||||||
|   - events: ["preapply"] |  | ||||||
|     command: echo |  | ||||||
|     showlogs: true |  | ||||||
|     args: ["foo"] |  | ||||||
| `, |  | ||||||
| 			}, |  | ||||||
| 			selectors: []string{"name=foo"}, |  | ||||||
| 			upgraded: []exectest.Release{ |  | ||||||
| 				{Name: "foo"}, |  | ||||||
| 			}, |  | ||||||
| 			diffs: map[exectest.DiffKey]error{ |  | ||||||
| 				{Name: "foo", Chart: "incubator/raw", Flags: "--kube-contextdefault--namespacedefault--detailed-exitcode"}: helmexec.ExitError{Code: 2}, |  | ||||||
| 			}, |  | ||||||
| 			error: "", |  | ||||||
| 			// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
 |  | ||||||
| 			concurrency: 1, |  | ||||||
| 		}) |  | ||||||
| 	}) |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,68 @@ | ||||||
|  | processing file "helmfile.yaml" in directory "." | ||||||
|  | first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil> | ||||||
|  | first-pass uses: &{default map[] map[]} | ||||||
|  | first-pass rendering output of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: foo | ||||||
|  |  3:   chart: incubator/raw | ||||||
|  |  4:   namespace: default | ||||||
|  |  5:   labels: | ||||||
|  |  6:     app: test | ||||||
|  |  7:   hooks: | ||||||
|  |  8:   - events: ["preapply"] | ||||||
|  |  9:     command: echo | ||||||
|  | 10:     showlogs: true | ||||||
|  | 11:     args: ["foo"] | ||||||
|  | 12:  | ||||||
|  | 
 | ||||||
|  | first-pass produced: &{default map[] map[]} | ||||||
|  | first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]} | ||||||
|  | vals: | ||||||
|  | map[] | ||||||
|  | defaultVals:[] | ||||||
|  | second-pass rendering result of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: foo | ||||||
|  |  3:   chart: incubator/raw | ||||||
|  |  4:   namespace: default | ||||||
|  |  5:   labels: | ||||||
|  |  6:     app: test | ||||||
|  |  7:   hooks: | ||||||
|  |  8:   - events: ["preapply"] | ||||||
|  |  9:     command: echo | ||||||
|  | 10:     showlogs: true | ||||||
|  | 11:     args: ["foo"] | ||||||
|  | 12:  | ||||||
|  | 
 | ||||||
|  | merged environment: &{default map[] map[]} | ||||||
|  | 1 release(s) matching name=foo found in helmfile.yaml | ||||||
|  | 
 | ||||||
|  | Affected releases are: | ||||||
|  |   foo (incubator/raw) UPDATED | ||||||
|  | Releases with preapply hooks:  | ||||||
|  |   foo (incubator/raw) | ||||||
|  | 
 | ||||||
|  | Running preapply hook for foo: | ||||||
|  | hook[echo]: stateFilePath=helmfile.yaml, basePath=. | ||||||
|  | hook[echo]: triggered by event "preapply" | ||||||
|  | 
 | ||||||
|  | echo:XlBWj> foo | ||||||
|  | hook[echo]: foo | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | hook[preapply] logs | foo | ||||||
|  | hook[preapply] logs |  | ||||||
|  | processing 1 groups of releases in this order: | ||||||
|  | GROUP RELEASES | ||||||
|  | 1     default/default/foo | ||||||
|  | 
 | ||||||
|  | processing releases in group 1/1: default/default/foo | ||||||
|  | getting deployed release version failed:unexpected list key: {^foo$ --kube-contextdefault--deleting--deployed--failed--pending} | ||||||
|  | 
 | ||||||
|  | UPDATED RELEASES: | ||||||
|  | NAME   CHART           VERSION | ||||||
|  | foo    incubator/raw           | ||||||
|  | 
 | ||||||
|  | @ -1,8 +1,13 @@ | ||||||
| 
 | 
 | ||||||
|  | hook[prepare] logs | foo | ||||||
|  | hook[prepare] logs |  | ||||||
|  | 
 | ||||||
| Running preapply hook for foo: | Running preapply hook for foo: | ||||||
| 
 | 
 | ||||||
| hook[preapply] logs | foo | hook[preapply] logs | foo | ||||||
| hook[preapply] logs |  | hook[preapply] logs |  | ||||||
|  | hook[echo]: already executed by "preapply", skipping "presync" | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| UPDATED RELEASES: | UPDATED RELEASES: | ||||||
| NAME   CHART           VERSION | NAME   CHART           VERSION | ||||||
|  |  | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | 
 | ||||||
|  | hook[presync] logs | foo | ||||||
|  | hook[presync] logs |  | ||||||
|  | 
 | ||||||
|  | UPDATED RELEASES: | ||||||
|  | NAME   CHART           VERSION | ||||||
|  | foo    incubator/raw           | ||||||
|  | 
 | ||||||
|  | @ -10,6 +10,8 @@ import ( | ||||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||||
| 	"github.com/helmfile/helmfile/pkg/tmpl" | 	"github.com/helmfile/helmfile/pkg/tmpl" | ||||||
|  | 	"go.uber.org/zap" | ||||||
|  | 	"golang.org/x/exp/slices" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type Hook struct { | type Hook struct { | ||||||
|  | @ -19,6 +21,7 @@ type Hook struct { | ||||||
| 	Kubectl  map[string]string `yaml:"kubectlApply,omitempty"` | 	Kubectl  map[string]string `yaml:"kubectlApply,omitempty"` | ||||||
| 	Args     []string          `yaml:"args"` | 	Args     []string          `yaml:"args"` | ||||||
| 	ShowLogs bool              `yaml:"showlogs"` | 	ShowLogs bool              `yaml:"showlogs"` | ||||||
|  | 	Executed bool              `yaml:"-"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type event struct { | type event struct { | ||||||
|  | @ -71,6 +74,10 @@ func (bus *Bus) Trigger(evt string, evtErr error, context map[string]interface{} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		if slices.Contains(hook.Events, "preapply") && evt == "presync" && hook.Executed { | ||||||
|  | 			bus.Logger.Infof("hook[%s]: already executed by \"preapply\", skipping \"%s\"\n", name, evt) | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
| 		if hook.Kubectl != nil { | 		if hook.Kubectl != nil { | ||||||
| 			if hook.Command != "" { | 			if hook.Command != "" { | ||||||
| 				bus.Logger.Warnf("warn: ignoring command '%s' given within a kubectlApply hook", hook.Command) | 				bus.Logger.Warnf("warn: ignoring command '%s' given within a kubectlApply hook", hook.Command) | ||||||
|  |  | ||||||
|  | @ -41,21 +41,21 @@ func TestTrigger(t *testing.T) { | ||||||
| 	}{ | 	}{ | ||||||
| 		{ | 		{ | ||||||
| 			"okhook1", | 			"okhook1", | ||||||
| 			&Hook{"okhook1", []string{"foo"}, "ok", nil, []string{}, true}, | 			&Hook{"okhook1", []string{"foo"}, "ok", nil, []string{}, true, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			true, | 			true, | ||||||
| 			"", | 			"", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"okhooké", | 			"okhooké", | ||||||
| 			&Hook{"okhook2", []string{"foo"}, "ok", nil, []string{}, false}, | 			&Hook{"okhook2", []string{"foo"}, "ok", nil, []string{}, false, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			true, | 			true, | ||||||
| 			"", | 			"", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"missinghook1", | 			"missinghook1", | ||||||
| 			&Hook{"okhook1", []string{"foo"}, "ok", nil, []string{}, false}, | 			&Hook{"okhook1", []string{"foo"}, "ok", nil, []string{}, false, false}, | ||||||
| 			"bar", | 			"bar", | ||||||
| 			false, | 			false, | ||||||
| 			"", | 			"", | ||||||
|  | @ -69,70 +69,70 @@ func TestTrigger(t *testing.T) { | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"nghook1", | 			"nghook1", | ||||||
| 			&Hook{"nghook1", []string{"foo"}, "ng", nil, []string{}, false}, | 			&Hook{"nghook1", []string{"foo"}, "ng", nil, []string{}, false, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			false, | 			false, | ||||||
| 			"hook[nghook1]: command `ng` failed: cmd failed due to invalid cmd: ng", | 			"hook[nghook1]: command `ng` failed: cmd failed due to invalid cmd: ng", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"nghook2", | 			"nghook2", | ||||||
| 			&Hook{"nghook2", []string{"foo"}, "ok", nil, []string{"ng"}, false}, | 			&Hook{"nghook2", []string{"foo"}, "ok", nil, []string{"ng"}, false, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			false, | 			false, | ||||||
| 			"hook[nghook2]: command `ok` failed: cmd failed due to invalid arg: ng", | 			"hook[nghook2]: command `ok` failed: cmd failed due to invalid arg: ng", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"okkubeapply1", | 			"okkubeapply1", | ||||||
| 			&Hook{"okkubeapply1", []string{"foo"}, "", map[string]string{"kustomize": "kustodir"}, []string{}, false}, | 			&Hook{"okkubeapply1", []string{"foo"}, "", map[string]string{"kustomize": "kustodir"}, []string{}, false, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			true, | 			true, | ||||||
| 			"", | 			"", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"okkubeapply2", | 			"okkubeapply2", | ||||||
| 			&Hook{"okkubeapply2", []string{"foo"}, "", map[string]string{"filename": "resource.yaml"}, []string{}, false}, | 			&Hook{"okkubeapply2", []string{"foo"}, "", map[string]string{"filename": "resource.yaml"}, []string{}, false, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			true, | 			true, | ||||||
| 			"", | 			"", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"kokubeapply", | 			"kokubeapply", | ||||||
| 			&Hook{"kokubeapply", []string{"foo"}, "", map[string]string{"kustomize": "kustodir", "filename": "resource.yaml"}, []string{}, true}, | 			&Hook{"kokubeapply", []string{"foo"}, "", map[string]string{"kustomize": "kustodir", "filename": "resource.yaml"}, []string{}, true, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			false, | 			false, | ||||||
| 			"hook[kokubeapply]: kustomize & filename cannot be used together", | 			"hook[kokubeapply]: kustomize & filename cannot be used together", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"kokubeapply2", | 			"kokubeapply2", | ||||||
| 			&Hook{"kokubeapply2", []string{"foo"}, "", map[string]string{}, []string{}, true}, | 			&Hook{"kokubeapply2", []string{"foo"}, "", map[string]string{}, []string{}, true, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			false, | 			false, | ||||||
| 			"hook[kokubeapply2]: either kustomize or filename must be given", | 			"hook[kokubeapply2]: either kustomize or filename must be given", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"kokubeapply3", | 			"kokubeapply3", | ||||||
| 			&Hook{"", []string{"foo"}, "", map[string]string{}, []string{}, true}, | 			&Hook{"", []string{"foo"}, "", map[string]string{}, []string{}, true, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			false, | 			false, | ||||||
| 			"hook[kubectlApply]: either kustomize or filename must be given", | 			"hook[kubectlApply]: either kustomize or filename must be given", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"warnkubeapply1", | 			"warnkubeapply1", | ||||||
| 			&Hook{"warnkubeapply1", []string{"foo"}, "ok", map[string]string{"filename": "resource.yaml"}, []string{}, true}, | 			&Hook{"warnkubeapply1", []string{"foo"}, "ok", map[string]string{"filename": "resource.yaml"}, []string{}, true, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			true, | 			true, | ||||||
| 			"", | 			"", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"warnkubeapply2", | 			"warnkubeapply2", | ||||||
| 			&Hook{"warnkubeapply2", []string{"foo"}, "", map[string]string{"filename": "resource.yaml"}, []string{"ng"}, true}, | 			&Hook{"warnkubeapply2", []string{"foo"}, "", map[string]string{"filename": "resource.yaml"}, []string{"ng"}, true, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			true, | 			true, | ||||||
| 			"", | 			"", | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"warnkubeapply3", | 			"warnkubeapply3", | ||||||
| 			&Hook{"warnkubeapply3", []string{"foo"}, "ok", map[string]string{"filename": "resource.yaml"}, []string{"ng"}, true}, | 			&Hook{"warnkubeapply3", []string{"foo"}, "ok", map[string]string{"filename": "resource.yaml"}, []string{"ng"}, true, false}, | ||||||
| 			"foo", | 			"foo", | ||||||
| 			true, | 			true, | ||||||
| 			"", | 			"", | ||||||
|  |  | ||||||
|  | @ -18,6 +18,15 @@ import ( | ||||||
| 	"text/template" | 	"text/template" | ||||||
| 
 | 
 | ||||||
| 	"github.com/imdario/mergo" | 	"github.com/imdario/mergo" | ||||||
|  | 	"github.com/variantdev/chartify" | ||||||
|  | 	"golang.org/x/exp/slices" | ||||||
|  | 
 | ||||||
|  | 	"github.com/helmfile/helmfile/pkg/environment" | ||||||
|  | 	"github.com/helmfile/helmfile/pkg/event" | ||||||
|  | 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||||
|  | 	"github.com/helmfile/helmfile/pkg/remote" | ||||||
|  | 	"github.com/helmfile/helmfile/pkg/tmpl" | ||||||
|  | 
 | ||||||
| 	"github.com/tatsushid/go-prettytable" | 	"github.com/tatsushid/go-prettytable" | ||||||
| 	"github.com/variantdev/chartify" | 	"github.com/variantdev/chartify" | ||||||
| 	"github.com/variantdev/vals" | 	"github.com/variantdev/vals" | ||||||
|  | @ -2256,6 +2265,16 @@ func (st *HelmState) TriggerPreapplyEvent(r *ReleaseSpec, helmfileCommand string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (st *HelmState) triggerReleaseEvent(evt string, evtErr error, r *ReleaseSpec, helmfileCmd string) (bool, error) { | func (st *HelmState) triggerReleaseEvent(evt string, evtErr error, r *ReleaseSpec, helmfileCmd string) (bool, error) { | ||||||
|  | 
 | ||||||
|  | 	var stateRelease ReleaseSpec | ||||||
|  | 
 | ||||||
|  | 	for id, release := range st.Releases { | ||||||
|  | 		if release.Name == r.Name { | ||||||
|  | 			stateRelease = st.Releases[id] | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	bus := &event.Bus{ | 	bus := &event.Bus{ | ||||||
| 		Hooks:         r.Hooks, | 		Hooks:         r.Hooks, | ||||||
| 		StateFilePath: st.FilePath, | 		StateFilePath: st.FilePath, | ||||||
|  | @ -2272,7 +2291,18 @@ func (st *HelmState) triggerReleaseEvent(evt string, evtErr error, r *ReleaseSpe | ||||||
| 		"Release":         r, | 		"Release":         r, | ||||||
| 		"HelmfileCommand": helmfileCmd, | 		"HelmfileCommand": helmfileCmd, | ||||||
| 	} | 	} | ||||||
| 	return bus.Trigger(evt, evtErr, data) | 
 | ||||||
|  | 	executed, err := bus.Trigger(evt, evtErr, data) | ||||||
|  | 
 | ||||||
|  | 	if executed { | ||||||
|  | 		for id, hook := range stateRelease.Hooks { | ||||||
|  | 			if slices.Contains(hook.Events, evt) { | ||||||
|  | 				stateRelease.Hooks[id].Executed = true | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return executed, err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ResolveDeps returns a copy of this helmfile state with the concrete chart version numbers filled in for remote chart dependencies
 | // ResolveDeps returns a copy of this helmfile state with the concrete chart version numbers filled in for remote chart dependencies
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue