From 1c6342a79439c6fbd6e8de464d45b3e5c3fdc2cc Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Mon, 16 Jun 2014 17:57:57 -0700 Subject: [PATCH] Move labels to own package --- pkg/labels/doc.go | 19 ++++++++ pkg/{apiserver => labels}/labelquery.go | 47 +++++++++++--------- pkg/{apiserver => labels}/labelquery_test.go | 12 ++--- 3 files changed, 50 insertions(+), 28 deletions(-) create mode 100644 pkg/labels/doc.go rename pkg/{apiserver => labels}/labelquery.go (79%) rename pkg/{apiserver => labels}/labelquery_test.go (90%) diff --git a/pkg/labels/doc.go b/pkg/labels/doc.go new file mode 100644 index 00000000000..54318e41bb8 --- /dev/null +++ b/pkg/labels/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package labels implements a simple label system, parsing and matching queries +// with sets of labels. +package labels diff --git a/pkg/apiserver/labelquery.go b/pkg/labels/labelquery.go similarity index 79% rename from pkg/apiserver/labelquery.go rename to pkg/labels/labelquery.go index 1c7d174bf24..1cf1c95f5b2 100644 --- a/pkg/apiserver/labelquery.go +++ b/pkg/labels/labelquery.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package apiserver +package labels import ( "fmt" @@ -26,9 +26,11 @@ type Labels interface { Get(label string) (value string) } -// A map of label:value. +// A map of label:value. Implements Labels. type LabelSet map[string]string +// All labels listed as a human readable string. Conveiently, exactly the format +// that ParseQuery takes. func (ls LabelSet) String() string { query := make([]string, 0, len(ls)) for key, value := range ls { @@ -37,12 +39,13 @@ func (ls LabelSet) String() string { return strings.Join(query, ",") } +// Implement Labels interface. func (ls LabelSet) Get(label string) string { return ls[label] } -// Represents a query. -type LabelQuery interface { +// Represents a label query. +type Query interface { // Returns true if this query matches the given set of labels. Matches(Labels) bool @@ -51,7 +54,7 @@ type LabelQuery interface { } // A single term of a label query. -type labelQueryTerm struct { +type queryTerm struct { // Not inverts the meaning of the items in this term. not bool @@ -61,14 +64,14 @@ type labelQueryTerm struct { label, value *string // A list of terms which must all match for this query term to return true. - and []labelQueryTerm + and []queryTerm // A list of terms, any one of which will cause this query term to return true. // Parsing/printing not implemented. - or []labelQueryTerm + or []queryTerm } -func (l *labelQueryTerm) Matches(ls Labels) bool { +func (l *queryTerm) Matches(ls Labels) bool { matches := !l.not switch { case l.label != nil && l.value != nil: @@ -105,19 +108,19 @@ func try(queryPiece, op string) (lhs, rhs string, ok bool) { } // Takes a string repsenting a label query and returns an object suitable for matching, or an error. -func ParseLabelQuery(query string) (LabelQuery, error) { +func ParseQuery(query string) (Query, error) { parts := strings.Split(query, ",") - var items []labelQueryTerm + var items []queryTerm for _, part := range parts { if part == "" { continue } if lhs, rhs, ok := try(part, "!="); ok { - items = append(items, labelQueryTerm{not: true, label: &lhs, value: &rhs}) + items = append(items, queryTerm{not: true, label: &lhs, value: &rhs}) } else if lhs, rhs, ok := try(part, "=="); ok { - items = append(items, labelQueryTerm{label: &lhs, value: &rhs}) + items = append(items, queryTerm{label: &lhs, value: &rhs}) } else if lhs, rhs, ok := try(part, "="); ok { - items = append(items, labelQueryTerm{label: &lhs, value: &rhs}) + items = append(items, queryTerm{label: &lhs, value: &rhs}) } else { return nil, fmt.Errorf("invalid label query: '%s'; can't understand '%s'", query, part) } @@ -125,11 +128,11 @@ func ParseLabelQuery(query string) (LabelQuery, error) { if len(items) == 1 { return &items[0], nil } - return &labelQueryTerm{and: items}, nil + return &queryTerm{and: items}, nil } -// Returns this query as a string in a form that ParseLabelQuery can parse. -func (l *labelQueryTerm) String() (out string) { +// Returns this query as a string in a form that ParseQuery can parse. +func (l *queryTerm) String() (out string) { if len(l.and) > 0 { for _, part := range l.and { if out != "" { @@ -158,7 +161,7 @@ func (p parseErr) Error() string { return fmt.Sprintf("%v: %v", p.Reason, p.Pos) } -func fromLiteral(expr *ast.BinaryExpr) (*labelQueryTerm, error) { +func fromLiteral(expr *ast.BinaryExpr) (*queryTerm, error) { lhs, ok := expr.X.(*ast.Ident) if !ok { return nil, parseErr{"expected literal", expr.X.Pos()} @@ -166,7 +169,7 @@ func fromLiteral(expr *ast.BinaryExpr) (*labelQueryTerm, error) { } -func fromBinaryExpr(expr *ast.BinaryExpr) (*labelQueryTerm, error) { +func fromBinaryExpr(expr *ast.BinaryExpr) (*queryTerm, error) { switch expr.Op { case token.EQL, token.NEQ: return fromLiteral(expr) @@ -181,13 +184,13 @@ func fromBinaryExpr(expr *ast.BinaryExpr) (*labelQueryTerm, error) { } switch expr.Op { case token.AND, token.LAND: - return &labelQueryTerm{And: []LabelQuery{lhs, rhs}} + return &queryTerm{And: []LabelQuery{lhs, rhs}} case token.OR, token.LOR: - return &labelQueryTerm{Or: []LabelQuery{lhs, rhs}} + return &queryTerm{Or: []LabelQuery{lhs, rhs}} } } -func fromUnaryExpr(expr *ast.UnaryExpr) (*labelQueryTerm, error) { +func fromUnaryExpr(expr *ast.UnaryExpr) (*queryTerm, error) { if expr.Op == token.NOT { lqt, err := fromExpr(expr.X) if err != nil { @@ -199,7 +202,7 @@ func fromUnaryExpr(expr *ast.UnaryExpr) (*labelQueryTerm, error) { return nil, parseErr{"unrecognized unary expression", expr.OpPos} } -func fromExpr(expr ast.Expr) (*labelQueryTerm, error) { +func fromExpr(expr ast.Expr) (*queryTerm, error) { switch v := expr.(type) { case *ast.UnaryExpr: return fromUnaryExpr(v) diff --git a/pkg/apiserver/labelquery_test.go b/pkg/labels/labelquery_test.go similarity index 90% rename from pkg/apiserver/labelquery_test.go rename to pkg/labels/labelquery_test.go index acc3964ee78..f0f3f83fd4f 100644 --- a/pkg/apiserver/labelquery_test.go +++ b/pkg/labels/labelquery_test.go @@ -14,13 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -package apiserver +package labels import ( "testing" ) -func TestLabelQueryParse(t *testing.T) { +func TestQueryParse(t *testing.T) { testGoodStrings := []string{ "x=a,y=b,z=c", "", @@ -31,7 +31,7 @@ func TestLabelQueryParse(t *testing.T) { "x==a==b", } for _, test := range testGoodStrings { - lq, err := ParseLabelQuery(test) + lq, err := ParseQuery(test) if err != nil { t.Errorf("%v: error %v (%#v)\n", test, err, err) } @@ -40,7 +40,7 @@ func TestLabelQueryParse(t *testing.T) { } } for _, test := range testBadStrings { - _, err := ParseLabelQuery(test) + _, err := ParseQuery(test) if err == nil { t.Errorf("%v: did not get expected error\n", test) } @@ -48,7 +48,7 @@ func TestLabelQueryParse(t *testing.T) { } func shouldMatch(t *testing.T, query string, ls LabelSet) { - lq, err := ParseLabelQuery(query) + lq, err := ParseQuery(query) if err != nil { t.Errorf("Unable to parse %v as a query\n", query) return @@ -59,7 +59,7 @@ func shouldMatch(t *testing.T, query string, ls LabelSet) { } func shouldNotMatch(t *testing.T, query string, ls LabelSet) { - lq, err := ParseLabelQuery(query) + lq, err := ParseQuery(query) if err != nil { t.Errorf("Unable to parse %v as a query\n", query) return