aboutsummaryrefslogtreecommitdiff
path: root/vendor/k8s.io/apimachinery/pkg/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/k8s.io/apimachinery/pkg/runtime')
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/codec.go92
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/conversion.go97
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/interfaces.go66
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/negotiate.go146
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/register.go30
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/schema/group_version.go14
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go4
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go48
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go59
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go82
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/types.go15
-rw-r--r--vendor/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go33
12 files changed, 499 insertions, 187 deletions
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/codec.go b/vendor/k8s.io/apimachinery/pkg/runtime/codec.go
index 284e32bc3..0bccf9dd9 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/codec.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/codec.go
@@ -19,13 +19,17 @@ package runtime
import (
"bytes"
"encoding/base64"
+ "encoding/json"
"fmt"
"io"
"net/url"
"reflect"
+ "strconv"
+ "strings"
"k8s.io/apimachinery/pkg/conversion/queryparams"
"k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/klog"
)
// codec binds an encoder and decoder.
@@ -100,10 +104,19 @@ type NoopEncoder struct {
var _ Serializer = NoopEncoder{}
+const noopEncoderIdentifier Identifier = "noop"
+
func (n NoopEncoder) Encode(obj Object, w io.Writer) error {
+ // There is no need to handle runtime.CacheableObject, as we don't
+ // process the obj at all.
return fmt.Errorf("encoding is not allowed for this codec: %v", reflect.TypeOf(n.Decoder))
}
+// Identifier implements runtime.Encoder interface.
+func (n NoopEncoder) Identifier() Identifier {
+ return noopEncoderIdentifier
+}
+
// NoopDecoder converts an Encoder to a Serializer or Codec for code that expects them but only uses encoding.
type NoopDecoder struct {
Encoder
@@ -193,19 +206,51 @@ func (c *parameterCodec) EncodeParameters(obj Object, to schema.GroupVersion) (u
type base64Serializer struct {
Encoder
Decoder
+
+ identifier Identifier
}
func NewBase64Serializer(e Encoder, d Decoder) Serializer {
- return &base64Serializer{e, d}
+ return &base64Serializer{
+ Encoder: e,
+ Decoder: d,
+ identifier: identifier(e),
+ }
+}
+
+func identifier(e Encoder) Identifier {
+ result := map[string]string{
+ "name": "base64",
+ }
+ if e != nil {
+ result["encoder"] = string(e.Identifier())
+ }
+ identifier, err := json.Marshal(result)
+ if err != nil {
+ klog.Fatalf("Failed marshaling identifier for base64Serializer: %v", err)
+ }
+ return Identifier(identifier)
}
func (s base64Serializer) Encode(obj Object, stream io.Writer) error {
+ if co, ok := obj.(CacheableObject); ok {
+ return co.CacheEncode(s.Identifier(), s.doEncode, stream)
+ }
+ return s.doEncode(obj, stream)
+}
+
+func (s base64Serializer) doEncode(obj Object, stream io.Writer) error {
e := base64.NewEncoder(base64.StdEncoding, stream)
err := s.Encoder.Encode(obj, e)
e.Close()
return err
}
+// Identifier implements runtime.Encoder interface.
+func (s base64Serializer) Identifier() Identifier {
+ return s.identifier
+}
+
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)
@@ -238,6 +283,11 @@ var (
DisabledGroupVersioner GroupVersioner = disabledGroupVersioner{}
)
+const (
+ internalGroupVersionerIdentifier = "internal"
+ disabledGroupVersionerIdentifier = "disabled"
+)
+
type internalGroupVersioner struct{}
// KindForGroupVersionKinds returns an internal Kind if one is found, or converts the first provided kind to the internal version.
@@ -253,6 +303,11 @@ func (internalGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersi
return schema.GroupVersionKind{}, false
}
+// Identifier implements GroupVersioner interface.
+func (internalGroupVersioner) Identifier() string {
+ return internalGroupVersionerIdentifier
+}
+
type disabledGroupVersioner struct{}
// KindForGroupVersionKinds returns false for any input.
@@ -260,19 +315,9 @@ func (disabledGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersi
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 occurred.
-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
+// Identifier implements GroupVersioner interface.
+func (disabledGroupVersioner) Identifier() string {
+ return disabledGroupVersionerIdentifier
}
// Assert that schema.GroupVersion and GroupVersions implement GroupVersioner
@@ -330,3 +375,22 @@ func (v multiGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersio
}
return schema.GroupVersionKind{}, false
}
+
+// Identifier implements GroupVersioner interface.
+func (v multiGroupVersioner) Identifier() string {
+ groupKinds := make([]string, 0, len(v.acceptedGroupKinds))
+ for _, gk := range v.acceptedGroupKinds {
+ groupKinds = append(groupKinds, gk.String())
+ }
+ result := map[string]string{
+ "name": "multi",
+ "target": v.target.String(),
+ "accepted": strings.Join(groupKinds, ","),
+ "coerce": strconv.FormatBool(v.coerce),
+ }
+ identifier, err := json.Marshal(result)
+ if err != nil {
+ klog.Fatalf("Failed marshaling Identifier for %#v: %v", v, err)
+ }
+ return string(identifier)
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/conversion.go b/vendor/k8s.io/apimachinery/pkg/runtime/conversion.go
index 08d2abfe6..0947dce73 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/conversion.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/conversion.go
@@ -61,19 +61,21 @@ var DefaultStringConversions = []interface{}{
Convert_Slice_string_To_int64,
}
-func Convert_Slice_string_To_string(input *[]string, out *string, s conversion.Scope) error {
- if len(*input) == 0 {
+func Convert_Slice_string_To_string(in *[]string, out *string, s conversion.Scope) error {
+ if len(*in) == 0 {
*out = ""
+ return nil
}
- *out = (*input)[0]
+ *out = (*in)[0]
return nil
}
-func Convert_Slice_string_To_int(input *[]string, out *int, s conversion.Scope) error {
- if len(*input) == 0 {
+func Convert_Slice_string_To_int(in *[]string, out *int, s conversion.Scope) error {
+ if len(*in) == 0 {
*out = 0
+ return nil
}
- str := (*input)[0]
+ str := (*in)[0]
i, err := strconv.Atoi(str)
if err != nil {
return err
@@ -83,15 +85,16 @@ func Convert_Slice_string_To_int(input *[]string, out *int, s conversion.Scope)
}
// Convert_Slice_string_To_bool will convert a string parameter to boolean.
-// Only the absence of a value, a value of "false", or a value of "0" resolve to false.
+// Only the absence of a value (i.e. zero-length slice), a value of "false", or a
+// value of "0" resolve to false.
// Any other value (including empty string) resolves to true.
-func Convert_Slice_string_To_bool(input *[]string, out *bool, s conversion.Scope) error {
- if len(*input) == 0 {
+func Convert_Slice_string_To_bool(in *[]string, out *bool, s conversion.Scope) error {
+ if len(*in) == 0 {
*out = false
return nil
}
- switch strings.ToLower((*input)[0]) {
- case "false", "0":
+ switch {
+ case (*in)[0] == "0", strings.EqualFold((*in)[0], "false"):
*out = false
default:
*out = true
@@ -99,15 +102,79 @@ func Convert_Slice_string_To_bool(input *[]string, out *bool, s conversion.Scope
return nil
}
-func Convert_Slice_string_To_int64(input *[]string, out *int64, s conversion.Scope) error {
- if len(*input) == 0 {
+// Convert_Slice_string_To_bool will convert a string parameter to boolean.
+// Only the absence of a value (i.e. zero-length slice), a value of "false", or a
+// value of "0" resolve to false.
+// Any other value (including empty string) resolves to true.
+func Convert_Slice_string_To_Pointer_bool(in *[]string, out **bool, s conversion.Scope) error {
+ if len(*in) == 0 {
+ boolVar := false
+ *out = &boolVar
+ return nil
+ }
+ switch {
+ case (*in)[0] == "0", strings.EqualFold((*in)[0], "false"):
+ boolVar := false
+ *out = &boolVar
+ default:
+ boolVar := true
+ *out = &boolVar
+ }
+ return nil
+}
+
+func string_to_int64(in string) (int64, error) {
+ return strconv.ParseInt(in, 10, 64)
+}
+
+func Convert_string_To_int64(in *string, out *int64, s conversion.Scope) error {
+ if in == nil {
+ *out = 0
+ return nil
+ }
+ i, err := string_to_int64(*in)
+ if err != nil {
+ return err
+ }
+ *out = i
+ return nil
+}
+
+func Convert_Slice_string_To_int64(in *[]string, out *int64, s conversion.Scope) error {
+ if len(*in) == 0 {
*out = 0
+ return nil
}
- str := (*input)[0]
- i, err := strconv.ParseInt(str, 10, 64)
+ i, err := string_to_int64((*in)[0])
if err != nil {
return err
}
*out = i
return nil
}
+
+func Convert_string_To_Pointer_int64(in *string, out **int64, s conversion.Scope) error {
+ if in == nil {
+ *out = nil
+ return nil
+ }
+ i, err := string_to_int64(*in)
+ if err != nil {
+ return err
+ }
+ *out = &i
+ return nil
+}
+
+func Convert_Slice_string_To_Pointer_int64(in *[]string, out **int64, s conversion.Scope) error {
+ if len(*in) == 0 {
+ *out = nil
+ return nil
+ }
+ i, err := string_to_int64((*in)[0])
+ if err != nil {
+ return err
+ }
+ *out = &i
+ return nil
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/interfaces.go b/vendor/k8s.io/apimachinery/pkg/runtime/interfaces.go
index bded5bf15..f44693c0c 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/interfaces.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/interfaces.go
@@ -37,13 +37,36 @@ type GroupVersioner interface {
// Scheme.New(target) and then perform a conversion between the current Go type and the destination Go type.
// Sophisticated implementations may use additional information about the input kinds to pick a destination kind.
KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (target schema.GroupVersionKind, ok bool)
+ // Identifier returns string representation of the object.
+ // Identifiers of two different encoders should be equal only if for every input
+ // kinds they return the same result.
+ Identifier() string
}
+// Identifier represents an identifier.
+// Identitier of two different objects should be equal if and only if for every
+// input the output they produce is exactly the same.
+type Identifier string
+
// Encoder writes objects to a serialized form
type Encoder interface {
// 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
+ // Identifier returns an identifier of the encoder.
+ // Identifiers of two different encoders should be equal if and only if for every input
+ // object it will be encoded to the same representation by both of them.
+ //
+ // Identifier is inteted for use with CacheableObject#CacheEncode method. In order to
+ // correctly handle CacheableObject, Encode() method should look similar to below, where
+ // doEncode() is the encoding logic of implemented encoder:
+ // func (e *MyEncoder) Encode(obj Object, w io.Writer) error {
+ // if co, ok := obj.(CacheableObject); ok {
+ // return co.CacheEncode(e.Identifier(), e.doEncode, w)
+ // }
+ // return e.doEncode(obj, w)
+ // }
+ Identifier() Identifier
}
// Decoder attempts to load an object from data.
@@ -132,6 +155,28 @@ type NegotiatedSerializer interface {
DecoderToVersion(serializer Decoder, gv GroupVersioner) Decoder
}
+// ClientNegotiator handles turning an HTTP content type into the appropriate encoder.
+// Use NewClientNegotiator or NewVersionedClientNegotiator to create this interface from
+// a NegotiatedSerializer.
+type ClientNegotiator interface {
+ // Encoder returns the appropriate encoder for the provided contentType (e.g. application/json)
+ // and any optional mediaType parameters (e.g. pretty=1), or an error. If no serializer is found
+ // a NegotiateError will be returned. The current client implementations consider params to be
+ // optional modifiers to the contentType and will ignore unrecognized parameters.
+ Encoder(contentType string, params map[string]string) (Encoder, error)
+ // Decoder returns the appropriate decoder for the provided contentType (e.g. application/json)
+ // and any optional mediaType parameters (e.g. pretty=1), or an error. If no serializer is found
+ // a NegotiateError will be returned. The current client implementations consider params to be
+ // optional modifiers to the contentType and will ignore unrecognized parameters.
+ Decoder(contentType string, params map[string]string) (Decoder, error)
+ // StreamDecoder returns the appropriate stream decoder for the provided contentType (e.g.
+ // application/json) and any optional mediaType parameters (e.g. pretty=1), or an error. If no
+ // serializer is found a NegotiateError will be returned. The Serializer and Framer will always
+ // be returned if a Decoder is returned. The current client implementations consider params to be
+ // optional modifiers to the contentType and will ignore unrecognized parameters.
+ StreamDecoder(contentType string, params map[string]string) (Decoder, Serializer, Framer, error)
+}
+
// StorageSerializer is an interface used for obtaining encoders, decoders, and serializers
// that can read and write data at rest. This would commonly be used by client tools that must
// read files, or server side storage interfaces that persist restful objects.
@@ -256,6 +301,27 @@ type Object interface {
DeepCopyObject() Object
}
+// CacheableObject allows an object to cache its different serializations
+// to avoid performing the same serialization multiple times.
+type CacheableObject interface {
+ // CacheEncode writes an object to a stream. The <encode> function will
+ // be used in case of cache miss. The <encode> function takes ownership
+ // of the object.
+ // If CacheableObject is a wrapper, then deep-copy of the wrapped object
+ // should be passed to <encode> function.
+ // CacheEncode assumes that for two different calls with the same <id>,
+ // <encode> function will also be the same.
+ CacheEncode(id Identifier, encode func(Object, io.Writer) error, w io.Writer) error
+ // GetObject returns a deep-copy of an object to be encoded - the caller of
+ // GetObject() is the owner of returned object. The reason for making a copy
+ // is to avoid bugs, where caller modifies the object and forgets to copy it,
+ // thus modifying the object for everyone.
+ // The object returned by GetObject should be the same as the one that is supposed
+ // to be passed to <encode> function in CacheEncode method.
+ // If CacheableObject is a wrapper, the copy of wrapped object should be returned.
+ GetObject() Object
+}
+
// Unstructured objects store values as map[string]interface{}, with only values that can be serialized
// to JSON allowed.
type Unstructured interface {
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/negotiate.go b/vendor/k8s.io/apimachinery/pkg/runtime/negotiate.go
new file mode 100644
index 000000000..159b30120
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/negotiate.go
@@ -0,0 +1,146 @@
+/*
+Copyright 2019 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 (
+ "fmt"
+
+ "k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+// NegotiateError is returned when a ClientNegotiator is unable to locate
+// a serializer for the requested operation.
+type NegotiateError struct {
+ ContentType string
+ Stream bool
+}
+
+func (e NegotiateError) Error() string {
+ if e.Stream {
+ return fmt.Sprintf("no stream serializers registered for %s", e.ContentType)
+ }
+ return fmt.Sprintf("no serializers registered for %s", e.ContentType)
+}
+
+type clientNegotiator struct {
+ serializer NegotiatedSerializer
+ encode, decode GroupVersioner
+}
+
+func (n *clientNegotiator) Encoder(contentType string, params map[string]string) (Encoder, error) {
+ // TODO: `pretty=1` is handled in NegotiateOutputMediaType, consider moving it to this method
+ // if client negotiators truly need to use it
+ mediaTypes := n.serializer.SupportedMediaTypes()
+ info, ok := SerializerInfoForMediaType(mediaTypes, contentType)
+ if !ok {
+ if len(contentType) != 0 || len(mediaTypes) == 0 {
+ return nil, NegotiateError{ContentType: contentType}
+ }
+ info = mediaTypes[0]
+ }
+ return n.serializer.EncoderForVersion(info.Serializer, n.encode), nil
+}
+
+func (n *clientNegotiator) Decoder(contentType string, params map[string]string) (Decoder, error) {
+ mediaTypes := n.serializer.SupportedMediaTypes()
+ info, ok := SerializerInfoForMediaType(mediaTypes, contentType)
+ if !ok {
+ if len(contentType) != 0 || len(mediaTypes) == 0 {
+ return nil, NegotiateError{ContentType: contentType}
+ }
+ info = mediaTypes[0]
+ }
+ return n.serializer.DecoderToVersion(info.Serializer, n.decode), nil
+}
+
+func (n *clientNegotiator) StreamDecoder(contentType string, params map[string]string) (Decoder, Serializer, Framer, error) {
+ mediaTypes := n.serializer.SupportedMediaTypes()
+ info, ok := SerializerInfoForMediaType(mediaTypes, contentType)
+ if !ok {
+ if len(contentType) != 0 || len(mediaTypes) == 0 {
+ return nil, nil, nil, NegotiateError{ContentType: contentType, Stream: true}
+ }
+ info = mediaTypes[0]
+ }
+ if info.StreamSerializer == nil {
+ return nil, nil, nil, NegotiateError{ContentType: info.MediaType, Stream: true}
+ }
+ return n.serializer.DecoderToVersion(info.Serializer, n.decode), info.StreamSerializer.Serializer, info.StreamSerializer.Framer, nil
+}
+
+// NewClientNegotiator will attempt to retrieve the appropriate encoder, decoder, or
+// stream decoder for a given content type. Does not perform any conversion, but will
+// encode the object to the desired group, version, and kind. Use when creating a client.
+func NewClientNegotiator(serializer NegotiatedSerializer, gv schema.GroupVersion) ClientNegotiator {
+ return &clientNegotiator{
+ serializer: serializer,
+ encode: gv,
+ }
+}
+
+// NewInternalClientNegotiator applies the default client rules for connecting to a Kubernetes apiserver
+// where objects are converted to gv prior to sending and decoded to their internal representation prior
+// to retrieval.
+//
+// DEPRECATED: Internal clients are deprecated and will be removed in a future Kubernetes release.
+func NewInternalClientNegotiator(serializer NegotiatedSerializer, gv schema.GroupVersion) ClientNegotiator {
+ decode := schema.GroupVersions{
+ {
+ Group: gv.Group,
+ Version: APIVersionInternal,
+ },
+ // always include the legacy group as a decoding target to handle non-error `Status` return types
+ {
+ Group: "",
+ Version: APIVersionInternal,
+ },
+ }
+ return &clientNegotiator{
+ encode: gv,
+ decode: decode,
+ serializer: serializer,
+ }
+}
+
+// NewSimpleClientNegotiator will negotiate for a single serializer. This should only be used
+// for testing or when the caller is taking responsibility for setting the GVK on encoded objects.
+func NewSimpleClientNegotiator(info SerializerInfo, gv schema.GroupVersion) ClientNegotiator {
+ return &clientNegotiator{
+ serializer: &simpleNegotiatedSerializer{info: info},
+ encode: gv,
+ }
+}
+
+type simpleNegotiatedSerializer struct {
+ info SerializerInfo
+}
+
+func NewSimpleNegotiatedSerializer(info SerializerInfo) NegotiatedSerializer {
+ return &simpleNegotiatedSerializer{info: info}
+}
+
+func (n *simpleNegotiatedSerializer) SupportedMediaTypes() []SerializerInfo {
+ return []SerializerInfo{n.info}
+}
+
+func (n *simpleNegotiatedSerializer) EncoderForVersion(e Encoder, _ GroupVersioner) Encoder {
+ return e
+}
+
+func (n *simpleNegotiatedSerializer) DecoderToVersion(d Decoder, _gv GroupVersioner) Decoder {
+ return d
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/register.go b/vendor/k8s.io/apimachinery/pkg/runtime/register.go
index eeb380c3d..1cd2e4c38 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/register.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/register.go
@@ -29,33 +29,3 @@ func (obj *TypeMeta) GroupVersionKind() schema.GroupVersionKind {
}
func (obj *TypeMeta) GetObjectKind() schema.ObjectKind { return obj }
-
-// GetObjectKind implements Object for VersionedObjects, returning an empty ObjectKind
-// interface if no objects are provided, or the ObjectKind interface of the object in the
-// highest array position.
-func (obj *VersionedObjects) GetObjectKind() schema.ObjectKind {
- last := obj.Last()
- if last == nil {
- return schema.EmptyObjectKind
- }
- return last.GetObjectKind()
-}
-
-// First returns the leftmost object in the VersionedObjects array, which is usually the
-// object as serialized on the wire.
-func (obj *VersionedObjects) First() Object {
- if len(obj.Objects) == 0 {
- return nil
- }
- return obj.Objects[0]
-}
-
-// Last is the rightmost object in the VersionedObjects array, which is the object after
-// all transformations have been applied. This is the same object that would be returned
-// by Decode in a normal invocation (without VersionedObjects in the into argument).
-func (obj *VersionedObjects) Last() Object {
- if len(obj.Objects) == 0 {
- return nil
- }
- return obj.Objects[len(obj.Objects)-1]
-}
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/schema/group_version.go b/vendor/k8s.io/apimachinery/pkg/runtime/schema/group_version.go
index 4c67ed598..636103312 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/schema/group_version.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/schema/group_version.go
@@ -191,6 +191,11 @@ func (gv GroupVersion) String() string {
return gv.Version
}
+// Identifier implements runtime.GroupVersioner interface.
+func (gv GroupVersion) Identifier() string {
+ return gv.String()
+}
+
// KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false
// if none of the options match the group. It prefers a match to group and version over just group.
// TODO: Move GroupVersion to a package under pkg/runtime, since it's used by scheme.
@@ -246,6 +251,15 @@ func (gv GroupVersion) WithResource(resource string) GroupVersionResource {
// in fewer places.
type GroupVersions []GroupVersion
+// Identifier implements runtime.GroupVersioner interface.
+func (gv GroupVersions) Identifier() string {
+ groupVersions := make([]string, 0, len(gv))
+ for i := range gv {
+ groupVersions = append(groupVersions, gv[i].String())
+ }
+ return fmt.Sprintf("[%s]", strings.Join(groupVersions, ","))
+}
+
// KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false
// if none of the options match the group.
func (gvs GroupVersions) KindForGroupVersionKinds(kinds []GroupVersionKind) (GroupVersionKind, bool) {
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go
index d1d407397..f21b0ef19 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go
@@ -322,7 +322,3 @@ func (f WithoutConversionCodecFactory) DecoderToVersion(serializer runtime.Decod
Decoder: serializer,
}
}
-
-// DirectCodecFactory was renamed to WithoutConversionCodecFactory in 1.15.
-// TODO: remove in 1.16.
-type DirectCodecFactory = WithoutConversionCodecFactory
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go
index 69ada8ecf..9d17f09e5 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go
@@ -31,6 +31,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
"k8s.io/apimachinery/pkg/util/framer"
utilyaml "k8s.io/apimachinery/pkg/util/yaml"
+ "k8s.io/klog"
)
// NewSerializer creates a JSON serializer that handles encoding versioned objects into the proper JSON form. If typer
@@ -53,13 +54,28 @@ func NewYAMLSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer ru
// and are immutable.
func NewSerializerWithOptions(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, options SerializerOptions) *Serializer {
return &Serializer{
- meta: meta,
- creater: creater,
- typer: typer,
- options: options,
+ meta: meta,
+ creater: creater,
+ typer: typer,
+ options: options,
+ identifier: identifier(options),
}
}
+// identifier computes Identifier of Encoder based on the given options.
+func identifier(options SerializerOptions) runtime.Identifier {
+ result := map[string]string{
+ "name": "json",
+ "yaml": strconv.FormatBool(options.Yaml),
+ "pretty": strconv.FormatBool(options.Pretty),
+ }
+ identifier, err := json.Marshal(result)
+ if err != nil {
+ klog.Fatalf("Failed marshaling identifier for json Serializer: %v", err)
+ }
+ return runtime.Identifier(identifier)
+}
+
// SerializerOptions holds the options which are used to configure a JSON/YAML serializer.
// example:
// (1) To configure a JSON serializer, set `Yaml` to `false`.
@@ -85,6 +101,8 @@ type Serializer struct {
options SerializerOptions
creater runtime.ObjectCreater
typer runtime.ObjectTyper
+
+ identifier runtime.Identifier
}
// Serializer implements Serializer
@@ -188,16 +206,6 @@ func gvkWithDefaults(actual, defaultGVK schema.GroupVersionKind) schema.GroupVer
// On success or most errors, the method will return the calculated schema kind.
// The gvk calculate priority will be originalData > default gvk > into
func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
- if versioned, ok := into.(*runtime.VersionedObjects); ok {
- into = versioned.Last()
- obj, actual, err := s.Decode(originalData, gvk, into)
- if err != nil {
- return nil, actual, err
- }
- versioned.Objects = []runtime.Object{obj}
- return versioned, actual, nil
- }
-
data := originalData
if s.options.Yaml {
altered, err := yaml.YAMLToJSON(data)
@@ -286,6 +294,13 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i
// Encode serializes the provided object to the given writer.
func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
+ if co, ok := obj.(runtime.CacheableObject); ok {
+ return co.CacheEncode(s.Identifier(), s.doEncode, w)
+ }
+ return s.doEncode(obj, w)
+}
+
+func (s *Serializer) doEncode(obj runtime.Object, w io.Writer) error {
if s.options.Yaml {
json, err := caseSensitiveJsonIterator.Marshal(obj)
if err != nil {
@@ -311,6 +326,11 @@ func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
return encoder.Encode(obj)
}
+// Identifier implements runtime.Encoder interface.
+func (s *Serializer) Identifier() runtime.Identifier {
+ return s.identifier
+}
+
// RecognizesData implements the RecognizingDecoder interface.
func (s *Serializer) RecognizesData(peek io.Reader) (ok, unknown bool, err error) {
if s.options.Yaml {
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go
index 0f33e1d82..f606b7d72 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go
@@ -86,6 +86,8 @@ type Serializer struct {
var _ runtime.Serializer = &Serializer{}
var _ recognizer.RecognizingDecoder = &Serializer{}
+const serializerIdentifier runtime.Identifier = "protobuf"
+
// Decode attempts to convert the provided data into a protobuf message, extract the stored schema kind, apply the provided default
// gvk, and then load that data into an object matching the desired schema kind or the provided into. If into is *runtime.Unknown,
// the raw data will be extracted and no decoding will be performed. If into is not registered with the typer, then the object will
@@ -93,23 +95,6 @@ var _ recognizer.RecognizingDecoder = &Serializer{}
// not fully qualified with kind/version/group, the type of the into will be used to alter the returned gvk. On success or most
// errors, the method will return the calculated schema kind.
func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
- if versioned, ok := into.(*runtime.VersionedObjects); ok {
- into = versioned.Last()
- obj, actual, err := s.Decode(originalData, gvk, into)
- if err != nil {
- return nil, actual, err
- }
- // the last item in versioned becomes into, so if versioned was not originally empty we reset the object
- // array so the first position is the decoded object and the second position is the outermost object.
- // if there were no objects in the versioned list passed to us, only add ourselves.
- if into != nil && into != obj {
- versioned.Objects = []runtime.Object{obj, into}
- } else {
- versioned.Objects = []runtime.Object{obj}
- }
- return versioned, actual, err
- }
-
prefixLen := len(s.prefix)
switch {
case len(originalData) == 0:
@@ -176,6 +161,13 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i
// Encode serializes the provided object to the given writer.
func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
+ if co, ok := obj.(runtime.CacheableObject); ok {
+ return co.CacheEncode(s.Identifier(), s.doEncode, w)
+ }
+ return s.doEncode(obj, w)
+}
+
+func (s *Serializer) doEncode(obj runtime.Object, w io.Writer) error {
prefixSize := uint64(len(s.prefix))
var unk runtime.Unknown
@@ -245,6 +237,11 @@ func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
}
}
+// Identifier implements runtime.Encoder interface.
+func (s *Serializer) Identifier() runtime.Identifier {
+ return serializerIdentifier
+}
+
// RecognizesData implements the RecognizingDecoder interface.
func (s *Serializer) RecognizesData(peek io.Reader) (bool, bool, error) {
prefix := make([]byte, 4)
@@ -321,6 +318,8 @@ type RawSerializer struct {
var _ runtime.Serializer = &RawSerializer{}
+const rawSerializerIdentifier runtime.Identifier = "raw-protobuf"
+
// Decode attempts to convert the provided data into a protobuf message, extract the stored schema kind, apply the provided default
// gvk, and then load that data into an object matching the desired schema kind or the provided into. If into is *runtime.Unknown,
// the raw data will be extracted and no decoding will be performed. If into is not registered with the typer, then the object will
@@ -332,20 +331,6 @@ func (s *RawSerializer) Decode(originalData []byte, gvk *schema.GroupVersionKind
return nil, nil, fmt.Errorf("this serializer requires an object to decode into: %#v", s)
}
- if versioned, ok := into.(*runtime.VersionedObjects); ok {
- into = versioned.Last()
- obj, actual, err := s.Decode(originalData, gvk, into)
- if err != nil {
- return nil, actual, err
- }
- if into != nil && into != obj {
- versioned.Objects = []runtime.Object{obj, into}
- } else {
- versioned.Objects = []runtime.Object{obj}
- }
- return versioned, actual, err
- }
-
if len(originalData) == 0 {
// TODO: treat like decoding {} from JSON with defaulting
return nil, nil, fmt.Errorf("empty data")
@@ -419,6 +404,13 @@ func unmarshalToObject(typer runtime.ObjectTyper, creater runtime.ObjectCreater,
// Encode serializes the provided object to the given writer. Overrides is ignored.
func (s *RawSerializer) Encode(obj runtime.Object, w io.Writer) error {
+ if co, ok := obj.(runtime.CacheableObject); ok {
+ return co.CacheEncode(s.Identifier(), s.doEncode, w)
+ }
+ return s.doEncode(obj, w)
+}
+
+func (s *RawSerializer) doEncode(obj runtime.Object, w io.Writer) error {
switch t := obj.(type) {
case bufferedReverseMarshaller:
// this path performs a single allocation during write but requires the caller to implement
@@ -460,6 +452,11 @@ func (s *RawSerializer) Encode(obj runtime.Object, w io.Writer) error {
}
}
+// Identifier implements runtime.Encoder interface.
+func (s *RawSerializer) Identifier() runtime.Identifier {
+ return rawSerializerIdentifier
+}
+
var LengthDelimitedFramer = lengthDelimitedFramer{}
type lengthDelimitedFramer struct{}
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go
index ee5cb86f7..ced184c91 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go
@@ -17,12 +17,15 @@ limitations under the License.
package versioning
import (
+ "encoding/json"
"io"
"reflect"
+ "sync"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/klog"
)
// NewDefaultingCodecForScheme is a convenience method for callers that are using a scheme.
@@ -62,6 +65,8 @@ func NewCodec(
encodeVersion: encodeVersion,
decodeVersion: decodeVersion,
+ identifier: identifier(encodeVersion, encoder),
+
originalSchemeName: originalSchemeName,
}
return internal
@@ -78,19 +83,47 @@ type codec struct {
encodeVersion runtime.GroupVersioner
decodeVersion runtime.GroupVersioner
+ identifier runtime.Identifier
+
// originalSchemeName is optional, but when filled in it holds the name of the scheme from which this codec originates
originalSchemeName string
}
+var identifiersMap sync.Map
+
+type codecIdentifier struct {
+ EncodeGV string `json:"encodeGV,omitempty"`
+ Encoder string `json:"encoder,omitempty"`
+ Name string `json:"name,omitempty"`
+}
+
+// identifier computes Identifier of Encoder based on codec parameters.
+func identifier(encodeGV runtime.GroupVersioner, encoder runtime.Encoder) runtime.Identifier {
+ result := codecIdentifier{
+ Name: "versioning",
+ }
+
+ if encodeGV != nil {
+ result.EncodeGV = encodeGV.Identifier()
+ }
+ if encoder != nil {
+ result.Encoder = string(encoder.Identifier())
+ }
+ if id, ok := identifiersMap.Load(result); ok {
+ return id.(runtime.Identifier)
+ }
+ identifier, err := json.Marshal(result)
+ if err != nil {
+ klog.Fatalf("Failed marshaling identifier for codec: %v", err)
+ }
+ identifiersMap.Store(result, runtime.Identifier(identifier))
+ return runtime.Identifier(identifier)
+}
+
// Decode attempts a decode of the object, then tries to convert it to the internal version. If into is provided and the decoding is
// successful, the returned runtime.Object will be the value passed as into. Note that this may bypass conversion if you pass an
// into that matches the serialized version.
func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
- versioned, isVersioned := into.(*runtime.VersionedObjects)
- if isVersioned {
- into = versioned.Last()
- }
-
// If the into object is unstructured and expresses an opinion about its group/version,
// create a new instance of the type so we always exercise the conversion path (skips short-circuiting on `into == obj`)
decodeInto := into
@@ -115,22 +148,11 @@ func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into ru
if into != nil {
// perform defaulting if requested
if c.defaulter != nil {
- // create a copy to ensure defaulting is not applied to the original versioned objects
- if isVersioned {
- versioned.Objects = []runtime.Object{obj.DeepCopyObject()}
- }
c.defaulter.Default(obj)
- } else {
- if isVersioned {
- versioned.Objects = []runtime.Object{obj}
- }
}
// Short-circuit conversion if the into object is same object
if into == obj {
- if isVersioned {
- return versioned, gvk, nil
- }
return into, gvk, nil
}
@@ -138,19 +160,9 @@ func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into ru
return nil, gvk, err
}
- if isVersioned {
- versioned.Objects = append(versioned.Objects, into)
- return versioned, gvk, nil
- }
return into, gvk, nil
}
- // Convert if needed.
- if isVersioned {
- // create a copy, because ConvertToVersion does not guarantee non-mutation of objects
- versioned.Objects = []runtime.Object{obj.DeepCopyObject()}
- }
-
// perform defaulting if requested
if c.defaulter != nil {
c.defaulter.Default(obj)
@@ -160,18 +172,19 @@ func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into ru
if err != nil {
return nil, gvk, err
}
- if isVersioned {
- if versioned.Last() != out {
- versioned.Objects = append(versioned.Objects, out)
- }
- return versioned, gvk, nil
- }
return out, gvk, nil
}
// 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 co, ok := obj.(runtime.CacheableObject); ok {
+ return co.CacheEncode(c.Identifier(), c.doEncode, w)
+ }
+ return c.doEncode(obj, w)
+}
+
+func (c *codec) doEncode(obj runtime.Object, w io.Writer) error {
switch obj := obj.(type) {
case *runtime.Unknown:
return c.encoder.Encode(obj, w)
@@ -230,3 +243,8 @@ func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
// Conversion is responsible for setting the proper group, version, and kind onto the outgoing object
return c.encoder.Encode(out, w)
}
+
+// Identifier implements runtime.Encoder interface.
+func (c *codec) Identifier() runtime.Identifier {
+ return c.identifier
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/types.go b/vendor/k8s.io/apimachinery/pkg/runtime/types.go
index 3d3ebe5f9..31359f35f 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/types.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/types.go
@@ -95,7 +95,7 @@ type RawExtension struct {
// Raw is the underlying serialization of this object.
//
// TODO: Determine how to detect ContentType and ContentEncoding of 'Raw' data.
- Raw []byte `protobuf:"bytes,1,opt,name=raw"`
+ Raw []byte `json:"-" protobuf:"bytes,1,opt,name=raw"`
// Object can hold a representation of this extension - useful for working with versioned
// structs.
Object Object `json:"-"`
@@ -124,16 +124,3 @@ type Unknown struct {
// Unspecified means ContentTypeJSON.
ContentType string `protobuf:"bytes,4,opt,name=contentType"`
}
-
-// VersionedObjects is used by Decoders to give callers a way to access all versions
-// of an object during the decoding process.
-//
-// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
-// +k8s:deepcopy-gen=true
-type VersionedObjects struct {
- // Objects is the set of objects retrieved during decoding, in order of conversion.
- // The 0 index is the object as serialized on the wire. If conversion has occurred,
- // other objects may be present. The right most object is the same as would be returned
- // by a normal Decode call.
- Objects []Object
-}
diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go b/vendor/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go
index 8b9182f35..b0393839e 100644
--- a/vendor/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go
+++ b/vendor/k8s.io/apimachinery/pkg/runtime/zz_generated.deepcopy.go
@@ -73,36 +73,3 @@ func (in *Unknown) DeepCopyObject() Object {
}
return nil
}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *VersionedObjects) DeepCopyInto(out *VersionedObjects) {
- *out = *in
- if in.Objects != nil {
- in, out := &in.Objects, &out.Objects
- *out = make([]Object, len(*in))
- for i := range *in {
- if (*in)[i] != nil {
- (*out)[i] = (*in)[i].DeepCopyObject()
- }
- }
- }
- return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VersionedObjects.
-func (in *VersionedObjects) DeepCopy() *VersionedObjects {
- if in == nil {
- return nil
- }
- out := new(VersionedObjects)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new Object.
-func (in *VersionedObjects) DeepCopyObject() Object {
- if c := in.DeepCopy(); c != nil {
- return c
- }
- return nil
-}