Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / k8s.io / apimachinery / pkg / runtime / converter.go
1 /*
2 Copyright 2017 The Kubernetes Authors.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 package runtime
18
19 import (
20         "bytes"
21         encodingjson "encoding/json"
22         "fmt"
23         "math"
24         "os"
25         "reflect"
26         "strconv"
27         "strings"
28         "sync"
29         "sync/atomic"
30         "time"
31
32         "k8s.io/apimachinery/pkg/conversion"
33         "k8s.io/apimachinery/pkg/util/json"
34         utilruntime "k8s.io/apimachinery/pkg/util/runtime"
35
36         "k8s.io/klog"
37 )
38
39 // UnstructuredConverter is an interface for converting between interface{}
40 // and map[string]interface representation.
41 type UnstructuredConverter interface {
42         ToUnstructured(obj interface{}) (map[string]interface{}, error)
43         FromUnstructured(u map[string]interface{}, obj interface{}) error
44 }
45
46 type structField struct {
47         structType reflect.Type
48         field      int
49 }
50
51 type fieldInfo struct {
52         name      string
53         nameValue reflect.Value
54         omitempty bool
55 }
56
57 type fieldsCacheMap map[structField]*fieldInfo
58
59 type fieldsCache struct {
60         sync.Mutex
61         value atomic.Value
62 }
63
64 func newFieldsCache() *fieldsCache {
65         cache := &fieldsCache{}
66         cache.value.Store(make(fieldsCacheMap))
67         return cache
68 }
69
70 var (
71         marshalerType          = reflect.TypeOf(new(encodingjson.Marshaler)).Elem()
72         unmarshalerType        = reflect.TypeOf(new(encodingjson.Unmarshaler)).Elem()
73         mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{})
74         stringType             = reflect.TypeOf(string(""))
75         int64Type              = reflect.TypeOf(int64(0))
76         float64Type            = reflect.TypeOf(float64(0))
77         boolType               = reflect.TypeOf(bool(false))
78         fieldCache             = newFieldsCache()
79
80         // DefaultUnstructuredConverter performs unstructured to Go typed object conversions.
81         DefaultUnstructuredConverter = &unstructuredConverter{
82                 mismatchDetection: parseBool(os.Getenv("KUBE_PATCH_CONVERSION_DETECTOR")),
83                 comparison: conversion.EqualitiesOrDie(
84                         func(a, b time.Time) bool {
85                                 return a.UTC() == b.UTC()
86                         },
87                 ),
88         }
89 )
90
91 func parseBool(key string) bool {
92         if len(key) == 0 {
93                 return false
94         }
95         value, err := strconv.ParseBool(key)
96         if err != nil {
97                 utilruntime.HandleError(fmt.Errorf("Couldn't parse '%s' as bool for unstructured mismatch detection", key))
98         }
99         return value
100 }
101
102 // unstructuredConverter knows how to convert between interface{} and
103 // Unstructured in both ways.
104 type unstructuredConverter struct {
105         // If true, we will be additionally running conversion via json
106         // to ensure that the result is true.
107         // This is supposed to be set only in tests.
108         mismatchDetection bool
109         // comparison is the default test logic used to compare
110         comparison conversion.Equalities
111 }
112
113 // NewTestUnstructuredConverter creates an UnstructuredConverter that accepts JSON typed maps and translates them
114 // to Go types via reflection. It performs mismatch detection automatically and is intended for use by external
115 // test tools. Use DefaultUnstructuredConverter if you do not explicitly need mismatch detection.
116 func NewTestUnstructuredConverter(comparison conversion.Equalities) UnstructuredConverter {
117         return &unstructuredConverter{
118                 mismatchDetection: true,
119                 comparison:        comparison,
120         }
121 }
122
123 // FromUnstructured converts an object from map[string]interface{} representation into a concrete type.
124 // It uses encoding/json/Unmarshaler if object implements it or reflection if not.
125 func (c *unstructuredConverter) FromUnstructured(u map[string]interface{}, obj interface{}) error {
126         t := reflect.TypeOf(obj)
127         value := reflect.ValueOf(obj)
128         if t.Kind() != reflect.Ptr || value.IsNil() {
129                 return fmt.Errorf("FromUnstructured requires a non-nil pointer to an object, got %v", t)
130         }
131         err := fromUnstructured(reflect.ValueOf(u), value.Elem())
132         if c.mismatchDetection {
133                 newObj := reflect.New(t.Elem()).Interface()
134                 newErr := fromUnstructuredViaJSON(u, newObj)
135                 if (err != nil) != (newErr != nil) {
136                         klog.Fatalf("FromUnstructured unexpected error for %v: error: %v", u, err)
137                 }
138                 if err == nil && !c.comparison.DeepEqual(obj, newObj) {
139                         klog.Fatalf("FromUnstructured mismatch\nobj1: %#v\nobj2: %#v", obj, newObj)
140                 }
141         }
142         return err
143 }
144
145 func fromUnstructuredViaJSON(u map[string]interface{}, obj interface{}) error {
146         data, err := json.Marshal(u)
147         if err != nil {
148                 return err
149         }
150         return json.Unmarshal(data, obj)
151 }
152
153 func fromUnstructured(sv, dv reflect.Value) error {
154         sv = unwrapInterface(sv)
155         if !sv.IsValid() {
156                 dv.Set(reflect.Zero(dv.Type()))
157                 return nil
158         }
159         st, dt := sv.Type(), dv.Type()
160
161         switch dt.Kind() {
162         case reflect.Map, reflect.Slice, reflect.Ptr, reflect.Struct, reflect.Interface:
163                 // Those require non-trivial conversion.
164         default:
165                 // This should handle all simple types.
166                 if st.AssignableTo(dt) {
167                         dv.Set(sv)
168                         return nil
169                 }
170                 // We cannot simply use "ConvertibleTo", as JSON doesn't support conversions
171                 // between those four groups: bools, integers, floats and string. We need to
172                 // do the same.
173                 if st.ConvertibleTo(dt) {
174                         switch st.Kind() {
175                         case reflect.String:
176                                 switch dt.Kind() {
177                                 case reflect.String:
178                                         dv.Set(sv.Convert(dt))
179                                         return nil
180                                 }
181                         case reflect.Bool:
182                                 switch dt.Kind() {
183                                 case reflect.Bool:
184                                         dv.Set(sv.Convert(dt))
185                                         return nil
186                                 }
187                         case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
188                                 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
189                                 switch dt.Kind() {
190                                 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
191                                         reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
192                                         dv.Set(sv.Convert(dt))
193                                         return nil
194                                 }
195                         case reflect.Float32, reflect.Float64:
196                                 switch dt.Kind() {
197                                 case reflect.Float32, reflect.Float64:
198                                         dv.Set(sv.Convert(dt))
199                                         return nil
200                                 }
201                                 if sv.Float() == math.Trunc(sv.Float()) {
202                                         dv.Set(sv.Convert(dt))
203                                         return nil
204                                 }
205                         }
206                         return fmt.Errorf("cannot convert %s to %s", st.String(), dt.String())
207                 }
208         }
209
210         // Check if the object has a custom JSON marshaller/unmarshaller.
211         if reflect.PtrTo(dt).Implements(unmarshalerType) {
212                 data, err := json.Marshal(sv.Interface())
213                 if err != nil {
214                         return fmt.Errorf("error encoding %s to json: %v", st.String(), err)
215                 }
216                 unmarshaler := dv.Addr().Interface().(encodingjson.Unmarshaler)
217                 return unmarshaler.UnmarshalJSON(data)
218         }
219
220         switch dt.Kind() {
221         case reflect.Map:
222                 return mapFromUnstructured(sv, dv)
223         case reflect.Slice:
224                 return sliceFromUnstructured(sv, dv)
225         case reflect.Ptr:
226                 return pointerFromUnstructured(sv, dv)
227         case reflect.Struct:
228                 return structFromUnstructured(sv, dv)
229         case reflect.Interface:
230                 return interfaceFromUnstructured(sv, dv)
231         default:
232                 return fmt.Errorf("unrecognized type: %v", dt.Kind())
233         }
234 }
235
236 func fieldInfoFromField(structType reflect.Type, field int) *fieldInfo {
237         fieldCacheMap := fieldCache.value.Load().(fieldsCacheMap)
238         if info, ok := fieldCacheMap[structField{structType, field}]; ok {
239                 return info
240         }
241
242         // Cache miss - we need to compute the field name.
243         info := &fieldInfo{}
244         typeField := structType.Field(field)
245         jsonTag := typeField.Tag.Get("json")
246         if len(jsonTag) == 0 {
247                 // Make the first character lowercase.
248                 if typeField.Name == "" {
249                         info.name = typeField.Name
250                 } else {
251                         info.name = strings.ToLower(typeField.Name[:1]) + typeField.Name[1:]
252                 }
253         } else {
254                 items := strings.Split(jsonTag, ",")
255                 info.name = items[0]
256                 for i := range items {
257                         if items[i] == "omitempty" {
258                                 info.omitempty = true
259                         }
260                 }
261         }
262         info.nameValue = reflect.ValueOf(info.name)
263
264         fieldCache.Lock()
265         defer fieldCache.Unlock()
266         fieldCacheMap = fieldCache.value.Load().(fieldsCacheMap)
267         newFieldCacheMap := make(fieldsCacheMap)
268         for k, v := range fieldCacheMap {
269                 newFieldCacheMap[k] = v
270         }
271         newFieldCacheMap[structField{structType, field}] = info
272         fieldCache.value.Store(newFieldCacheMap)
273         return info
274 }
275
276 func unwrapInterface(v reflect.Value) reflect.Value {
277         for v.Kind() == reflect.Interface {
278                 v = v.Elem()
279         }
280         return v
281 }
282
283 func mapFromUnstructured(sv, dv reflect.Value) error {
284         st, dt := sv.Type(), dv.Type()
285         if st.Kind() != reflect.Map {
286                 return fmt.Errorf("cannot restore map from %v", st.Kind())
287         }
288
289         if !st.Key().AssignableTo(dt.Key()) && !st.Key().ConvertibleTo(dt.Key()) {
290                 return fmt.Errorf("cannot copy map with non-assignable keys: %v %v", st.Key(), dt.Key())
291         }
292
293         if sv.IsNil() {
294                 dv.Set(reflect.Zero(dt))
295                 return nil
296         }
297         dv.Set(reflect.MakeMap(dt))
298         for _, key := range sv.MapKeys() {
299                 value := reflect.New(dt.Elem()).Elem()
300                 if val := unwrapInterface(sv.MapIndex(key)); val.IsValid() {
301                         if err := fromUnstructured(val, value); err != nil {
302                                 return err
303                         }
304                 } else {
305                         value.Set(reflect.Zero(dt.Elem()))
306                 }
307                 if st.Key().AssignableTo(dt.Key()) {
308                         dv.SetMapIndex(key, value)
309                 } else {
310                         dv.SetMapIndex(key.Convert(dt.Key()), value)
311                 }
312         }
313         return nil
314 }
315
316 func sliceFromUnstructured(sv, dv reflect.Value) error {
317         st, dt := sv.Type(), dv.Type()
318         if st.Kind() == reflect.String && dt.Elem().Kind() == reflect.Uint8 {
319                 // We store original []byte representation as string.
320                 // This conversion is allowed, but we need to be careful about
321                 // marshaling data appropriately.
322                 if len(sv.Interface().(string)) > 0 {
323                         marshalled, err := json.Marshal(sv.Interface())
324                         if err != nil {
325                                 return fmt.Errorf("error encoding %s to json: %v", st, err)
326                         }
327                         // TODO: Is this Unmarshal needed?
328                         var data []byte
329                         err = json.Unmarshal(marshalled, &data)
330                         if err != nil {
331                                 return fmt.Errorf("error decoding from json: %v", err)
332                         }
333                         dv.SetBytes(data)
334                 } else {
335                         dv.Set(reflect.Zero(dt))
336                 }
337                 return nil
338         }
339         if st.Kind() != reflect.Slice {
340                 return fmt.Errorf("cannot restore slice from %v", st.Kind())
341         }
342
343         if sv.IsNil() {
344                 dv.Set(reflect.Zero(dt))
345                 return nil
346         }
347         dv.Set(reflect.MakeSlice(dt, sv.Len(), sv.Cap()))
348         for i := 0; i < sv.Len(); i++ {
349                 if err := fromUnstructured(sv.Index(i), dv.Index(i)); err != nil {
350                         return err
351                 }
352         }
353         return nil
354 }
355
356 func pointerFromUnstructured(sv, dv reflect.Value) error {
357         st, dt := sv.Type(), dv.Type()
358
359         if st.Kind() == reflect.Ptr && sv.IsNil() {
360                 dv.Set(reflect.Zero(dt))
361                 return nil
362         }
363         dv.Set(reflect.New(dt.Elem()))
364         switch st.Kind() {
365         case reflect.Ptr, reflect.Interface:
366                 return fromUnstructured(sv.Elem(), dv.Elem())
367         default:
368                 return fromUnstructured(sv, dv.Elem())
369         }
370 }
371
372 func structFromUnstructured(sv, dv reflect.Value) error {
373         st, dt := sv.Type(), dv.Type()
374         if st.Kind() != reflect.Map {
375                 return fmt.Errorf("cannot restore struct from: %v", st.Kind())
376         }
377
378         for i := 0; i < dt.NumField(); i++ {
379                 fieldInfo := fieldInfoFromField(dt, i)
380                 fv := dv.Field(i)
381
382                 if len(fieldInfo.name) == 0 {
383                         // This field is inlined.
384                         if err := fromUnstructured(sv, fv); err != nil {
385                                 return err
386                         }
387                 } else {
388                         value := unwrapInterface(sv.MapIndex(fieldInfo.nameValue))
389                         if value.IsValid() {
390                                 if err := fromUnstructured(value, fv); err != nil {
391                                         return err
392                                 }
393                         } else {
394                                 fv.Set(reflect.Zero(fv.Type()))
395                         }
396                 }
397         }
398         return nil
399 }
400
401 func interfaceFromUnstructured(sv, dv reflect.Value) error {
402         // TODO: Is this conversion safe?
403         dv.Set(sv)
404         return nil
405 }
406
407 // ToUnstructured converts an object into map[string]interface{} representation.
408 // It uses encoding/json/Marshaler if object implements it or reflection if not.
409 func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]interface{}, error) {
410         var u map[string]interface{}
411         var err error
412         if unstr, ok := obj.(Unstructured); ok {
413                 u = unstr.UnstructuredContent()
414         } else {
415                 t := reflect.TypeOf(obj)
416                 value := reflect.ValueOf(obj)
417                 if t.Kind() != reflect.Ptr || value.IsNil() {
418                         return nil, fmt.Errorf("ToUnstructured requires a non-nil pointer to an object, got %v", t)
419                 }
420                 u = map[string]interface{}{}
421                 err = toUnstructured(value.Elem(), reflect.ValueOf(&u).Elem())
422         }
423         if c.mismatchDetection {
424                 newUnstr := map[string]interface{}{}
425                 newErr := toUnstructuredViaJSON(obj, &newUnstr)
426                 if (err != nil) != (newErr != nil) {
427                         klog.Fatalf("ToUnstructured unexpected error for %v: error: %v; newErr: %v", obj, err, newErr)
428                 }
429                 if err == nil && !c.comparison.DeepEqual(u, newUnstr) {
430                         klog.Fatalf("ToUnstructured mismatch\nobj1: %#v\nobj2: %#v", u, newUnstr)
431                 }
432         }
433         if err != nil {
434                 return nil, err
435         }
436         return u, nil
437 }
438
439 // DeepCopyJSON deep copies the passed value, assuming it is a valid JSON representation i.e. only contains
440 // types produced by json.Unmarshal() and also int64.
441 // bool, int64, float64, string, []interface{}, map[string]interface{}, json.Number and nil
442 func DeepCopyJSON(x map[string]interface{}) map[string]interface{} {
443         return DeepCopyJSONValue(x).(map[string]interface{})
444 }
445
446 // DeepCopyJSONValue deep copies the passed value, assuming it is a valid JSON representation i.e. only contains
447 // types produced by json.Unmarshal() and also int64.
448 // bool, int64, float64, string, []interface{}, map[string]interface{}, json.Number and nil
449 func DeepCopyJSONValue(x interface{}) interface{} {
450         switch x := x.(type) {
451         case map[string]interface{}:
452                 if x == nil {
453                         // Typed nil - an interface{} that contains a type map[string]interface{} with a value of nil
454                         return x
455                 }
456                 clone := make(map[string]interface{}, len(x))
457                 for k, v := range x {
458                         clone[k] = DeepCopyJSONValue(v)
459                 }
460                 return clone
461         case []interface{}:
462                 if x == nil {
463                         // Typed nil - an interface{} that contains a type []interface{} with a value of nil
464                         return x
465                 }
466                 clone := make([]interface{}, len(x))
467                 for i, v := range x {
468                         clone[i] = DeepCopyJSONValue(v)
469                 }
470                 return clone
471         case string, int64, bool, float64, nil, encodingjson.Number:
472                 return x
473         default:
474                 panic(fmt.Errorf("cannot deep copy %T", x))
475         }
476 }
477
478 func toUnstructuredViaJSON(obj interface{}, u *map[string]interface{}) error {
479         data, err := json.Marshal(obj)
480         if err != nil {
481                 return err
482         }
483         return json.Unmarshal(data, u)
484 }
485
486 var (
487         nullBytes  = []byte("null")
488         trueBytes  = []byte("true")
489         falseBytes = []byte("false")
490 )
491
492 func getMarshaler(v reflect.Value) (encodingjson.Marshaler, bool) {
493         // Check value receivers if v is not a pointer and pointer receivers if v is a pointer
494         if v.Type().Implements(marshalerType) {
495                 return v.Interface().(encodingjson.Marshaler), true
496         }
497         // Check pointer receivers if v is not a pointer
498         if v.Kind() != reflect.Ptr && v.CanAddr() {
499                 v = v.Addr()
500                 if v.Type().Implements(marshalerType) {
501                         return v.Interface().(encodingjson.Marshaler), true
502                 }
503         }
504         return nil, false
505 }
506
507 func toUnstructured(sv, dv reflect.Value) error {
508         // Check if the object has a custom JSON marshaller/unmarshaller.
509         if marshaler, ok := getMarshaler(sv); ok {
510                 if sv.Kind() == reflect.Ptr && sv.IsNil() {
511                         // We're done - we don't need to store anything.
512                         return nil
513                 }
514
515                 data, err := marshaler.MarshalJSON()
516                 if err != nil {
517                         return err
518                 }
519                 switch {
520                 case len(data) == 0:
521                         return fmt.Errorf("error decoding from json: empty value")
522
523                 case bytes.Equal(data, nullBytes):
524                         // We're done - we don't need to store anything.
525
526                 case bytes.Equal(data, trueBytes):
527                         dv.Set(reflect.ValueOf(true))
528
529                 case bytes.Equal(data, falseBytes):
530                         dv.Set(reflect.ValueOf(false))
531
532                 case data[0] == '"':
533                         var result string
534                         err := json.Unmarshal(data, &result)
535                         if err != nil {
536                                 return fmt.Errorf("error decoding string from json: %v", err)
537                         }
538                         dv.Set(reflect.ValueOf(result))
539
540                 case data[0] == '{':
541                         result := make(map[string]interface{})
542                         err := json.Unmarshal(data, &result)
543                         if err != nil {
544                                 return fmt.Errorf("error decoding object from json: %v", err)
545                         }
546                         dv.Set(reflect.ValueOf(result))
547
548                 case data[0] == '[':
549                         result := make([]interface{}, 0)
550                         err := json.Unmarshal(data, &result)
551                         if err != nil {
552                                 return fmt.Errorf("error decoding array from json: %v", err)
553                         }
554                         dv.Set(reflect.ValueOf(result))
555
556                 default:
557                         var (
558                                 resultInt   int64
559                                 resultFloat float64
560                                 err         error
561                         )
562                         if err = json.Unmarshal(data, &resultInt); err == nil {
563                                 dv.Set(reflect.ValueOf(resultInt))
564                         } else if err = json.Unmarshal(data, &resultFloat); err == nil {
565                                 dv.Set(reflect.ValueOf(resultFloat))
566                         } else {
567                                 return fmt.Errorf("error decoding number from json: %v", err)
568                         }
569                 }
570
571                 return nil
572         }
573
574         st, dt := sv.Type(), dv.Type()
575         switch st.Kind() {
576         case reflect.String:
577                 if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {
578                         dv.Set(reflect.New(stringType))
579                 }
580                 dv.Set(reflect.ValueOf(sv.String()))
581                 return nil
582         case reflect.Bool:
583                 if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {
584                         dv.Set(reflect.New(boolType))
585                 }
586                 dv.Set(reflect.ValueOf(sv.Bool()))
587                 return nil
588         case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
589                 if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {
590                         dv.Set(reflect.New(int64Type))
591                 }
592                 dv.Set(reflect.ValueOf(sv.Int()))
593                 return nil
594         case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
595                 uVal := sv.Uint()
596                 if uVal > math.MaxInt64 {
597                         return fmt.Errorf("unsigned value %d does not fit into int64 (overflow)", uVal)
598                 }
599                 if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {
600                         dv.Set(reflect.New(int64Type))
601                 }
602                 dv.Set(reflect.ValueOf(int64(uVal)))
603                 return nil
604         case reflect.Float32, reflect.Float64:
605                 if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {
606                         dv.Set(reflect.New(float64Type))
607                 }
608                 dv.Set(reflect.ValueOf(sv.Float()))
609                 return nil
610         case reflect.Map:
611                 return mapToUnstructured(sv, dv)
612         case reflect.Slice:
613                 return sliceToUnstructured(sv, dv)
614         case reflect.Ptr:
615                 return pointerToUnstructured(sv, dv)
616         case reflect.Struct:
617                 return structToUnstructured(sv, dv)
618         case reflect.Interface:
619                 return interfaceToUnstructured(sv, dv)
620         default:
621                 return fmt.Errorf("unrecognized type: %v", st.Kind())
622         }
623 }
624
625 func mapToUnstructured(sv, dv reflect.Value) error {
626         st, dt := sv.Type(), dv.Type()
627         if sv.IsNil() {
628                 dv.Set(reflect.Zero(dt))
629                 return nil
630         }
631         if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {
632                 if st.Key().Kind() == reflect.String {
633                         switch st.Elem().Kind() {
634                         // TODO It should be possible to reuse the slice for primitive types.
635                         // However, it is panicing in the following form.
636                         // case reflect.String, reflect.Bool,
637                         //      reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
638                         //      reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
639                         //      sv.Set(sv)
640                         //      return nil
641                         default:
642                                 // We need to do a proper conversion.
643                         }
644                 }
645                 dv.Set(reflect.MakeMap(mapStringInterfaceType))
646                 dv = dv.Elem()
647                 dt = dv.Type()
648         }
649         if dt.Kind() != reflect.Map {
650                 return fmt.Errorf("cannot convert struct to: %v", dt.Kind())
651         }
652
653         if !st.Key().AssignableTo(dt.Key()) && !st.Key().ConvertibleTo(dt.Key()) {
654                 return fmt.Errorf("cannot copy map with non-assignable keys: %v %v", st.Key(), dt.Key())
655         }
656
657         for _, key := range sv.MapKeys() {
658                 value := reflect.New(dt.Elem()).Elem()
659                 if err := toUnstructured(sv.MapIndex(key), value); err != nil {
660                         return err
661                 }
662                 if st.Key().AssignableTo(dt.Key()) {
663                         dv.SetMapIndex(key, value)
664                 } else {
665                         dv.SetMapIndex(key.Convert(dt.Key()), value)
666                 }
667         }
668         return nil
669 }
670
671 func sliceToUnstructured(sv, dv reflect.Value) error {
672         st, dt := sv.Type(), dv.Type()
673         if sv.IsNil() {
674                 dv.Set(reflect.Zero(dt))
675                 return nil
676         }
677         if st.Elem().Kind() == reflect.Uint8 {
678                 dv.Set(reflect.New(stringType))
679                 data, err := json.Marshal(sv.Bytes())
680                 if err != nil {
681                         return err
682                 }
683                 var result string
684                 if err = json.Unmarshal(data, &result); err != nil {
685                         return err
686                 }
687                 dv.Set(reflect.ValueOf(result))
688                 return nil
689         }
690         if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {
691                 switch st.Elem().Kind() {
692                 // TODO It should be possible to reuse the slice for primitive types.
693                 // However, it is panicing in the following form.
694                 // case reflect.String, reflect.Bool,
695                 //      reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
696                 //      reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
697                 //      sv.Set(sv)
698                 //      return nil
699                 default:
700                         // We need to do a proper conversion.
701                         dv.Set(reflect.MakeSlice(reflect.SliceOf(dt), sv.Len(), sv.Cap()))
702                         dv = dv.Elem()
703                         dt = dv.Type()
704                 }
705         }
706         if dt.Kind() != reflect.Slice {
707                 return fmt.Errorf("cannot convert slice to: %v", dt.Kind())
708         }
709         for i := 0; i < sv.Len(); i++ {
710                 if err := toUnstructured(sv.Index(i), dv.Index(i)); err != nil {
711                         return err
712                 }
713         }
714         return nil
715 }
716
717 func pointerToUnstructured(sv, dv reflect.Value) error {
718         if sv.IsNil() {
719                 // We're done - we don't need to store anything.
720                 return nil
721         }
722         return toUnstructured(sv.Elem(), dv)
723 }
724
725 func isZero(v reflect.Value) bool {
726         switch v.Kind() {
727         case reflect.Array, reflect.String:
728                 return v.Len() == 0
729         case reflect.Bool:
730                 return !v.Bool()
731         case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
732                 return v.Int() == 0
733         case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
734                 return v.Uint() == 0
735         case reflect.Float32, reflect.Float64:
736                 return v.Float() == 0
737         case reflect.Map, reflect.Slice:
738                 // TODO: It seems that 0-len maps are ignored in it.
739                 return v.IsNil() || v.Len() == 0
740         case reflect.Ptr, reflect.Interface:
741                 return v.IsNil()
742         }
743         return false
744 }
745
746 func structToUnstructured(sv, dv reflect.Value) error {
747         st, dt := sv.Type(), dv.Type()
748         if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {
749                 dv.Set(reflect.MakeMap(mapStringInterfaceType))
750                 dv = dv.Elem()
751                 dt = dv.Type()
752         }
753         if dt.Kind() != reflect.Map {
754                 return fmt.Errorf("cannot convert struct to: %v", dt.Kind())
755         }
756         realMap := dv.Interface().(map[string]interface{})
757
758         for i := 0; i < st.NumField(); i++ {
759                 fieldInfo := fieldInfoFromField(st, i)
760                 fv := sv.Field(i)
761
762                 if fieldInfo.name == "-" {
763                         // This field should be skipped.
764                         continue
765                 }
766                 if fieldInfo.omitempty && isZero(fv) {
767                         // omitempty fields should be ignored.
768                         continue
769                 }
770                 if len(fieldInfo.name) == 0 {
771                         // This field is inlined.
772                         if err := toUnstructured(fv, dv); err != nil {
773                                 return err
774                         }
775                         continue
776                 }
777                 switch fv.Type().Kind() {
778                 case reflect.String:
779                         realMap[fieldInfo.name] = fv.String()
780                 case reflect.Bool:
781                         realMap[fieldInfo.name] = fv.Bool()
782                 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
783                         realMap[fieldInfo.name] = fv.Int()
784                 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
785                         realMap[fieldInfo.name] = fv.Uint()
786                 case reflect.Float32, reflect.Float64:
787                         realMap[fieldInfo.name] = fv.Float()
788                 default:
789                         subv := reflect.New(dt.Elem()).Elem()
790                         if err := toUnstructured(fv, subv); err != nil {
791                                 return err
792                         }
793                         dv.SetMapIndex(fieldInfo.nameValue, subv)
794                 }
795         }
796         return nil
797 }
798
799 func interfaceToUnstructured(sv, dv reflect.Value) error {
800         if !sv.IsValid() || sv.IsNil() {
801                 dv.Set(reflect.Zero(dv.Type()))
802                 return nil
803         }
804         return toUnstructured(sv.Elem(), dv)
805 }