Simplify Codec and split responsibilities

Break Codec into two general purpose interfaces, Encoder and Decoder,
and move parameter codec responsibilities to ParameterCodec.

Make unversioned types explicit when registering - these types go
through conversion without modification.

Switch to use "__internal" instead of "" to represent the internal
version. Future commits will also add group defaulting (so that "" is
expanded internally into a known group version, and only cleared during
set).

For embedded types like runtime.Object -> runtime.RawExtension, put the
responsibility on the caller of Decode/Encode to handle transformation
into destination serialization. Future commits will expand RawExtension
and Unknown to accept a content encoding as well as bytes.

Make Unknown a bit more powerful and use it to carry unrecognized types.
This commit is contained in:
Clayton Coleman
2015-12-21 00:08:33 -05:00
parent 6582b4c2ea
commit 63a7a41ddf
17 changed files with 798 additions and 723 deletions

View File

@@ -18,9 +18,7 @@ package runtime
import (
"encoding/json"
"fmt"
"net/url"
"reflect"
"io"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/conversion"
@@ -28,36 +26,19 @@ import (
// 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{}
// TODO: move into serializer/json.
var UnstructuredJSONScheme Decoder = unstructuredJSONScheme{}
type unstructuredJSONScheme struct{}
var _ Decoder = unstructuredJSONScheme{}
var _ ObjectDecoder = unstructuredJSONScheme{}
var _ Codec = unstructuredJSONScheme{}
// Recognizes returns true for any version or kind that is specified (internal
// versions are specifically excluded).
func (unstructuredJSONScheme) Recognizes(gvk unversioned.GroupVersionKind) bool {
return !gvk.GroupVersion().IsEmpty() && len(gvk.Kind) > 0
}
func (s unstructuredJSONScheme) Decode(data []byte) (Object, error) {
func (s unstructuredJSONScheme) Decode(data []byte, _ *unversioned.GroupVersionKind, _ Object) (Object, *unversioned.GroupVersionKind, error) {
unstruct := &Unstructured{}
if err := DecodeInto(s, 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
return nil, nil, err
}
if v, ok := m["kind"]; ok {
if s, ok := v.(string); ok {
@@ -69,44 +50,30 @@ func (unstructuredJSONScheme) DecodeInto(data []byte, obj Object) error {
unstruct.APIVersion = s
}
}
if len(unstruct.APIVersion) == 0 {
return conversion.NewMissingVersionErr(string(data))
return nil, nil, conversion.NewMissingVersionErr(string(data))
}
gv, err := unversioned.ParseGroupVersion(unstruct.APIVersion)
if err != nil {
return nil, nil, err
}
gvk := gv.WithKind(unstruct.Kind)
if len(unstruct.Kind) == 0 {
return conversion.NewMissingKindErr(string(data))
return nil, &gvk, conversion.NewMissingKindErr(string(data))
}
unstruct.Object = m
return nil
return unstruct, &gvk, nil
}
func (unstructuredJSONScheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj Object, gvk unversioned.GroupVersionKind) error {
return nil
}
func (unstructuredJSONScheme) DecodeToVersion(data []byte, gv unversioned.GroupVersion) (Object, error) {
return nil, nil
}
func (unstructuredJSONScheme) DecodeParametersInto(paramaters url.Values, obj Object) error {
return nil
}
func (unstructuredJSONScheme) DataKind(data []byte) (unversioned.GroupVersionKind, error) {
obj := TypeMeta{}
if err := json.Unmarshal(data, &obj); err != nil {
return unversioned.GroupVersionKind{}, err
func (s unstructuredJSONScheme) EncodeToStream(obj Object, w io.Writer, overrides ...unversioned.GroupVersion) error {
switch t := obj.(type) {
case *Unstructured:
return json.NewEncoder(w).Encode(t.Object)
case *Unknown:
_, err := w.Write(t.RawJSON)
return err
default:
return json.NewEncoder(w).Encode(t)
}
if len(obj.APIVersion) == 0 {
return unversioned.GroupVersionKind{}, conversion.NewMissingVersionErr(string(data))
}
if len(obj.Kind) == 0 {
return unversioned.GroupVersionKind{}, conversion.NewMissingKindErr(string(data))
}
gv, err := unversioned.ParseGroupVersion(obj.APIVersion)
if err != nil {
return unversioned.GroupVersionKind{}, err
}
return gv.WithKind(obj.Kind), nil
}