summaryrefslogtreecommitdiff
path: root/vendor/k8s.io/apimachinery/pkg/runtime/codec.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/k8s.io/apimachinery/pkg/runtime/codec.go')
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/codec.go316
1 files changed, 316 insertions, 0 deletions
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/codec.go b/vendor/k8s.io/apimachinery/pkg/runtime/codec.go
new file mode 100644
index 000000000..d9748f066
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/codec.go
@@ -0,0 +1,316 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+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.
+*/
+
+package runtime
+
+import (
+ "bytes"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "net/url"
+ "reflect"
+
+ "k8s.io/apimachinery/pkg/conversion/queryparams"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+// codec binds an encoder and decoder.
+type codec struct {
+ Encoder
+ Decoder
+}
+
+// NewCodec creates a Codec from an Encoder and Decoder.
+func NewCodec(e Encoder, d Decoder) Codec {
+ return codec{e, d}
+}
+
+// Encode is a convenience wrapper for encoding to a []byte from an Encoder
+func Encode(e Encoder, obj Object) ([]byte, error) {
+ // TODO: reuse buffer
+ buf := &bytes.Buffer{}
+ if err := e.Encode(obj, buf); err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// Decode is a convenience wrapper for decoding data into an Object.
+func Decode(d Decoder, data []byte) (Object, error) {
+ obj, _, err := d.Decode(data, nil, nil)
+ return obj, err
+}
+
+// DecodeInto performs a Decode into the provided object.
+func DecodeInto(d Decoder, data []byte, into Object) error {
+ out, gvk, err := d.Decode(data, nil, into)
+ if err != nil {
+ return err
+ }
+ if out != into {
+ return fmt.Errorf("unable to decode %s into %v", gvk, reflect.TypeOf(into))
+ }
+ return nil
+}
+
+// EncodeOrDie is a version of Encode which will panic instead of returning an error. For tests.
+func EncodeOrDie(e Encoder, obj Object) string {
+ bytes, err := Encode(e, obj)
+ if err != nil {
+ panic(err)
+ }
+ return string(bytes)
+}
+
+// DefaultingSerializer invokes defaulting after decoding.
+type DefaultingSerializer struct {
+ Defaulter ObjectDefaulter
+ Decoder Decoder
+ // Encoder is optional to allow this type to be used as both a Decoder and an Encoder
+ Encoder
+}
+
+// Decode performs a decode and then allows the defaulter to act on the provided object.
+func (d DefaultingSerializer) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error) {
+ obj, gvk, err := d.Decoder.Decode(data, defaultGVK, into)
+ if err != nil {
+ return obj, gvk, err
+ }
+ d.Defaulter.Default(obj)
+ return obj, gvk, nil
+}
+
+// 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 ObjectTyper, c ObjectCreater, gvk schema.GroupVersionKind, obj Object) (Object, error) {
+ if obj != nil {
+ kinds, _, err := t.ObjectKinds(obj)
+ if err != nil {
+ return nil, err
+ }
+ for _, kind := range kinds {
+ if gvk == kind {
+ return obj, nil
+ }
+ }
+ }
+ return c.New(gvk)
+}
+
+// NoopEncoder converts an Decoder to a Serializer or Codec for code that expects them but only uses decoding.
+type NoopEncoder struct {
+ Decoder
+}
+
+var _ Serializer = NoopEncoder{}
+
+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))
+}
+
+// NoopDecoder converts an Encoder to a Serializer or Codec for code that expects them but only uses encoding.
+type NoopDecoder struct {
+ Encoder
+}
+
+var _ Serializer = NoopDecoder{}
+
+func (n NoopDecoder) Decode(data []byte, gvk *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error) {
+ return nil, nil, fmt.Errorf("decoding is not allowed for this codec: %v", reflect.TypeOf(n.Encoder))
+}
+
+// NewParameterCodec creates a ParameterCodec capable of transforming url values into versioned objects and back.
+func NewParameterCodec(scheme *Scheme) ParameterCodec {
+ return &parameterCodec{
+ typer: scheme,
+ convertor: scheme,
+ creator: scheme,
+ }
+}
+
+// parameterCodec implements conversion to and from query parameters and objects.
+type parameterCodec struct {
+ typer ObjectTyper
+ convertor ObjectConvertor
+ creator ObjectCreater
+}
+
+var _ ParameterCodec = &parameterCodec{}
+
+// DecodeParameters converts the provided url.Values into an object of type From with the kind of into, and then
+// converts that object to into (if necessary). Returns an error if the operation cannot be completed.
+func (c *parameterCodec) DecodeParameters(parameters url.Values, from schema.GroupVersion, into Object) error {
+ if len(parameters) == 0 {
+ return nil
+ }
+ targetGVKs, _, err := c.typer.ObjectKinds(into)
+ if err != nil {
+ return err
+ }
+ for i := range targetGVKs {
+ if targetGVKs[i].GroupVersion() == from {
+ return c.convertor.Convert(&parameters, into, nil)
+ }
+ }
+ input, err := c.creator.New(from.WithKind(targetGVKs[0].Kind))
+ if err != nil {
+ return err
+ }
+ if err := c.convertor.Convert(&parameters, input, nil); err != nil {
+ return err
+ }
+ return c.convertor.Convert(input, into, nil)
+}
+
+// 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 schema.GroupVersion) (url.Values, error) {
+ 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)
+ if err != nil {
+ return nil, err
+ }
+ obj = out
+ }
+ return queryparams.Convert(obj)
+}
+
+type base64Serializer struct {
+ Encoder
+ Decoder
+}
+
+func NewBase64Serializer(e Encoder, d Decoder) Serializer {
+ return &base64Serializer{e, d}
+}
+
+func (s base64Serializer) Encode(obj Object, stream io.Writer) error {
+ e := base64.NewEncoder(base64.StdEncoding, stream)
+ err := s.Encoder.Encode(obj, e)
+ e.Close()
+ return err
+}
+
+func (s base64Serializer) Decode(data []byte, defaults *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error) {
+ out := make([]byte, base64.StdEncoding.DecodedLen(len(data)))
+ n, err := base64.StdEncoding.Decode(out, data)
+ if err != nil {
+ return nil, nil, err
+ }
+ return s.Decoder.Decode(out[:n], defaults, into)
+}
+
+// SerializerInfoForMediaType returns the first info in types that has a matching media type (which cannot
+// include media-type parameters), or the first info with an empty media type, or false if no type matches.
+func SerializerInfoForMediaType(types []SerializerInfo, mediaType string) (SerializerInfo, bool) {
+ for _, info := range types {
+ if info.MediaType == mediaType {
+ return info, true
+ }
+ }
+ for _, info := range types {
+ if len(info.MediaType) == 0 {
+ return info, true
+ }
+ }
+ return SerializerInfo{}, false
+}
+
+var (
+ // InternalGroupVersioner will always prefer the internal version for a given group version kind.
+ InternalGroupVersioner GroupVersioner = internalGroupVersioner{}
+ // DisabledGroupVersioner will reject all kinds passed to it.
+ DisabledGroupVersioner GroupVersioner = disabledGroupVersioner{}
+)
+
+type internalGroupVersioner struct{}
+
+// KindForGroupVersionKinds returns an internal Kind if one is found, or converts the first provided kind to the internal version.
+func (internalGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (schema.GroupVersionKind, bool) {
+ for _, kind := range kinds {
+ if kind.Version == APIVersionInternal {
+ return kind, true
+ }
+ }
+ for _, kind := range kinds {
+ return schema.GroupVersionKind{Group: kind.Group, Version: APIVersionInternal, Kind: kind.Kind}, true
+ }
+ return schema.GroupVersionKind{}, false
+}
+
+type disabledGroupVersioner struct{}
+
+// KindForGroupVersionKinds returns false for any input.
+func (disabledGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (schema.GroupVersionKind, bool) {
+ return schema.GroupVersionKind{}, false
+}
+
+// GroupVersioners implements GroupVersioner and resolves to the first exact match for any kind.
+type GroupVersioners []GroupVersioner
+
+// KindForGroupVersionKinds returns the first match of any of the group versioners, or false if no match occured.
+func (gvs GroupVersioners) KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (schema.GroupVersionKind, bool) {
+ for _, gv := range gvs {
+ target, ok := gv.KindForGroupVersionKinds(kinds)
+ if !ok {
+ continue
+ }
+ return target, true
+ }
+ return schema.GroupVersionKind{}, false
+}
+
+// Assert that schema.GroupVersion and GroupVersions implement GroupVersioner
+var _ GroupVersioner = schema.GroupVersion{}
+var _ GroupVersioner = schema.GroupVersions{}
+var _ GroupVersioner = multiGroupVersioner{}
+
+type multiGroupVersioner struct {
+ target schema.GroupVersion
+ acceptedGroupKinds []schema.GroupKind
+}
+
+// NewMultiGroupVersioner returns the provided group version for any kind that matches one of the provided group kinds.
+// Kind may be empty in the provided group kind, in which case any kind will match.
+func NewMultiGroupVersioner(gv schema.GroupVersion, groupKinds ...schema.GroupKind) GroupVersioner {
+ if len(groupKinds) == 0 || (len(groupKinds) == 1 && groupKinds[0].Group == gv.Group) {
+ return gv
+ }
+ return multiGroupVersioner{target: gv, acceptedGroupKinds: groupKinds}
+}
+
+// KindForGroupVersionKinds returns the target group version if any kind matches any of the original group kinds. It will
+// use the originating kind where possible.
+func (v multiGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (schema.GroupVersionKind, bool) {
+ for _, src := range kinds {
+ for _, kind := range v.acceptedGroupKinds {
+ if kind.Group != src.Group {
+ continue
+ }
+ if len(kind.Kind) > 0 && kind.Kind != src.Kind {
+ continue
+ }
+ return v.target.WithKind(src.Kind), true
+ }
+ }
+ return schema.GroupVersionKind{}, false
+}