mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-11 06:02:18 +00:00
Make runtime less global for Codec
* Make Codec separate from Scheme * Move EncodeOrDie off Scheme to take a Codec * Make Copy work without a Codec * Create a "latest" package that imports all versions and sets global defaults for "most recent encoding" * v1beta1 is the current "latest", v1beta2 exists * Kill DefaultCodec, replace it with "latest.Codec" * This updates the client and etcd to store the latest known version * EmbeddedObject is per schema and per package now * Move runtime.DefaultScheme to api.Scheme * Split out WatchEvent since it's not an API object today, treat it like a special object in api * Kill DefaultResourceVersioner, instead place it on "latest" (as the package that understands all packages) * Move objDiff to runtime.ObjectDiff
This commit is contained in:
@@ -20,42 +20,80 @@ import (
|
||||
"gopkg.in/v1/yaml"
|
||||
)
|
||||
|
||||
// EmbeddedObject must have an appropriate encoder and decoder functions, such that on the
|
||||
// wire, it's stored as a []byte, but in memory, the contained object is accessable as an
|
||||
// Object via the Get() function. Only valid API objects may be stored via EmbeddedObject.
|
||||
// The purpose of this is to allow an API object of type known only at runtime to be
|
||||
// embedded within other API objects.
|
||||
//
|
||||
// Define a Codec variable in your package and import the runtime package and
|
||||
// then use the commented section below
|
||||
|
||||
/*
|
||||
// EmbeddedObject implements a Codec specific version of an
|
||||
// embedded object.
|
||||
type EmbeddedObject struct {
|
||||
runtime.Object
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||
func (a *EmbeddedObject) UnmarshalJSON(b []byte) error {
|
||||
obj, err := runtime.CodecUnmarshalJSON(Codec, b)
|
||||
a.Object = obj
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (a EmbeddedObject) MarshalJSON() ([]byte, error) {
|
||||
return runtime.CodecMarshalJSON(Codec, a.Object)
|
||||
}
|
||||
|
||||
// SetYAML implements the yaml.Setter interface.
|
||||
func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
|
||||
obj, ok := runtime.CodecSetYAML(Codec, tag, value)
|
||||
a.Object = obj
|
||||
return ok
|
||||
}
|
||||
|
||||
// GetYAML implements the yaml.Getter interface.
|
||||
func (a EmbeddedObject) GetYAML() (tag string, value interface{}) {
|
||||
return runtime.CodecGetYAML(Codec, a.Object)
|
||||
}
|
||||
*/
|
||||
|
||||
// Encode()/Decode() are the canonical way of converting an API object to/from
|
||||
// wire format. This file provides utility functions which permit doing so
|
||||
// recursively, such that API objects of types known only at run time can be
|
||||
// embedded within other API types.
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||
func (a *EmbeddedObject) UnmarshalJSON(b []byte) error {
|
||||
func CodecUnmarshalJSON(codec Codec, b []byte) (Object, error) {
|
||||
// Handle JSON's "null": Decode() doesn't expect it.
|
||||
if len(b) == 4 && string(b) == "null" {
|
||||
a.Object = nil
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
obj, err := DefaultCodec.Decode(b)
|
||||
obj, err := codec.Decode(b)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
a.Object = obj
|
||||
return nil
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (a EmbeddedObject) MarshalJSON() ([]byte, error) {
|
||||
if a.Object == nil {
|
||||
func CodecMarshalJSON(codec Codec, obj Object) ([]byte, error) {
|
||||
if obj == nil {
|
||||
// Encode unset/nil objects as JSON's "null".
|
||||
return []byte("null"), nil
|
||||
}
|
||||
|
||||
return DefaultCodec.Encode(a.Object)
|
||||
return codec.Encode(obj)
|
||||
}
|
||||
|
||||
// SetYAML implements the yaml.Setter interface.
|
||||
func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
|
||||
func CodecSetYAML(codec Codec, tag string, value interface{}) (Object, bool) {
|
||||
if value == nil {
|
||||
a.Object = nil
|
||||
return true
|
||||
return nil, true
|
||||
}
|
||||
// Why does the yaml package send value as a map[interface{}]interface{}?
|
||||
// It's especially frustrating because encoding/json does the right thing
|
||||
@@ -67,22 +105,21 @@ func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
|
||||
if err != nil {
|
||||
panic("yaml can't reverse its own object")
|
||||
}
|
||||
obj, err := DefaultCodec.Decode(b)
|
||||
obj, err := codec.Decode(b)
|
||||
if err != nil {
|
||||
return false
|
||||
return nil, false
|
||||
}
|
||||
a.Object = obj
|
||||
return true
|
||||
return obj, true
|
||||
}
|
||||
|
||||
// GetYAML implements the yaml.Getter interface.
|
||||
func (a EmbeddedObject) GetYAML() (tag string, value interface{}) {
|
||||
if a.Object == nil {
|
||||
func CodecGetYAML(codec Codec, obj Object) (tag string, value interface{}) {
|
||||
if obj == nil {
|
||||
value = "null"
|
||||
return
|
||||
}
|
||||
// Encode returns JSON, which is conveniently a subset of YAML.
|
||||
v, err := DefaultCodec.Encode(a.Object)
|
||||
v, err := codec.Encode(obj)
|
||||
if err != nil {
|
||||
panic("impossible to encode API object!")
|
||||
}
|
||||
|
@@ -14,38 +14,72 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package runtime
|
||||
package runtime_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
var Codec = runtime.CodecFor(scheme, "v1test")
|
||||
|
||||
// EmbeddedObject implements a Codec specific version of an
|
||||
// embedded object.
|
||||
type EmbeddedObject struct {
|
||||
runtime.Object
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||
func (a *EmbeddedObject) UnmarshalJSON(b []byte) error {
|
||||
obj, err := runtime.CodecUnmarshalJSON(Codec, b)
|
||||
a.Object = obj
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (a EmbeddedObject) MarshalJSON() ([]byte, error) {
|
||||
return runtime.CodecMarshalJSON(Codec, a.Object)
|
||||
}
|
||||
|
||||
// SetYAML implements the yaml.Setter interface.
|
||||
func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
|
||||
obj, ok := runtime.CodecSetYAML(Codec, tag, value)
|
||||
a.Object = obj
|
||||
return ok
|
||||
}
|
||||
|
||||
// GetYAML implements the yaml.Getter interface.
|
||||
func (a EmbeddedObject) GetYAML() (tag string, value interface{}) {
|
||||
return runtime.CodecGetYAML(Codec, a.Object)
|
||||
}
|
||||
|
||||
type EmbeddedTest struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
Object EmbeddedObject `yaml:"object,omitempty" json:"object,omitempty"`
|
||||
EmptyObject EmbeddedObject `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"`
|
||||
runtime.JSONBase `yaml:",inline" json:",inline"`
|
||||
Object EmbeddedObject `yaml:"object,omitempty" json:"object,omitempty"`
|
||||
EmptyObject EmbeddedObject `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"`
|
||||
}
|
||||
|
||||
func (*EmbeddedTest) IsAnAPIObject() {}
|
||||
|
||||
func TestEmbeddedObject(t *testing.T) {
|
||||
// TODO(dbsmith) fix EmbeddedObject to not use DefaultScheme.
|
||||
s := DefaultScheme
|
||||
s := scheme
|
||||
s.AddKnownTypes("", &EmbeddedTest{})
|
||||
s.AddKnownTypes("v1beta1", &EmbeddedTest{})
|
||||
s.AddKnownTypes("v1test", &EmbeddedTest{})
|
||||
|
||||
outer := &EmbeddedTest{
|
||||
JSONBase: JSONBase{ID: "outer"},
|
||||
JSONBase: runtime.JSONBase{ID: "outer"},
|
||||
Object: EmbeddedObject{
|
||||
&EmbeddedTest{
|
||||
JSONBase: JSONBase{ID: "inner"},
|
||||
JSONBase: runtime.JSONBase{ID: "inner"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
wire, err := s.Encode(outer)
|
||||
wire, err := s.EncodeToVersion(outer, "v1test")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected encode error '%v'", err)
|
||||
}
|
||||
|
@@ -16,13 +16,23 @@ limitations under the License.
|
||||
|
||||
package runtime
|
||||
|
||||
// Codec defines methods for serializing and deserializing API objects.
|
||||
type Codec interface {
|
||||
Encode(obj Object) (data []byte, err error)
|
||||
// Decoder defines methods for deserializing API objects into a given type
|
||||
type Decoder interface {
|
||||
Decode(data []byte) (Object, error)
|
||||
DecodeInto(data []byte, obj Object) error
|
||||
}
|
||||
|
||||
// Encoder defines methods for serializing API objects into bytes
|
||||
type Encoder interface {
|
||||
Encode(obj Object) (data []byte, err error)
|
||||
}
|
||||
|
||||
// Codec defines methods for serializing and deserializing API objects.
|
||||
type Codec interface {
|
||||
Decoder
|
||||
Encoder
|
||||
}
|
||||
|
||||
// ResourceVersioner provides methods for setting and retrieving
|
||||
// the resource version from an API object.
|
||||
type ResourceVersioner interface {
|
||||
|
@@ -17,16 +17,40 @@ limitations under the License.
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"gopkg.in/v1/yaml"
|
||||
)
|
||||
|
||||
var DefaultResourceVersioner ResourceVersioner = NewJSONBaseResourceVersioner()
|
||||
var DefaultScheme = NewScheme("", "v1beta1")
|
||||
var DefaultCodec Codec = DefaultScheme
|
||||
// codecWrapper implements encoding to an alternative
|
||||
// default version for a scheme.
|
||||
type codecWrapper struct {
|
||||
*Scheme
|
||||
version string
|
||||
}
|
||||
|
||||
// Encode implements Codec
|
||||
func (c *codecWrapper) Encode(obj Object) ([]byte, error) {
|
||||
return c.Scheme.EncodeToVersion(obj, c.version)
|
||||
}
|
||||
|
||||
// CodecFor returns a Codec that invokes Encode with the provided version.
|
||||
func CodecFor(scheme *Scheme, version string) Codec {
|
||||
return &codecWrapper{scheme, version}
|
||||
}
|
||||
|
||||
// EncodeOrDie is a version of Encode which will panic instead of returning an error. For tests.
|
||||
func EncodeOrDie(codec Codec, obj Object) string {
|
||||
bytes, err := codec.Encode(obj)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
// Scheme defines methods for serializing and deserializing API objects. It
|
||||
// is an adaptation of conversion's Scheme for our API objects.
|
||||
@@ -36,21 +60,13 @@ type Scheme struct {
|
||||
|
||||
// fromScope gets the input version, desired output version, and desired Scheme
|
||||
// from a conversion.Scope.
|
||||
func fromScope(s conversion.Scope) (inVersion, outVersion string, scheme *Scheme) {
|
||||
scheme = DefaultScheme
|
||||
func (self *Scheme) fromScope(s conversion.Scope) (inVersion, outVersion string, scheme *Scheme) {
|
||||
scheme = self
|
||||
inVersion = s.Meta().SrcVersion
|
||||
outVersion = s.Meta().DestVersion
|
||||
return inVersion, outVersion, scheme
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Set up a generic mapping between RawExtension and EmbeddedObject.
|
||||
DefaultScheme.AddConversionFuncs(
|
||||
embeddedObjectToRawExtension,
|
||||
rawExtensionToEmbeddedObject,
|
||||
)
|
||||
}
|
||||
|
||||
// emptyPlugin is used to copy the Kind field to and from plugin objects.
|
||||
type emptyPlugin struct {
|
||||
PluginBase `json:",inline" yaml:",inline"`
|
||||
@@ -59,14 +75,14 @@ type emptyPlugin struct {
|
||||
// embeddedObjectToRawExtension does the conversion you would expect from the name, using the information
|
||||
// given in conversion.Scope. It's placed in the DefaultScheme as a ConversionFunc to enable plugins;
|
||||
// see the comment for RawExtension.
|
||||
func embeddedObjectToRawExtension(in *EmbeddedObject, out *RawExtension, s conversion.Scope) error {
|
||||
func (self *Scheme) embeddedObjectToRawExtension(in *EmbeddedObject, out *RawExtension, s conversion.Scope) error {
|
||||
if in.Object == nil {
|
||||
out.RawJSON = []byte("null")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Figure out the type and kind of the output object.
|
||||
_, outVersion, scheme := fromScope(s)
|
||||
_, outVersion, scheme := self.fromScope(s)
|
||||
_, kind, err := scheme.raw.ObjectVersionAndKind(in.Object)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -107,13 +123,13 @@ func embeddedObjectToRawExtension(in *EmbeddedObject, out *RawExtension, s conve
|
||||
// rawExtensionToEmbeddedObject does the conversion you would expect from the name, using the information
|
||||
// given in conversion.Scope. It's placed in the DefaultScheme as a ConversionFunc to enable plugins;
|
||||
// see the comment for RawExtension.
|
||||
func rawExtensionToEmbeddedObject(in *RawExtension, out *EmbeddedObject, s conversion.Scope) error {
|
||||
func (self *Scheme) rawExtensionToEmbeddedObject(in *RawExtension, out *EmbeddedObject, s conversion.Scope) error {
|
||||
if len(in.RawJSON) == 4 && string(in.RawJSON) == "null" {
|
||||
out.Object = nil
|
||||
return nil
|
||||
}
|
||||
// Figure out the type and kind of the output object.
|
||||
inVersion, outVersion, scheme := fromScope(s)
|
||||
inVersion, outVersion, scheme := self.fromScope(s)
|
||||
_, kind, err := scheme.raw.DataVersionAndKind(in.RawJSON)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -153,13 +169,15 @@ func rawExtensionToEmbeddedObject(in *RawExtension, out *EmbeddedObject, s conve
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewScheme creates a new Scheme. A default scheme is provided and accessible
|
||||
// as the "DefaultScheme" variable.
|
||||
func NewScheme(internalVersion, externalVersion string) *Scheme {
|
||||
// NewScheme creates a new Scheme. This scheme is pluggable by default.
|
||||
func NewScheme() *Scheme {
|
||||
s := &Scheme{conversion.NewScheme()}
|
||||
s.raw.InternalVersion = internalVersion
|
||||
s.raw.ExternalVersion = externalVersion
|
||||
s.raw.InternalVersion = ""
|
||||
s.raw.MetaInsertionFactory = metaInsertion{}
|
||||
s.raw.AddConversionFuncs(
|
||||
s.embeddedObjectToRawExtension,
|
||||
s.rawExtensionToEmbeddedObject,
|
||||
)
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -180,6 +198,10 @@ func (s *Scheme) AddKnownTypeWithName(version, kind string, obj Object) {
|
||||
s.raw.AddKnownTypeWithName(version, kind, obj)
|
||||
}
|
||||
|
||||
func (s *Scheme) KnownTypes(version string) map[string]reflect.Type {
|
||||
return s.raw.KnownTypes(version)
|
||||
}
|
||||
|
||||
// New returns a new API object of the given version ("" for internal
|
||||
// representation) and name, or an error if it hasn't been registered.
|
||||
func (s *Scheme) New(versionName, typeName string) (Object, error) {
|
||||
@@ -236,12 +258,7 @@ func FindJSONBase(obj Object) (JSONBaseInterface, error) {
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// EncodeOrDie is a version of Encode which will panic instead of returning an error. For tests.
|
||||
func (s *Scheme) EncodeOrDie(obj Object) string {
|
||||
return s.raw.EncodeOrDie(obj)
|
||||
}
|
||||
|
||||
// Encode turns the given api object into an appropriate JSON string.
|
||||
// EncodeToVersion turns the given api object into an appropriate JSON string.
|
||||
// Will return an error if the object doesn't have an embedded JSONBase.
|
||||
// Obj may be a pointer to a struct, or a struct. If a struct, a copy
|
||||
// must be made. If a pointer, the object may be modified before encoding,
|
||||
@@ -269,17 +286,6 @@ func (s *Scheme) EncodeOrDie(obj Object) string {
|
||||
// change the memory format yet not break compatibility with any stored
|
||||
// objects, whether they be in our storage layer (e.g., etcd), or in user's
|
||||
// config files.
|
||||
//
|
||||
// TODO/next steps: When we add our second versioned type, this package will
|
||||
// need a version of Encode that lets you choose the wire version. A configurable
|
||||
// default will be needed, to allow operating in clusters that haven't yet
|
||||
// upgraded.
|
||||
//
|
||||
func (s *Scheme) Encode(obj Object) (data []byte, err error) {
|
||||
return s.raw.Encode(obj)
|
||||
}
|
||||
|
||||
// EncodeToVersion is like Encode, but lets you specify the destination version.
|
||||
func (s *Scheme) EncodeToVersion(obj Object, destVersion string) (data []byte, err error) {
|
||||
return s.raw.EncodeToVersion(obj, destVersion)
|
||||
}
|
||||
@@ -332,10 +338,10 @@ func (s *Scheme) DecodeInto(data []byte, obj Object) error {
|
||||
return s.raw.DecodeInto(data, obj)
|
||||
}
|
||||
|
||||
// Does a deep copy of an API object. Useful mostly for tests.
|
||||
// Copy does a deep copy of an API object. Useful mostly for tests.
|
||||
// TODO(dbsmith): implement directly instead of via Encode/Decode
|
||||
func (s *Scheme) Copy(obj Object) (Object, error) {
|
||||
data, err := s.Encode(obj)
|
||||
data, err := s.EncodeToVersion(obj, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -350,6 +356,26 @@ func (s *Scheme) CopyOrDie(obj Object) Object {
|
||||
return newObj
|
||||
}
|
||||
|
||||
func ObjectDiff(a, b Object) string {
|
||||
ab, err := json.Marshal(a)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("a: %v", err))
|
||||
}
|
||||
bb, err := json.Marshal(b)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("b: %v", err))
|
||||
}
|
||||
return util.StringDiff(string(ab), string(bb))
|
||||
|
||||
// An alternate diff attempt, in case json isn't showing you
|
||||
// the difference. (reflect.DeepEqual makes a distinction between
|
||||
// nil and empty slices, for example.)
|
||||
return util.StringDiff(
|
||||
fmt.Sprintf("%#v", a),
|
||||
fmt.Sprintf("%#v", b),
|
||||
)
|
||||
}
|
||||
|
||||
// metaInsertion implements conversion.MetaInsertionFactory, which lets the conversion
|
||||
// package figure out how to encode our object's types and versions. These fields are
|
||||
// located in our JSONBase.
|
||||
|
@@ -43,14 +43,15 @@ func (*InternalSimple) IsAnAPIObject() {}
|
||||
func (*ExternalSimple) IsAnAPIObject() {}
|
||||
|
||||
func TestScheme(t *testing.T) {
|
||||
runtime.DefaultScheme.AddKnownTypeWithName("", "Simple", &InternalSimple{})
|
||||
runtime.DefaultScheme.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{})
|
||||
scheme := runtime.NewScheme()
|
||||
scheme.AddKnownTypeWithName("", "Simple", &InternalSimple{})
|
||||
scheme.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{})
|
||||
|
||||
internalToExternalCalls := 0
|
||||
externalToInternalCalls := 0
|
||||
|
||||
// Register functions to verify that scope.Meta() gets set correctly.
|
||||
err := runtime.DefaultScheme.AddConversionFuncs(
|
||||
err := scheme.AddConversionFuncs(
|
||||
func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error {
|
||||
if e, a := "", scope.Meta().SrcVersion; e != a {
|
||||
t.Errorf("Expected '%v', got '%v'", e, a)
|
||||
@@ -85,10 +86,10 @@ func TestScheme(t *testing.T) {
|
||||
|
||||
// Test Encode, Decode, and DecodeInto
|
||||
obj := runtime.Object(simple)
|
||||
data, err := runtime.DefaultScheme.EncodeToVersion(obj, "externalVersion")
|
||||
obj2, err2 := runtime.DefaultScheme.Decode(data)
|
||||
data, err := scheme.EncodeToVersion(obj, "externalVersion")
|
||||
obj2, err2 := scheme.Decode(data)
|
||||
obj3 := &InternalSimple{}
|
||||
err3 := runtime.DefaultScheme.DecodeInto(data, obj3)
|
||||
err3 := scheme.DecodeInto(data, obj3)
|
||||
if err != nil || err2 != nil {
|
||||
t.Fatalf("Failure: '%v' '%v' '%v'", err, err2, err3)
|
||||
}
|
||||
@@ -104,7 +105,7 @@ func TestScheme(t *testing.T) {
|
||||
|
||||
// Test Convert
|
||||
external := &ExternalSimple{}
|
||||
err = runtime.DefaultScheme.Convert(simple, external)
|
||||
err = scheme.Convert(simple, external)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
@@ -123,12 +124,13 @@ func TestScheme(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBadJSONRejection(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
badJSONMissingKind := []byte(`{ }`)
|
||||
if _, err := runtime.DefaultScheme.Decode(badJSONMissingKind); err == nil {
|
||||
if _, err := scheme.Decode(badJSONMissingKind); err == nil {
|
||||
t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind)
|
||||
}
|
||||
badJSONUnknownType := []byte(`{"kind": "bar"}`)
|
||||
if _, err1 := runtime.DefaultScheme.Decode(badJSONUnknownType); err1 == nil {
|
||||
if _, err1 := scheme.Decode(badJSONUnknownType); err1 == nil {
|
||||
t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType)
|
||||
}
|
||||
/*badJSONKindMismatch := []byte(`{"kind": "Pod"}`)
|
||||
@@ -163,12 +165,13 @@ func (*ExternalExtensionType) IsAnAPIObject() {}
|
||||
func (*InternalExtensionType) IsAnAPIObject() {}
|
||||
|
||||
func TestExtensionMapping(t *testing.T) {
|
||||
runtime.DefaultScheme.AddKnownTypeWithName("", "ExtensionType", &InternalExtensionType{})
|
||||
runtime.DefaultScheme.AddKnownTypeWithName("", "A", &ExtensionA{})
|
||||
runtime.DefaultScheme.AddKnownTypeWithName("", "B", &ExtensionB{})
|
||||
runtime.DefaultScheme.AddKnownTypeWithName("testExternal", "ExtensionType", &ExternalExtensionType{})
|
||||
runtime.DefaultScheme.AddKnownTypeWithName("testExternal", "A", &ExtensionA{})
|
||||
runtime.DefaultScheme.AddKnownTypeWithName("testExternal", "B", &ExtensionB{})
|
||||
scheme := runtime.NewScheme()
|
||||
scheme.AddKnownTypeWithName("", "ExtensionType", &InternalExtensionType{})
|
||||
scheme.AddKnownTypeWithName("", "A", &ExtensionA{})
|
||||
scheme.AddKnownTypeWithName("", "B", &ExtensionB{})
|
||||
scheme.AddKnownTypeWithName("testExternal", "ExtensionType", &ExternalExtensionType{})
|
||||
scheme.AddKnownTypeWithName("testExternal", "A", &ExtensionA{})
|
||||
scheme.AddKnownTypeWithName("testExternal", "B", &ExtensionB{})
|
||||
|
||||
table := []struct {
|
||||
obj runtime.Object
|
||||
@@ -187,14 +190,14 @@ func TestExtensionMapping(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, item := range table {
|
||||
gotEncoded, err := runtime.DefaultScheme.EncodeToVersion(item.obj, "testExternal")
|
||||
gotEncoded, err := scheme.EncodeToVersion(item.obj, "testExternal")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error '%v' (%#v)", err, item.obj)
|
||||
} else if e, a := item.encoded, string(gotEncoded); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
gotDecoded, err := runtime.DefaultScheme.Decode([]byte(item.encoded))
|
||||
gotDecoded, err := scheme.Decode([]byte(item.encoded))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error '%v' (%v)", err, item.encoded)
|
||||
} else if e, a := item.obj, gotDecoded; !reflect.DeepEqual(e, a) {
|
||||
@@ -209,3 +212,25 @@ func TestExtensionMapping(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncode(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
scheme.AddKnownTypeWithName("", "Simple", &InternalSimple{})
|
||||
scheme.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{})
|
||||
codec := runtime.CodecFor(scheme, "externalVersion")
|
||||
test := &InternalSimple{
|
||||
TestString: "I'm the same",
|
||||
}
|
||||
obj := runtime.Object(test)
|
||||
data, err := codec.Encode(obj)
|
||||
obj2, err2 := codec.Decode(data)
|
||||
if err != nil || err2 != nil {
|
||||
t.Fatalf("Failure: '%v' '%v'", err, err2)
|
||||
}
|
||||
if _, ok := obj2.(*InternalSimple); !ok {
|
||||
t.Fatalf("Got wrong type")
|
||||
}
|
||||
if !reflect.DeepEqual(obj2, test) {
|
||||
t.Errorf("Expected:\n %#v,\n Got:\n %#v", &test, obj2)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user