mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 15:05:27 +00:00
Merge pull request #7490 from smarterclayton/alter_list
Do not automatically decode runtime.RawExtension
This commit is contained in:
commit
1a8845af61
@ -115,12 +115,14 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
|
|||||||
},
|
},
|
||||||
func(j *api.List, c fuzz.Continue) {
|
func(j *api.List, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||||
if j.Items == nil {
|
// TODO: uncomment when round trip starts from a versioned object
|
||||||
|
if false { //j.Items == nil {
|
||||||
j.Items = []runtime.Object{}
|
j.Items = []runtime.Object{}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
func(j *runtime.Object, c fuzz.Continue) {
|
func(j *runtime.Object, c fuzz.Continue) {
|
||||||
if c.RandBool() {
|
// TODO: uncomment when round trip starts from a versioned object
|
||||||
|
if true { //c.RandBool() {
|
||||||
*j = &runtime.Unknown{
|
*j = &runtime.Unknown{
|
||||||
TypeMeta: runtime.TypeMeta{Kind: "Something", APIVersion: "unknown"},
|
TypeMeta: runtime.TypeMeta{Kind: "Something", APIVersion: "unknown"},
|
||||||
RawJSON: []byte(`{"apiVersion":"unknown","kind":"Something","someKey":"someValue"}`),
|
RawJSON: []byte(`{"apiVersion":"unknown","kind":"Something","someKey":"someValue"}`),
|
||||||
|
@ -81,7 +81,7 @@ func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc {
|
|||||||
|
|
||||||
// AddObjectsFromPath loads the JSON or YAML file containing Kubernetes API resources
|
// AddObjectsFromPath loads the JSON or YAML file containing Kubernetes API resources
|
||||||
// and adds them to the provided ObjectRetriever.
|
// and adds them to the provided ObjectRetriever.
|
||||||
func AddObjectsFromPath(path string, o ObjectRetriever) error {
|
func AddObjectsFromPath(path string, o ObjectRetriever, decoder runtime.Decoder) error {
|
||||||
data, err := ioutil.ReadFile(path)
|
data, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -90,7 +90,7 @@ func AddObjectsFromPath(path string, o ObjectRetriever) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
obj, err := api.Codec.Decode(data)
|
obj, err := decoder.Decode(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -103,17 +103,12 @@ func AddObjectsFromPath(path string, o ObjectRetriever) error {
|
|||||||
type objects struct {
|
type objects struct {
|
||||||
types map[string][]runtime.Object
|
types map[string][]runtime.Object
|
||||||
last map[string]int
|
last map[string]int
|
||||||
typer runtime.ObjectTyper
|
scheme runtime.ObjectScheme
|
||||||
creater runtime.ObjectCreater
|
decoder runtime.ObjectDecoder
|
||||||
copier copier
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ ObjectRetriever = &objects{}
|
var _ ObjectRetriever = &objects{}
|
||||||
|
|
||||||
type copier interface {
|
|
||||||
Copy(obj runtime.Object) (runtime.Object, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewObjects implements the ObjectRetriever interface by introspecting the
|
// NewObjects implements the ObjectRetriever interface by introspecting the
|
||||||
// objects provided to Add() and returning them when the Kind method is invoked.
|
// objects provided to Add() and returning them when the Kind method is invoked.
|
||||||
// If an api.List object is provided to Add(), each child item is added. If an
|
// If an api.List object is provided to Add(), each child item is added. If an
|
||||||
@ -124,18 +119,17 @@ type copier interface {
|
|||||||
// as a runtime.Object if Status == Success). If multiple PodLists are provided, they
|
// as a runtime.Object if Status == Success). If multiple PodLists are provided, they
|
||||||
// will be returned in order by the Kind call, and the last PodList will be reused for
|
// will be returned in order by the Kind call, and the last PodList will be reused for
|
||||||
// subsequent calls.
|
// subsequent calls.
|
||||||
func NewObjects(scheme *runtime.Scheme) ObjectRetriever {
|
func NewObjects(scheme runtime.ObjectScheme, decoder runtime.ObjectDecoder) ObjectRetriever {
|
||||||
return objects{
|
return objects{
|
||||||
types: make(map[string][]runtime.Object),
|
types: make(map[string][]runtime.Object),
|
||||||
last: make(map[string]int),
|
last: make(map[string]int),
|
||||||
typer: scheme,
|
scheme: scheme,
|
||||||
creater: scheme,
|
decoder: decoder,
|
||||||
copier: scheme,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o objects) Kind(kind, name string) (runtime.Object, error) {
|
func (o objects) Kind(kind, name string) (runtime.Object, error) {
|
||||||
empty, _ := o.creater.New("", kind)
|
empty, _ := o.scheme.New("", kind)
|
||||||
nilValue := reflect.Zero(reflect.TypeOf(empty)).Interface().(runtime.Object)
|
nilValue := reflect.Zero(reflect.TypeOf(empty)).Interface().(runtime.Object)
|
||||||
|
|
||||||
arr, ok := o.types[kind]
|
arr, ok := o.types[kind]
|
||||||
@ -146,14 +140,14 @@ func (o objects) Kind(kind, name string) (runtime.Object, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return empty, nil
|
return empty, nil
|
||||||
}
|
}
|
||||||
out, err := o.creater.New("", kind)
|
out, err := o.scheme.New("", kind)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nilValue, err
|
return nilValue, err
|
||||||
}
|
}
|
||||||
if err := runtime.SetList(out, arr); err != nil {
|
if err := runtime.SetList(out, arr); err != nil {
|
||||||
return nilValue, err
|
return nilValue, err
|
||||||
}
|
}
|
||||||
if out, err = o.copier.Copy(out); err != nil {
|
if out, err = o.scheme.Copy(out); err != nil {
|
||||||
return nilValue, err
|
return nilValue, err
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
@ -168,7 +162,7 @@ func (o objects) Kind(kind, name string) (runtime.Object, error) {
|
|||||||
if index < 0 {
|
if index < 0 {
|
||||||
return nilValue, errors.NewNotFound(kind, name)
|
return nilValue, errors.NewNotFound(kind, name)
|
||||||
}
|
}
|
||||||
out, err := o.copier.Copy(arr[index])
|
out, err := o.scheme.Copy(arr[index])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nilValue, err
|
return nilValue, err
|
||||||
}
|
}
|
||||||
@ -187,7 +181,7 @@ func (o objects) Kind(kind, name string) (runtime.Object, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o objects) Add(obj runtime.Object) error {
|
func (o objects) Add(obj runtime.Object) error {
|
||||||
_, kind, err := o.typer.ObjectVersionAndKind(obj)
|
_, kind, err := o.scheme.ObjectVersionAndKind(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -202,6 +196,9 @@ func (o objects) Add(obj runtime.Object) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if errs := runtime.DecodeList(list, o.decoder); len(errs) > 0 {
|
||||||
|
return errs[0]
|
||||||
|
}
|
||||||
for _, obj := range list {
|
for _, obj := range list {
|
||||||
if err := o.Add(obj); err != nil {
|
if err := o.Add(obj); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
|
|
||||||
// NewSimpleFake returns a client that will respond with the provided objects
|
// NewSimpleFake returns a client that will respond with the provided objects
|
||||||
func NewSimpleFake(objects ...runtime.Object) *Fake {
|
func NewSimpleFake(objects ...runtime.Object) *Fake {
|
||||||
o := NewObjects(api.Scheme)
|
o := NewObjects(api.Scheme, api.Scheme)
|
||||||
for _, obj := range objects {
|
for _, obj := range objects {
|
||||||
if err := o.Add(obj); err != nil {
|
if err := o.Add(obj); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -27,8 +27,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestNewClient(t *testing.T) {
|
func TestNewClient(t *testing.T) {
|
||||||
o := NewObjects(api.Scheme)
|
o := NewObjects(api.Scheme, api.Scheme)
|
||||||
if err := AddObjectsFromPath("../../../examples/guestbook/frontend-service.json", o); err != nil {
|
if err := AddObjectsFromPath("../../../examples/guestbook/frontend-service.json", o, api.Scheme); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
client := &Fake{ReactFn: ObjectReaction(o, latest.RESTMapper)}
|
client := &Fake{ReactFn: ObjectReaction(o, latest.RESTMapper)}
|
||||||
@ -52,7 +52,7 @@ func TestNewClient(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestErrors(t *testing.T) {
|
func TestErrors(t *testing.T) {
|
||||||
o := NewObjects(api.Scheme)
|
o := NewObjects(api.Scheme, api.Scheme)
|
||||||
o.Add(&api.List{
|
o.Add(&api.List{
|
||||||
Items: []runtime.Object{
|
Items: []runtime.Object{
|
||||||
// This first call to List will return this error
|
// This first call to List will return this error
|
||||||
|
@ -54,6 +54,10 @@ type missingKindErr struct {
|
|||||||
data string
|
data string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewMissingKindErr(data string) error {
|
||||||
|
return &missingKindErr{data}
|
||||||
|
}
|
||||||
|
|
||||||
func (k *missingKindErr) Error() string {
|
func (k *missingKindErr) Error() string {
|
||||||
return fmt.Sprintf("Object 'Kind' is missing in '%s'", k.data)
|
return fmt.Sprintf("Object 'Kind' is missing in '%s'", k.data)
|
||||||
}
|
}
|
||||||
@ -70,6 +74,10 @@ type missingVersionErr struct {
|
|||||||
data string
|
data string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewMissingVersionErr(data string) error {
|
||||||
|
return &missingVersionErr{data}
|
||||||
|
}
|
||||||
|
|
||||||
func (k *missingVersionErr) Error() string {
|
func (k *missingVersionErr) Error() string {
|
||||||
return fmt.Sprintf("Object 'apiVersion' is missing in '%s'", k.data)
|
return fmt.Sprintf("Object 'apiVersion' is missing in '%s'", k.data)
|
||||||
}
|
}
|
||||||
|
@ -238,6 +238,17 @@ func (s *Scheme) AddDefaultingFuncs(defaultingFuncs ...interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recognizes returns true if the scheme is able to handle the provided version and kind
|
||||||
|
// of an object.
|
||||||
|
func (s *Scheme) Recognizes(version, kind string) bool {
|
||||||
|
m, ok := s.versionMap[version]
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, ok = m[kind]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterInputDefaults sets the provided field mapping function and field matching
|
// RegisterInputDefaults sets the provided field mapping function and field matching
|
||||||
// as the defaults for the provided input type. The fn may be nil, in which case no
|
// as the defaults for the provided input type. The fn may be nil, in which case no
|
||||||
// mapping will happen by default. Use this method to register a mechanism for handling
|
// mapping will happen by default. Use this method to register a mechanism for handling
|
||||||
|
@ -393,6 +393,17 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
list, err := runtime.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 {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
expected := &api.List{
|
expected := &api.List{
|
||||||
Items: []runtime.Object{
|
Items: []runtime.Object{
|
||||||
&pods.Items[0],
|
&pods.Items[0],
|
||||||
|
@ -347,6 +347,12 @@ func (v FlattenListVisitor) Visit(fn VisitorFunc) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fn(info)
|
return fn(info)
|
||||||
}
|
}
|
||||||
|
if errs := runtime.DecodeList(items, struct {
|
||||||
|
runtime.ObjectTyper
|
||||||
|
runtime.Decoder
|
||||||
|
}{v.Mapper, info.Mapping.Codec}); len(errs) > 0 {
|
||||||
|
return errors.NewAggregate(errs)
|
||||||
|
}
|
||||||
for i := range items {
|
for i := range items {
|
||||||
item, err := v.InfoForObject(items[i])
|
item, err := v.InfoForObject(items[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -135,7 +135,7 @@ func TestSyncNamespaceThatIsActive(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunStop(t *testing.T) {
|
func TestRunStop(t *testing.T) {
|
||||||
o := testclient.NewObjects(api.Scheme)
|
o := testclient.NewObjects(api.Scheme, api.Scheme)
|
||||||
client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)}
|
client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)}
|
||||||
nsMgr := NewNamespaceManager(client, 1*time.Second)
|
nsMgr := NewNamespaceManager(client, 1*time.Second)
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// CodecFor returns a Codec that invokes Encode with the provided version.
|
// CodecFor returns a Codec that invokes Encode with the provided version.
|
||||||
func CodecFor(scheme *Scheme, version string) Codec {
|
func CodecFor(codec ObjectCodec, version string) Codec {
|
||||||
return &codecWrapper{scheme, version}
|
return &codecWrapper{codec, version}
|
||||||
}
|
}
|
||||||
|
|
||||||
// yamlCodec converts YAML passed to the Decoder methods to JSON.
|
// yamlCodec converts YAML passed to the Decoder methods to JSON.
|
||||||
@ -69,11 +69,11 @@ func EncodeOrDie(codec Codec, obj Object) string {
|
|||||||
// codecWrapper implements encoding to an alternative
|
// codecWrapper implements encoding to an alternative
|
||||||
// default version for a scheme.
|
// default version for a scheme.
|
||||||
type codecWrapper struct {
|
type codecWrapper struct {
|
||||||
*Scheme
|
ObjectCodec
|
||||||
version string
|
version string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode implements Codec
|
// Encode implements Codec
|
||||||
func (c *codecWrapper) Encode(obj Object) ([]byte, error) {
|
func (c *codecWrapper) Encode(obj Object) ([]byte, error) {
|
||||||
return c.Scheme.EncodeToVersion(obj, c.version)
|
return c.EncodeToVersion(obj, c.version)
|
||||||
}
|
}
|
||||||
|
@ -63,9 +63,22 @@ func TestDecodeEmptyRawExtensionAsObject(t *testing.T) {
|
|||||||
s.AddKnownTypes("", &ObjectTest{})
|
s.AddKnownTypes("", &ObjectTest{})
|
||||||
s.AddKnownTypeWithName("v1test", "ObjectTest", &ObjectTestExternal{})
|
s.AddKnownTypeWithName("v1test", "ObjectTest", &ObjectTestExternal{})
|
||||||
|
|
||||||
_, err := s.Decode([]byte(`{"kind":"ObjectTest","apiVersion":"v1test","items":[{}]}`))
|
obj, err := s.Decode([]byte(`{"kind":"ObjectTest","apiVersion":"v1test","items":[{}]}`))
|
||||||
if err == nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected non-error")
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
test := obj.(*ObjectTest)
|
||||||
|
if unk, ok := test.Items[0].(*runtime.Unknown); !ok || unk.Kind != "" || unk.APIVersion != "" || string(unk.RawJSON) != "{}" {
|
||||||
|
t.Fatalf("unexpected object: %#v", test.Items[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
obj, err = s.Decode([]byte(`{"kind":"ObjectTest","apiVersion":"v1test","items":[{"kind":"Other","apiVersion":"v1"}]}`))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
test = obj.(*ObjectTest)
|
||||||
|
if unk, ok := test.Items[0].(*runtime.Unknown); !ok || unk.Kind != "Other" || unk.APIVersion != "v1" || string(unk.RawJSON) != `{"kind":"Other","apiVersion":"v1"}` {
|
||||||
|
t.Fatalf("unexpected object: %#v", test.Items[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,17 +112,34 @@ func TestArrayOfRuntimeObject(t *testing.T) {
|
|||||||
if err := json.Unmarshal(wire, obj); err != nil {
|
if err := json.Unmarshal(wire, obj); err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
t.Logf("exact wire is: %#v", string(obj.Items[0].RawJSON))
|
t.Logf("exact wire is: %s", string(obj.Items[0].RawJSON))
|
||||||
|
|
||||||
decoded, err := s.Decode(wire)
|
decoded, err := s.Decode(wire)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
list, err := runtime.ExtractList(decoded)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if errs := runtime.DecodeList(list, s); len(errs) > 0 {
|
||||||
|
t.Fatalf("unexpected error: %v", errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
list2, err := runtime.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 {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
internal.Items[2].(*runtime.Unknown).Kind = "OtherTest"
|
internal.Items[2].(*runtime.Unknown).Kind = "OtherTest"
|
||||||
internal.Items[2].(*runtime.Unknown).APIVersion = "unknown"
|
internal.Items[2].(*runtime.Unknown).APIVersion = "unknown"
|
||||||
if e, a := internal, decoded; !reflect.DeepEqual(e, a) {
|
if e, a := internal.Items, list; !reflect.DeepEqual(e, a) {
|
||||||
t.Log(string(decoded.(*ObjectTest).Items[2].(*runtime.Unknown).RawJSON))
|
|
||||||
t.Errorf("mismatched decoded: %s", util.ObjectDiff(e, a))
|
t.Errorf("mismatched decoded: %s", util.ObjectDiff(e, a))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: move me to pkg/api/meta
|
// IsListType returns true if the provided Object has a slice called Items
|
||||||
func IsListType(obj Object) bool {
|
func IsListType(obj Object) bool {
|
||||||
_, err := GetItemsPtr(obj)
|
_, err := GetItemsPtr(obj)
|
||||||
return err == nil
|
return err == nil
|
||||||
@ -33,7 +33,6 @@ func IsListType(obj Object) bool {
|
|||||||
// If 'list' doesn't have an Items member, it's not really a list type
|
// If 'list' doesn't have an Items member, it's not really a list type
|
||||||
// and an error will be returned.
|
// and an error will be returned.
|
||||||
// This function will either return a pointer to a slice, or an error, but not both.
|
// This function will either return a pointer to a slice, or an error, but not both.
|
||||||
// TODO: move me to pkg/api/meta
|
|
||||||
func GetItemsPtr(list Object) (interface{}, error) {
|
func GetItemsPtr(list Object) (interface{}, error) {
|
||||||
v, err := conversion.EnforcePtr(list)
|
v, err := conversion.EnforcePtr(list)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -150,9 +149,36 @@ func FieldPtr(v reflect.Value, fieldName string, dest interface{}) error {
|
|||||||
return fmt.Errorf("couldn't assign/convert %v to %v", field.Type(), v.Type())
|
return fmt.Errorf("couldn't assign/convert %v to %v", field.Type(), v.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeList alters the list in place, attempting to decode any objects found in
|
||||||
|
// the list that have the runtime.Unknown type. Any errors that occur are returned
|
||||||
|
// after the entire list is processed. Decoders are tried in order.
|
||||||
|
func DecodeList(objects []Object, decoders ...ObjectDecoder) []error {
|
||||||
|
errs := []error(nil)
|
||||||
|
for i, obj := range objects {
|
||||||
|
switch t := obj.(type) {
|
||||||
|
case *Unknown:
|
||||||
|
for _, decoder := range decoders {
|
||||||
|
if !decoder.Recognizes(t.APIVersion, t.Kind) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
obj, err := decoder.Decode(t.RawJSON)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
objects[i] = obj
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errs
|
||||||
|
}
|
||||||
|
|
||||||
// MultiObjectTyper returns the types of objects across multiple schemes in order.
|
// MultiObjectTyper returns the types of objects across multiple schemes in order.
|
||||||
type MultiObjectTyper []ObjectTyper
|
type MultiObjectTyper []ObjectTyper
|
||||||
|
|
||||||
|
var _ ObjectTyper = MultiObjectTyper{}
|
||||||
|
|
||||||
func (m MultiObjectTyper) DataVersionAndKind(data []byte) (version, kind string, err error) {
|
func (m MultiObjectTyper) DataVersionAndKind(data []byte) (version, kind string, err error) {
|
||||||
for _, t := range m {
|
for _, t := range m {
|
||||||
version, kind, err = t.DataVersionAndKind(data)
|
version, kind, err = t.DataVersionAndKind(data)
|
||||||
@ -162,6 +188,7 @@ func (m MultiObjectTyper) DataVersionAndKind(data []byte) (version, kind string,
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m MultiObjectTyper) ObjectVersionAndKind(obj Object) (version, kind string, err error) {
|
func (m MultiObjectTyper) ObjectVersionAndKind(obj Object) (version, kind string, err error) {
|
||||||
for _, t := range m {
|
for _, t := range m {
|
||||||
version, kind, err = t.ObjectVersionAndKind(obj)
|
version, kind, err = t.ObjectVersionAndKind(obj)
|
||||||
@ -171,3 +198,12 @@ func (m MultiObjectTyper) ObjectVersionAndKind(obj Object) (version, kind string
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m MultiObjectTyper) Recognizes(version, kind string) bool {
|
||||||
|
for _, t := range m {
|
||||||
|
if t.Recognizes(version, kind) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
|
|
||||||
@ -132,6 +133,22 @@ func TestExtractListOfValuePtrs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDecodeList(t *testing.T) {
|
||||||
|
pl := &api.List{
|
||||||
|
Items: []runtime.Object{
|
||||||
|
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}},
|
||||||
|
&runtime.Unknown{TypeMeta: runtime.TypeMeta{Kind: "Pod", APIVersion: "v1beta3"}, RawJSON: []byte(`{"kind":"Pod","apiVersion":"v1beta3","metadata":{"name":"test"}}`)},
|
||||||
|
&runtime.Unstructured{TypeMeta: runtime.TypeMeta{Kind: "Foo", APIVersion: "Bar"}, Object: map[string]interface{}{"test": "value"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if errs := runtime.DecodeList(pl.Items, api.Scheme); len(errs) != 0 {
|
||||||
|
t.Fatalf("unexpected error %v", errs)
|
||||||
|
}
|
||||||
|
if pod, ok := pl.Items[1].(*api.Pod); !ok || pod.Name != "test" {
|
||||||
|
t.Errorf("object not converted: %#v", pl.Items[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSetList(t *testing.T) {
|
func TestSetList(t *testing.T) {
|
||||||
pl := &api.PodList{}
|
pl := &api.PodList{}
|
||||||
list := []runtime.Object{
|
list := []runtime.Object{
|
||||||
|
@ -16,6 +16,24 @@ limitations under the License.
|
|||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
// ObjectScheme represents common conversions between formal external API versions
|
||||||
|
// and the internal Go structs. ObjectScheme is typically used with ObjectCodec to
|
||||||
|
// transform internal Go structs into serialized versions. There may be many valid
|
||||||
|
// ObjectCodecs for each ObjectScheme.
|
||||||
|
type ObjectScheme interface {
|
||||||
|
ObjectConvertor
|
||||||
|
ObjectTyper
|
||||||
|
ObjectCreater
|
||||||
|
ObjectCopier
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectCodec represents the common mechanisms for converting to and from a particular
|
||||||
|
// binary representation of an object.
|
||||||
|
type ObjectCodec interface {
|
||||||
|
ObjectEncoder
|
||||||
|
Decoder
|
||||||
|
}
|
||||||
|
|
||||||
// Decoder defines methods for deserializing API objects into a given type
|
// Decoder defines methods for deserializing API objects into a given type
|
||||||
type Decoder interface {
|
type Decoder interface {
|
||||||
Decode(data []byte) (Object, error)
|
Decode(data []byte) (Object, error)
|
||||||
@ -33,6 +51,22 @@ type Codec interface {
|
|||||||
Encoder
|
Encoder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ObjectCopier duplicates an object.
|
||||||
|
type ObjectCopier interface {
|
||||||
|
// Copy returns an exact copy of the provided Object, or an error if the
|
||||||
|
// copy could not be completed.
|
||||||
|
Copy(Object) (Object, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectEncoder turns an object into a byte array. This interface is a
|
||||||
|
// general form of the Encoder interface
|
||||||
|
type ObjectEncoder interface {
|
||||||
|
// EncodeToVersion convert and serializes an object in the internal format
|
||||||
|
// to a specified output version. An error is returned if the object
|
||||||
|
// cannot be converted for any reason.
|
||||||
|
EncodeToVersion(obj Object, outVersion string) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
// ObjectConvertor converts an object to a different version.
|
// ObjectConvertor converts an object to a different version.
|
||||||
type ObjectConvertor interface {
|
type ObjectConvertor interface {
|
||||||
Convert(in, out interface{}) error
|
Convert(in, out interface{}) error
|
||||||
@ -43,8 +77,17 @@ type ObjectConvertor interface {
|
|||||||
// ObjectTyper contains methods for extracting the APIVersion and Kind
|
// ObjectTyper contains methods for extracting the APIVersion and Kind
|
||||||
// of objects.
|
// of objects.
|
||||||
type ObjectTyper interface {
|
type ObjectTyper interface {
|
||||||
|
// DataVersionAndKind returns the version and kind of the provided data, or an error
|
||||||
|
// if another problem is detected. In many cases this method can be as expensive to
|
||||||
|
// invoke as the Decode method.
|
||||||
DataVersionAndKind([]byte) (version, kind string, err error)
|
DataVersionAndKind([]byte) (version, kind string, err error)
|
||||||
|
// ObjectVersionAndKind returns the version and kind of the provided object, or an
|
||||||
|
// error if the object is not recognized (IsNotRegisteredError will return true).
|
||||||
ObjectVersionAndKind(Object) (version, kind string, err error)
|
ObjectVersionAndKind(Object) (version, kind string, err error)
|
||||||
|
// Recognizes returns true if the scheme is able to handle the provided version and kind,
|
||||||
|
// or more precisely that the provided version is a possible conversion or decoding
|
||||||
|
// target.
|
||||||
|
Recognizes(version, kind string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectCreater contains methods for instantiating an object by kind and version.
|
// ObjectCreater contains methods for instantiating an object by kind and version.
|
||||||
@ -52,6 +95,20 @@ type ObjectCreater interface {
|
|||||||
New(version, kind string) (out Object, err error)
|
New(version, kind string) (out Object, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ObjectDecoder is a convenience interface for identifying serialized versions of objects
|
||||||
|
// and transforming them into Objects. It intentionally overlaps with ObjectTyper and
|
||||||
|
// Decoder for use in decode only paths.
|
||||||
|
type ObjectDecoder interface {
|
||||||
|
Decoder
|
||||||
|
// DataVersionAndKind returns the version and kind of the provided data, or an error
|
||||||
|
// if another problem is detected. In many cases this method can be as expensive to
|
||||||
|
// invoke as the Decode method.
|
||||||
|
DataVersionAndKind([]byte) (version, kind string, err error)
|
||||||
|
// Recognizes returns true if the scheme is able to handle the provided version and kind
|
||||||
|
// of an object.
|
||||||
|
Recognizes(version, kind string) bool
|
||||||
|
}
|
||||||
|
|
||||||
// ResourceVersioner provides methods for setting and retrieving
|
// ResourceVersioner provides methods for setting and retrieving
|
||||||
// the resource version from an API object.
|
// the resource version from an API object.
|
||||||
type ResourceVersioner interface {
|
type ResourceVersioner interface {
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -164,7 +165,15 @@ func (self *Scheme) runtimeObjectToRawExtensionArray(in *[]Object, out *[]RawExt
|
|||||||
for i := range src {
|
for i := range src {
|
||||||
switch t := src[i].(type) {
|
switch t := src[i].(type) {
|
||||||
case *Unknown:
|
case *Unknown:
|
||||||
|
// TODO: this should be decoupled from the scheme (since it is JSON specific)
|
||||||
dest[i].RawJSON = t.RawJSON
|
dest[i].RawJSON = t.RawJSON
|
||||||
|
case *Unstructured:
|
||||||
|
// TODO: this should be decoupled from the scheme (since it is JSON specific)
|
||||||
|
data, err := json.Marshal(t.Object)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dest[i].RawJSON = data
|
||||||
default:
|
default:
|
||||||
version := outVersion
|
version := outVersion
|
||||||
// if the object exists
|
// if the object exists
|
||||||
@ -192,24 +201,17 @@ func (self *Scheme) rawExtensionToRuntimeObjectArray(in *[]RawExtension, out *[]
|
|||||||
|
|
||||||
for i := range src {
|
for i := range src {
|
||||||
data := src[i].RawJSON
|
data := src[i].RawJSON
|
||||||
obj, err := scheme.Decode(data)
|
version, kind, err := scheme.raw.DataVersionAndKind(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !IsNotRegisteredError(err) {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
dest[i] = &Unknown{
|
||||||
version, kind, err := scheme.raw.DataVersionAndKind(data)
|
TypeMeta: TypeMeta{
|
||||||
if err != nil {
|
APIVersion: version,
|
||||||
return err
|
Kind: kind,
|
||||||
}
|
},
|
||||||
obj = &Unknown{
|
RawJSON: data,
|
||||||
TypeMeta: TypeMeta{
|
|
||||||
APIVersion: version,
|
|
||||||
Kind: kind,
|
|
||||||
},
|
|
||||||
RawJSON: data,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dest[i] = obj
|
|
||||||
}
|
}
|
||||||
*out = dest
|
*out = dest
|
||||||
return nil
|
return nil
|
||||||
@ -275,6 +277,12 @@ func (s *Scheme) ObjectVersionAndKind(obj Object) (version, kind string, err err
|
|||||||
return s.raw.ObjectVersionAndKind(obj)
|
return s.raw.ObjectVersionAndKind(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recognizes returns true if the scheme is able to handle the provided version and kind
|
||||||
|
// of an object.
|
||||||
|
func (s *Scheme) Recognizes(version, kind string) bool {
|
||||||
|
return s.raw.Recognizes(version, kind)
|
||||||
|
}
|
||||||
|
|
||||||
// New returns a new API object of the given version ("" for internal
|
// New returns a new API object of the given version ("" for internal
|
||||||
// representation) and name, or an error if it hasn't been registered.
|
// representation) and name, or an error if it hasn't been registered.
|
||||||
func (s *Scheme) New(versionName, typeName string) (Object, error) {
|
func (s *Scheme) New(versionName, typeName string) (Object, error) {
|
||||||
|
@ -116,3 +116,17 @@ type Unknown struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (*Unknown) IsAnAPIObject() {}
|
func (*Unknown) IsAnAPIObject() {}
|
||||||
|
|
||||||
|
// Unstructured allows objects that do not have Golang structs registered to be manipulated
|
||||||
|
// generically. This can be used to deal with the API objects from a plug-in. Unstructured
|
||||||
|
// objects still have functioning TypeMeta features-- kind, version, etc.
|
||||||
|
// TODO: Make this object have easy access to field based accessors and settors for
|
||||||
|
// metadata and field mutatation.
|
||||||
|
type Unstructured struct {
|
||||||
|
TypeMeta `json:",inline"`
|
||||||
|
// Object is a JSON compatible map with string, float, int, []interface{}, or map[string]interface{}
|
||||||
|
// children.
|
||||||
|
Object map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Unstructured) IsAnAPIObject() {}
|
||||||
|
89
pkg/runtime/unstructured.go
Normal file
89
pkg/runtime/unstructured.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 Google Inc. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnstructuredJSONScheme is capable of converting JSON data into the Unstructured
|
||||||
|
// type, which can be used for generic access to objects without a predefined scheme.
|
||||||
|
var UnstructuredJSONScheme ObjectDecoder = unstructuredJSONScheme{}
|
||||||
|
|
||||||
|
type unstructuredJSONScheme struct{}
|
||||||
|
|
||||||
|
// Recognizes returns true for any version or kind that is specified (internal
|
||||||
|
// versions are specifically excluded).
|
||||||
|
func (unstructuredJSONScheme) Recognizes(version, kind string) bool {
|
||||||
|
return len(version) > 0 && len(kind) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s unstructuredJSONScheme) Decode(data []byte) (Object, error) {
|
||||||
|
unstruct := &Unstructured{}
|
||||||
|
if err := s.DecodeInto(data, unstruct); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return unstruct, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (unstructuredJSONScheme) DecodeInto(data []byte, obj Object) error {
|
||||||
|
unstruct, ok := obj.(*Unstructured)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("the unstructured JSON scheme does not recognize %v", reflect.TypeOf(obj))
|
||||||
|
}
|
||||||
|
|
||||||
|
m := make(map[string]interface{})
|
||||||
|
if err := json.Unmarshal(data, &m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if v, ok := m["kind"]; ok {
|
||||||
|
if s, ok := v.(string); ok {
|
||||||
|
unstruct.Kind = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v, ok := m["apiVersion"]; ok {
|
||||||
|
if s, ok := v.(string); ok {
|
||||||
|
unstruct.APIVersion = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(unstruct.APIVersion) == 0 {
|
||||||
|
return conversion.NewMissingVersionErr(string(data))
|
||||||
|
}
|
||||||
|
if len(unstruct.Kind) == 0 {
|
||||||
|
return conversion.NewMissingKindErr(string(data))
|
||||||
|
}
|
||||||
|
unstruct.Object = m
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (unstructuredJSONScheme) DataVersionAndKind(data []byte) (version, kind string, err error) {
|
||||||
|
obj := TypeMeta{}
|
||||||
|
if err := json.Unmarshal(data, &obj); err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
if len(obj.APIVersion) == 0 {
|
||||||
|
return "", "", conversion.NewMissingVersionErr(string(data))
|
||||||
|
}
|
||||||
|
if len(obj.Kind) == 0 {
|
||||||
|
return "", "", conversion.NewMissingKindErr(string(data))
|
||||||
|
}
|
||||||
|
return obj.APIVersion, obj.Kind, nil
|
||||||
|
}
|
44
pkg/runtime/unstructured_test.go
Normal file
44
pkg/runtime/unstructured_test.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 Google Inc. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package runtime_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDecodeUnstructured(t *testing.T) {
|
||||||
|
pl := &api.List{
|
||||||
|
Items: []runtime.Object{
|
||||||
|
&api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}},
|
||||||
|
&runtime.Unknown{TypeMeta: runtime.TypeMeta{Kind: "Pod", APIVersion: "v1beta3"}, RawJSON: []byte(`{"kind":"Pod","apiVersion":"v1beta3","metadata":{"name":"test"}}`)},
|
||||||
|
&runtime.Unknown{TypeMeta: runtime.TypeMeta{Kind: "", APIVersion: "v1beta3"}, RawJSON: []byte(`{"kind":"Pod","apiVersion":"v1beta3","metadata":{"name":"test"}}`)},
|
||||||
|
&runtime.Unstructured{TypeMeta: runtime.TypeMeta{Kind: "Foo", APIVersion: "Bar"}, Object: map[string]interface{}{"test": "value"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if errs := runtime.DecodeList(pl.Items, runtime.UnstructuredJSONScheme); len(errs) == 1 {
|
||||||
|
t.Fatalf("unexpected error %v", errs)
|
||||||
|
}
|
||||||
|
if pod, ok := pl.Items[1].(*runtime.Unstructured); !ok || pod.Object["kind"] != "Pod" || pod.Object["metadata"].(map[string]interface{})["name"] != "test" {
|
||||||
|
t.Errorf("object not converted: %#v", pl.Items[1])
|
||||||
|
}
|
||||||
|
if _, ok := pl.Items[2].(*runtime.Unknown); !ok {
|
||||||
|
t.Errorf("object should not have been converted: %#v", pl.Items[2])
|
||||||
|
}
|
||||||
|
}
|
@ -153,7 +153,7 @@ func TestNewBuilder(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, item := range tests {
|
for _, item := range tests {
|
||||||
o := testclient.NewObjects(api.Scheme)
|
o := testclient.NewObjects(api.Scheme, api.Scheme)
|
||||||
o.Add(item.pv)
|
o.Add(item.pv)
|
||||||
o.Add(item.claim)
|
o.Add(item.claim)
|
||||||
client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)}
|
client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)}
|
||||||
@ -213,7 +213,7 @@ func TestNewBuilderClaimNotBound(t *testing.T) {
|
|||||||
ClaimName: "claimC",
|
ClaimName: "claimC",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
o := testclient.NewObjects(api.Scheme)
|
o := testclient.NewObjects(api.Scheme, api.Scheme)
|
||||||
o.Add(pv)
|
o.Add(pv)
|
||||||
o.Add(claim)
|
o.Add(claim)
|
||||||
client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)}
|
client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)}
|
||||||
|
@ -29,7 +29,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestRunStop(t *testing.T) {
|
func TestRunStop(t *testing.T) {
|
||||||
o := testclient.NewObjects(api.Scheme)
|
o := testclient.NewObjects(api.Scheme, api.Scheme)
|
||||||
client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)}
|
client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)}
|
||||||
binder := NewPersistentVolumeClaimBinder(client, 1*time.Second)
|
binder := NewPersistentVolumeClaimBinder(client, 1*time.Second)
|
||||||
|
|
||||||
@ -111,8 +111,8 @@ func TestExampleObjects(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for name, scenario := range scenarios {
|
for name, scenario := range scenarios {
|
||||||
o := testclient.NewObjects(api.Scheme)
|
o := testclient.NewObjects(api.Scheme, api.Scheme)
|
||||||
if err := testclient.AddObjectsFromPath("../../examples/persistent-volumes/"+name, o); err != nil {
|
if err := testclient.AddObjectsFromPath("../../examples/persistent-volumes/"+name, o, api.Scheme); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,11 +168,11 @@ func TestExampleObjects(t *testing.T) {
|
|||||||
|
|
||||||
func TestBindingWithExamples(t *testing.T) {
|
func TestBindingWithExamples(t *testing.T) {
|
||||||
api.ForTesting_ReferencesAllowBlankSelfLinks = true
|
api.ForTesting_ReferencesAllowBlankSelfLinks = true
|
||||||
o := testclient.NewObjects(api.Scheme)
|
o := testclient.NewObjects(api.Scheme, api.Scheme)
|
||||||
if err := testclient.AddObjectsFromPath("../../examples/persistent-volumes/claims/claim-01.yaml", o); err != nil {
|
if err := testclient.AddObjectsFromPath("../../examples/persistent-volumes/claims/claim-01.yaml", o, api.Scheme); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := testclient.AddObjectsFromPath("../../examples/persistent-volumes/volumes/local-01.yaml", o); err != nil {
|
if err := testclient.AddObjectsFromPath("../../examples/persistent-volumes/volumes/local-01.yaml", o, api.Scheme); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user