blob: f44693c0c6f8416a2eb7f2031533071547ae7060 [file] [log] [blame]
Matteo Scandoloa4285862020-12-01 18:10:10 -08001/*
2Copyright 2014 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package runtime
18
19import (
20 "io"
21 "net/url"
22
23 "k8s.io/apimachinery/pkg/runtime/schema"
24)
25
26const (
27 // APIVersionInternal may be used if you are registering a type that should not
28 // be considered stable or serialized - it is a convention only and has no
29 // special behavior in this package.
30 APIVersionInternal = "__internal"
31)
32
33// GroupVersioner refines a set of possible conversion targets into a single option.
34type GroupVersioner interface {
35 // KindForGroupVersionKinds returns a desired target group version kind for the given input, or returns ok false if no
36 // target is known. In general, if the return target is not in the input list, the caller is expected to invoke
37 // Scheme.New(target) and then perform a conversion between the current Go type and the destination Go type.
38 // Sophisticated implementations may use additional information about the input kinds to pick a destination kind.
39 KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (target schema.GroupVersionKind, ok bool)
40 // Identifier returns string representation of the object.
41 // Identifiers of two different encoders should be equal only if for every input
42 // kinds they return the same result.
43 Identifier() string
44}
45
46// Identifier represents an identifier.
47// Identitier of two different objects should be equal if and only if for every
48// input the output they produce is exactly the same.
49type Identifier string
50
51// Encoder writes objects to a serialized form
52type Encoder interface {
53 // Encode writes an object to a stream. Implementations may return errors if the versions are
54 // incompatible, or if no conversion is defined.
55 Encode(obj Object, w io.Writer) error
56 // Identifier returns an identifier of the encoder.
57 // Identifiers of two different encoders should be equal if and only if for every input
58 // object it will be encoded to the same representation by both of them.
59 //
60 // Identifier is inteted for use with CacheableObject#CacheEncode method. In order to
61 // correctly handle CacheableObject, Encode() method should look similar to below, where
62 // doEncode() is the encoding logic of implemented encoder:
63 // func (e *MyEncoder) Encode(obj Object, w io.Writer) error {
64 // if co, ok := obj.(CacheableObject); ok {
65 // return co.CacheEncode(e.Identifier(), e.doEncode, w)
66 // }
67 // return e.doEncode(obj, w)
68 // }
69 Identifier() Identifier
70}
71
72// Decoder attempts to load an object from data.
73type Decoder interface {
74 // Decode attempts to deserialize the provided data using either the innate typing of the scheme or the
75 // default kind, group, and version provided. It returns a decoded object as well as the kind, group, and
76 // version from the serialized data, or an error. If into is non-nil, it will be used as the target type
77 // and implementations may choose to use it rather than reallocating an object. However, the object is not
78 // guaranteed to be populated. The returned object is not guaranteed to match into. If defaults are
79 // provided, they are applied to the data by default. If no defaults or partial defaults are provided, the
80 // type of the into may be used to guide conversion decisions.
81 Decode(data []byte, defaults *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error)
82}
83
84// Serializer is the core interface for transforming objects into a serialized format and back.
85// Implementations may choose to perform conversion of the object, but no assumptions should be made.
86type Serializer interface {
87 Encoder
88 Decoder
89}
90
91// Codec is a Serializer that deals with the details of versioning objects. It offers the same
92// interface as Serializer, so this is a marker to consumers that care about the version of the objects
93// they receive.
94type Codec Serializer
95
96// ParameterCodec defines methods for serializing and deserializing API objects to url.Values and
97// performing any necessary conversion. Unlike the normal Codec, query parameters are not self describing
98// and the desired version must be specified.
99type ParameterCodec interface {
100 // DecodeParameters takes the given url.Values in the specified group version and decodes them
101 // into the provided object, or returns an error.
102 DecodeParameters(parameters url.Values, from schema.GroupVersion, into Object) error
103 // EncodeParameters encodes the provided object as query parameters or returns an error.
104 EncodeParameters(obj Object, to schema.GroupVersion) (url.Values, error)
105}
106
107// Framer is a factory for creating readers and writers that obey a particular framing pattern.
108type Framer interface {
109 NewFrameReader(r io.ReadCloser) io.ReadCloser
110 NewFrameWriter(w io.Writer) io.Writer
111}
112
113// SerializerInfo contains information about a specific serialization format
114type SerializerInfo struct {
115 // MediaType is the value that represents this serializer over the wire.
116 MediaType string
117 // MediaTypeType is the first part of the MediaType ("application" in "application/json").
118 MediaTypeType string
119 // MediaTypeSubType is the second part of the MediaType ("json" in "application/json").
120 MediaTypeSubType string
121 // EncodesAsText indicates this serializer can be encoded to UTF-8 safely.
122 EncodesAsText bool
123 // Serializer is the individual object serializer for this media type.
124 Serializer Serializer
125 // PrettySerializer, if set, can serialize this object in a form biased towards
126 // readability.
127 PrettySerializer Serializer
128 // StreamSerializer, if set, describes the streaming serialization format
129 // for this media type.
130 StreamSerializer *StreamSerializerInfo
131}
132
133// StreamSerializerInfo contains information about a specific stream serialization format
134type StreamSerializerInfo struct {
135 // EncodesAsText indicates this serializer can be encoded to UTF-8 safely.
136 EncodesAsText bool
137 // Serializer is the top level object serializer for this type when streaming
138 Serializer
139 // Framer is the factory for retrieving streams that separate objects on the wire
140 Framer
141}
142
143// NegotiatedSerializer is an interface used for obtaining encoders, decoders, and serializers
144// for multiple supported media types. This would commonly be accepted by a server component
145// that performs HTTP content negotiation to accept multiple formats.
146type NegotiatedSerializer interface {
147 // SupportedMediaTypes is the media types supported for reading and writing single objects.
148 SupportedMediaTypes() []SerializerInfo
149
150 // EncoderForVersion returns an encoder that ensures objects being written to the provided
151 // serializer are in the provided group version.
152 EncoderForVersion(serializer Encoder, gv GroupVersioner) Encoder
153 // DecoderForVersion returns a decoder that ensures objects being read by the provided
154 // serializer are in the provided group version by default.
155 DecoderToVersion(serializer Decoder, gv GroupVersioner) Decoder
156}
157
158// ClientNegotiator handles turning an HTTP content type into the appropriate encoder.
159// Use NewClientNegotiator or NewVersionedClientNegotiator to create this interface from
160// a NegotiatedSerializer.
161type ClientNegotiator interface {
162 // Encoder returns the appropriate encoder for the provided contentType (e.g. application/json)
163 // and any optional mediaType parameters (e.g. pretty=1), or an error. If no serializer is found
164 // a NegotiateError will be returned. The current client implementations consider params to be
165 // optional modifiers to the contentType and will ignore unrecognized parameters.
166 Encoder(contentType string, params map[string]string) (Encoder, error)
167 // Decoder returns the appropriate decoder for the provided contentType (e.g. application/json)
168 // and any optional mediaType parameters (e.g. pretty=1), or an error. If no serializer is found
169 // a NegotiateError will be returned. The current client implementations consider params to be
170 // optional modifiers to the contentType and will ignore unrecognized parameters.
171 Decoder(contentType string, params map[string]string) (Decoder, error)
172 // StreamDecoder returns the appropriate stream decoder for the provided contentType (e.g.
173 // application/json) and any optional mediaType parameters (e.g. pretty=1), or an error. If no
174 // serializer is found a NegotiateError will be returned. The Serializer and Framer will always
175 // be returned if a Decoder is returned. The current client implementations consider params to be
176 // optional modifiers to the contentType and will ignore unrecognized parameters.
177 StreamDecoder(contentType string, params map[string]string) (Decoder, Serializer, Framer, error)
178}
179
180// StorageSerializer is an interface used for obtaining encoders, decoders, and serializers
181// that can read and write data at rest. This would commonly be used by client tools that must
182// read files, or server side storage interfaces that persist restful objects.
183type StorageSerializer interface {
184 // SupportedMediaTypes are the media types supported for reading and writing objects.
185 SupportedMediaTypes() []SerializerInfo
186
187 // UniversalDeserializer returns a Serializer that can read objects in multiple supported formats
188 // by introspecting the data at rest.
189 UniversalDeserializer() Decoder
190
191 // EncoderForVersion returns an encoder that ensures objects being written to the provided
192 // serializer are in the provided group version.
193 EncoderForVersion(serializer Encoder, gv GroupVersioner) Encoder
194 // DecoderForVersion returns a decoder that ensures objects being read by the provided
195 // serializer are in the provided group version by default.
196 DecoderToVersion(serializer Decoder, gv GroupVersioner) Decoder
197}
198
199// NestedObjectEncoder is an optional interface that objects may implement to be given
200// an opportunity to encode any nested Objects / RawExtensions during serialization.
201type NestedObjectEncoder interface {
202 EncodeNestedObjects(e Encoder) error
203}
204
205// NestedObjectDecoder is an optional interface that objects may implement to be given
206// an opportunity to decode any nested Objects / RawExtensions during serialization.
207type NestedObjectDecoder interface {
208 DecodeNestedObjects(d Decoder) error
209}
210
211///////////////////////////////////////////////////////////////////////////////
212// Non-codec interfaces
213
214type ObjectDefaulter interface {
215 // Default takes an object (must be a pointer) and applies any default values.
216 // Defaulters may not error.
217 Default(in Object)
218}
219
220type ObjectVersioner interface {
221 ConvertToVersion(in Object, gv GroupVersioner) (out Object, err error)
222}
223
224// ObjectConvertor converts an object to a different version.
225type ObjectConvertor interface {
226 // Convert attempts to convert one object into another, or returns an error. This
227 // method does not mutate the in object, but the in and out object might share data structures,
228 // i.e. the out object cannot be mutated without mutating the in object as well.
229 // The context argument will be passed to all nested conversions.
230 Convert(in, out, context interface{}) error
231 // ConvertToVersion takes the provided object and converts it the provided version. This
232 // method does not mutate the in object, but the in and out object might share data structures,
233 // i.e. the out object cannot be mutated without mutating the in object as well.
234 // This method is similar to Convert() but handles specific details of choosing the correct
235 // output version.
236 ConvertToVersion(in Object, gv GroupVersioner) (out Object, err error)
237 ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error)
238}
239
240// ObjectTyper contains methods for extracting the APIVersion and Kind
241// of objects.
242type ObjectTyper interface {
243 // ObjectKinds returns the all possible group,version,kind of the provided object, true if
244 // the object is unversioned, or an error if the object is not recognized
245 // (IsNotRegisteredError will return true).
246 ObjectKinds(Object) ([]schema.GroupVersionKind, bool, error)
247 // Recognizes returns true if the scheme is able to handle the provided version and kind,
248 // or more precisely that the provided version is a possible conversion or decoding
249 // target.
250 Recognizes(gvk schema.GroupVersionKind) bool
251}
252
253// ObjectCreater contains methods for instantiating an object by kind and version.
254type ObjectCreater interface {
255 New(kind schema.GroupVersionKind) (out Object, err error)
256}
257
258// EquivalentResourceMapper provides information about resources that address the same underlying data as a specified resource
259type EquivalentResourceMapper interface {
260 // EquivalentResourcesFor returns a list of resources that address the same underlying data as resource.
261 // If subresource is specified, only equivalent resources which also have the same subresource are included.
262 // The specified resource can be included in the returned list.
263 EquivalentResourcesFor(resource schema.GroupVersionResource, subresource string) []schema.GroupVersionResource
264 // KindFor returns the kind expected by the specified resource[/subresource].
265 // A zero value is returned if the kind is unknown.
266 KindFor(resource schema.GroupVersionResource, subresource string) schema.GroupVersionKind
267}
268
269// EquivalentResourceRegistry provides an EquivalentResourceMapper interface,
270// and allows registering known resource[/subresource] -> kind
271type EquivalentResourceRegistry interface {
272 EquivalentResourceMapper
273 // RegisterKindFor registers the existence of the specified resource[/subresource] along with its expected kind.
274 RegisterKindFor(resource schema.GroupVersionResource, subresource string, kind schema.GroupVersionKind)
275}
276
277// ResourceVersioner provides methods for setting and retrieving
278// the resource version from an API object.
279type ResourceVersioner interface {
280 SetResourceVersion(obj Object, version string) error
281 ResourceVersion(obj Object) (string, error)
282}
283
284// SelfLinker provides methods for setting and retrieving the SelfLink field of an API object.
285type SelfLinker interface {
286 SetSelfLink(obj Object, selfLink string) error
287 SelfLink(obj Object) (string, error)
288
289 // Knowing Name is sometimes necessary to use a SelfLinker.
290 Name(obj Object) (string, error)
291 // Knowing Namespace is sometimes necessary to use a SelfLinker
292 Namespace(obj Object) (string, error)
293}
294
295// Object interface must be supported by all API types registered with Scheme. Since objects in a scheme are
296// expected to be serialized to the wire, the interface an Object must provide to the Scheme allows
297// serializers to set the kind, version, and group the object is represented as. An Object may choose
298// to return a no-op ObjectKindAccessor in cases where it is not expected to be serialized.
299type Object interface {
300 GetObjectKind() schema.ObjectKind
301 DeepCopyObject() Object
302}
303
304// CacheableObject allows an object to cache its different serializations
305// to avoid performing the same serialization multiple times.
306type CacheableObject interface {
307 // CacheEncode writes an object to a stream. The <encode> function will
308 // be used in case of cache miss. The <encode> function takes ownership
309 // of the object.
310 // If CacheableObject is a wrapper, then deep-copy of the wrapped object
311 // should be passed to <encode> function.
312 // CacheEncode assumes that for two different calls with the same <id>,
313 // <encode> function will also be the same.
314 CacheEncode(id Identifier, encode func(Object, io.Writer) error, w io.Writer) error
315 // GetObject returns a deep-copy of an object to be encoded - the caller of
316 // GetObject() is the owner of returned object. The reason for making a copy
317 // is to avoid bugs, where caller modifies the object and forgets to copy it,
318 // thus modifying the object for everyone.
319 // The object returned by GetObject should be the same as the one that is supposed
320 // to be passed to <encode> function in CacheEncode method.
321 // If CacheableObject is a wrapper, the copy of wrapped object should be returned.
322 GetObject() Object
323}
324
325// Unstructured objects store values as map[string]interface{}, with only values that can be serialized
326// to JSON allowed.
327type Unstructured interface {
328 Object
329 // NewEmptyInstance returns a new instance of the concrete type containing only kind/apiVersion and no other data.
330 // This should be called instead of reflect.New() for unstructured types because the go type alone does not preserve kind/apiVersion info.
331 NewEmptyInstance() Unstructured
332 // UnstructuredContent returns a non-nil map with this object's contents. Values may be
333 // []interface{}, map[string]interface{}, or any primitive type. Contents are typically serialized to
334 // and from JSON. SetUnstructuredContent should be used to mutate the contents.
335 UnstructuredContent() map[string]interface{}
336 // SetUnstructuredContent updates the object content to match the provided map.
337 SetUnstructuredContent(map[string]interface{})
338 // IsList returns true if this type is a list or matches the list convention - has an array called "items".
339 IsList() bool
340 // EachListItem should pass a single item out of the list as an Object to the provided function. Any
341 // error should terminate the iteration. If IsList() returns false, this method should return an error
342 // instead of calling the provided function.
343 EachListItem(func(Object) error) error
344}