mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-12 20:57:20 +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:
@@ -25,14 +25,14 @@ import (
|
||||
// Decode converts a YAML or JSON string back into a pointer to an api object.
|
||||
// Deduces the type based upon the fields added by the MetaInsertionFactory
|
||||
// technique. The object will be converted, if necessary, into the
|
||||
// s.InternalVersion type before being returned. Decode will refuse to decode
|
||||
// objects without a version, because that's probably an error.
|
||||
// s.InternalVersion type before being returned. Decode will not decode
|
||||
// objects without version set unless InternalVersion is also "".
|
||||
func (s *Scheme) Decode(data []byte) (interface{}, error) {
|
||||
version, kind, err := s.DataVersionAndKind(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if version == "" {
|
||||
if version == "" && s.InternalVersion != "" {
|
||||
return nil, fmt.Errorf("version not set in '%s'", string(data))
|
||||
}
|
||||
obj, err := s.NewObject(version, kind)
|
||||
|
@@ -21,16 +21,7 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// EncodeOrDie is a version of Encode which will panic instead of returning an error. For tests.
|
||||
func (s *Scheme) EncodeOrDie(obj interface{}) string {
|
||||
bytes, err := s.Encode(obj)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
// Encode turns the given api object into an appropriate JSON string.
|
||||
// EncodeToVersion turns the given api object into an appropriate JSON string.
|
||||
// Obj may be a pointer to a struct, or a struct. If a struct, a copy
|
||||
// will be made, therefore it's recommended to pass a pointer to a
|
||||
// struct. The type must have been registered.
|
||||
@@ -58,11 +49,6 @@ func (s *Scheme) EncodeOrDie(obj interface{}) string {
|
||||
// objects, whether they be in our storage layer (e.g., etcd), or in user's
|
||||
// config files.
|
||||
//
|
||||
func (s *Scheme) Encode(obj interface{}) (data []byte, err error) {
|
||||
return s.EncodeToVersion(obj, s.ExternalVersion)
|
||||
}
|
||||
|
||||
// EncodeToVersion is like Encode, but you may choose the version.
|
||||
func (s *Scheme) EncodeToVersion(obj interface{}, destVersion string) (data []byte, err error) {
|
||||
obj = maybeCopy(obj)
|
||||
v, _ := enforcePtr(obj) // maybeCopy guarantees a pointer
|
||||
|
@@ -66,9 +66,6 @@ type Scheme struct {
|
||||
// you use "" for the internal version.
|
||||
InternalVersion string
|
||||
|
||||
// ExternalVersion is the default external version.
|
||||
ExternalVersion string
|
||||
|
||||
// MetaInsertionFactory is used to create an object to store and retrieve
|
||||
// the version and kind information for all objects. The default uses the
|
||||
// keys "version" and "kind" respectively.
|
||||
@@ -83,7 +80,6 @@ func NewScheme() *Scheme {
|
||||
typeToKind: map[reflect.Type]string{},
|
||||
converter: NewConverter(),
|
||||
InternalVersion: "",
|
||||
ExternalVersion: "v1",
|
||||
MetaInsertionFactory: metaInsertion{},
|
||||
}
|
||||
s.converter.NameFunc = s.nameFunc
|
||||
@@ -146,6 +142,19 @@ func (s *Scheme) AddKnownTypeWithName(version, kind string, obj interface{}) {
|
||||
s.typeToKind[t] = kind
|
||||
}
|
||||
|
||||
// KnownTypes returns an array of the types that are known for a particular version.
|
||||
func (s *Scheme) KnownTypes(version string) map[string]reflect.Type {
|
||||
all, ok := s.versionMap[version]
|
||||
if !ok {
|
||||
return map[string]reflect.Type{}
|
||||
}
|
||||
types := make(map[string]reflect.Type)
|
||||
for k, v := range all {
|
||||
types[k] = v
|
||||
}
|
||||
return types
|
||||
}
|
||||
|
||||
// NewObject returns a new object of the given version and name,
|
||||
// or an error if it hasn't been registered.
|
||||
func (s *Scheme) NewObject(versionName, typeName string) (interface{}, error) {
|
||||
|
@@ -125,7 +125,6 @@ func GetTestScheme() *Scheme {
|
||||
s.AddKnownTypes("v1", &ExternalInternalSame{})
|
||||
s.AddKnownTypeWithName("v1", "TestType1", &ExternalTestType1{})
|
||||
s.AddKnownTypeWithName("v1", "TestType2", &ExternalTestType2{})
|
||||
s.ExternalVersion = "v1"
|
||||
s.InternalVersion = ""
|
||||
s.MetaInsertionFactory = testMetaInsertionFactory{}
|
||||
return s
|
||||
@@ -178,7 +177,7 @@ func runTest(t *testing.T, source interface{}) {
|
||||
TestObjectFuzzer.Fuzz(source)
|
||||
|
||||
s := GetTestScheme()
|
||||
data, err := s.Encode(source)
|
||||
data, err := s.EncodeToVersion(source, "v1")
|
||||
if err != nil {
|
||||
t.Errorf("%v: %v (%#v)", name, err, source)
|
||||
return
|
||||
@@ -221,7 +220,7 @@ func TestEncode_NonPtr(t *testing.T) {
|
||||
s := GetTestScheme()
|
||||
tt := TestType1{A: "I'm not a pointer object"}
|
||||
obj := interface{}(tt)
|
||||
data, err := s.Encode(obj)
|
||||
data, err := s.EncodeToVersion(obj, "v1")
|
||||
obj2, err2 := s.Decode(data)
|
||||
if err != nil || err2 != nil {
|
||||
t.Fatalf("Failure: '%v' '%v'", err, err2)
|
||||
@@ -238,7 +237,7 @@ func TestEncode_Ptr(t *testing.T) {
|
||||
s := GetTestScheme()
|
||||
tt := &TestType1{A: "I am a pointer object"}
|
||||
obj := interface{}(tt)
|
||||
data, err := s.Encode(obj)
|
||||
data, err := s.EncodeToVersion(obj, "v1")
|
||||
obj2, err2 := s.Decode(data)
|
||||
if err != nil || err2 != nil {
|
||||
t.Fatalf("Failure: '%v' '%v'", err, err2)
|
||||
@@ -255,7 +254,6 @@ func TestBadJSONRejection(t *testing.T) {
|
||||
s := GetTestScheme()
|
||||
badJSONs := [][]byte{
|
||||
[]byte(`{"myVersionKey":"v1"}`), // Missing kind
|
||||
[]byte(`{"myKindKey":"TestType1"}`), // Missing version
|
||||
[]byte(`{"myVersionKey":"v1","myKindKey":"bar"}`), // Unknown kind
|
||||
[]byte(`{"myVersionKey":"bar","myKindKey":"TestType1"}`), // Unknown version
|
||||
}
|
||||
@@ -270,6 +268,23 @@ func TestBadJSONRejection(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadJSONRejectionForSetInternalVersion(t *testing.T) {
|
||||
s := GetTestScheme()
|
||||
s.InternalVersion = "v1"
|
||||
badJSONs := [][]byte{
|
||||
[]byte(`{"myKindKey":"TestType1"}`), // Missing version
|
||||
}
|
||||
for _, b := range badJSONs {
|
||||
if _, err := s.Decode(b); err == nil {
|
||||
t.Errorf("Did not reject bad json: %s", string(b))
|
||||
}
|
||||
}
|
||||
badJSONKindMismatch := []byte(`{"myVersionKey":"v1","myKindKey":"ExternalInternalSame"}`)
|
||||
if err := s.DecodeInto(badJSONKindMismatch, &TestType1{}); err == nil {
|
||||
t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetaValues(t *testing.T) {
|
||||
type InternalSimple struct {
|
||||
Version string `json:"version,omitempty" yaml:"version,omitempty"`
|
||||
@@ -283,7 +298,6 @@ func TestMetaValues(t *testing.T) {
|
||||
}
|
||||
s := NewScheme()
|
||||
s.InternalVersion = ""
|
||||
s.ExternalVersion = "externalVersion"
|
||||
s.AddKnownTypeWithName("", "Simple", &InternalSimple{})
|
||||
s.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{})
|
||||
|
||||
@@ -373,7 +387,6 @@ func TestMetaValuesUnregisteredConvert(t *testing.T) {
|
||||
}
|
||||
s := NewScheme()
|
||||
s.InternalVersion = ""
|
||||
s.ExternalVersion = "externalVersion"
|
||||
// We deliberately don't register the types.
|
||||
|
||||
internalToExternalCalls := 0
|
||||
|
Reference in New Issue
Block a user