diff --git a/pkg/labels/query.go b/pkg/labels/selector.go similarity index 98% rename from pkg/labels/query.go rename to pkg/labels/selector.go index 52e712cb3c..668699ee8a 100644 --- a/pkg/labels/query.go +++ b/pkg/labels/selector.go @@ -18,6 +18,7 @@ package labels import ( "fmt" + "sort" "strings" ) @@ -101,6 +102,7 @@ func SelectorFromSet(ls Set) Selector { // Takes a string repsenting a selector and returns an object suitable for matching, or an error. func ParseSelector(selector string) (Selector, error) { parts := strings.Split(selector, ",") + sort.StringSlice(parts).Sort() var items []Selector for _, part := range parts { if part == "" { diff --git a/pkg/labels/query_test.go b/pkg/labels/selector_test.go similarity index 92% rename from pkg/labels/query_test.go rename to pkg/labels/selector_test.go index 2947e042bf..30d6f26589 100644 --- a/pkg/labels/query_test.go +++ b/pkg/labels/selector_test.go @@ -47,6 +47,17 @@ 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") + } +} + func expectMatch(t *testing.T, selector string, ls Set) { lq, err := ParseSelector(selector) if err != nil {