1
16
17 package serializer
18
19 import (
20 "mime"
21 "strings"
22
23 "k8s.io/apimachinery/pkg/runtime"
24 "k8s.io/apimachinery/pkg/runtime/schema"
25 "k8s.io/apimachinery/pkg/runtime/serializer/json"
26 "k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
27 "k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
28 "k8s.io/apimachinery/pkg/runtime/serializer/versioning"
29 )
30
31
32 var serializerExtensions = []func(*runtime.Scheme) (serializerType, bool){}
33
34 type serializerType struct {
35 AcceptContentTypes []string
36 ContentType string
37 FileExtensions []string
38
39 EncodesAsText bool
40
41 Serializer runtime.Serializer
42 PrettySerializer runtime.Serializer
43 StrictSerializer runtime.Serializer
44
45 AcceptStreamContentTypes []string
46 StreamContentType string
47
48 Framer runtime.Framer
49 StreamSerializer runtime.Serializer
50 }
51
52 func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, options CodecFactoryOptions) []serializerType {
53 jsonSerializer := json.NewSerializerWithOptions(
54 mf, scheme, scheme,
55 json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict},
56 )
57 jsonSerializerType := serializerType{
58 AcceptContentTypes: []string{runtime.ContentTypeJSON},
59 ContentType: runtime.ContentTypeJSON,
60 FileExtensions: []string{"json"},
61 EncodesAsText: true,
62 Serializer: jsonSerializer,
63
64 Framer: json.Framer,
65 StreamSerializer: jsonSerializer,
66 }
67 if options.Pretty {
68 jsonSerializerType.PrettySerializer = json.NewSerializerWithOptions(
69 mf, scheme, scheme,
70 json.SerializerOptions{Yaml: false, Pretty: true, Strict: options.Strict},
71 )
72 }
73
74 strictJSONSerializer := json.NewSerializerWithOptions(
75 mf, scheme, scheme,
76 json.SerializerOptions{Yaml: false, Pretty: false, Strict: true},
77 )
78 jsonSerializerType.StrictSerializer = strictJSONSerializer
79
80 yamlSerializer := json.NewSerializerWithOptions(
81 mf, scheme, scheme,
82 json.SerializerOptions{Yaml: true, Pretty: false, Strict: options.Strict},
83 )
84 strictYAMLSerializer := json.NewSerializerWithOptions(
85 mf, scheme, scheme,
86 json.SerializerOptions{Yaml: true, Pretty: false, Strict: true},
87 )
88 protoSerializer := protobuf.NewSerializer(scheme, scheme)
89 protoRawSerializer := protobuf.NewRawSerializer(scheme, scheme)
90
91 serializers := []serializerType{
92 jsonSerializerType,
93 {
94 AcceptContentTypes: []string{runtime.ContentTypeYAML},
95 ContentType: runtime.ContentTypeYAML,
96 FileExtensions: []string{"yaml"},
97 EncodesAsText: true,
98 Serializer: yamlSerializer,
99 StrictSerializer: strictYAMLSerializer,
100 },
101 {
102 AcceptContentTypes: []string{runtime.ContentTypeProtobuf},
103 ContentType: runtime.ContentTypeProtobuf,
104 FileExtensions: []string{"pb"},
105 Serializer: protoSerializer,
106
107
108 StrictSerializer: protoSerializer,
109
110 Framer: protobuf.LengthDelimitedFramer,
111 StreamSerializer: protoRawSerializer,
112 },
113 }
114
115 for _, fn := range serializerExtensions {
116 if serializer, ok := fn(scheme); ok {
117 serializers = append(serializers, serializer)
118 }
119 }
120 return serializers
121 }
122
123
124
125 type CodecFactory struct {
126 scheme *runtime.Scheme
127 universal runtime.Decoder
128 accepts []runtime.SerializerInfo
129
130 legacySerializer runtime.Serializer
131 }
132
133
134 type CodecFactoryOptions struct {
135
136 Strict bool
137
138 Pretty bool
139 }
140
141
142
143 type CodecFactoryOptionsMutator func(*CodecFactoryOptions)
144
145
146 func EnablePretty(options *CodecFactoryOptions) {
147 options.Pretty = true
148 }
149
150
151 func DisablePretty(options *CodecFactoryOptions) {
152 options.Pretty = false
153 }
154
155
156 func EnableStrict(options *CodecFactoryOptions) {
157 options.Strict = true
158 }
159
160
161 func DisableStrict(options *CodecFactoryOptions) {
162 options.Strict = false
163 }
164
165
166
167
168
169
170
171
172
173
174
175
176 func NewCodecFactory(scheme *runtime.Scheme, mutators ...CodecFactoryOptionsMutator) CodecFactory {
177 options := CodecFactoryOptions{Pretty: true}
178 for _, fn := range mutators {
179 fn(&options)
180 }
181
182 serializers := newSerializersForScheme(scheme, json.DefaultMetaFactory, options)
183 return newCodecFactory(scheme, serializers)
184 }
185
186
187 func newCodecFactory(scheme *runtime.Scheme, serializers []serializerType) CodecFactory {
188 decoders := make([]runtime.Decoder, 0, len(serializers))
189 var accepts []runtime.SerializerInfo
190 alreadyAccepted := make(map[string]struct{})
191
192 var legacySerializer runtime.Serializer
193 for _, d := range serializers {
194 decoders = append(decoders, d.Serializer)
195 for _, mediaType := range d.AcceptContentTypes {
196 if _, ok := alreadyAccepted[mediaType]; ok {
197 continue
198 }
199 alreadyAccepted[mediaType] = struct{}{}
200 info := runtime.SerializerInfo{
201 MediaType: d.ContentType,
202 EncodesAsText: d.EncodesAsText,
203 Serializer: d.Serializer,
204 PrettySerializer: d.PrettySerializer,
205 StrictSerializer: d.StrictSerializer,
206 }
207
208 mediaType, _, err := mime.ParseMediaType(info.MediaType)
209 if err != nil {
210 panic(err)
211 }
212 parts := strings.SplitN(mediaType, "/", 2)
213 info.MediaTypeType = parts[0]
214 info.MediaTypeSubType = parts[1]
215
216 if d.StreamSerializer != nil {
217 info.StreamSerializer = &runtime.StreamSerializerInfo{
218 Serializer: d.StreamSerializer,
219 EncodesAsText: d.EncodesAsText,
220 Framer: d.Framer,
221 }
222 }
223 accepts = append(accepts, info)
224 if mediaType == runtime.ContentTypeJSON {
225 legacySerializer = d.Serializer
226 }
227 }
228 }
229 if legacySerializer == nil {
230 legacySerializer = serializers[0].Serializer
231 }
232
233 return CodecFactory{
234 scheme: scheme,
235 universal: recognizer.NewDecoder(decoders...),
236
237 accepts: accepts,
238
239 legacySerializer: legacySerializer,
240 }
241 }
242
243
244
245 func (f CodecFactory) WithoutConversion() runtime.NegotiatedSerializer {
246 return WithoutConversionCodecFactory{f}
247 }
248
249
250 func (f CodecFactory) SupportedMediaTypes() []runtime.SerializerInfo {
251 return f.accepts
252 }
253
254
255
256
257
258
259
260
261
262
263 func (f CodecFactory) LegacyCodec(version ...schema.GroupVersion) runtime.Codec {
264 return versioning.NewDefaultingCodecForScheme(f.scheme, f.legacySerializer, f.universal, schema.GroupVersions(version), runtime.InternalGroupVersioner)
265 }
266
267
268
269 func (f CodecFactory) UniversalDeserializer() runtime.Decoder {
270 return f.universal
271 }
272
273
274
275
276
277
278
279
280
281
282 func (f CodecFactory) UniversalDecoder(versions ...schema.GroupVersion) runtime.Decoder {
283 var versioner runtime.GroupVersioner
284 if len(versions) == 0 {
285 versioner = runtime.InternalGroupVersioner
286 } else {
287 versioner = schema.GroupVersions(versions)
288 }
289 return f.CodecForVersions(nil, f.universal, nil, versioner)
290 }
291
292
293
294
295 func (f CodecFactory) CodecForVersions(encoder runtime.Encoder, decoder runtime.Decoder, encode runtime.GroupVersioner, decode runtime.GroupVersioner) runtime.Codec {
296
297 if encode == nil {
298 encode = runtime.DisabledGroupVersioner
299 }
300 if decode == nil {
301 decode = runtime.InternalGroupVersioner
302 }
303 return versioning.NewDefaultingCodecForScheme(f.scheme, encoder, decoder, encode, decode)
304 }
305
306
307 func (f CodecFactory) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
308 return f.CodecForVersions(nil, decoder, nil, gv)
309 }
310
311
312 func (f CodecFactory) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
313 return f.CodecForVersions(encoder, nil, gv, nil)
314 }
315
316
317
318
319 type WithoutConversionCodecFactory struct {
320 CodecFactory
321 }
322
323
324
325 func (f WithoutConversionCodecFactory) EncoderForVersion(serializer runtime.Encoder, version runtime.GroupVersioner) runtime.Encoder {
326 return runtime.WithVersionEncoder{
327 Version: version,
328 Encoder: serializer,
329 ObjectTyper: f.CodecFactory.scheme,
330 }
331 }
332
333
334 func (f WithoutConversionCodecFactory) DecoderToVersion(serializer runtime.Decoder, _ runtime.GroupVersioner) runtime.Decoder {
335 return runtime.WithoutVersionDecoder{
336 Decoder: serializer,
337 }
338 }
339
View as plain text