2 Copyright 2015 The Kubernetes Authors.
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
25 "k8s.io/apimachinery/pkg/selection"
28 // Selector represents a field selector.
29 type Selector interface {
30 // Matches returns true if this selector matches the given set of fields.
33 // Empty returns true if this selector does not restrict the selection space.
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
39 RequiresExactMatch(field string) (value string, found bool)
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)
47 // Requirements converts this interface to Requirements to expose
48 // more detailed selection information.
49 Requirements() Requirements
51 // String returns a human readable string that represents this selector.
54 // Make a deep copy of the selector.
55 DeepCopySelector() Selector
58 type nothingSelector struct{}
60 func (n nothingSelector) Matches(_ Fields) bool { return false }
61 func (n nothingSelector) Empty() bool { return false }
62 func (n nothingSelector) String() string { return "" }
63 func (n nothingSelector) Requirements() Requirements { return nil }
64 func (n nothingSelector) DeepCopySelector() Selector { return n }
65 func (n nothingSelector) RequiresExactMatch(field string) (value string, found bool) { return "", false }
66 func (n nothingSelector) Transform(fn TransformFunc) (Selector, error) { return n, nil }
68 // Nothing returns a selector that matches no fields
69 func Nothing() Selector {
70 return nothingSelector{}
73 // Everything returns a selector that matches all fields.
74 func Everything() Selector {
82 func (t *hasTerm) Matches(ls Fields) bool {
83 return ls.Get(t.field) == t.value
86 func (t *hasTerm) Empty() bool {
90 func (t *hasTerm) RequiresExactMatch(field string) (value string, found bool) {
97 func (t *hasTerm) Transform(fn TransformFunc) (Selector, error) {
98 field, value, err := fn(t.field, t.value)
102 if len(field) == 0 && len(value) == 0 {
103 return Everything(), nil
105 return &hasTerm{field, value}, nil
108 func (t *hasTerm) Requirements() Requirements {
109 return []Requirement{{
111 Operator: selection.Equals,
116 func (t *hasTerm) String() string {
117 return fmt.Sprintf("%v=%v", t.field, EscapeValue(t.value))
120 func (t *hasTerm) DeepCopySelector() Selector {
129 type notHasTerm struct {
133 func (t *notHasTerm) Matches(ls Fields) bool {
134 return ls.Get(t.field) != t.value
137 func (t *notHasTerm) Empty() bool {
141 func (t *notHasTerm) RequiresExactMatch(field string) (value string, found bool) {
145 func (t *notHasTerm) Transform(fn TransformFunc) (Selector, error) {
146 field, value, err := fn(t.field, t.value)
150 if len(field) == 0 && len(value) == 0 {
151 return Everything(), nil
153 return ¬HasTerm{field, value}, nil
156 func (t *notHasTerm) Requirements() Requirements {
157 return []Requirement{{
159 Operator: selection.NotEquals,
164 func (t *notHasTerm) String() string {
165 return fmt.Sprintf("%v!=%v", t.field, EscapeValue(t.value))
168 func (t *notHasTerm) DeepCopySelector() Selector {
172 out := new(notHasTerm)
177 type andTerm []Selector
179 func (t andTerm) Matches(ls Fields) bool {
180 for _, q := range t {
188 func (t andTerm) Empty() bool {
192 if len([]Selector(t)) == 0 {
203 func (t andTerm) RequiresExactMatch(field string) (string, bool) {
204 if t == nil || len([]Selector(t)) == 0 {
208 if value, found := t[i].RequiresExactMatch(field); found {
215 func (t andTerm) Transform(fn TransformFunc) (Selector, error) {
216 next := make([]Selector, 0, len([]Selector(t)))
217 for _, s := range []Selector(t) {
218 n, err := s.Transform(fn)
223 next = append(next, n)
226 return andTerm(next), nil
229 func (t andTerm) Requirements() Requirements {
230 reqs := make([]Requirement, 0, len(t))
231 for _, s := range []Selector(t) {
232 rs := s.Requirements()
233 reqs = append(reqs, rs...)
238 func (t andTerm) String() string {
240 for _, q := range t {
241 terms = append(terms, q.String())
243 return strings.Join(terms, ",")
246 func (t andTerm) DeepCopySelector() Selector {
250 out := make([]Selector, len(t))
252 out[i] = t[i].DeepCopySelector()
257 // SelectorFromSet returns a Selector which will match exactly the given Set. A
258 // nil Set is considered equivalent to Everything().
259 func SelectorFromSet(ls Set) Selector {
263 items := make([]Selector, 0, len(ls))
264 for field, value := range ls {
265 items = append(items, &hasTerm{field: field, value: value})
270 return andTerm(items)
273 // valueEscaper prefixes \,= characters with a backslash
274 var valueEscaper = strings.NewReplacer(
275 // escape \ characters
277 // then escape , and = characters to allow unambiguous parsing of the value in a fieldSelector
282 // EscapeValue escapes an arbitrary literal string for use as a fieldSelector value
283 func EscapeValue(s string) string {
284 return valueEscaper.Replace(s)
287 // InvalidEscapeSequence indicates an error occurred unescaping a field selector
288 type InvalidEscapeSequence struct {
292 func (i InvalidEscapeSequence) Error() string {
293 return fmt.Sprintf("invalid field selector: invalid escape sequence: %s", i.sequence)
296 // UnescapedRune indicates an error occurred unescaping a field selector
297 type UnescapedRune struct {
301 func (i UnescapedRune) Error() string {
302 return fmt.Sprintf("invalid field selector: unescaped character in value: %v", i.r)
305 // UnescapeValue unescapes a fieldSelector value and returns the original literal value.
306 // May return the original string if it contains no escaped or special characters.
307 func UnescapeValue(s string) (string, error) {
308 // if there's no escaping or special characters, just return to avoid allocation
309 if !strings.ContainsAny(s, `\,=`) {
313 v := bytes.NewBuffer(make([]byte, 0, len(s)))
315 for _, c := range s {
319 // omit the \ for recognized escape sequences
322 // error on unrecognized escape sequences
323 return "", InvalidEscapeSequence{sequence: string([]rune{'\\', c})}
333 // unescaped , and = characters are not allowed in field selector values
334 return "", UnescapedRune{r: c}
340 // Ending with a single backslash is an invalid sequence
342 return "", InvalidEscapeSequence{sequence: "\\"}
345 return v.String(), nil
348 // ParseSelectorOrDie takes a string representing a selector and returns an
349 // object suitable for matching, or panic when an error occur.
350 func ParseSelectorOrDie(s string) Selector {
351 selector, err := ParseSelector(s)
358 // ParseSelector takes a string representing a selector and returns an
359 // object suitable for matching, or an error.
360 func ParseSelector(selector string) (Selector, error) {
361 return parseSelector(selector,
362 func(lhs, rhs string) (newLhs, newRhs string, err error) {
367 // ParseAndTransformSelector parses the selector and runs them through the given TransformFunc.
368 func ParseAndTransformSelector(selector string, fn TransformFunc) (Selector, error) {
369 return parseSelector(selector, fn)
372 // TransformFunc transforms selectors.
373 type TransformFunc func(field, value string) (newField, newValue string, err error)
375 // splitTerms returns the comma-separated terms contained in the given fieldSelector.
376 // Backslash-escaped commas are treated as data instead of delimiters, and are included in the returned terms, with the leading backslash preserved.
377 func splitTerms(fieldSelector string) []string {
378 if len(fieldSelector) == 0 {
382 terms := make([]string, 0, 1)
385 for i, c := range fieldSelector {
392 terms = append(terms, fieldSelector[startIndex:i])
397 terms = append(terms, fieldSelector[startIndex:])
403 notEqualOperator = "!="
404 doubleEqualOperator = "=="
408 // termOperators holds the recognized operators supported in fieldSelectors.
409 // doubleEqualOperator and equal are equivalent, but doubleEqualOperator is checked first
410 // to avoid leaving a leading = character on the rhs value.
411 var termOperators = []string{notEqualOperator, doubleEqualOperator, equalOperator}
413 // splitTerm returns the lhs, operator, and rhs parsed from the given term, along with an indicator of whether the parse was successful.
414 // 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.
415 // the literal rhs is returned, and the caller is responsible for applying any desired unescaping.
416 func splitTerm(term string) (lhs, op, rhs string, ok bool) {
417 for i := range term {
418 remaining := term[i:]
419 for _, op := range termOperators {
420 if strings.HasPrefix(remaining, op) {
421 return term[0:i], op, term[i+len(op):], true
425 return "", "", "", false
428 func parseSelector(selector string, fn TransformFunc) (Selector, error) {
429 parts := splitTerms(selector)
430 sort.StringSlice(parts).Sort()
432 for _, part := range parts {
436 lhs, op, rhs, ok := splitTerm(part)
438 return nil, fmt.Errorf("invalid selector: '%s'; can't understand '%s'", selector, part)
440 unescapedRHS, err := UnescapeValue(rhs)
445 case notEqualOperator:
446 items = append(items, ¬HasTerm{field: lhs, value: unescapedRHS})
447 case doubleEqualOperator:
448 items = append(items, &hasTerm{field: lhs, value: unescapedRHS})
450 items = append(items, &hasTerm{field: lhs, value: unescapedRHS})
452 return nil, fmt.Errorf("invalid selector: '%s'; can't understand '%s'", selector, part)
456 return items[0].Transform(fn)
458 return andTerm(items).Transform(fn)
461 // OneTermEqualSelector returns an object that matches objects where one field/field equals one value.
462 // Cannot return an error.
463 func OneTermEqualSelector(k, v string) Selector {
464 return &hasTerm{field: k, value: v}
467 // OneTermNotEqualSelector returns an object that matches objects where one field/field does not equal one value.
468 // Cannot return an error.
469 func OneTermNotEqualSelector(k, v string) Selector {
470 return ¬HasTerm{field: k, value: v}
473 // AndSelectors creates a selector that is the logical AND of all the given selectors
474 func AndSelectors(selectors ...Selector) Selector {
475 return andTerm(selectors)