1
2
3
4
19
20 package labels
21
22 import (
23 "bytes"
24 "fmt"
25 "sort"
26 "strconv"
27 "strings"
28
29 "log"
30 "sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/selection"
31 "sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/util/sets"
32 "sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/util/validation"
33 )
34
35
36 type Requirements []Requirement
37
38
39 type Selector interface {
40
41 Matches(Labels) bool
42
43
44 Empty() bool
45
46
47 String() string
48
49
50 Add(r ...Requirement) Selector
51
52
53
54
55
56 Requirements() (requirements Requirements, selectable bool)
57
58
59 DeepCopySelector() Selector
60
61
62
63
64 RequiresExactMatch(label string) (value string, found bool)
65 }
66
67
68 func Everything() Selector {
69 return internalSelector{}
70 }
71
72 type nothingSelector struct{}
73
74 func (n nothingSelector) Matches(_ Labels) bool { return false }
75 func (n nothingSelector) Empty() bool { return false }
76 func (n nothingSelector) String() string { return "" }
77 func (n nothingSelector) Add(_ ...Requirement) Selector { return n }
78 func (n nothingSelector) Requirements() (Requirements, bool) { return nil, false }
79 func (n nothingSelector) DeepCopySelector() Selector { return n }
80 func (n nothingSelector) RequiresExactMatch(label string) (value string, found bool) {
81 return "", false
82 }
83
84
85 func Nothing() Selector {
86 return nothingSelector{}
87 }
88
89
90 func NewSelector() Selector {
91 return internalSelector(nil)
92 }
93
94 type internalSelector []Requirement
95
96 func (s internalSelector) DeepCopy() internalSelector {
97 if s == nil {
98 return nil
99 }
100 result := make([]Requirement, len(s))
101 for i := range s {
102 s[i].DeepCopyInto(&result[i])
103 }
104 return result
105 }
106
107 func (s internalSelector) DeepCopySelector() Selector {
108 return s.DeepCopy()
109 }
110
111
112 type ByKey []Requirement
113
114 func (a ByKey) Len() int { return len(a) }
115
116 func (a ByKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
117
118 func (a ByKey) Less(i, j int) bool { return a[i].key < a[j].key }
119
120
121
122
123
124 type Requirement struct {
125 key string
126 operator selection.Operator
127
128
129
130 strValues []string
131 }
132
133
134
135
136
137
138
139
140
141
142
143
144 func NewRequirement(key string, op selection.Operator, vals []string) (*Requirement, error) {
145 if err := validateLabelKey(key); err != nil {
146 return nil, err
147 }
148 switch op {
149 case selection.In, selection.NotIn:
150 if len(vals) == 0 {
151 return nil, fmt.Errorf("for 'in', 'notin' operators, values set can't be empty")
152 }
153 case selection.Equals, selection.DoubleEquals, selection.NotEquals:
154 if len(vals) != 1 {
155 return nil, fmt.Errorf("exact-match compatibility requires one single value")
156 }
157 case selection.Exists, selection.DoesNotExist:
158 if len(vals) != 0 {
159 return nil, fmt.Errorf("values set must be empty for exists and does not exist")
160 }
161 case selection.GreaterThan, selection.LessThan:
162 if len(vals) != 1 {
163 return nil, fmt.Errorf("for 'Gt', 'Lt' operators, exactly one value is required")
164 }
165 for i := range vals {
166 if _, err := strconv.ParseInt(vals[i], 10, 64); err != nil {
167 return nil, fmt.Errorf("for 'Gt', 'Lt' operators, the value must be an integer")
168 }
169 }
170 default:
171 return nil, fmt.Errorf("operator '%v' is not recognized", op)
172 }
173
174 for i := range vals {
175 if err := validateLabelValue(key, vals[i]); err != nil {
176 return nil, err
177 }
178 }
179 return &Requirement{key: key, operator: op, strValues: vals}, nil
180 }
181
182 func (r *Requirement) hasValue(value string) bool {
183 for i := range r.strValues {
184 if r.strValues[i] == value {
185 return true
186 }
187 }
188 return false
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202 func (r *Requirement) Matches(ls Labels) bool {
203 switch r.operator {
204 case selection.In, selection.Equals, selection.DoubleEquals:
205 if !ls.Has(r.key) {
206 return false
207 }
208 return r.hasValue(ls.Get(r.key))
209 case selection.NotIn, selection.NotEquals:
210 if !ls.Has(r.key) {
211 return true
212 }
213 return !r.hasValue(ls.Get(r.key))
214 case selection.Exists:
215 return ls.Has(r.key)
216 case selection.DoesNotExist:
217 return !ls.Has(r.key)
218 case selection.GreaterThan, selection.LessThan:
219 if !ls.Has(r.key) {
220 return false
221 }
222 lsValue, err := strconv.ParseInt(ls.Get(r.key), 10, 64)
223 if err != nil {
224 log.Printf("ParseInt failed for value %+v in label %+v, %+v", ls.Get(r.key), ls, err)
225 return false
226 }
227
228
229 if len(r.strValues) != 1 {
230 log.Printf("Invalid values count %+v of requirement %#v, for 'Gt', 'Lt' operators, exactly one value is required", len(r.strValues), r)
231 return false
232 }
233
234 var rValue int64
235 for i := range r.strValues {
236 rValue, err = strconv.ParseInt(r.strValues[i], 10, 64)
237 if err != nil {
238 log.Printf("ParseInt failed for value %+v in requirement %#v, for 'Gt', 'Lt' operators, the value must be an integer", r.strValues[i], r)
239 return false
240 }
241 }
242 return (r.operator == selection.GreaterThan && lsValue > rValue) || (r.operator == selection.LessThan && lsValue < rValue)
243 default:
244 return false
245 }
246 }
247
248
249 func (r *Requirement) Key() string {
250 return r.key
251 }
252
253
254 func (r *Requirement) Operator() selection.Operator {
255 return r.operator
256 }
257
258
259 func (r *Requirement) Values() sets.String {
260 ret := sets.String{}
261 for i := range r.strValues {
262 ret.Insert(r.strValues[i])
263 }
264 return ret
265 }
266
267
268 func (lsel internalSelector) Empty() bool {
269 if lsel == nil {
270 return true
271 }
272 return len(lsel) == 0
273 }
274
275
276
277
278 func (r *Requirement) String() string {
279 var buffer bytes.Buffer
280 if r.operator == selection.DoesNotExist {
281 buffer.WriteString("!")
282 }
283 buffer.WriteString(r.key)
284
285 switch r.operator {
286 case selection.Equals:
287 buffer.WriteString("=")
288 case selection.DoubleEquals:
289 buffer.WriteString("==")
290 case selection.NotEquals:
291 buffer.WriteString("!=")
292 case selection.In:
293 buffer.WriteString(" in ")
294 case selection.NotIn:
295 buffer.WriteString(" notin ")
296 case selection.GreaterThan:
297 buffer.WriteString(">")
298 case selection.LessThan:
299 buffer.WriteString("<")
300 case selection.Exists, selection.DoesNotExist:
301 return buffer.String()
302 }
303
304 switch r.operator {
305 case selection.In, selection.NotIn:
306 buffer.WriteString("(")
307 }
308 if len(r.strValues) == 1 {
309 buffer.WriteString(r.strValues[0])
310 } else {
311
312
313 buffer.WriteString(strings.Join(safeSort(r.strValues), ","))
314 }
315
316 switch r.operator {
317 case selection.In, selection.NotIn:
318 buffer.WriteString(")")
319 }
320 return buffer.String()
321 }
322
323
324 func safeSort(in []string) []string {
325 if sort.StringsAreSorted(in) {
326 return in
327 }
328 out := make([]string, len(in))
329 copy(out, in)
330 sort.Strings(out)
331 return out
332 }
333
334
335 func (lsel internalSelector) Add(reqs ...Requirement) Selector {
336 var sel internalSelector
337 for ix := range lsel {
338 sel = append(sel, lsel[ix])
339 }
340 for _, r := range reqs {
341 sel = append(sel, r)
342 }
343 sort.Sort(ByKey(sel))
344 return sel
345 }
346
347
348
349
350 func (lsel internalSelector) Matches(l Labels) bool {
351 for ix := range lsel {
352 if matches := lsel[ix].Matches(l); !matches {
353 return false
354 }
355 }
356 return true
357 }
358
359 func (lsel internalSelector) Requirements() (Requirements, bool) { return Requirements(lsel), true }
360
361
362
363 func (lsel internalSelector) String() string {
364 var reqs []string
365 for ix := range lsel {
366 reqs = append(reqs, lsel[ix].String())
367 }
368 return strings.Join(reqs, ",")
369 }
370
371
372
373 func (lsel internalSelector) RequiresExactMatch(label string) (value string, found bool) {
374 for ix := range lsel {
375 if lsel[ix].key == label {
376 switch lsel[ix].operator {
377 case selection.Equals, selection.DoubleEquals, selection.In:
378 if len(lsel[ix].strValues) == 1 {
379 return lsel[ix].strValues[0], true
380 }
381 }
382 return "", false
383 }
384 }
385 return "", false
386 }
387
388
389 type Token int
390
391 const (
392
393 ErrorToken Token = iota
394
395 EndOfStringToken
396
397 ClosedParToken
398
399 CommaToken
400
401 DoesNotExistToken
402
403 DoubleEqualsToken
404
405 EqualsToken
406
407 GreaterThanToken
408
409 IdentifierToken
410
411 InToken
412
413 LessThanToken
414
415 NotEqualsToken
416
417 NotInToken
418
419 OpenParToken
420 )
421
422
423
424 var string2token = map[string]Token{
425 ")": ClosedParToken,
426 ",": CommaToken,
427 "!": DoesNotExistToken,
428 "==": DoubleEqualsToken,
429 "=": EqualsToken,
430 ">": GreaterThanToken,
431 "in": InToken,
432 "<": LessThanToken,
433 "!=": NotEqualsToken,
434 "notin": NotInToken,
435 "(": OpenParToken,
436 }
437
438
439 type ScannedItem struct {
440 tok Token
441 literal string
442 }
443
444
445 func isWhitespace(ch byte) bool {
446 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'
447 }
448
449
450 func isSpecialSymbol(ch byte) bool {
451 switch ch {
452 case '=', '!', '(', ')', ',', '>', '<':
453 return true
454 }
455 return false
456 }
457
458
459
460 type Lexer struct {
461
462 s string
463
464 pos int
465 }
466
467
468
469 func (l *Lexer) read() (b byte) {
470 b = 0
471 if l.pos < len(l.s) {
472 b = l.s[l.pos]
473 l.pos++
474 }
475 return b
476 }
477
478
479 func (l *Lexer) unread() {
480 l.pos--
481 }
482
483
484 func (l *Lexer) scanIDOrKeyword() (tok Token, lit string) {
485 var buffer []byte
486 IdentifierLoop:
487 for {
488 switch ch := l.read(); {
489 case ch == 0:
490 break IdentifierLoop
491 case isSpecialSymbol(ch) || isWhitespace(ch):
492 l.unread()
493 break IdentifierLoop
494 default:
495 buffer = append(buffer, ch)
496 }
497 }
498 s := string(buffer)
499 if val, ok := string2token[s]; ok {
500 return val, s
501 }
502 return IdentifierToken, s
503 }
504
505
506
507 func (l *Lexer) scanSpecialSymbol() (Token, string) {
508 lastScannedItem := ScannedItem{}
509 var buffer []byte
510 SpecialSymbolLoop:
511 for {
512 switch ch := l.read(); {
513 case ch == 0:
514 break SpecialSymbolLoop
515 case isSpecialSymbol(ch):
516 buffer = append(buffer, ch)
517 if token, ok := string2token[string(buffer)]; ok {
518 lastScannedItem = ScannedItem{tok: token, literal: string(buffer)}
519 } else if lastScannedItem.tok != 0 {
520 l.unread()
521 break SpecialSymbolLoop
522 }
523 default:
524 l.unread()
525 break SpecialSymbolLoop
526 }
527 }
528 if lastScannedItem.tok == 0 {
529 return ErrorToken, fmt.Sprintf("error expected: keyword found '%s'", buffer)
530 }
531 return lastScannedItem.tok, lastScannedItem.literal
532 }
533
534
535
536 func (l *Lexer) skipWhiteSpaces(ch byte) byte {
537 for {
538 if !isWhitespace(ch) {
539 return ch
540 }
541 ch = l.read()
542 }
543 }
544
545
546
547 func (l *Lexer) Lex() (tok Token, lit string) {
548 switch ch := l.skipWhiteSpaces(l.read()); {
549 case ch == 0:
550 return EndOfStringToken, ""
551 case isSpecialSymbol(ch):
552 l.unread()
553 return l.scanSpecialSymbol()
554 default:
555 l.unread()
556 return l.scanIDOrKeyword()
557 }
558 }
559
560
561 type Parser struct {
562 l *Lexer
563 scannedItems []ScannedItem
564 position int
565 }
566
567
568
569
570
571 type ParserContext int
572
573 const (
574
575 KeyAndOperator ParserContext = iota
576
577 Values
578 )
579
580
581 func (p *Parser) lookahead(context ParserContext) (Token, string) {
582 tok, lit := p.scannedItems[p.position].tok, p.scannedItems[p.position].literal
583 if context == Values {
584 switch tok {
585 case InToken, NotInToken:
586 tok = IdentifierToken
587 }
588 }
589 return tok, lit
590 }
591
592
593 func (p *Parser) consume(context ParserContext) (Token, string) {
594 p.position++
595 tok, lit := p.scannedItems[p.position-1].tok, p.scannedItems[p.position-1].literal
596 if context == Values {
597 switch tok {
598 case InToken, NotInToken:
599 tok = IdentifierToken
600 }
601 }
602 return tok, lit
603 }
604
605
606
607 func (p *Parser) scan() {
608 for {
609 token, literal := p.l.Lex()
610 p.scannedItems = append(p.scannedItems, ScannedItem{token, literal})
611 if token == EndOfStringToken {
612 break
613 }
614 }
615 }
616
617
618
619 func (p *Parser) parse() (internalSelector, error) {
620 p.scan()
621
622 var requirements internalSelector
623 for {
624 tok, lit := p.lookahead(Values)
625 switch tok {
626 case IdentifierToken, DoesNotExistToken:
627 r, err := p.parseRequirement()
628 if err != nil {
629 return nil, fmt.Errorf("unable to parse requirement: %v", err)
630 }
631 requirements = append(requirements, *r)
632 t, l := p.consume(Values)
633 switch t {
634 case EndOfStringToken:
635 return requirements, nil
636 case CommaToken:
637 t2, l2 := p.lookahead(Values)
638 if t2 != IdentifierToken && t2 != DoesNotExistToken {
639 return nil, fmt.Errorf("found '%s', expected: identifier after ','", l2)
640 }
641 default:
642 return nil, fmt.Errorf("found '%s', expected: ',' or 'end of string'", l)
643 }
644 case EndOfStringToken:
645 return requirements, nil
646 default:
647 return nil, fmt.Errorf("found '%s', expected: !, identifier, or 'end of string'", lit)
648 }
649 }
650 }
651
652 func (p *Parser) parseRequirement() (*Requirement, error) {
653 key, operator, err := p.parseKeyAndInferOperator()
654 if err != nil {
655 return nil, err
656 }
657 if operator == selection.Exists || operator == selection.DoesNotExist {
658 return NewRequirement(key, operator, []string{})
659 }
660 operator, err = p.parseOperator()
661 if err != nil {
662 return nil, err
663 }
664 var values sets.String
665 switch operator {
666 case selection.In, selection.NotIn:
667 values, err = p.parseValues()
668 case selection.Equals, selection.DoubleEquals, selection.NotEquals, selection.GreaterThan, selection.LessThan:
669 values, err = p.parseExactValue()
670 }
671 if err != nil {
672 return nil, err
673 }
674 return NewRequirement(key, operator, values.List())
675
676 }
677
678
679
680
681 func (p *Parser) parseKeyAndInferOperator() (string, selection.Operator, error) {
682 var operator selection.Operator
683 tok, literal := p.consume(Values)
684 if tok == DoesNotExistToken {
685 operator = selection.DoesNotExist
686 tok, literal = p.consume(Values)
687 }
688 if tok != IdentifierToken {
689 err := fmt.Errorf("found '%s', expected: identifier", literal)
690 return "", "", err
691 }
692 if err := validateLabelKey(literal); err != nil {
693 return "", "", err
694 }
695 if t, _ := p.lookahead(Values); t == EndOfStringToken || t == CommaToken {
696 if operator != selection.DoesNotExist {
697 operator = selection.Exists
698 }
699 }
700 return literal, operator, nil
701 }
702
703
704
705 func (p *Parser) parseOperator() (op selection.Operator, err error) {
706 tok, lit := p.consume(KeyAndOperator)
707 switch tok {
708
709 case InToken:
710 op = selection.In
711 case EqualsToken:
712 op = selection.Equals
713 case DoubleEqualsToken:
714 op = selection.DoubleEquals
715 case GreaterThanToken:
716 op = selection.GreaterThan
717 case LessThanToken:
718 op = selection.LessThan
719 case NotInToken:
720 op = selection.NotIn
721 case NotEqualsToken:
722 op = selection.NotEquals
723 default:
724 return "", fmt.Errorf("found '%s', expected: '=', '!=', '==', 'in', notin'", lit)
725 }
726 return op, nil
727 }
728
729
730 func (p *Parser) parseValues() (sets.String, error) {
731 tok, lit := p.consume(Values)
732 if tok != OpenParToken {
733 return nil, fmt.Errorf("found '%s' expected: '('", lit)
734 }
735 tok, lit = p.lookahead(Values)
736 switch tok {
737 case IdentifierToken, CommaToken:
738 s, err := p.parseIdentifiersList()
739 if err != nil {
740 return s, err
741 }
742 if tok, _ = p.consume(Values); tok != ClosedParToken {
743 return nil, fmt.Errorf("found '%s', expected: ')'", lit)
744 }
745 return s, nil
746 case ClosedParToken:
747 p.consume(Values)
748 return sets.NewString(""), nil
749 default:
750 return nil, fmt.Errorf("found '%s', expected: ',', ')' or identifier", lit)
751 }
752 }
753
754
755
756 func (p *Parser) parseIdentifiersList() (sets.String, error) {
757 s := sets.NewString()
758 for {
759 tok, lit := p.consume(Values)
760 switch tok {
761 case IdentifierToken:
762 s.Insert(lit)
763 tok2, lit2 := p.lookahead(Values)
764 switch tok2 {
765 case CommaToken:
766 continue
767 case ClosedParToken:
768 return s, nil
769 default:
770 return nil, fmt.Errorf("found '%s', expected: ',' or ')'", lit2)
771 }
772 case CommaToken:
773 if s.Len() == 0 {
774 s.Insert("")
775 }
776 tok2, _ := p.lookahead(Values)
777 if tok2 == ClosedParToken {
778 s.Insert("")
779 return s, nil
780 }
781 if tok2 == CommaToken {
782 p.consume(Values)
783 s.Insert("")
784 }
785 default:
786 return s, fmt.Errorf("found '%s', expected: ',', or identifier", lit)
787 }
788 }
789 }
790
791
792 func (p *Parser) parseExactValue() (sets.String, error) {
793 s := sets.NewString()
794 tok, lit := p.lookahead(Values)
795 if tok == EndOfStringToken || tok == CommaToken {
796 s.Insert("")
797 return s, nil
798 }
799 tok, lit = p.consume(Values)
800 if tok == IdentifierToken {
801 s.Insert(lit)
802 return s, nil
803 }
804 return nil, fmt.Errorf("found '%s', expected: identifier", lit)
805 }
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838 func Parse(selector string) (Selector, error) {
839 parsedSelector, err := parse(selector)
840 if err == nil {
841 return parsedSelector, nil
842 }
843 return nil, err
844 }
845
846
847
848
849
850 func parse(selector string) (internalSelector, error) {
851 p := &Parser{l: &Lexer{s: selector, pos: 0}}
852 items, err := p.parse()
853 if err != nil {
854 return nil, err
855 }
856 sort.Sort(ByKey(items))
857 return internalSelector(items), err
858 }
859
860 func validateLabelKey(k string) error {
861 if errs := validation.IsQualifiedName(k); len(errs) != 0 {
862 return fmt.Errorf("invalid label key %q: %s", k, strings.Join(errs, "; "))
863 }
864 return nil
865 }
866
867 func validateLabelValue(k, v string) error {
868 if errs := validation.IsValidLabelValue(v); len(errs) != 0 {
869 return fmt.Errorf("invalid label value: %q: at key: %q: %s", v, k, strings.Join(errs, "; "))
870 }
871 return nil
872 }
873
874
875
876
877
878 func SelectorFromSet(ls Set) Selector {
879 return SelectorFromValidatedSet(ls)
880 }
881
882
883
884
885 func ValidatedSelectorFromSet(ls Set) (Selector, error) {
886 if ls == nil || len(ls) == 0 {
887 return internalSelector{}, nil
888 }
889 requirements := make([]Requirement, 0, len(ls))
890 for label, value := range ls {
891 r, err := NewRequirement(label, selection.Equals, []string{value})
892 if err != nil {
893 return nil, err
894 }
895 requirements = append(requirements, *r)
896 }
897
898 sort.Sort(ByKey(requirements))
899 return internalSelector(requirements), nil
900 }
901
902
903
904
905 func SelectorFromValidatedSet(ls Set) Selector {
906 if ls == nil || len(ls) == 0 {
907 return internalSelector{}
908 }
909 requirements := make([]Requirement, 0, len(ls))
910 for label, value := range ls {
911 requirements = append(requirements, Requirement{key: label, operator: selection.Equals, strValues: []string{value}})
912 }
913
914 sort.Sort(ByKey(requirements))
915 return internalSelector(requirements)
916 }
917
918
919
920
921
922
923 func ParseToRequirements(selector string) ([]Requirement, error) {
924 return parse(selector)
925 }
926
View as plain text