patch.go 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257
  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. "strings"
  19. "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
  20. "k8s.io/apimachinery/pkg/util/json"
  21. "k8s.io/apimachinery/pkg/util/mergepatch"
  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. retainKeysStrategy = "retainKeys"
  38. deleteFromPrimitiveListDirectivePrefix = "$deleteFromPrimitiveList"
  39. retainKeysDirective = "$" + retainKeysStrategy
  40. setElementOrderDirectivePrefix = "$setElementOrder"
  41. )
  42. // JSONMap is a representations of JSON object encoded as map[string]interface{}
  43. // where the children can be either map[string]interface{}, []interface{} or
  44. // primitive type).
  45. // Operating on JSONMap representation is much faster as it doesn't require any
  46. // json marshaling and/or unmarshaling operations.
  47. type JSONMap map[string]interface{}
  48. type DiffOptions struct {
  49. // SetElementOrder determines whether we generate the $setElementOrder parallel list.
  50. SetElementOrder bool
  51. // IgnoreChangesAndAdditions indicates if we keep the changes and additions in the patch.
  52. IgnoreChangesAndAdditions bool
  53. // IgnoreDeletions indicates if we keep the deletions in the patch.
  54. IgnoreDeletions bool
  55. // We introduce a new value retainKeys for patchStrategy.
  56. // It indicates that all fields needing to be preserved must be
  57. // present in the `retainKeys` list.
  58. // And the fields that are present will be merged with live object.
  59. // All the missing fields will be cleared when patching.
  60. BuildRetainKeysDirective bool
  61. }
  62. type MergeOptions struct {
  63. // MergeParallelList indicates if we are merging the parallel list.
  64. // We don't merge parallel list when calling mergeMap() in CreateThreeWayMergePatch()
  65. // which is called client-side.
  66. // We merge parallel list iff when calling mergeMap() in StrategicMergeMapPatch()
  67. // which is called server-side
  68. MergeParallelList bool
  69. // IgnoreUnmatchedNulls indicates if we should process the unmatched nulls.
  70. IgnoreUnmatchedNulls bool
  71. }
  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. // CreateTwoWayMergePatch creates a patch that can be passed to StrategicMergePatch from an original
  76. // document and a modified document, which are passed to the method as json encoded content. It will
  77. // return a patch that yields the modified document when applied to the original document, or an error
  78. // if either of the two documents is invalid.
  79. func CreateTwoWayMergePatch(original, modified []byte, dataStruct interface{}, fns ...mergepatch.PreconditionFunc) ([]byte, error) {
  80. schema, err := NewPatchMetaFromStruct(dataStruct)
  81. if err != nil {
  82. return nil, err
  83. }
  84. return CreateTwoWayMergePatchUsingLookupPatchMeta(original, modified, schema, fns...)
  85. }
  86. func CreateTwoWayMergePatchUsingLookupPatchMeta(
  87. original, modified []byte, schema LookupPatchMeta, fns ...mergepatch.PreconditionFunc) ([]byte, error) {
  88. originalMap := map[string]interface{}{}
  89. if len(original) > 0 {
  90. if err := json.Unmarshal(original, &originalMap); err != nil {
  91. return nil, mergepatch.ErrBadJSONDoc
  92. }
  93. }
  94. modifiedMap := map[string]interface{}{}
  95. if len(modified) > 0 {
  96. if err := json.Unmarshal(modified, &modifiedMap); err != nil {
  97. return nil, mergepatch.ErrBadJSONDoc
  98. }
  99. }
  100. patchMap, err := CreateTwoWayMergeMapPatchUsingLookupPatchMeta(originalMap, modifiedMap, schema, fns...)
  101. if err != nil {
  102. return nil, err
  103. }
  104. return json.Marshal(patchMap)
  105. }
  106. // CreateTwoWayMergeMapPatch creates a patch from an original and modified JSON objects,
  107. // encoded JSONMap.
  108. // The serialized version of the map can then be passed to StrategicMergeMapPatch.
  109. func CreateTwoWayMergeMapPatch(original, modified JSONMap, dataStruct interface{}, fns ...mergepatch.PreconditionFunc) (JSONMap, error) {
  110. schema, err := NewPatchMetaFromStruct(dataStruct)
  111. if err != nil {
  112. return nil, err
  113. }
  114. return CreateTwoWayMergeMapPatchUsingLookupPatchMeta(original, modified, schema, fns...)
  115. }
  116. func CreateTwoWayMergeMapPatchUsingLookupPatchMeta(original, modified JSONMap, schema LookupPatchMeta, fns ...mergepatch.PreconditionFunc) (JSONMap, error) {
  117. diffOptions := DiffOptions{
  118. SetElementOrder: true,
  119. }
  120. patchMap, err := diffMaps(original, modified, schema, diffOptions)
  121. if err != nil {
  122. return nil, err
  123. }
  124. // Apply the preconditions to the patch, and return an error if any of them fail.
  125. for _, fn := range fns {
  126. if !fn(patchMap) {
  127. return nil, mergepatch.NewErrPreconditionFailed(patchMap)
  128. }
  129. }
  130. return patchMap, nil
  131. }
  132. // Returns a (recursive) strategic merge patch that yields modified when applied to original.
  133. // Including:
  134. // - Adding fields to the patch present in modified, missing from original
  135. // - Setting fields to the patch present in modified and original with different values
  136. // - Delete fields present in original, missing from modified through
  137. // - IFF map field - set to nil in patch
  138. // - IFF list of maps && merge strategy - use deleteDirective for the elements
  139. // - IFF list of primitives && merge strategy - use parallel deletion list
  140. // - IFF list of maps or primitives with replace strategy (default) - set patch value to the value in modified
  141. // - Build $retainKeys directive for fields with retainKeys patch strategy
  142. func diffMaps(original, modified map[string]interface{}, schema LookupPatchMeta, diffOptions DiffOptions) (map[string]interface{}, error) {
  143. patch := map[string]interface{}{}
  144. // This will be used to build the $retainKeys directive sent in the patch
  145. retainKeysList := make([]interface{}, 0, len(modified))
  146. // Compare each value in the modified map against the value in the original map
  147. for key, modifiedValue := range modified {
  148. // Get the underlying type for pointers
  149. if diffOptions.BuildRetainKeysDirective && modifiedValue != nil {
  150. retainKeysList = append(retainKeysList, key)
  151. }
  152. originalValue, ok := original[key]
  153. if !ok {
  154. // Key was added, so add to patch
  155. if !diffOptions.IgnoreChangesAndAdditions {
  156. patch[key] = modifiedValue
  157. }
  158. continue
  159. }
  160. // The patch may have a patch directive
  161. // TODO: figure out if we need this. This shouldn't be needed by apply. When would the original map have patch directives in it?
  162. foundDirectiveMarker, err := handleDirectiveMarker(key, originalValue, modifiedValue, patch)
  163. if err != nil {
  164. return nil, err
  165. }
  166. if foundDirectiveMarker {
  167. continue
  168. }
  169. if reflect.TypeOf(originalValue) != reflect.TypeOf(modifiedValue) {
  170. // Types have changed, so add to patch
  171. if !diffOptions.IgnoreChangesAndAdditions {
  172. patch[key] = modifiedValue
  173. }
  174. continue
  175. }
  176. // Types are the same, so compare values
  177. switch originalValueTyped := originalValue.(type) {
  178. case map[string]interface{}:
  179. modifiedValueTyped := modifiedValue.(map[string]interface{})
  180. err = handleMapDiff(key, originalValueTyped, modifiedValueTyped, patch, schema, diffOptions)
  181. case []interface{}:
  182. modifiedValueTyped := modifiedValue.([]interface{})
  183. err = handleSliceDiff(key, originalValueTyped, modifiedValueTyped, patch, schema, diffOptions)
  184. default:
  185. replacePatchFieldIfNotEqual(key, originalValue, modifiedValue, patch, diffOptions)
  186. }
  187. if err != nil {
  188. return nil, err
  189. }
  190. }
  191. updatePatchIfMissing(original, modified, patch, diffOptions)
  192. // Insert the retainKeysList iff there are values present in the retainKeysList and
  193. // either of the following is true:
  194. // - the patch is not empty
  195. // - there are additional field in original that need to be cleared
  196. if len(retainKeysList) > 0 &&
  197. (len(patch) > 0 || hasAdditionalNewField(original, modified)) {
  198. patch[retainKeysDirective] = sortScalars(retainKeysList)
  199. }
  200. return patch, nil
  201. }
  202. // handleDirectiveMarker handles how to diff directive marker between 2 objects
  203. func handleDirectiveMarker(key string, originalValue, modifiedValue interface{}, patch map[string]interface{}) (bool, error) {
  204. if key == directiveMarker {
  205. originalString, ok := originalValue.(string)
  206. if !ok {
  207. return false, fmt.Errorf("invalid value for special key: %s", directiveMarker)
  208. }
  209. modifiedString, ok := modifiedValue.(string)
  210. if !ok {
  211. return false, fmt.Errorf("invalid value for special key: %s", directiveMarker)
  212. }
  213. if modifiedString != originalString {
  214. patch[directiveMarker] = modifiedValue
  215. }
  216. return true, nil
  217. }
  218. return false, nil
  219. }
  220. // handleMapDiff diff between 2 maps `originalValueTyped` and `modifiedValue`,
  221. // puts the diff in the `patch` associated with `key`
  222. // key is the key associated with originalValue and modifiedValue.
  223. // originalValue, modifiedValue are the old and new value respectively.They are both maps
  224. // patch is the patch map that contains key and the updated value, and it is the parent of originalValue, modifiedValue
  225. // diffOptions contains multiple options to control how we do the diff.
  226. func handleMapDiff(key string, originalValue, modifiedValue, patch map[string]interface{},
  227. schema LookupPatchMeta, diffOptions DiffOptions) error {
  228. subschema, patchMeta, err := schema.LookupPatchMetadataForStruct(key)
  229. if err != nil {
  230. // We couldn't look up metadata for the field
  231. // If the values are identical, this doesn't matter, no patch is needed
  232. if reflect.DeepEqual(originalValue, modifiedValue) {
  233. return nil
  234. }
  235. // Otherwise, return the error
  236. return err
  237. }
  238. retainKeys, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
  239. if err != nil {
  240. return err
  241. }
  242. diffOptions.BuildRetainKeysDirective = retainKeys
  243. switch patchStrategy {
  244. // The patch strategic from metadata tells us to replace the entire object instead of diffing it
  245. case replaceDirective:
  246. if !diffOptions.IgnoreChangesAndAdditions {
  247. patch[key] = modifiedValue
  248. }
  249. default:
  250. patchValue, err := diffMaps(originalValue, modifiedValue, subschema, diffOptions)
  251. if err != nil {
  252. return err
  253. }
  254. // Maps were not identical, use provided patch value
  255. if len(patchValue) > 0 {
  256. patch[key] = patchValue
  257. }
  258. }
  259. return nil
  260. }
  261. // handleSliceDiff diff between 2 slices `originalValueTyped` and `modifiedValue`,
  262. // puts the diff in the `patch` associated with `key`
  263. // key is the key associated with originalValue and modifiedValue.
  264. // originalValue, modifiedValue are the old and new value respectively.They are both slices
  265. // patch is the patch map that contains key and the updated value, and it is the parent of originalValue, modifiedValue
  266. // diffOptions contains multiple options to control how we do the diff.
  267. func handleSliceDiff(key string, originalValue, modifiedValue []interface{}, patch map[string]interface{},
  268. schema LookupPatchMeta, diffOptions DiffOptions) error {
  269. subschema, patchMeta, err := schema.LookupPatchMetadataForSlice(key)
  270. if err != nil {
  271. // We couldn't look up metadata for the field
  272. // If the values are identical, this doesn't matter, no patch is needed
  273. if reflect.DeepEqual(originalValue, modifiedValue) {
  274. return nil
  275. }
  276. // Otherwise, return the error
  277. return err
  278. }
  279. retainKeys, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
  280. if err != nil {
  281. return err
  282. }
  283. switch patchStrategy {
  284. // Merge the 2 slices using mergePatchKey
  285. case mergeDirective:
  286. diffOptions.BuildRetainKeysDirective = retainKeys
  287. addList, deletionList, setOrderList, err := diffLists(originalValue, modifiedValue, subschema, patchMeta.GetPatchMergeKey(), diffOptions)
  288. if err != nil {
  289. return err
  290. }
  291. if len(addList) > 0 {
  292. patch[key] = addList
  293. }
  294. // generate a parallel list for deletion
  295. if len(deletionList) > 0 {
  296. parallelDeletionListKey := fmt.Sprintf("%s/%s", deleteFromPrimitiveListDirectivePrefix, key)
  297. patch[parallelDeletionListKey] = deletionList
  298. }
  299. if len(setOrderList) > 0 {
  300. parallelSetOrderListKey := fmt.Sprintf("%s/%s", setElementOrderDirectivePrefix, key)
  301. patch[parallelSetOrderListKey] = setOrderList
  302. }
  303. default:
  304. replacePatchFieldIfNotEqual(key, originalValue, modifiedValue, patch, diffOptions)
  305. }
  306. return nil
  307. }
  308. // replacePatchFieldIfNotEqual updates the patch if original and modified are not deep equal
  309. // if diffOptions.IgnoreChangesAndAdditions is false.
  310. // original is the old value, maybe either the live cluster object or the last applied configuration
  311. // modified is the new value, is always the users new config
  312. func replacePatchFieldIfNotEqual(key string, original, modified interface{},
  313. patch map[string]interface{}, diffOptions DiffOptions) {
  314. if diffOptions.IgnoreChangesAndAdditions {
  315. // Ignoring changes - do nothing
  316. return
  317. }
  318. if reflect.DeepEqual(original, modified) {
  319. // Contents are identical - do nothing
  320. return
  321. }
  322. // Create a patch to replace the old value with the new one
  323. patch[key] = modified
  324. }
  325. // updatePatchIfMissing iterates over `original` when ignoreDeletions is false.
  326. // Clear the field whose key is not present in `modified`.
  327. // original is the old value, maybe either the live cluster object or the last applied configuration
  328. // modified is the new value, is always the users new config
  329. func updatePatchIfMissing(original, modified, patch map[string]interface{}, diffOptions DiffOptions) {
  330. if diffOptions.IgnoreDeletions {
  331. // Ignoring deletion - do nothing
  332. return
  333. }
  334. // Add nils for deleted values
  335. for key := range original {
  336. if _, found := modified[key]; !found {
  337. patch[key] = nil
  338. }
  339. }
  340. }
  341. // validateMergeKeyInLists checks if each map in the list has the mentryerge key.
  342. func validateMergeKeyInLists(mergeKey string, lists ...[]interface{}) error {
  343. for _, list := range lists {
  344. for _, item := range list {
  345. m, ok := item.(map[string]interface{})
  346. if !ok {
  347. return mergepatch.ErrBadArgType(m, item)
  348. }
  349. if _, ok = m[mergeKey]; !ok {
  350. return mergepatch.ErrNoMergeKey(m, mergeKey)
  351. }
  352. }
  353. }
  354. return nil
  355. }
  356. // normalizeElementOrder sort `patch` list by `patchOrder` and sort `serverOnly` list by `serverOrder`.
  357. // Then it merges the 2 sorted lists.
  358. // It guarantee the relative order in the patch list and in the serverOnly list is kept.
  359. // `patch` is a list of items in the patch, and `serverOnly` is a list of items in the live object.
  360. // `patchOrder` is the order we want `patch` list to have and
  361. // `serverOrder` is the order we want `serverOnly` list to have.
  362. // kind is the kind of each item in the lists `patch` and `serverOnly`.
  363. func normalizeElementOrder(patch, serverOnly, patchOrder, serverOrder []interface{}, mergeKey string, kind reflect.Kind) ([]interface{}, error) {
  364. patch, err := normalizeSliceOrder(patch, patchOrder, mergeKey, kind)
  365. if err != nil {
  366. return nil, err
  367. }
  368. serverOnly, err = normalizeSliceOrder(serverOnly, serverOrder, mergeKey, kind)
  369. if err != nil {
  370. return nil, err
  371. }
  372. all := mergeSortedSlice(serverOnly, patch, serverOrder, mergeKey, kind)
  373. return all, nil
  374. }
  375. // mergeSortedSlice merges the 2 sorted lists by serverOrder with best effort.
  376. // It will insert each item in `left` list to `right` list. In most cases, the 2 lists will be interleaved.
  377. // The relative order of left and right are guaranteed to be kept.
  378. // They have higher precedence than the order in the live list.
  379. // The place for a item in `left` is found by:
  380. // scan from the place of last insertion in `right` to the end of `right`,
  381. // the place is before the first item that is greater than the item we want to insert.
  382. // example usage: using server-only items as left and patch items as right. We insert server-only items
  383. // to patch list. We use the order of live object as record for comparison.
  384. func mergeSortedSlice(left, right, serverOrder []interface{}, mergeKey string, kind reflect.Kind) []interface{} {
  385. // Returns if l is less than r, and if both have been found.
  386. // If l and r both present and l is in front of r, l is less than r.
  387. less := func(l, r interface{}) (bool, bool) {
  388. li := index(serverOrder, l, mergeKey, kind)
  389. ri := index(serverOrder, r, mergeKey, kind)
  390. if li >= 0 && ri >= 0 {
  391. return li < ri, true
  392. } else {
  393. return false, false
  394. }
  395. }
  396. // left and right should be non-overlapping.
  397. size := len(left) + len(right)
  398. i, j := 0, 0
  399. s := make([]interface{}, size, size)
  400. for k := 0; k < size; k++ {
  401. if i >= len(left) && j < len(right) {
  402. // have items left in `right` list
  403. s[k] = right[j]
  404. j++
  405. } else if j >= len(right) && i < len(left) {
  406. // have items left in `left` list
  407. s[k] = left[i]
  408. i++
  409. } else {
  410. // compare them if i and j are both in bound
  411. less, foundBoth := less(left[i], right[j])
  412. if foundBoth && less {
  413. s[k] = left[i]
  414. i++
  415. } else {
  416. s[k] = right[j]
  417. j++
  418. }
  419. }
  420. }
  421. return s
  422. }
  423. // index returns the index of the item in the given items, or -1 if it doesn't exist
  424. // l must NOT be a slice of slices, this should be checked before calling.
  425. func index(l []interface{}, valToLookUp interface{}, mergeKey string, kind reflect.Kind) int {
  426. var getValFn func(interface{}) interface{}
  427. // Get the correct `getValFn` based on item `kind`.
  428. // It should return the value of merge key for maps and
  429. // return the item for other kinds.
  430. switch kind {
  431. case reflect.Map:
  432. getValFn = func(item interface{}) interface{} {
  433. typedItem, ok := item.(map[string]interface{})
  434. if !ok {
  435. return nil
  436. }
  437. val := typedItem[mergeKey]
  438. return val
  439. }
  440. default:
  441. getValFn = func(item interface{}) interface{} {
  442. return item
  443. }
  444. }
  445. for i, v := range l {
  446. if getValFn(valToLookUp) == getValFn(v) {
  447. return i
  448. }
  449. }
  450. return -1
  451. }
  452. // extractToDeleteItems takes a list and
  453. // returns 2 lists: one contains items that should be kept and the other contains items to be deleted.
  454. func extractToDeleteItems(l []interface{}) ([]interface{}, []interface{}, error) {
  455. var nonDelete, toDelete []interface{}
  456. for _, v := range l {
  457. m, ok := v.(map[string]interface{})
  458. if !ok {
  459. return nil, nil, mergepatch.ErrBadArgType(m, v)
  460. }
  461. directive, foundDirective := m[directiveMarker]
  462. if foundDirective && directive == deleteDirective {
  463. toDelete = append(toDelete, v)
  464. } else {
  465. nonDelete = append(nonDelete, v)
  466. }
  467. }
  468. return nonDelete, toDelete, nil
  469. }
  470. // normalizeSliceOrder sort `toSort` list by `order`
  471. func normalizeSliceOrder(toSort, order []interface{}, mergeKey string, kind reflect.Kind) ([]interface{}, error) {
  472. var toDelete []interface{}
  473. if kind == reflect.Map {
  474. // make sure each item in toSort, order has merge key
  475. err := validateMergeKeyInLists(mergeKey, toSort, order)
  476. if err != nil {
  477. return nil, err
  478. }
  479. toSort, toDelete, err = extractToDeleteItems(toSort)
  480. if err != nil {
  481. return nil, err
  482. }
  483. }
  484. sort.SliceStable(toSort, func(i, j int) bool {
  485. if ii := index(order, toSort[i], mergeKey, kind); ii >= 0 {
  486. if ij := index(order, toSort[j], mergeKey, kind); ij >= 0 {
  487. return ii < ij
  488. }
  489. }
  490. return true
  491. })
  492. toSort = append(toSort, toDelete...)
  493. return toSort, nil
  494. }
  495. // Returns a (recursive) strategic merge patch, a parallel deletion list if necessary and
  496. // another list to set the order of the list
  497. // Only list of primitives with merge strategy will generate a parallel deletion list.
  498. // These two lists should yield modified when applied to original, for lists with merge semantics.
  499. func diffLists(original, modified []interface{}, schema LookupPatchMeta, mergeKey string, diffOptions DiffOptions) ([]interface{}, []interface{}, []interface{}, error) {
  500. if len(original) == 0 {
  501. // Both slices are empty - do nothing
  502. if len(modified) == 0 || diffOptions.IgnoreChangesAndAdditions {
  503. return nil, nil, nil, nil
  504. }
  505. // Old slice was empty - add all elements from the new slice
  506. return modified, nil, nil, nil
  507. }
  508. elementType, err := sliceElementType(original, modified)
  509. if err != nil {
  510. return nil, nil, nil, err
  511. }
  512. var patchList, deleteList, setOrderList []interface{}
  513. kind := elementType.Kind()
  514. switch kind {
  515. case reflect.Map:
  516. patchList, deleteList, err = diffListsOfMaps(original, modified, schema, mergeKey, diffOptions)
  517. if err != nil {
  518. return nil, nil, nil, err
  519. }
  520. patchList, err = normalizeSliceOrder(patchList, modified, mergeKey, kind)
  521. if err != nil {
  522. return nil, nil, nil, err
  523. }
  524. orderSame, err := isOrderSame(original, modified, mergeKey)
  525. if err != nil {
  526. return nil, nil, nil, err
  527. }
  528. // append the deletions to the end of the patch list.
  529. patchList = append(patchList, deleteList...)
  530. deleteList = nil
  531. // generate the setElementOrder list when there are content changes or order changes
  532. if diffOptions.SetElementOrder &&
  533. ((!diffOptions.IgnoreChangesAndAdditions && (len(patchList) > 0 || !orderSame)) ||
  534. (!diffOptions.IgnoreDeletions && len(patchList) > 0)) {
  535. // Generate a list of maps that each item contains only the merge key.
  536. setOrderList = make([]interface{}, len(modified))
  537. for i, v := range modified {
  538. typedV := v.(map[string]interface{})
  539. setOrderList[i] = map[string]interface{}{
  540. mergeKey: typedV[mergeKey],
  541. }
  542. }
  543. }
  544. case reflect.Slice:
  545. // Lists of Lists are not permitted by the api
  546. return nil, nil, nil, mergepatch.ErrNoListOfLists
  547. default:
  548. patchList, deleteList, err = diffListsOfScalars(original, modified, diffOptions)
  549. if err != nil {
  550. return nil, nil, nil, err
  551. }
  552. patchList, err = normalizeSliceOrder(patchList, modified, mergeKey, kind)
  553. // generate the setElementOrder list when there are content changes or order changes
  554. if diffOptions.SetElementOrder && ((!diffOptions.IgnoreDeletions && len(deleteList) > 0) ||
  555. (!diffOptions.IgnoreChangesAndAdditions && !reflect.DeepEqual(original, modified))) {
  556. setOrderList = modified
  557. }
  558. }
  559. return patchList, deleteList, setOrderList, err
  560. }
  561. // isOrderSame checks if the order in a list has changed
  562. func isOrderSame(original, modified []interface{}, mergeKey string) (bool, error) {
  563. if len(original) != len(modified) {
  564. return false, nil
  565. }
  566. for i, modifiedItem := range modified {
  567. equal, err := mergeKeyValueEqual(original[i], modifiedItem, mergeKey)
  568. if err != nil || !equal {
  569. return equal, err
  570. }
  571. }
  572. return true, nil
  573. }
  574. // diffListsOfScalars returns 2 lists, the first one is addList and the second one is deletionList.
  575. // Argument diffOptions.IgnoreChangesAndAdditions controls if calculate addList. true means not calculate.
  576. // Argument diffOptions.IgnoreDeletions controls if calculate deletionList. true means not calculate.
  577. // original may be changed, but modified is guaranteed to not be changed
  578. func diffListsOfScalars(original, modified []interface{}, diffOptions DiffOptions) ([]interface{}, []interface{}, error) {
  579. modifiedCopy := make([]interface{}, len(modified))
  580. copy(modifiedCopy, modified)
  581. // Sort the scalars for easier calculating the diff
  582. originalScalars := sortScalars(original)
  583. modifiedScalars := sortScalars(modifiedCopy)
  584. originalIndex, modifiedIndex := 0, 0
  585. addList := []interface{}{}
  586. deletionList := []interface{}{}
  587. for {
  588. originalInBounds := originalIndex < len(originalScalars)
  589. modifiedInBounds := modifiedIndex < len(modifiedScalars)
  590. if !originalInBounds && !modifiedInBounds {
  591. break
  592. }
  593. // we need to compare the string representation of the scalar,
  594. // because the scalar is an interface which doesn't support either < or >
  595. // And that's how func sortScalars compare scalars.
  596. var originalString, modifiedString string
  597. var originalValue, modifiedValue interface{}
  598. if originalInBounds {
  599. originalValue = originalScalars[originalIndex]
  600. originalString = fmt.Sprintf("%v", originalValue)
  601. }
  602. if modifiedInBounds {
  603. modifiedValue = modifiedScalars[modifiedIndex]
  604. modifiedString = fmt.Sprintf("%v", modifiedValue)
  605. }
  606. originalV, modifiedV := compareListValuesAtIndex(originalInBounds, modifiedInBounds, originalString, modifiedString)
  607. switch {
  608. case originalV == nil && modifiedV == nil:
  609. originalIndex++
  610. modifiedIndex++
  611. case originalV != nil && modifiedV == nil:
  612. if !diffOptions.IgnoreDeletions {
  613. deletionList = append(deletionList, originalValue)
  614. }
  615. originalIndex++
  616. case originalV == nil && modifiedV != nil:
  617. if !diffOptions.IgnoreChangesAndAdditions {
  618. addList = append(addList, modifiedValue)
  619. }
  620. modifiedIndex++
  621. default:
  622. return nil, nil, fmt.Errorf("Unexpected returned value from compareListValuesAtIndex: %v and %v", originalV, modifiedV)
  623. }
  624. }
  625. return addList, deduplicateScalars(deletionList), nil
  626. }
  627. // If first return value is non-nil, list1 contains an element not present in list2
  628. // If second return value is non-nil, list2 contains an element not present in list1
  629. func compareListValuesAtIndex(list1Inbounds, list2Inbounds bool, list1Value, list2Value string) (interface{}, interface{}) {
  630. bothInBounds := list1Inbounds && list2Inbounds
  631. switch {
  632. // scalars are identical
  633. case bothInBounds && list1Value == list2Value:
  634. return nil, nil
  635. // only list2 is in bound
  636. case !list1Inbounds:
  637. fallthrough
  638. // list2 has additional scalar
  639. case bothInBounds && list1Value > list2Value:
  640. return nil, list2Value
  641. // only original is in bound
  642. case !list2Inbounds:
  643. fallthrough
  644. // original has additional scalar
  645. case bothInBounds && list1Value < list2Value:
  646. return list1Value, nil
  647. default:
  648. return nil, nil
  649. }
  650. }
  651. // diffListsOfMaps takes a pair of lists and
  652. // returns a (recursive) strategic merge patch list contains additions and changes and
  653. // a deletion list contains deletions
  654. func diffListsOfMaps(original, modified []interface{}, schema LookupPatchMeta, mergeKey string, diffOptions DiffOptions) ([]interface{}, []interface{}, error) {
  655. patch := make([]interface{}, 0, len(modified))
  656. deletionList := make([]interface{}, 0, len(original))
  657. originalSorted, err := sortMergeListsByNameArray(original, schema, mergeKey, false)
  658. if err != nil {
  659. return nil, nil, err
  660. }
  661. modifiedSorted, err := sortMergeListsByNameArray(modified, schema, mergeKey, false)
  662. if err != nil {
  663. return nil, nil, err
  664. }
  665. originalIndex, modifiedIndex := 0, 0
  666. for {
  667. originalInBounds := originalIndex < len(originalSorted)
  668. modifiedInBounds := modifiedIndex < len(modifiedSorted)
  669. bothInBounds := originalInBounds && modifiedInBounds
  670. if !originalInBounds && !modifiedInBounds {
  671. break
  672. }
  673. var originalElementMergeKeyValueString, modifiedElementMergeKeyValueString string
  674. var originalElementMergeKeyValue, modifiedElementMergeKeyValue interface{}
  675. var originalElement, modifiedElement map[string]interface{}
  676. if originalInBounds {
  677. originalElement, originalElementMergeKeyValue, err = getMapAndMergeKeyValueByIndex(originalIndex, mergeKey, originalSorted)
  678. if err != nil {
  679. return nil, nil, err
  680. }
  681. originalElementMergeKeyValueString = fmt.Sprintf("%v", originalElementMergeKeyValue)
  682. }
  683. if modifiedInBounds {
  684. modifiedElement, modifiedElementMergeKeyValue, err = getMapAndMergeKeyValueByIndex(modifiedIndex, mergeKey, modifiedSorted)
  685. if err != nil {
  686. return nil, nil, err
  687. }
  688. modifiedElementMergeKeyValueString = fmt.Sprintf("%v", modifiedElementMergeKeyValue)
  689. }
  690. switch {
  691. case bothInBounds && ItemMatchesOriginalAndModifiedSlice(originalElementMergeKeyValueString, modifiedElementMergeKeyValueString):
  692. // Merge key values are equal, so recurse
  693. patchValue, err := diffMaps(originalElement, modifiedElement, schema, diffOptions)
  694. if err != nil {
  695. return nil, nil, err
  696. }
  697. if len(patchValue) > 0 {
  698. patchValue[mergeKey] = modifiedElementMergeKeyValue
  699. patch = append(patch, patchValue)
  700. }
  701. originalIndex++
  702. modifiedIndex++
  703. // only modified is in bound
  704. case !originalInBounds:
  705. fallthrough
  706. // modified has additional map
  707. case bothInBounds && ItemAddedToModifiedSlice(originalElementMergeKeyValueString, modifiedElementMergeKeyValueString):
  708. if !diffOptions.IgnoreChangesAndAdditions {
  709. patch = append(patch, modifiedElement)
  710. }
  711. modifiedIndex++
  712. // only original is in bound
  713. case !modifiedInBounds:
  714. fallthrough
  715. // original has additional map
  716. case bothInBounds && ItemRemovedFromModifiedSlice(originalElementMergeKeyValueString, modifiedElementMergeKeyValueString):
  717. if !diffOptions.IgnoreDeletions {
  718. // Item was deleted, so add delete directive
  719. deletionList = append(deletionList, CreateDeleteDirective(mergeKey, originalElementMergeKeyValue))
  720. }
  721. originalIndex++
  722. }
  723. }
  724. return patch, deletionList, nil
  725. }
  726. // getMapAndMergeKeyValueByIndex return a map in the list and its merge key value given the index of the map.
  727. func getMapAndMergeKeyValueByIndex(index int, mergeKey string, listOfMaps []interface{}) (map[string]interface{}, interface{}, error) {
  728. m, ok := listOfMaps[index].(map[string]interface{})
  729. if !ok {
  730. return nil, nil, mergepatch.ErrBadArgType(m, listOfMaps[index])
  731. }
  732. val, ok := m[mergeKey]
  733. if !ok {
  734. return nil, nil, mergepatch.ErrNoMergeKey(m, mergeKey)
  735. }
  736. return m, val, nil
  737. }
  738. // StrategicMergePatch applies a strategic merge patch. The patch and the original document
  739. // must be json encoded content. A patch can be created from an original and a modified document
  740. // by calling CreateStrategicMergePatch.
  741. func StrategicMergePatch(original, patch []byte, dataStruct interface{}) ([]byte, error) {
  742. schema, err := NewPatchMetaFromStruct(dataStruct)
  743. if err != nil {
  744. return nil, err
  745. }
  746. return StrategicMergePatchUsingLookupPatchMeta(original, patch, schema)
  747. }
  748. func StrategicMergePatchUsingLookupPatchMeta(original, patch []byte, schema LookupPatchMeta) ([]byte, error) {
  749. originalMap, err := handleUnmarshal(original)
  750. if err != nil {
  751. return nil, err
  752. }
  753. patchMap, err := handleUnmarshal(patch)
  754. if err != nil {
  755. return nil, err
  756. }
  757. result, err := StrategicMergeMapPatchUsingLookupPatchMeta(originalMap, patchMap, schema)
  758. if err != nil {
  759. return nil, err
  760. }
  761. return json.Marshal(result)
  762. }
  763. func handleUnmarshal(j []byte) (map[string]interface{}, error) {
  764. if j == nil {
  765. j = []byte("{}")
  766. }
  767. m := map[string]interface{}{}
  768. err := json.Unmarshal(j, &m)
  769. if err != nil {
  770. return nil, mergepatch.ErrBadJSONDoc
  771. }
  772. return m, nil
  773. }
  774. // StrategicMergeMapPatch applies a strategic merge patch. The original and patch documents
  775. // must be JSONMap. A patch can be created from an original and modified document by
  776. // calling CreateTwoWayMergeMapPatch.
  777. // Warning: the original and patch JSONMap objects are mutated by this function and should not be reused.
  778. func StrategicMergeMapPatch(original, patch JSONMap, dataStruct interface{}) (JSONMap, error) {
  779. schema, err := NewPatchMetaFromStruct(dataStruct)
  780. if err != nil {
  781. return nil, err
  782. }
  783. // We need the go struct tags `patchMergeKey` and `patchStrategy` for fields that support a strategic merge patch.
  784. // For native resources, we can easily figure out these tags since we know the fields.
  785. // Because custom resources are decoded as Unstructured and because we're missing the metadata about how to handle
  786. // each field in a strategic merge patch, we can't find the go struct tags. Hence, we can't easily do a strategic merge
  787. // for custom resources. So we should fail fast and return an error.
  788. if _, ok := dataStruct.(*unstructured.Unstructured); ok {
  789. return nil, mergepatch.ErrUnsupportedStrategicMergePatchFormat
  790. }
  791. return StrategicMergeMapPatchUsingLookupPatchMeta(original, patch, schema)
  792. }
  793. func StrategicMergeMapPatchUsingLookupPatchMeta(original, patch JSONMap, schema LookupPatchMeta) (JSONMap, error) {
  794. mergeOptions := MergeOptions{
  795. MergeParallelList: true,
  796. IgnoreUnmatchedNulls: true,
  797. }
  798. return mergeMap(original, patch, schema, mergeOptions)
  799. }
  800. // MergeStrategicMergeMapPatchUsingLookupPatchMeta merges strategic merge
  801. // patches retaining `null` fields and parallel lists. If 2 patches change the
  802. // same fields and the latter one will override the former one. If you don't
  803. // want that happen, you need to run func MergingMapsHaveConflicts before
  804. // merging these patches. Applying the resulting merged merge patch to a JSONMap
  805. // yields the same as merging each strategic merge patch to the JSONMap in
  806. // succession.
  807. func MergeStrategicMergeMapPatchUsingLookupPatchMeta(schema LookupPatchMeta, patches ...JSONMap) (JSONMap, error) {
  808. mergeOptions := MergeOptions{
  809. MergeParallelList: false,
  810. IgnoreUnmatchedNulls: false,
  811. }
  812. merged := JSONMap{}
  813. var err error
  814. for _, patch := range patches {
  815. merged, err = mergeMap(merged, patch, schema, mergeOptions)
  816. if err != nil {
  817. return nil, err
  818. }
  819. }
  820. return merged, nil
  821. }
  822. // handleDirectiveInMergeMap handles the patch directive when merging 2 maps.
  823. func handleDirectiveInMergeMap(directive interface{}, patch map[string]interface{}) (map[string]interface{}, error) {
  824. if directive == replaceDirective {
  825. // If the patch contains "$patch: replace", don't merge it, just use the
  826. // patch directly. Later on, we can add a single level replace that only
  827. // affects the map that the $patch is in.
  828. delete(patch, directiveMarker)
  829. return patch, nil
  830. }
  831. if directive == deleteDirective {
  832. // If the patch contains "$patch: delete", don't merge it, just return
  833. // an empty map.
  834. return map[string]interface{}{}, nil
  835. }
  836. return nil, mergepatch.ErrBadPatchType(directive, patch)
  837. }
  838. func containsDirectiveMarker(item interface{}) bool {
  839. m, ok := item.(map[string]interface{})
  840. if ok {
  841. if _, foundDirectiveMarker := m[directiveMarker]; foundDirectiveMarker {
  842. return true
  843. }
  844. }
  845. return false
  846. }
  847. func mergeKeyValueEqual(left, right interface{}, mergeKey string) (bool, error) {
  848. if len(mergeKey) == 0 {
  849. return left == right, nil
  850. }
  851. typedLeft, ok := left.(map[string]interface{})
  852. if !ok {
  853. return false, mergepatch.ErrBadArgType(typedLeft, left)
  854. }
  855. typedRight, ok := right.(map[string]interface{})
  856. if !ok {
  857. return false, mergepatch.ErrBadArgType(typedRight, right)
  858. }
  859. mergeKeyLeft, ok := typedLeft[mergeKey]
  860. if !ok {
  861. return false, mergepatch.ErrNoMergeKey(typedLeft, mergeKey)
  862. }
  863. mergeKeyRight, ok := typedRight[mergeKey]
  864. if !ok {
  865. return false, mergepatch.ErrNoMergeKey(typedRight, mergeKey)
  866. }
  867. return mergeKeyLeft == mergeKeyRight, nil
  868. }
  869. // extractKey trims the prefix and return the original key
  870. func extractKey(s, prefix string) (string, error) {
  871. substrings := strings.SplitN(s, "/", 2)
  872. if len(substrings) <= 1 || substrings[0] != prefix {
  873. switch prefix {
  874. case deleteFromPrimitiveListDirectivePrefix:
  875. return "", mergepatch.ErrBadPatchFormatForPrimitiveList
  876. case setElementOrderDirectivePrefix:
  877. return "", mergepatch.ErrBadPatchFormatForSetElementOrderList
  878. default:
  879. return "", fmt.Errorf("fail to find unknown prefix %q in %s\n", prefix, s)
  880. }
  881. }
  882. return substrings[1], nil
  883. }
  884. // validatePatchUsingSetOrderList verifies:
  885. // the relative order of any two items in the setOrderList list matches that in the patch list.
  886. // the items in the patch list must be a subset or the same as the $setElementOrder list (deletions are ignored).
  887. func validatePatchWithSetOrderList(patchList, setOrderList interface{}, mergeKey string) error {
  888. typedSetOrderList, ok := setOrderList.([]interface{})
  889. if !ok {
  890. return mergepatch.ErrBadPatchFormatForSetElementOrderList
  891. }
  892. typedPatchList, ok := patchList.([]interface{})
  893. if !ok {
  894. return mergepatch.ErrBadPatchFormatForSetElementOrderList
  895. }
  896. if len(typedSetOrderList) == 0 || len(typedPatchList) == 0 {
  897. return nil
  898. }
  899. var nonDeleteList []interface{}
  900. var err error
  901. if len(mergeKey) > 0 {
  902. nonDeleteList, _, err = extractToDeleteItems(typedPatchList)
  903. if err != nil {
  904. return err
  905. }
  906. } else {
  907. nonDeleteList = typedPatchList
  908. }
  909. patchIndex, setOrderIndex := 0, 0
  910. for patchIndex < len(nonDeleteList) && setOrderIndex < len(typedSetOrderList) {
  911. if containsDirectiveMarker(nonDeleteList[patchIndex]) {
  912. patchIndex++
  913. continue
  914. }
  915. mergeKeyEqual, err := mergeKeyValueEqual(nonDeleteList[patchIndex], typedSetOrderList[setOrderIndex], mergeKey)
  916. if err != nil {
  917. return err
  918. }
  919. if mergeKeyEqual {
  920. patchIndex++
  921. }
  922. setOrderIndex++
  923. }
  924. // If patchIndex is inbound but setOrderIndex if out of bound mean there are items mismatching between the patch list and setElementOrder list.
  925. // the second check is a sanity check, and should always be true if the first is true.
  926. if patchIndex < len(nonDeleteList) && setOrderIndex >= len(typedSetOrderList) {
  927. return fmt.Errorf("The order in patch list:\n%v\n doesn't match %s list:\n%v\n", typedPatchList, setElementOrderDirectivePrefix, setOrderList)
  928. }
  929. return nil
  930. }
  931. // preprocessDeletionListForMerging preprocesses the deletion list.
  932. // it returns shouldContinue, isDeletionList, noPrefixKey
  933. func preprocessDeletionListForMerging(key string, original map[string]interface{},
  934. patchVal interface{}, mergeDeletionList bool) (bool, bool, string, error) {
  935. // If found a parallel list for deletion and we are going to merge the list,
  936. // overwrite the key to the original key and set flag isDeleteList
  937. foundParallelListPrefix := strings.HasPrefix(key, deleteFromPrimitiveListDirectivePrefix)
  938. if foundParallelListPrefix {
  939. if !mergeDeletionList {
  940. original[key] = patchVal
  941. return true, false, "", nil
  942. }
  943. originalKey, err := extractKey(key, deleteFromPrimitiveListDirectivePrefix)
  944. return false, true, originalKey, err
  945. }
  946. return false, false, "", nil
  947. }
  948. // applyRetainKeysDirective looks for a retainKeys directive and applies to original
  949. // - if no directive exists do nothing
  950. // - if directive is found, clear keys in original missing from the directive list
  951. // - validate that all keys present in the patch are present in the retainKeys directive
  952. // note: original may be another patch request, e.g. applying the add+modified patch to the deletions patch. In this case it may have directives
  953. func applyRetainKeysDirective(original, patch map[string]interface{}, options MergeOptions) error {
  954. retainKeysInPatch, foundInPatch := patch[retainKeysDirective]
  955. if !foundInPatch {
  956. return nil
  957. }
  958. // cleanup the directive
  959. delete(patch, retainKeysDirective)
  960. if !options.MergeParallelList {
  961. // If original is actually a patch, make sure the retainKeys directives are the same in both patches if present in both.
  962. // If not present in the original patch, copy from the modified patch.
  963. retainKeysInOriginal, foundInOriginal := original[retainKeysDirective]
  964. if foundInOriginal {
  965. if !reflect.DeepEqual(retainKeysInOriginal, retainKeysInPatch) {
  966. // This error actually should never happen.
  967. return fmt.Errorf("%v and %v are not deep equal: this may happen when calculating the 3-way diff patch", retainKeysInOriginal, retainKeysInPatch)
  968. }
  969. } else {
  970. original[retainKeysDirective] = retainKeysInPatch
  971. }
  972. return nil
  973. }
  974. retainKeysList, ok := retainKeysInPatch.([]interface{})
  975. if !ok {
  976. return mergepatch.ErrBadPatchFormatForRetainKeys
  977. }
  978. // validate patch to make sure all fields in the patch are present in the retainKeysList.
  979. // The map is used only as a set, the value is never referenced
  980. m := map[interface{}]struct{}{}
  981. for _, v := range retainKeysList {
  982. m[v] = struct{}{}
  983. }
  984. for k, v := range patch {
  985. if v == nil || strings.HasPrefix(k, deleteFromPrimitiveListDirectivePrefix) ||
  986. strings.HasPrefix(k, setElementOrderDirectivePrefix) {
  987. continue
  988. }
  989. // If there is an item present in the patch but not in the retainKeys list,
  990. // the patch is invalid.
  991. if _, found := m[k]; !found {
  992. return mergepatch.ErrBadPatchFormatForRetainKeys
  993. }
  994. }
  995. // clear not present fields
  996. for k := range original {
  997. if _, found := m[k]; !found {
  998. delete(original, k)
  999. }
  1000. }
  1001. return nil
  1002. }
  1003. // mergePatchIntoOriginal processes $setElementOrder list.
  1004. // When not merging the directive, it will make sure $setElementOrder list exist only in original.
  1005. // When merging the directive, it will try to find the $setElementOrder list and
  1006. // its corresponding patch list, validate it and merge it.
  1007. // Then, sort them by the relative order in setElementOrder, patch list and live list.
  1008. // The precedence is $setElementOrder > order in patch list > order in live list.
  1009. // This function will delete the item after merging it to prevent process it again in the future.
  1010. // Ref: https://git.k8s.io/design-proposals-archive/cli/preserve-order-in-strategic-merge-patch.md
  1011. func mergePatchIntoOriginal(original, patch map[string]interface{}, schema LookupPatchMeta, mergeOptions MergeOptions) error {
  1012. for key, patchV := range patch {
  1013. // Do nothing if there is no ordering directive
  1014. if !strings.HasPrefix(key, setElementOrderDirectivePrefix) {
  1015. continue
  1016. }
  1017. setElementOrderInPatch := patchV
  1018. // Copies directive from the second patch (`patch`) to the first patch (`original`)
  1019. // and checks they are equal and delete the directive in the second patch
  1020. if !mergeOptions.MergeParallelList {
  1021. setElementOrderListInOriginal, ok := original[key]
  1022. if ok {
  1023. // check if the setElementOrder list in original and the one in patch matches
  1024. if !reflect.DeepEqual(setElementOrderListInOriginal, setElementOrderInPatch) {
  1025. return mergepatch.ErrBadPatchFormatForSetElementOrderList
  1026. }
  1027. } else {
  1028. // move the setElementOrder list from patch to original
  1029. original[key] = setElementOrderInPatch
  1030. }
  1031. }
  1032. delete(patch, key)
  1033. var (
  1034. ok bool
  1035. originalFieldValue, patchFieldValue, merged []interface{}
  1036. patchStrategy string
  1037. patchMeta PatchMeta
  1038. subschema LookupPatchMeta
  1039. )
  1040. typedSetElementOrderList, ok := setElementOrderInPatch.([]interface{})
  1041. if !ok {
  1042. return mergepatch.ErrBadArgType(typedSetElementOrderList, setElementOrderInPatch)
  1043. }
  1044. // Trim the setElementOrderDirectivePrefix to get the key of the list field in original.
  1045. originalKey, err := extractKey(key, setElementOrderDirectivePrefix)
  1046. if err != nil {
  1047. return err
  1048. }
  1049. // try to find the list with `originalKey` in `original` and `modified` and merge them.
  1050. originalList, foundOriginal := original[originalKey]
  1051. patchList, foundPatch := patch[originalKey]
  1052. if foundOriginal {
  1053. originalFieldValue, ok = originalList.([]interface{})
  1054. if !ok {
  1055. return mergepatch.ErrBadArgType(originalFieldValue, originalList)
  1056. }
  1057. }
  1058. if foundPatch {
  1059. patchFieldValue, ok = patchList.([]interface{})
  1060. if !ok {
  1061. return mergepatch.ErrBadArgType(patchFieldValue, patchList)
  1062. }
  1063. }
  1064. subschema, patchMeta, err = schema.LookupPatchMetadataForSlice(originalKey)
  1065. if err != nil {
  1066. return err
  1067. }
  1068. _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
  1069. if err != nil {
  1070. return err
  1071. }
  1072. // Check for consistency between the element order list and the field it applies to
  1073. err = validatePatchWithSetOrderList(patchFieldValue, typedSetElementOrderList, patchMeta.GetPatchMergeKey())
  1074. if err != nil {
  1075. return err
  1076. }
  1077. switch {
  1078. case foundOriginal && !foundPatch:
  1079. // no change to list contents
  1080. merged = originalFieldValue
  1081. case !foundOriginal && foundPatch:
  1082. // list was added
  1083. v, keep := removeDirectives(patchFieldValue)
  1084. if !keep {
  1085. // Shouldn't be possible since patchFieldValue is a slice
  1086. continue
  1087. }
  1088. merged = v.([]interface{})
  1089. case foundOriginal && foundPatch:
  1090. merged, err = mergeSliceHandler(originalList, patchList, subschema,
  1091. patchStrategy, patchMeta.GetPatchMergeKey(), false, mergeOptions)
  1092. if err != nil {
  1093. return err
  1094. }
  1095. case !foundOriginal && !foundPatch:
  1096. continue
  1097. }
  1098. // Split all items into patch items and server-only items and then enforce the order.
  1099. var patchItems, serverOnlyItems []interface{}
  1100. if len(patchMeta.GetPatchMergeKey()) == 0 {
  1101. // Primitives doesn't need merge key to do partitioning.
  1102. patchItems, serverOnlyItems = partitionPrimitivesByPresentInList(merged, typedSetElementOrderList)
  1103. } else {
  1104. // Maps need merge key to do partitioning.
  1105. patchItems, serverOnlyItems, err = partitionMapsByPresentInList(merged, typedSetElementOrderList, patchMeta.GetPatchMergeKey())
  1106. if err != nil {
  1107. return err
  1108. }
  1109. }
  1110. elementType, err := sliceElementType(originalFieldValue, patchFieldValue)
  1111. if err != nil {
  1112. return err
  1113. }
  1114. kind := elementType.Kind()
  1115. // normalize merged list
  1116. // typedSetElementOrderList contains all the relative order in typedPatchList,
  1117. // so don't need to use typedPatchList
  1118. both, err := normalizeElementOrder(patchItems, serverOnlyItems, typedSetElementOrderList, originalFieldValue, patchMeta.GetPatchMergeKey(), kind)
  1119. if err != nil {
  1120. return err
  1121. }
  1122. original[originalKey] = both
  1123. // delete patch list from patch to prevent process again in the future
  1124. delete(patch, originalKey)
  1125. }
  1126. return nil
  1127. }
  1128. // partitionPrimitivesByPresentInList partitions elements into 2 slices, the first containing items present in partitionBy, the other not.
  1129. func partitionPrimitivesByPresentInList(original, partitionBy []interface{}) ([]interface{}, []interface{}) {
  1130. patch := make([]interface{}, 0, len(original))
  1131. serverOnly := make([]interface{}, 0, len(original))
  1132. inPatch := map[interface{}]bool{}
  1133. for _, v := range partitionBy {
  1134. inPatch[v] = true
  1135. }
  1136. for _, v := range original {
  1137. if !inPatch[v] {
  1138. serverOnly = append(serverOnly, v)
  1139. } else {
  1140. patch = append(patch, v)
  1141. }
  1142. }
  1143. return patch, serverOnly
  1144. }
  1145. // partitionMapsByPresentInList partitions elements into 2 slices, the first containing items present in partitionBy, the other not.
  1146. func partitionMapsByPresentInList(original, partitionBy []interface{}, mergeKey string) ([]interface{}, []interface{}, error) {
  1147. patch := make([]interface{}, 0, len(original))
  1148. serverOnly := make([]interface{}, 0, len(original))
  1149. for _, v := range original {
  1150. typedV, ok := v.(map[string]interface{})
  1151. if !ok {
  1152. return nil, nil, mergepatch.ErrBadArgType(typedV, v)
  1153. }
  1154. mergeKeyValue, foundMergeKey := typedV[mergeKey]
  1155. if !foundMergeKey {
  1156. return nil, nil, mergepatch.ErrNoMergeKey(typedV, mergeKey)
  1157. }
  1158. _, _, found, err := findMapInSliceBasedOnKeyValue(partitionBy, mergeKey, mergeKeyValue)
  1159. if err != nil {
  1160. return nil, nil, err
  1161. }
  1162. if !found {
  1163. serverOnly = append(serverOnly, v)
  1164. } else {
  1165. patch = append(patch, v)
  1166. }
  1167. }
  1168. return patch, serverOnly, nil
  1169. }
  1170. // Removes directives from an object and returns value to use instead and whether
  1171. // or not the field/index should even be kept
  1172. // May modify input
  1173. func removeDirectives(obj interface{}) (interface{}, bool) {
  1174. if obj == nil {
  1175. return obj, true
  1176. } else if typedV, ok := obj.(map[string]interface{}); ok {
  1177. if _, hasDirective := typedV[directiveMarker]; hasDirective {
  1178. return nil, false
  1179. }
  1180. for k, v := range typedV {
  1181. var keep bool
  1182. typedV[k], keep = removeDirectives(v)
  1183. if !keep {
  1184. delete(typedV, k)
  1185. }
  1186. }
  1187. return typedV, true
  1188. } else if typedV, ok := obj.([]interface{}); ok {
  1189. var res []interface{}
  1190. if typedV != nil {
  1191. // Make sure res is non-nil if patch is non-nil
  1192. res = []interface{}{}
  1193. }
  1194. for _, v := range typedV {
  1195. if newV, keep := removeDirectives(v); keep {
  1196. res = append(res, newV)
  1197. }
  1198. }
  1199. return res, true
  1200. } else {
  1201. return obj, true
  1202. }
  1203. }
  1204. // Merge fields from a patch map into the original map. Note: This may modify
  1205. // both the original map and the patch because getting a deep copy of a map in
  1206. // golang is highly non-trivial.
  1207. // flag mergeOptions.MergeParallelList controls if using the parallel list to delete or keeping the list.
  1208. // If patch contains any null field (e.g. field_1: null) that is not
  1209. // present in original, then to propagate it to the end result use
  1210. // mergeOptions.IgnoreUnmatchedNulls == false.
  1211. func mergeMap(original, patch map[string]interface{}, schema LookupPatchMeta, mergeOptions MergeOptions) (map[string]interface{}, error) {
  1212. if v, ok := patch[directiveMarker]; ok {
  1213. return handleDirectiveInMergeMap(v, patch)
  1214. }
  1215. // nil is an accepted value for original to simplify logic in other places.
  1216. // If original is nil, replace it with an empty map and then apply the patch.
  1217. if original == nil {
  1218. original = map[string]interface{}{}
  1219. }
  1220. err := applyRetainKeysDirective(original, patch, mergeOptions)
  1221. if err != nil {
  1222. return nil, err
  1223. }
  1224. // Process $setElementOrder list and other lists sharing the same key.
  1225. // When not merging the directive, it will make sure $setElementOrder list exist only in original.
  1226. // When merging the directive, it will process $setElementOrder and its patch list together.
  1227. // This function will delete the merged elements from patch so they will not be reprocessed
  1228. err = mergePatchIntoOriginal(original, patch, schema, mergeOptions)
  1229. if err != nil {
  1230. return nil, err
  1231. }
  1232. // Start merging the patch into the original.
  1233. for k, patchV := range patch {
  1234. skipProcessing, isDeleteList, noPrefixKey, err := preprocessDeletionListForMerging(k, original, patchV, mergeOptions.MergeParallelList)
  1235. if err != nil {
  1236. return nil, err
  1237. }
  1238. if skipProcessing {
  1239. continue
  1240. }
  1241. if len(noPrefixKey) > 0 {
  1242. k = noPrefixKey
  1243. }
  1244. // If the value of this key is null, delete the key if it exists in the
  1245. // original. Otherwise, check if we want to preserve it or skip it.
  1246. // Preserving the null value is useful when we want to send an explicit
  1247. // delete to the API server.
  1248. // In some cases, this may lead to inconsistent behavior with create.
  1249. // ref: https://github.com/kubernetes/kubernetes/issues/123304
  1250. // To avoid breaking compatibility,
  1251. // we made corresponding changes on the client side to ensure that the create and patch behaviors are idempotent.
  1252. if patchV == nil {
  1253. delete(original, k)
  1254. if mergeOptions.IgnoreUnmatchedNulls {
  1255. continue
  1256. }
  1257. }
  1258. _, ok := original[k]
  1259. if !ok {
  1260. if !isDeleteList {
  1261. // If it's not in the original document, just take the patch value.
  1262. if mergeOptions.IgnoreUnmatchedNulls {
  1263. discardNullValuesFromPatch(patchV)
  1264. }
  1265. original[k], ok = removeDirectives(patchV)
  1266. if !ok {
  1267. delete(original, k)
  1268. }
  1269. }
  1270. continue
  1271. }
  1272. originalType := reflect.TypeOf(original[k])
  1273. patchType := reflect.TypeOf(patchV)
  1274. if originalType != patchType {
  1275. if !isDeleteList {
  1276. if mergeOptions.IgnoreUnmatchedNulls {
  1277. discardNullValuesFromPatch(patchV)
  1278. }
  1279. original[k], ok = removeDirectives(patchV)
  1280. if !ok {
  1281. delete(original, k)
  1282. }
  1283. }
  1284. continue
  1285. }
  1286. // If they're both maps or lists, recurse into the value.
  1287. switch originalType.Kind() {
  1288. case reflect.Map:
  1289. subschema, patchMeta, err2 := schema.LookupPatchMetadataForStruct(k)
  1290. if err2 != nil {
  1291. return nil, err2
  1292. }
  1293. _, patchStrategy, err2 := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
  1294. if err2 != nil {
  1295. return nil, err2
  1296. }
  1297. original[k], err = mergeMapHandler(original[k], patchV, subschema, patchStrategy, mergeOptions)
  1298. case reflect.Slice:
  1299. subschema, patchMeta, err2 := schema.LookupPatchMetadataForSlice(k)
  1300. if err2 != nil {
  1301. return nil, err2
  1302. }
  1303. _, patchStrategy, err2 := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
  1304. if err2 != nil {
  1305. return nil, err2
  1306. }
  1307. original[k], err = mergeSliceHandler(original[k], patchV, subschema, patchStrategy, patchMeta.GetPatchMergeKey(), isDeleteList, mergeOptions)
  1308. default:
  1309. original[k], ok = removeDirectives(patchV)
  1310. if !ok {
  1311. // if patchV itself is a directive, then don't keep it
  1312. delete(original, k)
  1313. }
  1314. }
  1315. if err != nil {
  1316. return nil, err
  1317. }
  1318. }
  1319. return original, nil
  1320. }
  1321. // discardNullValuesFromPatch discards all null property values from patch.
  1322. // It traverses all slices and map types.
  1323. func discardNullValuesFromPatch(patchV interface{}) {
  1324. switch patchV := patchV.(type) {
  1325. case map[string]interface{}:
  1326. for k, v := range patchV {
  1327. if v == nil {
  1328. delete(patchV, k)
  1329. } else {
  1330. discardNullValuesFromPatch(v)
  1331. }
  1332. }
  1333. case []interface{}:
  1334. for _, v := range patchV {
  1335. discardNullValuesFromPatch(v)
  1336. }
  1337. }
  1338. }
  1339. // mergeMapHandler handles how to merge `patchV` whose key is `key` with `original` respecting
  1340. // fieldPatchStrategy and mergeOptions.
  1341. func mergeMapHandler(original, patch interface{}, schema LookupPatchMeta,
  1342. fieldPatchStrategy string, mergeOptions MergeOptions) (map[string]interface{}, error) {
  1343. typedOriginal, typedPatch, err := mapTypeAssertion(original, patch)
  1344. if err != nil {
  1345. return nil, err
  1346. }
  1347. if fieldPatchStrategy != replaceDirective {
  1348. return mergeMap(typedOriginal, typedPatch, schema, mergeOptions)
  1349. } else {
  1350. return typedPatch, nil
  1351. }
  1352. }
  1353. // mergeSliceHandler handles how to merge `patchV` whose key is `key` with `original` respecting
  1354. // fieldPatchStrategy, fieldPatchMergeKey, isDeleteList and mergeOptions.
  1355. func mergeSliceHandler(original, patch interface{}, schema LookupPatchMeta,
  1356. fieldPatchStrategy, fieldPatchMergeKey string, isDeleteList bool, mergeOptions MergeOptions) ([]interface{}, error) {
  1357. typedOriginal, typedPatch, err := sliceTypeAssertion(original, patch)
  1358. if err != nil {
  1359. return nil, err
  1360. }
  1361. // Delete lists are handled the same way regardless of what the field's patch strategy is
  1362. if fieldPatchStrategy == mergeDirective || isDeleteList {
  1363. return mergeSlice(typedOriginal, typedPatch, schema, fieldPatchMergeKey, mergeOptions, isDeleteList)
  1364. } else {
  1365. return typedPatch, nil
  1366. }
  1367. }
  1368. // Merge two slices together. Note: This may modify both the original slice and
  1369. // the patch because getting a deep copy of a slice in golang is highly
  1370. // non-trivial.
  1371. func mergeSlice(original, patch []interface{}, schema LookupPatchMeta, mergeKey string, mergeOptions MergeOptions, isDeleteList bool) ([]interface{}, error) {
  1372. if len(original) == 0 && len(patch) == 0 {
  1373. return original, nil
  1374. }
  1375. // All the values must be of the same type, but not a list.
  1376. t, err := sliceElementType(original, patch)
  1377. if err != nil {
  1378. return nil, err
  1379. }
  1380. var merged []interface{}
  1381. kind := t.Kind()
  1382. // If the elements are not maps, merge the slices of scalars.
  1383. if kind != reflect.Map {
  1384. if mergeOptions.MergeParallelList && isDeleteList {
  1385. return deleteFromSlice(original, patch), nil
  1386. }
  1387. // Maybe in the future add a "concat" mode that doesn't
  1388. // deduplicate.
  1389. both := append(original, patch...)
  1390. merged = deduplicateScalars(both)
  1391. } else {
  1392. if mergeKey == "" {
  1393. return nil, fmt.Errorf("cannot merge lists without merge key for %s", schema.Name())
  1394. }
  1395. original, patch, err = mergeSliceWithSpecialElements(original, patch, mergeKey)
  1396. if err != nil {
  1397. return nil, err
  1398. }
  1399. merged, err = mergeSliceWithoutSpecialElements(original, patch, mergeKey, schema, mergeOptions)
  1400. if err != nil {
  1401. return nil, err
  1402. }
  1403. }
  1404. // enforce the order
  1405. var patchItems, serverOnlyItems []interface{}
  1406. if len(mergeKey) == 0 {
  1407. patchItems, serverOnlyItems = partitionPrimitivesByPresentInList(merged, patch)
  1408. } else {
  1409. patchItems, serverOnlyItems, err = partitionMapsByPresentInList(merged, patch, mergeKey)
  1410. if err != nil {
  1411. return nil, err
  1412. }
  1413. }
  1414. return normalizeElementOrder(patchItems, serverOnlyItems, patch, original, mergeKey, kind)
  1415. }
  1416. // mergeSliceWithSpecialElements handles special elements with directiveMarker
  1417. // before merging the slices. It returns a updated `original` and a patch without special elements.
  1418. // original and patch must be slices of maps, they should be checked before calling this function.
  1419. func mergeSliceWithSpecialElements(original, patch []interface{}, mergeKey string) ([]interface{}, []interface{}, error) {
  1420. patchWithoutSpecialElements := []interface{}{}
  1421. replace := false
  1422. for _, v := range patch {
  1423. typedV := v.(map[string]interface{})
  1424. patchType, ok := typedV[directiveMarker]
  1425. if !ok {
  1426. patchWithoutSpecialElements = append(patchWithoutSpecialElements, v)
  1427. } else {
  1428. switch patchType {
  1429. case deleteDirective:
  1430. mergeValue, ok := typedV[mergeKey]
  1431. if ok {
  1432. var err error
  1433. original, err = deleteMatchingEntries(original, mergeKey, mergeValue)
  1434. if err != nil {
  1435. return nil, nil, err
  1436. }
  1437. } else {
  1438. return nil, nil, mergepatch.ErrNoMergeKey(typedV, mergeKey)
  1439. }
  1440. case replaceDirective:
  1441. replace = true
  1442. // Continue iterating through the array to prune any other $patch elements.
  1443. case mergeDirective:
  1444. return nil, nil, fmt.Errorf("merging lists cannot yet be specified in the patch")
  1445. default:
  1446. return nil, nil, mergepatch.ErrBadPatchType(patchType, typedV)
  1447. }
  1448. }
  1449. }
  1450. if replace {
  1451. return patchWithoutSpecialElements, nil, nil
  1452. }
  1453. return original, patchWithoutSpecialElements, nil
  1454. }
  1455. // delete all matching entries (based on merge key) from a merging list
  1456. func deleteMatchingEntries(original []interface{}, mergeKey string, mergeValue interface{}) ([]interface{}, error) {
  1457. for {
  1458. _, originalKey, found, err := findMapInSliceBasedOnKeyValue(original, mergeKey, mergeValue)
  1459. if err != nil {
  1460. return nil, err
  1461. }
  1462. if !found {
  1463. break
  1464. }
  1465. // Delete the element at originalKey.
  1466. original = append(original[:originalKey], original[originalKey+1:]...)
  1467. }
  1468. return original, nil
  1469. }
  1470. // mergeSliceWithoutSpecialElements merges slices with non-special elements.
  1471. // original and patch must be slices of maps, they should be checked before calling this function.
  1472. func mergeSliceWithoutSpecialElements(original, patch []interface{}, mergeKey string, schema LookupPatchMeta, mergeOptions MergeOptions) ([]interface{}, error) {
  1473. for _, v := range patch {
  1474. typedV := v.(map[string]interface{})
  1475. mergeValue, ok := typedV[mergeKey]
  1476. if !ok {
  1477. return nil, mergepatch.ErrNoMergeKey(typedV, mergeKey)
  1478. }
  1479. // If we find a value with this merge key value in original, merge the
  1480. // maps. Otherwise append onto original.
  1481. originalMap, originalKey, found, err := findMapInSliceBasedOnKeyValue(original, mergeKey, mergeValue)
  1482. if err != nil {
  1483. return nil, err
  1484. }
  1485. if found {
  1486. var mergedMaps interface{}
  1487. var err error
  1488. // Merge into original.
  1489. mergedMaps, err = mergeMap(originalMap, typedV, schema, mergeOptions)
  1490. if err != nil {
  1491. return nil, err
  1492. }
  1493. original[originalKey] = mergedMaps
  1494. } else {
  1495. original = append(original, v)
  1496. }
  1497. }
  1498. return original, nil
  1499. }
  1500. // deleteFromSlice uses the parallel list to delete the items in a list of scalars
  1501. func deleteFromSlice(current, toDelete []interface{}) []interface{} {
  1502. toDeleteMap := map[interface{}]interface{}{}
  1503. processed := make([]interface{}, 0, len(current))
  1504. for _, v := range toDelete {
  1505. toDeleteMap[v] = true
  1506. }
  1507. for _, v := range current {
  1508. if _, found := toDeleteMap[v]; !found {
  1509. processed = append(processed, v)
  1510. }
  1511. }
  1512. return processed
  1513. }
  1514. // This method no longer panics if any element of the slice is not a map.
  1515. func findMapInSliceBasedOnKeyValue(m []interface{}, key string, value interface{}) (map[string]interface{}, int, bool, error) {
  1516. for k, v := range m {
  1517. typedV, ok := v.(map[string]interface{})
  1518. if !ok {
  1519. return nil, 0, false, fmt.Errorf("value for key %v is not a map", k)
  1520. }
  1521. valueToMatch, ok := typedV[key]
  1522. if ok && valueToMatch == value {
  1523. return typedV, k, true, nil
  1524. }
  1525. }
  1526. return nil, 0, false, nil
  1527. }
  1528. // This function takes a JSON map and sorts all the lists that should be merged
  1529. // by key. This is needed by tests because in JSON, list order is significant,
  1530. // but in Strategic Merge Patch, merge lists do not have significant order.
  1531. // Sorting the lists allows for order-insensitive comparison of patched maps.
  1532. func sortMergeListsByName(mapJSON []byte, schema LookupPatchMeta) ([]byte, error) {
  1533. var m map[string]interface{}
  1534. err := json.Unmarshal(mapJSON, &m)
  1535. if err != nil {
  1536. return nil, mergepatch.ErrBadJSONDoc
  1537. }
  1538. newM, err := sortMergeListsByNameMap(m, schema)
  1539. if err != nil {
  1540. return nil, err
  1541. }
  1542. return json.Marshal(newM)
  1543. }
  1544. // Function sortMergeListsByNameMap recursively sorts the merge lists by its mergeKey in a map.
  1545. func sortMergeListsByNameMap(s map[string]interface{}, schema LookupPatchMeta) (map[string]interface{}, error) {
  1546. newS := map[string]interface{}{}
  1547. for k, v := range s {
  1548. if k == retainKeysDirective {
  1549. typedV, ok := v.([]interface{})
  1550. if !ok {
  1551. return nil, mergepatch.ErrBadPatchFormatForRetainKeys
  1552. }
  1553. v = sortScalars(typedV)
  1554. } else if strings.HasPrefix(k, deleteFromPrimitiveListDirectivePrefix) {
  1555. typedV, ok := v.([]interface{})
  1556. if !ok {
  1557. return nil, mergepatch.ErrBadPatchFormatForPrimitiveList
  1558. }
  1559. v = sortScalars(typedV)
  1560. } else if strings.HasPrefix(k, setElementOrderDirectivePrefix) {
  1561. _, ok := v.([]interface{})
  1562. if !ok {
  1563. return nil, mergepatch.ErrBadPatchFormatForSetElementOrderList
  1564. }
  1565. } else if k != directiveMarker {
  1566. // recurse for map and slice.
  1567. switch typedV := v.(type) {
  1568. case map[string]interface{}:
  1569. subschema, _, err := schema.LookupPatchMetadataForStruct(k)
  1570. if err != nil {
  1571. return nil, err
  1572. }
  1573. v, err = sortMergeListsByNameMap(typedV, subschema)
  1574. if err != nil {
  1575. return nil, err
  1576. }
  1577. case []interface{}:
  1578. subschema, patchMeta, err := schema.LookupPatchMetadataForSlice(k)
  1579. if err != nil {
  1580. return nil, err
  1581. }
  1582. _, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
  1583. if err != nil {
  1584. return nil, err
  1585. }
  1586. if patchStrategy == mergeDirective {
  1587. var err error
  1588. v, err = sortMergeListsByNameArray(typedV, subschema, patchMeta.GetPatchMergeKey(), true)
  1589. if err != nil {
  1590. return nil, err
  1591. }
  1592. }
  1593. }
  1594. }
  1595. newS[k] = v
  1596. }
  1597. return newS, nil
  1598. }
  1599. // Function sortMergeListsByNameMap recursively sorts the merge lists by its mergeKey in an array.
  1600. func sortMergeListsByNameArray(s []interface{}, schema LookupPatchMeta, mergeKey string, recurse bool) ([]interface{}, error) {
  1601. if len(s) == 0 {
  1602. return s, nil
  1603. }
  1604. // We don't support lists of lists yet.
  1605. t, err := sliceElementType(s)
  1606. if err != nil {
  1607. return nil, err
  1608. }
  1609. // If the elements are not maps...
  1610. if t.Kind() != reflect.Map {
  1611. // Sort the elements, because they may have been merged out of order.
  1612. return deduplicateAndSortScalars(s), nil
  1613. }
  1614. // Elements are maps - if one of the keys of the map is a map or a
  1615. // list, we may need to recurse into it.
  1616. newS := []interface{}{}
  1617. for _, elem := range s {
  1618. if recurse {
  1619. typedElem := elem.(map[string]interface{})
  1620. newElem, err := sortMergeListsByNameMap(typedElem, schema)
  1621. if err != nil {
  1622. return nil, err
  1623. }
  1624. newS = append(newS, newElem)
  1625. } else {
  1626. newS = append(newS, elem)
  1627. }
  1628. }
  1629. // Sort the maps.
  1630. newS = sortMapsBasedOnField(newS, mergeKey)
  1631. return newS, nil
  1632. }
  1633. func sortMapsBasedOnField(m []interface{}, fieldName string) []interface{} {
  1634. mapM := mapSliceFromSlice(m)
  1635. ss := SortableSliceOfMaps{mapM, fieldName}
  1636. sort.Sort(ss)
  1637. newS := sliceFromMapSlice(ss.s)
  1638. return newS
  1639. }
  1640. func mapSliceFromSlice(m []interface{}) []map[string]interface{} {
  1641. newM := []map[string]interface{}{}
  1642. for _, v := range m {
  1643. vt := v.(map[string]interface{})
  1644. newM = append(newM, vt)
  1645. }
  1646. return newM
  1647. }
  1648. func sliceFromMapSlice(s []map[string]interface{}) []interface{} {
  1649. newS := []interface{}{}
  1650. for _, v := range s {
  1651. newS = append(newS, v)
  1652. }
  1653. return newS
  1654. }
  1655. type SortableSliceOfMaps struct {
  1656. s []map[string]interface{}
  1657. k string // key to sort on
  1658. }
  1659. func (ss SortableSliceOfMaps) Len() int {
  1660. return len(ss.s)
  1661. }
  1662. func (ss SortableSliceOfMaps) Less(i, j int) bool {
  1663. iStr := fmt.Sprintf("%v", ss.s[i][ss.k])
  1664. jStr := fmt.Sprintf("%v", ss.s[j][ss.k])
  1665. return sort.StringsAreSorted([]string{iStr, jStr})
  1666. }
  1667. func (ss SortableSliceOfMaps) Swap(i, j int) {
  1668. tmp := ss.s[i]
  1669. ss.s[i] = ss.s[j]
  1670. ss.s[j] = tmp
  1671. }
  1672. func deduplicateAndSortScalars(s []interface{}) []interface{} {
  1673. s = deduplicateScalars(s)
  1674. return sortScalars(s)
  1675. }
  1676. func sortScalars(s []interface{}) []interface{} {
  1677. ss := SortableSliceOfScalars{s}
  1678. sort.Sort(ss)
  1679. return ss.s
  1680. }
  1681. func deduplicateScalars(s []interface{}) []interface{} {
  1682. // Clever algorithm to deduplicate.
  1683. length := len(s) - 1
  1684. for i := 0; i < length; i++ {
  1685. for j := i + 1; j <= length; j++ {
  1686. if s[i] == s[j] {
  1687. s[j] = s[length]
  1688. s = s[0:length]
  1689. length--
  1690. j--
  1691. }
  1692. }
  1693. }
  1694. return s
  1695. }
  1696. type SortableSliceOfScalars struct {
  1697. s []interface{}
  1698. }
  1699. func (ss SortableSliceOfScalars) Len() int {
  1700. return len(ss.s)
  1701. }
  1702. func (ss SortableSliceOfScalars) Less(i, j int) bool {
  1703. iStr := fmt.Sprintf("%v", ss.s[i])
  1704. jStr := fmt.Sprintf("%v", ss.s[j])
  1705. return sort.StringsAreSorted([]string{iStr, jStr})
  1706. }
  1707. func (ss SortableSliceOfScalars) Swap(i, j int) {
  1708. tmp := ss.s[i]
  1709. ss.s[i] = ss.s[j]
  1710. ss.s[j] = tmp
  1711. }
  1712. // Returns the type of the elements of N slice(s). If the type is different,
  1713. // another slice or undefined, returns an error.
  1714. func sliceElementType(slices ...[]interface{}) (reflect.Type, error) {
  1715. var prevType reflect.Type
  1716. for _, s := range slices {
  1717. // Go through elements of all given slices and make sure they are all the same type.
  1718. for _, v := range s {
  1719. currentType := reflect.TypeOf(v)
  1720. if prevType == nil {
  1721. prevType = currentType
  1722. // We don't support lists of lists yet.
  1723. if prevType.Kind() == reflect.Slice {
  1724. return nil, mergepatch.ErrNoListOfLists
  1725. }
  1726. } else {
  1727. if prevType != currentType {
  1728. return nil, fmt.Errorf("list element types are not identical: %v", fmt.Sprint(slices))
  1729. }
  1730. prevType = currentType
  1731. }
  1732. }
  1733. }
  1734. if prevType == nil {
  1735. return nil, fmt.Errorf("no elements in any of the given slices")
  1736. }
  1737. return prevType, nil
  1738. }
  1739. // MergingMapsHaveConflicts returns true if the left and right JSON interface
  1740. // objects overlap with different values in any key. All keys are required to be
  1741. // strings. Since patches of the same Type have congruent keys, this is valid
  1742. // for multiple patch types. This method supports strategic merge patch semantics.
  1743. func MergingMapsHaveConflicts(left, right map[string]interface{}, schema LookupPatchMeta) (bool, error) {
  1744. return mergingMapFieldsHaveConflicts(left, right, schema, "", "")
  1745. }
  1746. func mergingMapFieldsHaveConflicts(
  1747. left, right interface{},
  1748. schema LookupPatchMeta,
  1749. fieldPatchStrategy, fieldPatchMergeKey string,
  1750. ) (bool, error) {
  1751. switch leftType := left.(type) {
  1752. case map[string]interface{}:
  1753. rightType, ok := right.(map[string]interface{})
  1754. if !ok {
  1755. return true, nil
  1756. }
  1757. leftMarker, okLeft := leftType[directiveMarker]
  1758. rightMarker, okRight := rightType[directiveMarker]
  1759. // if one or the other has a directive marker,
  1760. // then we need to consider that before looking at the individual keys,
  1761. // since a directive operates on the whole map.
  1762. if okLeft || okRight {
  1763. // if one has a directive marker and the other doesn't,
  1764. // then we have a conflict, since one is deleting or replacing the whole map,
  1765. // and the other is doing things to individual keys.
  1766. if okLeft != okRight {
  1767. return true, nil
  1768. }
  1769. // if they both have markers, but they are not the same directive,
  1770. // then we have a conflict because they're doing different things to the map.
  1771. if leftMarker != rightMarker {
  1772. return true, nil
  1773. }
  1774. }
  1775. if fieldPatchStrategy == replaceDirective {
  1776. return false, nil
  1777. }
  1778. // Check the individual keys.
  1779. return mapsHaveConflicts(leftType, rightType, schema)
  1780. case []interface{}:
  1781. rightType, ok := right.([]interface{})
  1782. if !ok {
  1783. return true, nil
  1784. }
  1785. return slicesHaveConflicts(leftType, rightType, schema, fieldPatchStrategy, fieldPatchMergeKey)
  1786. case string, float64, bool, int64, nil:
  1787. return !reflect.DeepEqual(left, right), nil
  1788. default:
  1789. return true, fmt.Errorf("unknown type: %v", reflect.TypeOf(left))
  1790. }
  1791. }
  1792. func mapsHaveConflicts(typedLeft, typedRight map[string]interface{}, schema LookupPatchMeta) (bool, error) {
  1793. for key, leftValue := range typedLeft {
  1794. if key != directiveMarker && key != retainKeysDirective {
  1795. if rightValue, ok := typedRight[key]; ok {
  1796. var subschema LookupPatchMeta
  1797. var patchMeta PatchMeta
  1798. var patchStrategy string
  1799. var err error
  1800. switch leftValue.(type) {
  1801. case []interface{}:
  1802. subschema, patchMeta, err = schema.LookupPatchMetadataForSlice(key)
  1803. if err != nil {
  1804. return true, err
  1805. }
  1806. _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.patchStrategies)
  1807. if err != nil {
  1808. return true, err
  1809. }
  1810. case map[string]interface{}:
  1811. subschema, patchMeta, err = schema.LookupPatchMetadataForStruct(key)
  1812. if err != nil {
  1813. return true, err
  1814. }
  1815. _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.patchStrategies)
  1816. if err != nil {
  1817. return true, err
  1818. }
  1819. }
  1820. if hasConflicts, err := mergingMapFieldsHaveConflicts(leftValue, rightValue,
  1821. subschema, patchStrategy, patchMeta.GetPatchMergeKey()); hasConflicts {
  1822. return true, err
  1823. }
  1824. }
  1825. }
  1826. }
  1827. return false, nil
  1828. }
  1829. func slicesHaveConflicts(
  1830. typedLeft, typedRight []interface{},
  1831. schema LookupPatchMeta,
  1832. fieldPatchStrategy, fieldPatchMergeKey string,
  1833. ) (bool, error) {
  1834. elementType, err := sliceElementType(typedLeft, typedRight)
  1835. if err != nil {
  1836. return true, err
  1837. }
  1838. if fieldPatchStrategy == mergeDirective {
  1839. // Merging lists of scalars have no conflicts by definition
  1840. // So we only need to check further if the elements are maps
  1841. if elementType.Kind() != reflect.Map {
  1842. return false, nil
  1843. }
  1844. // Build a map for each slice and then compare the two maps
  1845. leftMap, err := sliceOfMapsToMapOfMaps(typedLeft, fieldPatchMergeKey)
  1846. if err != nil {
  1847. return true, err
  1848. }
  1849. rightMap, err := sliceOfMapsToMapOfMaps(typedRight, fieldPatchMergeKey)
  1850. if err != nil {
  1851. return true, err
  1852. }
  1853. return mapsOfMapsHaveConflicts(leftMap, rightMap, schema)
  1854. }
  1855. // Either we don't have type information, or these are non-merging lists
  1856. if len(typedLeft) != len(typedRight) {
  1857. return true, nil
  1858. }
  1859. // Sort scalar slices to prevent ordering issues
  1860. // We have no way to sort non-merging lists of maps
  1861. if elementType.Kind() != reflect.Map {
  1862. typedLeft = deduplicateAndSortScalars(typedLeft)
  1863. typedRight = deduplicateAndSortScalars(typedRight)
  1864. }
  1865. // Compare the slices element by element in order
  1866. // This test will fail if the slices are not sorted
  1867. for i := range typedLeft {
  1868. if hasConflicts, err := mergingMapFieldsHaveConflicts(typedLeft[i], typedRight[i], schema, "", ""); hasConflicts {
  1869. return true, err
  1870. }
  1871. }
  1872. return false, nil
  1873. }
  1874. func sliceOfMapsToMapOfMaps(slice []interface{}, mergeKey string) (map[string]interface{}, error) {
  1875. result := make(map[string]interface{}, len(slice))
  1876. for _, value := range slice {
  1877. typedValue, ok := value.(map[string]interface{})
  1878. if !ok {
  1879. return nil, fmt.Errorf("invalid element type in merging list:%v", slice)
  1880. }
  1881. mergeValue, ok := typedValue[mergeKey]
  1882. if !ok {
  1883. return nil, fmt.Errorf("cannot find merge key `%s` in merging list element:%v", mergeKey, typedValue)
  1884. }
  1885. result[fmt.Sprintf("%s", mergeValue)] = typedValue
  1886. }
  1887. return result, nil
  1888. }
  1889. func mapsOfMapsHaveConflicts(typedLeft, typedRight map[string]interface{}, schema LookupPatchMeta) (bool, error) {
  1890. for key, leftValue := range typedLeft {
  1891. if rightValue, ok := typedRight[key]; ok {
  1892. if hasConflicts, err := mergingMapFieldsHaveConflicts(leftValue, rightValue, schema, "", ""); hasConflicts {
  1893. return true, err
  1894. }
  1895. }
  1896. }
  1897. return false, nil
  1898. }
  1899. // CreateThreeWayMergePatch reconciles a modified configuration with an original configuration,
  1900. // while preserving any changes or deletions made to the original configuration in the interim,
  1901. // and not overridden by the current configuration. All three documents must be passed to the
  1902. // method as json encoded content. It will return a strategic merge patch, or an error if any
  1903. // of the documents is invalid, or if there are any preconditions that fail against the modified
  1904. // configuration, or, if overwrite is false and there are conflicts between the modified and current
  1905. // configurations. Conflicts are defined as keys changed differently from original to modified
  1906. // than from original to current. In other words, a conflict occurs if modified changes any key
  1907. // in a way that is different from how it is changed in current (e.g., deleting it, changing its
  1908. // value). We also propagate values fields that do not exist in original but are explicitly
  1909. // defined in modified.
  1910. func CreateThreeWayMergePatch(original, modified, current []byte, schema LookupPatchMeta, overwrite bool, fns ...mergepatch.PreconditionFunc) ([]byte, error) {
  1911. originalMap := map[string]interface{}{}
  1912. if len(original) > 0 {
  1913. if err := json.Unmarshal(original, &originalMap); err != nil {
  1914. return nil, mergepatch.ErrBadJSONDoc
  1915. }
  1916. }
  1917. modifiedMap := map[string]interface{}{}
  1918. if len(modified) > 0 {
  1919. if err := json.Unmarshal(modified, &modifiedMap); err != nil {
  1920. return nil, mergepatch.ErrBadJSONDoc
  1921. }
  1922. }
  1923. currentMap := map[string]interface{}{}
  1924. if len(current) > 0 {
  1925. if err := json.Unmarshal(current, &currentMap); err != nil {
  1926. return nil, mergepatch.ErrBadJSONDoc
  1927. }
  1928. }
  1929. // The patch is the difference from current to modified without deletions, plus deletions
  1930. // from original to modified. To find it, we compute deletions, which are the deletions from
  1931. // original to modified, and delta, which is the difference from current to modified without
  1932. // deletions, and then apply delta to deletions as a patch, which should be strictly additive.
  1933. deltaMapDiffOptions := DiffOptions{
  1934. IgnoreDeletions: true,
  1935. SetElementOrder: true,
  1936. }
  1937. deltaMap, err := diffMaps(currentMap, modifiedMap, schema, deltaMapDiffOptions)
  1938. if err != nil {
  1939. return nil, err
  1940. }
  1941. deletionsMapDiffOptions := DiffOptions{
  1942. SetElementOrder: true,
  1943. IgnoreChangesAndAdditions: true,
  1944. }
  1945. deletionsMap, err := diffMaps(originalMap, modifiedMap, schema, deletionsMapDiffOptions)
  1946. if err != nil {
  1947. return nil, err
  1948. }
  1949. mergeOptions := MergeOptions{}
  1950. patchMap, err := mergeMap(deletionsMap, deltaMap, schema, mergeOptions)
  1951. if err != nil {
  1952. return nil, err
  1953. }
  1954. // Apply the preconditions to the patch, and return an error if any of them fail.
  1955. for _, fn := range fns {
  1956. if !fn(patchMap) {
  1957. return nil, mergepatch.NewErrPreconditionFailed(patchMap)
  1958. }
  1959. }
  1960. // If overwrite is false, and the patch contains any keys that were changed differently,
  1961. // then return a conflict error.
  1962. if !overwrite {
  1963. changeMapDiffOptions := DiffOptions{}
  1964. changedMap, err := diffMaps(originalMap, currentMap, schema, changeMapDiffOptions)
  1965. if err != nil {
  1966. return nil, err
  1967. }
  1968. hasConflicts, err := MergingMapsHaveConflicts(patchMap, changedMap, schema)
  1969. if err != nil {
  1970. return nil, err
  1971. }
  1972. if hasConflicts {
  1973. return nil, mergepatch.NewErrConflict(mergepatch.ToYAMLOrError(patchMap), mergepatch.ToYAMLOrError(changedMap))
  1974. }
  1975. }
  1976. return json.Marshal(patchMap)
  1977. }
  1978. func ItemAddedToModifiedSlice(original, modified string) bool { return original > modified }
  1979. func ItemRemovedFromModifiedSlice(original, modified string) bool { return original < modified }
  1980. func ItemMatchesOriginalAndModifiedSlice(original, modified string) bool { return original == modified }
  1981. func CreateDeleteDirective(mergeKey string, mergeKeyValue interface{}) map[string]interface{} {
  1982. return map[string]interface{}{mergeKey: mergeKeyValue, directiveMarker: deleteDirective}
  1983. }
  1984. func mapTypeAssertion(original, patch interface{}) (map[string]interface{}, map[string]interface{}, error) {
  1985. typedOriginal, ok := original.(map[string]interface{})
  1986. if !ok {
  1987. return nil, nil, mergepatch.ErrBadArgType(typedOriginal, original)
  1988. }
  1989. typedPatch, ok := patch.(map[string]interface{})
  1990. if !ok {
  1991. return nil, nil, mergepatch.ErrBadArgType(typedPatch, patch)
  1992. }
  1993. return typedOriginal, typedPatch, nil
  1994. }
  1995. func sliceTypeAssertion(original, patch interface{}) ([]interface{}, []interface{}, error) {
  1996. typedOriginal, ok := original.([]interface{})
  1997. if !ok {
  1998. return nil, nil, mergepatch.ErrBadArgType(typedOriginal, original)
  1999. }
  2000. typedPatch, ok := patch.([]interface{})
  2001. if !ok {
  2002. return nil, nil, mergepatch.ErrBadArgType(typedPatch, patch)
  2003. }
  2004. return typedOriginal, typedPatch, nil
  2005. }
  2006. // extractRetainKeysPatchStrategy process patch strategy, which is a string may contains multiple
  2007. // patch strategies separated by ",". It returns a boolean var indicating if it has
  2008. // retainKeys strategies and a string for the other strategy.
  2009. func extractRetainKeysPatchStrategy(strategies []string) (bool, string, error) {
  2010. switch len(strategies) {
  2011. case 0:
  2012. return false, "", nil
  2013. case 1:
  2014. singleStrategy := strategies[0]
  2015. switch singleStrategy {
  2016. case retainKeysStrategy:
  2017. return true, "", nil
  2018. default:
  2019. return false, singleStrategy, nil
  2020. }
  2021. case 2:
  2022. switch {
  2023. case strategies[0] == retainKeysStrategy:
  2024. return true, strategies[1], nil
  2025. case strategies[1] == retainKeysStrategy:
  2026. return true, strategies[0], nil
  2027. default:
  2028. return false, "", fmt.Errorf("unexpected patch strategy: %v", strategies)
  2029. }
  2030. default:
  2031. return false, "", fmt.Errorf("unexpected patch strategy: %v", strategies)
  2032. }
  2033. }
  2034. // hasAdditionalNewField returns if original map has additional key with non-nil value than modified.
  2035. func hasAdditionalNewField(original, modified map[string]interface{}) bool {
  2036. for k, v := range original {
  2037. if v == nil {
  2038. continue
  2039. }
  2040. if _, found := modified[k]; !found {
  2041. return true
  2042. }
  2043. }
  2044. return false
  2045. }