From c67a62da495ebe2654c8cf49b169b861ceaa62f1 Mon Sep 17 00:00:00 2001 From: ymqytw Date: Wed, 17 Aug 2016 11:28:07 -0700 Subject: [PATCH] Fixes #30562: Refactor kubectl command options to use common struct for common file params --- pkg/kubectl/cmd/annotate.go | 14 +++++------- pkg/kubectl/cmd/annotate_test.go | 2 +- pkg/kubectl/cmd/apply.go | 18 +++++---------- pkg/kubectl/cmd/autoscale.go | 18 +++++---------- pkg/kubectl/cmd/convert.go | 16 ++++++------- pkg/kubectl/cmd/create.go | 20 +++++------------ pkg/kubectl/cmd/delete.go | 18 +++++---------- pkg/kubectl/cmd/delete_test.go | 15 ++++++------- pkg/kubectl/cmd/describe.go | 20 +++++------------ pkg/kubectl/cmd/edit.go | 18 +++++---------- pkg/kubectl/cmd/expose.go | 18 +++++---------- pkg/kubectl/cmd/get.go | 14 +++++------- pkg/kubectl/cmd/label.go | 20 +++++------------ pkg/kubectl/cmd/label_test.go | 10 ++++----- pkg/kubectl/cmd/patch.go | 13 +++++------ pkg/kubectl/cmd/replace.go | 26 ++++++++-------------- pkg/kubectl/cmd/rollingupdate.go | 12 +++------- pkg/kubectl/cmd/rollout/rollout_history.go | 20 +++++------------ pkg/kubectl/cmd/rollout/rollout_pause.go | 21 +++++++++-------- pkg/kubectl/cmd/rollout/rollout_resume.go | 21 +++++++++-------- pkg/kubectl/cmd/rollout/rollout_status.go | 20 +++++------------ pkg/kubectl/cmd/rollout/rollout_undo.go | 21 +++++++++-------- pkg/kubectl/cmd/scale.go | 18 +++++---------- pkg/kubectl/cmd/set/set_image.go | 14 +++++------- pkg/kubectl/cmd/stop.go | 19 +++++----------- pkg/kubectl/cmd/util/helpers.go | 12 ++++++++-- pkg/kubectl/resource/builder.go | 9 +++++++- pkg/kubectl/resource/builder_test.go | 26 +++++++++++----------- 28 files changed, 182 insertions(+), 291 deletions(-) diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index 24e22f6a9c5..de843cb5a71 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -36,11 +36,12 @@ import ( // AnnotateOptions have the data required to perform the annotate operation type AnnotateOptions struct { + resource.FilenameOptions + resources []string newAnnotations map[string]string removeAnnotations []string builder *resource.Builder - filenames []string selector string overwrite bool @@ -53,8 +54,6 @@ type AnnotateOptions struct { f *cmdutil.Factory out io.Writer cmd *cobra.Command - - recursive bool } var ( @@ -128,9 +127,8 @@ func NewCmdAnnotate(f *cmdutil.Factory, out io.Writer) *cobra.Command { cmd.Flags().BoolVar(&options.overwrite, "overwrite", false, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.") cmd.Flags().BoolVar(&options.all, "all", false, "select all resources in the namespace of the specified resource types") cmd.Flags().StringVar(&options.resourceVersion, "resource-version", "", "If non-empty, the annotation update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.") - usage := "Filename, directory, or URL to a file identifying the resource to update the annotation" - kubectl.AddJsonFilenameFlag(cmd, &options.filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.recursive) + usage := "identifying the resource to update the annotation" + cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmdutil.AddRecordFlag(cmd) return cmd } @@ -150,7 +148,7 @@ func (o *AnnotateOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra return err } o.resources = resources - if len(o.resources) < 1 && len(o.filenames) == 0 { + if len(o.resources) < 1 && cmdutil.IsFilenameEmpty(o.Filenames) { return fmt.Errorf("one or more resources must be specified as or /") } if len(annotationArgs) < 1 { @@ -168,7 +166,7 @@ func (o *AnnotateOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra o.builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(namespace).DefaultNamespace(). - FilenameParam(enforceNamespace, o.recursive, o.filenames...). + FilenameParam(enforceNamespace, &o.FilenameOptions). SelectorParam(o.selector). ResourceTypeOrNameArgs(o.all, o.resources...). Flatten(). diff --git a/pkg/kubectl/cmd/annotate_test.go b/pkg/kubectl/cmd/annotate_test.go index ae49363f78a..52473fe0170 100644 --- a/pkg/kubectl/cmd/annotate_test.go +++ b/pkg/kubectl/cmd/annotate_test.go @@ -504,7 +504,7 @@ func TestAnnotateObjectFromFile(t *testing.T) { cmd := NewCmdAnnotate(f, buf) cmd.SetOutput(buf) options := &AnnotateOptions{} - options.filenames = []string{"../../../examples/storage/cassandra/cassandra-controller.yaml"} + options.Filenames = []string{"../../../examples/storage/cassandra/cassandra-controller.yaml"} args := []string{"a=b", "c-"} if err := options.Complete(f, buf, cmd, args); err != nil { t.Fatalf("unexpected error: %v", err) diff --git a/pkg/kubectl/cmd/apply.go b/pkg/kubectl/cmd/apply.go index 45a46f14e3e..7e1ba450567 100644 --- a/pkg/kubectl/cmd/apply.go +++ b/pkg/kubectl/cmd/apply.go @@ -35,13 +35,6 @@ import ( "k8s.io/kubernetes/pkg/util/strategicpatch" ) -// ApplyOptions stores cmd.Flag values for apply. As new fields are added, -// add them here instead of referencing the cmd.Flags() -type ApplyOptions struct { - Filenames []string - Recursive bool -} - const ( // maxPatchRetry is the maximum number of conflicts retry for during a patch operation before returning failure maxPatchRetry = 5 @@ -68,7 +61,7 @@ var ( ) func NewCmdApply(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ApplyOptions{} + options := &resource.FilenameOptions{} cmd := &cobra.Command{ Use: "apply -f FILENAME", @@ -82,12 +75,11 @@ func NewCmdApply(f *cmdutil.Factory, out io.Writer) *cobra.Command { }, } - usage := "Filename, directory, or URL to file that contains the configuration to apply" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) + usage := "that contains the configuration to apply" + cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmd.MarkFlagRequired("filename") cmd.Flags().Bool("overwrite", true, "Automatically resolve conflicts between the modified and live configuration by using values from the modified configuration") cmdutil.AddValidateFlags(cmd) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) cmdutil.AddOutputFlagsForMutation(cmd) cmdutil.AddRecordFlag(cmd) cmdutil.AddInclude3rdPartyFlags(cmd) @@ -102,7 +94,7 @@ func validateArgs(cmd *cobra.Command, args []string) error { return nil } -func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *ApplyOptions) error { +func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *resource.FilenameOptions) error { shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) if err != nil { @@ -119,7 +111,7 @@ func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *Ap Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). Flatten(). Do() err = r.Err() diff --git a/pkg/kubectl/cmd/autoscale.go b/pkg/kubectl/cmd/autoscale.go index db8cea36092..a3029f6b758 100644 --- a/pkg/kubectl/cmd/autoscale.go +++ b/pkg/kubectl/cmd/autoscale.go @@ -30,13 +30,6 @@ import ( "github.com/spf13/cobra" ) -// AutoscaleOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type AutoscaleOptions struct { - Filenames []string - Recursive bool -} - var ( autoscaleLong = dedent.Dedent(` Creates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster. @@ -53,7 +46,7 @@ var ( ) func NewCmdAutoscale(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &AutoscaleOptions{} + options := &resource.FilenameOptions{} validArgs := []string{"deployment", "replicaset", "replicationcontroller"} argAliases := kubectl.ResourceAliases(validArgs) @@ -78,16 +71,15 @@ func NewCmdAutoscale(f *cmdutil.Factory, out io.Writer) *cobra.Command { cmd.Flags().Int("cpu-percent", -1, fmt.Sprintf("The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, a default autoscaling policy will be used.")) cmd.Flags().String("name", "", "The name for the newly created object. If not specified, the name of the input resource will be used.") cmdutil.AddDryRunFlag(cmd) - usage := "Filename, directory, or URL to a file identifying the resource to autoscale." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) + usage := "identifying the resource to autoscale." + cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddRecordFlag(cmd) cmdutil.AddInclude3rdPartyFlags(cmd) return cmd } -func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *AutoscaleOptions) error { +func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { namespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err @@ -102,7 +94,7 @@ func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args [] r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(namespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). ResourceTypeOrNameArgs(false, args...). Flatten(). Do() diff --git a/pkg/kubectl/cmd/convert.go b/pkg/kubectl/cmd/convert.go index bad2e5565e7..70106088919 100644 --- a/pkg/kubectl/cmd/convert.go +++ b/pkg/kubectl/cmd/convert.go @@ -78,9 +78,8 @@ func NewCmdConvert(f *cmdutil.Factory, out io.Writer) *cobra.Command { }, } - usage := "Filename, directory, or URL to file to need to get converted." - kubectl.AddJsonFilenameFlag(cmd, &options.filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.recursive) + usage := "to need to get converted." + cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmd.MarkFlagRequired("filename") cmdutil.AddValidateFlags(cmd) cmdutil.AddPrinterFlags(cmd) @@ -91,17 +90,16 @@ func NewCmdConvert(f *cmdutil.Factory, out io.Writer) *cobra.Command { // ConvertOptions have the data required to perform the convert operation type ConvertOptions struct { - builder *resource.Builder - filenames []string - local bool + resource.FilenameOptions + + builder *resource.Builder + local bool encoder runtime.Encoder out io.Writer printer kubectl.ResourcePrinter outputVersion unversioned.GroupVersion - - recursive bool } // Complete collects information required to run Convert command from command line. @@ -135,7 +133,7 @@ func (o *ConvertOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra. } o.builder = o.builder.NamespaceParam(cmdNamespace). ContinueOnError(). - FilenameParam(false, o.recursive, o.filenames...). + FilenameParam(false, &o.FilenameOptions). Flatten() // build the printer diff --git a/pkg/kubectl/cmd/create.go b/pkg/kubectl/cmd/create.go index 891a6409e50..1206c615110 100644 --- a/pkg/kubectl/cmd/create.go +++ b/pkg/kubectl/cmd/create.go @@ -30,13 +30,6 @@ import ( "k8s.io/kubernetes/pkg/runtime" ) -// CreateOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type CreateOptions struct { - Filenames []string - Recursive bool -} - var ( create_long = dedent.Dedent(` Create a resource by filename or stdin. @@ -51,7 +44,7 @@ var ( ) func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &CreateOptions{} + options := &resource.FilenameOptions{} cmd := &cobra.Command{ Use: "create -f FILENAME", @@ -59,7 +52,7 @@ func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command { Long: create_long, Example: create_example, Run: func(cmd *cobra.Command, args []string) { - if len(options.Filenames) == 0 { + if cmdutil.IsFilenameEmpty(options.Filenames) { cmd.Help() return } @@ -69,11 +62,10 @@ func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command { }, } - usage := "Filename, directory, or URL to file to use to create the resource" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) + usage := "to use to create the resource" + cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmd.MarkFlagRequired("filename") cmdutil.AddValidateFlags(cmd) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) cmdutil.AddOutputFlagsForMutation(cmd) cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddRecordFlag(cmd) @@ -97,7 +89,7 @@ func ValidateArgs(cmd *cobra.Command, args []string) error { return nil } -func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *CreateOptions) error { +func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *resource.FilenameOptions) error { schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) if err != nil { return err @@ -116,7 +108,7 @@ func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *C Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). Flatten(). Do() err = r.Err() diff --git a/pkg/kubectl/cmd/delete.go b/pkg/kubectl/cmd/delete.go index fdad53bf452..d3124603bc8 100644 --- a/pkg/kubectl/cmd/delete.go +++ b/pkg/kubectl/cmd/delete.go @@ -32,13 +32,6 @@ import ( "k8s.io/kubernetes/pkg/kubectl/resource" ) -// DeleteOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type DeleteOptions struct { - Filenames []string - Recursive bool -} - var ( delete_long = dedent.Dedent(` Delete resources by filenames, stdin, resources and names, or by resources and label selector. @@ -74,7 +67,7 @@ var ( ) func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &DeleteOptions{} + options := &resource.FilenameOptions{} // retrieve a list of handled resources from printer as valid args validArgs, argAliases := []string{}, []string{} @@ -101,9 +94,8 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command { ValidArgs: validArgs, ArgAliases: argAliases, } - usage := "Filename, directory, or URL to a file containing the resource to delete." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) + usage := "containing the resource to delete." + cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on.") cmd.Flags().Bool("all", false, "[-all] to select all the specified resources.") cmd.Flags().Bool("ignore-not-found", false, "Treat \"resource not found\" as a successful delete. Defaults to \"true\" when --all is specified.") @@ -116,7 +108,7 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command { return cmd } -func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *DeleteOptions) error { +func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err @@ -126,7 +118,7 @@ func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). SelectorParam(cmdutil.GetFlagString(cmd, "selector")). SelectAllParam(deleteAll). ResourceTypeOrNameArgs(false, args...).RequireObject(false). diff --git a/pkg/kubectl/cmd/delete_test.go b/pkg/kubectl/cmd/delete_test.go index 33167e378d3..86a834ddc16 100644 --- a/pkg/kubectl/cmd/delete_test.go +++ b/pkg/kubectl/cmd/delete_test.go @@ -28,6 +28,7 @@ import ( "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/unversioned/fake" + "k8s.io/kubernetes/pkg/kubectl/resource" ) func TestDeleteObjectByTuple(t *testing.T) { @@ -145,9 +146,8 @@ func TestDeleteObjectNotFound(t *testing.T) { buf := bytes.NewBuffer([]byte{}) cmd := NewCmdDelete(f, buf) - options := &DeleteOptions{ - Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}, - } + options := &resource.FilenameOptions{} + options.Filenames = []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"} cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") err := RunDelete(f, buf, cmd, []string{}, options) @@ -222,7 +222,7 @@ func TestDeleteAllNotFound(t *testing.T) { cmd.Flags().Set("ignore-not-found", "false") cmd.Flags().Set("output", "name") - err := RunDelete(f, buf, cmd, []string{"services"}, &DeleteOptions{}) + err := RunDelete(f, buf, cmd, []string{"services"}, &resource.FilenameOptions{}) if err == nil || !errors.IsNotFound(err) { t.Errorf("unexpected error: expected NotFound, got %v", err) } @@ -325,9 +325,8 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { buf := bytes.NewBuffer([]byte{}) cmd := NewCmdDelete(f, buf) - options := &DeleteOptions{ - Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml", "../../../examples/guestbook/frontend-service.yaml"}, - } + options := &resource.FilenameOptions{} + options.Filenames = []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml", "../../../examples/guestbook/frontend-service.yaml"} cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") err := RunDelete(f, buf, cmd, []string{}, options) @@ -486,7 +485,7 @@ func TestResourceErrors(t *testing.T) { for k, v := range testCase.flags { cmd.Flags().Set(k, v) } - err := RunDelete(f, buf, cmd, testCase.args, &DeleteOptions{}) + err := RunDelete(f, buf, cmd, testCase.args, &resource.FilenameOptions{}) if !testCase.errFn(err) { t.Errorf("%s: unexpected error: %v", k, err) continue diff --git a/pkg/kubectl/cmd/describe.go b/pkg/kubectl/cmd/describe.go index f6b33833b7e..6e69657b6a9 100644 --- a/pkg/kubectl/cmd/describe.go +++ b/pkg/kubectl/cmd/describe.go @@ -33,13 +33,6 @@ import ( utilerrors "k8s.io/kubernetes/pkg/util/errors" ) -// DescribeOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type DescribeOptions struct { - Filenames []string - Recursive bool -} - var ( describe_long = dedent.Dedent(` Show details of a specific resource or group of resources. @@ -75,7 +68,7 @@ var ( ) func NewCmdDescribe(f *cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { - options := &DescribeOptions{} + options := &resource.FilenameOptions{} describerSettings := &kubectl.DescriberSettings{} validArgs := kubectl.DescribableResources() @@ -93,9 +86,8 @@ func NewCmdDescribe(f *cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { ValidArgs: validArgs, ArgAliases: argAliases, } - usage := "Filename, directory, or URL to a file containing the resource to describe" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) + usage := "containing the resource to describe" + cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on") cmd.Flags().Bool("all-namespaces", false, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") cmd.Flags().BoolVar(&describerSettings.ShowEvents, "show-events", true, "If true, display events related to the described object.") @@ -103,7 +95,7 @@ func NewCmdDescribe(f *cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { return cmd } -func RunDescribe(f *cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, args []string, options *DescribeOptions, describerSettings *kubectl.DescriberSettings) error { +func RunDescribe(f *cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions, describerSettings *kubectl.DescriberSettings) error { selector := cmdutil.GetFlagString(cmd, "selector") allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces") cmdNamespace, enforceNamespace, err := f.DefaultNamespace() @@ -113,7 +105,7 @@ func RunDescribe(f *cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, if allNamespaces { enforceNamespace = false } - if len(args) == 0 && len(options.Filenames) == 0 { + if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { fmt.Fprint(cmdErr, "You must specify the type of resource to describe. ", valid_resources) return cmdutil.UsageError(cmd, "Required resource not specified.") } @@ -122,7 +114,7 @@ func RunDescribe(f *cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). SelectorParam(selector). ResourceTypeOrNameArgs(true, args...). Flatten(). diff --git a/pkg/kubectl/cmd/edit.go b/pkg/kubectl/cmd/edit.go index ae760b39619..e9c3ea8024f 100644 --- a/pkg/kubectl/cmd/edit.go +++ b/pkg/kubectl/cmd/edit.go @@ -79,17 +79,10 @@ var ( kubectl edit svc/docker-registry --output-version=v1 -o json`) ) -// EditOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type EditOptions struct { - Filenames []string - Recursive bool -} - var errExit = fmt.Errorf("exit directly") func NewCmdEdit(f *cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - options := &EditOptions{} + options := &resource.FilenameOptions{} // retrieve a list of handled resources from printer as valid args validArgs, argAliases := []string{}, []string{} @@ -117,9 +110,8 @@ func NewCmdEdit(f *cmdutil.Factory, out, errOut io.Writer) *cobra.Command { ValidArgs: validArgs, ArgAliases: argAliases, } - usage := "Filename, directory, or URL to file to use to edit the resource" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) + usage := "to use to edit the resource" + cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmdutil.AddValidateFlags(cmd) cmd.Flags().StringP("output", "o", "yaml", "Output format. One of: yaml|json.") cmd.Flags().String("output-version", "", "Output the formatted object with the given group version (for ex: 'extensions/v1beta1').") @@ -130,7 +122,7 @@ func NewCmdEdit(f *cmdutil.Factory, out, errOut io.Writer) *cobra.Command { return cmd } -func RunEdit(f *cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, options *EditOptions) error { +func RunEdit(f *cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { var printer kubectl.ResourcePrinter var ext string var addHeader bool @@ -168,7 +160,7 @@ func RunEdit(f *cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Flatten(). diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index 2ae63f9e90a..df82f09ff7f 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -32,13 +32,6 @@ import ( "k8s.io/kubernetes/pkg/util/validation" ) -// ExposeOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type ExposeOptions struct { - Filenames []string - Recursive bool -} - var ( expose_resources = dedent.Dedent(` pod (po), service (svc), replicationcontroller (rc), @@ -81,7 +74,7 @@ var ( ) func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ExposeOptions{} + options := &resource.FilenameOptions{} validArgs, argAliases := []string{}, []string{} resources := regexp.MustCompile(`\s*,`).Split(expose_resources, -1) @@ -122,16 +115,15 @@ func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command { cmd.Flags().String("session-affinity", "", "If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'") cmd.Flags().String("cluster-ip", "", "ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.") - usage := "Filename, directory, or URL to a file identifying the resource to expose a service" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) + usage := "identifying the resource to expose a service" + cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmdutil.AddDryRunFlag(cmd) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddRecordFlag(cmd) return cmd } -func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *ExposeOptions) error { +func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { namespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err @@ -141,7 +133,7 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(namespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). ResourceTypeOrNameArgs(false, args...). Flatten(). Do() diff --git a/pkg/kubectl/cmd/get.go b/pkg/kubectl/cmd/get.go index 620750b85fb..a5e31fbc962 100644 --- a/pkg/kubectl/cmd/get.go +++ b/pkg/kubectl/cmd/get.go @@ -34,8 +34,7 @@ import ( // GetOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() type GetOptions struct { - Filenames []string - Recursive bool + resource.FilenameOptions Raw string } @@ -114,9 +113,8 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comma cmd.Flags().Bool("all-namespaces", false, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") cmd.Flags().StringSliceP("label-columns", "L", []string{}, "Accepts a comma separated list of labels that are going to be presented as columns. Names are case-sensitive. You can also use multiple flag options like -L label1 -L label2...") cmd.Flags().Bool("export", false, "If true, use 'export' for the resources. Exported resources are stripped of cluster-specific information.") - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) + usage := "identifying the resource to get from a server." + cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmdutil.AddInclude3rdPartyFlags(cmd) cmd.Flags().StringVar(&options.Raw, "raw", options.Raw, "Raw URI to request from the server. Uses the transport specified by the kubeconfig file.") return cmd @@ -167,7 +165,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Comm enforceNamespace = false } - if len(args) == 0 && len(options.Filenames) == 0 { + if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { fmt.Fprint(errOut, "You must specify the type of resource to get. ", valid_resources) return cmdutil.UsageError(cmd, "Required resource not specified.") } @@ -195,7 +193,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Comm if isWatch || isWatchOnly { r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, &options.FilenameOptions). SelectorParam(selector). ExportParam(export). ResourceTypeOrNameArgs(true, args...). @@ -271,7 +269,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Comm r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, &options.FilenameOptions). SelectorParam(selector). ExportParam(export). ResourceTypeOrNameArgs(true, args...). diff --git a/pkg/kubectl/cmd/label.go b/pkg/kubectl/cmd/label.go index 763b2cc4111..95c2c22c94e 100644 --- a/pkg/kubectl/cmd/label.go +++ b/pkg/kubectl/cmd/label.go @@ -37,13 +37,6 @@ import ( "k8s.io/kubernetes/pkg/util/validation" ) -// LabelOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type LabelOptions struct { - Filenames []string - Recursive bool -} - var ( label_long = dedent.Dedent(` Update the labels on a resource. @@ -73,7 +66,7 @@ var ( ) func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &LabelOptions{} + options := &resource.FilenameOptions{} // retrieve a list of handled resources from printer as valid args validArgs, argAliases := []string{}, []string{} @@ -103,9 +96,8 @@ func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command { cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on") cmd.Flags().Bool("all", false, "select all resources in the namespace of the specified resource types") cmd.Flags().String("resource-version", "", "If non-empty, the labels update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.") - usage := "Filename, directory, or URL to a file identifying the resource to update the labels" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) + usage := "identifying the resource to update the labels" + cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmdutil.AddDryRunFlag(cmd) cmdutil.AddRecordFlag(cmd) cmdutil.AddInclude3rdPartyFlags(cmd) @@ -180,12 +172,12 @@ func labelFunc(obj runtime.Object, overwrite bool, resourceVersion string, label return nil } -func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *LabelOptions) error { +func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { resources, labelArgs, err := cmdutil.GetResourcesAndPairs(args, "label") if err != nil { return err } - if len(resources) < 1 && len(options.Filenames) == 0 { + if len(resources) < 1 && cmdutil.IsFilenameEmpty(options.Filenames) { return cmdutil.UsageError(cmd, "one or more resources must be specified as or /") } if len(labelArgs) < 1 { @@ -210,7 +202,7 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). SelectorParam(selector). ResourceTypeOrNameArgs(all, resources...). Flatten(). diff --git a/pkg/kubectl/cmd/label_test.go b/pkg/kubectl/cmd/label_test.go index 9081c50998a..fb3e753d532 100644 --- a/pkg/kubectl/cmd/label_test.go +++ b/pkg/kubectl/cmd/label_test.go @@ -27,6 +27,7 @@ import ( "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/unversioned/fake" + "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/runtime" ) @@ -322,7 +323,7 @@ func TestLabelErrors(t *testing.T) { for k, v := range testCase.flags { cmd.Flags().Set(k, v) } - err := RunLabel(f, buf, cmd, testCase.args, &LabelOptions{}) + err := RunLabel(f, buf, cmd, testCase.args, &resource.FilenameOptions{}) if !testCase.errFn(err) { t.Errorf("%s: unexpected error: %v", k, err) continue @@ -370,9 +371,8 @@ func TestLabelForResourceFromFile(t *testing.T) { buf := bytes.NewBuffer([]byte{}) cmd := NewCmdLabel(f, buf) - options := &LabelOptions{ - Filenames: []string{"../../../examples/storage/cassandra/cassandra-controller.yaml"}, - } + options := &resource.FilenameOptions{} + options.Filenames = []string{"../../../examples/storage/cassandra/cassandra-controller.yaml"} err := RunLabel(f, buf, cmd, []string{"a=b"}, options) if err != nil { @@ -421,7 +421,7 @@ func TestLabelMultipleObjects(t *testing.T) { cmd := NewCmdLabel(f, buf) cmd.Flags().Set("all", "true") - if err := RunLabel(f, buf, cmd, []string{"pods", "a=b"}, &LabelOptions{}); err != nil { + if err := RunLabel(f, buf, cmd, []string{"pods", "a=b"}, &resource.FilenameOptions{}); err != nil { t.Fatalf("unexpected error: %v", err) } if strings.Count(buf.String(), "labeled") != len(pods.Items) { diff --git a/pkg/kubectl/cmd/patch.go b/pkg/kubectl/cmd/patch.go index 0e830908bc5..70ee8c66508 100644 --- a/pkg/kubectl/cmd/patch.go +++ b/pkg/kubectl/cmd/patch.go @@ -40,9 +40,9 @@ var patchTypes = map[string]api.PatchType{"json": api.JSONPatchType, "merge": ap // PatchOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() type PatchOptions struct { - Filenames []string - Recursive bool - Local bool + resource.FilenameOptions + + Local bool OutputFormat string } @@ -103,9 +103,8 @@ func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command { cmdutil.AddRecordFlag(cmd) cmdutil.AddInclude3rdPartyFlags(cmd) - usage := "Filename, directory, or URL to a file identifying the resource to update" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) + usage := "identifying the resource to update" + cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmd.Flags().BoolVar(&options.Local, "local", false, "If true, patch will operate on the content of the file, not the server-side resource.") @@ -146,7 +145,7 @@ func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, &options.FilenameOptions). ResourceTypeOrNameArgs(false, args...). Flatten(). Do() diff --git a/pkg/kubectl/cmd/replace.go b/pkg/kubectl/cmd/replace.go index f1bd13e4f12..650f9d6de1c 100644 --- a/pkg/kubectl/cmd/replace.go +++ b/pkg/kubectl/cmd/replace.go @@ -35,13 +35,6 @@ import ( "k8s.io/kubernetes/pkg/util/wait" ) -// ReplaceOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type ReplaceOptions struct { - Filenames []string - Recursive bool -} - var ( replace_long = dedent.Dedent(` Replace a resource by filename or stdin. @@ -66,7 +59,7 @@ var ( ) func NewCmdReplace(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ReplaceOptions{} + options := &resource.FilenameOptions{} cmd := &cobra.Command{ Use: "replace -f FILENAME", @@ -81,15 +74,14 @@ func NewCmdReplace(f *cmdutil.Factory, out io.Writer) *cobra.Command { cmdutil.CheckErr(err) }, } - usage := "Filename, directory, or URL to file to use to replace the resource." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) + usage := "to use to replace the resource." + cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmd.MarkFlagRequired("filename") cmd.Flags().Bool("force", false, "Delete and re-create the specified resource") cmd.Flags().Bool("cascade", false, "Only relevant during a force replace. If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController).") cmd.Flags().Int("grace-period", -1, "Only relevant during a force replace. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative.") cmd.Flags().Duration("timeout", 0, "Only relevant during a force replace. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object. Any other values should contain a corresponding time unit (e.g. 1s, 2m, 3h).") cmdutil.AddValidateFlags(cmd) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) cmdutil.AddOutputFlagsForMutation(cmd) cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddRecordFlag(cmd) @@ -98,7 +90,7 @@ func NewCmdReplace(f *cmdutil.Factory, out io.Writer) *cobra.Command { return cmd } -func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *ReplaceOptions) error { +func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { if len(os.Args) > 1 && os.Args[1] == "update" { printDeprecationWarning("replace", "update") } @@ -113,7 +105,7 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st } force := cmdutil.GetFlagBool(cmd, "force") - if len(options.Filenames) == 0 { + if cmdutil.IsFilenameEmpty(options.Filenames) { return cmdutil.UsageError(cmd, "Must specify --filename to replace") } @@ -135,7 +127,7 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). Flatten(). Do() err = r.Err() @@ -171,7 +163,7 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st }) } -func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *ReplaceOptions) error { +func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *resource.FilenameOptions) error { schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) if err != nil { return err @@ -205,7 +197,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args [] r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), runtime.UnstructuredJSONScheme). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). ResourceTypeOrNameArgs(false, args...).RequireObject(false). Flatten(). Do() @@ -247,7 +239,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args [] Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). Flatten(). Do() err = r.Err() diff --git a/pkg/kubectl/cmd/rollingupdate.go b/pkg/kubectl/cmd/rollingupdate.go index 2f336b7b417..8a5da16176e 100644 --- a/pkg/kubectl/cmd/rollingupdate.go +++ b/pkg/kubectl/cmd/rollingupdate.go @@ -38,12 +38,6 @@ import ( "k8s.io/kubernetes/pkg/util/intstr" ) -// RollingUpdateOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type RollingUpdateOptions struct { - Filenames []string -} - var ( rollingUpdate_long = dedent.Dedent(` Perform a rolling update of the given ReplicationController. @@ -80,7 +74,7 @@ var ( ) func NewCmdRollingUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &RollingUpdateOptions{} + options := &resource.FilenameOptions{} cmd := &cobra.Command{ Use: "rolling-update OLD_CONTROLLER_NAME ([NEW_CONTROLLER_NAME] --image=NEW_CONTAINER_IMAGE | -f NEW_CONTROLLER_SPEC)", @@ -146,7 +140,7 @@ func validateArguments(cmd *cobra.Command, filenames, args []string) error { return utilerrors.NewAggregate(errors) } -func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *RollingUpdateOptions) error { +func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { if len(os.Args) > 1 && os.Args[1] == "rollingupdate" { printDeprecationWarning("rolling-update", "rollingupdate") } @@ -211,7 +205,7 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg request := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). Schema(schema). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, false, filename). + FilenameParam(enforceNamespace, &resource.FilenameOptions{Recursive: false, Filenames: []string{filename}}). Do() obj, err := request.Object() if err != nil { diff --git a/pkg/kubectl/cmd/rollout/rollout_history.go b/pkg/kubectl/cmd/rollout/rollout_history.go index ad51038a76a..10fcddcdafc 100644 --- a/pkg/kubectl/cmd/rollout/rollout_history.go +++ b/pkg/kubectl/cmd/rollout/rollout_history.go @@ -28,13 +28,6 @@ import ( "github.com/spf13/cobra" ) -// HistoryOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type HistoryOptions struct { - Filenames []string - Recursive bool -} - var ( history_long = dedent.Dedent(` View previous rollout revisions and configurations.`) @@ -47,7 +40,7 @@ var ( ) func NewCmdRolloutHistory(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &HistoryOptions{} + options := &resource.FilenameOptions{} validArgs := []string{"deployment"} argAliases := kubectl.ResourceAliases(validArgs) @@ -65,14 +58,13 @@ func NewCmdRolloutHistory(f *cmdutil.Factory, out io.Writer) *cobra.Command { } cmd.Flags().Int64("revision", 0, "See the details, including podTemplate of the revision specified") - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) + usage := "identifying the resource to get from a server." + cmdutil.AddFilenameOptionFlags(cmd, options, usage) return cmd } -func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *HistoryOptions) error { - if len(args) == 0 && len(options.Filenames) == 0 { +func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *resource.FilenameOptions) error { + if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { return cmdutil.UsageError(cmd, "Required resource not specified.") } revision := cmdutil.GetFlagInt64(cmd, "revision") @@ -86,7 +78,7 @@ func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []st r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Latest(). diff --git a/pkg/kubectl/cmd/rollout/rollout_pause.go b/pkg/kubectl/cmd/rollout/rollout_pause.go index 9d7bbbc6c28..577fe9646cc 100644 --- a/pkg/kubectl/cmd/rollout/rollout_pause.go +++ b/pkg/kubectl/cmd/rollout/rollout_pause.go @@ -33,14 +33,14 @@ import ( // PauseConfig is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() type PauseConfig struct { + resource.FilenameOptions + PauseObject func(object runtime.Object) (bool, error) Mapper meta.RESTMapper Typer runtime.ObjectTyper Infos []*resource.Info - Out io.Writer - Filenames []string - Recursive bool + Out io.Writer } var ( @@ -59,7 +59,7 @@ var ( ) func NewCmdRolloutPause(f *cmdutil.Factory, out io.Writer) *cobra.Command { - opts := &PauseConfig{} + options := &PauseConfig{} validArgs := []string{"deployment"} argAliases := kubectl.ResourceAliases(validArgs) @@ -71,11 +71,11 @@ func NewCmdRolloutPause(f *cmdutil.Factory, out io.Writer) *cobra.Command { Example: pause_example, Run: func(cmd *cobra.Command, args []string) { allErrs := []error{} - err := opts.CompletePause(f, cmd, out, args) + err := options.CompletePause(f, cmd, out, args) if err != nil { allErrs = append(allErrs, err) } - err = opts.RunPause() + err = options.RunPause() if err != nil { allErrs = append(allErrs, err) } @@ -85,14 +85,13 @@ func NewCmdRolloutPause(f *cmdutil.Factory, out io.Writer) *cobra.Command { ArgAliases: argAliases, } - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &opts.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &opts.Recursive) + usage := "identifying the resource to get from a server." + cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) return cmd } func (o *PauseConfig) CompletePause(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { - if len(args) == 0 && len(o.Filenames) == 0 { + if len(args) == 0 && cmdutil.IsFilenameEmpty(o.Filenames) { return cmdutil.UsageError(cmd, cmd.Use) } @@ -107,7 +106,7 @@ func (o *PauseConfig) CompletePause(f *cmdutil.Factory, cmd *cobra.Command, out r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, o.Recursive, o.Filenames...). + FilenameParam(enforceNamespace, &o.FilenameOptions). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Latest(). diff --git a/pkg/kubectl/cmd/rollout/rollout_resume.go b/pkg/kubectl/cmd/rollout/rollout_resume.go index 4e9c21a69d0..11025197631 100644 --- a/pkg/kubectl/cmd/rollout/rollout_resume.go +++ b/pkg/kubectl/cmd/rollout/rollout_resume.go @@ -33,14 +33,14 @@ import ( // ResumeConfig is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() type ResumeConfig struct { + resource.FilenameOptions + ResumeObject func(object runtime.Object) (bool, error) Mapper meta.RESTMapper Typer runtime.ObjectTyper Infos []*resource.Info - Out io.Writer - Filenames []string - Recursive bool + Out io.Writer } var ( @@ -57,7 +57,7 @@ var ( ) func NewCmdRolloutResume(f *cmdutil.Factory, out io.Writer) *cobra.Command { - opts := &ResumeConfig{} + options := &ResumeConfig{} validArgs := []string{"deployment"} argAliases := kubectl.ResourceAliases(validArgs) @@ -69,11 +69,11 @@ func NewCmdRolloutResume(f *cmdutil.Factory, out io.Writer) *cobra.Command { Example: resume_example, Run: func(cmd *cobra.Command, args []string) { allErrs := []error{} - err := opts.CompleteResume(f, cmd, out, args) + err := options.CompleteResume(f, cmd, out, args) if err != nil { allErrs = append(allErrs, err) } - err = opts.RunResume() + err = options.RunResume() if err != nil { allErrs = append(allErrs, err) } @@ -83,14 +83,13 @@ func NewCmdRolloutResume(f *cmdutil.Factory, out io.Writer) *cobra.Command { ArgAliases: argAliases, } - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &opts.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &opts.Recursive) + usage := "identifying the resource to get from a server." + cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) return cmd } func (o *ResumeConfig) CompleteResume(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { - if len(args) == 0 && len(o.Filenames) == 0 { + if len(args) == 0 && cmdutil.IsFilenameEmpty(o.Filenames) { return cmdutil.UsageError(cmd, cmd.Use) } @@ -105,7 +104,7 @@ func (o *ResumeConfig) CompleteResume(f *cmdutil.Factory, cmd *cobra.Command, ou r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, o.Recursive, o.Filenames...). + FilenameParam(enforceNamespace, &o.FilenameOptions). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Latest(). diff --git a/pkg/kubectl/cmd/rollout/rollout_status.go b/pkg/kubectl/cmd/rollout/rollout_status.go index 5395b6d5c25..b374c1d570d 100644 --- a/pkg/kubectl/cmd/rollout/rollout_status.go +++ b/pkg/kubectl/cmd/rollout/rollout_status.go @@ -29,13 +29,6 @@ import ( "github.com/spf13/cobra" ) -// StatusOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type StatusOptions struct { - Filenames []string - Recursive bool -} - var ( status_long = dedent.Dedent(` Watch the status of current rollout, until it's done.`) @@ -45,7 +38,7 @@ var ( ) func NewCmdRolloutStatus(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &StatusOptions{} + options := &resource.FilenameOptions{} validArgs := []string{"deployment"} argAliases := kubectl.ResourceAliases(validArgs) @@ -62,14 +55,13 @@ func NewCmdRolloutStatus(f *cmdutil.Factory, out io.Writer) *cobra.Command { ArgAliases: argAliases, } - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) + usage := "identifying the resource to get from a server." + cmdutil.AddFilenameOptionFlags(cmd, options, usage) return cmd } -func RunStatus(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *StatusOptions) error { - if len(args) == 0 && len(options.Filenames) == 0 { +func RunStatus(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *resource.FilenameOptions) error { + if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { return cmdutil.UsageError(cmd, "Required resource not specified.") } @@ -82,7 +74,7 @@ func RunStatus(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []str r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). ResourceTypeOrNameArgs(true, args...). SingleResourceType(). Latest(). diff --git a/pkg/kubectl/cmd/rollout/rollout_undo.go b/pkg/kubectl/cmd/rollout/rollout_undo.go index eb6960631f6..2326f24bb7e 100644 --- a/pkg/kubectl/cmd/rollout/rollout_undo.go +++ b/pkg/kubectl/cmd/rollout/rollout_undo.go @@ -33,6 +33,8 @@ import ( // UndoOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() type UndoOptions struct { + resource.FilenameOptions + Rollbackers []kubectl.Rollbacker Mapper meta.RESTMapper Typer runtime.ObjectTyper @@ -40,9 +42,7 @@ type UndoOptions struct { ToRevision int64 DryRun bool - Out io.Writer - Filenames []string - Recursive bool + Out io.Writer } var ( @@ -60,7 +60,7 @@ var ( ) func NewCmdRolloutUndo(f *cmdutil.Factory, out io.Writer) *cobra.Command { - opts := &UndoOptions{} + options := &UndoOptions{} validArgs := []string{"deployment"} argAliases := kubectl.ResourceAliases(validArgs) @@ -72,11 +72,11 @@ func NewCmdRolloutUndo(f *cmdutil.Factory, out io.Writer) *cobra.Command { Example: undo_example, Run: func(cmd *cobra.Command, args []string) { allErrs := []error{} - err := opts.CompleteUndo(f, cmd, out, args) + err := options.CompleteUndo(f, cmd, out, args) if err != nil { allErrs = append(allErrs, err) } - err = opts.RunUndo() + err = options.RunUndo() if err != nil { allErrs = append(allErrs, err) } @@ -87,15 +87,14 @@ func NewCmdRolloutUndo(f *cmdutil.Factory, out io.Writer) *cobra.Command { } cmd.Flags().Int64("to-revision", 0, "The revision to rollback to. Default to 0 (last revision).") - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &opts.Filenames, usage) + usage := "identifying the resource to get from a server." + cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmdutil.AddDryRunFlag(cmd) - cmdutil.AddRecursiveFlag(cmd, &opts.Recursive) return cmd } func (o *UndoOptions) CompleteUndo(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { - if len(args) == 0 && len(o.Filenames) == 0 { + if len(args) == 0 && cmdutil.IsFilenameEmpty(o.Filenames) { return cmdutil.UsageError(cmd, "Required resource not specified.") } @@ -111,7 +110,7 @@ func (o *UndoOptions) CompleteUndo(f *cmdutil.Factory, cmd *cobra.Command, out i r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, o.Recursive, o.Filenames...). + FilenameParam(enforceNamespace, &o.FilenameOptions). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Latest(). diff --git a/pkg/kubectl/cmd/scale.go b/pkg/kubectl/cmd/scale.go index 1475ba81453..e76e7310c82 100644 --- a/pkg/kubectl/cmd/scale.go +++ b/pkg/kubectl/cmd/scale.go @@ -30,13 +30,6 @@ import ( "k8s.io/kubernetes/pkg/kubectl/resource" ) -// ScaleOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type ScaleOptions struct { - Filenames []string - Recursive bool -} - var ( scale_long = dedent.Dedent(` Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job. @@ -64,7 +57,7 @@ var ( // NewCmdScale returns a cobra command with the appropriate configuration and flags to run scale func NewCmdScale(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ScaleOptions{} + options := &resource.FilenameOptions{} validArgs := []string{"deployment", "replicaset", "replicationcontroller", "job"} argAliases := kubectl.ResourceAliases(validArgs) @@ -94,14 +87,13 @@ func NewCmdScale(f *cmdutil.Factory, out io.Writer) *cobra.Command { cmdutil.AddRecordFlag(cmd) cmdutil.AddInclude3rdPartyFlags(cmd) - usage := "Filename, directory, or URL to a file identifying the resource to set a new size" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) + usage := "identifying the resource to set a new size" + cmdutil.AddFilenameOptionFlags(cmd, options, usage) return cmd } // RunScale executes the scaling -func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *ScaleOptions) error { +func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *resource.FilenameOptions) error { if len(os.Args) > 1 && os.Args[1] == "resize" { printDeprecationWarning("scale", "resize") } @@ -115,7 +107,7 @@ func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). ResourceTypeOrNameArgs(false, args...). Flatten(). Do() diff --git a/pkg/kubectl/cmd/set/set_image.go b/pkg/kubectl/cmd/set/set_image.go index 4444e6c550a..8f9646e6081 100644 --- a/pkg/kubectl/cmd/set/set_image.go +++ b/pkg/kubectl/cmd/set/set_image.go @@ -24,7 +24,6 @@ import ( "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/runtime" @@ -34,6 +33,8 @@ import ( // ImageOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() type ImageOptions struct { + resource.FilenameOptions + Mapper meta.RESTMapper Typer runtime.ObjectTyper Infos []*resource.Info @@ -41,8 +42,6 @@ type ImageOptions struct { Selector string Out io.Writer Err io.Writer - Filenames []string - Recursive bool ShortOutput bool All bool Record bool @@ -97,13 +96,12 @@ func NewCmdImage(f *cmdutil.Factory, out io.Writer) *cobra.Command { } cmdutil.AddPrinterFlags(cmd) - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) + usage := "identifying the resource to get from a server." + cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmd.Flags().BoolVar(&options.All, "all", false, "select all resources in the namespace of the specified resource types") cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on") cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set image will NOT contact api-server but run locally.") cmdutil.AddRecordFlag(cmd) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) return cmd } @@ -130,7 +128,7 @@ func (o *ImageOptions) Complete(f *cmdutil.Factory, cmd *cobra.Command, args []s builder := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, o.Recursive, o.Filenames...). + FilenameParam(enforceNamespace, &o.FilenameOptions). Flatten() if !o.Local { builder = builder. @@ -148,7 +146,7 @@ func (o *ImageOptions) Complete(f *cmdutil.Factory, cmd *cobra.Command, args []s func (o *ImageOptions) Validate() error { errors := []error{} - if len(o.Resources) < 1 && len(o.Filenames) == 0 { + if len(o.Resources) < 1 && cmdutil.IsFilenameEmpty(o.Filenames) { errors = append(errors, fmt.Errorf("one or more resources must be specified as or /")) } if len(o.ContainerImages) < 1 { diff --git a/pkg/kubectl/cmd/stop.go b/pkg/kubectl/cmd/stop.go index ac7132b2e29..f1c64c86685 100644 --- a/pkg/kubectl/cmd/stop.go +++ b/pkg/kubectl/cmd/stop.go @@ -22,18 +22,10 @@ import ( "github.com/renstrom/dedent" "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/resource" ) -// StopOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type StopOptions struct { - Filenames []string - Recursive bool -} - var ( stop_long = dedent.Dedent(` Deprecated: Gracefully shut down a resource by name or filename. @@ -58,7 +50,7 @@ var ( ) func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &StopOptions{} + options := &resource.FilenameOptions{} cmd := &cobra.Command{ Use: "stop (-f FILENAME | TYPE (NAME | -l label | --all))", @@ -71,9 +63,8 @@ func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command { cmdutil.CheckErr(RunStop(f, cmd, args, out, options)) }, } - usage := "Filename, directory, or URL to file of resource(s) to be stopped." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) + usage := "of resource(s) to be stopped." + cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on.") cmd.Flags().Bool("all", false, "[-all] to select all the specified resources.") cmd.Flags().Bool("ignore-not-found", false, "Treat \"resource not found\" as a successful stop.") @@ -84,7 +75,7 @@ func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command { return cmd } -func RunStop(f *cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer, options *StopOptions) error { +func RunStop(f *cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer, options *resource.FilenameOptions) error { cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err @@ -95,7 +86,7 @@ func RunStop(f *cmdutil.Factory, cmd *cobra.Command, args []string, out io.Write ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). ResourceTypeOrNameArgs(false, args...). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). + FilenameParam(enforceNamespace, options). SelectorParam(cmdutil.GetFlagString(cmd, "selector")). SelectAllParam(cmdutil.GetFlagBool(cmd, "all")). Flatten(). diff --git a/pkg/kubectl/cmd/util/helpers.go b/pkg/kubectl/cmd/util/helpers.go index dac0610e7ad..2efcfcdd9b4 100644 --- a/pkg/kubectl/cmd/util/helpers.go +++ b/pkg/kubectl/cmd/util/helpers.go @@ -266,6 +266,13 @@ func UsageError(cmd *cobra.Command, format string, args ...interface{}) error { return fmt.Errorf("%s\nSee '%s -h' for help and examples.", msg, cmd.CommandPath()) } +func IsFilenameEmpty(filenames []string) bool { + if len(filenames) == 0 { + return true + } + return false +} + // Whether this cmd need watching objects. func isWatch(cmd *cobra.Command) bool { if w, err := cmd.Flags().GetBool("watch"); w && err == nil { @@ -353,8 +360,9 @@ func AddValidateFlags(cmd *cobra.Command) { cmd.MarkFlagFilename("schema-cache-dir") } -func AddRecursiveFlag(cmd *cobra.Command, value *bool) { - cmd.Flags().BoolVarP(value, "recursive", "R", *value, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") +func AddFilenameOptionFlags(cmd *cobra.Command, options *resource.FilenameOptions, usage string) { + kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, "Filename, directory, or URL to files "+usage) + cmd.Flags().BoolVarP(&options.Recursive, "recursive", "R", options.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") } // AddDryRunFlag adds dry-run flag to a command. Usually used by mutations. diff --git a/pkg/kubectl/resource/builder.go b/pkg/kubectl/resource/builder.go index 41fc1a8b515..6de96852537 100644 --- a/pkg/kubectl/resource/builder.go +++ b/pkg/kubectl/resource/builder.go @@ -93,6 +93,11 @@ func IsUsageError(err error) bool { return err == missingResourceError } +type FilenameOptions struct { + Filenames []string + Recursive bool +} + type resourceTuple struct { Resource string Name string @@ -117,7 +122,9 @@ func (b *Builder) Schema(schema validation.Schema) *Builder { // will cause an error. // If ContinueOnError() is set prior to this method, objects on the path that are not // recognized will be ignored (but logged at V(2)). -func (b *Builder) FilenameParam(enforceNamespace, recursive bool, paths ...string) *Builder { +func (b *Builder) FilenameParam(enforceNamespace bool, filenameOptions *FilenameOptions) *Builder { + recursive := filenameOptions.Recursive + paths := filenameOptions.Filenames for _, s := range paths { switch { case s == "-": diff --git a/pkg/kubectl/resource/builder_test.go b/pkg/kubectl/resource/builder_test.go index 32a2264a15c..a5e7892f662 100644 --- a/pkg/kubectl/resource/builder_test.go +++ b/pkg/kubectl/resource/builder_test.go @@ -253,7 +253,7 @@ var aRC string = ` func TestPathBuilderAndVersionedObjectNotDefaulted(t *testing.T) { b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, false, "../../../test/fixtures/pkg/kubectl/builder/kitten-rc.yaml") + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../test/fixtures/pkg/kubectl/builder/kitten-rc.yaml"}}) test := &testVisitor{} singular := false @@ -356,7 +356,7 @@ func TestPathBuilderWithMultiple(t *testing.T) { for _, test := range tests { b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, test.recursive, test.directory). + FilenameParam(false, &FilenameOptions{Recursive: test.recursive, Filenames: []string{test.directory}}). NamespaceParam("test").DefaultNamespace() testVisitor := &testVisitor{} @@ -415,7 +415,7 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) { for _, test := range tests { b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, test.recursive, test.directory). + FilenameParam(false, &FilenameOptions{Recursive: test.recursive, Filenames: []string{test.directory}}). NamespaceParam("test").DefaultNamespace() testVisitor := &testVisitor{} @@ -430,7 +430,7 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) { func TestDirectoryBuilder(t *testing.T) { b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, false, "../../../examples/guestbook/legacy"). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy"}}). NamespaceParam("test").DefaultNamespace() test := &testVisitor{} @@ -461,7 +461,7 @@ func TestNamespaceOverride(t *testing.T) { defer s.Close() b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, false, s.URL). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}). NamespaceParam("test") test := &testVisitor{} @@ -472,7 +472,7 @@ func TestNamespaceOverride(t *testing.T) { } b = NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(true, false, s.URL). + FilenameParam(true, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}). NamespaceParam("test") test = &testVisitor{} @@ -492,7 +492,7 @@ func TestURLBuilder(t *testing.T) { defer s.Close() b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, false, s.URL). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}). NamespaceParam("foo") test := &testVisitor{} @@ -521,7 +521,7 @@ func TestURLBuilderRequireNamespace(t *testing.T) { defer s.Close() b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, false, s.URL). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}). NamespaceParam("test").RequireNamespace() test := &testVisitor{} @@ -941,7 +941,7 @@ func TestContinueOnErrorVisitor(t *testing.T) { func TestSingularObject(t *testing.T) { obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, false, "../../../examples/guestbook/legacy/redis-master-controller.yaml"). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}). Flatten(). Do().Object() @@ -961,7 +961,7 @@ func TestSingularObject(t *testing.T) { func TestSingularObjectNoExtension(t *testing.T) { obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, false, "../../../examples/pod"). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/pod"}}). Flatten(). Do().Object() @@ -1072,7 +1072,7 @@ func TestWatch(t *testing.T) { }), }), testapi.Default.Codec()). NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, false, "../../../examples/guestbook/redis-master-service.yaml").Flatten(). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/redis-master-service.yaml"}}).Flatten(). Do().Watch("12") if err != nil { @@ -1099,8 +1099,8 @@ func TestWatch(t *testing.T) { func TestWatchMultipleError(t *testing.T) { _, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, false, "../../../examples/guestbook/legacy/redis-master-controller.yaml").Flatten(). - FilenameParam(false, false, "../../../examples/guestbook/legacy/redis-master-controller.yaml").Flatten(). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}).Flatten(). + FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}).Flatten(). Do().Watch("") if err == nil {