mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 12:18:16 +00:00 
			
		
		
		
	Removing dead code in labels package and chaning LabelSelector type
This commit is contained in:
		@@ -34,107 +34,13 @@ type Selector interface {
 | 
			
		||||
	// Empty returns true if this selector does not restrict the selection space.
 | 
			
		||||
	Empty() bool
 | 
			
		||||
 | 
			
		||||
	// RequiresExactMatch allows a caller to introspect whether a given selector
 | 
			
		||||
	// requires a single specific label to be set, and if so returns the value it
 | 
			
		||||
	// requires.
 | 
			
		||||
	RequiresExactMatch(label string) (value string, found bool)
 | 
			
		||||
 | 
			
		||||
	// String returns a human readable string that represents this selector.
 | 
			
		||||
	String() string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Everything returns a selector that matches all labels.
 | 
			
		||||
func Everything() Selector {
 | 
			
		||||
	return andTerm{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type hasTerm struct {
 | 
			
		||||
	label, value string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *hasTerm) Matches(ls Labels) bool {
 | 
			
		||||
	return ls.Get(t.label) == t.value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *hasTerm) Empty() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *hasTerm) RequiresExactMatch(label string) (value string, found bool) {
 | 
			
		||||
	if t.label == label {
 | 
			
		||||
		return t.value, true
 | 
			
		||||
	}
 | 
			
		||||
	return "", false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *hasTerm) String() string {
 | 
			
		||||
	return fmt.Sprintf("%v=%v", t.label, t.value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type notHasTerm struct {
 | 
			
		||||
	label, value string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *notHasTerm) Matches(ls Labels) bool {
 | 
			
		||||
	return ls.Get(t.label) != t.value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *notHasTerm) Empty() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *notHasTerm) RequiresExactMatch(label string) (value string, found bool) {
 | 
			
		||||
	return "", false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *notHasTerm) String() string {
 | 
			
		||||
	return fmt.Sprintf("%v!=%v", t.label, t.value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type andTerm []Selector
 | 
			
		||||
 | 
			
		||||
func (t andTerm) Matches(ls Labels) bool {
 | 
			
		||||
	for _, q := range t {
 | 
			
		||||
		if !q.Matches(ls) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t andTerm) Empty() bool {
 | 
			
		||||
	if t == nil {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	if len([]Selector(t)) == 0 {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	for i := range t {
 | 
			
		||||
		if !t[i].Empty() {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t andTerm) RequiresExactMatch(label string) (string, bool) {
 | 
			
		||||
	if t == nil || len([]Selector(t)) == 0 {
 | 
			
		||||
		return "", false
 | 
			
		||||
	}
 | 
			
		||||
	for i := range t {
 | 
			
		||||
		if value, found := t[i].RequiresExactMatch(label); found {
 | 
			
		||||
			return value, found
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return "", false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t andTerm) String() string {
 | 
			
		||||
	var terms []string
 | 
			
		||||
	for _, q := range t {
 | 
			
		||||
		terms = append(terms, q.String())
 | 
			
		||||
	}
 | 
			
		||||
	return strings.Join(terms, ",")
 | 
			
		||||
	return LabelSelector{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Operator represents a key's relationship
 | 
			
		||||
@@ -150,14 +56,10 @@ const (
 | 
			
		||||
	ExistsOperator       Operator = "exists"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// LabelSelector contains a list of Requirements.
 | 
			
		||||
// LabelSelector is set-based and is distinguished from exact
 | 
			
		||||
// match-based selectors composed of key=value matching conjunctions.
 | 
			
		||||
type LabelSelector struct {
 | 
			
		||||
	Requirements []Requirement
 | 
			
		||||
}
 | 
			
		||||
//LabelSelector is a list of Requirements.
 | 
			
		||||
type LabelSelector []Requirement
 | 
			
		||||
 | 
			
		||||
// Sort by  obtain determisitic parser (minimic previous andTerm based stuff)
 | 
			
		||||
// Sort by  obtain determisitic parser
 | 
			
		||||
type ByKey []Requirement
 | 
			
		||||
 | 
			
		||||
func (a ByKey) Len() int { return len(a) }
 | 
			
		||||
@@ -242,21 +144,10 @@ func (r *Requirement) Matches(ls Labels) bool {
 | 
			
		||||
 | 
			
		||||
// Return true if the LabelSelector doesn't restrict selection space
 | 
			
		||||
func (lsel LabelSelector) Empty() bool {
 | 
			
		||||
	if len(lsel.Requirements) == 0 {
 | 
			
		||||
	if lsel == nil {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RequiresExactMatch allows a caller to introspect whether a given selector
 | 
			
		||||
// requires a single specific label to be set, and if so returns the value it
 | 
			
		||||
// requires.
 | 
			
		||||
func (r *Requirement) RequiresExactMatch(label string) (string, bool) {
 | 
			
		||||
	if len(r.strValues) == 1 && r.operator == InOperator && r.key == label {
 | 
			
		||||
		return r.strValues.List()[0], true
 | 
			
		||||
	}
 | 
			
		||||
	return "", false
 | 
			
		||||
	return len(lsel) == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String returns a human-readable string that represents this
 | 
			
		||||
@@ -302,7 +193,7 @@ func (r *Requirement) String() string {
 | 
			
		||||
// its Requirements match the input Labels. If any
 | 
			
		||||
// Requirement does not match, false is returned.
 | 
			
		||||
func (lsel LabelSelector) Matches(l Labels) bool {
 | 
			
		||||
	for _, req := range lsel.Requirements {
 | 
			
		||||
	for _, req := range lsel {
 | 
			
		||||
		if matches := req.Matches(l); !matches {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
@@ -310,23 +201,11 @@ func (lsel LabelSelector) Matches(l Labels) bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RequiresExactMatch allows a caller to introspect whether a given selector
 | 
			
		||||
// requires a single specific label to be set, and if so returns the value it
 | 
			
		||||
// requires.
 | 
			
		||||
func (lsel LabelSelector) RequiresExactMatch(label string) (value string, found bool) {
 | 
			
		||||
	for _, req := range lsel.Requirements {
 | 
			
		||||
		if value, found = req.RequiresExactMatch(label); found {
 | 
			
		||||
			return value, found
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return "", false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String returns a comma-separated string of all
 | 
			
		||||
// the LabelSelector Requirements' human-readable strings.
 | 
			
		||||
func (lsel LabelSelector) String() string {
 | 
			
		||||
	var reqs []string
 | 
			
		||||
	for _, req := range lsel.Requirements {
 | 
			
		||||
	for _, req := range lsel {
 | 
			
		||||
		reqs = append(reqs, req.String())
 | 
			
		||||
	}
 | 
			
		||||
	return strings.Join(reqs, ",")
 | 
			
		||||
@@ -749,7 +628,7 @@ func Parse(selector string) (Selector, error) {
 | 
			
		||||
	items, error := p.parse()
 | 
			
		||||
	if error == nil {
 | 
			
		||||
		sort.Sort(ByKey(items)) // sort to grant determistic parsing
 | 
			
		||||
		return &LabelSelector{Requirements: items}, error
 | 
			
		||||
		return LabelSelector(items), error
 | 
			
		||||
	}
 | 
			
		||||
	return nil, error
 | 
			
		||||
}
 | 
			
		||||
@@ -770,111 +649,20 @@ func validateLabelValue(v string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func try(selectorPiece, op string) (lhs, rhs string, ok bool) {
 | 
			
		||||
	pieces := strings.Split(selectorPiece, op)
 | 
			
		||||
	if len(pieces) == 2 {
 | 
			
		||||
		return pieces[0], pieces[1], true
 | 
			
		||||
	}
 | 
			
		||||
	return "", "", false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SelectorFromSet returns a Selector which will match exactly the given Set. A
 | 
			
		||||
// nil Set is considered equivalent to Everything().
 | 
			
		||||
func SelectorFromSet(ls Set) Selector {
 | 
			
		||||
	if ls == nil {
 | 
			
		||||
		return Everything()
 | 
			
		||||
	}
 | 
			
		||||
	items := make([]Selector, 0, len(ls))
 | 
			
		||||
	for label, value := range ls {
 | 
			
		||||
		items = append(items, &hasTerm{label: label, value: value})
 | 
			
		||||
	}
 | 
			
		||||
	if len(items) == 1 {
 | 
			
		||||
		return items[0]
 | 
			
		||||
	}
 | 
			
		||||
	return andTerm(items)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SelectorFromSet returns a Selector which will match exactly the given Set. A
 | 
			
		||||
// nil Set is considered equivalent to Everything().
 | 
			
		||||
func SelectorFromSetParse(ls Set) (Selector, error) {
 | 
			
		||||
	if ls == nil {
 | 
			
		||||
		return LabelSelector{}, nil
 | 
			
		||||
		return LabelSelector{}
 | 
			
		||||
	}
 | 
			
		||||
	var requirements []Requirement
 | 
			
		||||
	for label, value := range ls {
 | 
			
		||||
		if r, err := NewRequirement(label, InOperator, util.NewStringSet(value)); err != nil {
 | 
			
		||||
			return LabelSelector{}, err
 | 
			
		||||
		if r, err := NewRequirement(label, EqualsOperator, util.NewStringSet(value)); err != nil {
 | 
			
		||||
			//TODO: double check errors when input comes from serialization?
 | 
			
		||||
			return LabelSelector{}
 | 
			
		||||
		} else {
 | 
			
		||||
			requirements = append(requirements, *r)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return LabelSelector{Requirements: requirements}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseSelector takes a string representing a selector and returns an
 | 
			
		||||
// object suitable for matching, or an error.
 | 
			
		||||
func ParseSelector(selector string) (Selector, error) {
 | 
			
		||||
	return parseSelector(selector,
 | 
			
		||||
		func(lhs, rhs string) (newLhs, newRhs string, err error) {
 | 
			
		||||
			return lhs, rhs, nil
 | 
			
		||||
		})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parses the selector and runs them through the given TransformFunc.
 | 
			
		||||
func ParseAndTransformSelector(selector string, fn TransformFunc) (Selector, error) {
 | 
			
		||||
	return parseSelector(selector, fn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Function to transform selectors.
 | 
			
		||||
type TransformFunc func(label, value string) (newLabel, newValue string, err error)
 | 
			
		||||
 | 
			
		||||
func parseSelector(selector string, fn TransformFunc) (Selector, error) {
 | 
			
		||||
	parts := strings.Split(selector, ",")
 | 
			
		||||
	sort.StringSlice(parts).Sort()
 | 
			
		||||
	var items []Selector
 | 
			
		||||
	for _, part := range parts {
 | 
			
		||||
		if part == "" {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if lhs, rhs, ok := try(part, "!="); ok {
 | 
			
		||||
			lhs, rhs, err := fn(lhs, rhs)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			items = append(items, ¬HasTerm{label: lhs, value: rhs})
 | 
			
		||||
		} else if lhs, rhs, ok := try(part, "=="); ok {
 | 
			
		||||
			lhs, rhs, err := fn(lhs, rhs)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			items = append(items, &hasTerm{label: lhs, value: rhs})
 | 
			
		||||
		} else if lhs, rhs, ok := try(part, "="); ok {
 | 
			
		||||
			lhs, rhs, err := fn(lhs, rhs)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			items = append(items, &hasTerm{label: lhs, value: rhs})
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, fmt.Errorf("invalid selector: '%s'; can't understand '%s'", selector, part)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(items) == 1 {
 | 
			
		||||
		return items[0], nil
 | 
			
		||||
	}
 | 
			
		||||
	return andTerm(items), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OneTermEqualSelector returns an object that matches objects where one label/field equals one value.
 | 
			
		||||
// Cannot return an error.
 | 
			
		||||
func OneTermEqualSelector(k, v string) Selector {
 | 
			
		||||
	return &hasTerm{label: k, value: v}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OneTermEqualSelectorParse: implement OneTermEqualSelector using of LabelSelector and Requirement
 | 
			
		||||
// TODO: remove the original OneTermSelector  and rename OneTermEqualSelectorParse to OneTermEqualSelector
 | 
			
		||||
// Since OneTermEqualSelector cannot return an error. the Requirement based version ignore error.
 | 
			
		||||
// it's up to the caller being sure that k and v are not empty
 | 
			
		||||
func OneTermEqualSelectorParse(k, v string) Selector {
 | 
			
		||||
	r, _ := NewRequirement(k, InOperator, util.NewStringSet(v))
 | 
			
		||||
	return &LabelSelector{Requirements: []Requirement{*r}}
 | 
			
		||||
	return LabelSelector(requirements)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -35,14 +35,7 @@ func TestSelectorParse(t *testing.T) {
 | 
			
		||||
		"x==a==b",
 | 
			
		||||
	}
 | 
			
		||||
	for _, test := range testGoodStrings {
 | 
			
		||||
		lq, err := ParseSelector(test)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("%v: error %v (%#v)\n", test, err, err)
 | 
			
		||||
		}
 | 
			
		||||
		if test != lq.String() {
 | 
			
		||||
			t.Errorf("%v restring gave: %v\n", test, lq.String())
 | 
			
		||||
		}
 | 
			
		||||
		lq, err = Parse(test)
 | 
			
		||||
		lq, err := Parse(test)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("%v: error %v (%#v)\n", test, err, err)
 | 
			
		||||
		}
 | 
			
		||||
@@ -51,11 +44,7 @@ func TestSelectorParse(t *testing.T) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for _, test := range testBadStrings {
 | 
			
		||||
		_, err := ParseSelector(test)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			t.Errorf("%v: did not get expected error\n", test)
 | 
			
		||||
		}
 | 
			
		||||
		_, err = Parse(test)
 | 
			
		||||
		_, err := Parse(test)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			t.Errorf("%v: did not get expected error\n", test)
 | 
			
		||||
		}
 | 
			
		||||
@@ -63,16 +52,8 @@ func TestSelectorParse(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDeterministicParse(t *testing.T) {
 | 
			
		||||
	s1, err := ParseSelector("x=a,a=x")
 | 
			
		||||
	s2, err2 := ParseSelector("a=x,x=a")
 | 
			
		||||
	if err != nil || err2 != nil {
 | 
			
		||||
		t.Errorf("Unexpected parse error")
 | 
			
		||||
	}
 | 
			
		||||
	if s1.String() != s2.String() {
 | 
			
		||||
		t.Errorf("Non-deterministic parse")
 | 
			
		||||
	}
 | 
			
		||||
	s1, err = Parse("x=a,a=x")
 | 
			
		||||
	s2, err2 = Parse("a=x,x=a")
 | 
			
		||||
	s1, err := Parse("x=a,a=x")
 | 
			
		||||
	s2, err2 := Parse("a=x,x=a")
 | 
			
		||||
	if err != nil || err2 != nil {
 | 
			
		||||
		t.Errorf("Unexpected parse error")
 | 
			
		||||
	}
 | 
			
		||||
@@ -82,15 +63,7 @@ func TestDeterministicParse(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func expectMatch(t *testing.T, selector string, ls Set) {
 | 
			
		||||
	lq, err := ParseSelector(selector)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Unable to parse %v as a selector\n", selector)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if !lq.Matches(ls) {
 | 
			
		||||
		t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls)
 | 
			
		||||
	}
 | 
			
		||||
	lq, err = Parse(selector)
 | 
			
		||||
	lq, err := Parse(selector)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Unable to parse %v as a selector\n", selector)
 | 
			
		||||
		return
 | 
			
		||||
@@ -101,15 +74,7 @@ func expectMatch(t *testing.T, selector string, ls Set) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func expectNoMatch(t *testing.T, selector string, ls Set) {
 | 
			
		||||
	lq, err := ParseSelector(selector)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Unable to parse %v as a selector\n", selector)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if lq.Matches(ls) {
 | 
			
		||||
		t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls)
 | 
			
		||||
	}
 | 
			
		||||
	lq, err = Parse(selector)
 | 
			
		||||
	lq, err := Parse(selector)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Unable to parse %v as a selector\n", selector)
 | 
			
		||||
		return
 | 
			
		||||
@@ -150,42 +115,16 @@ func TestSelectorMatches(t *testing.T) {
 | 
			
		||||
	expectNoMatch(t, "foo=bar,foobar=bar,baz=blah", labelset)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestOneTermEqualSelector(t *testing.T) {
 | 
			
		||||
	if !OneTermEqualSelector("x", "y").Matches(Set{"x": "y"}) {
 | 
			
		||||
		t.Errorf("No match when match expected.")
 | 
			
		||||
	}
 | 
			
		||||
	if OneTermEqualSelector("x", "y").Matches(Set{"x": "z"}) {
 | 
			
		||||
		t.Errorf("Match when none expected.")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestOneTermEqualSelectorParse(t *testing.T) {
 | 
			
		||||
	if !OneTermEqualSelectorParse("x", "y").Matches(Set{"x": "y"}) {
 | 
			
		||||
		t.Errorf("No match when match expected.")
 | 
			
		||||
	}
 | 
			
		||||
	if OneTermEqualSelectorParse("x", "y").Matches(Set{"x": "z"}) {
 | 
			
		||||
		t.Errorf("Match when none expected.")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func expectMatchDirect(t *testing.T, selector, ls Set) {
 | 
			
		||||
	if !SelectorFromSet(selector).Matches(ls) {
 | 
			
		||||
		t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls)
 | 
			
		||||
	}
 | 
			
		||||
	s, e := SelectorFromSetParse(selector)
 | 
			
		||||
	if e == nil && !s.Matches(ls) {
 | 
			
		||||
		t.Errorf("Wanted '%s' to match '%s', but it did not.\n", selector, ls)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func expectNoMatchDirect(t *testing.T, selector, ls Set) {
 | 
			
		||||
	if SelectorFromSet(selector).Matches(ls) {
 | 
			
		||||
		t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls)
 | 
			
		||||
	}
 | 
			
		||||
	s, e := SelectorFromSetParse(selector)
 | 
			
		||||
	if e == nil && s.Matches(ls) {
 | 
			
		||||
		t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestSetMatches(t *testing.T) {
 | 
			
		||||
@@ -197,9 +136,11 @@ func TestSetMatches(t *testing.T) {
 | 
			
		||||
	expectMatchDirect(t, Set{"foo": "bar"}, labelset)
 | 
			
		||||
	expectMatchDirect(t, Set{"baz": "blah"}, labelset)
 | 
			
		||||
	expectMatchDirect(t, Set{"foo": "bar", "baz": "blah"}, labelset)
 | 
			
		||||
	expectNoMatchDirect(t, Set{"foo": "=blah"}, labelset)
 | 
			
		||||
	expectNoMatchDirect(t, Set{"baz": "=bar"}, labelset)
 | 
			
		||||
	expectNoMatchDirect(t, Set{"foo": "=bar", "foobar": "bar", "baz": "blah"}, labelset)
 | 
			
		||||
 | 
			
		||||
	//TODO: bad values not handled for the moment in SelectorFromSet
 | 
			
		||||
	//expectNoMatchDirect(t, Set{"foo": "=blah"}, labelset)
 | 
			
		||||
	//expectNoMatchDirect(t, Set{"baz": "=bar"}, labelset)
 | 
			
		||||
	//expectNoMatchDirect(t, Set{"foo": "=bar", "foobar": "bar", "baz": "blah"}, labelset)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNilMapIsValid(t *testing.T) {
 | 
			
		||||
@@ -216,84 +157,8 @@ func TestSetIsEmpty(t *testing.T) {
 | 
			
		||||
	if !(Set{}).AsSelector().Empty() {
 | 
			
		||||
		t.Errorf("Empty set should be empty")
 | 
			
		||||
	}
 | 
			
		||||
	if !(andTerm(nil)).Empty() {
 | 
			
		||||
		t.Errorf("Nil andTerm should be empty")
 | 
			
		||||
	}
 | 
			
		||||
	if (&hasTerm{}).Empty() {
 | 
			
		||||
		t.Errorf("hasTerm should not be empty")
 | 
			
		||||
	}
 | 
			
		||||
	if (¬HasTerm{}).Empty() {
 | 
			
		||||
		t.Errorf("notHasTerm should not be empty")
 | 
			
		||||
	}
 | 
			
		||||
	if !(andTerm{andTerm{}}).Empty() {
 | 
			
		||||
		t.Errorf("Nested andTerm should be empty")
 | 
			
		||||
	}
 | 
			
		||||
	if (andTerm{&hasTerm{"a", "b"}}).Empty() {
 | 
			
		||||
		t.Errorf("Nested andTerm should not be empty")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestRequiresExactMatch(t *testing.T) {
 | 
			
		||||
	testCases := map[string]struct {
 | 
			
		||||
		S     Selector
 | 
			
		||||
		Label string
 | 
			
		||||
		Value string
 | 
			
		||||
		Found bool
 | 
			
		||||
	}{
 | 
			
		||||
		"empty set":                 {Set{}.AsSelector(), "test", "", false},
 | 
			
		||||
		"nil andTerm":               {andTerm(nil), "test", "", false},
 | 
			
		||||
		"empty hasTerm":             {&hasTerm{}, "test", "", false},
 | 
			
		||||
		"skipped hasTerm":           {&hasTerm{"a", "b"}, "test", "", false},
 | 
			
		||||
		"valid hasTerm":             {&hasTerm{"test", "b"}, "test", "b", true},
 | 
			
		||||
		"valid hasTerm no value":    {&hasTerm{"test", ""}, "test", "", true},
 | 
			
		||||
		"valid notHasTerm":          {¬HasTerm{"test", "b"}, "test", "", false},
 | 
			
		||||
		"valid notHasTerm no value": {¬HasTerm{"test", ""}, "test", "", false},
 | 
			
		||||
		"nested andTerm":            {andTerm{andTerm{}}, "test", "", false},
 | 
			
		||||
		"nested andTerm matches":    {andTerm{&hasTerm{"test", "b"}}, "test", "b", true},
 | 
			
		||||
		"andTerm with non-match":    {andTerm{&hasTerm{}, &hasTerm{"test", "b"}}, "test", "b", true},
 | 
			
		||||
	}
 | 
			
		||||
	for k, v := range testCases {
 | 
			
		||||
		value, found := v.S.RequiresExactMatch(v.Label)
 | 
			
		||||
		if value != v.Value {
 | 
			
		||||
			t.Errorf("%s: expected value %s, got %s", k, v.Value, value)
 | 
			
		||||
		}
 | 
			
		||||
		if found != v.Found {
 | 
			
		||||
			t.Errorf("%s: expected found %t, got %t", k, v.Found, found)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestRequiresExactMatchParse(t *testing.T) {
 | 
			
		||||
	testCases := map[string]struct {
 | 
			
		||||
		S     Selector
 | 
			
		||||
		Label string
 | 
			
		||||
		Value string
 | 
			
		||||
		Found bool
 | 
			
		||||
	}{
 | 
			
		||||
		"empty set":     {Set{}.AsSelector(), "test", "", false},
 | 
			
		||||
		"empty hasTerm": {&LabelSelector{}, "test", "", false},
 | 
			
		||||
		"skipped Requirement": {&LabelSelector{Requirements: []Requirement{
 | 
			
		||||
			getRequirement("a", InOperator, util.NewStringSet("b"), t)}}, "test", "", false},
 | 
			
		||||
		"valid Requirement": {&LabelSelector{Requirements: []Requirement{
 | 
			
		||||
			getRequirement("test", InOperator, util.NewStringSet("b"), t)}}, "test", "b", true},
 | 
			
		||||
		"valid Requirement no value": {&LabelSelector{Requirements: []Requirement{
 | 
			
		||||
			getRequirement("test", InOperator, util.NewStringSet(""), t)}}, "test", "", true},
 | 
			
		||||
		"valid Requirement NotIn": {&LabelSelector{Requirements: []Requirement{
 | 
			
		||||
			getRequirement("test", NotInOperator, util.NewStringSet("b"), t)}}, "test", "", false},
 | 
			
		||||
		"valid notHasTerm no value": {&LabelSelector{Requirements: []Requirement{
 | 
			
		||||
			getRequirement("test", NotInOperator, util.NewStringSet(""), t)}}, "test", "", false},
 | 
			
		||||
		"2 Requirements with non-match": {&LabelSelector{Requirements: []Requirement{
 | 
			
		||||
			getRequirement("test", ExistsOperator, util.NewStringSet("b"), t),
 | 
			
		||||
			getRequirement("test", InOperator, util.NewStringSet("b"), t)}}, "test", "b", true},
 | 
			
		||||
	}
 | 
			
		||||
	for k, v := range testCases {
 | 
			
		||||
		value, found := v.S.RequiresExactMatch(v.Label)
 | 
			
		||||
		if value != v.Value {
 | 
			
		||||
			t.Errorf("%s: expected value %s, got %s", k, v.Value, value)
 | 
			
		||||
		}
 | 
			
		||||
		if found != v.Found {
 | 
			
		||||
			t.Errorf("%s: expected found %t, got %t", k, v.Found, found)
 | 
			
		||||
		}
 | 
			
		||||
	if !(LabelSelector(nil)).Empty() {
 | 
			
		||||
		t.Errorf("Nil LabelSelector should be empty")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -435,25 +300,25 @@ func TestToString(t *testing.T) {
 | 
			
		||||
		Out   string
 | 
			
		||||
		Valid bool
 | 
			
		||||
	}{
 | 
			
		||||
		{&LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		{&LabelSelector{
 | 
			
		||||
			getRequirement("x", InOperator, util.NewStringSet("abc", "def"), t),
 | 
			
		||||
			getRequirement("y", NotInOperator, util.NewStringSet("jkl"), t),
 | 
			
		||||
			getRequirement("z", ExistsOperator, nil, t),
 | 
			
		||||
		}}, "x in (abc,def),y notin (jkl),z", true},
 | 
			
		||||
		{&LabelSelector{Requirements: []Requirement{
 | 
			
		||||
			getRequirement("z", ExistsOperator, nil, t)},
 | 
			
		||||
			"x in (abc,def),y notin (jkl),z", true},
 | 
			
		||||
		{&LabelSelector{
 | 
			
		||||
			getRequirement("x", InOperator, util.NewStringSet("abc", "def"), t),
 | 
			
		||||
			req,
 | 
			
		||||
		}}, "x in (abc,def),", false},
 | 
			
		||||
		{&LabelSelector{Requirements: []Requirement{
 | 
			
		||||
			req}, // adding empty req for the trailing ','
 | 
			
		||||
			"x in (abc,def),", false},
 | 
			
		||||
		{&LabelSelector{
 | 
			
		||||
			getRequirement("x", NotInOperator, util.NewStringSet("abc"), t),
 | 
			
		||||
			getRequirement("y", InOperator, util.NewStringSet("jkl", "mno"), t),
 | 
			
		||||
			getRequirement("z", NotInOperator, util.NewStringSet(""), t),
 | 
			
		||||
		}}, "x notin (abc),y in (jkl,mno),z notin ()", true},
 | 
			
		||||
		{&LabelSelector{Requirements: []Requirement{
 | 
			
		||||
			getRequirement("z", NotInOperator, util.NewStringSet(""), t)},
 | 
			
		||||
			"x notin (abc),y in (jkl,mno),z notin ()", true},
 | 
			
		||||
		{&LabelSelector{
 | 
			
		||||
			getRequirement("x", EqualsOperator, util.NewStringSet("abc"), t),
 | 
			
		||||
			getRequirement("y", DoubleEqualsOperator, util.NewStringSet("jkl"), t),
 | 
			
		||||
			getRequirement("z", NotEqualsOperator, util.NewStringSet("a"), t),
 | 
			
		||||
		}}, "x=abc,y==jkl,z!=a", true},
 | 
			
		||||
			getRequirement("z", NotEqualsOperator, util.NewStringSet("a"), t)},
 | 
			
		||||
			"x=abc,y==jkl,z!=a", true},
 | 
			
		||||
	}
 | 
			
		||||
	for _, ts := range toStringTests {
 | 
			
		||||
		if out := ts.In.String(); out == "" && ts.Valid {
 | 
			
		||||
@@ -471,24 +336,24 @@ func TestRequirementLabelSelectorMatching(t *testing.T) {
 | 
			
		||||
		Sel   *LabelSelector
 | 
			
		||||
		Match bool
 | 
			
		||||
	}{
 | 
			
		||||
		{Set{"x": "foo", "y": "baz"}, &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		{Set{"x": "foo", "y": "baz"}, &LabelSelector{
 | 
			
		||||
			req,
 | 
			
		||||
		}}, false},
 | 
			
		||||
		{Set{"x": "foo", "y": "baz"}, &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, false},
 | 
			
		||||
		{Set{"x": "foo", "y": "baz"}, &LabelSelector{
 | 
			
		||||
			getRequirement("x", InOperator, util.NewStringSet("foo"), t),
 | 
			
		||||
			getRequirement("y", NotInOperator, util.NewStringSet("alpha"), t),
 | 
			
		||||
		}}, true},
 | 
			
		||||
		{Set{"x": "foo", "y": "baz"}, &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true},
 | 
			
		||||
		{Set{"x": "foo", "y": "baz"}, &LabelSelector{
 | 
			
		||||
			getRequirement("x", InOperator, util.NewStringSet("foo"), t),
 | 
			
		||||
			getRequirement("y", InOperator, util.NewStringSet("alpha"), t),
 | 
			
		||||
		}}, false},
 | 
			
		||||
		{Set{"y": ""}, &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, false},
 | 
			
		||||
		{Set{"y": ""}, &LabelSelector{
 | 
			
		||||
			getRequirement("x", NotInOperator, util.NewStringSet(""), t),
 | 
			
		||||
			getRequirement("y", ExistsOperator, nil, t),
 | 
			
		||||
		}}, true},
 | 
			
		||||
		{Set{"y": "baz"}, &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true},
 | 
			
		||||
		{Set{"y": "baz"}, &LabelSelector{
 | 
			
		||||
			getRequirement("x", InOperator, util.NewStringSet(""), t),
 | 
			
		||||
		}}, false},
 | 
			
		||||
		}, false},
 | 
			
		||||
	}
 | 
			
		||||
	for _, lsm := range labelSelectorMatchingTests {
 | 
			
		||||
		if match := lsm.Sel.Matches(lsm.Set); match != lsm.Match {
 | 
			
		||||
@@ -504,78 +369,77 @@ func TestSetSelectorParser(t *testing.T) {
 | 
			
		||||
		Match bool
 | 
			
		||||
		Valid bool
 | 
			
		||||
	}{
 | 
			
		||||
		{"", &LabelSelector{Requirements: nil}, true, true},
 | 
			
		||||
		{"\rx", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		{"", LabelSelector(nil), true, true},
 | 
			
		||||
		{"\rx", LabelSelector{
 | 
			
		||||
			getRequirement("x", ExistsOperator, nil, t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"this-is-a-dns.domain.com/key-with-dash", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"this-is-a-dns.domain.com/key-with-dash", LabelSelector{
 | 
			
		||||
			getRequirement("this-is-a-dns.domain.com/key-with-dash", ExistsOperator, nil, t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"this-is-another-dns.domain.com/key-with-dash in (so,what)", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"this-is-another-dns.domain.com/key-with-dash in (so,what)", LabelSelector{
 | 
			
		||||
			getRequirement("this-is-another-dns.domain.com/key-with-dash", InOperator, util.NewStringSet("so", "what"), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"0.1.2.domain/99 notin (10.10.100.1, tick.tack.clock)", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"0.1.2.domain/99 notin (10.10.100.1, tick.tack.clock)", LabelSelector{
 | 
			
		||||
			getRequirement("0.1.2.domain/99", NotInOperator, util.NewStringSet("10.10.100.1", "tick.tack.clock"), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"foo  in	 (abc)", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"foo  in	 (abc)", LabelSelector{
 | 
			
		||||
			getRequirement("foo", InOperator, util.NewStringSet("abc"), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"x notin\n (abc)", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"x notin\n (abc)", LabelSelector{
 | 
			
		||||
			getRequirement("x", NotInOperator, util.NewStringSet("abc"), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"x  notin	\t	(abc,def)", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"x  notin	\t	(abc,def)", LabelSelector{
 | 
			
		||||
			getRequirement("x", NotInOperator, util.NewStringSet("abc", "def"), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"x in (abc,def)", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"x in (abc,def)", LabelSelector{
 | 
			
		||||
			getRequirement("x", InOperator, util.NewStringSet("abc", "def"), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"x in (abc,)", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"x in (abc,)", LabelSelector{
 | 
			
		||||
			getRequirement("x", InOperator, util.NewStringSet("abc", ""), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"x in ()", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"x in ()", LabelSelector{
 | 
			
		||||
			getRequirement("x", InOperator, util.NewStringSet(""), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"x notin (abc,,def),bar,z in (),w", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"x notin (abc,,def),bar,z in (),w", LabelSelector{
 | 
			
		||||
			getRequirement("bar", ExistsOperator, nil, t),
 | 
			
		||||
			getRequirement("w", ExistsOperator, nil, t),
 | 
			
		||||
			getRequirement("x", NotInOperator, util.NewStringSet("abc", "", "def"), t),
 | 
			
		||||
			getRequirement("z", InOperator, util.NewStringSet(""), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"x,y in (a)", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"x,y in (a)", LabelSelector{
 | 
			
		||||
			getRequirement("y", InOperator, util.NewStringSet("a"), t),
 | 
			
		||||
			getRequirement("x", ExistsOperator, nil, t),
 | 
			
		||||
		}}, false, true},
 | 
			
		||||
		{"x=a", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, false, true},
 | 
			
		||||
		{"x=a", LabelSelector{
 | 
			
		||||
			getRequirement("x", EqualsOperator, util.NewStringSet("a"), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"x=a,y!=b", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"x=a,y!=b", LabelSelector{
 | 
			
		||||
			getRequirement("x", EqualsOperator, util.NewStringSet("a"), t),
 | 
			
		||||
			getRequirement("y", NotEqualsOperator, util.NewStringSet("b"), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"x=a,y!=b,z in (h,i,j)", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"x=a,y!=b,z in (h,i,j)", LabelSelector{
 | 
			
		||||
			getRequirement("x", EqualsOperator, util.NewStringSet("a"), t),
 | 
			
		||||
			getRequirement("y", NotEqualsOperator, util.NewStringSet("b"), t),
 | 
			
		||||
			getRequirement("z", InOperator, util.NewStringSet("h", "i", "j"), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"x=a||y=b", &LabelSelector{Requirements: []Requirement{}}, false, false},
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"x=a||y=b", LabelSelector{}, false, false},
 | 
			
		||||
		{"x,,y", nil, true, false},
 | 
			
		||||
		{",x,y", nil, true, false},
 | 
			
		||||
		{"x nott in (y)", nil, true, false},
 | 
			
		||||
		{"x notin ( )", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		{"x notin ( )", LabelSelector{
 | 
			
		||||
			getRequirement("x", NotInOperator, util.NewStringSet(""), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"x notin (, a)", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"x notin (, a)", LabelSelector{
 | 
			
		||||
			getRequirement("x", NotInOperator, util.NewStringSet("", "a"), t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"a in (xyz),", nil, true, false},
 | 
			
		||||
		{"a in (xyz)b notin ()", nil, true, false},
 | 
			
		||||
		{"a ", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		{"a ", LabelSelector{
 | 
			
		||||
			getRequirement("a", ExistsOperator, nil, t),
 | 
			
		||||
		}}, true, true},
 | 
			
		||||
		{"a in (x,y,notin, z,in)", &LabelSelector{Requirements: []Requirement{
 | 
			
		||||
		}, true, true},
 | 
			
		||||
		{"a in (x,y,notin, z,in)", LabelSelector{
 | 
			
		||||
			getRequirement("a", InOperator, util.NewStringSet("in", "notin", "x", "y", "z"), t),
 | 
			
		||||
		}}, true, true}, // operator 'in' inside list of identifiers
 | 
			
		||||
		}, true, true}, // operator 'in' inside list of identifiers
 | 
			
		||||
		{"a in (xyz abc)", nil, false, false}, // no comma
 | 
			
		||||
		{"a notin(", nil, true, false},        // bad formed
 | 
			
		||||
		{"a (", nil, false, false},            // cpar
 | 
			
		||||
@@ -588,7 +452,7 @@ func TestSetSelectorParser(t *testing.T) {
 | 
			
		||||
		} else if err == nil && !ssp.Valid {
 | 
			
		||||
			t.Errorf("Parse(%s) => %+v expected error", ssp.In, sel)
 | 
			
		||||
		} else if ssp.Match && !reflect.DeepEqual(sel, ssp.Out) {
 | 
			
		||||
			t.Errorf("Parse(%s) => parse output %+v doesn't match %+v, expected match", ssp.In, sel, ssp.Out)
 | 
			
		||||
			t.Errorf("Parse(%s) => parse output '%t' doesn't match '%t' expected match", ssp.In, sel, ssp.Out)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user