converter.go 25 KB

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