added option for --no-hooks for helm diff and apply (#279)
* added option for --no-hooks for helm diff and apply Signed-off-by: Arpan Adhikari <kcarpan5@gmail.com> * test case for --no-hooks Signed-off-by: Arpan Adhikari <kcarpan5@gmail.com> * fix test fails Signed-off-by: Arpan Adhikari <kcarpan5@gmail.com> * Resolve conflict with main Signed-off-by: Arpan Adhikari <kcarpan5@gmail.com> * fixup! Resolve conflict with main Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com> * Add no-hooks case for diff test Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com> * fixup! Add no-hooks case for diff test Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com> Signed-off-by: Arpan Adhikari <kcarpan5@gmail.com> Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com> Co-authored-by: Arpan Adhikari <arpan@thephotostudio.com.au> Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
This commit is contained in:
parent
b8cf0f156e
commit
e1ca846772
|
|
@ -50,6 +50,7 @@ func NewApplyCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
|||
f.StringArrayVar(&applyOptions.Suppress, "suppress", nil, "suppress specified Kubernetes objects in the diff output. Can be provided multiple times. For example: --suppress KeycloakClient --suppress VaultSecret")
|
||||
f.BoolVar(&applyOptions.SuppressSecrets, "suppress-secrets", false, "suppress secrets in the diff output. highly recommended to specify on CI/CD use-cases")
|
||||
f.BoolVar(&applyOptions.ShowSecrets, "show-secrets", false, "do not redact secret values in the diff output. should be used for debug purpose only")
|
||||
f.BoolVar(&applyOptions.NoHooks, "no-hooks", false, "do not diff changes made by hooks.")
|
||||
f.BoolVar(&applyOptions.SuppressDiff, "suppress-diff", false, "suppress diff in the output. Usable in new installs")
|
||||
f.BoolVar(&applyOptions.SkipDeps, "skip-deps", false, `skip running "helm repo update" and "helm dependency build"`)
|
||||
f.BoolVarP(&applyOptions.Interactive, "interactive", "i", false, "Request confirmation before attempting to modify clusters")
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ func NewDiffCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
|||
f.BoolVar(&diffOptions.SkipDeps, "skip-deps", false, `skip running "helm repo update" and "helm dependency build"`)
|
||||
f.BoolVar(&diffOptions.SkipDiffOnInstall, "skip-diff-on-install", false, "Skips running helm-diff on releases being newly installed on this apply. Useful when the release manifests are too huge to be reviewed, or it's too time-consuming to diff at all")
|
||||
f.BoolVar(&diffOptions.ShowSecrets, "show-secrets", false, "do not redact secret values in the output. should be used for debug purpose only")
|
||||
f.BoolVar(&diffOptions.NoHooks, "no-hooks", false, "do not diff changes made by hooks.")
|
||||
f.BoolVar(&diffOptions.DetailedExitcode, "detailed-exitcode", false, "return a detailed exit code")
|
||||
f.IntVar(&diffOptions.Context, "context", 0, "output NUM lines of context around changes")
|
||||
f.StringVar(&diffOptions.Output, "output", "", "output format for diff plugin")
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ func TestDiffWithNeeds(t *testing.T) {
|
|||
skipNeeds bool
|
||||
includeNeeds bool
|
||||
includeTransitiveNeeds bool
|
||||
noHooks bool
|
||||
}
|
||||
|
||||
type testcase struct {
|
||||
|
|
@ -154,6 +155,7 @@ releases:
|
|||
skipNeeds: tc.fields.skipNeeds,
|
||||
includeNeeds: tc.fields.includeNeeds,
|
||||
includeTransitiveNeeds: tc.fields.includeTransitiveNeeds,
|
||||
noHooks: tc.fields.noHooks,
|
||||
})
|
||||
|
||||
var gotErr string
|
||||
|
|
@ -297,6 +299,20 @@ releases:
|
|||
})
|
||||
})
|
||||
|
||||
t.Run("no-hooks", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
fields: fields{
|
||||
skipNeeds: true,
|
||||
noHooks: true,
|
||||
},
|
||||
selectors: []string{"app=test"},
|
||||
diffed: []exectest.Release{
|
||||
{Name: "external-secrets", Flags: []string{"--kube-context", "default", "--namespace", "default", "--no-hooks"}},
|
||||
{Name: "my-release", Flags: []string{"--kube-context", "default", "--namespace", "default", "--no-hooks"}},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("bad selector", func(t *testing.T) {
|
||||
check(t, testcase{
|
||||
selectors: []string{"app=test_non_existent"},
|
||||
|
|
|
|||
|
|
@ -2315,6 +2315,7 @@ type applyConfig struct {
|
|||
suppress []string
|
||||
suppressSecrets bool
|
||||
showSecrets bool
|
||||
noHooks bool
|
||||
suppressDiff bool
|
||||
noColor bool
|
||||
color bool
|
||||
|
|
@ -2397,6 +2398,10 @@ func (a applyConfig) ShowSecrets() bool {
|
|||
return a.showSecrets
|
||||
}
|
||||
|
||||
func (a applyConfig) NoHooks() bool {
|
||||
return a.noHooks
|
||||
}
|
||||
|
||||
func (a applyConfig) SuppressDiff() bool {
|
||||
return a.suppressDiff
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ type ApplyConfigProvider interface {
|
|||
Suppress() []string
|
||||
SuppressSecrets() bool
|
||||
ShowSecrets() bool
|
||||
NoHooks() bool
|
||||
SuppressDiff() bool
|
||||
|
||||
DetailedExitcode() bool
|
||||
|
|
@ -112,6 +113,7 @@ type DiffConfigProvider interface {
|
|||
Suppress() []string
|
||||
SuppressSecrets() bool
|
||||
ShowSecrets() bool
|
||||
NoHooks() bool
|
||||
SuppressDiff() bool
|
||||
SkipDiffOnInstall() bool
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ type diffConfig struct {
|
|||
suppress []string
|
||||
suppressSecrets bool
|
||||
showSecrets bool
|
||||
noHooks bool
|
||||
suppressDiff bool
|
||||
noColor bool
|
||||
context int
|
||||
|
|
@ -95,6 +96,10 @@ func (a diffConfig) ShowSecrets() bool {
|
|||
return a.showSecrets
|
||||
}
|
||||
|
||||
func (a diffConfig) NoHooks() bool {
|
||||
return a.noHooks
|
||||
}
|
||||
|
||||
func (a diffConfig) SuppressDiff() bool {
|
||||
return a.suppressDiff
|
||||
}
|
||||
|
|
@ -143,6 +148,7 @@ func TestDiff(t *testing.T) {
|
|||
type flags struct {
|
||||
skipNeeds bool
|
||||
includeNeeds bool
|
||||
noHooks bool
|
||||
}
|
||||
|
||||
testcases := []struct {
|
||||
|
|
@ -1377,6 +1383,7 @@ changing working directory back to "/path/to"
|
|||
detailedExitcode: tc.detailedExitcode,
|
||||
skipNeeds: tc.flags.skipNeeds,
|
||||
includeNeeds: tc.flags.includeNeeds,
|
||||
noHooks: tc.flags.noHooks,
|
||||
})
|
||||
|
||||
var diffErrStr string
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ func (r *Run) diff(triggerCleanupEvent bool, detailedExitCode bool, c DiffConfig
|
|||
|
||||
// TODO Better way to detect diff on only filtered releases
|
||||
{
|
||||
changedReleases, planningErrs = st.DiffReleases(helm, c.Values(), c.Concurrency(), detailedExitCode, c.IncludeTests(), c.Suppress(), c.SuppressSecrets(), c.ShowSecrets(), c.SuppressDiff(), triggerCleanupEvent, diffOpts)
|
||||
changedReleases, planningErrs = st.DiffReleases(helm, c.Values(), c.Concurrency(), detailedExitCode, c.IncludeTests(), c.Suppress(), c.SuppressSecrets(), c.ShowSecrets(), c.NoHooks(), c.SuppressDiff(), triggerCleanupEvent, diffOpts)
|
||||
|
||||
var err error
|
||||
deletingReleases, err = st.DetectReleasesToBeDeletedForSync(helm, st.Releases)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
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: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
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: logging
|
||||
3: chart: incubator/raw
|
||||
4: namespace: kube-system
|
||||
5:
|
||||
6: - name: kubernetes-external-secrets
|
||||
7: chart: incubator/raw
|
||||
8: namespace: kube-system
|
||||
9: needs:
|
||||
10: - kube-system/logging
|
||||
11:
|
||||
12: - name: external-secrets
|
||||
13: chart: incubator/raw
|
||||
14: namespace: default
|
||||
15: labels:
|
||||
16: app: test
|
||||
17: needs:
|
||||
18: - kube-system/kubernetes-external-secrets
|
||||
19:
|
||||
20: - name: my-release
|
||||
21: chart: incubator/raw
|
||||
22: namespace: default
|
||||
23: labels:
|
||||
24: app: test
|
||||
25: needs:
|
||||
26: - default/external-secrets
|
||||
27:
|
||||
28:
|
||||
29: # Disabled releases are treated as missing
|
||||
30: - name: disabled
|
||||
31: chart: incubator/raw
|
||||
32: namespace: kube-system
|
||||
33: installed: false
|
||||
34:
|
||||
35: - name: test2
|
||||
36: chart: incubator/raw
|
||||
37: needs:
|
||||
38: - kube-system/disabled
|
||||
39:
|
||||
40: - name: test3
|
||||
41: chart: incubator/raw
|
||||
42: needs:
|
||||
43: - test2
|
||||
44:
|
||||
|
||||
merged environment: &{default map[] map[]}
|
||||
2 release(s) matching app=test found in helmfile.yaml
|
||||
|
||||
processing 2 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/default/external-secrets
|
||||
2 default/default/my-release
|
||||
|
||||
processing releases in group 1/2: default/default/external-secrets
|
||||
processing releases in group 2/2: default/default/my-release
|
||||
changing working directory back to "/path/to"
|
||||
|
|
@ -42,6 +42,8 @@ type ApplyOptions struct {
|
|||
SuppressSecrets bool
|
||||
// SuppressDiff is true if the diff should be suppressed
|
||||
ShowSecrets bool
|
||||
// NoHooks skips checking for hooks
|
||||
NoHooks bool
|
||||
// SkipDeps is true if the running "helm repo update" and "helm dependency build" should be skipped
|
||||
SuppressDiff bool
|
||||
// ShowSecrets is true if the secrets should be shown
|
||||
|
|
@ -135,6 +137,11 @@ func (a *ApplyImpl) ShowSecrets() bool {
|
|||
return a.ApplyOptions.ShowSecrets
|
||||
}
|
||||
|
||||
// NoHooks skips hooks.
|
||||
func (a *ApplyImpl) NoHooks() bool {
|
||||
return a.ApplyOptions.NoHooks
|
||||
}
|
||||
|
||||
// SkipCRDs returns the skip crds.
|
||||
func (a *ApplyImpl) SkipCRDs() bool {
|
||||
return a.ApplyOptions.SkipCRDs
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ type DiffOptions struct {
|
|||
SkipDiffOnInstall bool
|
||||
// ShowSecrets is the show secrets flag
|
||||
ShowSecrets bool
|
||||
// NoHooks skips hooks during diff
|
||||
NoHooks bool
|
||||
// Suppress is the suppress flag
|
||||
Suppress []string
|
||||
// SuppressSecrets is the suppress secrets flag
|
||||
|
|
@ -131,6 +133,11 @@ func (t *DiffImpl) ShowSecrets() bool {
|
|||
return t.DiffOptions.ShowSecrets
|
||||
}
|
||||
|
||||
// NoHooks skips hooks.
|
||||
func (t *DiffImpl) NoHooks() bool {
|
||||
return t.DiffOptions.NoHooks
|
||||
}
|
||||
|
||||
// ShowCRDs returns the show crds
|
||||
func (t *DiffImpl) SkipCRDs() bool {
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -1618,7 +1618,7 @@ type diffPrepareResult struct {
|
|||
upgradeDueToSkippedDiff bool
|
||||
}
|
||||
|
||||
func (st *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValues []string, concurrency int, detailedExitCode bool, includeTests bool, suppress []string, suppressSecrets bool, showSecrets bool, opt ...DiffOpt) ([]diffPrepareResult, []error) {
|
||||
func (st *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValues []string, concurrency int, detailedExitCode bool, includeTests bool, suppress []string, suppressSecrets bool, showSecrets bool, noHooks bool, opt ...DiffOpt) ([]diffPrepareResult, []error) {
|
||||
opts := &DiffOpts{}
|
||||
for _, o := range opt {
|
||||
o.Apply(opts)
|
||||
|
|
@ -1731,6 +1731,10 @@ func (st *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValu
|
|||
flags = append(flags, "--show-secrets")
|
||||
}
|
||||
|
||||
if noHooks {
|
||||
flags = append(flags, "--no-hooks")
|
||||
}
|
||||
|
||||
if opts.NoColor {
|
||||
flags = append(flags, "--no-color")
|
||||
} else if opts.Color {
|
||||
|
|
@ -1846,13 +1850,13 @@ type DiffOpt interface{ Apply(*DiffOpts) }
|
|||
// For example, terraform-provider-helmfile runs a helmfile-diff on `terraform plan` and another on `terraform apply`.
|
||||
// `terraform`, by design, fails when helmfile-diff outputs were not equivalent.
|
||||
// Stabilized helmfile-diff output rescues that.
|
||||
func (st *HelmState) DiffReleases(helm helmexec.Interface, additionalValues []string, workerLimit int, detailedExitCode bool, includeTests bool, suppress []string, suppressSecrets, showSecrets, suppressDiff, triggerCleanupEvents bool, opt ...DiffOpt) ([]ReleaseSpec, []error) {
|
||||
func (st *HelmState) DiffReleases(helm helmexec.Interface, additionalValues []string, workerLimit int, detailedExitCode bool, includeTests bool, suppress []string, suppressSecrets, showSecrets, noHooks bool, suppressDiff, triggerCleanupEvents bool, opt ...DiffOpt) ([]ReleaseSpec, []error) {
|
||||
opts := &DiffOpts{}
|
||||
for _, o := range opt {
|
||||
o.Apply(opts)
|
||||
}
|
||||
|
||||
preps, prepErrs := st.prepareDiffReleases(helm, additionalValues, workerLimit, detailedExitCode, includeTests, suppress, suppressSecrets, showSecrets, opts)
|
||||
preps, prepErrs := st.prepareDiffReleases(helm, additionalValues, workerLimit, detailedExitCode, includeTests, suppress, suppressSecrets, showSecrets, noHooks, opts)
|
||||
|
||||
if !opts.SkipCleanup {
|
||||
defer func() {
|
||||
|
|
|
|||
|
|
@ -1597,7 +1597,7 @@ func TestHelmState_DiffReleases(t *testing.T) {
|
|||
valsRuntime: valsRuntime,
|
||||
RenderedValues: map[string]interface{}{},
|
||||
}
|
||||
_, errs := state.DiffReleases(tt.helm, []string{}, 1, false, false, []string{}, false, false, false, false)
|
||||
_, errs := state.DiffReleases(tt.helm, []string{}, 1, false, false, []string{}, false, false, false, false, false)
|
||||
if len(errs) > 0 {
|
||||
t.Errorf("unexpected error: %v", errs)
|
||||
}
|
||||
|
|
@ -1813,7 +1813,7 @@ func TestHelmState_DiffReleasesCleanup(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
state = injectFs(state, testfs)
|
||||
if _, errs := state.DiffReleases(tt.helm, []string{}, 1, false, false, []string{}, false, false, false, false); len(errs) > 0 {
|
||||
if _, errs := state.DiffReleases(tt.helm, []string{}, 1, false, false, []string{}, false, false, false, false, false); len(errs) > 0 {
|
||||
t.Errorf("unexpected errors: %v", errs)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue