From 48d0249a40cd4c539ca13554fa7c0343ee1dbf10 Mon Sep 17 00:00:00 2001 From: Wojciech Tyczynski Date: Fri, 26 May 2017 13:11:51 +0200 Subject: [PATCH] allow for deleting field selector requirements using Transform --- .../apimachinery/pkg/fields/selector.go | 16 ++++- .../apimachinery/pkg/fields/selector_test.go | 70 +++++++++++++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/staging/src/k8s.io/apimachinery/pkg/fields/selector.go b/staging/src/k8s.io/apimachinery/pkg/fields/selector.go index 69014d0e91c..1305dde086c 100644 --- a/staging/src/k8s.io/apimachinery/pkg/fields/selector.go +++ b/staging/src/k8s.io/apimachinery/pkg/fields/selector.go @@ -40,6 +40,8 @@ type Selector interface { // Transform returns a new copy of the selector after TransformFunc has been // applied to the entire selector, or an error if fn returns an error. + // If for a given requirement both field and value are transformed to empty + // string, the requirement is skipped. Transform(fn TransformFunc) (Selector, error) // Requirements converts this interface to Requirements to expose @@ -79,6 +81,9 @@ func (t *hasTerm) Transform(fn TransformFunc) (Selector, error) { if err != nil { return nil, err } + if len(field) == 0 && len(value) == 0 { + return Everything(), nil + } return &hasTerm{field, value}, nil } @@ -115,6 +120,9 @@ func (t *notHasTerm) Transform(fn TransformFunc) (Selector, error) { if err != nil { return nil, err } + if len(field) == 0 && len(value) == 0 { + return Everything(), nil + } return ¬HasTerm{field, value}, nil } @@ -169,13 +177,15 @@ func (t andTerm) RequiresExactMatch(field string) (string, bool) { } func (t andTerm) Transform(fn TransformFunc) (Selector, error) { - next := make([]Selector, len([]Selector(t))) - for i, s := range []Selector(t) { + next := make([]Selector, 0, len([]Selector(t))) + for _, s := range []Selector(t) { n, err := s.Transform(fn) if err != nil { return nil, err } - next[i] = n + if !n.Empty() { + next = append(next, n) + } } return andTerm(next), nil } diff --git a/staging/src/k8s.io/apimachinery/pkg/fields/selector_test.go b/staging/src/k8s.io/apimachinery/pkg/fields/selector_test.go index 458d1574a53..ff6245ca9e1 100644 --- a/staging/src/k8s.io/apimachinery/pkg/fields/selector_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/fields/selector_test.go @@ -325,3 +325,73 @@ func TestRequiresExactMatch(t *testing.T) { } } } + +func TestTransform(t *testing.T) { + testCases := []struct { + name string + selector string + transform func(field, value string) (string, string, error) + result string + isEmpty bool + }{ + { + name: "empty selector", + selector: "", + transform: func(field, value string) (string, string, error) { return field, value, nil }, + result: "", + isEmpty: true, + }, + { + name: "no-op transform", + selector: "a=b,c=d", + transform: func(field, value string) (string, string, error) { return field, value, nil }, + result: "a=b,c=d", + isEmpty: false, + }, + { + name: "transform one field", + selector: "a=b,c=d", + transform: func(field, value string) (string, string, error) { + if field == "a" { + return "e", "f", nil + } + return field, value, nil + }, + result: "e=f,c=d", + isEmpty: false, + }, + { + name: "remove field to make empty", + selector: "a=b", + transform: func(field, value string) (string, string, error) { return "", "", nil }, + result: "", + isEmpty: true, + }, + { + name: "remove only one field", + selector: "a=b,c=d,e=f", + transform: func(field, value string) (string, string, error) { + if field == "c" { + return "", "", nil + } + return field, value, nil + }, + result: "a=b,e=f", + isEmpty: false, + }, + } + + for i, tc := range testCases { + result, err := ParseAndTransformSelector(tc.selector, tc.transform) + if err != nil { + t.Errorf("[%d] unexpected error during Transform: %v", i, err) + } + if result.Empty() != tc.isEmpty { + t.Errorf("[%d] expected empty: %t, got: %t", i, tc.isEmpty, result.Empty) + } + if result.String() != tc.result { + t.Errorf("[%d] unexpected result: %s", i, result.String()) + } + } + +}