Merge pull request #362 from apelisse/rename-value-to-interface
selectors: Remove "Map" and "Slice"
This commit is contained in:
commit
11a04e5d8e
|
|
@ -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{}
|
||||
|
|
@ -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{}
|
||||
|
|
@ -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
|
||||
|
|
@ -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{}
|
||||
|
|
@ -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) {
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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...)}}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)...)}
|
||||
}
|
||||
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
@ -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)...)}
|
||||
}
|
||||
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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...)}}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
Loading…
Reference in New Issue