Update godeps

This commit is contained in:
Prashanth Balasubramanian 2016-06-21 11:58:43 -07:00
parent 423433bc5f
commit 701c5a0e30
482 changed files with 86915 additions and 19741 deletions

View file

@ -40,10 +40,10 @@ func NewCodec(e Encoder, d Decoder) Codec {
}
// Encode is a convenience wrapper for encoding to a []byte from an Encoder
func Encode(e Encoder, obj Object, overrides ...unversioned.GroupVersion) ([]byte, error) {
func Encode(e Encoder, obj Object) ([]byte, error) {
// TODO: reuse buffer
buf := &bytes.Buffer{}
if err := e.EncodeToStream(obj, buf, overrides...); err != nil {
if err := e.Encode(obj, buf); err != nil {
return nil, err
}
return buf.Bytes(), nil
@ -78,13 +78,13 @@ func EncodeOrDie(e Encoder, obj Object) string {
// UseOrCreateObject returns obj if the canonical ObjectKind returned by the provided typer matches gvk, or
// invokes the ObjectCreator to instantiate a new gvk. Returns an error if the typer cannot find the object.
func UseOrCreateObject(t Typer, c ObjectCreater, gvk unversioned.GroupVersionKind, obj Object) (Object, error) {
func UseOrCreateObject(t ObjectTyper, c ObjectCreater, gvk unversioned.GroupVersionKind, obj Object) (Object, error) {
if obj != nil {
into, _, err := t.ObjectKind(obj)
into, _, err := t.ObjectKinds(obj)
if err != nil {
return nil, err
}
if gvk == *into {
if gvk == into[0] {
return obj, nil
}
}
@ -98,7 +98,7 @@ type NoopEncoder struct {
var _ Serializer = NoopEncoder{}
func (n NoopEncoder) EncodeToStream(obj Object, w io.Writer, overrides ...unversioned.GroupVersion) error {
func (n NoopEncoder) Encode(obj Object, w io.Writer) error {
return fmt.Errorf("encoding is not allowed for this codec: %v", reflect.TypeOf(n.Decoder))
}
@ -116,7 +116,7 @@ func (n NoopDecoder) Decode(data []byte, gvk *unversioned.GroupVersionKind, into
// NewParameterCodec creates a ParameterCodec capable of transforming url values into versioned objects and back.
func NewParameterCodec(scheme *Scheme) ParameterCodec {
return &parameterCodec{
typer: ObjectTyperToTyper(scheme),
typer: scheme,
convertor: scheme,
creator: scheme,
}
@ -124,7 +124,7 @@ func NewParameterCodec(scheme *Scheme) ParameterCodec {
// parameterCodec implements conversion to and from query parameters and objects.
type parameterCodec struct {
typer Typer
typer ObjectTyper
convertor ObjectConvertor
creator ObjectCreater
}
@ -137,10 +137,11 @@ func (c *parameterCodec) DecodeParameters(parameters url.Values, from unversione
if len(parameters) == 0 {
return nil
}
targetGVK, _, err := c.typer.ObjectKind(into)
targetGVKs, _, err := c.typer.ObjectKinds(into)
if err != nil {
return err
}
targetGVK := targetGVKs[0]
if targetGVK.GroupVersion() == from {
return c.convertor.Convert(&parameters, into)
}
@ -157,12 +158,13 @@ func (c *parameterCodec) DecodeParameters(parameters url.Values, from unversione
// EncodeParameters converts the provided object into the to version, then converts that object to url.Values.
// Returns an error if conversion is not possible.
func (c *parameterCodec) EncodeParameters(obj Object, to unversioned.GroupVersion) (url.Values, error) {
gvk, _, err := c.typer.ObjectKind(obj)
gvks, _, err := c.typer.ObjectKinds(obj)
if err != nil {
return nil, err
}
gvk := gvks[0]
if to != gvk.GroupVersion() {
out, err := c.convertor.ConvertToVersion(obj, to.String())
out, err := c.convertor.ConvertToVersion(obj, to)
if err != nil {
return nil, err
}
@ -179,9 +181,9 @@ func NewBase64Serializer(s Serializer) Serializer {
return &base64Serializer{s}
}
func (s base64Serializer) EncodeToStream(obj Object, stream io.Writer, overrides ...unversioned.GroupVersion) error {
func (s base64Serializer) Encode(obj Object, stream io.Writer) error {
e := base64.NewEncoder(base64.StdEncoding, stream)
err := s.Serializer.EncodeToStream(obj, e, overrides...)
err := s.Serializer.Encode(obj, e)
e.Close()
return err
}

View file

@ -21,9 +21,7 @@ limitations under the License.
package runtime
import (
unversioned "k8s.io/kubernetes/pkg/api/unversioned"
conversion "k8s.io/kubernetes/pkg/conversion"
reflect "reflect"
)
func DeepCopy_runtime_RawExtension(in RawExtension, out *RawExtension, c *conversion.Cloner) error {
@ -44,107 +42,24 @@ func DeepCopy_runtime_RawExtension(in RawExtension, out *RawExtension, c *conver
return nil
}
func DeepCopy_runtime_Scheme(in Scheme, out *Scheme, c *conversion.Cloner) error {
if in.gvkToType != nil {
in, out := in.gvkToType, &out.gvkToType
*out = make(map[unversioned.GroupVersionKind]reflect.Type)
for range in {
// FIXME: Copying unassignable keys unsupported unversioned.GroupVersionKind
}
} else {
out.gvkToType = nil
}
if in.typeToGVK != nil {
in, out := in.typeToGVK, &out.typeToGVK
*out = make(map[reflect.Type][]unversioned.GroupVersionKind)
for range in {
// FIXME: Copying unassignable keys unsupported reflect.Type
}
} else {
out.typeToGVK = nil
}
if in.unversionedTypes != nil {
in, out := in.unversionedTypes, &out.unversionedTypes
*out = make(map[reflect.Type]unversioned.GroupVersionKind)
for range in {
// FIXME: Copying unassignable keys unsupported reflect.Type
}
} else {
out.unversionedTypes = nil
}
if in.unversionedKinds != nil {
in, out := in.unversionedKinds, &out.unversionedKinds
*out = make(map[string]reflect.Type)
for key, val := range in {
if newVal, err := c.DeepCopy(val); err != nil {
return err
} else {
(*out)[key] = newVal.(reflect.Type)
}
}
} else {
out.unversionedKinds = nil
}
if in.fieldLabelConversionFuncs != nil {
in, out := in.fieldLabelConversionFuncs, &out.fieldLabelConversionFuncs
*out = make(map[string]map[string]FieldLabelConversionFunc)
for key, val := range in {
if newVal, err := c.DeepCopy(val); err != nil {
return err
} else {
(*out)[key] = newVal.(map[string]FieldLabelConversionFunc)
}
}
} else {
out.fieldLabelConversionFuncs = nil
}
if in.converter != nil {
in, out := in.converter, &out.converter
*out = new(conversion.Converter)
if err := conversion.DeepCopy_conversion_Converter(*in, *out, c); err != nil {
return err
}
} else {
out.converter = nil
}
if in.cloner != nil {
in, out := in.cloner, &out.cloner
*out = new(conversion.Cloner)
if err := conversion.DeepCopy_conversion_Cloner(*in, *out, c); err != nil {
return err
}
} else {
out.cloner = nil
}
func DeepCopy_runtime_TypeMeta(in TypeMeta, out *TypeMeta, c *conversion.Cloner) error {
out.APIVersion = in.APIVersion
out.Kind = in.Kind
return nil
}
func DeepCopy_runtime_SerializerInfo(in SerializerInfo, out *SerializerInfo, c *conversion.Cloner) error {
if in.Serializer == nil {
out.Serializer = nil
} else if newVal, err := c.DeepCopy(in.Serializer); err != nil {
return err
} else {
out.Serializer = newVal.(Serializer)
}
out.EncodesAsText = in.EncodesAsText
out.MediaType = in.MediaType
return nil
}
func DeepCopy_runtime_StreamSerializerInfo(in StreamSerializerInfo, out *StreamSerializerInfo, c *conversion.Cloner) error {
if err := DeepCopy_runtime_SerializerInfo(in.SerializerInfo, &out.SerializerInfo, c); err != nil {
return err
}
if in.Framer == nil {
out.Framer = nil
} else if newVal, err := c.DeepCopy(in.Framer); err != nil {
return err
} else {
out.Framer = newVal.(Framer)
}
if err := DeepCopy_runtime_SerializerInfo(in.Embedded, &out.Embedded, c); err != nil {
func DeepCopy_runtime_Unknown(in Unknown, out *Unknown, c *conversion.Cloner) error {
if err := DeepCopy_runtime_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
return err
}
if in.Raw != nil {
in, out := in.Raw, &out.Raw
*out = make([]byte, len(in))
copy(*out, in)
} else {
out.Raw = nil
}
out.ContentEncoding = in.ContentEncoding
out.ContentType = in.ContentType
return nil
}

View file

@ -69,6 +69,7 @@ option go_package = "runtime";
// in the Object. (TODO: In the case where the object is of an unknown type, a
// runtime.Unknown object will be created and stored.)
//
// +gencopy=true
// +protobuf=true
message RawExtension {
// Raw is the underlying serialization of this object.
@ -88,6 +89,7 @@ message RawExtension {
// TypeMeta is provided here for convenience. You may use it directly from this package or define
// your own with the same fields.
//
// +gencopy=true
// +protobuf=true
message TypeMeta {
optional string apiVersion = 1;
@ -101,6 +103,7 @@ message TypeMeta {
// TODO: Make this object have easy access to field based accessors and settors for
// metadata and field mutatation.
//
// +gencopy=true
// +protobuf=true
message Unknown {
optional TypeMeta typeMeta = 1;

View file

@ -26,25 +26,65 @@ import (
"k8s.io/kubernetes/pkg/util/errors"
)
type objectTyperToTyper struct {
typer ObjectTyper
// unsafeObjectConvertor implements ObjectConvertor using the unsafe conversion path.
type unsafeObjectConvertor struct {
*Scheme
}
func (t objectTyperToTyper) ObjectKind(obj Object) (*unversioned.GroupVersionKind, bool, error) {
gvk, err := t.typer.ObjectKind(obj)
var _ ObjectConvertor = unsafeObjectConvertor{}
// ConvertToVersion converts in to the provided outVersion without copying the input first, which
// is only safe if the output object is not mutated or reused.
func (c unsafeObjectConvertor) ConvertToVersion(in Object, outVersion unversioned.GroupVersion) (Object, error) {
return c.Scheme.UnsafeConvertToVersion(in, outVersion)
}
// UnsafeObjectConvertor performs object conversion without copying the object structure,
// for use when the converted object will not be reused or mutated. Primarily for use within
// versioned codecs, which use the external object for serialization but do not return it.
func UnsafeObjectConvertor(scheme *Scheme) ObjectConvertor {
return unsafeObjectConvertor{scheme}
}
// SetField puts the value of src, into fieldName, which must be a member of v.
// The value of src must be assignable to the field.
func SetField(src interface{}, v reflect.Value, fieldName string) error {
field := v.FieldByName(fieldName)
if !field.IsValid() {
return fmt.Errorf("couldn't find %v field in %#v", fieldName, v.Interface())
}
srcValue := reflect.ValueOf(src)
if srcValue.Type().AssignableTo(field.Type()) {
field.Set(srcValue)
return nil
}
if srcValue.Type().ConvertibleTo(field.Type()) {
field.Set(srcValue.Convert(field.Type()))
return nil
}
return fmt.Errorf("couldn't assign/convert %v to %v", srcValue.Type(), field.Type())
}
// Field puts the value of fieldName, which must be a member of v, into dest,
// which must be a variable to which this field's value can be assigned.
func Field(v reflect.Value, fieldName string, dest interface{}) error {
field := v.FieldByName(fieldName)
if !field.IsValid() {
return fmt.Errorf("couldn't find %v field in %#v", fieldName, v.Interface())
}
destValue, err := conversion.EnforcePtr(dest)
if err != nil {
return nil, false, err
return err
}
unversionedType, ok := t.typer.IsUnversioned(obj)
if !ok {
// ObjectTyper violates its contract
return nil, false, fmt.Errorf("typer returned a kind for %v, but then reported it was not in the scheme with IsUnversioned", reflect.TypeOf(obj))
if field.Type().AssignableTo(destValue.Type()) {
destValue.Set(field)
return nil
}
return &gvk, unversionedType, nil
}
func ObjectTyperToTyper(typer ObjectTyper) Typer {
return objectTyperToTyper{typer: typer}
if field.Type().ConvertibleTo(destValue.Type()) {
destValue.Set(field.Convert(destValue.Type()))
return nil
}
return fmt.Errorf("couldn't assign/convert %v to %v", field.Type(), destValue.Type())
}
// fieldPtr puts the address of fieldName, which must be a member of v,
@ -73,10 +113,10 @@ func FieldPtr(v reflect.Value, fieldName string, dest interface{}) error {
// EncodeList ensures that each object in an array is converted to a Unknown{} in serialized form.
// TODO: accept a content type.
func EncodeList(e Encoder, objects []Object, overrides ...unversioned.GroupVersion) error {
func EncodeList(e Encoder, objects []Object) error {
var errs []error
for i := range objects {
data, err := Encode(e, objects[i], overrides...)
data, err := Encode(e, objects[i])
if err != nil {
errs = append(errs, err)
continue
@ -133,19 +173,9 @@ type MultiObjectTyper []ObjectTyper
var _ ObjectTyper = MultiObjectTyper{}
func (m MultiObjectTyper) ObjectKind(obj Object) (gvk unversioned.GroupVersionKind, err error) {
func (m MultiObjectTyper) ObjectKinds(obj Object) (gvks []unversioned.GroupVersionKind, unversionedType bool, err error) {
for _, t := range m {
gvk, err = t.ObjectKind(obj)
if err == nil {
return
}
}
return
}
func (m MultiObjectTyper) ObjectKinds(obj Object) (gvks []unversioned.GroupVersionKind, err error) {
for _, t := range m {
gvks, err = t.ObjectKinds(obj)
gvks, unversionedType, err = t.ObjectKinds(obj)
if err == nil {
return
}
@ -162,15 +192,6 @@ func (m MultiObjectTyper) Recognizes(gvk unversioned.GroupVersionKind) bool {
return false
}
func (m MultiObjectTyper) IsUnversioned(obj Object) (bool, bool) {
for _, t := range m {
if unversioned, ok := t.IsUnversioned(obj); ok {
return unversioned, true
}
}
return false, false
}
// SetZeroValue would set the object of objPtr to zero value of its type.
func SetZeroValue(objPtr Object) error {
v, err := conversion.EnforcePtr(objPtr)

View file

@ -30,20 +30,10 @@ const (
APIVersionInternal = "__internal"
)
// Typer retrieves information about an object's group, version, and kind.
type Typer interface {
// ObjectKind returns the version and kind of the provided object, or an
// error if the object is not recognized (IsNotRegisteredError will return true).
// It returns whether the object is considered unversioned at the same time.
// TODO: align the signature of ObjectTyper with this interface
ObjectKind(Object) (*unversioned.GroupVersionKind, bool, error)
}
type Encoder interface {
// EncodeToStream writes an object to a stream. Override versions may be provided for each group
// that enforce a certain versioning. Implementations may return errors if the versions are incompatible,
// or if no conversion is defined.
EncodeToStream(obj Object, stream io.Writer, overrides ...unversioned.GroupVersion) error
// Encode writes an object to a stream. Implementations may return errors if the versions are
// incompatible, or if no conversion is defined.
Encode(obj Object, w io.Writer) error
}
type Decoder interface {
@ -161,7 +151,7 @@ type StorageSerializer interface {
// Non-codec interfaces
type ObjectVersioner interface {
ConvertToVersion(in Object, outVersion string) (out Object, err error)
ConvertToVersion(in Object, outVersion unversioned.GroupVersion) (out Object, err error)
}
// ObjectConvertor converts an object to a different version.
@ -171,27 +161,21 @@ type ObjectConvertor interface {
Convert(in, out interface{}) error
// ConvertToVersion takes the provided object and converts it the provided version. This
// method does not guarantee that the in object is not mutated.
ConvertToVersion(in Object, outVersion string) (out Object, err error)
ConvertToVersion(in Object, outVersion unversioned.GroupVersion) (out Object, err error)
ConvertFieldLabel(version, kind, label, value string) (string, string, error)
}
// ObjectTyper contains methods for extracting the APIVersion and Kind
// of objects.
type ObjectTyper interface {
// ObjectKind returns the default group,version,kind of the provided object, or an
// error if the object is not recognized (IsNotRegisteredError will return true).
ObjectKind(Object) (unversioned.GroupVersionKind, error)
// ObjectKinds returns the all possible group,version,kind of the provided object, or an
// error if the object is not recognized (IsNotRegisteredError will return true).
ObjectKinds(Object) ([]unversioned.GroupVersionKind, error)
// ObjectKinds returns the all possible group,version,kind of the provided object, true if
// the object is unversioned, or an error if the object is not recognized
// (IsNotRegisteredError will return true).
ObjectKinds(Object) ([]unversioned.GroupVersionKind, bool, 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(gvk unversioned.GroupVersionKind) bool
// IsUnversioned returns true if the provided object is considered unversioned and thus
// should have Version and Group suppressed in the output. If the object is not recognized
// in the scheme, ok is false.
IsUnversioned(Object) (unversioned bool, ok bool)
}
// ObjectCreater contains methods for instantiating an object by kind and version.

View file

@ -21,12 +21,12 @@ import (
)
// SetGroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta
func (obj *TypeMeta) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) {
func (obj *TypeMeta) SetGroupVersionKind(gvk unversioned.GroupVersionKind) {
obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind()
}
// GroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta
func (obj *TypeMeta) GroupVersionKind() *unversioned.GroupVersionKind {
func (obj *TypeMeta) GroupVersionKind() unversioned.GroupVersionKind {
return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind)
}

View file

@ -124,11 +124,8 @@ func (s *Scheme) nameFunc(t reflect.Type) string {
// fromScope gets the input version, desired output version, and desired Scheme
// from a conversion.Scope.
func (s *Scheme) fromScope(scope conversion.Scope) (inVersion, outVersion string, scheme *Scheme) {
scheme = s
inVersion = scope.Meta().SrcVersion
outVersion = scope.Meta().DestVersion
return inVersion, outVersion, scheme
func (s *Scheme) fromScope(scope conversion.Scope) *Scheme {
return s
}
// Converter allows access to the converter for the scheme
@ -214,31 +211,32 @@ func (s *Scheme) KnownTypes(gv unversioned.GroupVersion) map[string]reflect.Type
return types
}
// ObjectKind returns the group,version,kind of the go object,
// or an error if it's not a pointer or is unregistered.
func (s *Scheme) ObjectKind(obj Object) (unversioned.GroupVersionKind, error) {
gvks, err := s.ObjectKinds(obj)
// ObjectKind returns the group,version,kind of the go object and true if this object
// is considered unversioned, or an error if it's not a pointer or is unregistered.
func (s *Scheme) ObjectKind(obj Object) (unversioned.GroupVersionKind, bool, error) {
gvks, unversionedType, err := s.ObjectKinds(obj)
if err != nil {
return unversioned.GroupVersionKind{}, err
return unversioned.GroupVersionKind{}, false, err
}
return gvks[0], nil
return gvks[0], unversionedType, nil
}
// ObjectKinds returns all possible group,version,kind of the go object,
// or an error if it's not a pointer or is unregistered.
func (s *Scheme) ObjectKinds(obj Object) ([]unversioned.GroupVersionKind, error) {
// ObjectKinds returns all possible group,version,kind of the go object, true if the
// object is considered unversioned, or an error if it's not a pointer or is unregistered.
func (s *Scheme) ObjectKinds(obj Object) ([]unversioned.GroupVersionKind, bool, error) {
v, err := conversion.EnforcePtr(obj)
if err != nil {
return nil, err
return nil, false, err
}
t := v.Type()
gvks, ok := s.typeToGVK[t]
if !ok {
return nil, &notRegisteredErr{t: t}
return nil, false, &notRegisteredErr{t: t}
}
_, unversionedType := s.unversionedTypes[t]
return gvks, nil
return gvks, unversionedType, nil
}
// Recognizes returns true if the scheme is able to handle the provided group,version,kind
@ -442,13 +440,13 @@ func (s *Scheme) Convert(in, out interface{}) error {
inVersion := unversioned.GroupVersion{Group: "unknown", Version: "unknown"}
outVersion := unversioned.GroupVersion{Group: "unknown", Version: "unknown"}
if inObj, ok := in.(Object); ok {
if gvk, err := s.ObjectKind(inObj); err == nil {
inVersion = gvk.GroupVersion()
if gvks, _, err := s.ObjectKinds(inObj); err == nil {
inVersion = gvks[0].GroupVersion()
}
}
if outObj, ok := out.(Object); ok {
if gvk, err := s.ObjectKind(outObj); err == nil {
outVersion = gvk.GroupVersion()
if gvks, _, err := s.ObjectKinds(outObj); err == nil {
outVersion = gvks[0].GroupVersion()
}
}
flags, meta := s.generateConvertMeta(inVersion, outVersion, in)
@ -476,16 +474,12 @@ func (s *Scheme) ConvertFieldLabel(version, kind, label, value string) (string,
// contain the inKind (or a mapping by name defined with AddKnownTypeWithName). Will also
// return an error if the conversion does not result in a valid Object being
// returned. The serializer handles loading/serializing nested objects.
func (s *Scheme) ConvertToVersion(in Object, outVersion string) (Object, error) {
gv, err := unversioned.ParseGroupVersion(outVersion)
if err != nil {
return nil, err
}
func (s *Scheme) ConvertToVersion(in Object, outVersion unversioned.GroupVersion) (Object, error) {
switch in.(type) {
case *Unknown, *Unstructured, *UnstructuredList:
old := in.GetObjectKind().GroupVersionKind()
defer in.GetObjectKind().SetGroupVersionKind(old)
setTargetVersion(in, s, gv)
setTargetVersion(in, s, outVersion)
return in, nil
}
t := reflect.TypeOf(in)
@ -509,9 +503,9 @@ func (s *Scheme) ConvertToVersion(in Object, outVersion string) (Object, error)
kind = kinds[0]
}
outKind := gv.WithKind(kind.Kind)
outKind := outVersion.WithKind(kind.Kind)
inKind, err := s.ObjectKind(in)
inKinds, _, err := s.ObjectKinds(in)
if err != nil {
return nil, err
}
@ -521,29 +515,109 @@ func (s *Scheme) ConvertToVersion(in Object, outVersion string) (Object, error)
return nil, err
}
flags, meta := s.generateConvertMeta(inKind.GroupVersion(), gv, in)
flags, meta := s.generateConvertMeta(inKinds[0].GroupVersion(), outVersion, in)
if err := s.converter.Convert(in, out, flags, meta); err != nil {
return nil, err
}
setTargetVersion(out, s, gv)
setTargetVersion(out, s, outVersion)
return out, nil
}
// UnsafeConvertToVersion will convert in to the provided outVersion if such a conversion is possible,
// but does not guarantee the output object does not share fields with the input object. It attempts to be as
// efficient as possible when doing conversion.
func (s *Scheme) UnsafeConvertToVersion(in Object, outVersion unversioned.GroupVersion) (Object, error) {
switch t := in.(type) {
case *Unknown:
t.APIVersion = outVersion.String()
return t, nil
case *Unstructured:
t.SetAPIVersion(outVersion.String())
return t, nil
case *UnstructuredList:
t.SetAPIVersion(outVersion.String())
return t, nil
}
// determine the incoming kinds with as few allocations as possible.
t := reflect.TypeOf(in)
if t.Kind() != reflect.Ptr {
return nil, fmt.Errorf("only pointer types may be converted: %v", t)
}
t = t.Elem()
if t.Kind() != reflect.Struct {
return nil, fmt.Errorf("only pointers to struct types may be converted: %v", t)
}
kinds, ok := s.typeToGVK[t]
if !ok || len(kinds) == 0 {
return nil, fmt.Errorf("%v is not a registered type and cannot be converted into version %q", t, outVersion)
}
// if the Go type is also registered to the destination kind, no conversion is necessary
for i := range kinds {
if kinds[i].Version == outVersion.Version && kinds[i].Group == outVersion.Group {
setTargetKind(in, kinds[i])
return in, nil
}
}
// type is unversioned, no conversion necessary
// it should be possible to avoid this allocation
if unversionedKind, ok := s.unversionedTypes[t]; ok {
kind := unversionedKind
outKind := outVersion.WithKind(kind.Kind)
setTargetKind(in, outKind)
return in, nil
}
// allocate a new object as the target using the target kind
// TODO: this should look in the target group version and find the first kind that matches, rather than the
// first kind registered in typeToGVK
kind := kinds[0]
kind.Version = outVersion.Version
kind.Group = outVersion.Group
out, err := s.New(kind)
if err != nil {
return nil, err
}
// TODO: try to avoid the allocations here - in fast paths we are not likely to need these flags or meta
flags, meta := s.converter.DefaultMeta(t)
if err := s.converter.Convert(in, out, flags, meta); err != nil {
return nil, err
}
setTargetKind(out, kind)
return out, nil
}
// generateConvertMeta constructs the meta value we pass to Convert.
func (s *Scheme) generateConvertMeta(srcGroupVersion, destGroupVersion unversioned.GroupVersion, in interface{}) (conversion.FieldMatchingFlags, *conversion.Meta) {
flags, meta := s.converter.DefaultMeta(reflect.TypeOf(in))
meta.SrcVersion = srcGroupVersion.String()
meta.DestVersion = destGroupVersion.String()
return flags, meta
return s.converter.DefaultMeta(reflect.TypeOf(in))
}
// setTargetVersion is deprecated and should be replaced by use of setTargetKind
func setTargetVersion(obj Object, raw *Scheme, gv unversioned.GroupVersion) {
if gv.Version == APIVersionInternal {
// internal is a special case
obj.GetObjectKind().SetGroupVersionKind(nil)
obj.GetObjectKind().SetGroupVersionKind(unversioned.GroupVersionKind{})
return
}
if gvks, _, _ := raw.ObjectKinds(obj); len(gvks) > 0 {
obj.GetObjectKind().SetGroupVersionKind(unversioned.GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: gvks[0].Kind})
} else {
gvk, _ := raw.ObjectKind(obj)
obj.GetObjectKind().SetGroupVersionKind(&unversioned.GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: gvk.Kind})
obj.GetObjectKind().SetGroupVersionKind(unversioned.GroupVersionKind{Group: gv.Group, Version: gv.Version})
}
}
// setTargetKind sets the kind on an object, taking into account whether the target kind is the internal version.
func setTargetKind(obj Object, kind unversioned.GroupVersionKind) {
if kind.Version == APIVersionInternal {
// internal is a special case
// TODO: look at removing the need to special case this
obj.GetObjectKind().SetGroupVersionKind(unversioned.GroupVersionKind{})
return
}
obj.GetObjectKind().SetGroupVersionKind(kind)
}

View file

@ -17,6 +17,8 @@ limitations under the License.
package serializer
import (
"io"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/serializer/json"
@ -58,9 +60,9 @@ type serializerType struct {
}
func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory) []serializerType {
jsonSerializer := json.NewSerializer(mf, scheme, runtime.ObjectTyperToTyper(scheme), false)
jsonPrettySerializer := json.NewSerializer(mf, scheme, runtime.ObjectTyperToTyper(scheme), true)
yamlSerializer := json.NewYAMLSerializer(mf, scheme, runtime.ObjectTyperToTyper(scheme))
jsonSerializer := json.NewSerializer(mf, scheme, scheme, false)
jsonPrettySerializer := json.NewSerializer(mf, scheme, scheme, true)
yamlSerializer := json.NewYAMLSerializer(mf, scheme, scheme)
serializers := []serializerType{
{
@ -308,3 +310,55 @@ func (f CodecFactory) SerializerForFileExtension(extension string) (runtime.Seri
}
return nil, false
}
// DirectCodecFactory provides methods for retrieving "DirectCodec"s, which do not do conversion.
type DirectCodecFactory struct {
CodecFactory
}
// EncoderForVersion returns an encoder that does not do conversion. gv is ignored.
func (f DirectCodecFactory) EncoderForVersion(serializer runtime.Encoder, gv unversioned.GroupVersion) runtime.Encoder {
return DirectCodec{
runtime.NewCodec(serializer, nil),
f.CodecFactory.scheme,
}
}
// DecoderToVersion returns an decoder that does not do conversion. gv is ignored.
func (f DirectCodecFactory) DecoderToVersion(serializer runtime.Decoder, gv unversioned.GroupVersion) runtime.Decoder {
return DirectCodec{
runtime.NewCodec(nil, serializer),
nil,
}
}
// DirectCodec is a codec that does not do conversion. It sets the gvk during serialization, and removes the gvk during deserialization.
type DirectCodec struct {
runtime.Serializer
runtime.ObjectTyper
}
// EncodeToStream does not do conversion. It sets the gvk during serialization. overrides are ignored.
func (c DirectCodec) Encode(obj runtime.Object, stream io.Writer) error {
gvks, _, err := c.ObjectTyper.ObjectKinds(obj)
if err != nil {
return err
}
kind := obj.GetObjectKind()
oldGVK := kind.GroupVersionKind()
kind.SetGroupVersionKind(gvks[0])
err = c.Serializer.Encode(obj, stream)
kind.SetGroupVersionKind(oldGVK)
return err
}
// Decode does not do conversion. It removes the gvk during deserialization.
func (c DirectCodec) Decode(data []byte, defaults *unversioned.GroupVersionKind, into runtime.Object) (runtime.Object, *unversioned.GroupVersionKind, error) {
obj, gvk, err := c.Serializer.Decode(data, defaults, into)
if obj != nil {
kind := obj.GetObjectKind()
// clearing the gvk is just a convention of a codec
kind.SetGroupVersionKind(unversioned.GroupVersionKind{})
}
return obj, gvk, err
}

View file

@ -1,80 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2016 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.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package serializer
import (
conversion "k8s.io/kubernetes/pkg/conversion"
runtime "k8s.io/kubernetes/pkg/runtime"
)
func DeepCopy_serializer_CodecFactory(in CodecFactory, out *CodecFactory, c *conversion.Cloner) error {
if in.scheme != nil {
in, out := in.scheme, &out.scheme
*out = new(runtime.Scheme)
if err := runtime.DeepCopy_runtime_Scheme(*in, *out, c); err != nil {
return err
}
} else {
out.scheme = nil
}
if in.serializers != nil {
in, out := in.serializers, &out.serializers
*out = make([]serializerType, len(in))
for i := range in {
if newVal, err := c.DeepCopy(in[i]); err != nil {
return err
} else {
(*out)[i] = newVal.(serializerType)
}
}
} else {
out.serializers = nil
}
if in.universal == nil {
out.universal = nil
} else if newVal, err := c.DeepCopy(in.universal); err != nil {
return err
} else {
out.universal = newVal.(runtime.Decoder)
}
if in.accepts != nil {
in, out := in.accepts, &out.accepts
*out = make([]string, len(in))
copy(*out, in)
} else {
out.accepts = nil
}
if in.streamingAccepts != nil {
in, out := in.streamingAccepts, &out.streamingAccepts
*out = make([]string, len(in))
copy(*out, in)
} else {
out.streamingAccepts = nil
}
if in.legacySerializer == nil {
out.legacySerializer = nil
} else if newVal, err := c.DeepCopy(in.legacySerializer); err != nil {
return err
} else {
out.legacySerializer = newVal.(runtime.Serializer)
}
return nil
}

View file

@ -31,7 +31,7 @@ import (
// NewSerializer creates a JSON serializer that handles encoding versioned objects into the proper JSON form. If typer
// is not nil, the object has the group, version, and kind fields set.
func NewSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.Typer, pretty bool) *Serializer {
func NewSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, pretty bool) *Serializer {
return &Serializer{
meta: meta,
creater: creater,
@ -44,7 +44,7 @@ func NewSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtim
// NewYAMLSerializer creates a YAML serializer that handles encoding versioned objects into the proper YAML form. If typer
// is not nil, the object has the group, version, and kind fields set. This serializer supports only the subset of YAML that
// matches JSON, and will error if constructs are used that do not serialize to JSON.
func NewYAMLSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.Typer) *Serializer {
func NewYAMLSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper) *Serializer {
return &Serializer{
meta: meta,
creater: creater,
@ -56,7 +56,7 @@ func NewYAMLSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer ru
type Serializer struct {
meta MetaFactory
creater runtime.ObjectCreater
typer runtime.Typer
typer runtime.ObjectTyper
yaml bool
pretty bool
}
@ -111,12 +111,12 @@ func (s *Serializer) Decode(originalData []byte, gvk *unversioned.GroupVersionKi
if unk, ok := into.(*runtime.Unknown); ok && unk != nil {
unk.Raw = originalData
unk.ContentType = runtime.ContentTypeJSON
unk.GetObjectKind().SetGroupVersionKind(actual)
unk.GetObjectKind().SetGroupVersionKind(*actual)
return unk, actual, nil
}
if into != nil {
typed, _, err := s.typer.ObjectKind(into)
types, _, err := s.typer.ObjectKinds(into)
switch {
case runtime.IsNotRegisteredError(err):
if err := codec.NewDecoderBytes(data, new(codec.JsonHandle)).Decode(into); err != nil {
@ -126,6 +126,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *unversioned.GroupVersionKi
case err != nil:
return nil, actual, err
default:
typed := types[0]
if len(actual.Kind) == 0 {
actual.Kind = typed.Kind
}
@ -158,8 +159,8 @@ func (s *Serializer) Decode(originalData []byte, gvk *unversioned.GroupVersionKi
return obj, actual, nil
}
// EncodeToStream serializes the provided object to the given writer. Overrides is ignored.
func (s *Serializer) EncodeToStream(obj runtime.Object, w io.Writer, overrides ...unversioned.GroupVersion) error {
// Encode serializes the provided object to the given writer.
func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
if s.yaml {
json, err := json.Marshal(obj)
if err != nil {

View file

@ -31,7 +31,7 @@ import (
var (
// protoEncodingPrefix serves as a magic number for an encoded protobuf message on this serializer. All
// proto messages serialized by this schema will be precedeed by the bytes 0x6b 0x38 0x73, with the fourth
// proto messages serialized by this schema will be preceded by the bytes 0x6b 0x38 0x73, with the fourth
// byte being reserved for the encoding style. The only encoding style defined is 0x00, which means that
// the rest of the byte stream is a message of type k8s.io.kubernetes.pkg.runtime.Unknown (proto2).
//
@ -59,7 +59,7 @@ func IsNotMarshalable(err error) bool {
// as-is (any type info passed with the object will be used).
//
// This encoding scheme is experimental, and is subject to change at any time.
func NewSerializer(creater runtime.ObjectCreater, typer runtime.Typer, defaultContentType string) *Serializer {
func NewSerializer(creater runtime.ObjectCreater, typer runtime.ObjectTyper, defaultContentType string) *Serializer {
return &Serializer{
prefix: protoEncodingPrefix,
creater: creater,
@ -71,7 +71,7 @@ func NewSerializer(creater runtime.ObjectCreater, typer runtime.Typer, defaultCo
type Serializer struct {
prefix []byte
creater runtime.ObjectCreater
typer runtime.Typer
typer runtime.ObjectTyper
contentType string
}
@ -120,61 +120,60 @@ func (s *Serializer) Decode(originalData []byte, gvk *unversioned.GroupVersionKi
}
actual := unk.GroupVersionKind()
copyKindDefaults(actual, gvk)
copyKindDefaults(&actual, gvk)
if intoUnknown, ok := into.(*runtime.Unknown); ok && intoUnknown != nil {
*intoUnknown = unk
if len(intoUnknown.ContentType) == 0 {
intoUnknown.ContentType = s.contentType
}
return intoUnknown, actual, nil
return intoUnknown, &actual, nil
}
if into != nil {
typed, _, err := s.typer.ObjectKind(into)
types, _, err := s.typer.ObjectKinds(into)
switch {
case runtime.IsNotRegisteredError(err):
pb, ok := into.(proto.Message)
if !ok {
return nil, actual, errNotMarshalable{reflect.TypeOf(into)}
return nil, &actual, errNotMarshalable{reflect.TypeOf(into)}
}
if err := proto.Unmarshal(unk.Raw, pb); err != nil {
return nil, actual, err
return nil, &actual, err
}
return into, actual, nil
return into, &actual, nil
case err != nil:
return nil, actual, err
return nil, &actual, err
default:
copyKindDefaults(actual, typed)
copyKindDefaults(&actual, &types[0])
// if the result of defaulting did not set a version or group, ensure that at least group is set
// (copyKindDefaults will not assign Group if version is already set). This guarantees that the group
// of into is set if there is no better information from the caller or object.
if len(actual.Version) == 0 && len(actual.Group) == 0 {
actual.Group = typed.Group
actual.Group = types[0].Group
}
}
}
if len(actual.Kind) == 0 {
return nil, actual, runtime.NewMissingKindErr(fmt.Sprintf("%#v", unk.TypeMeta))
return nil, &actual, runtime.NewMissingKindErr(fmt.Sprintf("%#v", unk.TypeMeta))
}
if len(actual.Version) == 0 {
return nil, actual, runtime.NewMissingVersionErr(fmt.Sprintf("%#v", unk.TypeMeta))
return nil, &actual, runtime.NewMissingVersionErr(fmt.Sprintf("%#v", unk.TypeMeta))
}
return unmarshalToObject(s.typer, s.creater, actual, into, unk.Raw)
return unmarshalToObject(s.typer, s.creater, &actual, into, unk.Raw)
}
// EncodeToStream serializes the provided object to the given writer. Overrides is ignored.
func (s *Serializer) EncodeToStream(obj runtime.Object, w io.Writer, overrides ...unversioned.GroupVersion) error {
// Encode serializes the provided object to the given writer.
func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
var unk runtime.Unknown
if kind := obj.GetObjectKind().GroupVersionKind(); kind != nil {
unk = runtime.Unknown{
TypeMeta: runtime.TypeMeta{
Kind: kind.Kind,
APIVersion: kind.GroupVersion().String(),
},
}
kind := obj.GetObjectKind().GroupVersionKind()
unk = runtime.Unknown{
TypeMeta: runtime.TypeMeta{
Kind: kind.Kind,
APIVersion: kind.GroupVersion().String(),
},
}
prefixSize := uint64(len(s.prefix))
@ -278,7 +277,7 @@ func estimateUnknownSize(unk *runtime.Unknown, byteSize uint64) uint64 {
// encoded object, and thus is not self describing (callers must know what type is being described in order to decode).
//
// This encoding scheme is experimental, and is subject to change at any time.
func NewRawSerializer(creater runtime.ObjectCreater, typer runtime.Typer, defaultContentType string) *RawSerializer {
func NewRawSerializer(creater runtime.ObjectCreater, typer runtime.ObjectTyper, defaultContentType string) *RawSerializer {
return &RawSerializer{
creater: creater,
typer: typer,
@ -290,7 +289,7 @@ func NewRawSerializer(creater runtime.ObjectCreater, typer runtime.Typer, defaul
// type).
type RawSerializer struct {
creater runtime.ObjectCreater
typer runtime.Typer
typer runtime.ObjectTyper
contentType string
}
@ -334,11 +333,11 @@ func (s *RawSerializer) Decode(originalData []byte, gvk *unversioned.GroupVersio
intoUnknown.Raw = data
intoUnknown.ContentEncoding = ""
intoUnknown.ContentType = s.contentType
intoUnknown.SetGroupVersionKind(actual)
intoUnknown.SetGroupVersionKind(*actual)
return intoUnknown, actual, nil
}
typed, _, err := s.typer.ObjectKind(into)
types, _, err := s.typer.ObjectKinds(into)
switch {
case runtime.IsNotRegisteredError(err):
pb, ok := into.(proto.Message)
@ -352,12 +351,12 @@ func (s *RawSerializer) Decode(originalData []byte, gvk *unversioned.GroupVersio
case err != nil:
return nil, actual, err
default:
copyKindDefaults(actual, typed)
copyKindDefaults(actual, &types[0])
// if the result of defaulting did not set a version or group, ensure that at least group is set
// (copyKindDefaults will not assign Group if version is already set). This guarantees that the group
// of into is set if there is no better information from the caller or object.
if len(actual.Version) == 0 && len(actual.Group) == 0 {
actual.Group = typed.Group
actual.Group = types[0].Group
}
}
@ -372,7 +371,7 @@ func (s *RawSerializer) Decode(originalData []byte, gvk *unversioned.GroupVersio
}
// unmarshalToObject is the common code between decode in the raw and normal serializer.
func unmarshalToObject(typer runtime.Typer, creater runtime.ObjectCreater, actual *unversioned.GroupVersionKind, into runtime.Object, data []byte) (runtime.Object, *unversioned.GroupVersionKind, error) {
func unmarshalToObject(typer runtime.ObjectTyper, creater runtime.ObjectCreater, actual *unversioned.GroupVersionKind, into runtime.Object, data []byte) (runtime.Object, *unversioned.GroupVersionKind, error) {
// use the target if necessary
obj, err := runtime.UseOrCreateObject(typer, creater, *actual, into)
if err != nil {
@ -389,8 +388,8 @@ func unmarshalToObject(typer runtime.Typer, creater runtime.ObjectCreater, actua
return obj, actual, nil
}
// EncodeToStream serializes the provided object to the given writer. Overrides is ignored.
func (s *RawSerializer) EncodeToStream(obj runtime.Object, w io.Writer, overrides ...unversioned.GroupVersion) error {
// Encode serializes the provided object to the given writer. Overrides is ignored.
func (s *RawSerializer) Encode(obj runtime.Object, w io.Writer) error {
switch t := obj.(type) {
case bufferedMarshaller:
// this path performs a single allocation during write but requires the caller to implement

View file

@ -31,8 +31,8 @@ const (
)
func protobufSerializer(scheme *runtime.Scheme) (serializerType, bool) {
serializer := protobuf.NewSerializer(scheme, runtime.ObjectTyperToTyper(scheme), contentTypeProtobuf)
raw := protobuf.NewRawSerializer(scheme, runtime.ObjectTyperToTyper(scheme), contentTypeProtobuf)
serializer := protobuf.NewSerializer(scheme, scheme, contentTypeProtobuf)
raw := protobuf.NewRawSerializer(scheme, scheme, contentTypeProtobuf)
return serializerType{
AcceptContentTypes: []string{contentTypeProtobuf},
ContentType: contentTypeProtobuf,

View file

@ -30,8 +30,8 @@ import (
// Encoder is a runtime.Encoder on a stream.
type Encoder interface {
// Encode will write the provided object to the stream or return an error. It obeys the same
// contract as runtime.Encoder.
Encode(obj runtime.Object, overrides ...unversioned.GroupVersion) error
// contract as runtime.VersionedEncoder.
Encode(obj runtime.Object) error
}
// Decoder is a runtime.Decoder from a stream.
@ -127,8 +127,8 @@ func NewEncoder(w io.Writer, e runtime.Encoder) Encoder {
}
// Encode writes the provided object to the nested writer.
func (e *encoder) Encode(obj runtime.Object, overrides ...unversioned.GroupVersion) error {
if err := e.encoder.EncodeToStream(obj, e.buf, overrides...); err != nil {
func (e *encoder) Encode(obj runtime.Object) error {
if err := e.encoder.Encode(obj, e.buf); err != nil {
return err
}
_, err := e.writer.Write(e.buf.Bytes())

View file

@ -71,7 +71,7 @@ func NewCodecForScheme(
encodeVersion []unversioned.GroupVersion,
decodeVersion []unversioned.GroupVersion,
) runtime.Codec {
return NewCodec(encoder, decoder, scheme, scheme, scheme, runtime.ObjectTyperToTyper(scheme), encodeVersion, decodeVersion)
return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, scheme, encodeVersion, decodeVersion)
}
// NewCodec takes objects in their internal versions and converts them to external versions before
@ -83,7 +83,7 @@ func NewCodec(
convertor runtime.ObjectConvertor,
creater runtime.ObjectCreater,
copier runtime.ObjectCopier,
typer runtime.Typer,
typer runtime.ObjectTyper,
encodeVersion []unversioned.GroupVersion,
decodeVersion []unversioned.GroupVersion,
) runtime.Codec {
@ -104,6 +104,11 @@ func NewCodec(
}
internal.encodeVersion[v.Group] = v
}
if len(internal.encodeVersion) == 1 {
for _, v := range internal.encodeVersion {
internal.preferredEncodeVersion = []unversioned.GroupVersion{v}
}
}
}
if decodeVersion != nil {
internal.decodeVersion = make(map[string]unversioned.GroupVersion)
@ -125,10 +130,12 @@ type codec struct {
convertor runtime.ObjectConvertor
creater runtime.ObjectCreater
copier runtime.ObjectCopier
typer runtime.Typer
typer runtime.ObjectTyper
encodeVersion map[string]unversioned.GroupVersion
decodeVersion map[string]unversioned.GroupVersion
preferredEncodeVersion []unversioned.GroupVersion
}
// Decode attempts a decode of the object, then tries to convert it to the internal version. If into is provided and the decoding is
@ -204,7 +211,7 @@ func (c *codec) Decode(data []byte, defaultGVK *unversioned.GroupVersionKind, in
}
// Convert if needed.
out, err := c.convertor.ConvertToVersion(obj, targetGV.String())
out, err := c.convertor.ConvertToVersion(obj, targetGV)
if err != nil {
return nil, gvk, err
}
@ -215,44 +222,33 @@ func (c *codec) Decode(data []byte, defaultGVK *unversioned.GroupVersionKind, in
return out, gvk, nil
}
// EncodeToStream ensures the provided object is output in the right scheme. If overrides are specified, when
// encoding the object the first override that matches the object's group is used. Other overrides are ignored.
func (c *codec) EncodeToStream(obj runtime.Object, w io.Writer, overrides ...unversioned.GroupVersion) error {
// Encode ensures the provided object is output in the appropriate group and version, invoking
// conversion if necessary. Unversioned objects (according to the ObjectTyper) are output as is.
func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
if _, ok := obj.(*runtime.Unknown); ok {
return c.encoder.EncodeToStream(obj, w, overrides...)
return c.encoder.Encode(obj, w)
}
gvk, isUnversioned, err := c.typer.ObjectKind(obj)
gvks, isUnversioned, err := c.typer.ObjectKinds(obj)
if err != nil {
return err
}
gvk := gvks[0]
if (c.encodeVersion == nil && len(overrides) == 0) || isUnversioned {
old := obj.GetObjectKind().GroupVersionKind()
obj.GetObjectKind().SetGroupVersionKind(gvk)
defer obj.GetObjectKind().SetGroupVersionKind(old)
return c.encoder.EncodeToStream(obj, w, overrides...)
if c.encodeVersion == nil || isUnversioned {
objectKind := obj.GetObjectKind()
old := objectKind.GroupVersionKind()
objectKind.SetGroupVersionKind(gvk)
err = c.encoder.Encode(obj, w)
objectKind.SetGroupVersionKind(old)
return err
}
targetGV, ok := c.encodeVersion[gvk.Group]
// use override if provided
for i, override := range overrides {
if override.Group == gvk.Group {
ok = true
targetGV = override
// swap the position of the override
overrides[0], overrides[i] = targetGV, overrides[0]
break
}
}
// attempt a conversion to the sole encode version
if !ok && len(c.encodeVersion) == 1 {
if !ok && c.preferredEncodeVersion != nil {
ok = true
for _, v := range c.encodeVersion {
targetGV = v
}
// ensure the target override is first
overrides = promoteOrPrependGroupVersion(targetGV, overrides)
targetGV = c.preferredEncodeVersion[0]
}
// if no fallback is available, error
@ -261,33 +257,19 @@ func (c *codec) EncodeToStream(obj runtime.Object, w io.Writer, overrides ...unv
}
// Perform a conversion if necessary
if gvk.GroupVersion() != targetGV {
out, err := c.convertor.ConvertToVersion(obj, targetGV.String())
if err != nil {
if ok {
return err
}
} else {
obj = out
objectKind := obj.GetObjectKind()
old := objectKind.GroupVersionKind()
out, err := c.convertor.ConvertToVersion(obj, targetGV)
if err != nil {
if ok {
return err
}
} else {
old := obj.GetObjectKind().GroupVersionKind()
defer obj.GetObjectKind().SetGroupVersionKind(old)
obj.GetObjectKind().SetGroupVersionKind(&unversioned.GroupVersionKind{Group: targetGV.Group, Version: targetGV.Version, Kind: gvk.Kind})
obj = out
}
return c.encoder.EncodeToStream(obj, w, overrides...)
}
// promoteOrPrependGroupVersion finds the group version in the provided group versions that has the same group as target.
// If the group is found the returned array will have that group version in the first position - if the group is not found
// the returned array will have target in the first position.
func promoteOrPrependGroupVersion(target unversioned.GroupVersion, gvs []unversioned.GroupVersion) []unversioned.GroupVersion {
for i, gv := range gvs {
if gv.Group == target.Group {
gvs[0], gvs[i] = gvs[i], gvs[0]
return gvs
}
}
return append([]unversioned.GroupVersion{target}, gvs...)
// Conversion is responsible for setting the proper group, version, and kind onto the outgoing object
err = c.encoder.Encode(obj, w)
// restore the old GVK, in case conversion returned the same object
objectKind.SetGroupVersionKind(old)
return err
}

View file

@ -17,6 +17,11 @@ limitations under the License.
package runtime
import (
"fmt"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api/meta/metatypes"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/types"
)
@ -35,6 +40,7 @@ import (
// TypeMeta is provided here for convenience. You may use it directly from this package or define
// your own with the same fields.
//
// +gencopy=true
// +protobuf=true
type TypeMeta struct {
APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty" protobuf:"bytes,1,opt,name=apiVersion"`
@ -87,6 +93,7 @@ const (
// in the Object. (TODO: In the case where the object is of an unknown type, a
// runtime.Unknown object will be created and stored.)
//
// +gencopy=true
// +protobuf=true
type RawExtension struct {
// Raw is the underlying serialization of this object.
@ -104,6 +111,7 @@ type RawExtension struct {
// TODO: Make this object have easy access to field based accessors and settors for
// metadata and field mutatation.
//
// +gencopy=true
// +protobuf=true
type Unknown struct {
TypeMeta `json:",inline" protobuf:"bytes,1,opt,name=typeMeta"`
@ -148,6 +156,19 @@ func getNestedString(obj map[string]interface{}, fields ...string) string {
return ""
}
func getNestedSlice(obj map[string]interface{}, fields ...string) []string {
if m, ok := getNestedField(obj, fields...).([]interface{}); ok {
strSlice := make([]string, 0, len(m))
for _, v := range m {
if str, ok := v.(string); ok {
strSlice = append(strSlice, str)
}
}
return strSlice
}
return nil
}
func getNestedMap(obj map[string]interface{}, fields ...string) map[string]string {
if m, ok := getNestedField(obj, fields...).(map[string]interface{}); ok {
strMap := make(map[string]string, len(m))
@ -174,6 +195,14 @@ func setNestedField(obj map[string]interface{}, value interface{}, fields ...str
m[fields[len(fields)-1]] = value
}
func setNestedSlice(obj map[string]interface{}, value []string, fields ...string) {
m := make([]interface{}, 0, len(value))
for _, v := range value {
m = append(m, v)
}
setNestedField(obj, m, fields...)
}
func setNestedMap(obj map[string]interface{}, value map[string]string, fields ...string) {
m := make(map[string]interface{}, len(value))
for k, v := range value {
@ -189,6 +218,13 @@ func (u *Unstructured) setNestedField(value interface{}, fields ...string) {
setNestedField(u.Object, value, fields...)
}
func (u *Unstructured) setNestedSlice(value []string, fields ...string) {
if u.Object == nil {
u.Object = make(map[string]interface{})
}
setNestedSlice(u.Object, value, fields...)
}
func (u *Unstructured) setNestedMap(value map[string]string, fields ...string) {
if u.Object == nil {
u.Object = make(map[string]interface{})
@ -196,6 +232,87 @@ func (u *Unstructured) setNestedMap(value map[string]string, fields ...string) {
setNestedMap(u.Object, value, fields...)
}
func extractOwnerReference(src interface{}) metatypes.OwnerReference {
v := src.(map[string]interface{})
controllerPtr, ok := (getNestedField(v, "controller")).(*bool)
if !ok {
controllerPtr = nil
} else {
if controllerPtr != nil {
controller := *controllerPtr
controllerPtr = &controller
}
}
return metatypes.OwnerReference{
Kind: getNestedString(v, "kind"),
Name: getNestedString(v, "name"),
APIVersion: getNestedString(v, "apiVersion"),
UID: (types.UID)(getNestedString(v, "uid")),
Controller: controllerPtr,
}
}
func setOwnerReference(src metatypes.OwnerReference) map[string]interface{} {
ret := make(map[string]interface{})
controllerPtr := src.Controller
if controllerPtr != nil {
controller := *controllerPtr
controllerPtr = &controller
}
setNestedField(ret, src.Kind, "kind")
setNestedField(ret, src.Name, "name")
setNestedField(ret, src.APIVersion, "apiVersion")
setNestedField(ret, string(src.UID), "uid")
setNestedField(ret, controllerPtr, "controller")
return ret
}
func getOwnerReferences(object map[string]interface{}) ([]map[string]interface{}, error) {
field := getNestedField(object, "metadata", "ownerReferences")
if field == nil {
return nil, fmt.Errorf("cannot find field metadata.ownerReferences in %v", object)
}
ownerReferences, ok := field.([]map[string]interface{})
if ok {
return ownerReferences, nil
}
// TODO: This is hacky...
interfaces, ok := field.([]interface{})
if !ok {
return nil, fmt.Errorf("expect metadata.ownerReferences to be a slice in %#v", object)
}
ownerReferences = make([]map[string]interface{}, 0, len(interfaces))
for i := 0; i < len(interfaces); i++ {
r, ok := interfaces[i].(map[string]interface{})
if !ok {
return nil, fmt.Errorf("expect element metadata.ownerReferences to be a map[string]interface{} in %#v", object)
}
ownerReferences = append(ownerReferences, r)
}
return ownerReferences, nil
}
func (u *Unstructured) GetOwnerReferences() []metatypes.OwnerReference {
original, err := getOwnerReferences(u.Object)
if err != nil {
glog.V(6).Info(err)
return nil
}
ret := make([]metatypes.OwnerReference, 0, len(original))
for i := 0; i < len(original); i++ {
ret = append(ret, extractOwnerReference(original[i]))
}
return ret
}
func (u *Unstructured) SetOwnerReferences(references []metatypes.OwnerReference) {
var newReferences = make([]map[string]interface{}, 0, len(references))
for i := 0; i < len(references); i++ {
newReferences = append(newReferences, setOwnerReference(references[i]))
}
u.setNestedField(newReferences, "metadata", "ownerReferences")
}
func (u *Unstructured) GetAPIVersion() string {
return getNestedString(u.Object, "apiVersion")
}
@ -301,18 +418,26 @@ func (u *Unstructured) SetAnnotations(annotations map[string]string) {
u.setNestedMap(annotations, "metadata", "annotations")
}
func (u *Unstructured) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) {
func (u *Unstructured) SetGroupVersionKind(gvk unversioned.GroupVersionKind) {
u.SetAPIVersion(gvk.GroupVersion().String())
u.SetKind(gvk.Kind)
}
func (u *Unstructured) GroupVersionKind() *unversioned.GroupVersionKind {
func (u *Unstructured) GroupVersionKind() unversioned.GroupVersionKind {
gv, err := unversioned.ParseGroupVersion(u.GetAPIVersion())
if err != nil {
return nil
return unversioned.GroupVersionKind{}
}
gvk := gv.WithKind(u.GetKind())
return &gvk
return gvk
}
func (u *Unstructured) GetFinalizers() []string {
return getNestedSlice(u.Object, "metadata", "finalizers")
}
func (u *Unstructured) SetFinalizers(finalizers []string) {
u.setNestedSlice(finalizers, "metadata", "finalizers")
}
// UnstructuredList allows lists that do not have Golang structs
@ -364,18 +489,18 @@ func (u *UnstructuredList) SetSelfLink(selfLink string) {
u.setNestedField(selfLink, "metadata", "selfLink")
}
func (u *UnstructuredList) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) {
func (u *UnstructuredList) SetGroupVersionKind(gvk unversioned.GroupVersionKind) {
u.SetAPIVersion(gvk.GroupVersion().String())
u.SetKind(gvk.Kind)
}
func (u *UnstructuredList) GroupVersionKind() *unversioned.GroupVersionKind {
func (u *UnstructuredList) GroupVersionKind() unversioned.GroupVersionKind {
gv, err := unversioned.ParseGroupVersion(u.GetAPIVersion())
if err != nil {
return nil
return unversioned.GroupVersionKind{}
}
gvk := gv.WithKind(u.GetKind())
return &gvk
return gvk
}
// VersionedObjects is used by Decoders to give callers a way to access all versions

View file

@ -16,6 +16,10 @@ limitations under the License.
package runtime
import (
"fmt"
)
type ProtobufMarshaller interface {
MarshalTo(data []byte) (int, error)
}
@ -44,6 +48,11 @@ func (m *Unknown) NestedMarshalTo(data []byte, b ProtobufMarshaller, size uint64
if err != nil {
return 0, err
}
if uint64(n2) != size {
// programmer error: the Size() method for protobuf does not match the results of MarshalTo, which means the proto
// struct returned would be wrong.
return 0, fmt.Errorf("the Size() value of %T was %d, but NestedMarshalTo wrote %d bytes to data", b, size, n2)
}
i += n2
}

View file

@ -18,7 +18,10 @@ package runtime
import (
gojson "encoding/json"
"errors"
"fmt"
"io"
"strings"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/util/json"
@ -45,18 +48,18 @@ func (s unstructuredJSONScheme) Decode(data []byte, _ *unversioned.GroupVersionK
gvk := obj.GetObjectKind().GroupVersionKind()
if len(gvk.Kind) == 0 {
return nil, gvk, NewMissingKindErr(string(data))
return nil, &gvk, NewMissingKindErr(string(data))
}
return obj, gvk, nil
return obj, &gvk, nil
}
func (unstructuredJSONScheme) EncodeToStream(obj Object, w io.Writer, overrides ...unversioned.GroupVersion) error {
func (unstructuredJSONScheme) Encode(obj Object, w io.Writer) error {
switch t := obj.(type) {
case *Unstructured:
return json.NewEncoder(w).Encode(t.Object)
case *UnstructuredList:
var items []map[string]interface{}
items := make([]map[string]interface{}, 0, len(t.Items))
for _, i := range t.Items {
items = append(items, i.Object)
}
@ -98,6 +101,13 @@ func (s unstructuredJSONScheme) decodeInto(data []byte, obj Object) error {
return s.decodeToUnstructured(data, x)
case *UnstructuredList:
return s.decodeToList(data, x)
case *VersionedObjects:
u := new(Unstructured)
err := s.decodeToUnstructured(data, u)
if err == nil {
x.Objects = []Object{u}
}
return err
default:
return json.Unmarshal(data, x)
}
@ -128,6 +138,12 @@ func (s unstructuredJSONScheme) decodeToList(data []byte, list *UnstructuredList
return err
}
// For typed lists, e.g., a PodList, API server doesn't set each item's
// APIVersion and Kind. We need to set it.
listAPIVersion := list.GetAPIVersion()
listKind := list.GetKind()
itemKind := strings.TrimSuffix(listKind, "List")
delete(list.Object, "items")
list.Items = nil
for _, i := range dList.Items {
@ -135,7 +151,49 @@ func (s unstructuredJSONScheme) decodeToList(data []byte, list *UnstructuredList
if err := s.decodeToUnstructured([]byte(i), unstruct); err != nil {
return err
}
// This is hacky. Set the item's Kind and APIVersion to those inferred
// from the List.
if len(unstruct.GetKind()) == 0 && len(unstruct.GetAPIVersion()) == 0 {
unstruct.SetKind(itemKind)
unstruct.SetAPIVersion(listAPIVersion)
}
list.Items = append(list.Items, unstruct)
}
return nil
}
// UnstructuredObjectConverter is an ObjectConverter for use with
// Unstructured objects. Since it has no schema or type information,
// it will only succeed for no-op conversions. This is provided as a
// sane implementation for APIs that require an object converter.
type UnstructuredObjectConverter struct{}
func (UnstructuredObjectConverter) Convert(in, out interface{}) error {
unstructIn, ok := in.(*Unstructured)
if !ok {
return fmt.Errorf("input type %T in not valid for unstructured conversion", in)
}
unstructOut, ok := out.(*Unstructured)
if !ok {
return fmt.Errorf("output type %T in not valid for unstructured conversion", out)
}
// maybe deep copy the map? It is documented in the
// ObjectConverter interface that this function is not
// guaranteeed to not mutate the input. Or maybe set the input
// object to nil.
unstructOut.Object = unstructIn.Object
return nil
}
func (UnstructuredObjectConverter) ConvertToVersion(in Object, outVersion unversioned.GroupVersion) (Object, error) {
if gvk := in.GetObjectKind().GroupVersionKind(); gvk.GroupVersion() != outVersion {
return nil, errors.New("unstructured converter cannot convert versions")
}
return in, nil
}
func (UnstructuredObjectConverter) ConvertFieldLabel(version, kind, label, value string) (string, string, error) {
return "", "", errors.New("unstructured cannot convert field labels")
}