mirror of
https://github.com/helmfile/helmfile.git
synced 2026-09-30 21:30:36 +02:00
* Various U/X improvements for `helmfile apply` This improves the U/X of `helmfile apply`, by allowing you to selectively apply sub-helmfiles. When you have two or more sub-helmfiles processed, typing `n` to cancel the first doesn't automatically stop the whole helmfile execution. Instead, it proceeds by diffing the next sub-helmfile, and asks you to apply it, which should be what the user would expect. To support this workflow, I have suppressed useless exec logs, correct exit status when diff exists in sub-helmfiles but not in the parent helmfile, and made the final error message emitted by helmfile better. More concretely, this moves more output from `helm` to STDERR and the `debug` log-level. The overall output from `helmfile` should be a bit more cleaner especially for `apply`, `sync`, `diff` and perhaps other `helmfile` sub-commands, too. For example, when one of release failed, `helmfile`'s final error message now includes the error message from the failed `helm` execution, like seen in the last line: ``` List of updated releases : RELEASE CHART VERSION envoy stable/envoy 1.5.0 List of releases in error : RELEASE envoy2 in ./helmfile.yaml: in .helmfiles[0]: in /Users/c-ykuoka/helmfile/helmfile.1.yaml: failed processing release envoy2: helm exited with status 1: Error: UPGRADE FAILED: "envoy2" has no deployed releases ``` This way you can better understand what caused helmfile to finally fail. `helmfile` has been streaminig a lot of stdout and stderr contents from the `helm` commands regardless of the helmfile's log-level. It has been suppressed by default and moved to the `debug` log-level. You will see that it helps you focus on what was the cause of a failure. While working on the above, I found an another bug that made `--detailed-exitcode` useless in some case. That is, `helmfile diff --detailed-exitcode`, when any diff existed only in sub-helmfiles, has been returning an exit code of `1`. It should return `2` when any release had diff and no release had an error, regardless of the target is a sub-helmfile or a parent helmfile. Why? Because that's what `--detailed-exitcode` meant for! After this PR gets merged, `helmfile diff --detailed-exitcode` propery return exit code `2` in such cases. Fixes #543 Resolves #540
95 lines
2.4 KiB
Go
95 lines
2.4 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/roboll/helmfile/helmexec"
|
|
"github.com/roboll/helmfile/pkg/app"
|
|
"github.com/roboll/helmfile/state"
|
|
"github.com/urfave/cli"
|
|
"go.uber.org/zap"
|
|
"strings"
|
|
)
|
|
|
|
func VisitAllDesiredStates(c *cli.Context, converge func(*state.HelmState, helmexec.Interface, app.Context) (bool, []error)) error {
|
|
a, fileOrDir, err := InitAppEntry(c, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ctx := app.NewContext()
|
|
|
|
convergeWithHelmBinary := func(st *state.HelmState, helm helmexec.Interface) (bool, []error) {
|
|
if c.GlobalString("helm-binary") != "" {
|
|
helm.SetHelmBinary(c.GlobalString("helm-binary"))
|
|
}
|
|
return converge(st, helm, ctx)
|
|
}
|
|
|
|
err = a.VisitDesiredStates(fileOrDir, a.Selectors, convergeWithHelmBinary)
|
|
|
|
return toCliError(err)
|
|
}
|
|
|
|
func InitAppEntry(c *cli.Context, reverse bool) (*app.App, string, error) {
|
|
if c.NArg() > 0 {
|
|
cli.ShowAppHelp(c)
|
|
return nil, "", fmt.Errorf("err: extraneous arguments: %s", strings.Join(c.Args(), ", "))
|
|
}
|
|
|
|
fileOrDir := c.GlobalString("file")
|
|
kubeContext := c.GlobalString("kube-context")
|
|
namespace := c.GlobalString("namespace")
|
|
selectors := c.GlobalStringSlice("selector")
|
|
logger := c.App.Metadata["logger"].(*zap.SugaredLogger)
|
|
|
|
env := c.GlobalString("environment")
|
|
if env == "" {
|
|
env = state.DefaultEnv
|
|
}
|
|
|
|
app := app.Init(&app.App{
|
|
KubeContext: kubeContext,
|
|
Logger: logger,
|
|
Reverse: reverse,
|
|
Env: env,
|
|
Namespace: namespace,
|
|
Selectors: selectors,
|
|
})
|
|
|
|
return app, fileOrDir, nil
|
|
}
|
|
|
|
func FindAndIterateOverDesiredStatesUsingFlagsWithReverse(c *cli.Context, reverse bool, converge func(*state.HelmState, helmexec.Interface, app.Context) []error) error {
|
|
a, fileOrDir, err := InitAppEntry(c, reverse)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ctx := app.NewContext()
|
|
|
|
convergeWithHelmBinary := func(st *state.HelmState, helm helmexec.Interface) []error {
|
|
if c.GlobalString("helm-binary") != "" {
|
|
helm.SetHelmBinary(c.GlobalString("helm-binary"))
|
|
}
|
|
return converge(st, helm, ctx)
|
|
}
|
|
|
|
err = a.VisitDesiredStatesWithReleasesFiltered(fileOrDir, convergeWithHelmBinary)
|
|
|
|
return toCliError(err)
|
|
}
|
|
|
|
func toCliError(err error) error {
|
|
if err != nil {
|
|
switch e := err.(type) {
|
|
case *app.NoMatchingHelmfileError:
|
|
return cli.NewExitError(e.Error(), 2)
|
|
case *app.Error:
|
|
return cli.NewExitError(e.Error(), e.Code())
|
|
default:
|
|
panic(fmt.Errorf("BUG: please file an github issue for this unhandled error: %T: %v", e, e))
|
|
}
|
|
}
|
|
return err
|
|
}
|