Merge pull request #362 from apelisse/rename-value-to-interface

selectors: Remove "Map" and "Slice"
This commit is contained in:
k8s-ci-robot 2018-03-20 15:40:01 -07:00 committed by GitHub
commit 11a04e5d8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 447 additions and 547 deletions

View File

@ -19,7 +19,7 @@ package predicates_test
import (
"testing"
. "k8s.io/kubectl/pkg/framework/predicates"
. "k8s.io/kubectl/pkg/framework/path/predicates"
)
type InterfaceTrue struct{}

View File

@ -19,7 +19,7 @@ package predicates_test
import (
"testing"
. "k8s.io/kubectl/pkg/framework/predicates"
. "k8s.io/kubectl/pkg/framework/path/predicates"
)
type MapTrue struct{}

View File

@ -20,7 +20,7 @@ import (
"fmt"
"testing"
. "k8s.io/kubectl/pkg/framework/predicates"
. "k8s.io/kubectl/pkg/framework/path/predicates"
)
// This example shows you how you can create a IntP, and how it's use to

View File

@ -19,7 +19,7 @@ package predicates_test
import (
"testing"
. "k8s.io/kubectl/pkg/framework/predicates"
. "k8s.io/kubectl/pkg/framework/path/predicates"
)
type SliceTrue struct{}

View File

@ -20,7 +20,7 @@ import (
"regexp"
"testing"
. "k8s.io/kubectl/pkg/framework/predicates"
. "k8s.io/kubectl/pkg/framework/path/predicates"
)
func TestStringEqual(t *testing.T) {

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// This package helps you find specific fields in your unstruct
// This package helps you find specific fields in your interface{}
// object. It is similar to what you can do with jsonpath, but reads the
// path from strongly typed object, not strings.
package unstructpath
package selectors

View File

@ -14,12 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package unstructpath
package selectors
import (
"github.com/ghodss/yaml"
p "k8s.io/kubectl/pkg/framework/predicates"
p "k8s.io/kubectl/pkg/framework/path/predicates"
)
// This example is inspired from http://goessner.net/articles/JsonPath/#e3.
@ -61,31 +61,31 @@ func Example() {
}
// The authors of all books in the store. Returns a list of strings.
Children().Map().Field("book").Children().Map().Field("author").String().SelectFrom(u)
Children().Field("book").Children().Field("author").AsString().SelectFrom(u)
// All authors. Returns a list of strings.
All().Map().Field("author").String().SelectFrom(u)
All().Field("author").AsString().SelectFrom(u)
// All things in store, which are some books and a red bicycle. Returns a list of interface{}.
Map().Field("store").Children().SelectFrom(u)
// All things in store, which are some books and a red bicycle. Returns a list of maps.
Field("store").Children().AsMap().SelectFrom(u)
// The price of everything in the store. Returns a list of "float64".
Map().Field("store").All().Map().Field("price").Number().SelectFrom(u)
Field("store").All().Field("price").AsNumber().SelectFrom(u)
// The third book. Returns a list of 1 interface{}.
All().Map().Field("book").Slice().At(2).SelectFrom(u)
All().Field("book").At(2).SelectFrom(u)
// The last book in order. Return a list of 1 interface{}.
All().Map().Field("book").Slice().Last().SelectFrom(u)
All().Field("book").Last().SelectFrom(u)
// The first two books. Returns a list of 2 interface{}.
All().Map().Field("book").Slice().AtP(p.NumberLessThan(2)).SelectFrom(u)
All().Field("book").AtP(p.NumberLessThan(2)).SelectFrom(u)
// Filter all books with isbn number. Returns a list of interface{}.
All().Map().Field("book").Filter(Map().Field("isbn")).SelectFrom(u)
All().Field("book").Filter(Field("isbn")).SelectFrom(u)
// Filter all books cheaper than 10. Returns a list of interface{}.
All().Map().Field("book").Children().Filter(Map().Field("price").Number().Filter(p.NumberLessThan(10))).SelectFrom(u)
All().Field("book").Children().Filter(Field("price").AsNumber().Filter(p.NumberLessThan(10))).SelectFrom(u)
// All elements in structure. Returns a list of interface{}.
All().SelectFrom(u)

View File

@ -0,0 +1,197 @@
/*
Copyright 2018 The Kubernetes Authors.
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 selectors
import (
p "k8s.io/kubectl/pkg/framework/path/predicates"
)
// Interface is a "interface selector". It filters interfaces based on the
// "filtered" predicates.
type Interface interface {
// Interface can be used as a Interface predicate. If the selector can't
// select any interface from the interface, then the predicate is
// false.
p.Interface
// SelectFrom finds interfaces from interfaces using this selector. The
// list can be bigger or smaller than the initial lists,
// depending on the select criterias.
SelectFrom(...interface{}) []interface{}
// AsMap returns a selector that selects Maps from the given
// values.
AsMap() Map
// AsSlice returns a selector that selects Slices from the given
// values.
AsSlice() Slice
// Number returns a selector taht selects Numbers from the given values.
AsNumber() Number
// String returns a selector that selects strings from the given values.
AsString() String
// Field returns the interface pointed by this specific field in the
// map. If the field doesn't exist, the value will be filtered
// out.
Field(string) Interface
// FieldP returns all the interfaces pointed by field that match the
// string predicate. This selector can return more values than
// it gets (for one map, it can returns multiple sub-values, one
// for each field that matches the predicate).
FieldP(...p.String) Interface
// At returns a selector that select the child at the given
// index, if the list has such an index. Otherwise, nothing is
// returned.
At(index int) Interface
// AtP returns a selector that selects all the item whose index
// matches the number predicate. More predicates can be given,
// they are "and"-ed by this method.
AtP(ips ...p.Number) Interface
// Last returns a selector that selects the last value of the
// list. If the list is empty, then nothing will be selected.
Last() Interface
// Children returns a selector that selects the direct children
// of the given values.
Children() Interface
// All returns a selector that selects all direct and indrect
// children of the given values.
All() Interface
// Filter will create a new String that filters only the values
// who match the predicate.
Filter(...p.Interface) Interface
}
// Field returns the interface pointed by this specific field in the
// map. If the field doesn't exist, the value will be filtered
// out.
func Field(field string) Interface {
return FieldP(p.StringEqual(field))
}
// FieldP returns all the interfaces pointed by field that match the
// string predicate. This selector can return more values than
// it gets (for one map, it can returns multiple sub-values, one
// for each field that matches the predicate).
func FieldP(predicates ...p.String) Interface {
return &interfaceS{vf: interfaceFieldPFilter{sp: p.StringAnd(predicates...)}}
}
// At returns a selector that select the child at the given
// index, if the list has such an index. Otherwise, nothing is
// returned.
func At(index int) Interface {
return AtP(p.NumberEqual(float64(index)))
}
// AtP returns a selector that selects all the item whose index
// matches the number predicate. More predicates can be given,
// they are "and"-ed by this method.
func AtP(ips ...p.Number) Interface {
return &interfaceS{vf: interfaceAtPFilter{ip: p.NumberAnd(ips...)}}
}
// Last returns a selector that selects the last value of the
// list. If the list is empty, then nothing will be selected.
func Last() Interface {
return &interfaceS{vf: interfaceLastFilter{}}
}
// Children selects all the children of the values.
func Children() Interface {
return &interfaceS{vf: interfaceChildrenFilter{}}
}
// All selects all the direct and indirect childrens of the values.
func All() Interface {
return &interfaceS{vf: interfaceAllFilter{}}
}
// Filter will only return the values that match the predicate.
func Filter(predicates ...p.Interface) Interface {
return &interfaceS{vf: &interfaceFilterP{vp: p.InterfaceAnd(predicates...)}}
}
// Interface is a "Interface Selector". It selects a list of values, maps,
// slices, strings, integer from a list of values.
type interfaceS struct {
vs Interface
vf interfaceFilter
}
// Match returns true if the selector can find items in the given
// value. Otherwise, it returns false.
func (s *interfaceS) Match(value interface{}) bool {
return len(s.SelectFrom(value)) != 0
}
func (s *interfaceS) SelectFrom(interfaces ...interface{}) []interface{} {
if s.vs != nil {
interfaces = s.vs.SelectFrom(interfaces...)
}
return s.vf.SelectFrom(interfaces...)
}
func (s *interfaceS) AsMap() Map {
return &mapS{vs: s}
}
func (s *interfaceS) AsSlice() Slice {
return &sliceS{vs: s}
}
func (s *interfaceS) AsNumber() Number {
return &numberS{vs: s}
}
func (s *interfaceS) AsString() String {
return &stringS{vs: s}
}
func (s *interfaceS) At(index int) Interface {
return s.AtP(p.NumberEqual(float64(index)))
}
func (s *interfaceS) AtP(predicates ...p.Number) Interface {
return &interfaceS{vs: s, vf: interfaceAtPFilter{ip: p.NumberAnd(predicates...)}}
}
func (s *interfaceS) Last() Interface {
return &interfaceS{vs: s, vf: interfaceLastFilter{}}
}
func (s *interfaceS) Field(key string) Interface {
return s.FieldP(p.StringEqual(key))
}
func (s *interfaceS) FieldP(predicates ...p.String) Interface {
return &interfaceS{vs: s, vf: interfaceFieldPFilter{sp: p.StringAnd(predicates...)}}
}
func (s *interfaceS) Children() Interface {
return &interfaceS{vs: s, vf: interfaceChildrenFilter{}}
}
func (s *interfaceS) All() Interface {
return &interfaceS{vs: s, vf: interfaceAllFilter{}}
}
func (s *interfaceS) Filter(predicates ...p.Interface) Interface {
return &interfaceS{vs: s, vf: &interfaceFilterP{vp: p.InterfaceAnd(predicates...)}}
}

View File

@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package unstructpath_test
package selectors_test
import (
"reflect"
"testing"
"k8s.io/kubectl/pkg/framework/unstructpath"
"k8s.io/kubectl/pkg/framework/path/selectors"
)
func TestAll(t *testing.T) {
@ -30,7 +30,7 @@ func TestAll(t *testing.T) {
"key4": map[string]interface{}{"key5": 5.},
}
numbers := unstructpath.All().Number().SelectFrom(u)
numbers := selectors.All().AsNumber().SelectFrom(u)
expected := []float64{1., 2., 3., 4., 5.}
if !reflect.DeepEqual(expected, numbers) {
t.Fatalf("Expected to find all numbers (%v), got: %v", expected, numbers)
@ -44,7 +44,7 @@ func TestChildren(t *testing.T) {
"key4": 5.,
}
numbers := unstructpath.Children().Number().SelectFrom(u)
numbers := selectors.Children().AsNumber().SelectFrom(u)
expected := []float64{1., 5.}
if !reflect.DeepEqual(expected, numbers) {
t.Fatalf("Expected to find all numbers (%v), got: %v", expected, numbers)
@ -60,19 +60,19 @@ func TestFilter(t *testing.T) {
"string",
}
expected := []interface{}{us[1]}
actual := unstructpath.Filter(unstructpath.Slice().At(3)).SelectFrom(us...)
actual := selectors.Filter(selectors.At(3)).SelectFrom(us...)
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected to filter (%v), got: %v", expected, actual)
}
}
func TestInterfaceSPredicate(t *testing.T) {
if !unstructpath.Slice().Match([]interface{}{}) {
func TestInterfacePredicate(t *testing.T) {
if !selectors.AsSlice().Match([]interface{}{}) {
t.Fatal("SelectFroming a slice from a slice should match.")
}
}
func TestInterfaceSMap(t *testing.T) {
func TestInterfaceMap(t *testing.T) {
root := map[string]interface{}{
"key1": "value",
"key2": 1,
@ -92,13 +92,13 @@ func TestInterfaceSMap(t *testing.T) {
root,
root["key4"].(map[string]interface{}),
}
actual := unstructpath.All().Map().SelectFrom(root)
actual := selectors.All().AsMap().SelectFrom(root)
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Map should find maps %v, got %v", expected, actual)
t.Fatalf("AsMap should find maps %v, got %v", expected, actual)
}
}
func TestInterfaceSSlice(t *testing.T) {
func TestInterfaceSlice(t *testing.T) {
root := map[string]interface{}{
"key1": "value",
"key2": 1,
@ -118,13 +118,13 @@ func TestInterfaceSSlice(t *testing.T) {
root["key3"].([]interface{}),
root["key4"].(map[string]interface{})["subkey"].([]interface{}),
}
actual := unstructpath.All().Slice().SelectFrom(root)
actual := selectors.All().AsSlice().SelectFrom(root)
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Slice should find slices %#v, got %#v", expected, actual)
}
}
func TestInterfaceSChildren(t *testing.T) {
func TestInterfaceChildren(t *testing.T) {
root := map[string]interface{}{
"key1": "value",
"key2": 1,
@ -144,24 +144,24 @@ func TestInterfaceSChildren(t *testing.T) {
root["key3"].([]interface{})[0],
root["key3"].([]interface{})[1],
}
actual := unstructpath.Map().Field("key3").Children().SelectFrom(root)
actual := selectors.Field("key3").Children().SelectFrom(root)
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected %v, got %v", expected, actual)
}
}
func TestInterfaceSNumber(t *testing.T) {
func TestInterfaceNumber(t *testing.T) {
u := []interface{}{1., 2., "three", 4., 5., []interface{}{}}
numbers := unstructpath.Children().Number().SelectFrom(u)
numbers := selectors.Children().AsNumber().SelectFrom(u)
expected := []float64{1., 2., 4., 5.}
if !reflect.DeepEqual(expected, numbers) {
t.Fatalf("Children().Number() should select %v, got %v", expected, numbers)
t.Fatalf("Children().AsNumber() should select %v, got %v", expected, numbers)
}
}
func TestInterfaceSString(t *testing.T) {
func TestInterfaceString(t *testing.T) {
root := map[string]interface{}{
"key1": "value",
"key2": 1,
@ -182,13 +182,13 @@ func TestInterfaceSString(t *testing.T) {
"other value",
"string",
}
actual := unstructpath.All().String().SelectFrom(root)
actual := selectors.All().AsString().SelectFrom(root)
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected %v, got %v", expected, actual)
}
}
func TestInterfaceSAll(t *testing.T) {
func TestInterfaceAll(t *testing.T) {
root := map[string]interface{}{
"key1": "value",
"key2": 1,
@ -211,7 +211,7 @@ func TestInterfaceSAll(t *testing.T) {
root["key4"].(map[string]interface{})["subkey"].([]interface{})[1],
}
actual := unstructpath.Map().Field("key4").All().SelectFrom(root)
actual := selectors.Field("key4").All().SelectFrom(root)
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected %v, got %v", expected, actual)
}

View File

@ -0,0 +1,142 @@
/*
Copyright 2018 The Kubernetes Authors.
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 selectors
import (
"sort"
p "k8s.io/kubectl/pkg/framework/path/predicates"
)
// A interfaceFilter allows us to chain Interface to Interface. None of this is
// public. It's implementing the "SelectFrom" part of a Interface.
type interfaceFilter interface {
SelectFrom(...interface{}) []interface{}
}
// interfaceFilterP filters using a predicate.
type interfaceFilterP struct {
vp p.Interface
}
func (f *interfaceFilterP) SelectFrom(interfaces ...interface{}) []interface{} {
vs := []interface{}{}
for _, value := range interfaces {
if f.vp.Match(value) {
vs = append(vs, value)
}
}
return vs
}
type interfaceChildrenFilter struct{}
func (interfaceChildrenFilter) SelectFrom(interfaces ...interface{}) []interface{} {
children := []interface{}{}
// We could process all slices and then all maps, but we want to
// keep things in the same order.
for _, value := range interfaces {
// Only one of the two should do something useful.
// AtP() with nothing selects all the children of a list
children = append(children, AtP().SelectFrom(value)...)
// FieldP() with nothing selects all the children of a map
children = append(children, FieldP().SelectFrom(value)...)
}
return children
}
type interfaceAtPFilter struct {
ip p.Number
}
func (f interfaceAtPFilter) SelectFrom(values ...interface{}) []interface{} {
interfaces := []interface{}{}
for _, value := range values {
slice, ok := value.([]interface{})
if !ok {
continue
}
for i := range slice {
if !f.ip.Match(float64(i)) {
continue
}
interfaces = append(interfaces, slice[i])
}
}
return interfaces
}
type interfaceLastFilter struct{}
func (f interfaceLastFilter) SelectFrom(values ...interface{}) []interface{} {
interfaces := []interface{}{}
for _, value := range values {
slice, ok := value.([]interface{})
if !ok {
continue
}
if len(slice) == 0 {
continue
}
interfaces = append(interfaces, slice[len(slice)-1])
}
return interfaces
}
type interfaceFieldPFilter struct {
sp p.String
}
func (f interfaceFieldPFilter) SelectFrom(values ...interface{}) []interface{} {
interfaces := []interface{}{}
for _, value := range values {
m, ok := value.(map[string]interface{})
if !ok {
continue
}
for _, field := range sortedKeys(m) {
if !f.sp.Match(field) {
continue
}
interfaces = append(interfaces, m[field])
}
}
return interfaces
}
func sortedKeys(m map[string]interface{}) []string {
keys := []string{}
for key := range m {
keys = append(keys, key)
}
sort.Strings(keys)
return keys
}
type interfaceAllFilter struct{}
func (interfaceAllFilter) SelectFrom(interfaces ...interface{}) []interface{} {
vs := []interface{}{}
for _, value := range interfaces {
vs = append(vs, value)
vs = append(vs, Children().All().SelectFrom(value)...)
}
return vs
}

View File

@ -14,17 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package unstructpath
package selectors
import (
p "k8s.io/kubectl/pkg/framework/predicates"
p "k8s.io/kubectl/pkg/framework/path/predicates"
)
// MapS is a "map selector". It selects interfaces as maps (if
// Map is a "map selector". It selects interfaces as maps (if
// possible) and filters those maps based on the "filtered"
// predicates.
type MapS interface {
// MapS can be used as a Interface predicate. If the selector can't
type Map interface {
// Map can be used as a Interface predicate. If the selector can't
// select any map from the interface, then the predicate is
// false.
p.Interface
@ -34,36 +34,19 @@ type MapS interface {
// depending on the select criterias.
SelectFrom(...interface{}) []map[string]interface{}
// Field returns the interface pointed by this specific field in the
// map. If the field doesn't exist, the value will be filtered
// out.
Field(string) InterfaceS
// FieldP returns all the interfaces pointed by field that match the
// string predicate. This selector can return more values than
// it gets (for one map, it can returns multiple sub-values, one
// for each field that matches the predicate).
FieldP(...p.String) InterfaceS
// All returns a selector that selects all direct and indrect
// children of the given values.
Children() InterfaceS
// All returns a selector that selects all direct and indrect
// children of the given values.
All() InterfaceS
// Filter will create a new MapS that filters only the values
// Filter will create a new Map that filters only the values
// who match the predicate.
Filter(...p.Map) MapS
Filter(...p.Map) Map
}
// Map creates a selector that takes interfaces and filters them into maps
// if possible.
func Map() MapS {
func AsMap() Map {
return &mapS{}
}
type mapS struct {
vs InterfaceS
vs Interface
mp p.Map
}
@ -87,24 +70,7 @@ func (s *mapS) SelectFrom(interfaces ...interface{}) []map[string]interface{} {
return maps
}
func (s *mapS) Field(str string) InterfaceS {
return s.FieldP(p.StringEqual(str))
}
func (s *mapS) FieldP(predicates ...p.String) InterfaceS {
return filterMap(s, mapFieldPFilter{sp: p.StringAnd(predicates...)})
}
func (s *mapS) Children() InterfaceS {
// No predicate means select all.
return s.FieldP()
}
func (s *mapS) All() InterfaceS {
return filterMap(s, mapAllFilter{})
}
func (s *mapS) Filter(predicates ...p.Map) MapS {
func (s *mapS) Filter(predicates ...p.Map) Map {
return &mapS{vs: s.vs, mp: p.MapAnd(append(predicates, s.mp)...)}
}

View File

@ -14,17 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package unstructpath
package selectors
import (
p "k8s.io/kubectl/pkg/framework/predicates"
p "k8s.io/kubectl/pkg/framework/path/predicates"
)
// NumberS is a "number selector". It selects values as numbers (if
// Number is a "number selector". It selects values as numbers (if
// possible) and filters those numbers based on the "filtered"
// predicates.
type NumberS interface {
// NumberS can be used as a Interface predicate. If the selector can't
type Number interface {
// Number can be used as a Interface predicate. If the selector can't
// select any number from the value, then the predicate is
// false.
p.Interface
@ -34,18 +34,18 @@ type NumberS interface {
// depending on the select criterias.
SelectFrom(...interface{}) []float64
// Filter will create a new NumberS that filters only the values
// Filter will create a new Number that filters only the values
// who match the predicate.
Filter(...p.Number) NumberS
Filter(...p.Number) Number
}
// Number returns a NumberS that selects numbers from given values.
func Number() NumberS {
// AsNumber returns a Number that selects numbers from given values.
func AsNumber() Number {
return &numberS{}
}
type numberS struct {
vs InterfaceS
vs Interface
ip p.Number
}
@ -67,7 +67,7 @@ func (s *numberS) SelectFrom(values ...interface{}) []float64 {
return numbers
}
func (s *numberS) Filter(predicates ...p.Number) NumberS {
func (s *numberS) Filter(predicates ...p.Number) Number {
if s.ip != nil {
predicates = append(predicates, s.ip)
}

View File

@ -14,18 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package unstructpath_test
package selectors_test
import (
"reflect"
"testing"
p "k8s.io/kubectl/pkg/framework/predicates"
. "k8s.io/kubectl/pkg/framework/unstructpath"
p "k8s.io/kubectl/pkg/framework/path/predicates"
. "k8s.io/kubectl/pkg/framework/path/selectors"
)
func TestNumberSSelectFrom(t *testing.T) {
s := Number().SelectFrom(
func TestNumberSelectFrom(t *testing.T) {
s := AsNumber().SelectFrom(
1.,
"string",
2.,
@ -36,8 +36,8 @@ func TestNumberSSelectFrom(t *testing.T) {
}
}
func TestNumberSFilter(t *testing.T) {
s := Number().
func TestNumberFilter(t *testing.T) {
s := AsNumber().
Filter(p.NumberGreaterThan(2), p.NumberEqualOrLessThan(4)).
SelectFrom(
1.,
@ -51,20 +51,20 @@ func TestNumberSFilter(t *testing.T) {
}
}
func TestNumberSPredicate(t *testing.T) {
if !Number().Filter(p.NumberGreaterThan(10)).Match(12.) {
func TestNumberPredicate(t *testing.T) {
if !AsNumber().Filter(p.NumberGreaterThan(10)).Match(12.) {
t.Fatal("SelectFromor matching element should match")
}
if Number().Filter(p.NumberGreaterThan(10)).Match(4.) {
if AsNumber().Filter(p.NumberGreaterThan(10)).Match(4.) {
t.Fatal("SelectFromor not matching element should not match")
}
}
func TestNumberSFromInterfaceS(t *testing.T) {
if !Children().Number().Filter(p.NumberGreaterThan(10)).Match([]interface{}{1., 2., 5., 12.}) {
func TestNumberFromInterface(t *testing.T) {
if !Children().AsNumber().Filter(p.NumberGreaterThan(10)).Match([]interface{}{1., 2., 5., 12.}) {
t.Fatal("SelectFromor should find element that match")
}
if Children().Number().Filter(p.NumberGreaterThan(10)).Match([]interface{}{1., 2., 5.}) {
if Children().AsNumber().Filter(p.NumberGreaterThan(10)).Match([]interface{}{1., 2., 5.}) {
t.Fatal("SelectFromor shouldn't find element that match")
}
}

View File

@ -14,17 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package unstructpath
package selectors
import (
p "k8s.io/kubectl/pkg/framework/predicates"
p "k8s.io/kubectl/pkg/framework/path/predicates"
)
// SliceS is a "slice selector". It selects values as slices (if
// Slice is a "slice selector". It selects values as slices (if
// possible) and filters those slices based on the "filtered"
// predicates.
type SliceS interface {
// SliceS can be used as a Interface predicate. If the selector
type Slice interface {
// Slice can be used as a Interface predicate. If the selector
// can't select any slice from the value, then the predicate is
// false.
p.Interface
@ -34,38 +34,19 @@ type SliceS interface {
// depending on the select criterias.
SelectFrom(...interface{}) [][]interface{}
// At returns a selector that select the child at the given
// index, if the list has such an index. Otherwise, nothing is
// returned.
At(index int) InterfaceS
// AtP returns a selector that selects all the item whose index
// matches the number predicate. More predicates can be given,
// they are "and"-ed by this method.
AtP(ips ...p.Number) InterfaceS
// Last returns a selector that selects the last value of the
// list. If the list is empty, then nothing will be selected.
Last() InterfaceS
// All returns a selector that selects all direct and indrect
// children of the given values.
Children() InterfaceS
// All returns a selector that selects all direct and indrect
// children of the given values.
All() InterfaceS
// Filter will create a new SliceS that filters only the values
// Filter will create a new Slice that filters only the values
// who match the predicate.
Filter(...p.Slice) SliceS
Filter(...p.Slice) Slice
}
// Slice creates a selector that takes values and filters them into
// slices if possible.
func Slice() SliceS {
func AsSlice() Slice {
return &sliceS{}
}
type sliceS struct {
vs InterfaceS
vs Interface
sp p.Slice
}
@ -89,28 +70,7 @@ func (s *sliceS) SelectFrom(interfaces ...interface{}) [][]interface{} {
return slices
}
func (s *sliceS) At(index int) InterfaceS {
return s.AtP(p.NumberEqual(float64(index)))
}
func (s *sliceS) AtP(predicates ...p.Number) InterfaceS {
return filterSlice(s, sliceAtPFilter{ip: p.NumberAnd(predicates...)})
}
func (s *sliceS) Last() InterfaceS {
return filterSlice(s, sliceLastFilter{})
}
func (s *sliceS) Children() InterfaceS {
// No predicates means select all direct children.
return s.AtP()
}
func (s *sliceS) All() InterfaceS {
return filterSlice(s, sliceAllFilter{})
}
func (s *sliceS) Filter(sps ...p.Slice) SliceS {
func (s *sliceS) Filter(sps ...p.Slice) Slice {
return &sliceS{vs: s.vs, sp: p.SliceAnd(append(sps, s.sp)...)}
}

View File

@ -14,17 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package unstructpath
package selectors
import (
p "k8s.io/kubectl/pkg/framework/predicates"
p "k8s.io/kubectl/pkg/framework/path/predicates"
)
// StringS is a "string selector". It selects values as strings (if
// String is a "string selector". It selects values as strings (if
// possible) and filters those strings based on the "filtered"
// predicates.
type StringS interface {
// StringS can be used as a Interface predicate. If the selector can't
type String interface {
// String can be used as a Interface predicate. If the selector can't
// select any string from the value, then the predicate is
// false.
p.Interface
@ -34,18 +34,18 @@ type StringS interface {
// depending on the select criterias.
SelectFrom(...interface{}) []string
// Filter will create a new StringS that filters only the values
// Filter will create a new String that filters only the values
// who match the predicate.
Filter(...p.String) StringS
Filter(...p.String) String
}
type stringS struct {
vs InterfaceS
vs Interface
sp p.String
}
// String returns a StringS that selects strings from values.
func String() StringS {
// AsString returns a String that selects strings from values.
func AsString() String {
return &stringS{}
}
@ -67,7 +67,7 @@ func (s *stringS) SelectFrom(values ...interface{}) []string {
return strings
}
func (s *stringS) Filter(predicates ...p.String) StringS {
func (s *stringS) Filter(predicates ...p.String) String {
if s.sp != nil {
predicates = append(predicates, s.sp)
}

View File

@ -14,18 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package unstructpath_test
package selectors_test
import (
"reflect"
"testing"
p "k8s.io/kubectl/pkg/framework/predicates"
. "k8s.io/kubectl/pkg/framework/unstructpath"
p "k8s.io/kubectl/pkg/framework/path/predicates"
. "k8s.io/kubectl/pkg/framework/path/selectors"
)
func TestStringSSelectFrom(t *testing.T) {
s := String().SelectFrom(
func TestStringSelectFrom(t *testing.T) {
s := AsString().SelectFrom(
"my string",
1,
"your string",
@ -36,8 +36,8 @@ func TestStringSSelectFrom(t *testing.T) {
}
}
func TestStringSFilter(t *testing.T) {
s := String().
func TestStringFilter(t *testing.T) {
s := AsString().
Filter(p.StringLength(p.NumberEqual(4))).
SelectFrom(
"one",
@ -51,20 +51,20 @@ func TestStringSFilter(t *testing.T) {
}
}
func TestStringSPredicate(t *testing.T) {
if !String().Filter(p.StringLength(p.NumberEqual(4))).Match("four") {
func TestStringPredicate(t *testing.T) {
if !AsString().Filter(p.StringLength(p.NumberEqual(4))).Match("four") {
t.Fatal("SelectFromor matching element should match")
}
if String().Filter(p.StringLength(p.NumberEqual(10))).Match("four") {
if AsString().Filter(p.StringLength(p.NumberEqual(10))).Match("four") {
t.Fatal("SelectFromor not matching element should not match")
}
}
func TestStringSFromInterfaceS(t *testing.T) {
if !Children().String().Filter(p.StringLength(p.NumberEqual(4))).Match([]interface{}{"four", "five"}) {
func TestStringFromInterface(t *testing.T) {
if !Children().AsString().Filter(p.StringLength(p.NumberEqual(4))).Match([]interface{}{"four", "five"}) {
t.Fatal("SelectFromor should find element that match")
}
if Children().String().Filter(p.StringLength(p.NumberEqual(4))).Match([]interface{}{"one", "two", "three"}) {
if Children().AsString().Filter(p.StringLength(p.NumberEqual(4))).Match([]interface{}{"one", "two", "three"}) {
t.Fatal("SelectFromor shouldn't find element that match")
}
}

View File

@ -1,91 +0,0 @@
/*
Copyright 2018 The Kubernetes Authors.
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 unstructpath
import (
p "k8s.io/kubectl/pkg/framework/predicates"
)
// A interfaceFilter allows us to chain InterfaceS to InterfaceS. None of this is
// public. It's implementing the "SelectFrom" part of a InterfaceS.
type interfaceFilter interface {
SelectFrom(...interface{}) []interface{}
}
// interfaceFilterP filters using a predicate.
type interfaceFilterP struct {
vp p.Interface
}
func (f *interfaceFilterP) SelectFrom(interfaces ...interface{}) []interface{} {
vs := []interface{}{}
for _, value := range interfaces {
if f.vp.Match(value) {
vs = append(vs, value)
}
}
return vs
}
type interfaceChildrenFilter struct{}
func (interfaceChildrenFilter) SelectFrom(interfaces ...interface{}) []interface{} {
children := []interface{}{}
// We could process all slices and then all maps, but we want to
// keep things in the same order.
for _, value := range interfaces {
// Only one of the two should do something useful.
children = append(children, Slice().Children().SelectFrom(value)...)
children = append(children, Map().Children().SelectFrom(value)...)
}
return children
}
// interfaceSliceFilter is a Interface-to-Slice combined with a Slice-to-Interface
// to form a Interface-to-Interface.
type interfaceSliceFilter struct {
ss SliceS
sf sliceFilter
}
func (s *interfaceSliceFilter) SelectFrom(interfaces ...interface{}) []interface{} {
return s.sf.SelectFrom(s.ss.SelectFrom(interfaces...)...)
}
// interfaceMapFilter is a Interface-to-Map combined with a Map-to-Interface to form
// a Interface-to-Interface.
type interfaceMapFilter struct {
ms MapS
mf mapFilter
}
func (s *interfaceMapFilter) SelectFrom(interfaces ...interface{}) []interface{} {
return s.mf.SelectFrom(s.ms.SelectFrom(interfaces...)...)
}
type interfaceAllFilter struct{}
func (interfaceAllFilter) SelectFrom(interfaces ...interface{}) []interface{} {
vs := []interface{}{}
for _, value := range interfaces {
vs = append(vs, value)
// Only one of the follow two statements should return something ...
vs = append(vs, Slice().All().SelectFrom(value)...)
vs = append(vs, Map().All().SelectFrom(value)...)
}
return vs
}

View File

@ -1,120 +0,0 @@
/*
Copyright 2018 The Kubernetes Authors.
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 unstructpath
import (
p "k8s.io/kubectl/pkg/framework/predicates"
)
// InterfaceS is a "interface selector". It filters interfaces based on the
// "filtered" predicates.
type InterfaceS interface {
// InterfaceS can be used as a Interface predicate. If the selector can't
// select any interface from the interface, then the predicate is
// false.
p.Interface
// SelectFrom finds interfaces from interfaces using this selector. The
// list can be bigger or smaller than the initial lists,
// depending on the select criterias.
SelectFrom(...interface{}) []interface{}
// Map returns a selector that selects Maps from the given
// values.
Map() MapS
// Slice returns a selector that selects Slices from the given
// values.
Slice() SliceS
// Number returns a selector taht selects Numbers from the given values.
Number() NumberS
// String returns a selector that selects strings from the given values.
String() StringS
// Children returns a selector that selects the direct children
// of the given values.
Children() InterfaceS
// All returns a selector that selects all direct and indrect
// children of the given values.
All() InterfaceS
// Filter will create a new StringS that filters only the values
// who match the predicate.
Filter(...p.Interface) InterfaceS
}
// Children selects all the children of the values.
func Children() InterfaceS {
return &interfaceS{vf: interfaceChildrenFilter{}}
}
// All selects all the direct and indirect childrens of the values.
func All() InterfaceS {
return &interfaceS{vf: interfaceAllFilter{}}
}
// Filter will only return the values that match the predicate.
func Filter(predicates ...p.Interface) InterfaceS {
return &interfaceS{vf: &interfaceFilterP{vp: p.InterfaceAnd(predicates...)}}
}
// InterfaceS is a "Interface SelectFromor". It selects a list of values, maps,
// slices, strings, integer from a list of values.
type interfaceS struct {
vs InterfaceS
vf interfaceFilter
}
// Match returns true if the selector can find items in the given
// value. Otherwise, it returns false.
func (s *interfaceS) Match(value interface{}) bool {
return len(s.SelectFrom(value)) != 0
}
func (s *interfaceS) SelectFrom(interfaces ...interface{}) []interface{} {
if s.vs != nil {
interfaces = s.vs.SelectFrom(interfaces...)
}
return s.vf.SelectFrom(interfaces...)
}
func (s *interfaceS) Map() MapS {
return &mapS{vs: s}
}
func (s *interfaceS) Slice() SliceS {
return &sliceS{vs: s}
}
func (s *interfaceS) Number() NumberS {
return &numberS{vs: s}
}
func (s *interfaceS) String() StringS {
return &stringS{vs: s}
}
func (s *interfaceS) Children() InterfaceS {
return &interfaceS{vs: s, vf: interfaceChildrenFilter{}}
}
func (s *interfaceS) All() InterfaceS {
return &interfaceS{vs: s, vf: interfaceAllFilter{}}
}
func (s *interfaceS) Filter(predicates ...p.Interface) InterfaceS {
return &interfaceS{vs: s, vf: &interfaceFilterP{vp: p.InterfaceAnd(predicates...)}}
}

View File

@ -1,76 +0,0 @@
/*
Copyright 2018 The Kubernetes Authors.
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 unstructpath
import (
"sort"
p "k8s.io/kubectl/pkg/framework/predicates"
)
// This is a Map-to-Interface filter.
type mapFilter interface {
SelectFrom(...map[string]interface{}) []interface{}
}
func filterMap(ms MapS, mf mapFilter) InterfaceS {
return &interfaceS{
vf: &interfaceMapFilter{
ms: ms,
mf: mf,
},
}
}
type mapFieldPFilter struct {
sp p.String
}
func (f mapFieldPFilter) SelectFrom(maps ...map[string]interface{}) []interface{} {
interfaces := []interface{}{}
for _, m := range maps {
for _, field := range sortedKeys(m) {
if !f.sp.Match(field) {
continue
}
interfaces = append(interfaces, m[field])
}
}
return interfaces
}
type mapAllFilter struct{}
func (mapAllFilter) SelectFrom(maps ...map[string]interface{}) []interface{} {
interfaces := []interface{}{}
for _, m := range maps {
for _, field := range sortedKeys(m) {
interfaces = append(interfaces, All().SelectFrom(m[field])...)
}
}
return interfaces
}
func sortedKeys(m map[string]interface{}) []string {
keys := []string{}
for key := range m {
keys = append(keys, key)
}
sort.Strings(keys)
return keys
}

View File

@ -1,78 +0,0 @@
/*
Copyright 2018 The Kubernetes Authors.
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 unstructpath
import (
p "k8s.io/kubectl/pkg/framework/predicates"
)
func filterSlice(ss SliceS, sf sliceFilter) InterfaceS {
return &interfaceS{
vf: &interfaceSliceFilter{
ss: ss,
sf: sf,
},
}
}
// This is a Slice-to-Interface filter.
type sliceFilter interface {
SelectFrom(...[]interface{}) []interface{}
}
type sliceAtPFilter struct {
ip p.Number
}
func (f sliceAtPFilter) SelectFrom(slices ...[]interface{}) []interface{} {
interfaces := []interface{}{}
for _, slice := range slices {
for i := range slice {
if !f.ip.Match(float64(i)) {
continue
}
interfaces = append(interfaces, slice[i])
}
}
return interfaces
}
type sliceLastFilter struct{}
func (f sliceLastFilter) SelectFrom(slices ...[]interface{}) []interface{} {
interfaces := []interface{}{}
for _, slice := range slices {
if len(slice) == 0 {
continue
}
interfaces = append(interfaces, slice[len(slice)-1])
}
return interfaces
}
type sliceAllFilter struct{}
func (sliceAllFilter) SelectFrom(slices ...[]interface{}) []interface{} {
interfaces := []interface{}{}
for _, slice := range slices {
for _, v := range slice {
interfaces = append(interfaces, All().SelectFrom(v)...)
}
}
return interfaces
}