Extend --dry-run to support string values.

* Extend --dry-run to support string values for dry run strategies
  'client', 'server', and 'none'
* Ensure --dry-run is set and accessed via cmdutil
* Deprecate --dry-run (unset), --dry-run=true, and --dry-run=false

Kubernetes-commit: af52beda260257e81cc9e19e9e5108b682ee93d6
This commit is contained in:
Julian V. Modesto 2019-12-15 18:29:27 -05:00 committed by Kubernetes Publisher
parent 0dd665ea25
commit c0b11fa131
22 changed files with 95 additions and 27 deletions

View File

@ -164,7 +164,7 @@ func (o *AnnotateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
}
o.outputFormat = cmdutil.GetFlagString(cmd, "output")
o.dryrun = cmdutil.GetDryRunFlag(cmd)
o.dryrun = cmdutil.GetClientSideDryRun(cmd)
if o.dryrun {
o.PrintFlags.Complete("%s (dry run)")

View File

@ -192,8 +192,9 @@ func NewCmdApply(baseName string, f cmdutil.Factory, ioStreams genericclioptions
cmd.Flags().BoolVar(&o.All, "all", o.All, "Select all resources in the namespace of the specified resource types.")
cmd.Flags().StringArrayVar(&o.PruneWhitelist, "prune-whitelist", o.PruneWhitelist, "Overwrite the default whitelist with <group/version/kind> for --prune")
cmd.Flags().BoolVar(&o.OpenAPIPatch, "openapi-patch", o.OpenAPIPatch, "If true, use openapi to calculate diff when the openapi presents and the resource can be found in the openapi spec. Otherwise, fall back to use baked-in types.")
cmd.Flags().BoolVar(&o.ServerDryRun, "server-dry-run", o.ServerDryRun, "If true, request will be sent to server with dry-run flag, which means the modifications won't be persisted. This is an alpha feature and flag.")
cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it. Warning: --dry-run cannot accurately output the result of merging the local manifest and the server-side data. Use --server-dry-run to get the merged result instead.")
cmd.Flags().BoolVar(&o.ServerDryRun, "server-dry-run", o.ServerDryRun, "If true, request will be sent to server with dry-run flag, which means the modifications won't be persisted.")
cmd.Flags().MarkDeprecated("server-dry-run", "--server-dry-run is deprecated and can be replaced with --dry-run=server.")
cmdutil.AddDryRunFlag(cmd)
cmdutil.AddServerSideApplyFlags(cmd)
// apply subcommands
@ -210,7 +211,7 @@ func (o *ApplyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
o.ServerSideApply = cmdutil.GetServerSideApplyFlag(cmd)
o.ForceConflicts = cmdutil.GetForceConflictsFlag(cmd)
o.FieldManager = cmdutil.GetFieldManagerFlag(cmd)
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
o.DynamicClient, err = f.DynamicClient()
if err != nil {
return err

View File

@ -118,7 +118,7 @@ func NewCmdApplySetLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IO
// Complete populates dry-run and output flag options.
func (o *SetLastAppliedOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
o.dryRun = cmdutil.GetDryRunFlag(cmd)
o.dryRun = cmdutil.GetClientSideDryRun(cmd)
o.output = cmdutil.GetFlagString(cmd, "output")
o.shortOutput = o.output == "name"

View File

@ -134,7 +134,7 @@ func NewCmdAutoscale(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *
// Complete verifies command line arguments and loads data from the command environment
func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
var err error
o.dryRun = cmdutil.GetFlagBool(cmd, "dry-run")
o.dryRun = cmdutil.GetClientSideDryRun(cmd)
o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
o.builder = f.NewBuilder()
discoveryClient, err := f.ToDiscoveryClient()

View File

@ -191,7 +191,7 @@ func (o *CreateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
return err
}
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
if o.DryRun {
o.PrintFlags.Complete("%s (dry run)")
@ -360,7 +360,7 @@ func (o *CreateSubcommandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command
o.Name = name
o.StructuredGenerator = generator
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
o.CreateAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
if o.DryRun {

View File

@ -133,7 +133,7 @@ func (o *CreateCronJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
o.Builder = f.NewBuilder()
o.Cmd = cmd
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
if o.DryRun {
o.PrintFlags.Complete("%s (dry run)")
}

View File

@ -132,7 +132,7 @@ func (o *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
o.Builder = f.NewBuilder()
o.Cmd = cmd
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
if o.DryRun {
o.PrintFlags.Complete("%s (dry run)")
}

View File

@ -235,7 +235,7 @@ func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
return err
}
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
o.OutputFormat = cmdutil.GetFlagString(cmd, "output")
if o.DryRun {

View File

@ -211,7 +211,7 @@ func (o *DrainCmdOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
return cmdutil.UsageErrorf(cmd, "error: cannot specify both a node name and a --selector option")
}
o.drainer.DryRun = cmdutil.GetDryRunFlag(cmd)
o.drainer.DryRun = cmdutil.GetClientSideDryRun(cmd)
if o.drainer.Client, err = f.KubernetesClientSet(); err != nil {
return err

View File

@ -167,7 +167,7 @@ func NewCmdExposeService(f cmdutil.Factory, streams genericclioptions.IOStreams)
}
func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
if o.DryRun {
o.PrintFlags.Complete("%s (dry run)")

View File

@ -164,7 +164,7 @@ func (o *LabelOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
}
o.outputFormat = cmdutil.GetFlagString(cmd, "output")
o.dryrun = cmdutil.GetDryRunFlag(cmd)
o.dryrun = cmdutil.GetClientSideDryRun(cmd)
o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) {
o.PrintFlags.NamePrintFlags.Operation = operation

View File

@ -139,7 +139,7 @@ func (o *PatchOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
}
o.outputFormat = cmdutil.GetFlagString(cmd, "output")
o.dryRun = cmdutil.GetFlagBool(cmd, "dry-run")
o.dryRun = cmdutil.GetClientSideDryRun(cmd)
o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) {
o.PrintFlags.NamePrintFlags.Operation = operation

View File

@ -195,7 +195,7 @@ func (o *RollingUpdateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
if len(args) > 0 {
o.OldName = args[0]
}
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
o.OutputFormat = cmdutil.GetFlagString(cmd, "output")
o.KeepOldName = len(args) == 1
o.ShouldValidate = cmdutil.GetFlagBool(cmd, "validate")

View File

@ -104,7 +104,7 @@ func NewCmdRolloutUndo(f cmdutil.Factory, streams genericclioptions.IOStreams) *
// Complete completes al the required options
func (o *UndoOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
o.Resources = args
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
var err error
if o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace(); err != nil {

View File

@ -217,7 +217,7 @@ func (o *RunOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
}
o.ArgsLenAtDash = cmd.ArgsLenAtDash()
o.DryRun = cmdutil.GetFlagBool(cmd, "dry-run")
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
attachFlag := cmd.Flags().Lookup("attach")
if !attachFlag.Changed && o.Interactive {

View File

@ -216,7 +216,7 @@ func (o *EnvOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri
o.updatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn
o.output = cmdutil.GetFlagString(cmd, "output")
o.dryRun = cmdutil.GetDryRunFlag(cmd)
o.dryRun = cmdutil.GetClientSideDryRun(cmd)
if o.dryRun {
// TODO(juanvallejo): This can be cleaned up even further by creating

View File

@ -138,7 +138,7 @@ func (o *SetImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
}
o.UpdatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
o.Output = cmdutil.GetFlagString(cmd, "output")
o.ResolveImage = resolveImageFunc

View File

@ -150,7 +150,7 @@ func (o *SetResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, ar
o.UpdatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn
o.Output = cmdutil.GetFlagString(cmd, "output")
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
if o.DryRun {
o.PrintFlags.Complete("%s (dry run)")

View File

@ -129,7 +129,7 @@ func (o *SetSelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
return err
}
o.dryrun = cmdutil.GetDryRunFlag(cmd)
o.dryrun = cmdutil.GetClientSideDryRun(cmd)
o.resources, o.selector, err = getResourcesAndSelector(args)
if err != nil {

View File

@ -128,7 +128,7 @@ func (o *SetServiceAccountOptions) Complete(f cmdutil.Factory, cmd *cobra.Comman
}
o.shortOutput = cmdutil.GetFlagString(cmd, "output") == "name"
o.dryRun = cmdutil.GetDryRunFlag(cmd)
o.dryRun = cmdutil.GetClientSideDryRun(cmd)
o.output = cmdutil.GetFlagString(cmd, "output")
o.updatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn

View File

@ -120,7 +120,7 @@ func NewCmdSubject(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobr
// Complete completes all required options
func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
o.Output = cmdutil.GetFlagString(cmd, "output")
o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.DryRun = cmdutil.GetClientSideDryRun(cmd)
if o.DryRun {
o.PrintFlags.Complete("%s (dry run)")

View File

@ -23,6 +23,7 @@ import (
"io"
"net/url"
"os"
"strconv"
"strings"
"time"
@ -409,7 +410,12 @@ func AddKustomizeFlag(flags *pflag.FlagSet, value *string) {
// AddDryRunFlag adds dry-run flag to a command. Usually used by mutations.
func AddDryRunFlag(cmd *cobra.Command) {
cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.")
cmd.Flags().String(
"dry-run",
"none",
`Must be "none", "server", or "client". If client strategy, only print the object that would be sent, without sending it. If server strategy, submit server-side request without persisting the resource.`,
)
cmd.Flags().Lookup("dry-run").NoOptDefVal = "unchanged"
}
func AddServerSideApplyFlags(cmd *cobra.Command) {
@ -498,8 +504,69 @@ func GetFieldManagerFlag(cmd *cobra.Command) string {
return GetFlagString(cmd, "field-manager")
}
func GetDryRunFlag(cmd *cobra.Command) bool {
return GetFlagBool(cmd, "dry-run")
type DryRunStrategy int
const (
DryRunNone DryRunStrategy = iota
DryRunClient
DryRunServer
)
// TODO(julianvmodesto): remove GetClientSideDryRun once we support
// server-side dry-run in all commands
func GetClientSideDryRun(cmd *cobra.Command) bool {
dryRunStrategy, err := GetDryRunStrategy(cmd)
if err != nil {
klog.Fatalf("error accessing --dry-run flag for command %s: %v", cmd.Name(), err)
}
if dryRunStrategy == DryRunServer {
klog.Fatalf("--dry-run=server for command %s is not supported yet", cmd.Name())
}
return dryRunStrategy == DryRunClient
}
func GetDryRunStrategy(cmd *cobra.Command) (DryRunStrategy, error) {
var dryRunFlag = GetFlagString(cmd, "dry-run")
b, err := strconv.ParseBool(dryRunFlag)
// The flag is not a boolean
if err != nil {
switch dryRunFlag {
case cmd.Flag("dry-run").NoOptDefVal:
klog.Warning(`--dry-run is deprecated and can be replaced with --dry-run=client.`)
return DryRunClient, nil
case "client":
return DryRunClient, nil
case "server":
return DryRunServer, nil
case "none":
return DryRunNone, nil
default:
return DryRunNone, fmt.Errorf(`Invalid dry-run value (%v). Must be "none", "server", or "client".`, dryRunFlag)
}
}
// The flag was a boolean
if b {
klog.Warningf(`--dry-run=%v is deprecated (boolean value) and can be replaced with --dry-run=%s.`, dryRunFlag, "client")
return DryRunClient, nil
}
klog.Warningf(`--dry-run=%v is deprecated (boolean value) and can be replaced with --dry-run=%s.`, dryRunFlag, "none")
return DryRunNone, nil
}
// PrintFlagsWithDryRunStrategy sets a success message at print time for the dry run strategy
//
// TODO(juanvallejo): This can be cleaned up even further by creating
// a PrintFlags struct that binds the --dry-run flag, and whose
// ToPrinter method returns a printer that understands how to print
// this success message.
func PrintFlagsWithDryRunStrategy(printFlags *genericclioptions.PrintFlags, dryRunStrategy DryRunStrategy) *genericclioptions.PrintFlags {
switch dryRunStrategy {
case DryRunClient:
printFlags.Complete("%s (dry run)")
case DryRunServer:
printFlags.Complete("%s (server dry run)")
}
return printFlags
}
// GetResourcesAndPairs retrieves resources and "KEY=VALUE or KEY-" pair args from given args