Move DirectEncoder to runtime, add `.WithoutConversion()` on CodecFactory

Renome the Direct*coders to clearly identify what they do - add or remove
the version information while encoding or decoding.

This refactor makes it easier for clients to move to a "no conversion"
model.
k3s-v1.15.3
Clayton Coleman 2019-04-03 12:27:40 -04:00
parent bbdba2bd21
commit 994b5c6cc2
No known key found for this signature in database
GPG Key ID: 3D16906B4F1C5CB3
4 changed files with 72 additions and 57 deletions

View File

@ -210,3 +210,50 @@ type defaultFramer struct{}
func (defaultFramer) NewFrameReader(r io.ReadCloser) io.ReadCloser { return r }
func (defaultFramer) NewFrameWriter(w io.Writer) io.Writer { return w }
// WithVersionEncoder serializes an object and ensures the GVK is set.
type WithVersionEncoder struct {
Version GroupVersioner
Encoder
ObjectTyper
}
// Encode does not do conversion. It sets the gvk during serialization.
func (e WithVersionEncoder) Encode(obj Object, stream io.Writer) error {
gvks, _, err := e.ObjectTyper.ObjectKinds(obj)
if err != nil {
if IsNotRegisteredError(err) {
return e.Encoder.Encode(obj, stream)
}
return err
}
kind := obj.GetObjectKind()
oldGVK := kind.GroupVersionKind()
gvk := gvks[0]
if e.Version != nil {
preferredGVK, ok := e.Version.KindForGroupVersionKinds(gvks)
if ok {
gvk = preferredGVK
}
}
kind.SetGroupVersionKind(gvk)
err = e.Encoder.Encode(obj, stream)
kind.SetGroupVersionKind(oldGVK)
return err
}
// WithoutVersionDecoder clears the group version kind of a deserialized object.
type WithoutVersionDecoder struct {
Decoder
}
// Decode does not do conversion. It removes the gvk during deserialization.
func (d WithoutVersionDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error) {
obj, gvk, err := d.Decoder.Decode(data, defaults, into)
if obj != nil {
kind := obj.GetObjectKind()
// clearing the gvk is just a convention of a codec
kind.SetGroupVersionKind(schema.GroupVersionKind{})
}
return obj, gvk, err
}

View File

@ -160,6 +160,12 @@ func newCodecFactory(scheme *runtime.Scheme, serializers []serializerType) Codec
}
}
// WithoutConversion returns a NegotiatedSerializer that performs no conversion, even if the
// caller requests it.
func (f CodecFactory) WithoutConversion() runtime.NegotiatedSerializer {
return WithoutConversionCodecFactory{f}
}
// SupportedMediaTypes returns the RFC2046 media types that this factory has serializers for.
func (f CodecFactory) SupportedMediaTypes() []runtime.SerializerInfo {
return f.accepts
@ -227,23 +233,26 @@ func (f CodecFactory) EncoderForVersion(encoder runtime.Encoder, gv runtime.Grou
return f.CodecForVersions(encoder, nil, gv, nil)
}
// DirectCodecFactory provides methods for retrieving "DirectCodec"s, which do not do conversion.
type DirectCodecFactory struct {
// WithoutConversionCodecFactory is a CodecFactory that will explicitly ignore requests to perform conversion.
// This wrapper is used while code migrates away from using conversion (such as external clients) and in the future
// will be unnecessary when we change the signature of NegotiatedSerializer.
type WithoutConversionCodecFactory struct {
CodecFactory
}
// EncoderForVersion returns an encoder that does not do conversion.
func (f DirectCodecFactory) EncoderForVersion(serializer runtime.Encoder, version runtime.GroupVersioner) runtime.Encoder {
return versioning.DirectEncoder{
// EncoderForVersion returns an encoder that does not do conversion, but does set the group version kind of the object
// when serialized.
func (f WithoutConversionCodecFactory) EncoderForVersion(serializer runtime.Encoder, version runtime.GroupVersioner) runtime.Encoder {
return runtime.WithVersionEncoder{
Version: version,
Encoder: serializer,
ObjectTyper: f.CodecFactory.scheme,
}
}
// DecoderToVersion returns an decoder that does not do conversion. gv is ignored.
func (f DirectCodecFactory) DecoderToVersion(serializer runtime.Decoder, _ runtime.GroupVersioner) runtime.Decoder {
return versioning.DirectDecoder{
// DecoderToVersion returns an decoder that does not do conversion.
func (f WithoutConversionCodecFactory) DecoderToVersion(serializer runtime.Decoder, _ runtime.GroupVersioner) runtime.Decoder {
return runtime.WithoutVersionDecoder{
Decoder: serializer,
}
}

View File

@ -106,7 +106,7 @@ func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into ru
}
if d, ok := obj.(runtime.NestedObjectDecoder); ok {
if err := d.DecodeNestedObjects(DirectDecoder{c.decoder}); err != nil {
if err := d.DecodeNestedObjects(runtime.WithoutVersionDecoder{c.decoder}); err != nil {
return nil, gvk, err
}
}
@ -201,7 +201,7 @@ func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
if c.encodeVersion == nil || isUnversioned {
if e, ok := obj.(runtime.NestedObjectEncoder); ok {
if err := e.EncodeNestedObjects(DirectEncoder{Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
if err := e.EncodeNestedObjects(runtime.WithVersionEncoder{Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
return err
}
}
@ -222,7 +222,7 @@ func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
}
if e, ok := out.(runtime.NestedObjectEncoder); ok {
if err := e.EncodeNestedObjects(DirectEncoder{Version: c.encodeVersion, Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
if err := e.EncodeNestedObjects(runtime.WithVersionEncoder{Version: c.encodeVersion, Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
return err
}
}
@ -234,49 +234,8 @@ func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
return err
}
// DirectEncoder serializes an object and ensures the GVK is set.
type DirectEncoder struct {
Version runtime.GroupVersioner
runtime.Encoder
runtime.ObjectTyper
}
// DirectEncoder was movend and renamed in 1.15 and will be removed in 1.16.
type DirectEncoder = runtime.WithVersionEncoder
// Encode does not do conversion. It sets the gvk during serialization.
func (e DirectEncoder) Encode(obj runtime.Object, stream io.Writer) error {
gvks, _, err := e.ObjectTyper.ObjectKinds(obj)
if err != nil {
if runtime.IsNotRegisteredError(err) {
return e.Encoder.Encode(obj, stream)
}
return err
}
kind := obj.GetObjectKind()
oldGVK := kind.GroupVersionKind()
gvk := gvks[0]
if e.Version != nil {
preferredGVK, ok := e.Version.KindForGroupVersionKinds(gvks)
if ok {
gvk = preferredGVK
}
}
kind.SetGroupVersionKind(gvk)
err = e.Encoder.Encode(obj, stream)
kind.SetGroupVersionKind(oldGVK)
return err
}
// DirectDecoder clears the group version kind of a deserialized object.
type DirectDecoder struct {
runtime.Decoder
}
// Decode does not do conversion. It removes the gvk during deserialization.
func (d DirectDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
obj, gvk, err := d.Decoder.Decode(data, defaults, into)
if obj != nil {
kind := obj.GetObjectKind()
// clearing the gvk is just a convention of a codec
kind.SetGroupVersionKind(schema.GroupVersionKind{})
}
return obj, gvk, err
}
// DirectDecoder was movend and renamed in 1.15 and will be removed in 1.16.
type DirectDecoder = runtime.WithoutVersionDecoder

View File

@ -370,7 +370,7 @@ func TestDirectCodecEncode(t *testing.T) {
},
}
c := DirectEncoder{
c := runtime.WithVersionEncoder{
Version: schema.GroupVersion{Group: "expected_group"},
Encoder: &serializer,
ObjectTyper: &typer,