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