Implment `--dry-run=["none"|"client"|"server"] install/upgrade/template flag

Signed-off-by: George Jenkins <gjenkins8@bloomberg.net>
pull/11744/head
George Jenkins 3 years ago
parent 76157c6d06
commit 6032df9e39

@ -122,10 +122,26 @@ To see the list of chart repositories, use 'helm repo list'. To search for
charts in a repository, use 'helm search'. charts in a repository, use 'helm search'.
` `
func determineInstallDryRunMode(dryRunModeFlag string) (*action.DryRunMode, error) {
switch dryRunModeFlag {
case "none":
case "false": // TODO: Remove "false" helm v4
return &action.DryRunModeNone, nil
case "client":
case "true": // TODO: Remove "true" helm v4
return &action.DryRunModeClient, nil
case "server":
return &action.DryRunModeServer, nil
}
return nil, fmt.Errorf("Invalid --dry-run flag value: %s", dryRunModeFlag)
}
func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client := action.NewInstall(cfg) client := action.NewInstall(cfg)
valueOpts := &values.Options{} valueOpts := &values.Options{}
var outfmt output.Format var outfmt output.Format
var dryRunModeFlag string
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "install [NAME] [CHART]", Use: "install [NAME] [CHART]",
@ -136,6 +152,15 @@ func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
return compInstall(args, toComplete, client) return compInstall(args, toComplete, client)
}, },
RunE: func(_ *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, args []string) error {
dryRunMode, err := determineInstallDryRunMode(dryRunModeFlag)
if err != nil {
return err
}
client.DryRunMode = *dryRunMode
fmt.Printf("drm: %s\n", client.DryRunMode)
rel, err := runInstall(args, client, valueOpts, out) rel, err := runInstall(args, client, valueOpts, out)
if err != nil { if err != nil {
return errors.Wrap(err, "INSTALLATION FAILED") return errors.Wrap(err, "INSTALLATION FAILED")
@ -145,16 +170,21 @@ func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
}, },
} }
addInstallFlags(cmd, cmd.Flags(), client, valueOpts) addInstallFlags(cmd, cmd.Flags(), client, &dryRunModeFlag, valueOpts)
bindOutputFlag(cmd, &outfmt) bindOutputFlag(cmd, &outfmt)
bindPostRenderFlag(cmd, &client.PostRenderer) bindPostRenderFlag(cmd, &client.PostRenderer)
return cmd return cmd
} }
func addInstallFlags(cmd *cobra.Command, f *pflag.FlagSet, client *action.Install, valueOpts *values.Options) { func addInstallFlags(cmd *cobra.Command, f *pflag.FlagSet, client *action.Install, dryRunModeFlag *string, valueOpts *values.Options) {
f.BoolVar(&client.CreateNamespace, "create-namespace", false, "create the release namespace if not present") f.BoolVar(&client.CreateNamespace, "create-namespace", false, "create the release namespace if not present")
f.BoolVar(&client.DryRun, "dry-run", false, "simulate an install") f.StringVar(
dryRunModeFlag,
"dry-run",
"none",
`simulate an install. Must be "none", "server", or "client". If client strategy, X. If server strategy, Y. For backwards compatibility, boolean values "true" and "false" are also accepted. "true" being a synonym for "client". "false" meaning disable dry-run`,
)
f.BoolVar(&client.Force, "force", false, "force resource updates through a replacement strategy") f.BoolVar(&client.Force, "force", false, "force resource updates through a replacement strategy")
f.BoolVar(&client.DisableHooks, "no-hooks", false, "prevent hooks from running during install") f.BoolVar(&client.DisableHooks, "no-hooks", false, "prevent hooks from running during install")
f.BoolVar(&client.Replace, "replace", false, "re-use the given name, only if that name is a deleted release which remains in the history. This is unsafe in production") f.BoolVar(&client.Replace, "replace", false, "re-use the given name, only if that name is a deleted release which remains in the history. This is unsafe in production")

@ -46,10 +46,28 @@ faked locally. Additionally, none of the server-side testing of chart validity
(e.g. whether an API is supported) is done. (e.g. whether an API is supported) is done.
` `
func determineTemplateDryRunMode(dryRunModeFlag string) (*action.DryRunMode, error) {
switch dryRunModeFlag {
case "none":
return nil, fmt.Errorf("Invalid flag --dry-run=none for template")
case "false": // TODO: Remove "false" helm v4
// helm template --dry-run=false was previously ignored, and dry-run set anyway
return &action.DryRunModeClient, nil
case "client":
case "true": // TODO: Remove "true" helm v4
return &action.DryRunModeClient, nil
case "server":
return &action.DryRunModeServer, nil
}
return nil, fmt.Errorf("Invalid --dry-run flag value: %s", dryRunModeFlag)
}
func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
var validate bool var validate bool
var includeCrds bool var includeCrds bool
var skipTests bool var skipTests bool
var dryRunModeFlag string
client := action.NewInstall(cfg) client := action.NewInstall(cfg)
valueOpts := &values.Options{} valueOpts := &values.Options{}
var kubeVersion string var kubeVersion string
@ -73,7 +91,12 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client.KubeVersion = parsedKubeVersion client.KubeVersion = parsedKubeVersion
} }
dryRunMode, err := determineTemplateDryRunMode(dryRunModeFlag)
if err != nil {
return err
}
client.DryRun = true client.DryRun = true
client.DryRunMode = *dryRunMode
client.ReleaseName = "release-name" client.ReleaseName = "release-name"
client.Replace = true // Skip the name check client.Replace = true // Skip the name check
client.ClientOnly = !validate client.ClientOnly = !validate
@ -173,7 +196,7 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
} }
f := cmd.Flags() f := cmd.Flags()
addInstallFlags(cmd, f, client, valueOpts) addInstallFlags(cmd, f, client, &dryRunModeFlag, valueOpts)
f.StringArrayVarP(&showFiles, "show-only", "s", []string{}, "only show manifests rendered from the given templates") f.StringArrayVarP(&showFiles, "show-only", "s", []string{}, "only show manifests rendered from the given templates")
f.StringVar(&client.OutputDir, "output-dir", "", "writes the executed templates to files in output-dir instead of stdout") f.StringVar(&client.OutputDir, "output-dir", "", "writes the executed templates to files in output-dir instead of stdout")
f.BoolVar(&validate, "validate", false, "validate your manifests against the Kubernetes cluster you are currently pointing at. This is the same validation performed on an install") f.BoolVar(&validate, "validate", false, "validate your manifests against the Kubernetes cluster you are currently pointing at. This is the same validation performed on an install")

@ -62,6 +62,14 @@ const notesFileSuffix = "NOTES.txt"
const defaultDirectoryPermission = 0755 const defaultDirectoryPermission = 0755
type DryRunMode string
var (
DryRunModeNone DryRunMode = "none"
DryRunModeClient DryRunMode = "client"
DryRunModeServer DryRunMode = "server"
)
// Install performs an installation operation. // Install performs an installation operation.
type Install struct { type Install struct {
cfg *Configuration cfg *Configuration
@ -71,7 +79,8 @@ type Install struct {
ClientOnly bool ClientOnly bool
Force bool Force bool
CreateNamespace bool CreateNamespace bool
DryRun bool DryRun bool // Deprecated: replaced by DryRunMode, to be removed helm v4
DryRunMode DryRunMode
DisableHooks bool DisableHooks bool
Replace bool Replace bool
Wait bool Wait bool
@ -179,7 +188,7 @@ func (i *Install) installCRDs(crds []chart.CRD) error {
// Run executes the installation // Run executes the installation
// //
// If DryRun is set to true, this will prepare the release, but not install it // If DryRunMode is not 'none', this will prepare the release, but not install it
func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.Release, error) { func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.Release, error) {
ctx := context.Background() ctx := context.Background()
@ -207,7 +216,7 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
// contacts the upstream server and builds the capabilities object. // contacts the upstream server and builds the capabilities object.
if crds := chrt.CRDObjects(); !i.ClientOnly && !i.SkipCRDs && len(crds) > 0 { if crds := chrt.CRDObjects(); !i.ClientOnly && !i.SkipCRDs && len(crds) > 0 {
// On dry run, bail here // On dry run, bail here
if i.DryRun { if i.isDryRun() {
i.cfg.Log("WARNING: This chart or one of its subcharts contains CRDs. Rendering may fail or contain inaccuracies.") i.cfg.Log("WARNING: This chart or one of its subcharts contains CRDs. Rendering may fail or contain inaccuracies.")
} else if err := i.installCRDs(crds); err != nil { } else if err := i.installCRDs(crds); err != nil {
return nil, err return nil, err
@ -241,7 +250,7 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
} }
// special case for helm template --is-upgrade // special case for helm template --is-upgrade
isUpgrade := i.IsUpgrade && i.DryRun isUpgrade := i.IsUpgrade && i.isDryRun()
options := chartutil.ReleaseOptions{ options := chartutil.ReleaseOptions{
Name: i.ReleaseName, Name: i.ReleaseName,
Namespace: i.Namespace, Namespace: i.Namespace,
@ -298,7 +307,7 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
} }
// Bail out here if it is a dry run // Bail out here if it is a dry run
if i.DryRun { if i.isDryRun() {
rel.Info.Description = "Dry run complete" rel.Info.Description = "Dry run complete"
return rel, nil return rel, nil
} }
@ -453,6 +462,23 @@ func (i *Install) failRelease(rel *release.Release, err error) (*release.Release
return rel, err return rel, err
} }
func (i *Install) isDryRun() bool {
if i.DryRunMode != "" {
switch i.DryRunMode {
case DryRunModeClient:
case DryRunModeServer:
return true
case DryRunModeNone:
return false
default:
panic("Invalid DryRun mode")
}
}
// Fallback to legacy
return i.DryRun
}
// availableName tests whether a name is available // availableName tests whether a name is available
// //
// Roughly, this will return an error if name is // Roughly, this will return an error if name is
@ -467,7 +493,8 @@ func (i *Install) availableName() error {
if err := chartutil.ValidateReleaseName(start); err != nil { if err := chartutil.ValidateReleaseName(start); err != nil {
return errors.Wrapf(err, "release name %q", start) return errors.Wrapf(err, "release name %q", start)
} }
if i.DryRun {
if i.isDryRun() {
return nil return nil
} }

Loading…
Cancel
Save