blob: bf62f98a42958ead9d2644857ecd83d2147ee5ca [file] [log] [blame]
Matteo Scandoloa4285862020-12-01 18:10:10 -08001/*
2Copyright 2014 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 labels
18
19import (
20 "bytes"
21 "fmt"
22 "sort"
23 "strconv"
24 "strings"
25
26 "k8s.io/apimachinery/pkg/selection"
27 "k8s.io/apimachinery/pkg/util/sets"
28 "k8s.io/apimachinery/pkg/util/validation"
29 "k8s.io/klog/v2"
30)
31
32// Requirements is AND of all requirements.
33type Requirements []Requirement
34
35// Selector represents a label selector.
36type Selector interface {
37 // Matches returns true if this selector matches the given set of labels.
38 Matches(Labels) bool
39
40 // Empty returns true if this selector does not restrict the selection space.
41 Empty() bool
42
43 // String returns a human readable string that represents this selector.
44 String() string
45
46 // Add adds requirements to the Selector
47 Add(r ...Requirement) Selector
48
49 // Requirements converts this interface into Requirements to expose
50 // more detailed selection information.
51 // If there are querying parameters, it will return converted requirements and selectable=true.
52 // If this selector doesn't want to select anything, it will return selectable=false.
53 Requirements() (requirements Requirements, selectable bool)
54
55 // Make a deep copy of the selector.
56 DeepCopySelector() Selector
57
58 // RequiresExactMatch allows a caller to introspect whether a given selector
59 // requires a single specific label to be set, and if so returns the value it
60 // requires.
61 RequiresExactMatch(label string) (value string, found bool)
62}
63
64// Everything returns a selector that matches all labels.
65func Everything() Selector {
66 return internalSelector{}
67}
68
69type nothingSelector struct{}
70
71func (n nothingSelector) Matches(_ Labels) bool { return false }
72func (n nothingSelector) Empty() bool { return false }
73func (n nothingSelector) String() string { return "" }
74func (n nothingSelector) Add(_ ...Requirement) Selector { return n }
75func (n nothingSelector) Requirements() (Requirements, bool) { return nil, false }
76func (n nothingSelector) DeepCopySelector() Selector { return n }
77func (n nothingSelector) RequiresExactMatch(label string) (value string, found bool) {
78 return "", false
79}
80
81// Nothing returns a selector that matches no labels
82func Nothing() Selector {
83 return nothingSelector{}
84}
85
86// NewSelector returns a nil selector
87func NewSelector() Selector {
88 return internalSelector(nil)
89}
90
91type internalSelector []Requirement
92
93func (s internalSelector) DeepCopy() internalSelector {
94 if s == nil {
95 return nil
96 }
97 result := make([]Requirement, len(s))
98 for i := range s {
99 s[i].DeepCopyInto(&result[i])
100 }
101 return result
102}
103
104func (s internalSelector) DeepCopySelector() Selector {
105 return s.DeepCopy()
106}
107
108// ByKey sorts requirements by key to obtain deterministic parser
109type ByKey []Requirement
110
111func (a ByKey) Len() int { return len(a) }
112
113func (a ByKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
114
115func (a ByKey) Less(i, j int) bool { return a[i].key < a[j].key }
116
117// Requirement contains values, a key, and an operator that relates the key and values.
118// The zero value of Requirement is invalid.
119// Requirement implements both set based match and exact match
120// Requirement should be initialized via NewRequirement constructor for creating a valid Requirement.
121// +k8s:deepcopy-gen=true
122type Requirement struct {
123 key string
124 operator selection.Operator
125 // In huge majority of cases we have at most one value here.
126 // It is generally faster to operate on a single-element slice
127 // than on a single-element map, so we have a slice here.
128 strValues []string
129}
130
131// NewRequirement is the constructor for a Requirement.
132// If any of these rules is violated, an error is returned:
133// (1) The operator can only be In, NotIn, Equals, DoubleEquals, NotEquals, Exists, or DoesNotExist.
134// (2) If the operator is In or NotIn, the values set must be non-empty.
135// (3) If the operator is Equals, DoubleEquals, or NotEquals, the values set must contain one value.
136// (4) If the operator is Exists or DoesNotExist, the value set must be empty.
137// (5) If the operator is Gt or Lt, the values set must contain only one value, which will be interpreted as an integer.
138// (6) The key is invalid due to its length, or sequence
139// of characters. See validateLabelKey for more details.
140//
141// The empty string is a valid value in the input values set.
142func NewRequirement(key string, op selection.Operator, vals []string) (*Requirement, error) {
143 if err := validateLabelKey(key); err != nil {
144 return nil, err
145 }
146 switch op {
147 case selection.In, selection.NotIn:
148 if len(vals) == 0 {
149 return nil, fmt.Errorf("for 'in', 'notin' operators, values set can't be empty")
150 }
151 case selection.Equals, selection.DoubleEquals, selection.NotEquals:
152 if len(vals) != 1 {
153 return nil, fmt.Errorf("exact-match compatibility requires one single value")
154 }
155 case selection.Exists, selection.DoesNotExist:
156 if len(vals) != 0 {
157 return nil, fmt.Errorf("values set must be empty for exists and does not exist")
158 }
159 case selection.GreaterThan, selection.LessThan:
160 if len(vals) != 1 {
161 return nil, fmt.Errorf("for 'Gt', 'Lt' operators, exactly one value is required")
162 }
163 for i := range vals {
164 if _, err := strconv.ParseInt(vals[i], 10, 64); err != nil {
165 return nil, fmt.Errorf("for 'Gt', 'Lt' operators, the value must be an integer")
166 }
167 }
168 default:
169 return nil, fmt.Errorf("operator '%v' is not recognized", op)
170 }
171
172 for i := range vals {
173 if err := validateLabelValue(key, vals[i]); err != nil {
174 return nil, err
175 }
176 }
177 return &Requirement{key: key, operator: op, strValues: vals}, nil
178}
179
180func (r *Requirement) hasValue(value string) bool {
181 for i := range r.strValues {
182 if r.strValues[i] == value {
183 return true
184 }
185 }
186 return false
187}
188
189// Matches returns true if the Requirement matches the input Labels.
190// There is a match in the following cases:
191// (1) The operator is Exists and Labels has the Requirement's key.
192// (2) The operator is In, Labels has the Requirement's key and Labels'
193// value for that key is in Requirement's value set.
194// (3) The operator is NotIn, Labels has the Requirement's key and
195// Labels' value for that key is not in Requirement's value set.
196// (4) The operator is DoesNotExist or NotIn and Labels does not have the
197// Requirement's key.
198// (5) The operator is GreaterThanOperator or LessThanOperator, and Labels has
199// the Requirement's key and the corresponding value satisfies mathematical inequality.
200func (r *Requirement) Matches(ls Labels) bool {
201 switch r.operator {
202 case selection.In, selection.Equals, selection.DoubleEquals:
203 if !ls.Has(r.key) {
204 return false
205 }
206 return r.hasValue(ls.Get(r.key))
207 case selection.NotIn, selection.NotEquals:
208 if !ls.Has(r.key) {
209 return true
210 }
211 return !r.hasValue(ls.Get(r.key))
212 case selection.Exists:
213 return ls.Has(r.key)
214 case selection.DoesNotExist:
215 return !ls.Has(r.key)
216 case selection.GreaterThan, selection.LessThan:
217 if !ls.Has(r.key) {
218 return false
219 }
220 lsValue, err := strconv.ParseInt(ls.Get(r.key), 10, 64)
221 if err != nil {
222 klog.V(10).Infof("ParseInt failed for value %+v in label %+v, %+v", ls.Get(r.key), ls, err)
223 return false
224 }
225
226 // There should be only one strValue in r.strValues, and can be converted to an integer.
227 if len(r.strValues) != 1 {
228 klog.V(10).Infof("Invalid values count %+v of requirement %#v, for 'Gt', 'Lt' operators, exactly one value is required", len(r.strValues), r)
229 return false
230 }
231
232 var rValue int64
233 for i := range r.strValues {
234 rValue, err = strconv.ParseInt(r.strValues[i], 10, 64)
235 if err != nil {
236 klog.V(10).Infof("ParseInt failed for value %+v in requirement %#v, for 'Gt', 'Lt' operators, the value must be an integer", r.strValues[i], r)
237 return false
238 }
239 }
240 return (r.operator == selection.GreaterThan && lsValue > rValue) || (r.operator == selection.LessThan && lsValue < rValue)
241 default:
242 return false
243 }
244}
245
246// Key returns requirement key
247func (r *Requirement) Key() string {
248 return r.key
249}
250
251// Operator returns requirement operator
252func (r *Requirement) Operator() selection.Operator {
253 return r.operator
254}
255
256// Values returns requirement values
257func (r *Requirement) Values() sets.String {
258 ret := sets.String{}
259 for i := range r.strValues {
260 ret.Insert(r.strValues[i])
261 }
262 return ret
263}
264
265// Empty returns true if the internalSelector doesn't restrict selection space
266func (lsel internalSelector) Empty() bool {
267 if lsel == nil {
268 return true
269 }
270 return len(lsel) == 0
271}
272
273// String returns a human-readable string that represents this
274// Requirement. If called on an invalid Requirement, an error is
275// returned. See NewRequirement for creating a valid Requirement.
276func (r *Requirement) String() string {
277 var buffer bytes.Buffer
278 if r.operator == selection.DoesNotExist {
279 buffer.WriteString("!")
280 }
281 buffer.WriteString(r.key)
282
283 switch r.operator {
284 case selection.Equals:
285 buffer.WriteString("=")
286 case selection.DoubleEquals:
287 buffer.WriteString("==")
288 case selection.NotEquals:
289 buffer.WriteString("!=")
290 case selection.In:
291 buffer.WriteString(" in ")
292 case selection.NotIn:
293 buffer.WriteString(" notin ")
294 case selection.GreaterThan:
295 buffer.WriteString(">")
296 case selection.LessThan:
297 buffer.WriteString("<")
298 case selection.Exists, selection.DoesNotExist:
299 return buffer.String()
300 }
301
302 switch r.operator {
303 case selection.In, selection.NotIn:
304 buffer.WriteString("(")
305 }
306 if len(r.strValues) == 1 {
307 buffer.WriteString(r.strValues[0])
308 } else { // only > 1 since == 0 prohibited by NewRequirement
309 // normalizes value order on output, without mutating the in-memory selector representation
310 // also avoids normalization when it is not required, and ensures we do not mutate shared data
311 buffer.WriteString(strings.Join(safeSort(r.strValues), ","))
312 }
313
314 switch r.operator {
315 case selection.In, selection.NotIn:
316 buffer.WriteString(")")
317 }
318 return buffer.String()
319}
320
321// safeSort sort input strings without modification
322func safeSort(in []string) []string {
323 if sort.StringsAreSorted(in) {
324 return in
325 }
326 out := make([]string, len(in))
327 copy(out, in)
328 sort.Strings(out)
329 return out
330}
331
332// Add adds requirements to the selector. It copies the current selector returning a new one
333func (lsel internalSelector) Add(reqs ...Requirement) Selector {
334 var sel internalSelector
335 for ix := range lsel {
336 sel = append(sel, lsel[ix])
337 }
338 for _, r := range reqs {
339 sel = append(sel, r)
340 }
341 sort.Sort(ByKey(sel))
342 return sel
343}
344
345// Matches for a internalSelector returns true if all
346// its Requirements match the input Labels. If any
347// Requirement does not match, false is returned.
348func (lsel internalSelector) Matches(l Labels) bool {
349 for ix := range lsel {
350 if matches := lsel[ix].Matches(l); !matches {
351 return false
352 }
353 }
354 return true
355}
356
357func (lsel internalSelector) Requirements() (Requirements, bool) { return Requirements(lsel), true }
358
359// String returns a comma-separated string of all
360// the internalSelector Requirements' human-readable strings.
361func (lsel internalSelector) String() string {
362 var reqs []string
363 for ix := range lsel {
364 reqs = append(reqs, lsel[ix].String())
365 }
366 return strings.Join(reqs, ",")
367}
368
369// RequiresExactMatch introspect whether a given selector requires a single specific field
370// to be set, and if so returns the value it requires.
371func (lsel internalSelector) RequiresExactMatch(label string) (value string, found bool) {
372 for ix := range lsel {
373 if lsel[ix].key == label {
374 switch lsel[ix].operator {
375 case selection.Equals, selection.DoubleEquals, selection.In:
376 if len(lsel[ix].strValues) == 1 {
377 return lsel[ix].strValues[0], true
378 }
379 }
380 return "", false
381 }
382 }
383 return "", false
384}
385
386// Token represents constant definition for lexer token
387type Token int
388
389const (
390 // ErrorToken represents scan error
391 ErrorToken Token = iota
392 // EndOfStringToken represents end of string
393 EndOfStringToken
394 // ClosedParToken represents close parenthesis
395 ClosedParToken
396 // CommaToken represents the comma
397 CommaToken
398 // DoesNotExistToken represents logic not
399 DoesNotExistToken
400 // DoubleEqualsToken represents double equals
401 DoubleEqualsToken
402 // EqualsToken represents equal
403 EqualsToken
404 // GreaterThanToken represents greater than
405 GreaterThanToken
406 // IdentifierToken represents identifier, e.g. keys and values
407 IdentifierToken
408 // InToken represents in
409 InToken
410 // LessThanToken represents less than
411 LessThanToken
412 // NotEqualsToken represents not equal
413 NotEqualsToken
414 // NotInToken represents not in
415 NotInToken
416 // OpenParToken represents open parenthesis
417 OpenParToken
418)
419
420// string2token contains the mapping between lexer Token and token literal
421// (except IdentifierToken, EndOfStringToken and ErrorToken since it makes no sense)
422var string2token = map[string]Token{
423 ")": ClosedParToken,
424 ",": CommaToken,
425 "!": DoesNotExistToken,
426 "==": DoubleEqualsToken,
427 "=": EqualsToken,
428 ">": GreaterThanToken,
429 "in": InToken,
430 "<": LessThanToken,
431 "!=": NotEqualsToken,
432 "notin": NotInToken,
433 "(": OpenParToken,
434}
435
436// ScannedItem contains the Token and the literal produced by the lexer.
437type ScannedItem struct {
438 tok Token
439 literal string
440}
441
442// isWhitespace returns true if the rune is a space, tab, or newline.
443func isWhitespace(ch byte) bool {
444 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'
445}
446
447// isSpecialSymbol detect if the character ch can be an operator
448func isSpecialSymbol(ch byte) bool {
449 switch ch {
450 case '=', '!', '(', ')', ',', '>', '<':
451 return true
452 }
453 return false
454}
455
456// Lexer represents the Lexer struct for label selector.
457// It contains necessary informationt to tokenize the input string
458type Lexer struct {
459 // s stores the string to be tokenized
460 s string
461 // pos is the position currently tokenized
462 pos int
463}
464
465// read return the character currently lexed
466// increment the position and check the buffer overflow
467func (l *Lexer) read() (b byte) {
468 b = 0
469 if l.pos < len(l.s) {
470 b = l.s[l.pos]
471 l.pos++
472 }
473 return b
474}
475
476// unread 'undoes' the last read character
477func (l *Lexer) unread() {
478 l.pos--
479}
480
481// scanIDOrKeyword scans string to recognize literal token (for example 'in') or an identifier.
482func (l *Lexer) scanIDOrKeyword() (tok Token, lit string) {
483 var buffer []byte
484IdentifierLoop:
485 for {
486 switch ch := l.read(); {
487 case ch == 0:
488 break IdentifierLoop
489 case isSpecialSymbol(ch) || isWhitespace(ch):
490 l.unread()
491 break IdentifierLoop
492 default:
493 buffer = append(buffer, ch)
494 }
495 }
496 s := string(buffer)
497 if val, ok := string2token[s]; ok { // is a literal token?
498 return val, s
499 }
500 return IdentifierToken, s // otherwise is an identifier
501}
502
503// scanSpecialSymbol scans string starting with special symbol.
504// special symbol identify non literal operators. "!=", "==", "="
505func (l *Lexer) scanSpecialSymbol() (Token, string) {
506 lastScannedItem := ScannedItem{}
507 var buffer []byte
508SpecialSymbolLoop:
509 for {
510 switch ch := l.read(); {
511 case ch == 0:
512 break SpecialSymbolLoop
513 case isSpecialSymbol(ch):
514 buffer = append(buffer, ch)
515 if token, ok := string2token[string(buffer)]; ok {
516 lastScannedItem = ScannedItem{tok: token, literal: string(buffer)}
517 } else if lastScannedItem.tok != 0 {
518 l.unread()
519 break SpecialSymbolLoop
520 }
521 default:
522 l.unread()
523 break SpecialSymbolLoop
524 }
525 }
526 if lastScannedItem.tok == 0 {
527 return ErrorToken, fmt.Sprintf("error expected: keyword found '%s'", buffer)
528 }
529 return lastScannedItem.tok, lastScannedItem.literal
530}
531
532// skipWhiteSpaces consumes all blank characters
533// returning the first non blank character
534func (l *Lexer) skipWhiteSpaces(ch byte) byte {
535 for {
536 if !isWhitespace(ch) {
537 return ch
538 }
539 ch = l.read()
540 }
541}
542
543// Lex returns a pair of Token and the literal
544// literal is meaningfull only for IdentifierToken token
545func (l *Lexer) Lex() (tok Token, lit string) {
546 switch ch := l.skipWhiteSpaces(l.read()); {
547 case ch == 0:
548 return EndOfStringToken, ""
549 case isSpecialSymbol(ch):
550 l.unread()
551 return l.scanSpecialSymbol()
552 default:
553 l.unread()
554 return l.scanIDOrKeyword()
555 }
556}
557
558// Parser data structure contains the label selector parser data structure
559type Parser struct {
560 l *Lexer
561 scannedItems []ScannedItem
562 position int
563}
564
565// ParserContext represents context during parsing:
566// some literal for example 'in' and 'notin' can be
567// recognized as operator for example 'x in (a)' but
568// it can be recognized as value for example 'value in (in)'
569type ParserContext int
570
571const (
572 // KeyAndOperator represents key and operator
573 KeyAndOperator ParserContext = iota
574 // Values represents values
575 Values
576)
577
578// lookahead func returns the current token and string. No increment of current position
579func (p *Parser) lookahead(context ParserContext) (Token, string) {
580 tok, lit := p.scannedItems[p.position].tok, p.scannedItems[p.position].literal
581 if context == Values {
582 switch tok {
583 case InToken, NotInToken:
584 tok = IdentifierToken
585 }
586 }
587 return tok, lit
588}
589
590// consume returns current token and string. Increments the position
591func (p *Parser) consume(context ParserContext) (Token, string) {
592 p.position++
593 tok, lit := p.scannedItems[p.position-1].tok, p.scannedItems[p.position-1].literal
594 if context == Values {
595 switch tok {
596 case InToken, NotInToken:
597 tok = IdentifierToken
598 }
599 }
600 return tok, lit
601}
602
603// scan runs through the input string and stores the ScannedItem in an array
604// Parser can now lookahead and consume the tokens
605func (p *Parser) scan() {
606 for {
607 token, literal := p.l.Lex()
608 p.scannedItems = append(p.scannedItems, ScannedItem{token, literal})
609 if token == EndOfStringToken {
610 break
611 }
612 }
613}
614
615// parse runs the left recursive descending algorithm
616// on input string. It returns a list of Requirement objects.
617func (p *Parser) parse() (internalSelector, error) {
618 p.scan() // init scannedItems
619
620 var requirements internalSelector
621 for {
622 tok, lit := p.lookahead(Values)
623 switch tok {
624 case IdentifierToken, DoesNotExistToken:
625 r, err := p.parseRequirement()
626 if err != nil {
627 return nil, fmt.Errorf("unable to parse requirement: %v", err)
628 }
629 requirements = append(requirements, *r)
630 t, l := p.consume(Values)
631 switch t {
632 case EndOfStringToken:
633 return requirements, nil
634 case CommaToken:
635 t2, l2 := p.lookahead(Values)
636 if t2 != IdentifierToken && t2 != DoesNotExistToken {
637 return nil, fmt.Errorf("found '%s', expected: identifier after ','", l2)
638 }
639 default:
640 return nil, fmt.Errorf("found '%s', expected: ',' or 'end of string'", l)
641 }
642 case EndOfStringToken:
643 return requirements, nil
644 default:
645 return nil, fmt.Errorf("found '%s', expected: !, identifier, or 'end of string'", lit)
646 }
647 }
648}
649
650func (p *Parser) parseRequirement() (*Requirement, error) {
651 key, operator, err := p.parseKeyAndInferOperator()
652 if err != nil {
653 return nil, err
654 }
655 if operator == selection.Exists || operator == selection.DoesNotExist { // operator found lookahead set checked
656 return NewRequirement(key, operator, []string{})
657 }
658 operator, err = p.parseOperator()
659 if err != nil {
660 return nil, err
661 }
662 var values sets.String
663 switch operator {
664 case selection.In, selection.NotIn:
665 values, err = p.parseValues()
666 case selection.Equals, selection.DoubleEquals, selection.NotEquals, selection.GreaterThan, selection.LessThan:
667 values, err = p.parseExactValue()
668 }
669 if err != nil {
670 return nil, err
671 }
672 return NewRequirement(key, operator, values.List())
673
674}
675
676// parseKeyAndInferOperator parse literals.
677// in case of no operator '!, in, notin, ==, =, !=' are found
678// the 'exists' operator is inferred
679func (p *Parser) parseKeyAndInferOperator() (string, selection.Operator, error) {
680 var operator selection.Operator
681 tok, literal := p.consume(Values)
682 if tok == DoesNotExistToken {
683 operator = selection.DoesNotExist
684 tok, literal = p.consume(Values)
685 }
686 if tok != IdentifierToken {
687 err := fmt.Errorf("found '%s', expected: identifier", literal)
688 return "", "", err
689 }
690 if err := validateLabelKey(literal); err != nil {
691 return "", "", err
692 }
693 if t, _ := p.lookahead(Values); t == EndOfStringToken || t == CommaToken {
694 if operator != selection.DoesNotExist {
695 operator = selection.Exists
696 }
697 }
698 return literal, operator, nil
699}
700
701// parseOperator return operator and eventually matchType
702// matchType can be exact
703func (p *Parser) parseOperator() (op selection.Operator, err error) {
704 tok, lit := p.consume(KeyAndOperator)
705 switch tok {
706 // DoesNotExistToken shouldn't be here because it's a unary operator, not a binary operator
707 case InToken:
708 op = selection.In
709 case EqualsToken:
710 op = selection.Equals
711 case DoubleEqualsToken:
712 op = selection.DoubleEquals
713 case GreaterThanToken:
714 op = selection.GreaterThan
715 case LessThanToken:
716 op = selection.LessThan
717 case NotInToken:
718 op = selection.NotIn
719 case NotEqualsToken:
720 op = selection.NotEquals
721 default:
722 return "", fmt.Errorf("found '%s', expected: '=', '!=', '==', 'in', notin'", lit)
723 }
724 return op, nil
725}
726
727// parseValues parses the values for set based matching (x,y,z)
728func (p *Parser) parseValues() (sets.String, error) {
729 tok, lit := p.consume(Values)
730 if tok != OpenParToken {
731 return nil, fmt.Errorf("found '%s' expected: '('", lit)
732 }
733 tok, lit = p.lookahead(Values)
734 switch tok {
735 case IdentifierToken, CommaToken:
736 s, err := p.parseIdentifiersList() // handles general cases
737 if err != nil {
738 return s, err
739 }
740 if tok, _ = p.consume(Values); tok != ClosedParToken {
741 return nil, fmt.Errorf("found '%s', expected: ')'", lit)
742 }
743 return s, nil
744 case ClosedParToken: // handles "()"
745 p.consume(Values)
746 return sets.NewString(""), nil
747 default:
748 return nil, fmt.Errorf("found '%s', expected: ',', ')' or identifier", lit)
749 }
750}
751
752// parseIdentifiersList parses a (possibly empty) list of
753// of comma separated (possibly empty) identifiers
754func (p *Parser) parseIdentifiersList() (sets.String, error) {
755 s := sets.NewString()
756 for {
757 tok, lit := p.consume(Values)
758 switch tok {
759 case IdentifierToken:
760 s.Insert(lit)
761 tok2, lit2 := p.lookahead(Values)
762 switch tok2 {
763 case CommaToken:
764 continue
765 case ClosedParToken:
766 return s, nil
767 default:
768 return nil, fmt.Errorf("found '%s', expected: ',' or ')'", lit2)
769 }
770 case CommaToken: // handled here since we can have "(,"
771 if s.Len() == 0 {
772 s.Insert("") // to handle (,
773 }
774 tok2, _ := p.lookahead(Values)
775 if tok2 == ClosedParToken {
776 s.Insert("") // to handle ,) Double "" removed by StringSet
777 return s, nil
778 }
779 if tok2 == CommaToken {
780 p.consume(Values)
781 s.Insert("") // to handle ,, Double "" removed by StringSet
782 }
783 default: // it can be operator
784 return s, fmt.Errorf("found '%s', expected: ',', or identifier", lit)
785 }
786 }
787}
788
789// parseExactValue parses the only value for exact match style
790func (p *Parser) parseExactValue() (sets.String, error) {
791 s := sets.NewString()
792 tok, lit := p.lookahead(Values)
793 if tok == EndOfStringToken || tok == CommaToken {
794 s.Insert("")
795 return s, nil
796 }
797 tok, lit = p.consume(Values)
798 if tok == IdentifierToken {
799 s.Insert(lit)
800 return s, nil
801 }
802 return nil, fmt.Errorf("found '%s', expected: identifier", lit)
803}
804
805// Parse takes a string representing a selector and returns a selector
806// object, or an error. This parsing function differs from ParseSelector
807// as they parse different selectors with different syntaxes.
808// The input will cause an error if it does not follow this form:
809//
810// <selector-syntax> ::= <requirement> | <requirement> "," <selector-syntax>
811// <requirement> ::= [!] KEY [ <set-based-restriction> | <exact-match-restriction> ]
812// <set-based-restriction> ::= "" | <inclusion-exclusion> <value-set>
813// <inclusion-exclusion> ::= <inclusion> | <exclusion>
814// <exclusion> ::= "notin"
815// <inclusion> ::= "in"
816// <value-set> ::= "(" <values> ")"
817// <values> ::= VALUE | VALUE "," <values>
818// <exact-match-restriction> ::= ["="|"=="|"!="] VALUE
819//
820// KEY is a sequence of one or more characters following [ DNS_SUBDOMAIN "/" ] DNS_LABEL. Max length is 63 characters.
821// VALUE is a sequence of zero or more characters "([A-Za-z0-9_-\.])". Max length is 63 characters.
822// Delimiter is white space: (' ', '\t')
823// Example of valid syntax:
824// "x in (foo,,baz),y,z notin ()"
825//
826// Note:
827// (1) Inclusion - " in " - denotes that the KEY exists and is equal to any of the
828// VALUEs in its requirement
829// (2) Exclusion - " notin " - denotes that the KEY is not equal to any
830// of the VALUEs in its requirement or does not exist
831// (3) The empty string is a valid VALUE
832// (4) A requirement with just a KEY - as in "y" above - denotes that
833// the KEY exists and can be any VALUE.
834// (5) A requirement with just !KEY requires that the KEY not exist.
835//
836func Parse(selector string) (Selector, error) {
837 parsedSelector, err := parse(selector)
838 if err == nil {
839 return parsedSelector, nil
840 }
841 return nil, err
842}
843
844// parse parses the string representation of the selector and returns the internalSelector struct.
845// The callers of this method can then decide how to return the internalSelector struct to their
846// callers. This function has two callers now, one returns a Selector interface and the other
847// returns a list of requirements.
848func parse(selector string) (internalSelector, error) {
849 p := &Parser{l: &Lexer{s: selector, pos: 0}}
850 items, err := p.parse()
851 if err != nil {
852 return nil, err
853 }
854 sort.Sort(ByKey(items)) // sort to grant determistic parsing
855 return internalSelector(items), err
856}
857
858func validateLabelKey(k string) error {
859 if errs := validation.IsQualifiedName(k); len(errs) != 0 {
860 return fmt.Errorf("invalid label key %q: %s", k, strings.Join(errs, "; "))
861 }
862 return nil
863}
864
865func validateLabelValue(k, v string) error {
866 if errs := validation.IsValidLabelValue(v); len(errs) != 0 {
867 return fmt.Errorf("invalid label value: %q: at key: %q: %s", v, k, strings.Join(errs, "; "))
868 }
869 return nil
870}
871
872// SelectorFromSet returns a Selector which will match exactly the given Set. A
873// nil and empty Sets are considered equivalent to Everything().
874// It does not perform any validation, which means the server will reject
875// the request if the Set contains invalid values.
876func SelectorFromSet(ls Set) Selector {
877 return SelectorFromValidatedSet(ls)
878}
879
880// ValidatedSelectorFromSet returns a Selector which will match exactly the given Set. A
881// nil and empty Sets are considered equivalent to Everything().
882// The Set is validated client-side, which allows to catch errors early.
883func ValidatedSelectorFromSet(ls Set) (Selector, error) {
884 if ls == nil || len(ls) == 0 {
885 return internalSelector{}, nil
886 }
887 requirements := make([]Requirement, 0, len(ls))
888 for label, value := range ls {
889 r, err := NewRequirement(label, selection.Equals, []string{value})
890 if err != nil {
891 return nil, err
892 }
893 requirements = append(requirements, *r)
894 }
895 // sort to have deterministic string representation
896 sort.Sort(ByKey(requirements))
897 return internalSelector(requirements), nil
898}
899
900// SelectorFromValidatedSet returns a Selector which will match exactly the given Set.
901// A nil and empty Sets are considered equivalent to Everything().
902// It assumes that Set is already validated and doesn't do any validation.
903func SelectorFromValidatedSet(ls Set) Selector {
904 if ls == nil || len(ls) == 0 {
905 return internalSelector{}
906 }
907 requirements := make([]Requirement, 0, len(ls))
908 for label, value := range ls {
909 requirements = append(requirements, Requirement{key: label, operator: selection.Equals, strValues: []string{value}})
910 }
911 // sort to have deterministic string representation
912 sort.Sort(ByKey(requirements))
913 return internalSelector(requirements)
914}
915
916// ParseToRequirements takes a string representing a selector and returns a list of
917// requirements. This function is suitable for those callers that perform additional
918// processing on selector requirements.
919// See the documentation for Parse() function for more details.
920// TODO: Consider exporting the internalSelector type instead.
921func ParseToRequirements(selector string) ([]Requirement, error) {
922 return parse(selector)
923}