patch.go 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243
  1. /*
  2. Copyright 2014 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 strategicpatch
  14. import (
  15. "fmt"
  16. "reflect"
  17. "sort"
  18. "k8s.io/kubernetes/pkg/util/json"
  19. forkedjson "k8s.io/kubernetes/third_party/forked/golang/json"
  20. "github.com/davecgh/go-spew/spew"
  21. "github.com/ghodss/yaml"
  22. )
  23. // An alternate implementation of JSON Merge Patch
  24. // (https://tools.ietf.org/html/rfc7386) which supports the ability to annotate
  25. // certain fields with metadata that indicates whether the elements of JSON
  26. // lists should be merged or replaced.
  27. //
  28. // For more information, see the PATCH section of docs/devel/api-conventions.md.
  29. //
  30. // Some of the content of this package was borrowed with minor adaptations from
  31. // evanphx/json-patch and openshift/origin.
  32. const (
  33. directiveMarker = "$patch"
  34. deleteDirective = "delete"
  35. replaceDirective = "replace"
  36. mergeDirective = "merge"
  37. )
  38. // IsPreconditionFailed returns true if the provided error indicates
  39. // a precondition failed.
  40. func IsPreconditionFailed(err error) bool {
  41. _, ok := err.(errPreconditionFailed)
  42. return ok
  43. }
  44. type errPreconditionFailed struct {
  45. message string
  46. }
  47. func newErrPreconditionFailed(target map[string]interface{}) errPreconditionFailed {
  48. s := fmt.Sprintf("precondition failed for: %v", target)
  49. return errPreconditionFailed{s}
  50. }
  51. func (err errPreconditionFailed) Error() string {
  52. return err.message
  53. }
  54. type errConflict struct {
  55. message string
  56. }
  57. func newErrConflict(patch, current string) errConflict {
  58. s := fmt.Sprintf("patch:\n%s\nconflicts with changes made from original to current:\n%s\n", patch, current)
  59. return errConflict{s}
  60. }
  61. func (err errConflict) Error() string {
  62. return err.message
  63. }
  64. // IsConflict returns true if the provided error indicates
  65. // a conflict between the patch and the current configuration.
  66. func IsConflict(err error) bool {
  67. _, ok := err.(errConflict)
  68. return ok
  69. }
  70. var errBadJSONDoc = fmt.Errorf("Invalid JSON document")
  71. var errNoListOfLists = fmt.Errorf("Lists of lists are not supported")
  72. // The following code is adapted from github.com/openshift/origin/pkg/util/jsonmerge.
  73. // Instead of defining a Delta that holds an original, a patch and a set of preconditions,
  74. // the reconcile method accepts a set of preconditions as an argument.
  75. // PreconditionFunc asserts that an incompatible change is not present within a patch.
  76. type PreconditionFunc func(interface{}) bool
  77. // RequireKeyUnchanged returns a precondition function that fails if the provided key
  78. // is present in the patch (indicating that its value has changed).
  79. func RequireKeyUnchanged(key string) PreconditionFunc {
  80. return func(patch interface{}) bool {
  81. patchMap, ok := patch.(map[string]interface{})
  82. if !ok {
  83. return true
  84. }
  85. // The presence of key means that its value has been changed, so the test fails.
  86. _, ok = patchMap[key]
  87. return !ok
  88. }
  89. }
  90. // Deprecated: Use the synonym CreateTwoWayMergePatch, instead.
  91. func CreateStrategicMergePatch(original, modified []byte, dataStruct interface{}) ([]byte, error) {
  92. return CreateTwoWayMergePatch(original, modified, dataStruct)
  93. }
  94. // CreateTwoWayMergePatch creates a patch that can be passed to StrategicMergePatch from an original
  95. // document and a modified document, which are passed to the method as json encoded content. It will
  96. // return a patch that yields the modified document when applied to the original document, or an error
  97. // if either of the two documents is invalid.
  98. func CreateTwoWayMergePatch(original, modified []byte, dataStruct interface{}, fns ...PreconditionFunc) ([]byte, error) {
  99. originalMap := map[string]interface{}{}
  100. if len(original) > 0 {
  101. if err := json.Unmarshal(original, &originalMap); err != nil {
  102. return nil, errBadJSONDoc
  103. }
  104. }
  105. modifiedMap := map[string]interface{}{}
  106. if len(modified) > 0 {
  107. if err := json.Unmarshal(modified, &modifiedMap); err != nil {
  108. return nil, errBadJSONDoc
  109. }
  110. }
  111. t, err := getTagStructType(dataStruct)
  112. if err != nil {
  113. return nil, err
  114. }
  115. patchMap, err := diffMaps(originalMap, modifiedMap, t, false, false)
  116. if err != nil {
  117. return nil, err
  118. }
  119. // Apply the preconditions to the patch, and return an error if any of them fail.
  120. for _, fn := range fns {
  121. if !fn(patchMap) {
  122. return nil, newErrPreconditionFailed(patchMap)
  123. }
  124. }
  125. return json.Marshal(patchMap)
  126. }
  127. // Returns a (recursive) strategic merge patch that yields modified when applied to original.
  128. func diffMaps(original, modified map[string]interface{}, t reflect.Type, ignoreChangesAndAdditions, ignoreDeletions bool) (map[string]interface{}, error) {
  129. patch := map[string]interface{}{}
  130. if t.Kind() == reflect.Ptr {
  131. t = t.Elem()
  132. }
  133. for key, modifiedValue := range modified {
  134. originalValue, ok := original[key]
  135. if !ok {
  136. // Key was added, so add to patch
  137. if !ignoreChangesAndAdditions {
  138. patch[key] = modifiedValue
  139. }
  140. continue
  141. }
  142. if key == directiveMarker {
  143. originalString, ok := originalValue.(string)
  144. if !ok {
  145. return nil, fmt.Errorf("invalid value for special key: %s", directiveMarker)
  146. }
  147. modifiedString, ok := modifiedValue.(string)
  148. if !ok {
  149. return nil, fmt.Errorf("invalid value for special key: %s", directiveMarker)
  150. }
  151. if modifiedString != originalString {
  152. patch[directiveMarker] = modifiedValue
  153. }
  154. continue
  155. }
  156. if reflect.TypeOf(originalValue) != reflect.TypeOf(modifiedValue) {
  157. // Types have changed, so add to patch
  158. if !ignoreChangesAndAdditions {
  159. patch[key] = modifiedValue
  160. }
  161. continue
  162. }
  163. // Types are the same, so compare values
  164. switch originalValueTyped := originalValue.(type) {
  165. case map[string]interface{}:
  166. modifiedValueTyped := modifiedValue.(map[string]interface{})
  167. fieldType, _, _, err := forkedjson.LookupPatchMetadata(t, key)
  168. if err != nil {
  169. return nil, err
  170. }
  171. patchValue, err := diffMaps(originalValueTyped, modifiedValueTyped, fieldType, ignoreChangesAndAdditions, ignoreDeletions)
  172. if err != nil {
  173. return nil, err
  174. }
  175. if len(patchValue) > 0 {
  176. patch[key] = patchValue
  177. }
  178. continue
  179. case []interface{}:
  180. modifiedValueTyped := modifiedValue.([]interface{})
  181. fieldType, fieldPatchStrategy, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadata(t, key)
  182. if err != nil {
  183. return nil, err
  184. }
  185. if fieldPatchStrategy == mergeDirective {
  186. patchValue, err := diffLists(originalValueTyped, modifiedValueTyped, fieldType.Elem(), fieldPatchMergeKey, ignoreChangesAndAdditions, ignoreDeletions)
  187. if err != nil {
  188. return nil, err
  189. }
  190. if len(patchValue) > 0 {
  191. patch[key] = patchValue
  192. }
  193. continue
  194. }
  195. }
  196. if !ignoreChangesAndAdditions {
  197. if !reflect.DeepEqual(originalValue, modifiedValue) {
  198. // Values are different, so add to patch
  199. patch[key] = modifiedValue
  200. }
  201. }
  202. }
  203. if !ignoreDeletions {
  204. // Add nils for deleted values
  205. for key := range original {
  206. _, found := modified[key]
  207. if !found {
  208. patch[key] = nil
  209. }
  210. }
  211. }
  212. return patch, nil
  213. }
  214. // Returns a (recursive) strategic merge patch that yields modified when applied to original,
  215. // for a pair of lists with merge semantics.
  216. func diffLists(original, modified []interface{}, t reflect.Type, mergeKey string, ignoreChangesAndAdditions, ignoreDeletions bool) ([]interface{}, error) {
  217. if len(original) == 0 {
  218. if len(modified) == 0 || ignoreChangesAndAdditions {
  219. return nil, nil
  220. }
  221. return modified, nil
  222. }
  223. elementType, err := sliceElementType(original, modified)
  224. if err != nil {
  225. return nil, err
  226. }
  227. var patch []interface{}
  228. if elementType.Kind() == reflect.Map {
  229. patch, err = diffListsOfMaps(original, modified, t, mergeKey, ignoreChangesAndAdditions, ignoreDeletions)
  230. } else if !ignoreChangesAndAdditions {
  231. patch, err = diffListsOfScalars(original, modified)
  232. }
  233. if err != nil {
  234. return nil, err
  235. }
  236. return patch, nil
  237. }
  238. // Returns a (recursive) strategic merge patch that yields modified when applied to original,
  239. // for a pair of lists of scalars with merge semantics.
  240. func diffListsOfScalars(original, modified []interface{}) ([]interface{}, error) {
  241. if len(modified) == 0 {
  242. // There is no need to check the length of original because there is no way to create
  243. // a patch that deletes a scalar from a list of scalars with merge semantics.
  244. return nil, nil
  245. }
  246. patch := []interface{}{}
  247. originalScalars := uniqifyAndSortScalars(original)
  248. modifiedScalars := uniqifyAndSortScalars(modified)
  249. originalIndex, modifiedIndex := 0, 0
  250. loopB:
  251. for ; modifiedIndex < len(modifiedScalars); modifiedIndex++ {
  252. for ; originalIndex < len(originalScalars); originalIndex++ {
  253. originalString := fmt.Sprintf("%v", original[originalIndex])
  254. modifiedString := fmt.Sprintf("%v", modified[modifiedIndex])
  255. if originalString >= modifiedString {
  256. if originalString != modifiedString {
  257. patch = append(patch, modified[modifiedIndex])
  258. }
  259. continue loopB
  260. }
  261. // There is no else clause because there is no way to create a patch that deletes
  262. // a scalar from a list of scalars with merge semantics.
  263. }
  264. break
  265. }
  266. // Add any remaining items found only in modified
  267. for ; modifiedIndex < len(modifiedScalars); modifiedIndex++ {
  268. patch = append(patch, modified[modifiedIndex])
  269. }
  270. return patch, nil
  271. }
  272. var errNoMergeKeyFmt = "map: %v does not contain declared merge key: %s"
  273. var errBadArgTypeFmt = "expected a %s, but received a %s"
  274. // Returns a (recursive) strategic merge patch that yields modified when applied to original,
  275. // for a pair of lists of maps with merge semantics.
  276. func diffListsOfMaps(original, modified []interface{}, t reflect.Type, mergeKey string, ignoreChangesAndAdditions, ignoreDeletions bool) ([]interface{}, error) {
  277. patch := make([]interface{}, 0)
  278. originalSorted, err := sortMergeListsByNameArray(original, t, mergeKey, false)
  279. if err != nil {
  280. return nil, err
  281. }
  282. modifiedSorted, err := sortMergeListsByNameArray(modified, t, mergeKey, false)
  283. if err != nil {
  284. return nil, err
  285. }
  286. originalIndex, modifiedIndex := 0, 0
  287. loopB:
  288. for ; modifiedIndex < len(modifiedSorted); modifiedIndex++ {
  289. modifiedMap, ok := modifiedSorted[modifiedIndex].(map[string]interface{})
  290. if !ok {
  291. t := reflect.TypeOf(modifiedSorted[modifiedIndex])
  292. return nil, fmt.Errorf(errBadArgTypeFmt, "map[string]interface{}", t.Kind().String())
  293. }
  294. modifiedValue, ok := modifiedMap[mergeKey]
  295. if !ok {
  296. return nil, fmt.Errorf(errNoMergeKeyFmt, modifiedMap, mergeKey)
  297. }
  298. for ; originalIndex < len(originalSorted); originalIndex++ {
  299. originalMap, ok := originalSorted[originalIndex].(map[string]interface{})
  300. if !ok {
  301. t := reflect.TypeOf(originalSorted[originalIndex])
  302. return nil, fmt.Errorf(errBadArgTypeFmt, "map[string]interface{}", t.Kind().String())
  303. }
  304. originalValue, ok := originalMap[mergeKey]
  305. if !ok {
  306. return nil, fmt.Errorf(errNoMergeKeyFmt, originalMap, mergeKey)
  307. }
  308. // Assume that the merge key values are comparable strings
  309. originalString := fmt.Sprintf("%v", originalValue)
  310. modifiedString := fmt.Sprintf("%v", modifiedValue)
  311. if originalString >= modifiedString {
  312. if originalString == modifiedString {
  313. // Merge key values are equal, so recurse
  314. patchValue, err := diffMaps(originalMap, modifiedMap, t, ignoreChangesAndAdditions, ignoreDeletions)
  315. if err != nil {
  316. return nil, err
  317. }
  318. originalIndex++
  319. if len(patchValue) > 0 {
  320. patchValue[mergeKey] = modifiedValue
  321. patch = append(patch, patchValue)
  322. }
  323. } else if !ignoreChangesAndAdditions {
  324. // Item was added, so add to patch
  325. patch = append(patch, modifiedMap)
  326. }
  327. continue loopB
  328. }
  329. if !ignoreDeletions {
  330. // Item was deleted, so add delete directive
  331. patch = append(patch, map[string]interface{}{mergeKey: originalValue, directiveMarker: deleteDirective})
  332. }
  333. }
  334. break
  335. }
  336. if !ignoreDeletions {
  337. // Delete any remaining items found only in original
  338. for ; originalIndex < len(originalSorted); originalIndex++ {
  339. originalMap, ok := originalSorted[originalIndex].(map[string]interface{})
  340. if !ok {
  341. t := reflect.TypeOf(originalSorted[originalIndex])
  342. return nil, fmt.Errorf(errBadArgTypeFmt, "map[string]interface{}", t.Kind().String())
  343. }
  344. originalValue, ok := originalMap[mergeKey]
  345. if !ok {
  346. return nil, fmt.Errorf(errNoMergeKeyFmt, originalMap, mergeKey)
  347. }
  348. patch = append(patch, map[string]interface{}{mergeKey: originalValue, directiveMarker: deleteDirective})
  349. }
  350. }
  351. if !ignoreChangesAndAdditions {
  352. // Add any remaining items found only in modified
  353. for ; modifiedIndex < len(modifiedSorted); modifiedIndex++ {
  354. patch = append(patch, modifiedSorted[modifiedIndex])
  355. }
  356. }
  357. return patch, nil
  358. }
  359. // Deprecated: StrategicMergePatchData is deprecated. Use the synonym StrategicMergePatch,
  360. // instead, which follows the naming convention of evanphx/json-patch.
  361. func StrategicMergePatchData(original, patch []byte, dataStruct interface{}) ([]byte, error) {
  362. return StrategicMergePatch(original, patch, dataStruct)
  363. }
  364. // StrategicMergePatch applies a strategic merge patch. The patch and the original document
  365. // must be json encoded content. A patch can be created from an original and a modified document
  366. // by calling CreateStrategicMergePatch.
  367. func StrategicMergePatch(original, patch []byte, dataStruct interface{}) ([]byte, error) {
  368. if original == nil {
  369. original = []byte("{}")
  370. }
  371. if patch == nil {
  372. patch = []byte("{}")
  373. }
  374. originalMap := map[string]interface{}{}
  375. err := json.Unmarshal(original, &originalMap)
  376. if err != nil {
  377. return nil, errBadJSONDoc
  378. }
  379. patchMap := map[string]interface{}{}
  380. err = json.Unmarshal(patch, &patchMap)
  381. if err != nil {
  382. return nil, errBadJSONDoc
  383. }
  384. t, err := getTagStructType(dataStruct)
  385. if err != nil {
  386. return nil, err
  387. }
  388. result, err := mergeMap(originalMap, patchMap, t)
  389. if err != nil {
  390. return nil, err
  391. }
  392. return json.Marshal(result)
  393. }
  394. func getTagStructType(dataStruct interface{}) (reflect.Type, error) {
  395. if dataStruct == nil {
  396. return nil, fmt.Errorf(errBadArgTypeFmt, "struct", "nil")
  397. }
  398. t := reflect.TypeOf(dataStruct)
  399. if t.Kind() == reflect.Ptr {
  400. t = t.Elem()
  401. }
  402. if t.Kind() != reflect.Struct {
  403. return nil, fmt.Errorf(errBadArgTypeFmt, "struct", t.Kind().String())
  404. }
  405. return t, nil
  406. }
  407. var errBadPatchTypeFmt = "unknown patch type: %s in map: %v"
  408. // Merge fields from a patch map into the original map. Note: This may modify
  409. // both the original map and the patch because getting a deep copy of a map in
  410. // golang is highly non-trivial.
  411. func mergeMap(original, patch map[string]interface{}, t reflect.Type) (map[string]interface{}, error) {
  412. if v, ok := patch[directiveMarker]; ok {
  413. if v == replaceDirective {
  414. // If the patch contains "$patch: replace", don't merge it, just use the
  415. // patch directly. Later on, we can add a single level replace that only
  416. // affects the map that the $patch is in.
  417. delete(patch, directiveMarker)
  418. return patch, nil
  419. }
  420. if v == deleteDirective {
  421. // If the patch contains "$patch: delete", don't merge it, just return
  422. // an empty map.
  423. return map[string]interface{}{}, nil
  424. }
  425. return nil, fmt.Errorf(errBadPatchTypeFmt, v, patch)
  426. }
  427. // nil is an accepted value for original to simplify logic in other places.
  428. // If original is nil, replace it with an empty map and then apply the patch.
  429. if original == nil {
  430. original = map[string]interface{}{}
  431. }
  432. // Start merging the patch into the original.
  433. for k, patchV := range patch {
  434. // If the value of this key is null, delete the key if it exists in the
  435. // original. Otherwise, skip it.
  436. if patchV == nil {
  437. if _, ok := original[k]; ok {
  438. delete(original, k)
  439. }
  440. continue
  441. }
  442. _, ok := original[k]
  443. if !ok {
  444. // If it's not in the original document, just take the patch value.
  445. original[k] = patchV
  446. continue
  447. }
  448. // If the data type is a pointer, resolve the element.
  449. if t.Kind() == reflect.Ptr {
  450. t = t.Elem()
  451. }
  452. // If they're both maps or lists, recurse into the value.
  453. originalType := reflect.TypeOf(original[k])
  454. patchType := reflect.TypeOf(patchV)
  455. if originalType == patchType {
  456. // First find the fieldPatchStrategy and fieldPatchMergeKey.
  457. fieldType, fieldPatchStrategy, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadata(t, k)
  458. if err != nil {
  459. return nil, err
  460. }
  461. if originalType.Kind() == reflect.Map && fieldPatchStrategy != replaceDirective {
  462. typedOriginal := original[k].(map[string]interface{})
  463. typedPatch := patchV.(map[string]interface{})
  464. var err error
  465. original[k], err = mergeMap(typedOriginal, typedPatch, fieldType)
  466. if err != nil {
  467. return nil, err
  468. }
  469. continue
  470. }
  471. if originalType.Kind() == reflect.Slice && fieldPatchStrategy == mergeDirective {
  472. elemType := fieldType.Elem()
  473. typedOriginal := original[k].([]interface{})
  474. typedPatch := patchV.([]interface{})
  475. var err error
  476. original[k], err = mergeSlice(typedOriginal, typedPatch, elemType, fieldPatchMergeKey)
  477. if err != nil {
  478. return nil, err
  479. }
  480. continue
  481. }
  482. }
  483. // If originalType and patchType are different OR the types are both
  484. // maps or slices but we're just supposed to replace them, just take
  485. // the value from patch.
  486. original[k] = patchV
  487. }
  488. return original, nil
  489. }
  490. // Merge two slices together. Note: This may modify both the original slice and
  491. // the patch because getting a deep copy of a slice in golang is highly
  492. // non-trivial.
  493. func mergeSlice(original, patch []interface{}, elemType reflect.Type, mergeKey string) ([]interface{}, error) {
  494. if len(original) == 0 && len(patch) == 0 {
  495. return original, nil
  496. }
  497. // All the values must be of the same type, but not a list.
  498. t, err := sliceElementType(original, patch)
  499. if err != nil {
  500. return nil, err
  501. }
  502. // If the elements are not maps, merge the slices of scalars.
  503. if t.Kind() != reflect.Map {
  504. // Maybe in the future add a "concat" mode that doesn't
  505. // uniqify.
  506. both := append(original, patch...)
  507. return uniqifyScalars(both), nil
  508. }
  509. if mergeKey == "" {
  510. return nil, fmt.Errorf("cannot merge lists without merge key for type %s", elemType.Kind().String())
  511. }
  512. // First look for any special $patch elements.
  513. patchWithoutSpecialElements := []interface{}{}
  514. replace := false
  515. for _, v := range patch {
  516. typedV := v.(map[string]interface{})
  517. patchType, ok := typedV[directiveMarker]
  518. if ok {
  519. if patchType == deleteDirective {
  520. mergeValue, ok := typedV[mergeKey]
  521. if ok {
  522. _, originalKey, found, err := findMapInSliceBasedOnKeyValue(original, mergeKey, mergeValue)
  523. if err != nil {
  524. return nil, err
  525. }
  526. if found {
  527. // Delete the element at originalKey.
  528. original = append(original[:originalKey], original[originalKey+1:]...)
  529. }
  530. } else {
  531. return nil, fmt.Errorf("delete patch type with no merge key defined")
  532. }
  533. } else if patchType == replaceDirective {
  534. replace = true
  535. // Continue iterating through the array to prune any other $patch elements.
  536. } else if patchType == mergeDirective {
  537. return nil, fmt.Errorf("merging lists cannot yet be specified in the patch")
  538. } else {
  539. return nil, fmt.Errorf(errBadPatchTypeFmt, patchType, typedV)
  540. }
  541. } else {
  542. patchWithoutSpecialElements = append(patchWithoutSpecialElements, v)
  543. }
  544. }
  545. if replace {
  546. return patchWithoutSpecialElements, nil
  547. }
  548. patch = patchWithoutSpecialElements
  549. // Merge patch into original.
  550. for _, v := range patch {
  551. // Because earlier we confirmed that all the elements are maps.
  552. typedV := v.(map[string]interface{})
  553. mergeValue, ok := typedV[mergeKey]
  554. if !ok {
  555. return nil, fmt.Errorf(errNoMergeKeyFmt, typedV, mergeKey)
  556. }
  557. // If we find a value with this merge key value in original, merge the
  558. // maps. Otherwise append onto original.
  559. originalMap, originalKey, found, err := findMapInSliceBasedOnKeyValue(original, mergeKey, mergeValue)
  560. if err != nil {
  561. return nil, err
  562. }
  563. if found {
  564. var mergedMaps interface{}
  565. var err error
  566. // Merge into original.
  567. mergedMaps, err = mergeMap(originalMap, typedV, elemType)
  568. if err != nil {
  569. return nil, err
  570. }
  571. original[originalKey] = mergedMaps
  572. } else {
  573. original = append(original, v)
  574. }
  575. }
  576. return original, nil
  577. }
  578. // This method no longer panics if any element of the slice is not a map.
  579. func findMapInSliceBasedOnKeyValue(m []interface{}, key string, value interface{}) (map[string]interface{}, int, bool, error) {
  580. for k, v := range m {
  581. typedV, ok := v.(map[string]interface{})
  582. if !ok {
  583. return nil, 0, false, fmt.Errorf("value for key %v is not a map.", k)
  584. }
  585. valueToMatch, ok := typedV[key]
  586. if ok && valueToMatch == value {
  587. return typedV, k, true, nil
  588. }
  589. }
  590. return nil, 0, false, nil
  591. }
  592. // This function takes a JSON map and sorts all the lists that should be merged
  593. // by key. This is needed by tests because in JSON, list order is significant,
  594. // but in Strategic Merge Patch, merge lists do not have significant order.
  595. // Sorting the lists allows for order-insensitive comparison of patched maps.
  596. func sortMergeListsByName(mapJSON []byte, dataStruct interface{}) ([]byte, error) {
  597. var m map[string]interface{}
  598. err := json.Unmarshal(mapJSON, &m)
  599. if err != nil {
  600. return nil, err
  601. }
  602. newM, err := sortMergeListsByNameMap(m, reflect.TypeOf(dataStruct))
  603. if err != nil {
  604. return nil, err
  605. }
  606. return json.Marshal(newM)
  607. }
  608. func sortMergeListsByNameMap(s map[string]interface{}, t reflect.Type) (map[string]interface{}, error) {
  609. newS := map[string]interface{}{}
  610. for k, v := range s {
  611. if k != directiveMarker {
  612. fieldType, fieldPatchStrategy, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadata(t, k)
  613. if err != nil {
  614. return nil, err
  615. }
  616. // If v is a map or a merge slice, recurse.
  617. if typedV, ok := v.(map[string]interface{}); ok {
  618. var err error
  619. v, err = sortMergeListsByNameMap(typedV, fieldType)
  620. if err != nil {
  621. return nil, err
  622. }
  623. } else if typedV, ok := v.([]interface{}); ok {
  624. if fieldPatchStrategy == mergeDirective {
  625. var err error
  626. v, err = sortMergeListsByNameArray(typedV, fieldType.Elem(), fieldPatchMergeKey, true)
  627. if err != nil {
  628. return nil, err
  629. }
  630. }
  631. }
  632. }
  633. newS[k] = v
  634. }
  635. return newS, nil
  636. }
  637. func sortMergeListsByNameArray(s []interface{}, elemType reflect.Type, mergeKey string, recurse bool) ([]interface{}, error) {
  638. if len(s) == 0 {
  639. return s, nil
  640. }
  641. // We don't support lists of lists yet.
  642. t, err := sliceElementType(s)
  643. if err != nil {
  644. return nil, err
  645. }
  646. // If the elements are not maps...
  647. if t.Kind() != reflect.Map {
  648. // Sort the elements, because they may have been merged out of order.
  649. return uniqifyAndSortScalars(s), nil
  650. }
  651. // Elements are maps - if one of the keys of the map is a map or a
  652. // list, we may need to recurse into it.
  653. newS := []interface{}{}
  654. for _, elem := range s {
  655. if recurse {
  656. typedElem := elem.(map[string]interface{})
  657. newElem, err := sortMergeListsByNameMap(typedElem, elemType)
  658. if err != nil {
  659. return nil, err
  660. }
  661. newS = append(newS, newElem)
  662. } else {
  663. newS = append(newS, elem)
  664. }
  665. }
  666. // Sort the maps.
  667. newS = sortMapsBasedOnField(newS, mergeKey)
  668. return newS, nil
  669. }
  670. func sortMapsBasedOnField(m []interface{}, fieldName string) []interface{} {
  671. mapM := mapSliceFromSlice(m)
  672. ss := SortableSliceOfMaps{mapM, fieldName}
  673. sort.Sort(ss)
  674. newS := sliceFromMapSlice(ss.s)
  675. return newS
  676. }
  677. func mapSliceFromSlice(m []interface{}) []map[string]interface{} {
  678. newM := []map[string]interface{}{}
  679. for _, v := range m {
  680. vt := v.(map[string]interface{})
  681. newM = append(newM, vt)
  682. }
  683. return newM
  684. }
  685. func sliceFromMapSlice(s []map[string]interface{}) []interface{} {
  686. newS := []interface{}{}
  687. for _, v := range s {
  688. newS = append(newS, v)
  689. }
  690. return newS
  691. }
  692. type SortableSliceOfMaps struct {
  693. s []map[string]interface{}
  694. k string // key to sort on
  695. }
  696. func (ss SortableSliceOfMaps) Len() int {
  697. return len(ss.s)
  698. }
  699. func (ss SortableSliceOfMaps) Less(i, j int) bool {
  700. iStr := fmt.Sprintf("%v", ss.s[i][ss.k])
  701. jStr := fmt.Sprintf("%v", ss.s[j][ss.k])
  702. return sort.StringsAreSorted([]string{iStr, jStr})
  703. }
  704. func (ss SortableSliceOfMaps) Swap(i, j int) {
  705. tmp := ss.s[i]
  706. ss.s[i] = ss.s[j]
  707. ss.s[j] = tmp
  708. }
  709. func uniqifyAndSortScalars(s []interface{}) []interface{} {
  710. s = uniqifyScalars(s)
  711. ss := SortableSliceOfScalars{s}
  712. sort.Sort(ss)
  713. return ss.s
  714. }
  715. func uniqifyScalars(s []interface{}) []interface{} {
  716. // Clever algorithm to uniqify.
  717. length := len(s) - 1
  718. for i := 0; i < length; i++ {
  719. for j := i + 1; j <= length; j++ {
  720. if s[i] == s[j] {
  721. s[j] = s[length]
  722. s = s[0:length]
  723. length--
  724. j--
  725. }
  726. }
  727. }
  728. return s
  729. }
  730. type SortableSliceOfScalars struct {
  731. s []interface{}
  732. }
  733. func (ss SortableSliceOfScalars) Len() int {
  734. return len(ss.s)
  735. }
  736. func (ss SortableSliceOfScalars) Less(i, j int) bool {
  737. iStr := fmt.Sprintf("%v", ss.s[i])
  738. jStr := fmt.Sprintf("%v", ss.s[j])
  739. return sort.StringsAreSorted([]string{iStr, jStr})
  740. }
  741. func (ss SortableSliceOfScalars) Swap(i, j int) {
  742. tmp := ss.s[i]
  743. ss.s[i] = ss.s[j]
  744. ss.s[j] = tmp
  745. }
  746. // Returns the type of the elements of N slice(s). If the type is different,
  747. // another slice or undefined, returns an error.
  748. func sliceElementType(slices ...[]interface{}) (reflect.Type, error) {
  749. var prevType reflect.Type
  750. for _, s := range slices {
  751. // Go through elements of all given slices and make sure they are all the same type.
  752. for _, v := range s {
  753. currentType := reflect.TypeOf(v)
  754. if prevType == nil {
  755. prevType = currentType
  756. // We don't support lists of lists yet.
  757. if prevType.Kind() == reflect.Slice {
  758. return nil, errNoListOfLists
  759. }
  760. } else {
  761. if prevType != currentType {
  762. return nil, fmt.Errorf("list element types are not identical: %v", fmt.Sprint(slices))
  763. }
  764. prevType = currentType
  765. }
  766. }
  767. }
  768. if prevType == nil {
  769. return nil, fmt.Errorf("no elements in any of the given slices")
  770. }
  771. return prevType, nil
  772. }
  773. // HasConflicts returns true if the left and right JSON interface objects overlap with
  774. // different values in any key. All keys are required to be strings. Since patches of the
  775. // same Type have congruent keys, this is valid for multiple patch types. This method
  776. // supports JSON merge patch semantics.
  777. func HasConflicts(left, right interface{}) (bool, error) {
  778. switch typedLeft := left.(type) {
  779. case map[string]interface{}:
  780. switch typedRight := right.(type) {
  781. case map[string]interface{}:
  782. for key, leftValue := range typedLeft {
  783. rightValue, ok := typedRight[key]
  784. if !ok {
  785. return false, nil
  786. }
  787. return HasConflicts(leftValue, rightValue)
  788. }
  789. return false, nil
  790. default:
  791. return true, nil
  792. }
  793. case []interface{}:
  794. switch typedRight := right.(type) {
  795. case []interface{}:
  796. if len(typedLeft) != len(typedRight) {
  797. return true, nil
  798. }
  799. for i := range typedLeft {
  800. return HasConflicts(typedLeft[i], typedRight[i])
  801. }
  802. return false, nil
  803. default:
  804. return true, nil
  805. }
  806. case string, float64, bool, int, int64, nil:
  807. return !reflect.DeepEqual(left, right), nil
  808. default:
  809. return true, fmt.Errorf("unknown type: %v", reflect.TypeOf(left))
  810. }
  811. }
  812. // MergingMapsHaveConflicts returns true if the left and right JSON interface
  813. // objects overlap with different values in any key. All keys are required to be
  814. // strings. Since patches of the same Type have congruent keys, this is valid
  815. // for multiple patch types. This method supports strategic merge patch semantics.
  816. func MergingMapsHaveConflicts(left, right map[string]interface{}, dataStruct interface{}) (bool, error) {
  817. t, err := getTagStructType(dataStruct)
  818. if err != nil {
  819. return true, err
  820. }
  821. return mergingMapFieldsHaveConflicts(left, right, t, "", "")
  822. }
  823. func mergingMapFieldsHaveConflicts(
  824. left, right interface{},
  825. fieldType reflect.Type,
  826. fieldPatchStrategy, fieldPatchMergeKey string,
  827. ) (bool, error) {
  828. switch leftType := left.(type) {
  829. case map[string]interface{}:
  830. switch rightType := right.(type) {
  831. case map[string]interface{}:
  832. leftMarker, okLeft := leftType[directiveMarker]
  833. rightMarker, okRight := rightType[directiveMarker]
  834. // if one or the other has a directive marker,
  835. // then we need to consider that before looking at the individual keys,
  836. // since a directive operates on the whole map.
  837. if okLeft || okRight {
  838. // if one has a directive marker and the other doesn't,
  839. // then we have a conflict, since one is deleting or replacing the whole map,
  840. // and the other is doing things to individual keys.
  841. if okLeft != okRight {
  842. return true, nil
  843. }
  844. // if they both have markers, but they are not the same directive,
  845. // then we have a conflict because they're doing different things to the map.
  846. if leftMarker != rightMarker {
  847. return true, nil
  848. }
  849. }
  850. // Check the individual keys.
  851. return mapsHaveConflicts(leftType, rightType, fieldType)
  852. default:
  853. return true, nil
  854. }
  855. case []interface{}:
  856. switch rightType := right.(type) {
  857. case []interface{}:
  858. return slicesHaveConflicts(leftType, rightType, fieldType, fieldPatchStrategy, fieldPatchMergeKey)
  859. default:
  860. return true, nil
  861. }
  862. case string, float64, bool, int, int64, nil:
  863. return !reflect.DeepEqual(left, right), nil
  864. default:
  865. return true, fmt.Errorf("unknown type: %v", reflect.TypeOf(left))
  866. }
  867. }
  868. func mapsHaveConflicts(typedLeft, typedRight map[string]interface{}, structType reflect.Type) (bool, error) {
  869. for key, leftValue := range typedLeft {
  870. if key != directiveMarker {
  871. if rightValue, ok := typedRight[key]; ok {
  872. fieldType, fieldPatchStrategy, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadata(structType, key)
  873. if err != nil {
  874. return true, err
  875. }
  876. if hasConflicts, err := mergingMapFieldsHaveConflicts(leftValue, rightValue,
  877. fieldType, fieldPatchStrategy, fieldPatchMergeKey); hasConflicts {
  878. return true, err
  879. }
  880. }
  881. }
  882. }
  883. return false, nil
  884. }
  885. func slicesHaveConflicts(
  886. typedLeft, typedRight []interface{},
  887. fieldType reflect.Type,
  888. fieldPatchStrategy, fieldPatchMergeKey string,
  889. ) (bool, error) {
  890. elementType, err := sliceElementType(typedLeft, typedRight)
  891. if err != nil {
  892. return true, err
  893. }
  894. valueType := fieldType.Elem()
  895. if fieldPatchStrategy == mergeDirective {
  896. // Merging lists of scalars have no conflicts by definition
  897. // So we only need to check further if the elements are maps
  898. if elementType.Kind() != reflect.Map {
  899. return false, nil
  900. }
  901. // Build a map for each slice and then compare the two maps
  902. leftMap, err := sliceOfMapsToMapOfMaps(typedLeft, fieldPatchMergeKey)
  903. if err != nil {
  904. return true, err
  905. }
  906. rightMap, err := sliceOfMapsToMapOfMaps(typedRight, fieldPatchMergeKey)
  907. if err != nil {
  908. return true, err
  909. }
  910. return mapsOfMapsHaveConflicts(leftMap, rightMap, valueType)
  911. }
  912. // Either we don't have type information, or these are non-merging lists
  913. if len(typedLeft) != len(typedRight) {
  914. return true, nil
  915. }
  916. // Sort scalar slices to prevent ordering issues
  917. // We have no way to sort non-merging lists of maps
  918. if elementType.Kind() != reflect.Map {
  919. typedLeft = uniqifyAndSortScalars(typedLeft)
  920. typedRight = uniqifyAndSortScalars(typedRight)
  921. }
  922. // Compare the slices element by element in order
  923. // This test will fail if the slices are not sorted
  924. for i := range typedLeft {
  925. if hasConflicts, err := mergingMapFieldsHaveConflicts(typedLeft[i], typedRight[i], valueType, "", ""); hasConflicts {
  926. return true, err
  927. }
  928. }
  929. return false, nil
  930. }
  931. func sliceOfMapsToMapOfMaps(slice []interface{}, mergeKey string) (map[string]interface{}, error) {
  932. result := make(map[string]interface{}, len(slice))
  933. for _, value := range slice {
  934. typedValue, ok := value.(map[string]interface{})
  935. if !ok {
  936. return nil, fmt.Errorf("invalid element type in merging list:%v", slice)
  937. }
  938. mergeValue, ok := typedValue[mergeKey]
  939. if !ok {
  940. return nil, fmt.Errorf("cannot find merge key `%s` in merging list element:%v", mergeKey, typedValue)
  941. }
  942. result[fmt.Sprintf("%s", mergeValue)] = typedValue
  943. }
  944. return result, nil
  945. }
  946. func mapsOfMapsHaveConflicts(typedLeft, typedRight map[string]interface{}, structType reflect.Type) (bool, error) {
  947. for key, leftValue := range typedLeft {
  948. if rightValue, ok := typedRight[key]; ok {
  949. if hasConflicts, err := mergingMapFieldsHaveConflicts(leftValue, rightValue, structType, "", ""); hasConflicts {
  950. return true, err
  951. }
  952. }
  953. }
  954. return false, nil
  955. }
  956. // CreateThreeWayMergePatch reconciles a modified configuration with an original configuration,
  957. // while preserving any changes or deletions made to the original configuration in the interim,
  958. // and not overridden by the current configuration. All three documents must be passed to the
  959. // method as json encoded content. It will return a strategic merge patch, or an error if any
  960. // of the documents is invalid, or if there are any preconditions that fail against the modified
  961. // configuration, or, if overwrite is false and there are conflicts between the modified and current
  962. // configurations. Conflicts are defined as keys changed differently from original to modified
  963. // than from original to current. In other words, a conflict occurs if modified changes any key
  964. // in a way that is different from how it is changed in current (e.g., deleting it, changing its
  965. // value).
  966. func CreateThreeWayMergePatch(original, modified, current []byte, dataStruct interface{}, overwrite bool, fns ...PreconditionFunc) ([]byte, error) {
  967. originalMap := map[string]interface{}{}
  968. if len(original) > 0 {
  969. if err := json.Unmarshal(original, &originalMap); err != nil {
  970. return nil, errBadJSONDoc
  971. }
  972. }
  973. modifiedMap := map[string]interface{}{}
  974. if len(modified) > 0 {
  975. if err := json.Unmarshal(modified, &modifiedMap); err != nil {
  976. return nil, errBadJSONDoc
  977. }
  978. }
  979. currentMap := map[string]interface{}{}
  980. if len(current) > 0 {
  981. if err := json.Unmarshal(current, &currentMap); err != nil {
  982. return nil, errBadJSONDoc
  983. }
  984. }
  985. t, err := getTagStructType(dataStruct)
  986. if err != nil {
  987. return nil, err
  988. }
  989. // The patch is the difference from current to modified without deletions, plus deletions
  990. // from original to modified. To find it, we compute deletions, which are the deletions from
  991. // original to modified, and delta, which is the difference from current to modified without
  992. // deletions, and then apply delta to deletions as a patch, which should be strictly additive.
  993. deltaMap, err := diffMaps(currentMap, modifiedMap, t, false, true)
  994. if err != nil {
  995. return nil, err
  996. }
  997. deletionsMap, err := diffMaps(originalMap, modifiedMap, t, true, false)
  998. if err != nil {
  999. return nil, err
  1000. }
  1001. patchMap, err := mergeMap(deletionsMap, deltaMap, t)
  1002. if err != nil {
  1003. return nil, err
  1004. }
  1005. // Apply the preconditions to the patch, and return an error if any of them fail.
  1006. for _, fn := range fns {
  1007. if !fn(patchMap) {
  1008. return nil, newErrPreconditionFailed(patchMap)
  1009. }
  1010. }
  1011. // If overwrite is false, and the patch contains any keys that were changed differently,
  1012. // then return a conflict error.
  1013. if !overwrite {
  1014. changedMap, err := diffMaps(originalMap, currentMap, t, false, false)
  1015. if err != nil {
  1016. return nil, err
  1017. }
  1018. hasConflicts, err := MergingMapsHaveConflicts(patchMap, changedMap, dataStruct)
  1019. if err != nil {
  1020. return nil, err
  1021. }
  1022. if hasConflicts {
  1023. return nil, newErrConflict(toYAMLOrError(patchMap), toYAMLOrError(changedMap))
  1024. }
  1025. }
  1026. return json.Marshal(patchMap)
  1027. }
  1028. func toYAMLOrError(v interface{}) string {
  1029. y, err := toYAML(v)
  1030. if err != nil {
  1031. return err.Error()
  1032. }
  1033. return y
  1034. }
  1035. func toYAML(v interface{}) (string, error) {
  1036. y, err := yaml.Marshal(v)
  1037. if err != nil {
  1038. return "", fmt.Errorf("yaml marshal failed:%v\n%v\n", err, spew.Sdump(v))
  1039. }
  1040. return string(y), nil
  1041. }