github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/fields/selector.go (about) 1 /* 2 Copyright 2015 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 fields 18 19 import ( 20 "bytes" 21 "fmt" 22 "sort" 23 "strings" 24 25 "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/selection" 26 ) 27 28 // Selector represents a field selector. 29 type Selector interface { 30 // Matches returns true if this selector matches the given set of fields. 31 Matches(Fields) bool 32 33 // Empty returns true if this selector does not restrict the selection space. 34 Empty() bool 35 36 // RequiresExactMatch allows a caller to introspect whether a given selector 37 // requires a single specific field to be set, and if so returns the value it 38 // requires. 39 RequiresExactMatch(field string) (value string, found bool) 40 41 // Transform returns a new copy of the selector after TransformFunc has been 42 // applied to the entire selector, or an error if fn returns an error. 43 // If for a given requirement both field and value are transformed to empty 44 // string, the requirement is skipped. 45 Transform(fn TransformFunc) (Selector, error) 46 47 // Requirements converts this interface to Requirements to expose 48 // more detailed selection information. 49 Requirements() Requirements 50 51 // String returns a human readable string that represents this selector. 52 String() string 53 54 // Make a deep copy of the selector. 55 DeepCopySelector() Selector 56 } 57 58 type nothingSelector struct{} 59 60 func (n nothingSelector) Matches(_ Fields) bool { return false } 61 func (n nothingSelector) Empty() bool { return false } 62 func (n nothingSelector) String() string { return "" } 63 func (n nothingSelector) Requirements() Requirements { return nil } 64 func (n nothingSelector) DeepCopySelector() Selector { return n } 65 func (n nothingSelector) RequiresExactMatch(field string) (value string, found bool) { 66 return "", false 67 } 68 func (n nothingSelector) Transform(fn TransformFunc) (Selector, error) { return n, nil } 69 70 // Nothing returns a selector that matches no fields 71 func Nothing() Selector { 72 return nothingSelector{} 73 } 74 75 // Everything returns a selector that matches all fields. 76 func Everything() Selector { 77 return andTerm{} 78 } 79 80 type hasTerm struct { 81 field, value string 82 } 83 84 func (t *hasTerm) Matches(ls Fields) bool { 85 return ls.Get(t.field) == t.value 86 } 87 88 func (t *hasTerm) Empty() bool { 89 return false 90 } 91 92 func (t *hasTerm) RequiresExactMatch(field string) (value string, found bool) { 93 if t.field == field { 94 return t.value, true 95 } 96 return "", false 97 } 98 99 func (t *hasTerm) Transform(fn TransformFunc) (Selector, error) { 100 field, value, err := fn(t.field, t.value) 101 if err != nil { 102 return nil, err 103 } 104 if len(field) == 0 && len(value) == 0 { 105 return Everything(), nil 106 } 107 return &hasTerm{field, value}, nil 108 } 109 110 func (t *hasTerm) Requirements() Requirements { 111 return []Requirement{{ 112 Field: t.field, 113 Operator: selection.Equals, 114 Value: t.value, 115 }} 116 } 117 118 func (t *hasTerm) String() string { 119 return fmt.Sprintf("%v=%v", t.field, EscapeValue(t.value)) 120 } 121 122 func (t *hasTerm) DeepCopySelector() Selector { 123 if t == nil { 124 return nil 125 } 126 out := new(hasTerm) 127 *out = *t 128 return out 129 } 130 131 type notHasTerm struct { 132 field, value string 133 } 134 135 func (t *notHasTerm) Matches(ls Fields) bool { 136 return ls.Get(t.field) != t.value 137 } 138 139 func (t *notHasTerm) Empty() bool { 140 return false 141 } 142 143 func (t *notHasTerm) RequiresExactMatch(field string) (value string, found bool) { 144 return "", false 145 } 146 147 func (t *notHasTerm) Transform(fn TransformFunc) (Selector, error) { 148 field, value, err := fn(t.field, t.value) 149 if err != nil { 150 return nil, err 151 } 152 if len(field) == 0 && len(value) == 0 { 153 return Everything(), nil 154 } 155 return ¬HasTerm{field, value}, nil 156 } 157 158 func (t *notHasTerm) Requirements() Requirements { 159 return []Requirement{{ 160 Field: t.field, 161 Operator: selection.NotEquals, 162 Value: t.value, 163 }} 164 } 165 166 func (t *notHasTerm) String() string { 167 return fmt.Sprintf("%v!=%v", t.field, EscapeValue(t.value)) 168 } 169 170 func (t *notHasTerm) DeepCopySelector() Selector { 171 if t == nil { 172 return nil 173 } 174 out := new(notHasTerm) 175 *out = *t 176 return out 177 } 178 179 type andTerm []Selector 180 181 func (t andTerm) Matches(ls Fields) bool { 182 for _, q := range t { 183 if !q.Matches(ls) { 184 return false 185 } 186 } 187 return true 188 } 189 190 func (t andTerm) Empty() bool { 191 if t == nil { 192 return true 193 } 194 if len([]Selector(t)) == 0 { 195 return true 196 } 197 for i := range t { 198 if !t[i].Empty() { 199 return false 200 } 201 } 202 return true 203 } 204 205 func (t andTerm) RequiresExactMatch(field string) (string, bool) { 206 if t == nil || len([]Selector(t)) == 0 { 207 return "", false 208 } 209 for i := range t { 210 if value, found := t[i].RequiresExactMatch(field); found { 211 return value, found 212 } 213 } 214 return "", false 215 } 216 217 func (t andTerm) Transform(fn TransformFunc) (Selector, error) { 218 next := make([]Selector, 0, len([]Selector(t))) 219 for _, s := range []Selector(t) { 220 n, err := s.Transform(fn) 221 if err != nil { 222 return nil, err 223 } 224 if !n.Empty() { 225 next = append(next, n) 226 } 227 } 228 return andTerm(next), nil 229 } 230 231 func (t andTerm) Requirements() Requirements { 232 reqs := make([]Requirement, 0, len(t)) 233 for _, s := range []Selector(t) { 234 rs := s.Requirements() 235 reqs = append(reqs, rs...) 236 } 237 return reqs 238 } 239 240 func (t andTerm) String() string { 241 var terms []string 242 for _, q := range t { 243 terms = append(terms, q.String()) 244 } 245 return strings.Join(terms, ",") 246 } 247 248 func (t andTerm) DeepCopySelector() Selector { 249 if t == nil { 250 return nil 251 } 252 out := make([]Selector, len(t)) 253 for i := range t { 254 out[i] = t[i].DeepCopySelector() 255 } 256 return andTerm(out) 257 } 258 259 // SelectorFromSet returns a Selector which will match exactly the given Set. A 260 // nil Set is considered equivalent to Everything(). 261 func SelectorFromSet(ls Set) Selector { 262 if ls == nil { 263 return Everything() 264 } 265 items := make([]Selector, 0, len(ls)) 266 for field, value := range ls { 267 items = append(items, &hasTerm{field: field, value: value}) 268 } 269 if len(items) == 1 { 270 return items[0] 271 } 272 return andTerm(items) 273 } 274 275 // valueEscaper prefixes \,= characters with a backslash 276 var valueEscaper = strings.NewReplacer( 277 // escape \ characters 278 `\`, `\\`, 279 // then escape , and = characters to allow unambiguous parsing of the value in a fieldSelector 280 `,`, `\,`, 281 `=`, `\=`, 282 ) 283 284 // EscapeValue escapes an arbitrary literal string for use as a fieldSelector value 285 func EscapeValue(s string) string { 286 return valueEscaper.Replace(s) 287 } 288 289 // InvalidEscapeSequence indicates an error occurred unescaping a field selector 290 type InvalidEscapeSequence struct { 291 sequence string 292 } 293 294 func (i InvalidEscapeSequence) Error() string { 295 return fmt.Sprintf("invalid field selector: invalid escape sequence: %s", i.sequence) 296 } 297 298 // UnescapedRune indicates an error occurred unescaping a field selector 299 type UnescapedRune struct { 300 r rune 301 } 302 303 func (i UnescapedRune) Error() string { 304 return fmt.Sprintf("invalid field selector: unescaped character in value: %v", i.r) 305 } 306 307 // UnescapeValue unescapes a fieldSelector value and returns the original literal value. 308 // May return the original string if it contains no escaped or special characters. 309 func UnescapeValue(s string) (string, error) { 310 // if there's no escaping or special characters, just return to avoid allocation 311 if !strings.ContainsAny(s, `\,=`) { 312 return s, nil 313 } 314 315 v := bytes.NewBuffer(make([]byte, 0, len(s))) 316 inSlash := false 317 for _, c := range s { 318 if inSlash { 319 switch c { 320 case '\\', ',', '=': 321 // omit the \ for recognized escape sequences 322 v.WriteRune(c) 323 default: 324 // error on unrecognized escape sequences 325 return "", InvalidEscapeSequence{sequence: string([]rune{'\\', c})} 326 } 327 inSlash = false 328 continue 329 } 330 331 switch c { 332 case '\\': 333 inSlash = true 334 case ',', '=': 335 // unescaped , and = characters are not allowed in field selector values 336 return "", UnescapedRune{r: c} 337 default: 338 v.WriteRune(c) 339 } 340 } 341 342 // Ending with a single backslash is an invalid sequence 343 if inSlash { 344 return "", InvalidEscapeSequence{sequence: "\\"} 345 } 346 347 return v.String(), nil 348 } 349 350 // ParseSelectorOrDie takes a string representing a selector and returns an 351 // object suitable for matching, or panic when an error occur. 352 func ParseSelectorOrDie(s string) Selector { 353 selector, err := ParseSelector(s) 354 if err != nil { 355 panic(err) 356 } 357 return selector 358 } 359 360 // ParseSelector takes a string representing a selector and returns an 361 // object suitable for matching, or an error. 362 func ParseSelector(selector string) (Selector, error) { 363 return parseSelector(selector, 364 func(lhs, rhs string) (newLhs, newRhs string, err error) { 365 return lhs, rhs, nil 366 }) 367 } 368 369 // ParseAndTransformSelector parses the selector and runs them through the given TransformFunc. 370 func ParseAndTransformSelector(selector string, fn TransformFunc) (Selector, error) { 371 return parseSelector(selector, fn) 372 } 373 374 // TransformFunc transforms selectors. 375 type TransformFunc func(field, value string) (newField, newValue string, err error) 376 377 // splitTerms returns the comma-separated terms contained in the given fieldSelector. 378 // Backslash-escaped commas are treated as data instead of delimiters, and are included in the returned terms, with the leading backslash preserved. 379 func splitTerms(fieldSelector string) []string { 380 if len(fieldSelector) == 0 { 381 return nil 382 } 383 384 terms := make([]string, 0, 1) 385 startIndex := 0 386 inSlash := false 387 for i, c := range fieldSelector { 388 switch { 389 case inSlash: 390 inSlash = false 391 case c == '\\': 392 inSlash = true 393 case c == ',': 394 terms = append(terms, fieldSelector[startIndex:i]) 395 startIndex = i + 1 396 } 397 } 398 399 terms = append(terms, fieldSelector[startIndex:]) 400 401 return terms 402 } 403 404 const ( 405 notEqualOperator = "!=" 406 doubleEqualOperator = "==" 407 equalOperator = "=" 408 ) 409 410 // termOperators holds the recognized operators supported in fieldSelectors. 411 // doubleEqualOperator and equal are equivalent, but doubleEqualOperator is checked first 412 // to avoid leaving a leading = character on the rhs value. 413 var termOperators = []string{notEqualOperator, doubleEqualOperator, equalOperator} 414 415 // splitTerm returns the lhs, operator, and rhs parsed from the given term, along with an indicator of whether the parse was successful. 416 // no escaping of special characters is supported in the lhs value, so the first occurrence of a recognized operator is used as the split point. 417 // the literal rhs is returned, and the caller is responsible for applying any desired unescaping. 418 func splitTerm(term string) (lhs, op, rhs string, ok bool) { 419 for i := range term { 420 remaining := term[i:] 421 for _, op := range termOperators { 422 if strings.HasPrefix(remaining, op) { 423 return term[0:i], op, term[i+len(op):], true 424 } 425 } 426 } 427 return "", "", "", false 428 } 429 430 func parseSelector(selector string, fn TransformFunc) (Selector, error) { 431 parts := splitTerms(selector) 432 sort.StringSlice(parts).Sort() 433 var items []Selector 434 for _, part := range parts { 435 if part == "" { 436 continue 437 } 438 lhs, op, rhs, ok := splitTerm(part) 439 if !ok { 440 return nil, fmt.Errorf("invalid selector: '%s'; can't understand '%s'", selector, part) 441 } 442 unescapedRHS, err := UnescapeValue(rhs) 443 if err != nil { 444 return nil, err 445 } 446 switch op { 447 case notEqualOperator: 448 items = append(items, ¬HasTerm{field: lhs, value: unescapedRHS}) 449 case doubleEqualOperator: 450 items = append(items, &hasTerm{field: lhs, value: unescapedRHS}) 451 case equalOperator: 452 items = append(items, &hasTerm{field: lhs, value: unescapedRHS}) 453 default: 454 return nil, fmt.Errorf("invalid selector: '%s'; can't understand '%s'", selector, part) 455 } 456 } 457 if len(items) == 1 { 458 return items[0].Transform(fn) 459 } 460 return andTerm(items).Transform(fn) 461 } 462 463 // OneTermEqualSelector returns an object that matches objects where one field/field equals one value. 464 // Cannot return an error. 465 func OneTermEqualSelector(k, v string) Selector { 466 return &hasTerm{field: k, value: v} 467 } 468 469 // OneTermNotEqualSelector returns an object that matches objects where one field/field does not equal one value. 470 // Cannot return an error. 471 func OneTermNotEqualSelector(k, v string) Selector { 472 return ¬HasTerm{field: k, value: v} 473 } 474 475 // AndSelectors creates a selector that is the logical AND of all the given selectors 476 func AndSelectors(selectors ...Selector) Selector { 477 return andTerm(selectors) 478 }