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 &notHasTerm{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, &notHasTerm{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 &notHasTerm{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  }