1
16
17 package runtime
18
19 import (
20 "bytes"
21 "encoding/base64"
22 "encoding/json"
23 "fmt"
24 "io"
25 "net/url"
26 "reflect"
27 "strconv"
28 "strings"
29
30 "k8s.io/apimachinery/pkg/conversion/queryparams"
31 "k8s.io/apimachinery/pkg/runtime/schema"
32 "k8s.io/klog/v2"
33 )
34
35
36 type codec struct {
37 Encoder
38 Decoder
39 }
40
41
42 func NewCodec(e Encoder, d Decoder) Codec {
43 return codec{e, d}
44 }
45
46
47 func Encode(e Encoder, obj Object) ([]byte, error) {
48 buf := &bytes.Buffer{}
49 if err := e.Encode(obj, buf); err != nil {
50 return nil, err
51 }
52 return buf.Bytes(), nil
53 }
54
55
56 func Decode(d Decoder, data []byte) (Object, error) {
57 obj, _, err := d.Decode(data, nil, nil)
58 return obj, err
59 }
60
61
62 func DecodeInto(d Decoder, data []byte, into Object) error {
63 out, gvk, err := d.Decode(data, nil, into)
64 if err != nil {
65 return err
66 }
67 if out != into {
68 return fmt.Errorf("unable to decode %s into %v", gvk, reflect.TypeOf(into))
69 }
70 return nil
71 }
72
73
74 func EncodeOrDie(e Encoder, obj Object) string {
75 bytes, err := Encode(e, obj)
76 if err != nil {
77 panic(err)
78 }
79 return string(bytes)
80 }
81
82
83
84 func UseOrCreateObject(t ObjectTyper, c ObjectCreater, gvk schema.GroupVersionKind, obj Object) (Object, error) {
85 if obj != nil {
86 kinds, _, err := t.ObjectKinds(obj)
87 if err != nil {
88 return nil, err
89 }
90 for _, kind := range kinds {
91 if gvk == kind {
92 return obj, nil
93 }
94 }
95 }
96 return c.New(gvk)
97 }
98
99
100 type NoopEncoder struct {
101 Decoder
102 }
103
104 var _ Serializer = NoopEncoder{}
105
106 const noopEncoderIdentifier Identifier = "noop"
107
108 func (n NoopEncoder) Encode(obj Object, w io.Writer) error {
109
110
111 return fmt.Errorf("encoding is not allowed for this codec: %v", reflect.TypeOf(n.Decoder))
112 }
113
114
115 func (n NoopEncoder) Identifier() Identifier {
116 return noopEncoderIdentifier
117 }
118
119
120 type NoopDecoder struct {
121 Encoder
122 }
123
124 var _ Serializer = NoopDecoder{}
125
126 func (n NoopDecoder) Decode(data []byte, gvk *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error) {
127 return nil, nil, fmt.Errorf("decoding is not allowed for this codec: %v", reflect.TypeOf(n.Encoder))
128 }
129
130
131 func NewParameterCodec(scheme *Scheme) ParameterCodec {
132 return ¶meterCodec{
133 typer: scheme,
134 convertor: scheme,
135 creator: scheme,
136 defaulter: scheme,
137 }
138 }
139
140
141 type parameterCodec struct {
142 typer ObjectTyper
143 convertor ObjectConvertor
144 creator ObjectCreater
145 defaulter ObjectDefaulter
146 }
147
148 var _ ParameterCodec = ¶meterCodec{}
149
150
151
152 func (c *parameterCodec) DecodeParameters(parameters url.Values, from schema.GroupVersion, into Object) error {
153 if len(parameters) == 0 {
154 return nil
155 }
156 targetGVKs, _, err := c.typer.ObjectKinds(into)
157 if err != nil {
158 return err
159 }
160 for i := range targetGVKs {
161 if targetGVKs[i].GroupVersion() == from {
162 if err := c.convertor.Convert(¶meters, into, nil); err != nil {
163 return err
164 }
165
166 if c.defaulter != nil {
167 c.defaulter.Default(into)
168 }
169 return nil
170 }
171 }
172
173 input, err := c.creator.New(from.WithKind(targetGVKs[0].Kind))
174 if err != nil {
175 return err
176 }
177 if err := c.convertor.Convert(¶meters, input, nil); err != nil {
178 return err
179 }
180
181 if c.defaulter != nil {
182 c.defaulter.Default(input)
183 }
184 return c.convertor.Convert(input, into, nil)
185 }
186
187
188
189 func (c *parameterCodec) EncodeParameters(obj Object, to schema.GroupVersion) (url.Values, error) {
190 gvks, _, err := c.typer.ObjectKinds(obj)
191 if err != nil {
192 return nil, err
193 }
194 gvk := gvks[0]
195 if to != gvk.GroupVersion() {
196 out, err := c.convertor.ConvertToVersion(obj, to)
197 if err != nil {
198 return nil, err
199 }
200 obj = out
201 }
202 return queryparams.Convert(obj)
203 }
204
205 type base64Serializer struct {
206 Encoder
207 Decoder
208
209 identifier Identifier
210 }
211
212 func NewBase64Serializer(e Encoder, d Decoder) Serializer {
213 return &base64Serializer{
214 Encoder: e,
215 Decoder: d,
216 identifier: identifier(e),
217 }
218 }
219
220 func identifier(e Encoder) Identifier {
221 result := map[string]string{
222 "name": "base64",
223 }
224 if e != nil {
225 result["encoder"] = string(e.Identifier())
226 }
227 identifier, err := json.Marshal(result)
228 if err != nil {
229 klog.Fatalf("Failed marshaling identifier for base64Serializer: %v", err)
230 }
231 return Identifier(identifier)
232 }
233
234 func (s base64Serializer) Encode(obj Object, stream io.Writer) error {
235 if co, ok := obj.(CacheableObject); ok {
236 return co.CacheEncode(s.Identifier(), s.doEncode, stream)
237 }
238 return s.doEncode(obj, stream)
239 }
240
241 func (s base64Serializer) doEncode(obj Object, stream io.Writer) error {
242 e := base64.NewEncoder(base64.StdEncoding, stream)
243 err := s.Encoder.Encode(obj, e)
244 e.Close()
245 return err
246 }
247
248
249 func (s base64Serializer) Identifier() Identifier {
250 return s.identifier
251 }
252
253 func (s base64Serializer) Decode(data []byte, defaults *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error) {
254 out := make([]byte, base64.StdEncoding.DecodedLen(len(data)))
255 n, err := base64.StdEncoding.Decode(out, data)
256 if err != nil {
257 return nil, nil, err
258 }
259 return s.Decoder.Decode(out[:n], defaults, into)
260 }
261
262
263
264 func SerializerInfoForMediaType(types []SerializerInfo, mediaType string) (SerializerInfo, bool) {
265 for _, info := range types {
266 if info.MediaType == mediaType {
267 return info, true
268 }
269 }
270 for _, info := range types {
271 if len(info.MediaType) == 0 {
272 return info, true
273 }
274 }
275 return SerializerInfo{}, false
276 }
277
278 var (
279
280 InternalGroupVersioner GroupVersioner = internalGroupVersioner{}
281
282 DisabledGroupVersioner GroupVersioner = disabledGroupVersioner{}
283 )
284
285 const (
286 internalGroupVersionerIdentifier = "internal"
287 disabledGroupVersionerIdentifier = "disabled"
288 )
289
290 type internalGroupVersioner struct{}
291
292
293 func (internalGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (schema.GroupVersionKind, bool) {
294 for _, kind := range kinds {
295 if kind.Version == APIVersionInternal {
296 return kind, true
297 }
298 }
299 for _, kind := range kinds {
300 return schema.GroupVersionKind{Group: kind.Group, Version: APIVersionInternal, Kind: kind.Kind}, true
301 }
302 return schema.GroupVersionKind{}, false
303 }
304
305
306 func (internalGroupVersioner) Identifier() string {
307 return internalGroupVersionerIdentifier
308 }
309
310 type disabledGroupVersioner struct{}
311
312
313 func (disabledGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (schema.GroupVersionKind, bool) {
314 return schema.GroupVersionKind{}, false
315 }
316
317
318 func (disabledGroupVersioner) Identifier() string {
319 return disabledGroupVersionerIdentifier
320 }
321
322
323 var _ GroupVersioner = schema.GroupVersion{}
324 var _ GroupVersioner = schema.GroupVersions{}
325 var _ GroupVersioner = multiGroupVersioner{}
326
327 type multiGroupVersioner struct {
328 target schema.GroupVersion
329 acceptedGroupKinds []schema.GroupKind
330 coerce bool
331 }
332
333
334
335 func NewMultiGroupVersioner(gv schema.GroupVersion, groupKinds ...schema.GroupKind) GroupVersioner {
336 if len(groupKinds) == 0 || (len(groupKinds) == 1 && groupKinds[0].Group == gv.Group) {
337 return gv
338 }
339 return multiGroupVersioner{target: gv, acceptedGroupKinds: groupKinds}
340 }
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355 func NewCoercingMultiGroupVersioner(gv schema.GroupVersion, groupKinds ...schema.GroupKind) GroupVersioner {
356 return multiGroupVersioner{target: gv, acceptedGroupKinds: groupKinds, coerce: true}
357 }
358
359
360
361 func (v multiGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (schema.GroupVersionKind, bool) {
362 for _, src := range kinds {
363 for _, kind := range v.acceptedGroupKinds {
364 if kind.Group != src.Group {
365 continue
366 }
367 if len(kind.Kind) > 0 && kind.Kind != src.Kind {
368 continue
369 }
370 return v.target.WithKind(src.Kind), true
371 }
372 }
373 if v.coerce && len(kinds) > 0 {
374 return v.target.WithKind(kinds[0].Kind), true
375 }
376 return schema.GroupVersionKind{}, false
377 }
378
379
380 func (v multiGroupVersioner) Identifier() string {
381 groupKinds := make([]string, 0, len(v.acceptedGroupKinds))
382 for _, gk := range v.acceptedGroupKinds {
383 groupKinds = append(groupKinds, gk.String())
384 }
385 result := map[string]string{
386 "name": "multi",
387 "target": v.target.String(),
388 "accepted": strings.Join(groupKinds, ","),
389 "coerce": strconv.FormatBool(v.coerce),
390 }
391 identifier, err := json.Marshal(result)
392 if err != nil {
393 klog.Fatalf("Failed marshaling Identifier for %#v: %v", v, err)
394 }
395 return string(identifier)
396 }
397
View as plain text