From af4496594974ebfecb1b2ef38395e1ecb8da5e63 Mon Sep 17 00:00:00 2001 From: KUOKA Yusuke Date: Fri, 28 Feb 2020 19:39:01 +0900 Subject: [PATCH] feat: `helmfile --log-level=debug apply --retain-values-files` (#1127) `--retain-values-files` prevents temporary values files that were passed to Helm commands run by Helmfile for debugging purpose. With that, you can manually rerun helm commands that were logged when `--log-level=debug` is enabled. Resolves ##1117 --- main.go | 8 ++++++++ pkg/app/app.go | 28 ++++++++++++++++++---------- pkg/app/app_test.go | 29 +++++++++++++++++------------ pkg/app/config.go | 2 ++ pkg/app/load_opts.go | 2 ++ 5 files changed, 47 insertions(+), 22 deletions(-) diff --git a/main.go b/main.go index 163fe6a5..b7683f82 100644 --- a/main.go +++ b/main.go @@ -338,6 +338,10 @@ func main() { Value: "", Usage: "pass args to helm exec", }, + cli.BoolFlag{ + Name: "retain-values-files", + Usage: "Stop cleaning up values files passed to Helm. Together with --log-level=debug, you can manually rerun helm commands as Helmfile did for debugging purpose", + }, cli.BoolFlag{ Name: "suppress-secrets", Usage: "suppress secrets in the diff output. highly recommended to specify on CI/CD use-cases", @@ -542,6 +546,10 @@ func (c configImpl) DetailedExitcode() bool { return c.c.Bool("detailed-exitcode") } +func (c configImpl) RetainValuesFiles() bool { + return c.c.Bool("retain-values-files") +} + func (c configImpl) SuppressSecrets() bool { return c.c.Bool("suppress-secrets") } diff --git a/pkg/app/app.go b/pkg/app/app.go index 38636b49..e1e878b6 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -155,7 +155,7 @@ func (a *App) Apply(c ApplyConfigProvider) error { mut.Unlock() return matched, errs - }) + }, c.RetainValuesFiles()) if err != nil { return err @@ -343,7 +343,7 @@ func (a *App) visitStates(fileOrDir string, defOpts LoadOpts, converge func(*sta sig := <-sigs errs := []error{fmt.Errorf("Received [%s] to shutdown ", sig)} - _ = context{a, st}.clean(errs) + _ = context{app: a, st: st, retainValues: defOpts.RetainValuesFiles}.clean(errs) // See http://tldp.org/LDP/abs/html/exitcodes.html switch sig { case syscall.SIGINT: @@ -353,7 +353,7 @@ func (a *App) visitStates(fileOrDir string, defOpts LoadOpts, converge func(*sta } }() - ctx := context{a, st} + ctx := context{app: a, st: st, retainValues: defOpts.RetainValuesFiles} helm := a.helmExecer @@ -409,7 +409,7 @@ func (a *App) visitStates(fileOrDir string, defOpts LoadOpts, converge func(*sta processed, errs := converge(templated, helm) noMatchInHelmfiles = noMatchInHelmfiles && !processed - return context{a, templated}.clean(errs) + return context{app: a, st: templated, retainValues: defOpts.RetainValuesFiles}.clean(errs) }) if err != nil { @@ -434,12 +434,12 @@ func (a *App) ForEachStateFiltered(do func(*Run) []error) error { return err } -func (a *App) ForEachState(do func(*Run) (bool, []error)) error { +func (a *App) ForEachState(do func(*Run) (bool, []error), retainValues ...bool) error { ctx := NewContext() err := a.visitStatesWithSelectorsAndRemoteSupport(a.FileOrDir, func(st *state.HelmState, helm helmexec.Interface) (bool, []error) { run := NewRun(st, helm, ctx) return do(run) - }) + }, retainValues...) return err } @@ -511,11 +511,15 @@ type Opts struct { DAGEnabled bool } -func (a *App) visitStatesWithSelectorsAndRemoteSupport(fileOrDir string, converge func(*state.HelmState, helmexec.Interface) (bool, []error)) error { +func (a *App) visitStatesWithSelectorsAndRemoteSupport(fileOrDir string, converge func(*state.HelmState, helmexec.Interface) (bool, []error), retainValues ...bool) error { opts := LoadOpts{ Selectors: a.Selectors, } + if len(retainValues) > 0 { + opts.RetainValuesFiles = retainValues[0] + } + envvals := []interface{}{} if a.ValuesFiles != nil { @@ -1222,9 +1226,11 @@ func (c context) clean(errs []error) error { errs = []error{} } - cleanErrs := c.st.Clean() - if cleanErrs != nil { - errs = append(errs, cleanErrs...) + if !c.retainValues { + cleanErrs := c.st.Clean() + if cleanErrs != nil { + errs = append(errs, cleanErrs...) + } } return c.wrapErrs(errs...) @@ -1233,6 +1239,8 @@ func (c context) clean(errs []error) error { type context struct { app *App st *state.HelmState + + retainValues bool } func (c context) wrapErrs(errs ...error) error { diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index 343af86a..d91edf1d 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -1890,18 +1890,19 @@ func (c configImpl) Concurrency() int { } type applyConfig struct { - args string - values []string - set []string - skipDeps bool - suppressSecrets bool - suppressDiff bool - noColor bool - context int - concurrency int - detailedExitcode bool - interactive bool - logger *zap.SugaredLogger + args string + values []string + retainValuesFiles bool + set []string + skipDeps bool + suppressSecrets bool + suppressDiff bool + noColor bool + context int + concurrency int + detailedExitcode bool + interactive bool + logger *zap.SugaredLogger } func (a applyConfig) Args() string { @@ -1952,6 +1953,10 @@ func (a applyConfig) Logger() *zap.SugaredLogger { return a.logger } +func (a applyConfig) RetainValuesFiles() bool { + return a.retainValuesFiles +} + // Mocking the command-line runner type mockRunner struct { diff --git a/pkg/app/config.go b/pkg/app/config.go index 377d325a..bae108ba 100644 --- a/pkg/app/config.go +++ b/pkg/app/config.go @@ -48,6 +48,8 @@ type ApplyConfigProvider interface { NoColor() bool Context() int + RetainValuesFiles() bool + concurrencyConfig interactive loggingConfig diff --git a/pkg/app/load_opts.go b/pkg/app/load_opts.go index f8403d0f..3f4a9b75 100644 --- a/pkg/app/load_opts.go +++ b/pkg/app/load_opts.go @@ -9,6 +9,8 @@ type LoadOpts struct { Selectors []string Environment state.SubhelmfileEnvironmentSpec + RetainValuesFiles bool + // CalleePath is the absolute path to the file being loaded CalleePath string }