converter.go 25 KB

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