Skip to content

Commit a74b910

Browse files
committed
Support multiple field selectors
Signed-off-by: Tamal Saha <[email protected]>
1 parent 9ee63fc commit a74b910

File tree

2 files changed

+51
-15
lines changed

2 files changed

+51
-15
lines changed

pkg/cache/internal/cache_reader.go

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -113,17 +113,55 @@ func (c *CacheReader) List(_ context.Context, out client.ObjectList, opts ...cli
113113
listOpts.ApplyOptions(opts)
114114

115115
switch {
116-
case listOpts.FieldSelector != nil:
116+
case listOpts.FieldSelector != nil && !listOpts.FieldSelector.Empty():
117117
// TODO(directxman12): support more complicated field selectors by
118118
// combining multiple indices, GetIndexers, etc
119-
field, val, requiresExact := requiresExactMatch(listOpts.FieldSelector)
119+
requiresExact := requiresExactMatch(listOpts.FieldSelector)
120120
if !requiresExact {
121121
return fmt.Errorf("non-exact field matches are not supported by the cache")
122122
}
123-
// list all objects by the field selector. If this is namespaced and we have one, ask for the
124-
// namespaced index key. Otherwise, ask for the non-namespaced variant by using the fake "all namespaces"
125-
// namespace.
126-
objs, err = c.indexer.ByIndex(FieldIndexName(field), KeyToNamespacedKey(listOpts.Namespace, val))
123+
124+
reqs := listOpts.FieldSelector.Requirements()
125+
// len(reqs) == 0 means, select nothing
126+
if len(reqs) > 0 {
127+
req := reqs[0]
128+
// list all objects by the field selector. If this is namespaced and we have one, ask for the
129+
// namespaced index key. Otherwise, ask for the non-namespaced variant by using the fake "all namespaces"
130+
// namespace.
131+
list, err := c.indexer.ByIndex(FieldIndexName(req.Field), KeyToNamespacedKey(listOpts.Namespace, req.Value))
132+
if err != nil {
133+
return err
134+
}
135+
if len(reqs) > 1 {
136+
objmap := make(map[client.ObjectKey]interface{}, len(list))
137+
for i := range list {
138+
obj := list[i].(client.Object)
139+
objmap[client.ObjectKey{Namespace: obj.GetNamespace(), Name: obj.GetName()}] = obj
140+
}
141+
for _, req := range reqs[1:] {
142+
list, err := c.indexer.ByIndex(FieldIndexName(req.Field), KeyToNamespacedKey(listOpts.Namespace, req.Value))
143+
if err != nil {
144+
return err
145+
}
146+
147+
numap := make(map[client.ObjectKey]interface{}, len(list))
148+
for i := range list {
149+
obj := list[i].(client.Object)
150+
key := client.ObjectKey{Namespace: obj.GetNamespace(), Name: obj.GetName()}
151+
if _, exists := objmap[key]; exists {
152+
numap[key] = obj
153+
}
154+
}
155+
objmap = numap
156+
}
157+
objs = make([]interface{}, 0, len(objmap))
158+
for _, obj := range objmap {
159+
objs = append(objs, obj)
160+
}
161+
} else {
162+
objs = list
163+
}
164+
}
127165
case listOpts.Namespace != "":
128166
objs, err = c.indexer.ByIndex(cache.NamespaceIndex, listOpts.Namespace)
129167
default:
@@ -187,16 +225,14 @@ func objectKeyToStoreKey(k client.ObjectKey) string {
187225
}
188226

189227
// requiresExactMatch checks if the given field selector is of the form `k=v` or `k==v`.
190-
func requiresExactMatch(sel fields.Selector) (field, val string, required bool) {
228+
func requiresExactMatch(sel fields.Selector) (required bool) {
191229
reqs := sel.Requirements()
192-
if len(reqs) != 1 {
193-
return "", "", false
194-
}
195-
req := reqs[0]
196-
if req.Operator != selection.Equals && req.Operator != selection.DoubleEquals {
197-
return "", "", false
230+
for _, req := range reqs {
231+
if req.Operator != selection.Equals && req.Operator != selection.DoubleEquals {
232+
return false
233+
}
198234
}
199-
return req.Field, req.Value, true
235+
return true
200236
}
201237

202238
// FieldIndexName constructs the name of the index over the given field,

pkg/client/options.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ type ListOptions struct {
323323
LabelSelector labels.Selector
324324
// FieldSelector filters results by a particular field. In order
325325
// to use this with cache-based implementations, restrict usage to
326-
// a single field-value pair that's been added to the indexers.
326+
// field-value pair exact matches that's been added to the indexers.
327327
FieldSelector fields.Selector
328328

329329
// Namespace represents the namespace to list for, or empty for

0 commit comments

Comments
 (0)