diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index 1b5864f2c7e..a66d86d7923 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -56,6 +56,7 @@ type AnnotateOptions struct { all bool resourceVersion string selector string + fieldSelector string outputFormat string // results of arg parsing @@ -144,6 +145,7 @@ func NewCmdAnnotate(parent string, f cmdutil.Factory, ioStreams genericclioption cmd.Flags().BoolVar(&o.overwrite, "overwrite", o.overwrite, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.") cmd.Flags().BoolVar(&o.local, "local", o.local, "If true, annotation will NOT contact api-server but run locally.") cmd.Flags().StringVarP(&o.selector, "selector", "l", o.selector, "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2).") + cmd.Flags().StringVar(&o.fieldSelector, "field-selector", o.fieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") cmd.Flags().BoolVar(&o.all, "all", o.all, "Select all resources, including uninitialized ones, in the namespace of the specified resource types.") cmd.Flags().StringVar(&o.resourceVersion, "resource-version", o.resourceVersion, 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" @@ -205,6 +207,9 @@ func (o AnnotateOptions) Validate() error { if o.all && len(o.selector) > 0 { return fmt.Errorf("cannot set --all and --selector at the same time") } + if o.all && len(o.fieldSelector) > 0 { + return fmt.Errorf("cannot set --all and --field-selector at the same time") + } if len(o.resources) < 1 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { return fmt.Errorf("one or more resources must be specified as or /") } @@ -227,6 +232,7 @@ func (o AnnotateOptions) RunAnnotate() error { if !o.local { b = b.LabelSelectorParam(o.selector). + FieldSelectorParam(o.fieldSelector). ResourceTypeOrNameArgs(o.all, o.resources...). Latest() } diff --git a/pkg/kubectl/cmd/delete.go b/pkg/kubectl/cmd/delete.go index ed14f31fbab..b27072c1819 100644 --- a/pkg/kubectl/cmd/delete.go +++ b/pkg/kubectl/cmd/delete.go @@ -90,7 +90,8 @@ var ( type DeleteOptions struct { resource.FilenameOptions - Selector string + LabelSelector string + FieldSelector string DeleteAll bool IgnoreNotFound bool Cascade bool @@ -143,9 +144,6 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { deleteFlags.AddFlags(cmd) - // flag-specific output flag, as this command does not depend on PrintFlags - cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones.") - cmdutil.AddIncludeUninitializedFlag(cmd) return cmd } @@ -156,7 +154,6 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args return err } - o.Selector = cmdutil.GetFlagString(cmd, "selector") o.Reaper = f.Reaper includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) @@ -165,7 +162,8 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &o.FilenameOptions). - LabelSelectorParam(o.Selector). + LabelSelectorParam(o.LabelSelector). + FieldSelectorParam(o.FieldSelector). IncludeUninitialized(includeUninitialized). SelectAllParam(o.DeleteAll). ResourceTypeOrNameArgs(false, args...).RequireObject(false). @@ -186,9 +184,12 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args } func (o *DeleteOptions) Validate(cmd *cobra.Command) error { - if o.DeleteAll && len(o.Selector) > 0 { + if o.DeleteAll && len(o.LabelSelector) > 0 { return fmt.Errorf("cannot set --all and --selector at the same time") } + if o.DeleteAll && len(o.FieldSelector) > 0 { + return fmt.Errorf("cannot set --all and --field-selector at the same time") + } if o.DeleteAll { f := cmd.Flags().Lookup("ignore-not-found") // The flag should never be missing diff --git a/pkg/kubectl/cmd/delete_flags.go b/pkg/kubectl/cmd/delete_flags.go index e611c6174dd..10cc3d85ea8 100644 --- a/pkg/kubectl/cmd/delete_flags.go +++ b/pkg/kubectl/cmd/delete_flags.go @@ -59,6 +59,8 @@ func (o *FileNameFlags) AddFlags(cmd *cobra.Command) { // used for commands requiring deletion logic. type DeleteFlags struct { FileNameFlags *FileNameFlags + LabelSelector *string + FieldSelector *string All *bool Cascade *bool @@ -80,6 +82,12 @@ func (f *DeleteFlags) ToOptions(out, errOut io.Writer) *DeleteOptions { if f.FileNameFlags != nil { options.FilenameOptions = f.FileNameFlags.ToOptions() } + if f.LabelSelector != nil { + options.LabelSelector = *f.LabelSelector + } + if f.FieldSelector != nil { + options.FieldSelector = *f.FieldSelector + } // add output format if f.Output != nil { @@ -113,7 +121,12 @@ func (f *DeleteFlags) ToOptions(out, errOut io.Writer) *DeleteOptions { func (f *DeleteFlags) AddFlags(cmd *cobra.Command) { f.FileNameFlags.AddFlags(cmd) - + if f.LabelSelector != nil { + cmd.Flags().StringVarP(f.LabelSelector, "selector", "l", *f.LabelSelector, "Selector (label query) to filter on, not including uninitialized ones.") + } + if f.FieldSelector != nil { + cmd.Flags().StringVarP(f.FieldSelector, "field-selector", "", *f.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") + } if f.All != nil { cmd.Flags().BoolVar(f.All, "all", *f.All, "Delete all resources, including uninitialized ones, in the namespace of the specified resource types.") } @@ -153,6 +166,8 @@ func NewDeleteCommandFlags(usage string) *DeleteFlags { ignoreNotFound := false now := false output := "" + labelSelector := "" + fieldSelector := "" timeout := time.Duration(0) filenames := []string{} @@ -160,6 +175,8 @@ func NewDeleteCommandFlags(usage string) *DeleteFlags { return &DeleteFlags{ FileNameFlags: &FileNameFlags{Usage: usage, Filenames: &filenames, Recursive: &recursive}, + LabelSelector: &labelSelector, + FieldSelector: &fieldSelector, Cascade: &cascade, GracePeriod: &gracePeriod, diff --git a/pkg/kubectl/cmd/delete_test.go b/pkg/kubectl/cmd/delete_test.go index 9e7da6b21af..ca3a1846edb 100644 --- a/pkg/kubectl/cmd/delete_test.go +++ b/pkg/kubectl/cmd/delete_test.go @@ -52,8 +52,6 @@ func fakecmd() *cobra.Command { cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) }, } - - cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones.") return cmd } diff --git a/pkg/kubectl/cmd/label.go b/pkg/kubectl/cmd/label.go index 8257d7582d2..0d6b439dbd9 100644 --- a/pkg/kubectl/cmd/label.go +++ b/pkg/kubectl/cmd/label.go @@ -59,6 +59,7 @@ type LabelOptions struct { all bool resourceVersion string selector string + fieldSelector string outputFormat string // results of arg parsing @@ -146,6 +147,7 @@ func NewCmdLabel(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobr cmd.Flags().BoolVar(&o.list, "list", o.list, "If true, display the labels for a given resource.") cmd.Flags().BoolVar(&o.local, "local", o.local, "If true, label will NOT contact api-server but run locally.") cmd.Flags().StringVarP(&o.selector, "selector", "l", o.selector, "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2).") + cmd.Flags().StringVar(&o.fieldSelector, "field-selector", o.fieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") cmd.Flags().BoolVar(&o.all, "all", o.all, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") cmd.Flags().StringVar(&o.resourceVersion, "resource-version", o.resourceVersion, 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" @@ -209,6 +211,9 @@ func (o *LabelOptions) Validate() error { if o.all && len(o.selector) > 0 { return fmt.Errorf("cannot set --all and --selector at the same time") } + if o.all && len(o.fieldSelector) > 0 { + return fmt.Errorf("cannot set --all and --field-selector at the same time") + } if len(o.resources) < 1 && cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames) { return fmt.Errorf("one or more resources must be specified as or /") } @@ -231,6 +236,7 @@ func (o *LabelOptions) RunLabel() error { if !o.local { b = b.LabelSelectorParam(o.selector). + FieldSelectorParam(o.fieldSelector). ResourceTypeOrNameArgs(o.all, o.resources...). Latest() }