diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index de8796b5..f256b0e1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,7 +20,7 @@ jobs: cache: false - uses: golangci/golangci-lint-action@v4 with: - version: v1.55.1 + version: v1.56.0 tests: runs-on: ubuntu-latest diff --git a/cmd/apply.go b/cmd/apply.go index f7349f44..bc23438d 100644 --- a/cmd/apply.go +++ b/cmd/apply.go @@ -68,6 +68,7 @@ func NewApplyCmd(globalCfg *config.GlobalImpl) *cobra.Command { f.StringVar(&applyOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`) f.StringArrayVar(&applyOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`) f.StringVar(&applyOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background") + f.StringArrayVar(&applyOptions.SuppressOutputLineRegex, "suppress-output-line-regex", nil, "a list of regex patterns to suppress output lines from the diff output") return cmd } diff --git a/cmd/diff.go b/cmd/diff.go index 86ec65b2..020bc6f1 100644 --- a/cmd/diff.go +++ b/cmd/diff.go @@ -54,6 +54,7 @@ func NewDiffCmd(globalCfg *config.GlobalImpl) *cobra.Command { f.BoolVar(&diffOptions.ResetValues, "reset-values", false, `Override helmDefaults.reuseValues "helm diff upgrade --install --reset-values"`) f.StringVar(&diffOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`) f.StringArrayVar(&diffOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`) + f.StringArrayVar(&diffOptions.SuppressOutputLineRegex, "suppress-output-line-regex", nil, "a list of regex patterns to suppress output lines from the diff output") return cmd } diff --git a/docs/index.md b/docs/index.md index 8af3a404..26deeb29 100644 --- a/docs/index.md +++ b/docs/index.md @@ -225,6 +225,9 @@ helmDefaults: deleteWait: false # Timeout is the time in seconds to wait for helmfile destroy/delete (default 300) deleteTimeout: 300 + # suppressOutputLineRegex is a list of regex patterns to suppress output lines from helm diff (default []), available in helmfile v0.162.0 + suppressOutputLineRegex: + - "version" # these labels will be applied to all releases in a Helmfile. Useful in templating if you have a helmfile per environment or customer and don't want to copy the same label to each release commonLabels: @@ -336,6 +339,9 @@ releases: insecureSkipTLSVerify: false # suppressDiff skip the helm diff output. Useful for charts which produces large not helpful diff, default: false suppressDiff: false + # suppressOutputLineRegex is a list of regex patterns to suppress output lines from helm diff (default []), available in helmfile v0.162.0 + suppressOutputLineRegex: + - "version" # Local chart example @@ -530,6 +536,7 @@ Helmfile uses some OS environment variables to override default behaviour: * `HELMFILE_V1MODE` - Helmfile v0.x behaves like v1.x with `true`, Helmfile v1.x behaves like v0.x with `false` as value * `HELMFILE_GOCCY_GOYAML` - 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. * `HELMFILE_CACHE_HOME` - specify directory to store cached files for remote operations +* `HELMFILE_FILE_PATH` - specify the path to the helmfile.yaml file ## CLI Reference @@ -565,33 +572,34 @@ Available Commands: write-values Write values files for releases. Similar to `helmfile template`, write values files instead of manifests. Flags: - --allow-no-matching-release Do not exit with an error code if the provided selector has no matching releases. - -c, --chart string Set chart. Uses the chart set in release by default, and is available in template as {{ .Chart }} - --color Output with color - --debug Enable verbose output for Helm and set log-level to debug, this disables --quiet/-q effect - --disable-force-update do not force helm repos to update when executing "helm repo add" - --enable-live-output Show live output from the Helm binary Stdout/Stderr into Helmfile own Stdout/Stderr. - It only applies for the Helm CLI commands, Stdout/Stderr for Hooks are still displayed only when it's execution finishes. - -e, --environment string specify the environment name. Overrides "HELMFILE_ENVIRONMENT" OS environment variable when specified. defaults to "default" - -f, --file helmfile.yaml load config from file or directory. defaults to "helmfile.yaml" or "helmfile.yaml.gotmpl" or "helmfile.d" (means "helmfile.d/*.yaml" or "helmfile.d/*.yaml.gotmpl") in this preference. Specify - to load the config from the standard input. - -b, --helm-binary string Path to the helm binary (default "helm") - -h, --help help for helmfile - -i, --interactive Request confirmation before attempting to modify clusters - --kube-context string Set kubectl context. Uses current context by default - -k, --kustomize-binary string Path to the kustomize binary (default "kustomize") - --log-level string Set log level, default info (default "info") - -n, --namespace string Set namespace. Uses the namespace set in the context by default, and is available in templates as {{ .Namespace }} - --no-color Output without color - -q, --quiet Silence output. Equivalent to log-level warn - -l, --selector stringArray Only run using the releases that match labels. Labels can take the form of foo=bar or foo!=bar. - A release must match all labels in a group in order to be used. Multiple groups can be specified at once. - "--selector tier=frontend,tier!=proxy --selector tier=backend" will match all frontend, non-proxy releases AND all backend releases. - The name of a release can be used as a label: "--selector name=myrelease" - --skip-deps skip running "helm repo update" and "helm dependency build" - --state-values-file stringArray specify state values in a YAML file. Used to override .Values within the helmfile template (not values template). - --state-values-set stringArray set state values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template). - --strip-args-values-on-exit-error Strip the potential secret values of the helm command args contained in a helmfile error message (default true) - -v, --version version for helmfile + --allow-no-matching-release Do not exit with an error code if the provided selector has no matching releases. + -c, --chart string Set chart. Uses the chart set in release by default, and is available in template as {{ .Chart }} + --color Output with color + --debug Enable verbose output for Helm and set log-level to debug, this disables --quiet/-q effect + --disable-force-update do not force helm repos to update when executing "helm repo add" + --enable-live-output Show live output from the Helm binary Stdout/Stderr into Helmfile own Stdout/Stderr. + It only applies for the Helm CLI commands, Stdout/Stderr for Hooks are still displayed only when it's execution finishes. + -e, --environment string specify the environment name. Overrides "HELMFILE_ENVIRONMENT" OS environment variable when specified. defaults to "default" + -f, --file helmfile.yaml load config from file or directory. defaults to "helmfile.yaml" or "helmfile.yaml.gotmpl" or "helmfile.d" (means "helmfile.d/*.yaml" or "helmfile.d/*.yaml.gotmpl") in this preference. Specify - to load the config from the standard input. + -b, --helm-binary string Path to the helm binary (default "helm") + -h, --help help for helmfile + -i, --interactive Request confirmation before attempting to modify clusters + --kube-context string Set kubectl context. Uses current context by default + -k, --kustomize-binary string Path to the kustomize binary (default "kustomize") + --log-level string Set log level, default info (default "info") + -n, --namespace string Set namespace. Uses the namespace set in the context by default, and is available in templates as {{ .Namespace }} + --no-color Output without color + -q, --quiet Silence output. Equivalent to log-level warn + -l, --selector stringArray Only run using the releases that match labels. Labels can take the form of foo=bar or foo!=bar. + A release must match all labels in a group in order to be used. Multiple groups can be specified at once. + "--selector tier=frontend,tier!=proxy --selector tier=backend" will match all frontend, non-proxy releases AND all backend releases. + The name of a release can be used as a label: "--selector name=myrelease" + --skip-deps skip running "helm repo update" and "helm dependency build" + --state-values-file stringArray specify state values in a YAML file. Used to override .Values within the helmfile template (not values template). + --state-values-set stringArray set state values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template). + --state-values-set-string stringArray set state STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template). + --strip-args-values-on-exit-error Strip the potential secret values of the helm command args contained in a helmfile error message (default true) + -v, --version version for helmfile Use "helmfile [command] --help" for more information about a command. ``` diff --git a/pkg/app/app.go b/pkg/app/app.go index 1b983a96..9edfa166 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -1352,18 +1352,19 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, bool, []error) { detailedExitCode := true diffOpts := &state.DiffOpts{ - Color: c.Color(), - NoColor: c.NoColor(), - Context: c.Context(), - Output: c.DiffOutput(), - Set: c.Set(), - SkipCleanup: c.RetainValuesFiles() || c.SkipCleanup(), - SkipDiffOnInstall: c.SkipDiffOnInstall(), - ReuseValues: c.ReuseValues(), - ResetValues: c.ResetValues(), - DiffArgs: c.DiffArgs(), - PostRenderer: c.PostRenderer(), - PostRendererArgs: c.PostRendererArgs(), + Color: c.Color(), + NoColor: c.NoColor(), + Context: c.Context(), + Output: c.DiffOutput(), + Set: c.Set(), + SkipCleanup: c.RetainValuesFiles() || c.SkipCleanup(), + SkipDiffOnInstall: c.SkipDiffOnInstall(), + ReuseValues: c.ReuseValues(), + ResetValues: c.ResetValues(), + DiffArgs: c.DiffArgs(), + PostRenderer: c.PostRenderer(), + PostRendererArgs: c.PostRendererArgs(), + SuppressOutputLineRegex: c.SuppressOutputLineRegex(), } infoMsg, releasesToBeUpdated, releasesToBeDeleted, errs := r.diff(false, detailedExitCode, c, diffOpts) @@ -1589,17 +1590,18 @@ func (a *App) diff(r *Run, c DiffConfigProvider) (*string, bool, bool, []error) helm.SetExtraArgs(GetArgs(c.Args(), r.state)...) opts := &state.DiffOpts{ - Context: c.Context(), - Output: c.DiffOutput(), - Color: c.Color(), - NoColor: c.NoColor(), - Set: c.Set(), - DiffArgs: c.DiffArgs(), - SkipDiffOnInstall: c.SkipDiffOnInstall(), - ReuseValues: c.ReuseValues(), - ResetValues: c.ResetValues(), - PostRenderer: c.PostRenderer(), - PostRendererArgs: c.PostRendererArgs(), + Context: c.Context(), + Output: c.DiffOutput(), + Color: c.Color(), + NoColor: c.NoColor(), + Set: c.Set(), + DiffArgs: c.DiffArgs(), + SkipDiffOnInstall: c.SkipDiffOnInstall(), + ReuseValues: c.ReuseValues(), + ResetValues: c.ResetValues(), + PostRenderer: c.PostRenderer(), + PostRendererArgs: c.PostRendererArgs(), + SuppressOutputLineRegex: c.SuppressOutputLineRegex(), } filtered := &Run{ diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index 46b2a141..91adcbe9 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -2197,37 +2197,38 @@ type applyConfig struct { // TODO: Remove this function once Helmfile v0.x retainValuesFiles bool - set []string - validate bool - skipCleanup bool - skipCRDs bool - skipDeps bool - skipNeeds bool - includeNeeds bool - includeTransitiveNeeds bool - includeTests bool - suppress []string - suppressSecrets bool - showSecrets bool - noHooks bool - suppressDiff bool - noColor bool - color bool - context int - diffOutput string - concurrency int - detailedExitcode bool - stripTrailingCR bool - interactive bool - skipDiffOnInstall bool - diffArgs string - logger *zap.SugaredLogger - wait bool - waitForJobs bool - reuseValues bool - postRenderer string - postRendererArgs []string - kubeVersion string + set []string + validate bool + skipCleanup bool + skipCRDs bool + skipDeps bool + skipNeeds bool + includeNeeds bool + includeTransitiveNeeds bool + includeTests bool + suppress []string + suppressSecrets bool + showSecrets bool + noHooks bool + suppressDiff bool + noColor bool + color bool + context int + diffOutput string + concurrency int + detailedExitcode bool + stripTrailingCR bool + interactive bool + skipDiffOnInstall bool + diffArgs string + logger *zap.SugaredLogger + wait bool + waitForJobs bool + reuseValues bool + postRenderer string + postRendererArgs []string + kubeVersion string + suppressOutputLineRegex []string // template-only options includeCRDs, skipTests bool @@ -2392,6 +2393,10 @@ func (a applyConfig) PostRendererArgs() []string { return a.postRendererArgs } +func (a applyConfig) SuppressOutputLineRegex() []string { + return a.suppressOutputLineRegex +} + func (a applyConfig) KubeVersion() string { return a.kubeVersion } diff --git a/pkg/app/config.go b/pkg/app/config.go index 47499e56..193b997e 100644 --- a/pkg/app/config.go +++ b/pkg/app/config.go @@ -50,6 +50,7 @@ type ApplyConfigProvider interface { PostRenderer() string PostRendererArgs() []string Cascade() string + SuppressOutputLineRegex() []string Values() []string Set() []string @@ -121,6 +122,7 @@ type DiffConfigProvider interface { Args() string PostRenderer() string PostRendererArgs() []string + SuppressOutputLineRegex() []string Values() []string Set() []string diff --git a/pkg/app/diff_test.go b/pkg/app/diff_test.go index 7400dd3e..c390c21d 100644 --- a/pkg/app/diff_test.go +++ b/pkg/app/diff_test.go @@ -16,33 +16,34 @@ import ( ) type diffConfig struct { - args string - diffArgs string - values []string - retainValuesFiles bool - set []string - validate bool - skipCRDs bool - skipDeps bool - includeTests bool - skipNeeds bool - includeNeeds bool - includeTransitiveNeeds bool - suppress []string - suppressSecrets bool - showSecrets bool - noHooks bool - suppressDiff bool - noColor bool - context int - diffOutput string - concurrency int - detailedExitcode bool - stripTrailingCR bool - interactive bool - skipDiffOnInstall bool - reuseValues bool - logger *zap.SugaredLogger + args string + diffArgs string + values []string + retainValuesFiles bool + set []string + validate bool + skipCRDs bool + skipDeps bool + includeTests bool + skipNeeds bool + includeNeeds bool + includeTransitiveNeeds bool + suppress []string + suppressSecrets bool + showSecrets bool + noHooks bool + suppressDiff bool + suppressOutputLineRegex []string + noColor bool + context int + diffOutput string + concurrency int + detailedExitcode bool + stripTrailingCR bool + interactive bool + skipDiffOnInstall bool + reuseValues bool + logger *zap.SugaredLogger } func (a diffConfig) Args() string { @@ -169,6 +170,10 @@ func (a diffConfig) PostRendererArgs() []string { return nil } +func (a diffConfig) SuppressOutputLineRegex() []string { + return a.suppressOutputLineRegex +} + func TestDiff(t *testing.T) { type flags struct { skipNeeds bool diff --git a/pkg/config/apply.go b/pkg/config/apply.go index 568e0893..d26a9dd1 100644 --- a/pkg/config/apply.go +++ b/pkg/config/apply.go @@ -62,6 +62,8 @@ type ApplyOptions struct { PostRendererArgs []string // Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background Cascade string + // SuppressOutputLineRegex is a list of regexes to suppress output lines + SuppressOutputLineRegex []string } // NewApply creates a new Apply @@ -233,3 +235,8 @@ func (a *ApplyImpl) PostRendererArgs() []string { func (a *ApplyImpl) Cascade() string { return a.ApplyOptions.Cascade } + +// SuppressOutputLineRegex returns the SuppressOutputLineRegex. +func (a *ApplyImpl) SuppressOutputLineRegex() []string { + return a.ApplyOptions.SuppressOutputLineRegex +} diff --git a/pkg/config/diff.go b/pkg/config/diff.go index be1d24cc..0fe525e8 100644 --- a/pkg/config/diff.go +++ b/pkg/config/diff.go @@ -46,6 +46,8 @@ type DiffOptions struct { PostRendererArgs []string // DiffArgs is the list of arguments to pass to helm-diff. DiffArgs string + // SuppressOutputLineRegex is a list of regexes to suppress output lines + SuppressOutputLineRegex []string } // NewDiffOptions creates a new Apply @@ -192,3 +194,8 @@ func (t *DiffImpl) PostRenderer() string { func (t *DiffImpl) PostRendererArgs() []string { return t.DiffOptions.PostRendererArgs } + +// SuppressOutputLineRegex returns the SuppressOutputLineRegex. +func (t *DiffImpl) SuppressOutputLineRegex() []string { + return t.DiffOptions.SuppressOutputLineRegex +} diff --git a/pkg/state/helmx.go b/pkg/state/helmx.go index 86447f7e..dc7f4712 100644 --- a/pkg/state/helmx.go +++ b/pkg/state/helmx.go @@ -41,24 +41,37 @@ func (st *HelmState) appendPostRenderFlags(flags []string, release *ReleaseSpec, // append post-renderer-args flags to helm flags func (st *HelmState) appendPostRenderArgsFlags(flags []string, release *ReleaseSpec, postRendererArgs []string) []string { + postRendererArgsFlags := []string{} switch { case len(release.PostRendererArgs) != 0: - for _, arg := range release.PostRendererArgs { - if arg != "" { - flags = append(flags, "--post-renderer-args", arg) - } - } + postRendererArgsFlags = release.PostRendererArgs case len(postRendererArgs) != 0: - for _, arg := range postRendererArgs { - if arg != "" { - flags = append(flags, "--post-renderer-args", arg) - } - } + postRendererArgsFlags = postRendererArgs case len(st.HelmDefaults.PostRendererArgs) != 0: - for _, arg := range st.HelmDefaults.PostRendererArgs { - if arg != "" { - flags = append(flags, "--post-renderer-args", arg) - } + postRendererArgsFlags = st.HelmDefaults.PostRendererArgs + } + for _, arg := range postRendererArgsFlags { + if arg != "" { + flags = append(flags, "--post-renderer-args", arg) + } + } + return flags +} + +// append suppress-output-line-regex flags to helm diff flags +func (st *HelmState) appendSuppressOutputLineRegexFlags(flags []string, release *ReleaseSpec, suppressOutputLineRegex []string) []string { + suppressOutputLineRegexFlags := []string{} + switch { + case len(release.SuppressOutputLineRegex) != 0: + suppressOutputLineRegexFlags = release.SuppressOutputLineRegex + case len(suppressOutputLineRegex) != 0: + suppressOutputLineRegexFlags = suppressOutputLineRegex + case len(st.HelmDefaults.SuppressOutputLineRegex) != 0: + suppressOutputLineRegexFlags = st.HelmDefaults.SuppressOutputLineRegex + } + for _, arg := range suppressOutputLineRegexFlags { + if arg != "" { + flags = append(flags, "--suppress-output-line-regex", arg) } } return flags diff --git a/pkg/state/helmx_test.go b/pkg/state/helmx_test.go index b3dbc171..74a7ba69 100644 --- a/pkg/state/helmx_test.go +++ b/pkg/state/helmx_test.go @@ -197,3 +197,55 @@ func TestAppendCascadeFlags(t *testing.T) { }) } } +func TestAppendSuppressOutputLineRegexFlags(t *testing.T) { + tests := []struct { + name string + flags []string + release *ReleaseSpec + suppressOutputLineRegex []string + helmDefaults HelmSpec + expected []string + }{ + { + name: "release suppress output line regex", + flags: []string{}, + release: &ReleaseSpec{SuppressOutputLineRegex: []string{"regex1", "regex2"}}, + suppressOutputLineRegex: nil, + helmDefaults: HelmSpec{}, + expected: []string{"--suppress-output-line-regex", "regex1", "--suppress-output-line-regex", "regex2"}, + }, + { + name: "cmd suppress output line regex", + flags: []string{}, + release: &ReleaseSpec{}, + suppressOutputLineRegex: []string{"regex1", "regex2"}, + helmDefaults: HelmSpec{}, + expected: []string{"--suppress-output-line-regex", "regex1", "--suppress-output-line-regex", "regex2"}, + }, + { + name: "helm defaults suppress output line regex", + flags: []string{}, + release: &ReleaseSpec{}, + suppressOutputLineRegex: nil, + helmDefaults: HelmSpec{SuppressOutputLineRegex: []string{"regex1", "regex2"}}, + expected: []string{"--suppress-output-line-regex", "regex1", "--suppress-output-line-regex", "regex2"}, + }, + { + name: "empty suppress output line regex", + flags: []string{}, + release: &ReleaseSpec{}, + suppressOutputLineRegex: nil, + helmDefaults: HelmSpec{}, + expected: []string{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + st := &HelmState{} + st.HelmDefaults = tt.helmDefaults + got := st.appendSuppressOutputLineRegexFlags(tt.flags, tt.release, tt.suppressOutputLineRegex) + require.Equalf(t, tt.expected, got, "appendSuppressOutputLineRegexFlags() = %v, want %v", got, tt.expected) + }) + } +} diff --git a/pkg/state/state.go b/pkg/state/state.go index 4adb8aca..4070bcdb 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -188,6 +188,8 @@ type HelmSpec struct { PostRendererArgs []string `yaml:"postRendererArgs,omitempty"` // Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background Cascade *string `yaml:"cascade,omitempty"` + // SuppressOutputLineRegex is a list of regexes to suppress output lines + SuppressOutputLineRegex []string `yaml:"suppressOutputLineRegex,omitempty"` DisableValidation *bool `yaml:"disableValidation,omitempty"` DisableOpenAPIValidation *bool `yaml:"disableOpenAPIValidation,omitempty"` @@ -370,6 +372,9 @@ type ReleaseSpec struct { // Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background Cascade *string `yaml:"cascade,omitempty"` + // SuppressOutputLineRegex is a list of regexes to suppress output lines + SuppressOutputLineRegex []string `yaml:"suppressOutputLineRegex,omitempty"` + // Inherit is used to inherit a release template from a release or another release template Inherit Inherits `yaml:"inherit,omitempty"` @@ -1710,6 +1715,7 @@ type diffPrepareResult struct { suppressDiff bool } +// commonDiffFlags returns common flags for helm diff, not in release-specific context func (st *HelmState) commonDiffFlags(detailedExitCode bool, stripTrailingCR bool, includeTests bool, suppress []string, suppressSecrets bool, showSecrets bool, noHooks bool, opt *DiffOpts) []string { var flags []string @@ -1762,6 +1768,7 @@ func (st *HelmState) commonDiffFlags(detailedExitCode bool, stripTrailingCR bool flags = append(flags, "--set", s) } } + flags = st.appendExtraDiffFlags(flags, opt) return flags } @@ -1850,6 +1857,7 @@ func (st *HelmState) prepareDiffReleases(helm helmexec.Interface, additionalValu // TODO We need a long-term fix for this :) // See https://github.com/roboll/helmfile/issues/737 mut.Lock() + // release level diff flags in here flags, files, err := st.flagsForDiff(helm, release, disableValidation, workerIndex, opt) mut.Unlock() if err != nil { @@ -1935,15 +1943,16 @@ type DiffOpts struct { Color bool // NoColor forces disabling the color output on helm-diff. // If this is true, Color has no effect. - NoColor bool - Set []string - SkipCleanup bool - SkipDiffOnInstall bool - DiffArgs string - ReuseValues bool - ResetValues bool - PostRenderer string - PostRendererArgs []string + NoColor bool + Set []string + SkipCleanup bool + SkipDiffOnInstall bool + DiffArgs string + ReuseValues bool + ResetValues bool + PostRenderer string + PostRendererArgs []string + SuppressOutputLineRegex []string } func (o *DiffOpts) Apply(opts *DiffOpts) { @@ -2494,6 +2503,10 @@ func (st *HelmState) appendConnectionFlags(flags []string, release *ReleaseSpec) return flags } +// appendExtraDiffFlags appends extra diff flags to the given flags slice based on the provided options. +// If opt is not nil and opt.DiffArgs is not empty, it collects the arguments from opt.DiffArgs and appends them to flags. +// If st.HelmDefaults.DiffArgs is not nil, it joins the arguments with a space and appends them to flags. +// The updated flags slice is returned. func (st *HelmState) appendExtraDiffFlags(flags []string, opt *DiffOpts) []string { switch { case opt != nil && opt.DiffArgs != "": @@ -2697,10 +2710,9 @@ func (st *HelmState) flagsForDiff(helm helmexec.Interface, release *ReleaseSpec, if diffVersion.LessThan(dv) { return nil, nil, fmt.Errorf("insecureSkipTLSVerify is not supported by helm-diff plugin version %s, please use at least v3.8.1", diffVersion) } + flags = st.appendChartDownloadTLSFlags(flags, release) } - flags = st.appendChartDownloadTLSFlags(flags, release) - flags = st.appendHelmXFlags(flags, release) postRenderer := "" @@ -2709,17 +2721,33 @@ func (st *HelmState) flagsForDiff(helm helmexec.Interface, release *ReleaseSpec, } flags = st.appendPostRenderFlags(flags, release, postRenderer) - var postRendererArgs []string + postRendererArgs := []string{} if opt != nil { postRendererArgs = opt.PostRendererArgs } flags = st.appendPostRenderArgsFlags(flags, release, postRendererArgs) + suppressOutputLineRegex := []string{} + if opt != nil { + suppressOutputLineRegex = opt.SuppressOutputLineRegex + } + if len(suppressOutputLineRegex) > 0 || len(st.HelmDefaults.SuppressOutputLineRegex) > 0 || len(release.SuppressOutputLineRegex) > 0 { + diffVersion, err := helmexec.GetPluginVersion("diff", settings.PluginsDirectory) + if err != nil { + return nil, nil, err + } + dv, _ := semver.NewVersion("v3.9.0") + + if diffVersion.LessThan(dv) { + return nil, nil, fmt.Errorf("suppressOutputLineRegex is not supported by helm-diff plugin version %s, please use at least v3.9.0", diffVersion) + } + flags = st.appendSuppressOutputLineRegexFlags(flags, release, suppressOutputLineRegex) + } + common, files, err := st.namespaceAndValuesFlags(helm, release, workerIndex) if err != nil { return nil, files, err } - flags = st.appendExtraDiffFlags(flags, opt) return append(flags, common...), files, nil } diff --git a/pkg/state/temp_test.go b/pkg/state/temp_test.go index e89747da..5dc63056 100644 --- a/pkg/state/temp_test.go +++ b/pkg/state/temp_test.go @@ -38,39 +38,39 @@ func TestGenerateID(t *testing.T) { run(testcase{ subject: "baseline", release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, - want: "foo-values-b5df4fc58", + want: "foo-values-85888d5bcb", }) run(testcase{ subject: "different bytes content", release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, data: []byte(`{"k":"v"}`), - want: "foo-values-5bd95d98d5", + want: "foo-values-77d5b4b567", }) run(testcase{ subject: "different map content", release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, data: map[string]any{"k": "v"}, - want: "foo-values-5cb8d75d9f", + want: "foo-values-6b5c7d665c", }) run(testcase{ subject: "different chart", release: ReleaseSpec{Name: "foo", Chart: "stable/envoy"}, - want: "foo-values-5f6b44cff5", + want: "foo-values-5b86b7bc7", }) run(testcase{ subject: "different name", release: ReleaseSpec{Name: "bar", Chart: "incubator/raw"}, - want: "bar-values-546889667f", + want: "bar-values-bcb888989", }) run(testcase{ subject: "specific ns", release: ReleaseSpec{Name: "foo", Chart: "incubator/raw", Namespace: "myns"}, - want: "myns-foo-values-78f4c8794f", + want: "myns-foo-values-7599b8cdcf", }) for id, n := range ids { diff --git a/test/integration/lib/version.sh b/test/integration/lib/version.sh new file mode 100644 index 00000000..f873071c --- /dev/null +++ b/test/integration/lib/version.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; } +function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" == "$1"; } +function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; } +function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; } \ No newline at end of file diff --git a/test/integration/run.sh b/test/integration/run.sh index e4812991..4c16aead 100755 --- a/test/integration/run.sh +++ b/test/integration/run.sh @@ -12,6 +12,7 @@ if [[ ! -d "${dir}" ]]; then dir="${PWD}"; fi . "${dir}/lib/output.sh" . "${dir}/lib/ensure.sh" +. "${dir}/lib/version.sh" # GLOBALS ----------------------------------------------------------------------------------------------------------- @@ -76,6 +77,7 @@ ${kubectl} create namespace ${test_ns} || fail "Could not create namespace ${tes # TEST CASES---------------------------------------------------------------------------------------------------------- +. ${dir}/test-cases/suppress-output-line-regex.sh . ${dir}/test-cases/include-template-func.sh . ${dir}/test-cases/happypath.sh . ${dir}/test-cases/chartify-with-non-chart-dir.sh diff --git a/test/integration/test-cases/suppress-output-line-regex.sh b/test/integration/test-cases/suppress-output-line-regex.sh new file mode 100644 index 00000000..e7ebdb62 --- /dev/null +++ b/test/integration/test-cases/suppress-output-line-regex.sh @@ -0,0 +1,34 @@ +suppress_output_line_regex_input_dir="${cases_dir}/suppress-output-line-regex/input" +suppress_output_line_regex_output_dir="${cases_dir}/suppress-output-line-regex/output" + +suppress_output_line_regex_tmp=$(mktemp -d) +suppress_output_line_regex_reverse=${suppress_output_line_regex_tmp}/diff.args.build.yaml + +case_title="suppress output line regex" +diff_out_file=${suppress_output_line_regex_output_dir}/diff +if [[ $EXTRA_HELMFILE_FLAGS == *--enable-live-output* ]]; then + diff_out_file=${suppress_output_line_regex_output_dir}/diff-live +fi + +if version_lt $HELM_DIFF_VERSION "3.9.0"; then + echo "Skipping ${case_title} because helm-diff version is less than 3.9.0" +else + test_start "$case_title" + info "sync ${case_title} with default version" + ${helmfile} -f ${suppress_output_line_regex_input_dir}/helmfile.yaml.gotmpl sync || fail "\"helmfile sync\" shouldn't fail" + + info "Comparing ${case_title} diff for output ${suppress_output_line_regex_reverse} with ${diff_out_file}" + export SUPPRESS_OUTPUT_LINE_REGEX_INGRESS_NGINX_VERSION="4.9.0" + + for i in $(seq 10); do + info "Comparing suppress-output-line-regex diff log #$i" + ${helmfile} -f ${suppress_output_line_regex_input_dir}/helmfile.yaml.gotmpl diff > ${suppress_output_line_regex_reverse} || fail "\"helmfile diff\" shouldn't fail" + diff -u ${diff_out_file} ${suppress_output_line_regex_reverse} || fail "\"helmfile diff\" should be consistent" + echo code=$? + done + unset SUPPRESS_OUTPUT_LINE_REGEX_INGRESS_NGINX_VERSION + + echo "clean up ${case_title} resources" + ${helmfile} -f ${suppress_output_line_regex_input_dir}/helmfile.yaml.gotmpl destroy || fail "\"helmfile destroy\" shouldn't fail" + test_pass "$case_title" +fi \ No newline at end of file diff --git a/test/integration/test-cases/suppress-output-line-regex/input/helmfile.yaml.gotmpl b/test/integration/test-cases/suppress-output-line-regex/input/helmfile.yaml.gotmpl new file mode 100644 index 00000000..634a5f76 --- /dev/null +++ b/test/integration/test-cases/suppress-output-line-regex/input/helmfile.yaml.gotmpl @@ -0,0 +1,14 @@ +helmDefaults: + suppressOutputLineRegex: + - "helm.sh/chart" + - "app.kubernetes.io/version" + +repositories: +- name: ingress-nginx + url: https://kubernetes.github.io/ingress-nginx + +releases: +- name: ingress-nginx + namespace: ingress-nginx + chart: ingress-nginx/ingress-nginx + version: {{ env "SUPPRESS_OUTPUT_LINE_REGEX_INGRESS_NGINX_VERSION" | default "4.8.3" }} \ No newline at end of file diff --git a/test/integration/test-cases/suppress-output-line-regex/output/diff b/test/integration/test-cases/suppress-output-line-regex/output/diff new file mode 100644 index 00000000..a9cdfdb6 --- /dev/null +++ b/test/integration/test-cases/suppress-output-line-regex/output/diff @@ -0,0 +1,530 @@ +Comparing release=ingress-nginx, chart=ingress-nginx/ingress-nginx +helmfile-tests, ingress-nginx, ClusterRole (rbac.authorization.k8s.io) has changed: +helmfile-tests, ingress-nginx, ClusterRoleBinding (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/clusterrolebinding.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + name: ingress-nginx + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-nginx + subjects: + - kind: ServiceAccount + name: ingress-nginx +- namespace: "helmfile-tests" ++ namespace: helmfile-tests +helmfile-tests, ingress-nginx, Role (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/controller-role.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: controller + name: ingress-nginx + namespace: helmfile-tests + rules: + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + - endpoints + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch ++ # Omit Ingress status permissions if `--update-status` is disabled. + - apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update + - apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + resourceNames: + - ingress-nginx-leader + verbs: + - get + - update + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +helmfile-tests, ingress-nginx, RoleBinding (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/controller-rolebinding.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: controller + name: ingress-nginx + namespace: helmfile-tests + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-nginx + subjects: + - kind: ServiceAccount + name: ingress-nginx +- namespace: "helmfile-tests" ++ namespace: helmfile-tests +helmfile-tests, ingress-nginx, ServiceAccount (v1) has changed: +helmfile-tests, ingress-nginx-admission, ClusterRole (rbac.authorization.k8s.io) has changed: +helmfile-tests, ingress-nginx-admission, ClusterRoleBinding (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + name: ingress-nginx-admission + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-nginx-admission + subjects: + - kind: ServiceAccount + name: ingress-nginx-admission +- namespace: "helmfile-tests" ++ namespace: helmfile-tests +helmfile-tests, ingress-nginx-admission, Role (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/admission-webhooks/job-patch/role.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: +- name: ingress-nginx-admission ++ name: ingress-nginx-admission + namespace: helmfile-tests + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - create +helmfile-tests, ingress-nginx-admission, RoleBinding (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: ingress-nginx-admission + namespace: helmfile-tests + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-nginx-admission + subjects: + - kind: ServiceAccount + name: ingress-nginx-admission +- namespace: "helmfile-tests" ++ namespace: helmfile-tests +helmfile-tests, ingress-nginx-admission, ServiceAccount (v1) has changed: +helmfile-tests, ingress-nginx-admission, ValidatingWebhookConfiguration (admissionregistration.k8s.io) has changed: + # Source: ingress-nginx/templates/admission-webhooks/validating-webhook.yaml + # before changing this value, check the required kubernetes version + # https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#prerequisites + apiVersion: admissionregistration.k8s.io/v1 + kind: ValidatingWebhookConfiguration + metadata: + annotations: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + name: ingress-nginx-admission + webhooks: + - name: validate.nginx.ingress.kubernetes.io + matchPolicy: Equivalent + rules: + - apiGroups: + - networking.k8s.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - ingresses + failurePolicy: Fail + sideEffects: None + admissionReviewVersions: + - v1 + clientConfig: + service: +- namespace: "helmfile-tests" + name: ingress-nginx-controller-admission ++ namespace: helmfile-tests + path: /networking/v1/ingresses +helmfile-tests, ingress-nginx-admission-create, Job (batch) has changed: + # Source: ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml + apiVersion: batch/v1 + kind: Job + metadata: + name: ingress-nginx-admission-create + namespace: helmfile-tests + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + spec: + template: + metadata: + name: ingress-nginx-admission-create + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + spec: + containers: + - name: create +- image: "registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231011-8b53cabe0@sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80" ++ image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231011-8b53cabe0@sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80 + imagePullPolicy: IfNotPresent + args: + - create + - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc + - --namespace=$(POD_NAMESPACE) + - --secret-name=ingress-nginx-admission + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + securityContext: + allowPrivilegeEscalation: false ++ capabilities: ++ drop: ++ - ALL ++ readOnlyRootFilesystem: true ++ runAsNonRoot: true ++ runAsUser: 65532 ++ seccompProfile: ++ type: RuntimeDefault + restartPolicy: OnFailure + serviceAccountName: ingress-nginx-admission + nodeSelector: + kubernetes.io/os: linux +- securityContext: +- fsGroup: 2000 +- runAsNonRoot: true +- runAsUser: 2000 +helmfile-tests, ingress-nginx-admission-patch, Job (batch) has changed: + # Source: ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml + apiVersion: batch/v1 + kind: Job + metadata: + name: ingress-nginx-admission-patch + namespace: helmfile-tests + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + spec: + template: + metadata: + name: ingress-nginx-admission-patch + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + spec: + containers: + - name: patch +- image: "registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231011-8b53cabe0@sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80" ++ image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231011-8b53cabe0@sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80 + imagePullPolicy: IfNotPresent + args: + - patch + - --webhook-name=ingress-nginx-admission + - --namespace=$(POD_NAMESPACE) + - --patch-mutating=false + - --secret-name=ingress-nginx-admission + - --patch-failure-policy=Fail + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + securityContext: + allowPrivilegeEscalation: false ++ capabilities: ++ drop: ++ - ALL ++ readOnlyRootFilesystem: true ++ runAsNonRoot: true ++ runAsUser: 65532 ++ seccompProfile: ++ type: RuntimeDefault + restartPolicy: OnFailure + serviceAccountName: ingress-nginx-admission + nodeSelector: + kubernetes.io/os: linux +- securityContext: +- fsGroup: 2000 +- runAsNonRoot: true +- runAsUser: 2000 +helmfile-tests, ingress-nginx-controller, ConfigMap (v1) has changed: +helmfile-tests, ingress-nginx-controller, Deployment (apps) has changed: + # Source: ingress-nginx/templates/controller-deployment.yaml + apiVersion: apps/v1 + kind: Deployment + metadata: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: controller + name: ingress-nginx-controller + namespace: helmfile-tests + spec: + selector: + matchLabels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/component: controller + replicas: 1 + revisionHistoryLimit: 10 + minReadySeconds: 0 + template: + metadata: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: controller + spec: + dnsPolicy: ClusterFirst + containers: + - name: controller +- image: "registry.k8s.io/ingress-nginx/controller:v1.9.4@sha256:5b161f051d017e55d358435f295f5e9a297e66158f136321d9b04520ec6c48a3" ++ image: registry.k8s.io/ingress-nginx/controller:v1.9.5@sha256:b3aba22b1da80e7acfc52b115cae1d4c687172cbf2b742d5b502419c25ff340e + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - /wait-shutdown +- args: ++ args: + - /nginx-ingress-controller + - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller + - --election-id=ingress-nginx-leader + - --controller-class=k8s.io/ingress-nginx + - --ingress-class=nginx + - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller + - --validating-webhook=:8443 + - --validating-webhook-certificate=/usr/local/certificates/cert + - --validating-webhook-key=/usr/local/certificates/key + securityContext: ++ runAsNonRoot: true ++ runAsUser: 101 ++ allowPrivilegeEscalation: false ++ seccompProfile: ++ type: RuntimeDefault + capabilities: + drop: + - ALL + add: + - NET_BIND_SERVICE +- runAsUser: 101 +- allowPrivilegeEscalation: true ++ readOnlyRootFilesystem: false + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: LD_PRELOAD + value: /usr/local/lib/libmimalloc.so + livenessProbe: + failureThreshold: 5 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + ports: + - name: http + containerPort: 80 + protocol: TCP + - name: https + containerPort: 443 + protocol: TCP + - name: webhook + containerPort: 8443 + protocol: TCP + volumeMounts: + - name: webhook-cert + mountPath: /usr/local/certificates/ + readOnly: true + resources: + requests: + cpu: 100m + memory: 90Mi + nodeSelector: + kubernetes.io/os: linux + serviceAccountName: ingress-nginx + terminationGracePeriodSeconds: 300 + volumes: + - name: webhook-cert + secret: + secretName: ingress-nginx-admission +helmfile-tests, ingress-nginx-controller, Service (v1) has changed: +helmfile-tests, ingress-nginx-controller-admission, Service (v1) has changed: +helmfile-tests, nginx, IngressClass (networking.k8s.io) has changed: +helmfile-tests, ingress-nginx-admission, NetworkPolicy (networking.k8s.io) has been removed: +- # Source: ingress-nginx/templates/admission-webhooks/job-patch/networkpolicy.yaml +- apiVersion: networking.k8s.io/v1 +- kind: NetworkPolicy +- metadata: +- name: ingress-nginx-admission +- namespace: helmfile-tests +- annotations: +- "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade +- "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +- labels: +- app.kubernetes.io/name: ingress-nginx +- app.kubernetes.io/instance: ingress-nginx +- app.kubernetes.io/part-of: ingress-nginx +- app.kubernetes.io/managed-by: Helm +- app.kubernetes.io/component: admission-webhook +- spec: +- podSelector: +- matchLabels: +- app.kubernetes.io/name: ingress-nginx +- app.kubernetes.io/instance: ingress-nginx +- app.kubernetes.io/component: admission-webhook +- policyTypes: +- - Ingress +- - Egress +- egress: +- - {} ++ + diff --git a/test/integration/test-cases/suppress-output-line-regex/output/diff-live b/test/integration/test-cases/suppress-output-line-regex/output/diff-live new file mode 100644 index 00000000..d072ee39 --- /dev/null +++ b/test/integration/test-cases/suppress-output-line-regex/output/diff-live @@ -0,0 +1,530 @@ +"ingress-nginx" has been added to your repositories +helmfile-tests, ingress-nginx, ClusterRole (rbac.authorization.k8s.io) has changed: +helmfile-tests, ingress-nginx, ClusterRoleBinding (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/clusterrolebinding.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + name: ingress-nginx + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-nginx + subjects: + - kind: ServiceAccount + name: ingress-nginx +- namespace: "helmfile-tests" ++ namespace: helmfile-tests +helmfile-tests, ingress-nginx, Role (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/controller-role.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: controller + name: ingress-nginx + namespace: helmfile-tests + rules: + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + - endpoints + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch ++ # Omit Ingress status permissions if `--update-status` is disabled. + - apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update + - apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - get + - list + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + resourceNames: + - ingress-nginx-leader + verbs: + - get + - update + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch + - get +helmfile-tests, ingress-nginx, RoleBinding (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/controller-rolebinding.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: controller + name: ingress-nginx + namespace: helmfile-tests + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-nginx + subjects: + - kind: ServiceAccount + name: ingress-nginx +- namespace: "helmfile-tests" ++ namespace: helmfile-tests +helmfile-tests, ingress-nginx, ServiceAccount (v1) has changed: +helmfile-tests, ingress-nginx-admission, ClusterRole (rbac.authorization.k8s.io) has changed: +helmfile-tests, ingress-nginx-admission, ClusterRoleBinding (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + name: ingress-nginx-admission + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-nginx-admission + subjects: + - kind: ServiceAccount + name: ingress-nginx-admission +- namespace: "helmfile-tests" ++ namespace: helmfile-tests +helmfile-tests, ingress-nginx-admission, Role (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/admission-webhooks/job-patch/role.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: +- name: ingress-nginx-admission ++ name: ingress-nginx-admission + namespace: helmfile-tests + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + rules: + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - create +helmfile-tests, ingress-nginx-admission, RoleBinding (rbac.authorization.k8s.io) has changed: + # Source: ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: ingress-nginx-admission + namespace: helmfile-tests + annotations: + "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-nginx-admission + subjects: + - kind: ServiceAccount + name: ingress-nginx-admission +- namespace: "helmfile-tests" ++ namespace: helmfile-tests +helmfile-tests, ingress-nginx-admission, ServiceAccount (v1) has changed: +helmfile-tests, ingress-nginx-admission, ValidatingWebhookConfiguration (admissionregistration.k8s.io) has changed: + # Source: ingress-nginx/templates/admission-webhooks/validating-webhook.yaml + # before changing this value, check the required kubernetes version + # https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#prerequisites + apiVersion: admissionregistration.k8s.io/v1 + kind: ValidatingWebhookConfiguration + metadata: + annotations: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + name: ingress-nginx-admission + webhooks: + - name: validate.nginx.ingress.kubernetes.io + matchPolicy: Equivalent + rules: + - apiGroups: + - networking.k8s.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - ingresses + failurePolicy: Fail + sideEffects: None + admissionReviewVersions: + - v1 + clientConfig: + service: +- namespace: "helmfile-tests" + name: ingress-nginx-controller-admission ++ namespace: helmfile-tests + path: /networking/v1/ingresses +helmfile-tests, ingress-nginx-admission-create, Job (batch) has changed: + # Source: ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml + apiVersion: batch/v1 + kind: Job + metadata: + name: ingress-nginx-admission-create + namespace: helmfile-tests + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + spec: + template: + metadata: + name: ingress-nginx-admission-create + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + spec: + containers: + - name: create +- image: "registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231011-8b53cabe0@sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80" ++ image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231011-8b53cabe0@sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80 + imagePullPolicy: IfNotPresent + args: + - create + - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc + - --namespace=$(POD_NAMESPACE) + - --secret-name=ingress-nginx-admission + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + securityContext: + allowPrivilegeEscalation: false ++ capabilities: ++ drop: ++ - ALL ++ readOnlyRootFilesystem: true ++ runAsNonRoot: true ++ runAsUser: 65532 ++ seccompProfile: ++ type: RuntimeDefault + restartPolicy: OnFailure + serviceAccountName: ingress-nginx-admission + nodeSelector: + kubernetes.io/os: linux +- securityContext: +- fsGroup: 2000 +- runAsNonRoot: true +- runAsUser: 2000 +helmfile-tests, ingress-nginx-admission-patch, Job (batch) has changed: + # Source: ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml + apiVersion: batch/v1 + kind: Job + metadata: + name: ingress-nginx-admission-patch + namespace: helmfile-tests + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + spec: + template: + metadata: + name: ingress-nginx-admission-patch + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: admission-webhook + spec: + containers: + - name: patch +- image: "registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231011-8b53cabe0@sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80" ++ image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231011-8b53cabe0@sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80 + imagePullPolicy: IfNotPresent + args: + - patch + - --webhook-name=ingress-nginx-admission + - --namespace=$(POD_NAMESPACE) + - --patch-mutating=false + - --secret-name=ingress-nginx-admission + - --patch-failure-policy=Fail + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + securityContext: + allowPrivilegeEscalation: false ++ capabilities: ++ drop: ++ - ALL ++ readOnlyRootFilesystem: true ++ runAsNonRoot: true ++ runAsUser: 65532 ++ seccompProfile: ++ type: RuntimeDefault + restartPolicy: OnFailure + serviceAccountName: ingress-nginx-admission + nodeSelector: + kubernetes.io/os: linux +- securityContext: +- fsGroup: 2000 +- runAsNonRoot: true +- runAsUser: 2000 +helmfile-tests, ingress-nginx-controller, ConfigMap (v1) has changed: +helmfile-tests, ingress-nginx-controller, Deployment (apps) has changed: + # Source: ingress-nginx/templates/controller-deployment.yaml + apiVersion: apps/v1 + kind: Deployment + metadata: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: controller + name: ingress-nginx-controller + namespace: helmfile-tests + spec: + selector: + matchLabels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/component: controller + replicas: 1 + revisionHistoryLimit: 10 + minReadySeconds: 0 + template: + metadata: + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/instance: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: controller + spec: + dnsPolicy: ClusterFirst + containers: + - name: controller +- image: "registry.k8s.io/ingress-nginx/controller:v1.9.4@sha256:5b161f051d017e55d358435f295f5e9a297e66158f136321d9b04520ec6c48a3" ++ image: registry.k8s.io/ingress-nginx/controller:v1.9.5@sha256:b3aba22b1da80e7acfc52b115cae1d4c687172cbf2b742d5b502419c25ff340e + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - /wait-shutdown +- args: ++ args: + - /nginx-ingress-controller + - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller + - --election-id=ingress-nginx-leader + - --controller-class=k8s.io/ingress-nginx + - --ingress-class=nginx + - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller + - --validating-webhook=:8443 + - --validating-webhook-certificate=/usr/local/certificates/cert + - --validating-webhook-key=/usr/local/certificates/key + securityContext: ++ runAsNonRoot: true ++ runAsUser: 101 ++ allowPrivilegeEscalation: false ++ seccompProfile: ++ type: RuntimeDefault + capabilities: + drop: + - ALL + add: + - NET_BIND_SERVICE +- runAsUser: 101 +- allowPrivilegeEscalation: true ++ readOnlyRootFilesystem: false + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: LD_PRELOAD + value: /usr/local/lib/libmimalloc.so + livenessProbe: + failureThreshold: 5 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + ports: + - name: http + containerPort: 80 + protocol: TCP + - name: https + containerPort: 443 + protocol: TCP + - name: webhook + containerPort: 8443 + protocol: TCP + volumeMounts: + - name: webhook-cert + mountPath: /usr/local/certificates/ + readOnly: true + resources: + requests: + cpu: 100m + memory: 90Mi + nodeSelector: + kubernetes.io/os: linux + serviceAccountName: ingress-nginx + terminationGracePeriodSeconds: 300 + volumes: + - name: webhook-cert + secret: + secretName: ingress-nginx-admission +helmfile-tests, ingress-nginx-controller, Service (v1) has changed: +helmfile-tests, ingress-nginx-controller-admission, Service (v1) has changed: +helmfile-tests, nginx, IngressClass (networking.k8s.io) has changed: +helmfile-tests, ingress-nginx-admission, NetworkPolicy (networking.k8s.io) has been removed: +- # Source: ingress-nginx/templates/admission-webhooks/job-patch/networkpolicy.yaml +- apiVersion: networking.k8s.io/v1 +- kind: NetworkPolicy +- metadata: +- name: ingress-nginx-admission +- namespace: helmfile-tests +- annotations: +- "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade +- "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +- labels: +- app.kubernetes.io/name: ingress-nginx +- app.kubernetes.io/instance: ingress-nginx +- app.kubernetes.io/part-of: ingress-nginx +- app.kubernetes.io/managed-by: Helm +- app.kubernetes.io/component: admission-webhook +- spec: +- podSelector: +- matchLabels: +- app.kubernetes.io/name: ingress-nginx +- app.kubernetes.io/instance: ingress-nginx +- app.kubernetes.io/component: admission-webhook +- policyTypes: +- - Ingress +- - Egress +- egress: +- - {} ++ +Comparing release=ingress-nginx, chart=ingress-nginx/ingress-nginx