From be0cadde2eae139b3959a2fcae81d5b63f9d7041 Mon Sep 17 00:00:00 2001 From: Di Xu Date: Fri, 11 Aug 2017 14:21:44 +0800 Subject: [PATCH] enforce include-uninitialized in several kubectl commands --- pkg/kubectl/cmd/annotate.go | 7 ++++-- pkg/kubectl/cmd/apply.go | 16 ++++++++---- pkg/kubectl/cmd/apply_edit_last_applied.go | 3 ++- pkg/kubectl/cmd/create.go | 2 +- pkg/kubectl/cmd/delete.go | 11 +++++--- pkg/kubectl/cmd/delete_test.go | 17 ++++++++++--- pkg/kubectl/cmd/describe.go | 7 ++++++ pkg/kubectl/cmd/edit.go | 3 ++- pkg/kubectl/cmd/get.go | 16 +++++++++--- pkg/kubectl/cmd/label.go | 7 ++++-- pkg/kubectl/cmd/set/helper.go | 4 +-- pkg/kubectl/cmd/set/set_image.go | 7 ++++-- pkg/kubectl/cmd/set/set_resources.go | 8 +++--- pkg/kubectl/cmd/set/set_selector.go | 5 +++- pkg/kubectl/cmd/set/set_serviceaccount.go | 5 +++- pkg/kubectl/cmd/set/set_subject.go | 7 ++++-- pkg/kubectl/cmd/util/editor/BUILD | 1 + pkg/kubectl/cmd/util/editor/editoptions.go | 6 ++++- pkg/kubectl/cmd/util/helpers.go | 29 +++++++++++++++++++--- 19 files changed, 123 insertions(+), 38 deletions(-) diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index 5d8eeebe124..318aeb75941 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -128,10 +128,11 @@ func NewCmdAnnotate(f cmdutil.Factory, out io.Writer) *cobra.Command { ArgAliases: argAliases, } cmdutil.AddPrinterFlags(cmd) + cmdutil.AddIncludeUninitializedFlag(cmd) cmd.Flags().Bool("overwrite", false, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.") cmd.Flags().Bool("local", false, "If true, annotation will NOT contact api-server but run locally.") - cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().Bool("all", false, "Select all resources in the namespace of the specified resource types") + cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2).") + cmd.Flags().Bool("all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types.") cmd.Flags().String("resource-version", "", i18n.T("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 := "identifying the resource to update the annotation" cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) @@ -190,10 +191,12 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro return err } + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) b := builder. ContinueOnError(). NamespaceParam(namespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). + IncludeUninitialized(includeUninitialized). Flatten() if !o.local { diff --git a/pkg/kubectl/cmd/apply.go b/pkg/kubectl/cmd/apply.go index b4ace54fa87..5b756c81e7b 100644 --- a/pkg/kubectl/cmd/apply.go +++ b/pkg/kubectl/cmd/apply.go @@ -118,7 +118,7 @@ func NewCmdApply(baseName string, f cmdutil.Factory, out, errOut io.Writer) *cob cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, 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") - cmd.Flags().BoolVar(&options.Prune, "prune", false, "Automatically delete resource objects that do not appear in the configs and are created by either apply or create --save-config. Should be used with either -l or --all.") + cmd.Flags().BoolVar(&options.Prune, "prune", false, "Automatically delete resource objects, including the uninitialized ones, that do not appear in the configs and are created by either apply or create --save-config. Should be used with either -l or --all.") cmd.Flags().BoolVar(&options.Cascade, "cascade", true, "Only relevant during a prune or a force apply. If true, cascade the deletion of the resources managed by pruned or deleted resources (e.g. Pods created by a ReplicationController).") cmd.Flags().IntVar(&options.GracePeriod, "grace-period", -1, "Only relevant during a prune or a force apply. Period of time in seconds given to pruned or deleted resources to terminate gracefully. Ignored if negative.") cmd.Flags().BoolVar(&options.Force, "force", false, fmt.Sprintf("Delete and re-create the specified resource, when PATCH encounters conflict and has retried for %d times.", maxPatchRetry)) @@ -131,6 +131,7 @@ func NewCmdApply(baseName string, f cmdutil.Factory, out, errOut io.Writer) *cob cmdutil.AddPrinterFlags(cmd) cmdutil.AddRecordFlag(cmd) cmdutil.AddInclude3rdPartyFlags(cmd) + cmdutil.AddIncludeUninitializedFlag(cmd) // apply subcommands cmd.AddCommand(NewCmdApplyViewLastApplied(f, out, errOut)) @@ -214,12 +215,17 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti return err } + // include the uninitialized objects by default if --prune is true + // unless explicitly set --include-uninitialized=false + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, options.Prune) + r := builder. Schema(schema). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &options.FilenameOptions). SelectorParam(options.Selector). + IncludeUninitialized(includeUninitialized). Flatten(). Do() err = r.Err() @@ -381,13 +387,13 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti for n := range visitedNamespaces { for _, m := range namespacedRESTMappings { - if err := p.prune(n, m, shortOutput); err != nil { + if err := p.prune(n, m, shortOutput, includeUninitialized); err != nil { return fmt.Errorf("error pruning namespaced object %v: %v", m.GroupVersionKind, err) } } } for _, m := range nonNamespacedRESTMappings { - if err := p.prune(metav1.NamespaceNone, m, shortOutput); err != nil { + if err := p.prune(metav1.NamespaceNone, m, shortOutput, includeUninitialized); err != nil { return fmt.Errorf("error pruning nonNamespaced object %v: %v", m.GroupVersionKind, err) } } @@ -460,13 +466,13 @@ type pruner struct { out io.Writer } -func (p *pruner) prune(namespace string, mapping *meta.RESTMapping, shortOutput bool) error { +func (p *pruner) prune(namespace string, mapping *meta.RESTMapping, shortOutput, includeUninitialized bool) error { c, err := p.clientFunc(mapping) if err != nil { return err } - objList, err := resource.NewHelper(c, mapping).List(namespace, mapping.GroupVersionKind.Version, p.selector, false, false) + objList, err := resource.NewHelper(c, mapping).List(namespace, mapping.GroupVersionKind.Version, p.selector, false, includeUninitialized) if err != nil { return err } diff --git a/pkg/kubectl/cmd/apply_edit_last_applied.go b/pkg/kubectl/cmd/apply_edit_last_applied.go index 519737e0d2e..ca4868fa5b8 100644 --- a/pkg/kubectl/cmd/apply_edit_last_applied.go +++ b/pkg/kubectl/cmd/apply_edit_last_applied.go @@ -82,7 +82,7 @@ func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra Example: applyEditLastAppliedExample, Run: func(cmd *cobra.Command, args []string) { options.ChangeCause = f.Command(cmd, false) - if err := options.Complete(f, out, errOut, args); err != nil { + if err := options.Complete(f, out, errOut, args, cmd); err != nil { cmdutil.CheckErr(err) } if err := options.Run(); err != nil { @@ -99,6 +99,7 @@ func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra cmd.Flags().BoolVar(&options.WindowsLineEndings, "windows-line-endings", runtime.GOOS == "windows", "Defaults to the line ending native to your platform.") cmdutil.AddRecordVarFlag(cmd, &options.Record) + cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } diff --git a/pkg/kubectl/cmd/create.go b/pkg/kubectl/cmd/create.go index 7447d50c3a9..77405db897e 100644 --- a/pkg/kubectl/cmd/create.go +++ b/pkg/kubectl/cmd/create.go @@ -209,7 +209,7 @@ func RunEditOnCreate(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Comman ChangeCause: f.Command(cmd, false), Include3rdParty: cmdutil.GetFlagBool(cmd, "include-extended-apis"), } - err := editOptions.Complete(f, out, errOut, []string{}) + err := editOptions.Complete(f, out, errOut, []string{}, cmd) if err != nil { return err } diff --git a/pkg/kubectl/cmd/delete.go b/pkg/kubectl/cmd/delete.go index 7e815411298..814b6aa4f17 100644 --- a/pkg/kubectl/cmd/delete.go +++ b/pkg/kubectl/cmd/delete.go @@ -133,7 +133,7 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { Example: delete_example, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - if err := options.Complete(f, out, errOut, args); err != nil { + if err := options.Complete(f, out, errOut, args, cmd); err != nil { cmdutil.CheckErr(err) } if err := options.Validate(cmd); err != nil { @@ -149,8 +149,8 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { } usage := "containing the resource to delete." cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) - cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on.") - cmd.Flags().BoolVar(&options.DeleteAll, "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, not including uninitialized ones.") + cmd.Flags().BoolVar(&options.DeleteAll, "all", false, "Delete all resources, including uninitialized ones, in the namespace of the specified resource types.") cmd.Flags().BoolVar(&options.IgnoreNotFound, "ignore-not-found", false, "Treat \"resource not found\" as a successful delete. Defaults to \"true\" when --all is specified.") cmd.Flags().BoolVar(&options.Cascade, "cascade", true, "If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.") cmd.Flags().IntVar(&options.GracePeriod, "grace-period", -1, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.") @@ -159,10 +159,11 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { cmd.Flags().DurationVar(&options.Timeout, "timeout", 0, "The length of time to wait before giving up on a delete, zero means determine a timeout from the size of the object") cmdutil.AddOutputVarFlagsForMutation(cmd, &options.Output) cmdutil.AddInclude3rdPartyVarFlags(cmd, &options.Include3rdParty) + cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } -func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string) error { +func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string, cmd *cobra.Command) error { cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err @@ -180,11 +181,13 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args } o.Mapper = mapper + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) r := builder. ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). SelectorParam(o.Selector). + IncludeUninitialized(includeUninitialized). SelectAllParam(o.DeleteAll). ResourceTypeOrNameArgs(false, args...).RequireObject(false). Flatten(). diff --git a/pkg/kubectl/cmd/delete_test.go b/pkg/kubectl/cmd/delete_test.go index 677e29660ff..5cd244d391e 100644 --- a/pkg/kubectl/cmd/delete_test.go +++ b/pkg/kubectl/cmd/delete_test.go @@ -26,6 +26,8 @@ import ( "testing" "time" + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -41,6 +43,13 @@ import ( var unstructuredSerializer = dynamic.ContentConfig().NegotiatedSerializer +var fakecmd = &cobra.Command{ + Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])", + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) + }, +} + func TestDeleteObjectByTuple(t *testing.T) { initTestErrorHandler(t) _, _, rc := testData() @@ -345,7 +354,7 @@ func TestDeleteObjectNotFound(t *testing.T) { Cascade: false, Output: "name", } - err := options.Complete(f, buf, errBuf, []string{}) + err := options.Complete(f, buf, errBuf, []string{}, fakecmd) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -426,7 +435,7 @@ func TestDeleteAllNotFound(t *testing.T) { IgnoreNotFound: false, Output: "name", } - err := options.Complete(f, buf, errBuf, []string{"services"}) + err := options.Complete(f, buf, errBuf, []string{"services"}, fakecmd) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -546,7 +555,7 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { Cascade: false, Output: "name", } - err := options.Complete(f, buf, errBuf, []string{}) + err := options.Complete(f, buf, errBuf, []string{}, fakecmd) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -714,7 +723,7 @@ func TestResourceErrors(t *testing.T) { Cascade: false, Output: "name", } - err := options.Complete(f, buf, errBuf, testCase.args) + err := options.Complete(f, buf, errBuf, testCase.args, fakecmd) 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 06f465834a5..993c74ceab0 100644 --- a/pkg/kubectl/cmd/describe.go +++ b/pkg/kubectl/cmd/describe.go @@ -39,6 +39,7 @@ import ( var ( describe_long = templates.LongDesc(` Show details of a specific resource or group of resources. + It includes the uninitialized objects, unless --include-uninitialized=false is explicitly set. This command joins many API calls together to form a detailed description of a given resource or group of resources. @@ -97,6 +98,7 @@ func NewCmdDescribe(f cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { 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.") cmdutil.AddInclude3rdPartyFlags(cmd) + cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } @@ -120,11 +122,16 @@ func RunDescribe(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, a return err } + // include the uninitialized objects by default + // unless user explicitly set --include-uninitialized=false + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, true) + r := builder. ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). FilenameParam(enforceNamespace, options). SelectorParam(selector). + IncludeUninitialized(includeUninitialized). ResourceTypeOrNameArgs(true, args...). Flatten(). Do() diff --git a/pkg/kubectl/cmd/edit.go b/pkg/kubectl/cmd/edit.go index 4aadfff3598..11ef23c6bd5 100644 --- a/pkg/kubectl/cmd/edit.go +++ b/pkg/kubectl/cmd/edit.go @@ -93,7 +93,7 @@ func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { Example: fmt.Sprintf(editExample), Run: func(cmd *cobra.Command, args []string) { options.ChangeCause = f.Command(cmd, false) - if err := options.Complete(f, out, errOut, args); err != nil { + if err := options.Complete(f, out, errOut, args, cmd); err != nil { cmdutil.CheckErr(err) } if err := options.Run(); err != nil { @@ -115,5 +115,6 @@ func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { cmdutil.AddApplyAnnotationVarFlags(cmd, &options.ApplyAnnotation) cmdutil.AddRecordVarFlag(cmd, &options.Record) cmdutil.AddInclude3rdPartyVarFlags(cmd, &options.Include3rdParty) + cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } diff --git a/pkg/kubectl/cmd/get.go b/pkg/kubectl/cmd/get.go index 97fa85d4bfc..3c1873d76b6 100644 --- a/pkg/kubectl/cmd/get.go +++ b/pkg/kubectl/cmd/get.go @@ -58,7 +58,8 @@ var ( This command will hide resources that have completed, such as pods that are in the Succeeded or Failed phases. You can see the full results for any - resource by providing the '--show-all' flag. + resource by providing the '--show-all' flag, but this flag does not include + the uninitialized objects by default, unless '--include-uninitialized' is explicitly set. By specifying the output as 'template' and providing a Go template as the value of the --template flag, you can filter the attributes of the fetched resources.`) @@ -127,7 +128,8 @@ func NewCmdGet(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comman } cmdutil.AddPrinterFlags(cmd) cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().BoolP("watch", "w", false, "After listing/getting the requested object, watch for changes.") + cmdutil.AddIncludeUninitializedFlag(cmd) + cmd.Flags().BoolP("watch", "w", false, "After listing/getting the requested object, watch for changes. Uninitialized objects are excluded if no object name is provided.") cmd.Flags().Bool("watch-only", false, "Watch for changes to the requested object(s), without listing/getting first.") cmd.Flags().Bool("show-kind", false, "If present, list the resource type for the requested object(s).") 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.") @@ -195,13 +197,21 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [ } export := cmdutil.GetFlagBool(cmd, "export") - includeUninitialized := cmdutil.GetFlagBool(cmd, "include-uninitialized") filterFuncs := f.DefaultResourceFilterFunc() filterOpts := f.DefaultResourceFilterOptions(cmd, allNamespaces) // handle watch separately since we cannot watch multiple resource types isWatch, isWatchOnly := cmdutil.GetFlagBool(cmd, "watch"), cmdutil.GetFlagBool(cmd, "watch-only") + + var includeUninitialized bool + if isWatch && len(args) == 2 { + // include the uninitialized one for watching on a single object + // unless explicitly set --include-uninitialized=false + includeUninitialized = true + } + includeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, includeUninitialized) + if isWatch || isWatchOnly { builder, err := f.NewUnstructuredBuilder(true) if err != nil { diff --git a/pkg/kubectl/cmd/label.go b/pkg/kubectl/cmd/label.go index 9b9d81e7605..0819a5e6332 100644 --- a/pkg/kubectl/cmd/label.go +++ b/pkg/kubectl/cmd/label.go @@ -128,14 +128,15 @@ func NewCmdLabel(f cmdutil.Factory, out io.Writer) *cobra.Command { cmdutil.AddPrinterFlags(cmd) cmd.Flags().Bool("overwrite", false, "If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.") cmd.Flags().Bool("local", false, "If true, label will NOT contact api-server but run locally.") - cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") - cmd.Flags().Bool("all", false, "Select all resources in the namespace of the specified resource types") + cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2).") + cmd.Flags().Bool("all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") cmd.Flags().String("resource-version", "", i18n.T("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 := "identifying the resource to update the labels" cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmdutil.AddDryRunFlag(cmd) cmdutil.AddRecordFlag(cmd) cmdutil.AddInclude3rdPartyFlags(cmd) + cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } @@ -185,10 +186,12 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error { return err } + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) b := builder. ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). + IncludeUninitialized(includeUninitialized). Flatten() if !o.local { diff --git a/pkg/kubectl/cmd/set/helper.go b/pkg/kubectl/cmd/set/helper.go index 35d49dc46e2..5fd7f2b94e2 100644 --- a/pkg/kubectl/cmd/set/helper.go +++ b/pkg/kubectl/cmd/set/helper.go @@ -25,7 +25,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/kubernetes/pkg/api" - kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/resource" ) @@ -61,7 +61,7 @@ func handlePodUpdateError(out io.Writer, err error, resource string) { return } } else { - if ok := kcmdutil.PrintErrorWithCauses(err, out); ok { + if ok := cmdutil.PrintErrorWithCauses(err, out); ok { return } } diff --git a/pkg/kubectl/cmd/set/set_image.go b/pkg/kubectl/cmd/set/set_image.go index a865bd80f1d..83fa12171b0 100644 --- a/pkg/kubectl/cmd/set/set_image.go +++ b/pkg/kubectl/cmd/set/set_image.go @@ -105,11 +105,12 @@ func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command { cmdutil.AddPrinterFlags(cmd) 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, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().BoolVar(&options.All, "all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") + cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set image will NOT contact api-server but run locally.") cmdutil.AddRecordFlag(cmd) cmdutil.AddDryRunFlag(cmd) + cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } @@ -137,10 +138,12 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st return err } + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) builder := f.NewBuilder(!o.Local). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). + IncludeUninitialized(includeUninitialized). Flatten() if !o.Local { builder = builder. diff --git a/pkg/kubectl/cmd/set/set_resources.go b/pkg/kubectl/cmd/set/set_resources.go index fa2aee7f54e..e3cff84942c 100644 --- a/pkg/kubectl/cmd/set/set_resources.go +++ b/pkg/kubectl/cmd/set/set_resources.go @@ -114,12 +114,13 @@ func NewCmdResources(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra. //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, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().BoolVar(&options.All, "all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") + cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones,supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().StringVarP(&options.ContainerSelector, "containers", "c", "*", "The names of containers in the selected pod templates to change, all containers are selected by default - may use wildcards") cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set resources will NOT contact api-server but run locally.") cmdutil.AddDryRunFlag(cmd) cmdutil.AddRecordFlag(cmd) + cmdutil.AddIncludeUninitializedFlag(cmd) cmd.Flags().StringVar(&options.Limits, "limits", options.Limits, "The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.") cmd.Flags().StringVar(&options.Requests, "requests", options.Requests, "The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.") return cmd @@ -141,11 +142,12 @@ func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args return err } + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) builder := f.NewBuilder(!o.Local). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). - //FilenameParam(enforceNamespace, o.Filenames...). FilenameParam(enforceNamespace, &o.FilenameOptions). + IncludeUninitialized(includeUninitialized). Flatten() if !o.Local { diff --git a/pkg/kubectl/cmd/set/set_selector.go b/pkg/kubectl/cmd/set/set_selector.go index 05398c95c8d..ae3f074099d 100644 --- a/pkg/kubectl/cmd/set/set_selector.go +++ b/pkg/kubectl/cmd/set/set_selector.go @@ -89,13 +89,14 @@ func NewCmdSelector(f cmdutil.Factory, out io.Writer) *cobra.Command { }, } cmdutil.AddPrinterFlags(cmd) - cmd.Flags().Bool("all", false, "Select all resources in the namespace of the specified resource types") + cmd.Flags().Bool("all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") cmd.Flags().Bool("local", false, "If true, set selector will NOT contact api-server but run locally.") cmd.Flags().String("resource-version", "", "If non-empty, the selectors update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.") usage := "the resource to update the selectors" cmdutil.AddFilenameOptionFlags(cmd, &options.fileOptions, usage) cmdutil.AddDryRunFlag(cmd) cmdutil.AddRecordFlag(cmd) + cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } @@ -121,10 +122,12 @@ func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [ return err } + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) o.builder = f.NewBuilder(!o.local). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.fileOptions). + IncludeUninitialized(includeUninitialized). Flatten() if !o.local { diff --git a/pkg/kubectl/cmd/set/set_serviceaccount.go b/pkg/kubectl/cmd/set/set_serviceaccount.go index ea088c53331..f983c170890 100644 --- a/pkg/kubectl/cmd/set/set_serviceaccount.go +++ b/pkg/kubectl/cmd/set/set_serviceaccount.go @@ -95,10 +95,11 @@ func NewCmdServiceAccount(f cmdutil.Factory, out, err io.Writer) *cobra.Command usage := "identifying the resource to get from a server." cmdutil.AddFilenameOptionFlags(cmd, &saConfig.fileNameOptions, usage) - cmd.Flags().BoolVar(&saConfig.all, "all", false, "Select all resources in the namespace of the specified resource types") + cmd.Flags().BoolVar(&saConfig.all, "all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") cmd.Flags().BoolVar(&saConfig.local, "local", false, "If true, set image will NOT contact api-server but run locally.") cmdutil.AddRecordFlag(cmd) cmdutil.AddDryRunFlag(cmd) + cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } @@ -124,9 +125,11 @@ func (saConfig *serviceAccountConfig) Complete(f cmdutil.Factory, cmd *cobra.Com } saConfig.serviceAccountName = args[len(args)-1] resources := args[:len(args)-1] + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) builder := f.NewBuilder(!saConfig.local).ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &saConfig.fileNameOptions). + IncludeUninitialized(includeUninitialized). Flatten() if !saConfig.local { builder.ResourceTypeOrNameArgs(saConfig.all, resources...). diff --git a/pkg/kubectl/cmd/set/set_subject.go b/pkg/kubectl/cmd/set/set_subject.go index 899f504ab31..791021b9b2f 100644 --- a/pkg/kubectl/cmd/set/set_subject.go +++ b/pkg/kubectl/cmd/set/set_subject.go @@ -98,13 +98,14 @@ func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Co cmdutil.AddPrinterFlags(cmd) usage := "the resource to update the subjects" 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, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().BoolVar(&options.All, "all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") + cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set resources will NOT contact api-server but run locally.") cmdutil.AddDryRunFlag(cmd) cmd.Flags().StringArrayVar(&options.Users, "user", []string{}, "Usernames to bind to the role") cmd.Flags().StringArrayVar(&options.Groups, "group", []string{}, "Groups to bind to the role") cmd.Flags().StringArrayVar(&options.ServiceAccounts, "serviceaccount", []string{}, "Service accounts to bind to the role") + cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } @@ -123,10 +124,12 @@ func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [] return err } + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) builder := f.NewBuilder(!o.Local). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). + IncludeUninitialized(includeUninitialized). Flatten() if !o.Local { diff --git a/pkg/kubectl/cmd/util/editor/BUILD b/pkg/kubectl/cmd/util/editor/BUILD index 31abf38cc4c..d0bcd1b1368 100644 --- a/pkg/kubectl/cmd/util/editor/BUILD +++ b/pkg/kubectl/cmd/util/editor/BUILD @@ -23,6 +23,7 @@ go_library( "//pkg/printers:go_default_library", "//vendor/github.com/evanphx/json-patch:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", diff --git a/pkg/kubectl/cmd/util/editor/editoptions.go b/pkg/kubectl/cmd/util/editor/editoptions.go index cc15bd59a0a..2374ec2d8fc 100644 --- a/pkg/kubectl/cmd/util/editor/editoptions.go +++ b/pkg/kubectl/cmd/util/editor/editoptions.go @@ -29,6 +29,7 @@ import ( "github.com/evanphx/json-patch" "github.com/golang/glog" + "github.com/spf13/cobra" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" @@ -86,7 +87,7 @@ type editPrinterOptions struct { } // Complete completes all the required options -func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string) error { +func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string, cmd *cobra.Command) error { if o.EditMode != NormalEditMode && o.EditMode != EditBeforeCreateMode && o.EditMode != ApplyEditMode { return fmt.Errorf("unsupported edit mode %q", o.EditMode) } @@ -118,8 +119,10 @@ func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args [] // when do normal edit or apply edit we need to always retrieve the latest resource from server b = b.ResourceTypeOrNameArgs(true, args...).Latest() } + includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) r := b.NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). + IncludeUninitialized(includeUninitialized). ContinueOnError(). Flatten(). Do() @@ -133,6 +136,7 @@ func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args [] // resource builder to read objects from edited data return resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme). Stream(bytes.NewReader(data), "edited-file"). + IncludeUninitialized(includeUninitialized). ContinueOnError(). Flatten(). Do() diff --git a/pkg/kubectl/cmd/util/helpers.go b/pkg/kubectl/cmd/util/helpers.go index ca88b0daad8..29a5b7b942b 100644 --- a/pkg/kubectl/cmd/util/helpers.go +++ b/pkg/kubectl/cmd/util/helpers.go @@ -52,8 +52,9 @@ import ( ) const ( - ApplyAnnotationsFlag = "save-config" - DefaultErrorExitCode = 1 + ApplyAnnotationsFlag = "save-config" + DefaultErrorExitCode = 1 + IncludeUninitializedFlag = "include-uninitialized" ) type debugError interface { @@ -431,7 +432,7 @@ func AddDryRunFlag(cmd *cobra.Command) { } func AddIncludeUninitializedFlag(cmd *cobra.Command) { - cmd.Flags().Bool("include-uninitialized", false, "If true, include the object(s) that have not been realized yet. Such object(s) have a non-empty initializer list.") + cmd.Flags().Bool(IncludeUninitializedFlag, false, `If true, the kubectl command applies to uninitialized objects. If explicitly set to false, this flag overrides other flags that make the kubectl commands apply to uninitialized objects, e.g., "--all". Objects with empty metadata.initializers are regarded as initialized.`) } func AddPodRunningTimeoutFlag(cmd *cobra.Command, defaultTimeout time.Duration) { @@ -840,3 +841,25 @@ func ManualStrip(file []byte) []byte { } return stripped } + +// ShouldIncludeUninitialized identifies whether to include uninitialized objects. +// includeUninitialized is the default value. +// Assume we can parse `all` and `selector` from cmd. +func ShouldIncludeUninitialized(cmd *cobra.Command, includeUninitialized bool) bool { + shouldIncludeUninitialized := includeUninitialized + if cmd.Flags().Lookup("all") != nil && GetFlagBool(cmd, "all") { + // include the uninitialized objects by default + // unless explicitly set --include-uninitialized=false + shouldIncludeUninitialized = true + } + if cmd.Flags().Lookup("selector") != nil && GetFlagString(cmd, "selector") != "" { + // does not include the uninitialized objects by default + // unless explicitly set --include-uninitialized=true + shouldIncludeUninitialized = false + } + if cmd.Flags().Changed(IncludeUninitializedFlag) { + // get explicit value + shouldIncludeUninitialized = GetFlagBool(cmd, IncludeUninitializedFlag) + } + return shouldIncludeUninitialized +}