blob: a9e204976af79e668557cb6e50ded1564bb9474f [file] [log] [blame]
Matteo Scandoloa4285862020-12-01 18:10:10 -08001/*
2Copyright 2015 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package fields
18
19import (
20 "bytes"
21 "fmt"
22 "sort"
23 "strings"
24
25 "k8s.io/apimachinery/pkg/selection"
26)
27
28// Selector represents a field selector.
29type Selector interface {
30 // Matches returns true if this selector matches the given set of fields.
31 Matches(Fields) bool
32
33 // Empty returns true if this selector does not restrict the selection space.
34 Empty() bool
35
36 // RequiresExactMatch allows a caller to introspect whether a given selector
37 // requires a single specific field to be set, and if so returns the value it
38 // requires.
39 RequiresExactMatch(field string) (value string, found bool)
40
41 // Transform returns a new copy of the selector after TransformFunc has been
42 // applied to the entire selector, or an error if fn returns an error.
43 // If for a given requirement both field and value are transformed to empty
44 // string, the requirement is skipped.
45 Transform(fn TransformFunc) (Selector, error)
46
47 // Requirements converts this interface to Requirements to expose
48 // more detailed selection information.
49 Requirements() Requirements
50
51 // String returns a human readable string that represents this selector.
52 String() string
53
54 // Make a deep copy of the selector.
55 DeepCopySelector() Selector
56}
57
58type nothingSelector struct{}
59
60func (n nothingSelector) Matches(_ Fields) bool { return false }
61func (n nothingSelector) Empty() bool { return false }
62func (n nothingSelector) String() string { return "" }
63func (n nothingSelector) Requirements() Requirements { return nil }
64func (n nothingSelector) DeepCopySelector() Selector { return n }
65func (n nothingSelector) RequiresExactMatch(field string) (value string, found bool) {
66 return "", false
67}
68func (n nothingSelector) Transform(fn TransformFunc) (Selector, error) { return n, nil }
69
70// Nothing returns a selector that matches no fields
71func Nothing() Selector {
72 return nothingSelector{}
73}
74
75// Everything returns a selector that matches all fields.
76func Everything() Selector {
77 return andTerm{}
78}
79
80type hasTerm struct {
81 field, value string
82}
83
84func (t *hasTerm) Matches(ls Fields) bool {
85 return ls.Get(t.field) == t.value
86}
87
88func (t *hasTerm) Empty() bool {
89 return false
90}
91
92func (t *hasTerm) RequiresExactMatch(field string) (value string, found bool) {
93 if t.field == field {
94 return t.value, true
95 }
96 return "", false
97}
98
99func (t *hasTerm) Transform(fn TransformFunc) (Selector, error) {
100 field, value, err := fn(t.field, t.value)
101 if err != nil {
102 return nil, err
103 }
104 if len(field) == 0 && len(value) == 0 {
105 return Everything(), nil
106 }
107 return &hasTerm{field, value}, nil
108}
109
110func (t *hasTerm) Requirements() Requirements {
111 return []Requirement{{
112 Field: t.field,
113 Operator: selection.Equals,
114 Value: t.value,
115 }}
116}
117
118func (t *hasTerm) String() string {
119 return fmt.Sprintf("%v=%v", t.field, EscapeValue(t.value))
120}
121
122func (t *hasTerm) DeepCopySelector() Selector {
123 if t == nil {
124 return nil
125 }
126 out := new(hasTerm)
127 *out = *t
128 return out
129}
130
131type notHasTerm struct {
132 field, value string
133}
134
135func (t *notHasTerm) Matches(ls Fields) bool {
136 return ls.Get(t.field) != t.value
137}
138
139func (t *notHasTerm) Empty() bool {
140 return false
141}
142
143func (t *notHasTerm) RequiresExactMatch(field string) (value string, found bool) {
144 return "", false
145}
146
147func (t *notHasTerm) Transform(fn TransformFunc) (Selector, error) {
148 field, value, err := fn(t.field, t.value)
149 if err != nil {
150 return nil, err
151 }
152 if len(field) == 0 && len(value) == 0 {
153 return Everything(), nil
154 }
155 return &notHasTerm{field, value}, nil
156}
157
158func (t *notHasTerm) Requirements() Requirements {
159 return []Requirement{{
160 Field: t.field,
161 Operator: selection.NotEquals,
162 Value: t.value,
163 }}
164}
165
166func (t *notHasTerm) String() string {
167 return fmt.Sprintf("%v!=%v", t.field, EscapeValue(t.value))
168}
169
170func (t *notHasTerm) DeepCopySelector() Selector {
171 if t == nil {
172 return nil
173 }
174 out := new(notHasTerm)
175 *out = *t
176 return out
177}
178
179type andTerm []Selector
180
181func (t andTerm) Matches(ls Fields) bool {
182 for _, q := range t {
183 if !q.Matches(ls) {
184 return false
185 }
186 }
187 return true
188}
189
190func (t andTerm) Empty() bool {
191 if t == nil {
192 return true
193 }
194 if len([]Selector(t)) == 0 {
195 return true
196 }
197 for i := range t {
198 if !t[i].Empty() {
199 return false
200 }
201 }
202 return true
203}
204
205func (t andTerm) RequiresExactMatch(field string) (string, bool) {
206 if t == nil || len([]Selector(t)) == 0 {
207 return "", false
208 }
209 for i := range t {
210 if value, found := t[i].RequiresExactMatch(field); found {
211 return value, found
212 }
213 }
214 return "", false
215}
216
217func (t andTerm) Transform(fn TransformFunc) (Selector, error) {
218 next := make([]Selector, 0, len([]Selector(t)))
219 for _, s := range []Selector(t) {
220 n, err := s.Transform(fn)
221 if err != nil {
222 return nil, err
223 }
224 if !n.Empty() {
225 next = append(next, n)
226 }
227 }
228 return andTerm(next), nil
229}
230
231func (t andTerm) Requirements() Requirements {
232 reqs := make([]Requirement, 0, len(t))
233 for _, s := range []Selector(t) {
234 rs := s.Requirements()
235 reqs = append(reqs, rs...)
236 }
237 return reqs
238}
239
240func (t andTerm) String() string {
241 var terms []string
242 for _, q := range t {
243 terms = append(terms, q.String())
244 }
245 return strings.Join(terms, ",")
246}
247
248func (t andTerm) DeepCopySelector() Selector {
249 if t == nil {
250 return nil
251 }
252 out := make([]Selector, len(t))
253 for i := range t {
254 out[i] = t[i].DeepCopySelector()
255 }
256 return andTerm(out)
257}
258
259// SelectorFromSet returns a Selector which will match exactly the given Set. A
260// nil Set is considered equivalent to Everything().
261func SelectorFromSet(ls Set) Selector {
262 if ls == nil {
263 return Everything()
264 }
265 items := make([]Selector, 0, len(ls))
266 for field, value := range ls {
267 items = append(items, &hasTerm{field: field, value: value})
268 }
269 if len(items) == 1 {
270 return items[0]
271 }
272 return andTerm(items)
273}
274
275// valueEscaper prefixes \,= characters with a backslash
276var valueEscaper = strings.NewReplacer(
277 // escape \ characters
278 `\`, `\\`,
279 // then escape , and = characters to allow unambiguous parsing of the value in a fieldSelector
280 `,`, `\,`,
281 `=`, `\=`,
282)
283
284// EscapeValue escapes an arbitrary literal string for use as a fieldSelector value
285func EscapeValue(s string) string {
286 return valueEscaper.Replace(s)
287}
288
289// InvalidEscapeSequence indicates an error occurred unescaping a field selector
290type InvalidEscapeSequence struct {
291 sequence string
292}
293
294func (i InvalidEscapeSequence) Error() string {
295 return fmt.Sprintf("invalid field selector: invalid escape sequence: %s", i.sequence)
296}
297
298// UnescapedRune indicates an error occurred unescaping a field selector
299type UnescapedRune struct {
300 r rune
301}
302
303func (i UnescapedRune) Error() string {
304 return fmt.Sprintf("invalid field selector: unescaped character in value: %v", i.r)
305}
306
307// UnescapeValue unescapes a fieldSelector value and returns the original literal value.
308// May return the original string if it contains no escaped or special characters.
309func UnescapeValue(s string) (string, error) {
310 // if there's no escaping or special characters, just return to avoid allocation
311 if !strings.ContainsAny(s, `\,=`) {
312 return s, nil
313 }
314
315 v := bytes.NewBuffer(make([]byte, 0, len(s)))
316 inSlash := false
317 for _, c := range s {
318 if inSlash {
319 switch c {
320 case '\\', ',', '=':
321 // omit the \ for recognized escape sequences
322 v.WriteRune(c)
323 default:
324 // error on unrecognized escape sequences
325 return "", InvalidEscapeSequence{sequence: string([]rune{'\\', c})}
326 }
327 inSlash = false
328 continue
329 }
330
331 switch c {
332 case '\\':
333 inSlash = true
334 case ',', '=':
335 // unescaped , and = characters are not allowed in field selector values
336 return "", UnescapedRune{r: c}
337 default:
338 v.WriteRune(c)
339 }
340 }
341
342 // Ending with a single backslash is an invalid sequence
343 if inSlash {
344 return "", InvalidEscapeSequence{sequence: "\\"}
345 }
346
347 return v.String(), nil
348}
349
350// ParseSelectorOrDie takes a string representing a selector and returns an
351// object suitable for matching, or panic when an error occur.
352func ParseSelectorOrDie(s string) Selector {
353 selector, err := ParseSelector(s)
354 if err != nil {
355 panic(err)
356 }
357 return selector
358}
359
360// ParseSelector takes a string representing a selector and returns an
361// object suitable for matching, or an error.
362func ParseSelector(selector string) (Selector, error) {
363 return parseSelector(selector,
364 func(lhs, rhs string) (newLhs, newRhs string, err error) {
365 return lhs, rhs, nil
366 })
367}
368
369// ParseAndTransformSelector parses the selector and runs them through the given TransformFunc.
370func ParseAndTransformSelector(selector string, fn TransformFunc) (Selector, error) {
371 return parseSelector(selector, fn)
372}
373
374// TransformFunc transforms selectors.
375type TransformFunc func(field, value string) (newField, newValue string, err error)
376
377// splitTerms returns the comma-separated terms contained in the given fieldSelector.
378// Backslash-escaped commas are treated as data instead of delimiters, and are included in the returned terms, with the leading backslash preserved.
379func splitTerms(fieldSelector string) []string {
380 if len(fieldSelector) == 0 {
381 return nil
382 }
383
384 terms := make([]string, 0, 1)
385 startIndex := 0
386 inSlash := false
387 for i, c := range fieldSelector {
388 switch {
389 case inSlash:
390 inSlash = false
391 case c == '\\':
392 inSlash = true
393 case c == ',':
394 terms = append(terms, fieldSelector[startIndex:i])
395 startIndex = i + 1
396 }
397 }
398
399 terms = append(terms, fieldSelector[startIndex:])
400
401 return terms
402}
403
404const (
405 notEqualOperator = "!="
406 doubleEqualOperator = "=="
407 equalOperator = "="
408)
409
410// termOperators holds the recognized operators supported in fieldSelectors.
411// doubleEqualOperator and equal are equivalent, but doubleEqualOperator is checked first
412// to avoid leaving a leading = character on the rhs value.
413var termOperators = []string{notEqualOperator, doubleEqualOperator, equalOperator}
414
415// splitTerm returns the lhs, operator, and rhs parsed from the given term, along with an indicator of whether the parse was successful.
416// no escaping of special characters is supported in the lhs value, so the first occurrence of a recognized operator is used as the split point.
417// the literal rhs is returned, and the caller is responsible for applying any desired unescaping.
418func splitTerm(term string) (lhs, op, rhs string, ok bool) {
419 for i := range term {
420 remaining := term[i:]
421 for _, op := range termOperators {
422 if strings.HasPrefix(remaining, op) {
423 return term[0:i], op, term[i+len(op):], true
424 }
425 }
426 }
427 return "", "", "", false
428}
429
430func parseSelector(selector string, fn TransformFunc) (Selector, error) {
431 parts := splitTerms(selector)
432 sort.StringSlice(parts).Sort()
433 var items []Selector
434 for _, part := range parts {
435 if part == "" {
436 continue
437 }
438 lhs, op, rhs, ok := splitTerm(part)
439 if !ok {
440 return nil, fmt.Errorf("invalid selector: '%s'; can't understand '%s'", selector, part)
441 }
442 unescapedRHS, err := UnescapeValue(rhs)
443 if err != nil {
444 return nil, err
445 }
446 switch op {
447 case notEqualOperator:
448 items = append(items, &notHasTerm{field: lhs, value: unescapedRHS})
449 case doubleEqualOperator:
450 items = append(items, &hasTerm{field: lhs, value: unescapedRHS})
451 case equalOperator:
452 items = append(items, &hasTerm{field: lhs, value: unescapedRHS})
453 default:
454 return nil, fmt.Errorf("invalid selector: '%s'; can't understand '%s'", selector, part)
455 }
456 }
457 if len(items) == 1 {
458 return items[0].Transform(fn)
459 }
460 return andTerm(items).Transform(fn)
461}
462
463// OneTermEqualSelector returns an object that matches objects where one field/field equals one value.
464// Cannot return an error.
465func OneTermEqualSelector(k, v string) Selector {
466 return &hasTerm{field: k, value: v}
467}
468
469// OneTermNotEqualSelector returns an object that matches objects where one field/field does not equal one value.
470// Cannot return an error.
471func OneTermNotEqualSelector(k, v string) Selector {
472 return &notHasTerm{field: k, value: v}
473}
474
475// AndSelectors creates a selector that is the logical AND of all the given selectors
476func AndSelectors(selectors ...Selector) Selector {
477 return andTerm(selectors)
478}