From 80b1fa000e1b8df7ca6744aa8385ed61978ab324 Mon Sep 17 00:00:00 2001 From: Meir Fischer Date: Thu, 31 Jul 2014 00:29:42 -0400 Subject: [PATCH] structured message for selector; matching functionality --- pkg/labels/selector.go | 48 +++++++++++++++++++++++++++++++++ pkg/labels/selector_test.go | 54 +++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/pkg/labels/selector.go b/pkg/labels/selector.go index 0845d82305f..65b8e2c3f7a 100644 --- a/pkg/labels/selector.go +++ b/pkg/labels/selector.go @@ -105,6 +105,54 @@ func (t andTerm) String() string { return strings.Join(terms, ",") } +type Comparator int + +const ( + IN Comparator = iota + 1 + NOT_IN +) + +// only not named 'Selector' due to name +// conflict until Selector is deprecated +type LabelSelector struct { + Requirements []Requirement +} + +type Requirement struct { + key string + comparator Comparator + strValues []string +} + +func (r *Requirement) containsStr(value string) bool { + for _, x := range r.strValues { + if value == x { + return true + } + } + return false +} + +func (r *Requirement) Matches(ls Labels) bool { + switch r.comparator { + case IN: + return r.containsStr(ls.Get(r.key)) + case NOT_IN: + return !r.containsStr(ls.Get(r.key)) + default: + return false + } +} + +func (sg *LabelSelector) Matches(ls Labels) bool { + for _, req := range sg.Requirements { + if sat := req.Matches(ls); !sat { + return false + } + } + return true +} + func try(selectorPiece, op string) (lhs, rhs string, ok bool) { pieces := strings.Split(selectorPiece, op) if len(pieces) == 2 { diff --git a/pkg/labels/selector_test.go b/pkg/labels/selector_test.go index 6c5b81296e3..67a9de100f0 100644 --- a/pkg/labels/selector_test.go +++ b/pkg/labels/selector_test.go @@ -163,3 +163,57 @@ func TestSetIsEmpty(t *testing.T) { t.Errorf("Nested andTerm should not be empty") } } + +func expectMatchRequirement(t *testing.T, req Requirement, ls Set) { + if !req.Matches(ls) { + t.Errorf("Wanted '%+v' to match '%s', but it did not.\n", req, ls) + } +} + +func expectNoMatchRequirement(t *testing.T, req Requirement, ls Set) { + if req.Matches(ls) { + t.Errorf("Wanted '%+v' to not match '%s', but it did.", req, ls) + } +} + +func TestRequirementMatches(t *testing.T) { + s := Set{"x": "foo", "y": "baz"} + a := Requirement{key: "x", comparator: IN, strValues: []string{"foo"}} + b := Requirement{key: "x", comparator: NOT_IN, strValues: []string{"beta"}} + c := Requirement{key: "y", comparator: IN, strValues: nil} + d := Requirement{key: "y", strValues: []string{"foo"}} + expectMatchRequirement(t, a, s) + expectMatchRequirement(t, b, s) + expectNoMatchRequirement(t, c, s) + expectNoMatchRequirement(t, d, s) +} + +func expectMatchLabSelector(t *testing.T, lsel LabelSelector, s Set) { + if !lsel.Matches(s) { + t.Errorf("Wanted '%+v' to match '%s', but it did not.\n", lsel, s) + } +} + +func expectNoMatchLabSelector(t *testing.T, lsel LabelSelector, s Set) { + if lsel.Matches(s) { + t.Errorf("Wanted '%+v' to not match '%s', but it did.\n", lsel, s) + } +} + +func TestLabelSelectorMatches(t *testing.T) { + s := Set{"x": "foo", "y": "baz"} + allMatch := LabelSelector{ + Requirements: []Requirement{ + {key: "x", comparator: IN, strValues: []string{"foo"}}, + {key: "y", comparator: NOT_IN, strValues: []string{"alpha"}}, + }, + } + singleNonMatch := LabelSelector{ + Requirements: []Requirement{ + {key: "x", comparator: IN, strValues: []string{"foo"}}, + {key: "y", comparator: IN, strValues: []string{"alpha"}}, + }, + } + expectMatchLabSelector(t, allMatch, s) + expectNoMatchLabSelector(t, singleNonMatch, s) +}