/* Copyright The Helm Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package cmd import ( "fmt" "log/slog" "strconv" "github.com/spf13/cobra" "helm.sh/helm/v4/pkg/action" ) func addDryRunFlag(cmd *cobra.Command) { // --dry-run options with expected outcome: // - Not set means no dry run and server is contacted. // - Set with no value, a value of client, or a value of true and the server is not contacted // - Set with a value of false, none, or false and the server is contacted // The true/false part is meant to reflect some legacy behavior while none is equal to "". f := cmd.Flags() f.String( "dry-run", "none", `simulates the operation without persisting changes. Must be one of: "none" (default), "client", or "server". '--dry-run=none' executes the operation normally and persists changes (no simulation). '--dry-run=client' simulates the operation client-side only and avoids cluster connections. '--dry-run=server' simulates the operation on the server, requiring cluster connectivity.`) f.Lookup("dry-run").NoOptDefVal = "unset" } // Determine the `action.DryRunStrategy` given -dry-run=` flag (or absence of) // Legacy usage of the flag: boolean values, and `--dry-run` (without value) are supported, and log warnings emitted func cmdGetDryRunFlagStrategy(cmd *cobra.Command, isTemplate bool) (action.DryRunStrategy, error) { f := cmd.Flag("dry-run") v := f.Value.String() switch v { case f.NoOptDefVal: slog.Warn(`--dry-run is deprecated and should be replaced with '--dry-run=client'`) return action.DryRunClient, nil case string(action.DryRunClient): return action.DryRunClient, nil case string(action.DryRunServer): return action.DryRunServer, nil case string(action.DryRunNone): if isTemplate { // Special case hack for `helm template`, which is always a dry run return action.DryRunNone, fmt.Errorf(`invalid dry-run value (%q). Must be "server" or "client"`, v) } return action.DryRunNone, nil } b, err := strconv.ParseBool(v) if err != nil { return action.DryRunNone, fmt.Errorf(`invalid dry-run value (%q). Must be "none", "server", or "client"`, v) } if isTemplate && !b { // Special case for `helm template`, which is always a dry run return action.DryRunNone, fmt.Errorf(`invalid dry-run value (%q). Must be "server" or "client"`, v) } result := action.DryRunNone if b { result = action.DryRunClient } slog.Warn(fmt.Sprintf(`boolean '--dry-run=%v' flag is deprecated and must be replaced with '--dry-run=%s'`, v, result)) return result, nil }