converter.go 23 KB

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