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