1
16
17 package cbor
18
19 import (
20 "bytes"
21 "encoding/hex"
22 "errors"
23 "fmt"
24 "io"
25
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/apimachinery/pkg/runtime/schema"
29 "k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes"
30 "k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
31 util "k8s.io/apimachinery/pkg/util/runtime"
32
33 "github.com/fxamacker/cbor/v2"
34 )
35
36 type metaFactory interface {
37
38 Interpret(data []byte) (*schema.GroupVersionKind, error)
39 }
40
41 type defaultMetaFactory struct{}
42
43 func (mf *defaultMetaFactory) Interpret(data []byte) (*schema.GroupVersionKind, error) {
44 var tm metav1.TypeMeta
45
46
47 if err := modes.DecodeLax.Unmarshal(data, &tm); err != nil {
48 return nil, fmt.Errorf("unable to determine group/version/kind: %w", err)
49 }
50 actual := tm.GetObjectKind().GroupVersionKind()
51 return &actual, nil
52 }
53
54 type Serializer interface {
55 runtime.Serializer
56 recognizer.RecognizingDecoder
57 }
58
59 var _ Serializer = &serializer{}
60
61 type options struct {
62 strict bool
63 }
64
65 type Option func(*options)
66
67 func Strict(s bool) Option {
68 return func(opts *options) {
69 opts.strict = s
70 }
71 }
72
73 type serializer struct {
74 metaFactory metaFactory
75 creater runtime.ObjectCreater
76 typer runtime.ObjectTyper
77 options options
78 }
79
80 func NewSerializer(creater runtime.ObjectCreater, typer runtime.ObjectTyper, options ...Option) Serializer {
81 return newSerializer(&defaultMetaFactory{}, creater, typer, options...)
82 }
83
84 func newSerializer(metaFactory metaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, options ...Option) *serializer {
85 s := &serializer{
86 metaFactory: metaFactory,
87 creater: creater,
88 typer: typer,
89 }
90 for _, o := range options {
91 o(&s.options)
92 }
93 return s
94 }
95
96 func (s *serializer) Identifier() runtime.Identifier {
97 return "cbor"
98 }
99
100 func (s *serializer) Encode(obj runtime.Object, w io.Writer) error {
101 if _, err := w.Write(selfDescribedCBOR); err != nil {
102 return err
103 }
104
105 e := modes.Encode.NewEncoder(w)
106 if u, ok := obj.(runtime.Unstructured); ok {
107 return e.Encode(u.UnstructuredContent())
108 }
109 return e.Encode(obj)
110 }
111
112
113 func gvkWithDefaults(actual, defaultGVK schema.GroupVersionKind) schema.GroupVersionKind {
114 if len(actual.Kind) == 0 {
115 actual.Kind = defaultGVK.Kind
116 }
117 if len(actual.Version) == 0 && len(actual.Group) == 0 {
118 actual.Group = defaultGVK.Group
119 actual.Version = defaultGVK.Version
120 }
121 if len(actual.Version) == 0 && actual.Group == defaultGVK.Group {
122 actual.Version = defaultGVK.Version
123 }
124 return actual
125 }
126
127
128 func diagnose(data []byte) string {
129 diag, err := modes.Diagnostic.Diagnose(data)
130 if err != nil {
131
132
133 util.HandleError(err)
134
135 return hex.EncodeToString(data)
136 }
137 return diag
138 }
139
140 func (s *serializer) unmarshal(data []byte, into interface{}) (strict, lax error) {
141 if u, ok := into.(runtime.Unstructured); ok {
142 var content map[string]interface{}
143 defer func() {
144
145
146
147
148
149 u.SetUnstructuredContent(content)
150 }()
151 into = &content
152 }
153
154 if !s.options.strict {
155 return nil, modes.DecodeLax.Unmarshal(data, into)
156 }
157
158 err := modes.Decode.Unmarshal(data, into)
159
160
161 var unknownField *cbor.UnknownFieldError
162 if errors.As(err, &unknownField) {
163
164
165
166 return runtime.NewStrictDecodingError([]error{unknownField}), modes.DecodeLax.Unmarshal(data, into)
167 }
168 return nil, err
169 }
170
171 func (s *serializer) Decode(data []byte, gvk *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
172
173
174 if _, ok := into.(runtime.Unstructured); ok {
175 if _, unmarshalErr := s.unmarshal(data, into); unmarshalErr != nil {
176 actual, interpretErr := s.metaFactory.Interpret(data)
177 if interpretErr != nil {
178 return nil, nil, interpretErr
179 }
180
181 if gvk != nil {
182 *actual = gvkWithDefaults(*actual, *gvk)
183 }
184
185 return nil, actual, unmarshalErr
186 }
187
188 actual := into.GetObjectKind().GroupVersionKind()
189 if len(actual.Kind) == 0 {
190 return nil, &actual, runtime.NewMissingKindErr(diagnose(data))
191 }
192 if len(actual.Version) == 0 {
193 return nil, &actual, runtime.NewMissingVersionErr(diagnose(data))
194 }
195
196 return into, &actual, nil
197 }
198
199 actual, err := s.metaFactory.Interpret(data)
200 if err != nil {
201 return nil, nil, err
202 }
203
204 if gvk != nil {
205 *actual = gvkWithDefaults(*actual, *gvk)
206 }
207
208 if into != nil {
209 types, _, err := s.typer.ObjectKinds(into)
210 if err != nil {
211 return nil, actual, err
212 }
213 *actual = gvkWithDefaults(*actual, types[0])
214 }
215
216 if len(actual.Kind) == 0 {
217 return nil, actual, runtime.NewMissingKindErr(diagnose(data))
218 }
219 if len(actual.Version) == 0 {
220 return nil, actual, runtime.NewMissingVersionErr(diagnose(data))
221 }
222
223 obj, err := runtime.UseOrCreateObject(s.typer, s.creater, *actual, into)
224 if err != nil {
225 return nil, actual, err
226 }
227
228 strict, err := s.unmarshal(data, obj)
229 if err != nil {
230 return nil, actual, err
231 }
232 return obj, actual, strict
233 }
234
235
236
237
238
239
240 var selfDescribedCBOR = []byte{0xd9, 0xd9, 0xf7}
241
242 func (s *serializer) RecognizesData(data []byte) (ok, unknown bool, err error) {
243 return bytes.HasPrefix(data, selfDescribedCBOR), false, nil
244 }
245
View as plain text