141
									
								
								vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										141
									
								
								vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -17,9 +17,13 @@ limitations under the License. | ||||
| package serializer | ||||
|  | ||||
| import ( | ||||
| 	"mime" | ||||
| 	"strings" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/serializer/json" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/serializer/protobuf" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/serializer/recognizer" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/serializer/versioning" | ||||
| ) | ||||
| @ -44,30 +48,53 @@ type serializerType struct { | ||||
| 	StreamSerializer runtime.Serializer | ||||
| } | ||||
|  | ||||
| func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory) []serializerType { | ||||
| 	jsonSerializer := json.NewSerializer(mf, scheme, scheme, false) | ||||
| 	jsonPrettySerializer := json.NewSerializer(mf, scheme, scheme, true) | ||||
| 	yamlSerializer := json.NewYAMLSerializer(mf, scheme, scheme) | ||||
| func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, options CodecFactoryOptions) []serializerType { | ||||
| 	jsonSerializer := json.NewSerializerWithOptions( | ||||
| 		mf, scheme, scheme, | ||||
| 		json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict}, | ||||
| 	) | ||||
| 	jsonSerializerType := serializerType{ | ||||
| 		AcceptContentTypes: []string{runtime.ContentTypeJSON}, | ||||
| 		ContentType:        runtime.ContentTypeJSON, | ||||
| 		FileExtensions:     []string{"json"}, | ||||
| 		EncodesAsText:      true, | ||||
| 		Serializer:         jsonSerializer, | ||||
|  | ||||
| 		Framer:           json.Framer, | ||||
| 		StreamSerializer: jsonSerializer, | ||||
| 	} | ||||
| 	if options.Pretty { | ||||
| 		jsonSerializerType.PrettySerializer = json.NewSerializerWithOptions( | ||||
| 			mf, scheme, scheme, | ||||
| 			json.SerializerOptions{Yaml: false, Pretty: true, Strict: options.Strict}, | ||||
| 		) | ||||
| 	} | ||||
|  | ||||
| 	yamlSerializer := json.NewSerializerWithOptions( | ||||
| 		mf, scheme, scheme, | ||||
| 		json.SerializerOptions{Yaml: true, Pretty: false, Strict: options.Strict}, | ||||
| 	) | ||||
| 	protoSerializer := protobuf.NewSerializer(scheme, scheme) | ||||
| 	protoRawSerializer := protobuf.NewRawSerializer(scheme, scheme) | ||||
|  | ||||
| 	serializers := []serializerType{ | ||||
| 		jsonSerializerType, | ||||
| 		{ | ||||
| 			AcceptContentTypes: []string{"application/json"}, | ||||
| 			ContentType:        "application/json", | ||||
| 			FileExtensions:     []string{"json"}, | ||||
| 			EncodesAsText:      true, | ||||
| 			Serializer:         jsonSerializer, | ||||
| 			PrettySerializer:   jsonPrettySerializer, | ||||
|  | ||||
| 			Framer:           json.Framer, | ||||
| 			StreamSerializer: jsonSerializer, | ||||
| 		}, | ||||
| 		{ | ||||
| 			AcceptContentTypes: []string{"application/yaml"}, | ||||
| 			ContentType:        "application/yaml", | ||||
| 			AcceptContentTypes: []string{runtime.ContentTypeYAML}, | ||||
| 			ContentType:        runtime.ContentTypeYAML, | ||||
| 			FileExtensions:     []string{"yaml"}, | ||||
| 			EncodesAsText:      true, | ||||
| 			Serializer:         yamlSerializer, | ||||
| 		}, | ||||
| 		{ | ||||
| 			AcceptContentTypes: []string{runtime.ContentTypeProtobuf}, | ||||
| 			ContentType:        runtime.ContentTypeProtobuf, | ||||
| 			FileExtensions:     []string{"pb"}, | ||||
| 			Serializer:         protoSerializer, | ||||
|  | ||||
| 			Framer:           protobuf.LengthDelimitedFramer, | ||||
| 			StreamSerializer: protoRawSerializer, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, fn := range serializerExtensions { | ||||
| @ -89,14 +116,56 @@ type CodecFactory struct { | ||||
| 	legacySerializer runtime.Serializer | ||||
| } | ||||
|  | ||||
| // CodecFactoryOptions holds the options for configuring CodecFactory behavior | ||||
| type CodecFactoryOptions struct { | ||||
| 	// Strict configures all serializers in strict mode | ||||
| 	Strict bool | ||||
| 	// Pretty includes a pretty serializer along with the non-pretty one | ||||
| 	Pretty bool | ||||
| } | ||||
|  | ||||
| // CodecFactoryOptionsMutator takes a pointer to an options struct and then modifies it. | ||||
| // Functions implementing this type can be passed to the NewCodecFactory() constructor. | ||||
| type CodecFactoryOptionsMutator func(*CodecFactoryOptions) | ||||
|  | ||||
| // EnablePretty enables including a pretty serializer along with the non-pretty one | ||||
| func EnablePretty(options *CodecFactoryOptions) { | ||||
| 	options.Pretty = true | ||||
| } | ||||
|  | ||||
| // DisablePretty disables including a pretty serializer along with the non-pretty one | ||||
| func DisablePretty(options *CodecFactoryOptions) { | ||||
| 	options.Pretty = false | ||||
| } | ||||
|  | ||||
| // EnableStrict enables configuring all serializers in strict mode | ||||
| func EnableStrict(options *CodecFactoryOptions) { | ||||
| 	options.Strict = true | ||||
| } | ||||
|  | ||||
| // DisableStrict disables configuring all serializers in strict mode | ||||
| func DisableStrict(options *CodecFactoryOptions) { | ||||
| 	options.Strict = false | ||||
| } | ||||
|  | ||||
| // NewCodecFactory provides methods for retrieving serializers for the supported wire formats | ||||
| // and conversion wrappers to define preferred internal and external versions. In the future, | ||||
| // as the internal version is used less, callers may instead use a defaulting serializer and | ||||
| // only convert objects which are shared internally (Status, common API machinery). | ||||
| // | ||||
| // Mutators can be passed to change the CodecFactoryOptions before construction of the factory. | ||||
| // It is recommended to explicitly pass mutators instead of relying on defaults. | ||||
| // By default, Pretty is enabled -- this is conformant with previously supported behavior. | ||||
| // | ||||
| // TODO: allow other codecs to be compiled in? | ||||
| // TODO: accept a scheme interface | ||||
| func NewCodecFactory(scheme *runtime.Scheme) CodecFactory { | ||||
| 	serializers := newSerializersForScheme(scheme, json.DefaultMetaFactory) | ||||
| func NewCodecFactory(scheme *runtime.Scheme, mutators ...CodecFactoryOptionsMutator) CodecFactory { | ||||
| 	options := CodecFactoryOptions{Pretty: true} | ||||
| 	for _, fn := range mutators { | ||||
| 		fn(&options) | ||||
| 	} | ||||
|  | ||||
| 	serializers := newSerializersForScheme(scheme, json.DefaultMetaFactory, options) | ||||
| 	return newCodecFactory(scheme, serializers) | ||||
| } | ||||
|  | ||||
| @ -120,6 +189,15 @@ func newCodecFactory(scheme *runtime.Scheme, serializers []serializerType) Codec | ||||
| 				Serializer:       d.Serializer, | ||||
| 				PrettySerializer: d.PrettySerializer, | ||||
| 			} | ||||
|  | ||||
| 			mediaType, _, err := mime.ParseMediaType(info.MediaType) | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 			parts := strings.SplitN(mediaType, "/", 2) | ||||
| 			info.MediaTypeType = parts[0] | ||||
| 			info.MediaTypeSubType = parts[1] | ||||
|  | ||||
| 			if d.StreamSerializer != nil { | ||||
| 				info.StreamSerializer = &runtime.StreamSerializerInfo{ | ||||
| 					Serializer:    d.StreamSerializer, | ||||
| @ -148,6 +226,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 | ||||
| @ -215,23 +299,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, | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										141
									
								
								vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										141
									
								
								vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -31,38 +31,78 @@ import ( | ||||
| 	"k8s.io/apimachinery/pkg/runtime/serializer/recognizer" | ||||
| 	"k8s.io/apimachinery/pkg/util/framer" | ||||
| 	utilyaml "k8s.io/apimachinery/pkg/util/yaml" | ||||
| 	"k8s.io/klog/v2" | ||||
| ) | ||||
|  | ||||
| // 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. | ||||
| // Deprecated: use NewSerializerWithOptions instead. | ||||
| func NewSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, pretty bool) *Serializer { | ||||
| 	return &Serializer{ | ||||
| 		meta:    meta, | ||||
| 		creater: creater, | ||||
| 		typer:   typer, | ||||
| 		yaml:    false, | ||||
| 		pretty:  pretty, | ||||
| 	} | ||||
| 	return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{false, pretty, false}) | ||||
| } | ||||
|  | ||||
| // 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. | ||||
| // Deprecated: use NewSerializerWithOptions instead. | ||||
| func NewYAMLSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper) *Serializer { | ||||
| 	return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{true, false, false}) | ||||
| } | ||||
|  | ||||
| // NewSerializerWithOptions creates a JSON/YAML serializer that handles encoding versioned objects into the proper JSON/YAML | ||||
| // form. If typer is not nil, the object has the group, version, and kind fields set. Options are copied into the Serializer | ||||
| // and are immutable. | ||||
| func NewSerializerWithOptions(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, options SerializerOptions) *Serializer { | ||||
| 	return &Serializer{ | ||||
| 		meta:    meta, | ||||
| 		creater: creater, | ||||
| 		typer:   typer, | ||||
| 		yaml:    true, | ||||
| 		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`. | ||||
| // (2) To configure a YAML serializer, set `Yaml` to `true`. | ||||
| // (3) To configure a strict serializer that can return strictDecodingError, set `Strict` to `true`. | ||||
| type SerializerOptions struct { | ||||
| 	// Yaml: configures the Serializer to work with JSON(false) or YAML(true). | ||||
| 	// When `Yaml` is enabled, this serializer only supports the subset of YAML that | ||||
| 	// matches JSON, and will error if constructs are used that do not serialize to JSON. | ||||
| 	Yaml bool | ||||
|  | ||||
| 	// Pretty: configures a JSON enabled Serializer(`Yaml: false`) to produce human-readable output. | ||||
| 	// This option is silently ignored when `Yaml` is `true`. | ||||
| 	Pretty bool | ||||
|  | ||||
| 	// Strict: configures the Serializer to return strictDecodingError's when duplicate fields are present decoding JSON or YAML. | ||||
| 	// Note that enabling this option is not as performant as the non-strict variant, and should not be used in fast paths. | ||||
| 	Strict bool | ||||
| } | ||||
|  | ||||
| type Serializer struct { | ||||
| 	meta    MetaFactory | ||||
| 	options SerializerOptions | ||||
| 	creater runtime.ObjectCreater | ||||
| 	typer   runtime.ObjectTyper | ||||
| 	yaml    bool | ||||
| 	pretty  bool | ||||
|  | ||||
| 	identifier runtime.Identifier | ||||
| } | ||||
|  | ||||
| // Serializer implements Serializer | ||||
| @ -119,11 +159,28 @@ func CaseSensitiveJsonIterator() jsoniter.API { | ||||
| 	return config | ||||
| } | ||||
|  | ||||
| // Private copy of jsoniter to try to shield against possible mutations | ||||
| // StrictCaseSensitiveJsonIterator returns a jsoniterator API that's configured to be | ||||
| // case-sensitive, but also disallows unknown fields when unmarshalling. It is compatible with | ||||
| // the encoding/json standard library. | ||||
| func StrictCaseSensitiveJsonIterator() jsoniter.API { | ||||
| 	config := jsoniter.Config{ | ||||
| 		EscapeHTML:             true, | ||||
| 		SortMapKeys:            true, | ||||
| 		ValidateJsonRawMessage: true, | ||||
| 		CaseSensitive:          true, | ||||
| 		DisallowUnknownFields:  true, | ||||
| 	}.Froze() | ||||
| 	// Force jsoniter to decode number to interface{} via int64/float64, if possible. | ||||
| 	config.RegisterExtension(&customNumberExtension{}) | ||||
| 	return config | ||||
| } | ||||
|  | ||||
| // Private copies of jsoniter to try to shield against possible mutations | ||||
| // from outside. Still does not protect from package level jsoniter.Register*() functions - someone calling them | ||||
| // in some other library will mess with every usage of the jsoniter library in the whole program. | ||||
| // See https://github.com/json-iterator/go/issues/265 | ||||
| var caseSensitiveJsonIterator = CaseSensitiveJsonIterator() | ||||
| var strictCaseSensitiveJsonIterator = StrictCaseSensitiveJsonIterator() | ||||
|  | ||||
| // gvkWithDefaults returns group kind and version defaulting from provided default | ||||
| func gvkWithDefaults(actual, defaultGVK schema.GroupVersionKind) schema.GroupVersionKind { | ||||
| @ -149,18 +206,8 @@ 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.yaml { | ||||
| 	if s.options.Yaml { | ||||
| 		altered, err := yaml.YAMLToJSON(data) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, err | ||||
| @ -216,12 +263,45 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i | ||||
| 	if err := caseSensitiveJsonIterator.Unmarshal(data, obj); err != nil { | ||||
| 		return nil, actual, err | ||||
| 	} | ||||
|  | ||||
| 	// If the deserializer is non-strict, return successfully here. | ||||
| 	if !s.options.Strict { | ||||
| 		return obj, actual, nil | ||||
| 	} | ||||
|  | ||||
| 	// In strict mode pass the data trough the YAMLToJSONStrict converter. | ||||
| 	// This is done to catch duplicate fields regardless of encoding (JSON or YAML). For JSON data, | ||||
| 	// the output would equal the input, unless there is a parsing error such as duplicate fields. | ||||
| 	// As we know this was successful in the non-strict case, the only error that may be returned here | ||||
| 	// is because of the newly-added strictness. hence we know we can return the typed strictDecoderError | ||||
| 	// the actual error is that the object contains duplicate fields. | ||||
| 	altered, err := yaml.YAMLToJSONStrict(originalData) | ||||
| 	if err != nil { | ||||
| 		return nil, actual, runtime.NewStrictDecodingError(err.Error(), string(originalData)) | ||||
| 	} | ||||
| 	// As performance is not an issue for now for the strict deserializer (one has regardless to do | ||||
| 	// the unmarshal twice), we take the sanitized, altered data that is guaranteed to have no duplicated | ||||
| 	// fields, and unmarshal this into a copy of the already-populated obj. Any error that occurs here is | ||||
| 	// due to that a matching field doesn't exist in the object. hence we can return a typed strictDecoderError, | ||||
| 	// the actual error is that the object contains unknown field. | ||||
| 	strictObj := obj.DeepCopyObject() | ||||
| 	if err := strictCaseSensitiveJsonIterator.Unmarshal(altered, strictObj); err != nil { | ||||
| 		return nil, actual, runtime.NewStrictDecodingError(err.Error(), string(originalData)) | ||||
| 	} | ||||
| 	// Always return the same object as the non-strict serializer to avoid any deviations. | ||||
| 	return obj, actual, nil | ||||
| } | ||||
|  | ||||
| // Encode serializes the provided object to the given writer. | ||||
| func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error { | ||||
| 	if s.yaml { | ||||
| 	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 { | ||||
| 			return err | ||||
| @ -234,7 +314,7 @@ func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if s.pretty { | ||||
| 	if s.options.Pretty { | ||||
| 		data, err := caseSensitiveJsonIterator.MarshalIndent(obj, "", "  ") | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| @ -246,9 +326,14 @@ 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.yaml { | ||||
| 	if s.options.Yaml { | ||||
| 		// we could potentially look for '---' | ||||
| 		return false, true, nil | ||||
| 	} | ||||
|  | ||||
							
								
								
									
										117
									
								
								vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										117
									
								
								vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -69,27 +69,25 @@ func IsNotMarshalable(err error) bool { | ||||
| // NewSerializer creates a Protobuf serializer that handles encoding versioned objects into the proper wire form. If a typer | ||||
| // is passed, the encoded object will have group, version, and kind fields set. If typer is nil, the objects will be written | ||||
| // 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.ObjectTyper, defaultContentType string) *Serializer { | ||||
| func NewSerializer(creater runtime.ObjectCreater, typer runtime.ObjectTyper) *Serializer { | ||||
| 	return &Serializer{ | ||||
| 		prefix:      protoEncodingPrefix, | ||||
| 		creater:     creater, | ||||
| 		typer:       typer, | ||||
| 		contentType: defaultContentType, | ||||
| 		prefix:  protoEncodingPrefix, | ||||
| 		creater: creater, | ||||
| 		typer:   typer, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type Serializer struct { | ||||
| 	prefix      []byte | ||||
| 	creater     runtime.ObjectCreater | ||||
| 	typer       runtime.ObjectTyper | ||||
| 	contentType string | ||||
| 	prefix  []byte | ||||
| 	creater runtime.ObjectCreater | ||||
| 	typer   runtime.ObjectTyper | ||||
| } | ||||
|  | ||||
| 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 | ||||
| @ -97,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: | ||||
| @ -138,7 +119,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i | ||||
| 	if intoUnknown, ok := into.(*runtime.Unknown); ok && intoUnknown != nil { | ||||
| 		*intoUnknown = unk | ||||
| 		if ok, _, _ := s.RecognizesData(bytes.NewBuffer(unk.Raw)); ok { | ||||
| 			intoUnknown.ContentType = s.contentType | ||||
| 			intoUnknown.ContentType = runtime.ContentTypeProtobuf | ||||
| 		} | ||||
| 		return intoUnknown, &actual, nil | ||||
| 	} | ||||
| @ -180,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 | ||||
| @ -207,7 +195,7 @@ func (s *Serializer) 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 | ||||
| 		// the more efficient Size and MarshalTo methods | ||||
| 		// the more efficient Size and MarshalToSizedBuffer methods | ||||
| 		encodedSize := uint64(t.Size()) | ||||
| 		estimatedSize := prefixSize + estimateUnknownSize(&unk, encodedSize) | ||||
| 		data := make([]byte, estimatedSize) | ||||
| @ -249,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) | ||||
| @ -287,6 +280,12 @@ type bufferedMarshaller interface { | ||||
| 	runtime.ProtobufMarshaller | ||||
| } | ||||
|  | ||||
| // Like bufferedMarshaller, but is able to marshal backwards, which is more efficient since it doesn't call Size() as frequently. | ||||
| type bufferedReverseMarshaller interface { | ||||
| 	proto.Sizer | ||||
| 	runtime.ProtobufReverseMarshaller | ||||
| } | ||||
|  | ||||
| // estimateUnknownSize returns the expected bytes consumed by a given runtime.Unknown | ||||
| // object with a nil RawJSON struct and the expected size of the provided buffer. The | ||||
| // returned size will not be correct if RawJSOn is set on unk. | ||||
| @ -303,24 +302,24 @@ 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.ObjectTyper, defaultContentType string) *RawSerializer { | ||||
| func NewRawSerializer(creater runtime.ObjectCreater, typer runtime.ObjectTyper) *RawSerializer { | ||||
| 	return &RawSerializer{ | ||||
| 		creater:     creater, | ||||
| 		typer:       typer, | ||||
| 		contentType: defaultContentType, | ||||
| 		creater: creater, | ||||
| 		typer:   typer, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // RawSerializer encodes and decodes objects without adding a runtime.Unknown wrapper (objects are encoded without identifying | ||||
| // type). | ||||
| type RawSerializer struct { | ||||
| 	creater     runtime.ObjectCreater | ||||
| 	typer       runtime.ObjectTyper | ||||
| 	contentType string | ||||
| 	creater runtime.ObjectCreater | ||||
| 	typer   runtime.ObjectTyper | ||||
| } | ||||
|  | ||||
| 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") | ||||
| @ -358,7 +343,7 @@ func (s *RawSerializer) Decode(originalData []byte, gvk *schema.GroupVersionKind | ||||
| 	if intoUnknown, ok := into.(*runtime.Unknown); ok && intoUnknown != nil { | ||||
| 		intoUnknown.Raw = data | ||||
| 		intoUnknown.ContentEncoding = "" | ||||
| 		intoUnknown.ContentType = s.contentType | ||||
| 		intoUnknown.ContentType = runtime.ContentTypeProtobuf | ||||
| 		intoUnknown.SetGroupVersionKind(*actual) | ||||
| 		return intoUnknown, actual, nil | ||||
| 	} | ||||
| @ -411,12 +396,35 @@ func unmarshalToObject(typer runtime.ObjectTyper, creater runtime.ObjectCreater, | ||||
| 	if err := proto.Unmarshal(data, pb); err != nil { | ||||
| 		return nil, actual, err | ||||
| 	} | ||||
| 	if actual != nil { | ||||
| 		obj.GetObjectKind().SetGroupVersionKind(*actual) | ||||
| 	} | ||||
| 	return obj, actual, nil | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| 		// the more efficient Size and MarshalToSizedBuffer methods | ||||
| 		encodedSize := uint64(t.Size()) | ||||
| 		data := make([]byte, encodedSize) | ||||
|  | ||||
| 		n, err := t.MarshalToSizedBuffer(data) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		_, err = w.Write(data[:n]) | ||||
| 		return err | ||||
|  | ||||
| 	case bufferedMarshaller: | ||||
| 		// this path performs a single allocation during write but requires the caller to implement | ||||
| 		// the more efficient Size and MarshalTo methods | ||||
| @ -444,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{} | ||||
|  | ||||
							
								
								
									
										48
									
								
								vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf_extension.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf_extension.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,48 +0,0 @@ | ||||
| /* | ||||
| 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 serializer | ||||
|  | ||||
| import ( | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/serializer/protobuf" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	// contentTypeProtobuf is the protobuf type exposed for Kubernetes. It is private to prevent others from | ||||
| 	// depending on it unintentionally. | ||||
| 	// TODO: potentially move to pkg/api (since it's part of the Kube public API) and pass it in to the | ||||
| 	//   CodecFactory on initialization. | ||||
| 	contentTypeProtobuf = "application/vnd.kubernetes.protobuf" | ||||
| ) | ||||
|  | ||||
| func protobufSerializer(scheme *runtime.Scheme) (serializerType, bool) { | ||||
| 	serializer := protobuf.NewSerializer(scheme, scheme, contentTypeProtobuf) | ||||
| 	raw := protobuf.NewRawSerializer(scheme, scheme, contentTypeProtobuf) | ||||
| 	return serializerType{ | ||||
| 		AcceptContentTypes: []string{contentTypeProtobuf}, | ||||
| 		ContentType:        contentTypeProtobuf, | ||||
| 		FileExtensions:     []string{"pb"}, | ||||
| 		Serializer:         serializer, | ||||
|  | ||||
| 		Framer:           protobuf.LengthDelimitedFramer, | ||||
| 		StreamSerializer: raw, | ||||
| 	}, true | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	serializerExtensions = append(serializerExtensions, protobufSerializer) | ||||
| } | ||||
							
								
								
									
										158
									
								
								vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										158
									
								
								vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -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/v2" | ||||
| ) | ||||
|  | ||||
| // 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 | ||||
| @ -106,50 +139,30 @@ 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 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// if we specify a target, use generic conversion. | ||||
| 	if into != nil { | ||||
| 		if into == obj { | ||||
| 			if isVersioned { | ||||
| 				return versioned, gvk, nil | ||||
| 			} | ||||
| 			return into, gvk, 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 { | ||||
| 			return into, gvk, nil | ||||
| 		} | ||||
|  | ||||
| 		if err := c.convertor.Convert(obj, into, c.decodeVersion); err != nil { | ||||
| 			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) | ||||
| @ -159,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) | ||||
| @ -199,84 +213,38 @@ func (c *codec) Encode(obj runtime.Object, w io.Writer) error { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	objectKind := obj.GetObjectKind() | ||||
| 	old := objectKind.GroupVersionKind() | ||||
| 	// restore the old GVK after encoding | ||||
| 	defer objectKind.SetGroupVersionKind(old) | ||||
|  | ||||
| 	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 | ||||
| 			} | ||||
| 		} | ||||
| 		objectKind := obj.GetObjectKind() | ||||
| 		old := objectKind.GroupVersionKind() | ||||
| 		objectKind.SetGroupVersionKind(gvks[0]) | ||||
| 		err = c.encoder.Encode(obj, w) | ||||
| 		objectKind.SetGroupVersionKind(old) | ||||
| 		return err | ||||
| 		return c.encoder.Encode(obj, w) | ||||
| 	} | ||||
|  | ||||
| 	// Perform a conversion if necessary | ||||
| 	objectKind := obj.GetObjectKind() | ||||
| 	old := objectKind.GroupVersionKind() | ||||
| 	out, err := c.convertor.ConvertToVersion(obj, c.encodeVersion) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	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 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Conversion is responsible for setting the proper group, version, and kind onto the outgoing object | ||||
| 	err = c.encoder.Encode(out, w) | ||||
| 	// restore the old GVK, in case conversion returned the same object | ||||
| 	objectKind.SetGroupVersionKind(old) | ||||
| 	return err | ||||
| 	return c.encoder.Encode(out, w) | ||||
| } | ||||
|  | ||||
| // DirectEncoder serializes an object and ensures the GVK is set. | ||||
| type DirectEncoder struct { | ||||
| 	Version runtime.GroupVersioner | ||||
| 	runtime.Encoder | ||||
| 	runtime.ObjectTyper | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| // Identifier implements runtime.Encoder interface. | ||||
| func (c *codec) Identifier() runtime.Identifier { | ||||
| 	return c.identifier | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user