fix(install): ensure --dry-run in client mode (=client, =true or empty) doesn't call kube API - fixes #30514

Signed-off-by: kilianpaquier <git@kilianpaquier.com>
pull/30944/head
kilianpaquier 4 months ago
parent 4f018e4f42
commit 621545c8fd
No known key found for this signature in database

@ -71,7 +71,6 @@ type Install struct {
ChartPathOptions
ClientOnly bool
Force bool
CreateNamespace bool
DryRun bool
@ -236,8 +235,13 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
// When the task is cancelled through ctx, the function returns and the install
// proceeds in the background.
func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals map[string]interface{}) (*release.Release, error) {
var interactWithRemote bool
if !i.isDryRun() || i.DryRunOption == "server" || i.DryRunOption == "none" || i.DryRunOption == "false" {
interactWithRemote = true
}
// Check reachability of cluster unless in client-only mode (e.g. `helm template` without `--validate`)
if !i.ClientOnly {
if interactWithRemote {
if err := i.cfg.KubeClient.IsReachable(); err != nil {
slog.Error(fmt.Sprintf("cluster reachability check failed: %v", err))
return nil, fmt.Errorf("cluster reachability check failed: %w", err)
@ -260,14 +264,9 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
return nil, fmt.Errorf("chart dependencies processing failed: %w", err)
}
var interactWithRemote bool
if !i.isDryRun() || i.DryRunOption == "server" || i.DryRunOption == "none" || i.DryRunOption == "false" {
interactWithRemote = true
}
// Pre-install anything in the crd/ directory. We do this before Helm
// contacts the upstream server and builds the capabilities object.
if crds := chrt.CRDObjects(); !i.ClientOnly && !i.SkipCRDs && len(crds) > 0 {
if crds := chrt.CRDObjects(); interactWithRemote && !i.SkipCRDs && len(crds) > 0 {
// On dry run, bail here
if i.isDryRun() {
slog.Warn("This chart or one of its subcharts contains CRDs. Rendering may fail or contain inaccuracies.")
@ -276,7 +275,7 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
}
}
if i.ClientOnly {
if !interactWithRemote {
// Add mock objects in here so it doesn't use Kube API server
// NOTE(bacongobbler): used for `helm template`
i.cfg.Capabilities = chartutil.DefaultCapabilities.Copy()
@ -289,7 +288,7 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
mem := driver.NewMemory()
mem.SetNamespace(i.Namespace)
i.cfg.Releases = storage.Init(mem)
} else if !i.ClientOnly && len(i.APIVersions) > 0 {
} else if interactWithRemote && len(i.APIVersions) > 0 {
slog.Debug("API Version list given outside of client only mode, this list will be ignored")
}
@ -358,7 +357,7 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
// we'll end up in a state where we will delete those resources upon
// deleting the release because the manifest will be pointing at that
// resource
if !i.ClientOnly && !isUpgrade && len(resources) > 0 {
if interactWithRemote && !isUpgrade && len(resources) > 0 {
if i.TakeOwnership {
toBeAdopted, err = requireAdoption(resources)
} else {

@ -254,7 +254,7 @@ func TestInstallReleaseWithValues(t *testing.T) {
func TestInstallReleaseClientOnly(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.ClientOnly = true
instAction.DryRunOption = "client"
instAction.Run(buildChart(), nil) // disregard output
is.Equal(instAction.cfg.Capabilities, chartutil.DefaultCapabilities)

@ -89,10 +89,13 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
if client.DryRunOption == "" {
client.DryRunOption = "true"
}
if validate {
client.DryRunOption = "server"
}
client.DryRun = true
client.ReleaseName = "release-name"
client.Replace = true // Skip the name check
client.ClientOnly = !validate
client.APIVersions = chartutil.VersionSet(extraAPIs)
client.IncludeCRDs = includeCrds
rel, err := runInstall(args, client, valueOpts, out)

Loading…
Cancel
Save