Move list functions from runtime to meta package

This commit is contained in:
feihujiang 2015-11-12 18:45:42 +08:00
parent b12550273e
commit ad79fa6e84
17 changed files with 387 additions and 331 deletions

128
pkg/api/meta/help.go Normal file
View File

@ -0,0 +1,128 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package meta
import (
"fmt"
"reflect"
"k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/runtime"
)
// IsListType returns true if the provided Object has a slice called Items
func IsListType(obj runtime.Object) bool {
_, err := GetItemsPtr(obj)
return err == nil
}
// GetItemsPtr returns a pointer to the list object's Items member.
// If 'list' doesn't have an Items member, it's not really a list type
// and an error will be returned.
// This function will either return a pointer to a slice, or an error, but not both.
func GetItemsPtr(list runtime.Object) (interface{}, error) {
v, err := conversion.EnforcePtr(list)
if err != nil {
return nil, err
}
items := v.FieldByName("Items")
if !items.IsValid() {
return nil, fmt.Errorf("no Items field in %#v", list)
}
switch items.Kind() {
case reflect.Interface, reflect.Ptr:
target := reflect.TypeOf(items.Interface()).Elem()
if target.Kind() != reflect.Slice {
return nil, fmt.Errorf("items: Expected slice, got %s", target.Kind())
}
return items.Interface(), nil
case reflect.Slice:
return items.Addr().Interface(), nil
default:
return nil, fmt.Errorf("items: Expected slice, got %s", items.Kind())
}
}
// ExtractList returns obj's Items element as an array of runtime.Objects.
// Returns an error if obj is not a List type (does not have an Items member).
func ExtractList(obj runtime.Object) ([]runtime.Object, error) {
itemsPtr, err := GetItemsPtr(obj)
if err != nil {
return nil, err
}
items, err := conversion.EnforcePtr(itemsPtr)
if err != nil {
return nil, err
}
list := make([]runtime.Object, items.Len())
for i := range list {
raw := items.Index(i)
switch item := raw.Interface().(type) {
case runtime.Object:
list[i] = item
case runtime.RawExtension:
list[i] = &runtime.Unknown{
RawJSON: item.RawJSON,
}
default:
var found bool
if list[i], found = raw.Addr().Interface().(runtime.Object); !found {
return nil, fmt.Errorf("%v: item[%v]: Expected object, got %#v(%s)", obj, i, raw.Interface(), raw.Kind())
}
}
}
return list, nil
}
// objectSliceType is the type of a slice of Objects
var objectSliceType = reflect.TypeOf([]runtime.Object{})
// SetList sets the given list object's Items member have the elements given in
// objects.
// Returns an error if list is not a List type (does not have an Items member),
// or if any of the objects are not of the right type.
func SetList(list runtime.Object, objects []runtime.Object) error {
itemsPtr, err := GetItemsPtr(list)
if err != nil {
return err
}
items, err := conversion.EnforcePtr(itemsPtr)
if err != nil {
return err
}
if items.Type() == objectSliceType {
items.Set(reflect.ValueOf(objects))
return nil
}
slice := reflect.MakeSlice(items.Type(), len(objects), len(objects))
for i := range objects {
dest := slice.Index(i)
src, err := conversion.EnforcePtr(objects[i])
if err != nil {
return err
}
if src.Type().AssignableTo(dest.Type()) {
dest.Set(src)
} else if src.Type().ConvertibleTo(dest.Type()) {
dest.Set(src.Convert(dest.Type()))
} else {
return fmt.Errorf("item[%d]: Type mismatch: Expected %v, got %v", i, dest.Type(), src.Type())
}
}
items.Set(slice)
return nil
}

222
pkg/api/meta/help_test.go Normal file
View File

@ -0,0 +1,222 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package meta_test
import (
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util"
"github.com/google/gofuzz"
)
func TestIsList(t *testing.T) {
tests := []struct {
obj runtime.Object
isList bool
}{
{&api.PodList{}, true},
{&api.Pod{}, false},
}
for _, item := range tests {
if e, a := item.isList, meta.IsListType(item.obj); e != a {
t.Errorf("%v: Expected %v, got %v", reflect.TypeOf(item.obj), e, a)
}
}
}
func TestExtractList(t *testing.T) {
pl := &api.PodList{
Items: []api.Pod{
{ObjectMeta: api.ObjectMeta{Name: "1"}},
{ObjectMeta: api.ObjectMeta{Name: "2"}},
{ObjectMeta: api.ObjectMeta{Name: "3"}},
},
}
list, err := meta.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if e, a := list[i].(*api.Pod).Name, pl.Items[i].Name; e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
}
}
func TestExtractListGeneric(t *testing.T) {
pl := &api.List{
Items: []runtime.Object{
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}},
&api.Service{ObjectMeta: api.ObjectMeta{Name: "2"}},
},
}
list, err := meta.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
if obj, ok := list[0].(*api.Pod); !ok {
t.Fatalf("Expected list[0] to be *api.Pod, it is %#v", obj)
}
if obj, ok := list[1].(*api.Service); !ok {
t.Fatalf("Expected list[1] to be *api.Service, it is %#v", obj)
}
}
func TestExtractListGenericV1(t *testing.T) {
pl := &v1.List{
Items: []runtime.RawExtension{
{RawJSON: []byte("foo")},
{RawJSON: []byte("bar")},
},
}
list, err := meta.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
if obj, ok := list[0].(*runtime.Unknown); !ok {
t.Fatalf("Expected list[0] to be *runtime.Unknown, it is %#v", obj)
}
if obj, ok := list[1].(*runtime.Unknown); !ok {
t.Fatalf("Expected list[1] to be *runtime.Unknown, it is %#v", obj)
}
}
type fakePtrInterfaceList struct {
Items *[]runtime.Object
}
func (f fakePtrInterfaceList) IsAnAPIObject() {}
func TestExtractListOfInterfacePtrs(t *testing.T) {
pl := &fakePtrInterfaceList{
Items: &[]runtime.Object{},
}
list, err := meta.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if len(list) > 0 {
t.Fatalf("Expected empty list, got %#v", list)
}
}
type fakePtrValueList struct {
Items []*api.Pod
}
func (f fakePtrValueList) IsAnAPIObject() {}
func TestExtractListOfValuePtrs(t *testing.T) {
pl := &fakePtrValueList{
Items: []*api.Pod{
{ObjectMeta: api.ObjectMeta{Name: "1"}},
{ObjectMeta: api.ObjectMeta{Name: "2"}},
},
}
list, err := meta.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if obj, ok := list[i].(*api.Pod); !ok {
t.Fatalf("Expected list[%d] to be *api.Pod, it is %#v", i, obj)
}
}
}
func TestSetList(t *testing.T) {
pl := &api.PodList{}
list := []runtime.Object{
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}},
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}},
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "3"}},
}
err := meta.SetList(pl, list)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if e, a := list[i].(*api.Pod).Name, pl.Items[i].Name; e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
}
}
func TestSetListToRuntimeObjectArray(t *testing.T) {
pl := &api.List{}
list := []runtime.Object{
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}},
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}},
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "3"}},
}
err := meta.SetList(pl, list)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if e, a := list[i], pl.Items[i]; e != a {
t.Fatalf("%d: unmatched: %s", i, util.ObjectDiff(e, a))
}
}
}
func TestSetExtractListRoundTrip(t *testing.T) {
fuzzer := fuzz.New().NilChance(0).NumElements(1, 5)
for i := 0; i < 5; i++ {
start := &api.PodList{}
fuzzer.Fuzz(&start.Items)
list, err := meta.ExtractList(start)
if err != nil {
t.Errorf("Unexpected error %v", err)
continue
}
got := &api.PodList{}
err = meta.SetList(got, list)
if err != nil {
t.Errorf("Unexpected error %v", err)
continue
}
if e, a := start, got; !reflect.DeepEqual(e, a) {
t.Fatalf("Expected %#v, got %#v", e, a)
}
}
}

View File

@ -29,6 +29,7 @@ import (
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/rest"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/fields"
@ -793,7 +794,7 @@ func checkName(obj runtime.Object, name, namespace string, namer ScopeNamer) err
// setListSelfLink sets the self link of a list to the base URL, then sets the self links
// on all child objects returned.
func setListSelfLink(obj runtime.Object, req *restful.Request, namer ScopeNamer) error {
if !runtime.IsListType(obj) {
if !meta.IsListType(obj) {
return nil
}
@ -812,7 +813,7 @@ func setListSelfLink(obj runtime.Object, req *restful.Request, namer ScopeNamer)
}
// Set self-link of objects in the list.
items, err := runtime.ExtractList(obj)
items, err := meta.ExtractList(obj)
if err != nil {
return err
}
@ -821,7 +822,7 @@ func setListSelfLink(obj runtime.Object, req *restful.Request, namer ScopeNamer)
return err
}
}
return runtime.SetList(obj, items)
return meta.SetList(obj, items)
}

View File

@ -231,12 +231,12 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
if err != nil {
return fmt.Errorf("%s: Failed to list %v: %v", r.name, r.expectedType, err)
}
meta, err := meta.Accessor(list)
metaInterface, err := meta.Accessor(list)
if err != nil {
return fmt.Errorf("%s: Unable to understand list result %#v", r.name, list)
}
resourceVersion = meta.ResourceVersion()
items, err := runtime.ExtractList(list)
resourceVersion = metaInterface.ResourceVersion()
items, err := meta.ExtractList(list)
if err != nil {
return fmt.Errorf("%s: Unable to understand list result %#v (%v)", r.name, list, err)
}

View File

@ -167,7 +167,7 @@ func (o objects) Kind(kind, name string) (runtime.Object, error) {
if err != nil {
return nilValue, err
}
if err := runtime.SetList(out, arr); err != nil {
if err := meta.SetList(out, arr); err != nil {
return nilValue, err
}
if out, err = o.scheme.Copy(out); err != nil {
@ -210,12 +210,12 @@ func (o objects) Add(obj runtime.Object) error {
}
switch {
case runtime.IsListType(obj):
case meta.IsListType(obj):
if kind != "List" {
o.types[kind] = append(o.types[kind], obj)
}
list, err := runtime.ExtractList(obj)
list, err := meta.ExtractList(obj)
if err != nil {
return err
}

View File

@ -23,6 +23,7 @@ import (
"sync"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/watch"
@ -136,7 +137,7 @@ func (f *FakeControllerSource) List() (runtime.Object, error) {
list = append(list, objCopy.(runtime.Object))
}
listObj := &api.List{}
if err := runtime.SetList(listObj, list); err != nil {
if err := meta.SetList(listObj, list); err != nil {
return nil, err
}
objMeta, err := api.ListMetaFor(listObj)

View File

@ -28,6 +28,7 @@ import (
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/testapi"
apitesting "k8s.io/kubernetes/pkg/api/testing"
"k8s.io/kubernetes/pkg/api/unversioned"
@ -331,7 +332,7 @@ func TestGetListObjects(t *testing.T) {
func extractResourceList(objs []runtime.Object) ([]runtime.Object, error) {
finalObjs := []runtime.Object{}
for _, obj := range objs {
items, err := runtime.ExtractList(obj)
items, err := meta.ExtractList(obj)
if err != nil {
return nil, err
}
@ -477,14 +478,14 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
list, err := runtime.ExtractList(out)
list, err := meta.ExtractList(out)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if errs := runtime.DecodeList(list, api.Scheme); len(errs) > 0 {
t.Fatalf("unexpected error: %v", errs)
}
if err := runtime.SetList(out, list); err != nil {
if err := meta.SetList(out, list); err != nil {
t.Fatalf("unexpected error: %v", err)
}

View File

@ -27,6 +27,7 @@ import (
"text/tabwriter"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/jsonpath"
)
@ -168,8 +169,8 @@ func (s *CustomColumnsPrinter) PrintObj(obj runtime.Object, out io.Writer) error
}
}
if runtime.IsListType(obj) {
objs, err := runtime.ExtractList(obj)
if meta.IsListType(obj) {
objs, err := meta.ExtractList(obj)
if err != nil {
return err
}

View File

@ -138,7 +138,7 @@ func (r *Result) Object() (runtime.Object, error) {
return objects[0], nil
}
// if the item is a list already, don't create another list
if runtime.IsListType(objects[0]) {
if meta.IsListType(objects[0]) {
return objects[0], nil
}
}

View File

@ -335,7 +335,7 @@ func (v FlattenListVisitor) Visit(fn VisitorFunc) error {
if info.Object == nil {
return fn(info, nil)
}
items, err := runtime.ExtractList(info.Object)
items, err := meta.ExtractList(info.Object)
if err != nil {
return fn(info, nil)
}
@ -564,7 +564,7 @@ func RetrieveLatest(info *Info, err error) error {
if err != nil {
return err
}
if runtime.IsListType(info.Object) {
if meta.IsListType(info.Object) {
return fmt.Errorf("watch is only supported on individual resources and resource collections, but a list of resources is found")
}
if len(info.Name) == 0 {

View File

@ -23,6 +23,7 @@ import (
"sort"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/jsonpath"
@ -38,7 +39,7 @@ type SortingPrinter struct {
}
func (s *SortingPrinter) PrintObj(obj runtime.Object, out io.Writer) error {
if !runtime.IsListType(obj) {
if !meta.IsListType(obj) {
return s.Delegate.PrintObj(obj, out)
}
@ -54,7 +55,7 @@ func (p *SortingPrinter) HandledResources() []string {
}
func (s *SortingPrinter) sortObj(obj runtime.Object) error {
objs, err := runtime.ExtractList(obj)
objs, err := meta.ExtractList(obj)
if err != nil {
return err
}
@ -76,7 +77,7 @@ func (s *SortingPrinter) sortObj(obj runtime.Object) error {
list.Items = outputList
return nil
}
return runtime.SetList(obj, objs)
return meta.SetList(obj, objs)
}
func SortObjects(objs []runtime.Object, fieldInput string) (*RuntimeSort, error) {

View File

@ -22,6 +22,7 @@ import (
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util"
)
@ -119,7 +120,7 @@ func TestArrayOfRuntimeObject(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
list, err := runtime.ExtractList(decoded)
list, err := meta.ExtractList(decoded)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
@ -127,14 +128,14 @@ func TestArrayOfRuntimeObject(t *testing.T) {
t.Fatalf("unexpected error: %v", errs)
}
list2, err := runtime.ExtractList(list[3])
list2, err := meta.ExtractList(list[3])
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if errs := runtime.DecodeList(list2, s); len(errs) > 0 {
t.Fatalf("unexpected error: %v", errs)
}
if err := runtime.SetList(list[3], list2); err != nil {
if err := meta.SetList(list[3], list2); err != nil {
t.Fatalf("unexpected error: %v", err)
}

View File

@ -23,111 +23,6 @@ import (
"k8s.io/kubernetes/pkg/conversion"
)
// IsListType returns true if the provided Object has a slice called Items
func IsListType(obj Object) bool {
_, err := GetItemsPtr(obj)
return err == nil
}
// GetItemsPtr returns a pointer to the list object's Items member.
// If 'list' doesn't have an Items member, it's not really a list type
// and an error will be returned.
// This function will either return a pointer to a slice, or an error, but not both.
func GetItemsPtr(list Object) (interface{}, error) {
v, err := conversion.EnforcePtr(list)
if err != nil {
return nil, err
}
items := v.FieldByName("Items")
if !items.IsValid() {
return nil, fmt.Errorf("no Items field in %#v", list)
}
switch items.Kind() {
case reflect.Interface, reflect.Ptr:
target := reflect.TypeOf(items.Interface()).Elem()
if target.Kind() != reflect.Slice {
return nil, fmt.Errorf("items: Expected slice, got %s", target.Kind())
}
return items.Interface(), nil
case reflect.Slice:
return items.Addr().Interface(), nil
default:
return nil, fmt.Errorf("items: Expected slice, got %s", items.Kind())
}
}
// ExtractList returns obj's Items element as an array of runtime.Objects.
// Returns an error if obj is not a List type (does not have an Items member).
// TODO: move me to pkg/api/meta
func ExtractList(obj Object) ([]Object, error) {
itemsPtr, err := GetItemsPtr(obj)
if err != nil {
return nil, err
}
items, err := conversion.EnforcePtr(itemsPtr)
if err != nil {
return nil, err
}
list := make([]Object, items.Len())
for i := range list {
raw := items.Index(i)
switch item := raw.Interface().(type) {
case Object:
list[i] = item
case RawExtension:
list[i] = &Unknown{
RawJSON: item.RawJSON,
}
default:
var found bool
if list[i], found = raw.Addr().Interface().(Object); !found {
return nil, fmt.Errorf("%v: item[%v]: Expected object, got %#v(%s)", obj, i, raw.Interface(), raw.Kind())
}
}
}
return list, nil
}
// objectSliceType is the type of a slice of Objects
var objectSliceType = reflect.TypeOf([]Object{})
// SetList sets the given list object's Items member have the elements given in
// objects.
// Returns an error if list is not a List type (does not have an Items member),
// or if any of the objects are not of the right type.
// TODO: move me to pkg/api/meta
func SetList(list Object, objects []Object) error {
itemsPtr, err := GetItemsPtr(list)
if err != nil {
return err
}
items, err := conversion.EnforcePtr(itemsPtr)
if err != nil {
return err
}
if items.Type() == objectSliceType {
items.Set(reflect.ValueOf(objects))
return nil
}
slice := reflect.MakeSlice(items.Type(), len(objects), len(objects))
for i := range objects {
dest := slice.Index(i)
src, err := conversion.EnforcePtr(objects[i])
if err != nil {
return err
}
if src.Type().AssignableTo(dest.Type()) {
dest.Set(src)
} else if src.Type().ConvertibleTo(dest.Type()) {
dest.Set(src.Convert(dest.Type()))
} else {
return fmt.Errorf("item[%d]: Type mismatch: Expected %v, got %v", i, dest.Type(), src.Type())
}
}
items.Set(slice)
return nil
}
// fieldPtr puts the address of fieldName, which must be a member of v,
// into dest, which must be an address of a variable to which this field's
// address can be assigned.

View File

@ -17,145 +17,13 @@ limitations under the License.
package runtime_test
import (
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util"
"github.com/google/gofuzz"
)
func TestIsList(t *testing.T) {
tests := []struct {
obj runtime.Object
isList bool
}{
{&api.PodList{}, true},
{&api.Pod{}, false},
}
for _, item := range tests {
if e, a := item.isList, runtime.IsListType(item.obj); e != a {
t.Errorf("%v: Expected %v, got %v", reflect.TypeOf(item.obj), e, a)
}
}
}
func TestExtractList(t *testing.T) {
pl := &api.PodList{
Items: []api.Pod{
{ObjectMeta: api.ObjectMeta{Name: "1"}},
{ObjectMeta: api.ObjectMeta{Name: "2"}},
{ObjectMeta: api.ObjectMeta{Name: "3"}},
},
}
list, err := runtime.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if e, a := list[i].(*api.Pod).Name, pl.Items[i].Name; e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
}
}
func TestExtractListGeneric(t *testing.T) {
pl := &api.List{
Items: []runtime.Object{
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}},
&api.Service{ObjectMeta: api.ObjectMeta{Name: "2"}},
},
}
list, err := runtime.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
if obj, ok := list[0].(*api.Pod); !ok {
t.Fatalf("Expected list[0] to be *api.Pod, it is %#v", obj)
}
if obj, ok := list[1].(*api.Service); !ok {
t.Fatalf("Expected list[1] to be *api.Service, it is %#v", obj)
}
}
func TestExtractListGenericV1(t *testing.T) {
pl := &v1.List{
Items: []runtime.RawExtension{
{RawJSON: []byte("foo")},
{RawJSON: []byte("bar")},
},
}
list, err := runtime.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
if obj, ok := list[0].(*runtime.Unknown); !ok {
t.Fatalf("Expected list[0] to be *runtime.Unknown, it is %#v", obj)
}
if obj, ok := list[1].(*runtime.Unknown); !ok {
t.Fatalf("Expected list[1] to be *runtime.Unknown, it is %#v", obj)
}
}
type fakePtrInterfaceList struct {
Items *[]runtime.Object
}
func (f fakePtrInterfaceList) IsAnAPIObject() {}
func TestExtractListOfInterfacePtrs(t *testing.T) {
pl := &fakePtrInterfaceList{
Items: &[]runtime.Object{},
}
list, err := runtime.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if len(list) > 0 {
t.Fatalf("Expected empty list, got %#v", list)
}
}
type fakePtrValueList struct {
Items []*api.Pod
}
func (f fakePtrValueList) IsAnAPIObject() {}
func TestExtractListOfValuePtrs(t *testing.T) {
pl := &fakePtrValueList{
Items: []*api.Pod{
{ObjectMeta: api.ObjectMeta{Name: "1"}},
{ObjectMeta: api.ObjectMeta{Name: "2"}},
},
}
list, err := runtime.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if obj, ok := list[i].(*api.Pod); !ok {
t.Fatalf("Expected list[%d] to be *api.Pod, it is %#v", i, obj)
}
}
}
func TestDecodeList(t *testing.T) {
pl := &api.List{
Items: []runtime.Object{
@ -171,68 +39,3 @@ func TestDecodeList(t *testing.T) {
t.Errorf("object not converted: %#v", pl.Items[1])
}
}
func TestSetList(t *testing.T) {
pl := &api.PodList{}
list := []runtime.Object{
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}},
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}},
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "3"}},
}
err := runtime.SetList(pl, list)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if e, a := list[i].(*api.Pod).Name, pl.Items[i].Name; e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
}
}
func TestSetListToRuntimeObjectArray(t *testing.T) {
pl := &api.List{}
list := []runtime.Object{
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}},
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}},
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "3"}},
}
err := runtime.SetList(pl, list)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if e, a := list[i], pl.Items[i]; e != a {
t.Fatalf("%d: unmatched: %s", i, util.ObjectDiff(e, a))
}
}
}
func TestSetExtractListRoundTrip(t *testing.T) {
fuzzer := fuzz.New().NilChance(0).NumElements(1, 5)
for i := 0; i < 5; i++ {
start := &api.PodList{}
fuzzer.Fuzz(&start.Items)
list, err := runtime.ExtractList(start)
if err != nil {
t.Errorf("Unexpected error %v", err)
continue
}
got := &api.PodList{}
err = runtime.SetList(got, list)
if err != nil {
t.Errorf("Unexpected error %v", err)
continue
}
if e, a := start, got; !reflect.DeepEqual(e, a) {
t.Fatalf("Expected %#v, got %#v", e, a)
}
}
}

View File

@ -25,6 +25,7 @@ import (
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/runtime"
@ -276,7 +277,7 @@ func (c *Cacher) List(ctx context.Context, key string, resourceVersion uint64, f
c.usable.RUnlock()
// List elements from cache, with at least 'resourceVersion'.
listPtr, err := runtime.GetItemsPtr(listObj)
listPtr, err := meta.GetItemsPtr(listObj)
if err != nil {
return err
}

View File

@ -26,6 +26,7 @@ import (
"github.com/coreos/go-etcd/etcd"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/storage"
@ -273,7 +274,7 @@ func (h *etcdHelper) GetToList(ctx context.Context, key string, filter storage.F
glog.Errorf("Context is nil")
}
trace := util.NewTrace("GetToList " + getTypeName(listObj))
listPtr, err := runtime.GetItemsPtr(listObj)
listPtr, err := meta.GetItemsPtr(listObj)
if err != nil {
return err
}
@ -356,7 +357,7 @@ func (h *etcdHelper) List(ctx context.Context, key string, resourceVersion uint6
}
trace := util.NewTrace("List " + getTypeName(listObj))
defer trace.LogIfLong(time.Second)
listPtr, err := runtime.GetItemsPtr(listObj)
listPtr, err := meta.GetItemsPtr(listObj)
if err != nil {
return err
}

View File

@ -49,7 +49,7 @@ func CreateObjList(prefix string, helper storage.Interface, items []runtime.Obje
// CreateList will properly create a list using the storage interface
func CreateList(prefix string, helper storage.Interface, list runtime.Object) error {
items, err := runtime.ExtractList(list)
items, err := meta.ExtractList(list)
if err != nil {
return err
}
@ -57,5 +57,5 @@ func CreateList(prefix string, helper storage.Interface, list runtime.Object) er
if err != nil {
return err
}
return runtime.SetList(list, items)
return meta.SetList(list, items)
}