Unverified Commit 45bdf707 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #50140 from dixudx/kubectl_add_fieldSelector

Automatic merge from submit-queue (batch tested with PRs 53273, 55058, 55237, 50140). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. add field selector for kubectl get **What this PR does / why we need it**: When working in #50075, I found current kubectl did not support using `field-selector`. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #14129 **Special notes for your reviewer**: /cc @janetkuo @kargakis /assign @derekwaynecarr @smarterclayton @bgrant0607 **Release note**: ```release-note add field selector for kubectl get ```
parents 552d2b35 fa143c6d
...@@ -430,6 +430,13 @@ run_pod_tests() { ...@@ -430,6 +430,13 @@ run_pod_tests() {
kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}" kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
# Post-condition: valid-pod POD is created # Post-condition: valid-pod POD is created
kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:' kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
# Command
output_message=$(kubectl get pods --field-selector metadata.name=valid-pod "${kube_flags[@]}")
kube::test::if_has_string "${output_message}" "valid-pod"
# Command
phase=$(kubectl get "${kube_flags[@]}" pod valid-pod -o go-template='{{ .status.phase }}')
output_message=$(kubectl get pods --field-selector status.phase="${phase}" "${kube_flags[@]}")
kube::test::if_has_string "${output_message}" "valid-pod"
### Delete PODs with no parameter mustn't kill everything ### Delete PODs with no parameter mustn't kill everything
# Pre-condition: valid-pod POD exists # Pre-condition: valid-pod POD exists
......
...@@ -205,7 +205,7 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro ...@@ -205,7 +205,7 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro
return err return err
} }
b = b.SelectorParam(o.selector). b = b.LabelSelectorParam(o.selector).
Unstructured(f.UnstructuredClientForMapping, mapper, typer). Unstructured(f.UnstructuredClientForMapping, mapper, typer).
ResourceTypeOrNameArgs(o.all, o.resources...). ResourceTypeOrNameArgs(o.all, o.resources...).
Latest() Latest()
......
...@@ -219,7 +219,7 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti ...@@ -219,7 +219,7 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti
ContinueOnError(). ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, &options.FilenameOptions). FilenameParam(enforceNamespace, &options.FilenameOptions).
SelectorParam(options.Selector). LabelSelectorParam(options.Selector).
IncludeUninitialized(includeUninitialized). IncludeUninitialized(includeUninitialized).
Flatten(). Flatten().
Do() Do()
...@@ -367,8 +367,8 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti ...@@ -367,8 +367,8 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti
clientFunc: f.UnstructuredClientForMapping, clientFunc: f.UnstructuredClientForMapping,
clientsetFunc: f.ClientSet, clientsetFunc: f.ClientSet,
selector: options.Selector, labelSelector: options.Selector,
visitedUids: visitedUids, visitedUids: visitedUids,
cascade: options.Cascade, cascade: options.Cascade,
dryRun: dryRun, dryRun: dryRun,
...@@ -453,8 +453,9 @@ type pruner struct { ...@@ -453,8 +453,9 @@ type pruner struct {
clientFunc resource.ClientMapperFunc clientFunc resource.ClientMapperFunc
clientsetFunc func() (internalclientset.Interface, error) clientsetFunc func() (internalclientset.Interface, error)
visitedUids sets.String visitedUids sets.String
selector string labelSelector string
fieldSelector string
cascade bool cascade bool
dryRun bool dryRun bool
...@@ -474,7 +475,8 @@ func (p *pruner) prune(namespace string, mapping *meta.RESTMapping, shortOutput, ...@@ -474,7 +475,8 @@ func (p *pruner) prune(namespace string, mapping *meta.RESTMapping, shortOutput,
mapping.GroupVersionKind.Version, mapping.GroupVersionKind.Version,
false, false,
&metav1.ListOptions{ &metav1.ListOptions{
LabelSelector: p.selector, LabelSelector: p.labelSelector,
FieldSelector: p.fieldSelector,
IncludeUninitialized: includeUninitialized, IncludeUninitialized: includeUninitialized,
}, },
) )
......
...@@ -98,7 +98,7 @@ func (o *ViewLastAppliedOptions) Complete(f cmdutil.Factory, args []string) erro ...@@ -98,7 +98,7 @@ func (o *ViewLastAppliedOptions) Complete(f cmdutil.Factory, args []string) erro
FilenameParam(enforceNamespace, &o.FilenameOptions). FilenameParam(enforceNamespace, &o.FilenameOptions).
ResourceTypeOrNameArgs(enforceNamespace, args...). ResourceTypeOrNameArgs(enforceNamespace, args...).
SelectAllParam(o.All). SelectAllParam(o.All).
SelectorParam(o.Selector). LabelSelectorParam(o.Selector).
Latest(). Latest().
Flatten(). Flatten().
Do() Do()
......
...@@ -74,7 +74,7 @@ func RunClusterInfo(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error ...@@ -74,7 +74,7 @@ func RunClusterInfo(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error
// TODO use generalized labels once they are implemented (#341) // TODO use generalized labels once they are implemented (#341)
b := f.NewBuilder(). b := f.NewBuilder().
NamespaceParam(cmdNamespace).DefaultNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
SelectorParam("kubernetes.io/cluster-service=true"). LabelSelectorParam("kubernetes.io/cluster-service=true").
ResourceTypeOrNameArgs(false, []string{"services"}...). ResourceTypeOrNameArgs(false, []string{"services"}...).
Latest() Latest()
err = b.Do().Visit(func(r *resource.Info, err error) error { err = b.Do().Visit(func(r *resource.Info, err error) error {
......
...@@ -194,7 +194,7 @@ func RunCreate(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opt ...@@ -194,7 +194,7 @@ func RunCreate(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opt
ContinueOnError(). ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, &options.FilenameOptions). FilenameParam(enforceNamespace, &options.FilenameOptions).
SelectorParam(options.Selector). LabelSelectorParam(options.Selector).
Flatten(). Flatten().
Do() Do()
err = r.Err() err = r.Err()
......
...@@ -182,7 +182,7 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args ...@@ -182,7 +182,7 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args
ContinueOnError(). ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, &o.FilenameOptions). FilenameParam(enforceNamespace, &o.FilenameOptions).
SelectorParam(o.Selector). LabelSelectorParam(o.Selector).
IncludeUninitialized(includeUninitialized). IncludeUninitialized(includeUninitialized).
SelectAllParam(o.DeleteAll). SelectAllParam(o.DeleteAll).
ResourceTypeOrNameArgs(false, args...).RequireObject(false). ResourceTypeOrNameArgs(false, args...).RequireObject(false).
......
...@@ -129,7 +129,7 @@ func RunDescribe(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, a ...@@ -129,7 +129,7 @@ func RunDescribe(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, a
ContinueOnError(). ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces).
FilenameParam(enforceNamespace, options). FilenameParam(enforceNamespace, options).
SelectorParam(selector). LabelSelectorParam(selector).
IncludeUninitialized(includeUninitialized). IncludeUninitialized(includeUninitialized).
ResourceTypeOrNameArgs(true, args...). ResourceTypeOrNameArgs(true, args...).
Flatten(). Flatten().
......
...@@ -243,7 +243,7 @@ func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error { ...@@ -243,7 +243,7 @@ func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error {
Flatten() Flatten()
if len(o.Selector) > 0 { if len(o.Selector) > 0 {
builder = builder.SelectorParam(o.Selector). builder = builder.LabelSelectorParam(o.Selector).
ResourceTypes("nodes") ResourceTypes("nodes")
} }
......
...@@ -206,7 +206,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error { ...@@ -206,7 +206,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error {
return err return err
} }
b = b.SelectorParam(o.selector). b = b.LabelSelectorParam(o.selector).
Unstructured(f.UnstructuredClientForMapping, mapper, typer). Unstructured(f.UnstructuredClientForMapping, mapper, typer).
ResourceTypeOrNameArgs(o.all, o.resources...). ResourceTypeOrNameArgs(o.all, o.resources...).
Latest() Latest()
......
...@@ -199,7 +199,7 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Comm ...@@ -199,7 +199,7 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Comm
builder.ResourceNames("pods", o.ResourceArg) builder.ResourceNames("pods", o.ResourceArg)
} }
if selector != "" { if selector != "" {
builder.ResourceTypes("pods").SelectorParam(selector) builder.ResourceTypes("pods").LabelSelectorParam(selector)
} }
infos, err := builder.Do().Infos() infos, err := builder.Do().Infos()
if err != nil { if err != nil {
......
...@@ -56,6 +56,7 @@ type GetOptions struct { ...@@ -56,6 +56,7 @@ type GetOptions struct {
ChunkSize int64 ChunkSize int64
LabelSelector string LabelSelector string
FieldSelector string
AllNamespaces bool AllNamespaces bool
Namespace string Namespace string
ExplicitNamespace bool ExplicitNamespace bool
...@@ -158,6 +159,7 @@ func NewCmdGet(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comman ...@@ -158,6 +159,7 @@ func NewCmdGet(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comman
cmd.Flags().Int64Var(&options.ChunkSize, "chunk-size", 500, "Return large lists in chunks rather than all at once. Pass 0 to disable. This flag is beta and may change in the future.") cmd.Flags().Int64Var(&options.ChunkSize, "chunk-size", 500, "Return large lists in chunks rather than all at once. Pass 0 to disable. This flag is beta and may change in the future.")
cmd.Flags().BoolVar(&options.IgnoreNotFound, "ignore-not-found", options.IgnoreNotFound, "If the requested object does not exist the command will return exit code 0.") cmd.Flags().BoolVar(&options.IgnoreNotFound, "ignore-not-found", options.IgnoreNotFound, "If the requested object does not exist the command will return exit code 0.")
cmd.Flags().StringVarP(&options.LabelSelector, "selector", "l", options.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().StringVarP(&options.LabelSelector, "selector", "l", options.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
cmd.Flags().StringVar(&options.FieldSelector, "field-selector", options.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(&options.AllNamespaces, "all-namespaces", options.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") cmd.Flags().BoolVar(&options.AllNamespaces, "all-namespaces", options.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
cmdutil.AddIncludeUninitializedFlag(cmd) cmdutil.AddIncludeUninitializedFlag(cmd)
cmdutil.AddPrinterFlags(cmd) cmdutil.AddPrinterFlags(cmd)
...@@ -233,7 +235,8 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str ...@@ -233,7 +235,8 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
Unstructured(f.UnstructuredClientForMapping, mapper, typer). Unstructured(f.UnstructuredClientForMapping, mapper, typer).
NamespaceParam(options.Namespace).DefaultNamespace().AllNamespaces(options.AllNamespaces). NamespaceParam(options.Namespace).DefaultNamespace().AllNamespaces(options.AllNamespaces).
FilenameParam(options.ExplicitNamespace, &options.FilenameOptions). FilenameParam(options.ExplicitNamespace, &options.FilenameOptions).
SelectorParam(options.LabelSelector). LabelSelectorParam(options.LabelSelector).
FieldSelectorParam(options.FieldSelector).
ExportParam(options.Export). ExportParam(options.Export).
RequestChunksOf(options.ChunkSize). RequestChunksOf(options.ChunkSize).
IncludeUninitialized(cmdutil.ShouldIncludeUninitialized(cmd, false)). // TODO: this needs to be better factored IncludeUninitialized(cmdutil.ShouldIncludeUninitialized(cmd, false)). // TODO: this needs to be better factored
...@@ -450,7 +453,8 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s ...@@ -450,7 +453,8 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s
Unstructured(f.UnstructuredClientForMapping, mapper, typer). Unstructured(f.UnstructuredClientForMapping, mapper, typer).
NamespaceParam(options.Namespace).DefaultNamespace().AllNamespaces(options.AllNamespaces). NamespaceParam(options.Namespace).DefaultNamespace().AllNamespaces(options.AllNamespaces).
FilenameParam(options.ExplicitNamespace, &options.FilenameOptions). FilenameParam(options.ExplicitNamespace, &options.FilenameOptions).
SelectorParam(options.LabelSelector). LabelSelectorParam(options.LabelSelector).
FieldSelectorParam(options.FieldSelector).
ExportParam(options.Export). ExportParam(options.Export).
RequestChunksOf(options.ChunkSize). RequestChunksOf(options.ChunkSize).
IncludeUninitialized(includeUninitialized). IncludeUninitialized(includeUninitialized).
......
...@@ -825,7 +825,7 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) { ...@@ -825,7 +825,7 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) {
} }
} }
func TestGetMultipleTypeObjectsWithSelector(t *testing.T) { func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) {
pods, svc, _ := testData() pods, svc, _ := testData()
f, tf, codec, _ := cmdtesting.NewAPIFactory() f, tf, codec, _ := cmdtesting.NewAPIFactory()
...@@ -868,6 +868,49 @@ func TestGetMultipleTypeObjectsWithSelector(t *testing.T) { ...@@ -868,6 +868,49 @@ func TestGetMultipleTypeObjectsWithSelector(t *testing.T) {
} }
} }
func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) {
pods, svc, _ := testData()
f, tf, codec, _ := cmdtesting.NewAPIFactory()
tf.Printer = &testPrinter{}
tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" {
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
}
switch req.URL.Path {
case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil
case "/namespaces/test/services":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
}
}),
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("field-selector", "a=b")
cmd.Run(cmd, []string{"pods,services"})
expected, err := extractResourceList([]runtime.Object{pods, svc})
if err != nil {
t.Fatal(err)
}
verifyObjects(t, expected, tf.Printer.(*testPrinter).Objects)
if len(buf.String()) == 0 {
t.Errorf("unexpected empty output")
}
}
func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) { func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) {
_, svc, _ := testData() _, svc, _ := testData()
node := &api.Node{ node := &api.Node{
...@@ -1006,7 +1049,7 @@ func watchTestData() ([]api.Pod, []watch.Event) { ...@@ -1006,7 +1049,7 @@ func watchTestData() ([]api.Pod, []watch.Event) {
return pods, events return pods, events
} }
func TestWatchSelector(t *testing.T) { func TestWatchLabelSelector(t *testing.T) {
pods, events := watchTestData() pods, events := watchTestData()
f, tf, codec, _ := cmdtesting.NewAPIFactory() f, tf, codec, _ := cmdtesting.NewAPIFactory()
...@@ -1054,6 +1097,54 @@ func TestWatchSelector(t *testing.T) { ...@@ -1054,6 +1097,54 @@ func TestWatchSelector(t *testing.T) {
} }
} }
func TestWatchFieldSelector(t *testing.T) {
pods, events := watchTestData()
f, tf, codec, _ := cmdtesting.NewAPIFactory()
tf.Printer = &testPrinter{}
podList := &api.PodList{
Items: pods,
ListMeta: metav1.ListMeta{
ResourceVersion: "10",
},
}
tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" {
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
}
switch req.URL.Path {
case "/namespaces/test/pods":
if req.URL.Query().Get("watch") == "true" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil
}
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
}
}),
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("watch", "true")
cmd.Flags().Set("field-selector", "a=b")
cmd.Run(cmd, []string{"pods"})
expected := []runtime.Object{&pods[0], &pods[1], events[2].Object, events[3].Object}
verifyObjects(t, expected, tf.Printer.(*testPrinter).Objects)
if len(buf.String()) == 0 {
t.Errorf("unexpected empty output")
}
}
func TestWatchResource(t *testing.T) { func TestWatchResource(t *testing.T) {
pods, events := watchTestData() pods, events := watchTestData()
......
...@@ -110,7 +110,7 @@ func RunScale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin ...@@ -110,7 +110,7 @@ func RunScale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin
FilenameParam(enforceNamespace, options). FilenameParam(enforceNamespace, options).
ResourceTypeOrNameArgs(all, args...). ResourceTypeOrNameArgs(all, args...).
Flatten(). Flatten().
SelectorParam(selector). LabelSelectorParam(selector).
Do() Do()
err = r.Err() err = r.Err()
if resource.IsUsageError(err) { if resource.IsUsageError(err) {
......
...@@ -240,7 +240,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { ...@@ -240,7 +240,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error {
if !o.Local { if !o.Local {
b = b. b = b.
SelectorParam(o.Selector). LabelSelectorParam(o.Selector).
ResourceTypeOrNameArgs(o.All, o.From). ResourceTypeOrNameArgs(o.All, o.From).
Latest() Latest()
} else { } else {
...@@ -304,7 +304,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { ...@@ -304,7 +304,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error {
if !o.Local { if !o.Local {
b = b. b = b.
SelectorParam(o.Selector). LabelSelectorParam(o.Selector).
ResourceTypeOrNameArgs(o.All, o.Resources...). ResourceTypeOrNameArgs(o.All, o.Resources...).
Latest() Latest()
} else { } else {
......
...@@ -149,7 +149,7 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st ...@@ -149,7 +149,7 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
if !o.Local { if !o.Local {
builder = builder. builder = builder.
SelectorParam(o.Selector). LabelSelectorParam(o.Selector).
ResourceTypeOrNameArgs(o.All, o.Resources...). ResourceTypeOrNameArgs(o.All, o.Resources...).
Latest() Latest()
} else { } else {
......
...@@ -153,7 +153,7 @@ func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args ...@@ -153,7 +153,7 @@ func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
if !o.Local { if !o.Local {
builder = builder. builder = builder.
SelectorParam(o.Selector). LabelSelectorParam(o.Selector).
ResourceTypeOrNameArgs(o.All, args...). ResourceTypeOrNameArgs(o.All, args...).
Latest() Latest()
} else { } else {
......
...@@ -135,7 +135,7 @@ func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [] ...@@ -135,7 +135,7 @@ func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
if !o.Local { if !o.Local {
builder = builder. builder = builder.
SelectorParam(o.Selector). LabelSelectorParam(o.Selector).
ResourceTypeOrNameArgs(o.All, args...). ResourceTypeOrNameArgs(o.All, args...).
Latest() Latest()
} else { } else {
......
...@@ -152,7 +152,7 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Com ...@@ -152,7 +152,7 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Com
ContinueOnError(). ContinueOnError().
NamespaceParam(namespace).DefaultNamespace() NamespaceParam(namespace).DefaultNamespace()
if o.selector != "" { if o.selector != "" {
o.builder = o.builder.SelectorParam(o.selector).ResourceTypes("node") o.builder = o.builder.LabelSelectorParam(o.selector).ResourceTypes("node")
} }
if o.all { if o.all {
o.builder = o.builder.SelectAllParam(o.all).ResourceTypes("node").Flatten().Latest() o.builder = o.builder.SelectAllParam(o.all).ResourceTypes("node").Flatten().Latest()
...@@ -160,7 +160,7 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Com ...@@ -160,7 +160,7 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Com
if !o.all && o.selector == "" && len(o.resources) >= 2 { if !o.all && o.selector == "" && len(o.resources) >= 2 {
o.builder = o.builder.ResourceNames("node", o.resources[1:]...) o.builder = o.builder.ResourceNames("node", o.resources[1:]...)
} }
o.builder = o.builder.SelectorParam(o.selector). o.builder = o.builder.LabelSelectorParam(o.selector).
Flatten(). Flatten().
Latest() Latest()
o.f = f o.f = f
......
...@@ -53,7 +53,8 @@ type Builder struct { ...@@ -53,7 +53,8 @@ type Builder struct {
stream bool stream bool
dir bool dir bool
selector *string labelSelector *string
fieldSelector *string
selectAll bool selectAll bool
includeUninitialized bool includeUninitialized bool
limitChunks int64 limitChunks int64
...@@ -274,24 +275,41 @@ func (b *Builder) ResourceNames(resource string, names ...string) *Builder { ...@@ -274,24 +275,41 @@ func (b *Builder) ResourceNames(resource string, names ...string) *Builder {
return b return b
} }
// SelectorParam defines a selector that should be applied to the object types to load. // LabelSelectorParam defines a selector that should be applied to the object types to load.
// This will not affect files loaded from disk or URL. If the parameter is empty it is // This will not affect files loaded from disk or URL. If the parameter is empty it is
// a no-op - to select all resources invoke `b.Selector(labels.Everything.String)`. // a no-op - to select all resources invoke `b.LabelSelector(labels.Everything.String)`.
func (b *Builder) SelectorParam(s string) *Builder { func (b *Builder) LabelSelectorParam(s string) *Builder {
selector := strings.TrimSpace(s) selector := strings.TrimSpace(s)
if len(selector) == 0 { if len(selector) == 0 {
return b return b
} }
if b.selectAll { if b.selectAll {
b.errs = append(b.errs, fmt.Errorf("found non empty selector %q with previously set 'all' parameter. ", s)) b.errs = append(b.errs, fmt.Errorf("found non-empty label selector %q with previously set 'all' parameter. ", s))
return b return b
} }
return b.Selector(selector) return b.LabelSelector(selector)
} }
// Selector accepts a selector directly, and if non nil will trigger a list action. // LabelSelector accepts a selector directly and will filter the resulting list by that object.
func (b *Builder) Selector(selector string) *Builder { // Use LabelSelectorParam instead for user input.
b.selector = &selector func (b *Builder) LabelSelector(selector string) *Builder {
b.labelSelector = &selector
return b
}
// FieldSelectorParam defines a selector that should be applied to the object types to load.
// This will not affect files loaded from disk or URL. If the parameter is empty it is
// a no-op - to select all resources.
func (b *Builder) FieldSelectorParam(s string) *Builder {
s = strings.TrimSpace(s)
if len(s) == 0 {
return b
}
if b.selectAll {
b.errs = append(b.errs, fmt.Errorf("found non-empty field selector %q with previously set 'all' parameter. ", s))
return b
}
b.fieldSelector = &s
return b return b
} }
...@@ -349,7 +367,7 @@ func (b *Builder) RequestChunksOf(chunkSize int64) *Builder { ...@@ -349,7 +367,7 @@ func (b *Builder) RequestChunksOf(chunkSize int64) *Builder {
// SelectEverythingParam // SelectEverythingParam
func (b *Builder) SelectAllParam(selectAll bool) *Builder { func (b *Builder) SelectAllParam(selectAll bool) *Builder {
if selectAll && b.selector != nil { if selectAll && (b.labelSelector != nil || b.fieldSelector != nil) {
b.errs = append(b.errs, fmt.Errorf("setting 'all' parameter but found a non empty selector. ")) b.errs = append(b.errs, fmt.Errorf("setting 'all' parameter but found a non empty selector. "))
return b return b
} }
...@@ -394,9 +412,9 @@ func (b *Builder) ResourceTypeOrNameArgs(allowEmptySelector bool, args ...string ...@@ -394,9 +412,9 @@ func (b *Builder) ResourceTypeOrNameArgs(allowEmptySelector bool, args ...string
b.ResourceTypes(SplitResourceArgument(args[0])...) b.ResourceTypes(SplitResourceArgument(args[0])...)
case len(args) == 1: case len(args) == 1:
b.ResourceTypes(SplitResourceArgument(args[0])...) b.ResourceTypes(SplitResourceArgument(args[0])...)
if b.selector == nil && allowEmptySelector { if b.labelSelector == nil && allowEmptySelector {
selector := labels.Everything().String() selector := labels.Everything().String()
b.selector = &selector b.labelSelector = &selector
} }
case len(args) == 0: case len(args) == 0:
default: default:
...@@ -585,7 +603,7 @@ func (b *Builder) visitorResult() *Result { ...@@ -585,7 +603,7 @@ func (b *Builder) visitorResult() *Result {
if b.selectAll { if b.selectAll {
selector := labels.Everything().String() selector := labels.Everything().String()
b.selector = &selector b.labelSelector = &selector
} }
// visit items specified by paths // visit items specified by paths
...@@ -594,7 +612,7 @@ func (b *Builder) visitorResult() *Result { ...@@ -594,7 +612,7 @@ func (b *Builder) visitorResult() *Result {
} }
// visit selectors // visit selectors
if b.selector != nil { if b.labelSelector != nil || b.fieldSelector != nil {
return b.visitBySelector() return b.visitBySelector()
} }
...@@ -634,6 +652,14 @@ func (b *Builder) visitBySelector() *Result { ...@@ -634,6 +652,14 @@ func (b *Builder) visitBySelector() *Result {
return result return result
} }
var labelSelector, fieldSelector string
if b.labelSelector != nil {
labelSelector = *b.labelSelector
}
if b.fieldSelector != nil {
fieldSelector = *b.fieldSelector
}
visitors := []Visitor{} visitors := []Visitor{}
for _, mapping := range mappings { for _, mapping := range mappings {
client, err := b.mapper.ClientForMapping(mapping) client, err := b.mapper.ClientForMapping(mapping)
...@@ -645,7 +671,7 @@ func (b *Builder) visitBySelector() *Result { ...@@ -645,7 +671,7 @@ func (b *Builder) visitBySelector() *Result {
if mapping.Scope.Name() != meta.RESTScopeNameNamespace { if mapping.Scope.Name() != meta.RESTScopeNameNamespace {
selectorNamespace = "" selectorNamespace = ""
} }
visitors = append(visitors, NewSelector(client, mapping, selectorNamespace, *b.selector, b.export, b.includeUninitialized, b.limitChunks)) visitors = append(visitors, NewSelector(client, mapping, selectorNamespace, labelSelector, fieldSelector, b.export, b.includeUninitialized, b.limitChunks))
} }
if b.continueOnError { if b.continueOnError {
result.visitor = EagerVisitorList(visitors) result.visitor = EagerVisitorList(visitors)
...@@ -820,12 +846,12 @@ func (b *Builder) visitByPaths() *Result { ...@@ -820,12 +846,12 @@ func (b *Builder) visitByPaths() *Result {
} }
visitors = NewDecoratedVisitor(visitors, RetrieveLatest) visitors = NewDecoratedVisitor(visitors, RetrieveLatest)
} }
if b.selector != nil { if b.labelSelector != nil {
selector, err := labels.Parse(*b.selector) selector, err := labels.Parse(*b.labelSelector)
if err != nil { if err != nil {
return result.withError(fmt.Errorf("the provided selector %q is not valid: %v", b.selector, err)) return result.withError(fmt.Errorf("the provided selector %q is not valid: %v", b.labelSelector, err))
} }
visitors = NewFilteredVisitor(visitors, FilterBySelector(selector)) visitors = NewFilteredVisitor(visitors, FilterByLabelSelector(selector))
} }
result.visitor = visitors result.visitor = visitors
result.sources = b.paths result.sources = b.paths
......
...@@ -697,7 +697,7 @@ func TestResourceByNameAndEmptySelector(t *testing.T) { ...@@ -697,7 +697,7 @@ func TestResourceByNameAndEmptySelector(t *testing.T) {
"/namespaces/test/pods/foo": runtime.EncodeOrDie(corev1Codec, &pods.Items[0]), "/namespaces/test/pods/foo": runtime.EncodeOrDie(corev1Codec, &pods.Items[0]),
}), corev1Codec). }), corev1Codec).
NamespaceParam("test"). NamespaceParam("test").
SelectorParam(""). LabelSelectorParam("").
ResourceTypeOrNameArgs(true, "pods", "foo") ResourceTypeOrNameArgs(true, "pods", "foo")
singleItemImplied := false singleItemImplied := false
...@@ -718,14 +718,14 @@ func TestResourceByNameAndEmptySelector(t *testing.T) { ...@@ -718,14 +718,14 @@ func TestResourceByNameAndEmptySelector(t *testing.T) {
} }
} }
func TestSelector(t *testing.T) { func TestLabelSelector(t *testing.T) {
pods, svc := testData() pods, svc := testData()
labelKey := metav1.LabelSelectorQueryParam(corev1GV.String()) labelKey := metav1.LabelSelectorQueryParam(corev1GV.String())
b := NewBuilder(restmapper, LegacyCategoryExpander, scheme.Scheme, fakeClientWith("", t, map[string]string{ b := NewBuilder(restmapper, LegacyCategoryExpander, scheme.Scheme, fakeClientWith("", t, map[string]string{
"/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, pods), "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, pods),
"/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, svc), "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, svc),
}), corev1Codec). }), corev1Codec).
SelectorParam("a=b"). LabelSelectorParam("a=b").
NamespaceParam("test"). NamespaceParam("test").
Flatten() Flatten()
...@@ -751,9 +751,53 @@ func TestSelector(t *testing.T) { ...@@ -751,9 +751,53 @@ func TestSelector(t *testing.T) {
} }
} }
func TestSelectorRequiresKnownTypes(t *testing.T) { func TestLabelSelectorRequiresKnownTypes(t *testing.T) {
b := NewBuilder(restmapper, LegacyCategoryExpander, scheme.Scheme, fakeClient(), corev1Codec). b := NewBuilder(restmapper, LegacyCategoryExpander, scheme.Scheme, fakeClient(), corev1Codec).
SelectorParam("a=b"). LabelSelectorParam("a=b").
NamespaceParam("test").
ResourceTypes("unknown")
if b.Do().Err() == nil {
t.Errorf("unexpected non-error")
}
}
func TestFieldSelector(t *testing.T) {
pods, svc := testData()
fieldKey := metav1.FieldSelectorQueryParam(corev1GV.String())
b := NewBuilder(restmapper, LegacyCategoryExpander, scheme.Scheme, fakeClientWith("", t, map[string]string{
"/namespaces/test/pods?" + fieldKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, pods),
"/namespaces/test/services?" + fieldKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, svc),
}), corev1Codec).
FieldSelectorParam("a=b").
NamespaceParam("test").
Flatten()
test := &testVisitor{}
singleItemImplied := false
if b.Do().Err() == nil {
t.Errorf("unexpected non-error")
}
b.ResourceTypeOrNameArgs(true, "pods,service")
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err != nil || singleItemImplied || len(test.Infos) != 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
if !apiequality.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &svc.Items[0]}, test.Objects()) {
t.Errorf("unexpected visited objects: %#v", test.Objects())
}
if _, err := b.Do().ResourceMapping(); err == nil {
t.Errorf("unexpected non-error")
}
}
func TestFieldSelectorRequiresKnownTypes(t *testing.T) {
b := NewBuilder(restmapper, LegacyCategoryExpander, scheme.Scheme, fakeClient(), corev1Codec).
FieldSelectorParam("a=b").
NamespaceParam("test"). NamespaceParam("test").
ResourceTypes("unknown") ResourceTypes("unknown")
...@@ -764,7 +808,7 @@ func TestSelectorRequiresKnownTypes(t *testing.T) { ...@@ -764,7 +808,7 @@ func TestSelectorRequiresKnownTypes(t *testing.T) {
func TestSingleResourceType(t *testing.T) { func TestSingleResourceType(t *testing.T) {
b := NewBuilder(restmapper, LegacyCategoryExpander, scheme.Scheme, fakeClient(), corev1Codec). b := NewBuilder(restmapper, LegacyCategoryExpander, scheme.Scheme, fakeClient(), corev1Codec).
SelectorParam("a=b"). LabelSelectorParam("a=b").
SingleResourceType(). SingleResourceType().
ResourceTypeOrNameArgs(true, "pods,services") ResourceTypeOrNameArgs(true, "pods,services")
...@@ -1019,7 +1063,7 @@ func TestListObject(t *testing.T) { ...@@ -1019,7 +1063,7 @@ func TestListObject(t *testing.T) {
b := NewBuilder(restmapper, LegacyCategoryExpander, scheme.Scheme, fakeClientWith("", t, map[string]string{ b := NewBuilder(restmapper, LegacyCategoryExpander, scheme.Scheme, fakeClientWith("", t, map[string]string{
"/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, pods), "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, pods),
}), corev1Codec). }), corev1Codec).
SelectorParam("a=b"). LabelSelectorParam("a=b").
NamespaceParam("test"). NamespaceParam("test").
ResourceTypeOrNameArgs(true, "pods"). ResourceTypeOrNameArgs(true, "pods").
Flatten() Flatten()
...@@ -1053,7 +1097,7 @@ func TestListObjectWithDifferentVersions(t *testing.T) { ...@@ -1053,7 +1097,7 @@ func TestListObjectWithDifferentVersions(t *testing.T) {
"/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, pods), "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, pods),
"/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, svc), "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(corev1Codec, svc),
}), corev1Codec). }), corev1Codec).
SelectorParam("a=b"). LabelSelectorParam("a=b").
NamespaceParam("test"). NamespaceParam("test").
ResourceTypeOrNameArgs(true, "pods,services"). ResourceTypeOrNameArgs(true, "pods,services").
Flatten(). Flatten().
......
...@@ -75,15 +75,12 @@ func (m *Helper) List(namespace, apiVersion string, export bool, options *metav1 ...@@ -75,15 +75,12 @@ func (m *Helper) List(namespace, apiVersion string, export bool, options *metav1
return req.Do().Get() return req.Do().Get()
} }
func (m *Helper) Watch(namespace, resourceVersion, apiVersion string, labelSelector string) (watch.Interface, error) { func (m *Helper) Watch(namespace, apiVersion string, options *metav1.ListOptions) (watch.Interface, error) {
options.Watch = true
return m.RESTClient.Get(). return m.RESTClient.Get().
NamespaceIfScoped(namespace, m.NamespaceScoped). NamespaceIfScoped(namespace, m.NamespaceScoped).
Resource(m.Resource). Resource(m.Resource).
VersionedParams(&metav1.ListOptions{ VersionedParams(options, metav1.ParameterCodec).
ResourceVersion: resourceVersion,
Watch: true,
LabelSelector: labelSelector,
}, metav1.ParameterCodec).
Watch() Watch()
} }
......
...@@ -385,6 +385,72 @@ func TestHelperList(t *testing.T) { ...@@ -385,6 +385,72 @@ func TestHelperList(t *testing.T) {
} }
} }
func TestHelperListSelectorCombination(t *testing.T) {
tests := []struct {
Name string
Err bool
ErrMsg string
FieldSelector string
LabelSelector string
}{
{
Name: "No selector",
Err: false,
},
{
Name: "Only Label Selector",
Err: false,
LabelSelector: "foo=baz",
},
{
Name: "Only Field Selector",
Err: false,
FieldSelector: "xyz=zyx",
},
{
Name: "Both Label and Field Selector",
Err: false,
LabelSelector: "foo=baz",
FieldSelector: "xyz=zyx",
},
}
resp := &http.Response{
StatusCode: http.StatusOK,
Header: header(),
Body: objBody(&corev1.PodList{
Items: []corev1.Pod{{
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
},
},
}),
}
client := &fake.RESTClient{
NegotiatedSerializer: scheme.Codecs,
Resp: resp,
Err: nil,
}
modifier := &Helper{
RESTClient: client,
NamespaceScoped: true,
}
for _, test := range tests {
_, err := modifier.List("bar",
corev1GV.String(),
false,
&metav1.ListOptions{LabelSelector: test.LabelSelector, FieldSelector: test.FieldSelector})
if test.Err {
if err == nil {
t.Errorf("%q expected error: %q", test.Name, test.ErrMsg)
}
if err != nil && err.Error() != test.ErrMsg {
t.Errorf("%q expected error: %q", test.Name, test.ErrMsg)
}
}
}
}
func TestHelperReplace(t *testing.T) { func TestHelperReplace(t *testing.T) {
expectPut := func(path string, req *http.Request) bool { expectPut := func(path string, req *http.Request) bool {
if req.Method != "PUT" { if req.Method != "PUT" {
......
...@@ -30,19 +30,21 @@ type Selector struct { ...@@ -30,19 +30,21 @@ type Selector struct {
Client RESTClient Client RESTClient
Mapping *meta.RESTMapping Mapping *meta.RESTMapping
Namespace string Namespace string
Selector string LabelSelector string
FieldSelector string
Export bool Export bool
IncludeUninitialized bool IncludeUninitialized bool
LimitChunks int64 LimitChunks int64
} }
// NewSelector creates a resource selector which hides details of getting items by their label selector. // NewSelector creates a resource selector which hides details of getting items by their label selector.
func NewSelector(client RESTClient, mapping *meta.RESTMapping, namespace string, selector string, export, includeUninitialized bool, limitChunks int64) *Selector { func NewSelector(client RESTClient, mapping *meta.RESTMapping, namespace, labelSelector, fieldSelector string, export, includeUninitialized bool, limitChunks int64) *Selector {
return &Selector{ return &Selector{
Client: client, Client: client,
Mapping: mapping, Mapping: mapping,
Namespace: namespace, Namespace: namespace,
Selector: selector, LabelSelector: labelSelector,
FieldSelector: fieldSelector,
Export: export, Export: export,
IncludeUninitialized: includeUninitialized, IncludeUninitialized: includeUninitialized,
LimitChunks: limitChunks, LimitChunks: limitChunks,
...@@ -58,7 +60,8 @@ func (r *Selector) Visit(fn VisitorFunc) error { ...@@ -58,7 +60,8 @@ func (r *Selector) Visit(fn VisitorFunc) error {
r.ResourceMapping().GroupVersionKind.GroupVersion().String(), r.ResourceMapping().GroupVersionKind.GroupVersion().String(),
r.Export, r.Export,
&metav1.ListOptions{ &metav1.ListOptions{
LabelSelector: r.Selector, LabelSelector: r.LabelSelector,
FieldSelector: r.FieldSelector,
IncludeUninitialized: r.IncludeUninitialized, IncludeUninitialized: r.IncludeUninitialized,
Limit: r.LimitChunks, Limit: r.LimitChunks,
Continue: continueToken, Continue: continueToken,
...@@ -71,17 +74,17 @@ func (r *Selector) Visit(fn VisitorFunc) error { ...@@ -71,17 +74,17 @@ func (r *Selector) Visit(fn VisitorFunc) error {
if errors.IsBadRequest(err) || errors.IsNotFound(err) { if errors.IsBadRequest(err) || errors.IsNotFound(err) {
if se, ok := err.(*errors.StatusError); ok { if se, ok := err.(*errors.StatusError); ok {
// modify the message without hiding this is an API error // modify the message without hiding this is an API error
if len(r.Selector) == 0 { if len(r.LabelSelector) == 0 && len(r.FieldSelector) == 0 {
se.ErrStatus.Message = fmt.Sprintf("Unable to list %q: %v", r.Mapping.Resource, se.ErrStatus.Message) se.ErrStatus.Message = fmt.Sprintf("Unable to list %q: %v", r.Mapping.Resource, se.ErrStatus.Message)
} else { } else {
se.ErrStatus.Message = fmt.Sprintf("Unable to find %q that match the selector %q: %v", r.Mapping.Resource, r.Selector, se.ErrStatus.Message) se.ErrStatus.Message = fmt.Sprintf("Unable to find %q that match label selector %q, field selector %q: %v", r.Mapping.Resource, r.LabelSelector, r.FieldSelector, se.ErrStatus.Message)
} }
return se return se
} }
if len(r.Selector) == 0 { if len(r.LabelSelector) == 0 && len(r.FieldSelector) == 0 {
return fmt.Errorf("Unable to list %q: %v", r.Mapping.Resource, err) return fmt.Errorf("Unable to list %q: %v", r.Mapping.Resource, err)
} }
return fmt.Errorf("Unable to find %q that match the selector %q: %v", r.Mapping.Resource, r.Selector, err) return fmt.Errorf("Unable to find %q that match label selector %q, field selector %q: %v", r.Mapping.Resource, r.LabelSelector, r.FieldSelector, err)
} }
return err return err
} }
...@@ -107,7 +110,8 @@ func (r *Selector) Visit(fn VisitorFunc) error { ...@@ -107,7 +110,8 @@ func (r *Selector) Visit(fn VisitorFunc) error {
} }
func (r *Selector) Watch(resourceVersion string) (watch.Interface, error) { func (r *Selector) Watch(resourceVersion string) (watch.Interface, error) {
return NewHelper(r.Client, r.Mapping).Watch(r.Namespace, resourceVersion, r.ResourceMapping().GroupVersionKind.GroupVersion().String(), r.Selector) return NewHelper(r.Client, r.Mapping).Watch(r.Namespace, r.ResourceMapping().GroupVersionKind.GroupVersion().String(),
&metav1.ListOptions{ResourceVersion: resourceVersion, LabelSelector: r.LabelSelector, FieldSelector: r.FieldSelector})
} }
// ResourceMapping returns the mapping for this resource and implements ResourceMapping // ResourceMapping returns the mapping for this resource and implements ResourceMapping
......
...@@ -691,7 +691,7 @@ func (v FilteredVisitor) Visit(fn VisitorFunc) error { ...@@ -691,7 +691,7 @@ func (v FilteredVisitor) Visit(fn VisitorFunc) error {
}) })
} }
func FilterBySelector(s labels.Selector) FilterFunc { func FilterByLabelSelector(s labels.Selector) FilterFunc {
return func(info *Info, err error) (bool, error) { return func(info *Info, err error) (bool, error) {
if err != nil { if err != nil {
return false, err return false, err
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment