Extend validation for ReplicationController

Provide type safe checks for empty sets of selectors.
This commit is contained in:
Clayton Coleman
2014-07-25 12:15:17 -04:00
parent fbd71c9c02
commit d32024870a
4 changed files with 146 additions and 2 deletions

View File

@@ -27,6 +27,9 @@ type Selector interface {
// Matches returns true if this selector matches the given set of labels.
Matches(Labels) bool
// Empty returns true if this selector does not restrict the selection space.
Empty() bool
// String returns a human readable string that represents this selector.
String() string
}
@@ -44,6 +47,10 @@ func (t *hasTerm) Matches(ls Labels) bool {
return ls.Get(t.label) == t.value
}
func (t *hasTerm) Empty() bool {
return false
}
func (t *hasTerm) String() string {
return fmt.Sprintf("%v=%v", t.label, t.value)
}
@@ -56,6 +63,10 @@ func (t *notHasTerm) Matches(ls Labels) bool {
return ls.Get(t.label) != t.value
}
func (t *notHasTerm) Empty() bool {
return false
}
func (t *notHasTerm) String() string {
return fmt.Sprintf("%v!=%v", t.label, t.value)
}
@@ -71,6 +82,21 @@ func (t andTerm) Matches(ls Labels) bool {
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) String() string {
var terms []string
for _, q := range t {
@@ -87,8 +113,12 @@ func try(selectorPiece, op string) (lhs, rhs string, ok bool) {
return "", "", false
}
// SelectorFromSet returns a Selector which will match exactly the given Set.
// 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})
@@ -124,3 +154,12 @@ func ParseSelector(selector string) (Selector, error) {
}
return andTerm(items), nil
}
// MustParseSelector parses the selection or panics.
func MustParseSelector(selector string) Selector {
s, err := ParseSelector(selector)
if err != nil {
panic(err)
}
return s
}

View File

@@ -84,6 +84,9 @@ func TestEverything(t *testing.T) {
if !Everything().Matches(Set{"x": "y"}) {
t.Errorf("Nil selector didn't match")
}
if !Everything().Empty() {
t.Errorf("Everything was not empty")
}
}
func TestSelectorMatches(t *testing.T) {
@@ -132,3 +135,31 @@ func TestSetMatches(t *testing.T) {
expectNoMatchDirect(t, Set{"baz": "=bar"}, labelset)
expectNoMatchDirect(t, Set{"foo": "=bar", "foobar": "bar", "baz": "blah"}, labelset)
}
func TestNilMapIsValid(t *testing.T) {
selector := Set(nil).AsSelector()
if selector == nil {
t.Errorf("Selector for nil set should be Everything")
}
if !selector.Empty() {
t.Errorf("Selector for nil set should be Empty")
}
}
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 !(andTerm{andTerm{}}).Empty() {
t.Errorf("Nested andTerm should be empty")
}
if (andTerm{&hasTerm{"a", "b"}}).Empty() {
t.Errorf("Nested andTerm should not be empty")
}
}