patch.go 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172
  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, toDeleteList []interface{}
  900. var err error
  901. if len(mergeKey) > 0 {
  902. nonDeleteList, toDeleteList, 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. typedPatchList = append(nonDeleteList, toDeleteList...)
  930. return nil
  931. }
  932. // preprocessDeletionListForMerging preprocesses the deletion list.
  933. // it returns shouldContinue, isDeletionList, noPrefixKey
  934. func preprocessDeletionListForMerging(key string, original map[string]interface{},
  935. patchVal interface{}, mergeDeletionList bool) (bool, bool, string, error) {
  936. // If found a parallel list for deletion and we are going to merge the list,
  937. // overwrite the key to the original key and set flag isDeleteList
  938. foundParallelListPrefix := strings.HasPrefix(key, deleteFromPrimitiveListDirectivePrefix)
  939. if foundParallelListPrefix {
  940. if !mergeDeletionList {
  941. original[key] = patchVal
  942. return true, false, "", nil
  943. }
  944. originalKey, err := extractKey(key, deleteFromPrimitiveListDirectivePrefix)
  945. return false, true, originalKey, err
  946. }
  947. return false, false, "", nil
  948. }
  949. // applyRetainKeysDirective looks for a retainKeys directive and applies to original
  950. // - if no directive exists do nothing
  951. // - if directive is found, clear keys in original missing from the directive list
  952. // - validate that all keys present in the patch are present in the retainKeys directive
  953. // 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
  954. func applyRetainKeysDirective(original, patch map[string]interface{}, options MergeOptions) error {
  955. retainKeysInPatch, foundInPatch := patch[retainKeysDirective]
  956. if !foundInPatch {
  957. return nil
  958. }
  959. // cleanup the directive
  960. delete(patch, retainKeysDirective)
  961. if !options.MergeParallelList {
  962. // If original is actually a patch, make sure the retainKeys directives are the same in both patches if present in both.
  963. // If not present in the original patch, copy from the modified patch.
  964. retainKeysInOriginal, foundInOriginal := original[retainKeysDirective]
  965. if foundInOriginal {
  966. if !reflect.DeepEqual(retainKeysInOriginal, retainKeysInPatch) {
  967. // This error actually should never happen.
  968. return fmt.Errorf("%v and %v are not deep equal: this may happen when calculating the 3-way diff patch", retainKeysInOriginal, retainKeysInPatch)
  969. }
  970. } else {
  971. original[retainKeysDirective] = retainKeysInPatch
  972. }
  973. return nil
  974. }
  975. retainKeysList, ok := retainKeysInPatch.([]interface{})
  976. if !ok {
  977. return mergepatch.ErrBadPatchFormatForRetainKeys
  978. }
  979. // validate patch to make sure all fields in the patch are present in the retainKeysList.
  980. // The map is used only as a set, the value is never referenced
  981. m := map[interface{}]struct{}{}
  982. for _, v := range retainKeysList {
  983. m[v] = struct{}{}
  984. }
  985. for k, v := range patch {
  986. if v == nil || strings.HasPrefix(k, deleteFromPrimitiveListDirectivePrefix) ||
  987. strings.HasPrefix(k, setElementOrderDirectivePrefix) {
  988. continue
  989. }
  990. // If there is an item present in the patch but not in the retainKeys list,
  991. // the patch is invalid.
  992. if _, found := m[k]; !found {
  993. return mergepatch.ErrBadPatchFormatForRetainKeys
  994. }
  995. }
  996. // clear not present fields
  997. for k := range original {
  998. if _, found := m[k]; !found {
  999. delete(original, k)
  1000. }
  1001. }
  1002. return nil
  1003. }
  1004. // mergePatchIntoOriginal processes $setElementOrder list.
  1005. // When not merging the directive, it will make sure $setElementOrder list exist only in original.
  1006. // When merging the directive, it will try to find the $setElementOrder list and
  1007. // its corresponding patch list, validate it and merge it.
  1008. // Then, sort them by the relative order in setElementOrder, patch list and live list.
  1009. // The precedence is $setElementOrder > order in patch list > order in live list.
  1010. // This function will delete the item after merging it to prevent process it again in the future.
  1011. // Ref: https://git.k8s.io/community/contributors/design-proposals/cli/preserve-order-in-strategic-merge-patch.md
  1012. func mergePatchIntoOriginal(original, patch map[string]interface{}, schema LookupPatchMeta, mergeOptions MergeOptions) error {
  1013. for key, patchV := range patch {
  1014. // Do nothing if there is no ordering directive
  1015. if !strings.HasPrefix(key, setElementOrderDirectivePrefix) {
  1016. continue
  1017. }
  1018. setElementOrderInPatch := patchV
  1019. // Copies directive from the second patch (`patch`) to the first patch (`original`)
  1020. // and checks they are equal and delete the directive in the second patch
  1021. if !mergeOptions.MergeParallelList {
  1022. setElementOrderListInOriginal, ok := original[key]
  1023. if ok {
  1024. // check if the setElementOrder list in original and the one in patch matches
  1025. if !reflect.DeepEqual(setElementOrderListInOriginal, setElementOrderInPatch) {
  1026. return mergepatch.ErrBadPatchFormatForSetElementOrderList
  1027. }
  1028. } else {
  1029. // move the setElementOrder list from patch to original
  1030. original[key] = setElementOrderInPatch
  1031. }
  1032. }
  1033. delete(patch, key)
  1034. var (
  1035. ok bool
  1036. originalFieldValue, patchFieldValue, merged []interface{}
  1037. patchStrategy string
  1038. patchMeta PatchMeta
  1039. subschema LookupPatchMeta
  1040. )
  1041. typedSetElementOrderList, ok := setElementOrderInPatch.([]interface{})
  1042. if !ok {
  1043. return mergepatch.ErrBadArgType(typedSetElementOrderList, setElementOrderInPatch)
  1044. }
  1045. // Trim the setElementOrderDirectivePrefix to get the key of the list field in original.
  1046. originalKey, err := extractKey(key, setElementOrderDirectivePrefix)
  1047. if err != nil {
  1048. return err
  1049. }
  1050. // try to find the list with `originalKey` in `original` and `modified` and merge them.
  1051. originalList, foundOriginal := original[originalKey]
  1052. patchList, foundPatch := patch[originalKey]
  1053. if foundOriginal {
  1054. originalFieldValue, ok = originalList.([]interface{})
  1055. if !ok {
  1056. return mergepatch.ErrBadArgType(originalFieldValue, originalList)
  1057. }
  1058. }
  1059. if foundPatch {
  1060. patchFieldValue, ok = patchList.([]interface{})
  1061. if !ok {
  1062. return mergepatch.ErrBadArgType(patchFieldValue, patchList)
  1063. }
  1064. }
  1065. subschema, patchMeta, err = schema.LookupPatchMetadataForSlice(originalKey)
  1066. if err != nil {
  1067. return err
  1068. }
  1069. _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
  1070. if err != nil {
  1071. return err
  1072. }
  1073. // Check for consistency between the element order list and the field it applies to
  1074. err = validatePatchWithSetOrderList(patchFieldValue, typedSetElementOrderList, patchMeta.GetPatchMergeKey())
  1075. if err != nil {
  1076. return err
  1077. }
  1078. switch {
  1079. case foundOriginal && !foundPatch:
  1080. // no change to list contents
  1081. merged = originalFieldValue
  1082. case !foundOriginal && foundPatch:
  1083. // list was added
  1084. merged = patchFieldValue
  1085. case foundOriginal && foundPatch:
  1086. merged, err = mergeSliceHandler(originalList, patchList, subschema,
  1087. patchStrategy, patchMeta.GetPatchMergeKey(), false, mergeOptions)
  1088. if err != nil {
  1089. return err
  1090. }
  1091. case !foundOriginal && !foundPatch:
  1092. continue
  1093. }
  1094. // Split all items into patch items and server-only items and then enforce the order.
  1095. var patchItems, serverOnlyItems []interface{}
  1096. if len(patchMeta.GetPatchMergeKey()) == 0 {
  1097. // Primitives doesn't need merge key to do partitioning.
  1098. patchItems, serverOnlyItems = partitionPrimitivesByPresentInList(merged, typedSetElementOrderList)
  1099. } else {
  1100. // Maps need merge key to do partitioning.
  1101. patchItems, serverOnlyItems, err = partitionMapsByPresentInList(merged, typedSetElementOrderList, patchMeta.GetPatchMergeKey())
  1102. if err != nil {
  1103. return err
  1104. }
  1105. }
  1106. elementType, err := sliceElementType(originalFieldValue, patchFieldValue)
  1107. if err != nil {
  1108. return err
  1109. }
  1110. kind := elementType.Kind()
  1111. // normalize merged list
  1112. // typedSetElementOrderList contains all the relative order in typedPatchList,
  1113. // so don't need to use typedPatchList
  1114. both, err := normalizeElementOrder(patchItems, serverOnlyItems, typedSetElementOrderList, originalFieldValue, patchMeta.GetPatchMergeKey(), kind)
  1115. if err != nil {
  1116. return err
  1117. }
  1118. original[originalKey] = both
  1119. // delete patch list from patch to prevent process again in the future
  1120. delete(patch, originalKey)
  1121. }
  1122. return nil
  1123. }
  1124. // partitionPrimitivesByPresentInList partitions elements into 2 slices, the first containing items present in partitionBy, the other not.
  1125. func partitionPrimitivesByPresentInList(original, partitionBy []interface{}) ([]interface{}, []interface{}) {
  1126. patch := make([]interface{}, 0, len(original))
  1127. serverOnly := make([]interface{}, 0, len(original))
  1128. inPatch := map[interface{}]bool{}
  1129. for _, v := range partitionBy {
  1130. inPatch[v] = true
  1131. }
  1132. for _, v := range original {
  1133. if !inPatch[v] {
  1134. serverOnly = append(serverOnly, v)
  1135. } else {
  1136. patch = append(patch, v)
  1137. }
  1138. }
  1139. return patch, serverOnly
  1140. }
  1141. // partitionMapsByPresentInList partitions elements into 2 slices, the first containing items present in partitionBy, the other not.
  1142. func partitionMapsByPresentInList(original, partitionBy []interface{}, mergeKey string) ([]interface{}, []interface{}, error) {
  1143. patch := make([]interface{}, 0, len(original))
  1144. serverOnly := make([]interface{}, 0, len(original))
  1145. for _, v := range original {
  1146. typedV, ok := v.(map[string]interface{})
  1147. if !ok {
  1148. return nil, nil, mergepatch.ErrBadArgType(typedV, v)
  1149. }
  1150. mergeKeyValue, foundMergeKey := typedV[mergeKey]
  1151. if !foundMergeKey {
  1152. return nil, nil, mergepatch.ErrNoMergeKey(typedV, mergeKey)
  1153. }
  1154. _, _, found, err := findMapInSliceBasedOnKeyValue(partitionBy, mergeKey, mergeKeyValue)
  1155. if err != nil {
  1156. return nil, nil, err
  1157. }
  1158. if !found {
  1159. serverOnly = append(serverOnly, v)
  1160. } else {
  1161. patch = append(patch, v)
  1162. }
  1163. }
  1164. return patch, serverOnly, nil
  1165. }
  1166. // Merge fields from a patch map into the original map. Note: This may modify
  1167. // both the original map and the patch because getting a deep copy of a map in
  1168. // golang is highly non-trivial.
  1169. // flag mergeOptions.MergeParallelList controls if using the parallel list to delete or keeping the list.
  1170. // If patch contains any null field (e.g. field_1: null) that is not
  1171. // present in original, then to propagate it to the end result use
  1172. // mergeOptions.IgnoreUnmatchedNulls == false.
  1173. func mergeMap(original, patch map[string]interface{}, schema LookupPatchMeta, mergeOptions MergeOptions) (map[string]interface{}, error) {
  1174. if v, ok := patch[directiveMarker]; ok {
  1175. return handleDirectiveInMergeMap(v, patch)
  1176. }
  1177. // nil is an accepted value for original to simplify logic in other places.
  1178. // If original is nil, replace it with an empty map and then apply the patch.
  1179. if original == nil {
  1180. original = map[string]interface{}{}
  1181. }
  1182. err := applyRetainKeysDirective(original, patch, mergeOptions)
  1183. if err != nil {
  1184. return nil, err
  1185. }
  1186. // Process $setElementOrder list and other lists sharing the same key.
  1187. // When not merging the directive, it will make sure $setElementOrder list exist only in original.
  1188. // When merging the directive, it will process $setElementOrder and its patch list together.
  1189. // This function will delete the merged elements from patch so they will not be reprocessed
  1190. err = mergePatchIntoOriginal(original, patch, schema, mergeOptions)
  1191. if err != nil {
  1192. return nil, err
  1193. }
  1194. // Start merging the patch into the original.
  1195. for k, patchV := range patch {
  1196. skipProcessing, isDeleteList, noPrefixKey, err := preprocessDeletionListForMerging(k, original, patchV, mergeOptions.MergeParallelList)
  1197. if err != nil {
  1198. return nil, err
  1199. }
  1200. if skipProcessing {
  1201. continue
  1202. }
  1203. if len(noPrefixKey) > 0 {
  1204. k = noPrefixKey
  1205. }
  1206. // If the value of this key is null, delete the key if it exists in the
  1207. // original. Otherwise, check if we want to preserve it or skip it.
  1208. // Preserving the null value is useful when we want to send an explicit
  1209. // delete to the API server.
  1210. if patchV == nil {
  1211. delete(original, k)
  1212. if mergeOptions.IgnoreUnmatchedNulls {
  1213. continue
  1214. }
  1215. }
  1216. _, ok := original[k]
  1217. if !ok {
  1218. // If it's not in the original document, just take the patch value.
  1219. original[k] = patchV
  1220. continue
  1221. }
  1222. originalType := reflect.TypeOf(original[k])
  1223. patchType := reflect.TypeOf(patchV)
  1224. if originalType != patchType {
  1225. original[k] = patchV
  1226. continue
  1227. }
  1228. // If they're both maps or lists, recurse into the value.
  1229. switch originalType.Kind() {
  1230. case reflect.Map:
  1231. subschema, patchMeta, err2 := schema.LookupPatchMetadataForStruct(k)
  1232. if err2 != nil {
  1233. return nil, err2
  1234. }
  1235. _, patchStrategy, err2 := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
  1236. if err2 != nil {
  1237. return nil, err2
  1238. }
  1239. original[k], err = mergeMapHandler(original[k], patchV, subschema, patchStrategy, mergeOptions)
  1240. case reflect.Slice:
  1241. subschema, patchMeta, err2 := schema.LookupPatchMetadataForSlice(k)
  1242. if err2 != nil {
  1243. return nil, err2
  1244. }
  1245. _, patchStrategy, err2 := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
  1246. if err2 != nil {
  1247. return nil, err2
  1248. }
  1249. original[k], err = mergeSliceHandler(original[k], patchV, subschema, patchStrategy, patchMeta.GetPatchMergeKey(), isDeleteList, mergeOptions)
  1250. default:
  1251. original[k] = patchV
  1252. }
  1253. if err != nil {
  1254. return nil, err
  1255. }
  1256. }
  1257. return original, nil
  1258. }
  1259. // mergeMapHandler handles how to merge `patchV` whose key is `key` with `original` respecting
  1260. // fieldPatchStrategy and mergeOptions.
  1261. func mergeMapHandler(original, patch interface{}, schema LookupPatchMeta,
  1262. fieldPatchStrategy string, mergeOptions MergeOptions) (map[string]interface{}, error) {
  1263. typedOriginal, typedPatch, err := mapTypeAssertion(original, patch)
  1264. if err != nil {
  1265. return nil, err
  1266. }
  1267. if fieldPatchStrategy != replaceDirective {
  1268. return mergeMap(typedOriginal, typedPatch, schema, mergeOptions)
  1269. } else {
  1270. return typedPatch, nil
  1271. }
  1272. }
  1273. // mergeSliceHandler handles how to merge `patchV` whose key is `key` with `original` respecting
  1274. // fieldPatchStrategy, fieldPatchMergeKey, isDeleteList and mergeOptions.
  1275. func mergeSliceHandler(original, patch interface{}, schema LookupPatchMeta,
  1276. fieldPatchStrategy, fieldPatchMergeKey string, isDeleteList bool, mergeOptions MergeOptions) ([]interface{}, error) {
  1277. typedOriginal, typedPatch, err := sliceTypeAssertion(original, patch)
  1278. if err != nil {
  1279. return nil, err
  1280. }
  1281. if fieldPatchStrategy == mergeDirective {
  1282. return mergeSlice(typedOriginal, typedPatch, schema, fieldPatchMergeKey, mergeOptions, isDeleteList)
  1283. } else {
  1284. return typedPatch, nil
  1285. }
  1286. }
  1287. // Merge two slices together. Note: This may modify both the original slice and
  1288. // the patch because getting a deep copy of a slice in golang is highly
  1289. // non-trivial.
  1290. func mergeSlice(original, patch []interface{}, schema LookupPatchMeta, mergeKey string, mergeOptions MergeOptions, isDeleteList bool) ([]interface{}, error) {
  1291. if len(original) == 0 && len(patch) == 0 {
  1292. return original, nil
  1293. }
  1294. // All the values must be of the same type, but not a list.
  1295. t, err := sliceElementType(original, patch)
  1296. if err != nil {
  1297. return nil, err
  1298. }
  1299. var merged []interface{}
  1300. kind := t.Kind()
  1301. // If the elements are not maps, merge the slices of scalars.
  1302. if kind != reflect.Map {
  1303. if mergeOptions.MergeParallelList && isDeleteList {
  1304. return deleteFromSlice(original, patch), nil
  1305. }
  1306. // Maybe in the future add a "concat" mode that doesn't
  1307. // deduplicate.
  1308. both := append(original, patch...)
  1309. merged = deduplicateScalars(both)
  1310. } else {
  1311. if mergeKey == "" {
  1312. return nil, fmt.Errorf("cannot merge lists without merge key for %s", schema.Name())
  1313. }
  1314. original, patch, err = mergeSliceWithSpecialElements(original, patch, mergeKey)
  1315. if err != nil {
  1316. return nil, err
  1317. }
  1318. merged, err = mergeSliceWithoutSpecialElements(original, patch, mergeKey, schema, mergeOptions)
  1319. if err != nil {
  1320. return nil, err
  1321. }
  1322. }
  1323. // enforce the order
  1324. var patchItems, serverOnlyItems []interface{}
  1325. if len(mergeKey) == 0 {
  1326. patchItems, serverOnlyItems = partitionPrimitivesByPresentInList(merged, patch)
  1327. } else {
  1328. patchItems, serverOnlyItems, err = partitionMapsByPresentInList(merged, patch, mergeKey)
  1329. if err != nil {
  1330. return nil, err
  1331. }
  1332. }
  1333. return normalizeElementOrder(patchItems, serverOnlyItems, patch, original, mergeKey, kind)
  1334. }
  1335. // mergeSliceWithSpecialElements handles special elements with directiveMarker
  1336. // before merging the slices. It returns a updated `original` and a patch without special elements.
  1337. // original and patch must be slices of maps, they should be checked before calling this function.
  1338. func mergeSliceWithSpecialElements(original, patch []interface{}, mergeKey string) ([]interface{}, []interface{}, error) {
  1339. patchWithoutSpecialElements := []interface{}{}
  1340. replace := false
  1341. for _, v := range patch {
  1342. typedV := v.(map[string]interface{})
  1343. patchType, ok := typedV[directiveMarker]
  1344. if !ok {
  1345. patchWithoutSpecialElements = append(patchWithoutSpecialElements, v)
  1346. } else {
  1347. switch patchType {
  1348. case deleteDirective:
  1349. mergeValue, ok := typedV[mergeKey]
  1350. if ok {
  1351. var err error
  1352. original, err = deleteMatchingEntries(original, mergeKey, mergeValue)
  1353. if err != nil {
  1354. return nil, nil, err
  1355. }
  1356. } else {
  1357. return nil, nil, mergepatch.ErrNoMergeKey(typedV, mergeKey)
  1358. }
  1359. case replaceDirective:
  1360. replace = true
  1361. // Continue iterating through the array to prune any other $patch elements.
  1362. case mergeDirective:
  1363. return nil, nil, fmt.Errorf("merging lists cannot yet be specified in the patch")
  1364. default:
  1365. return nil, nil, mergepatch.ErrBadPatchType(patchType, typedV)
  1366. }
  1367. }
  1368. }
  1369. if replace {
  1370. return patchWithoutSpecialElements, nil, nil
  1371. }
  1372. return original, patchWithoutSpecialElements, nil
  1373. }
  1374. // delete all matching entries (based on merge key) from a merging list
  1375. func deleteMatchingEntries(original []interface{}, mergeKey string, mergeValue interface{}) ([]interface{}, error) {
  1376. for {
  1377. _, originalKey, found, err := findMapInSliceBasedOnKeyValue(original, mergeKey, mergeValue)
  1378. if err != nil {
  1379. return nil, err
  1380. }
  1381. if !found {
  1382. break
  1383. }
  1384. // Delete the element at originalKey.
  1385. original = append(original[:originalKey], original[originalKey+1:]...)
  1386. }
  1387. return original, nil
  1388. }
  1389. // mergeSliceWithoutSpecialElements merges slices with non-special elements.
  1390. // original and patch must be slices of maps, they should be checked before calling this function.
  1391. func mergeSliceWithoutSpecialElements(original, patch []interface{}, mergeKey string, schema LookupPatchMeta, mergeOptions MergeOptions) ([]interface{}, error) {
  1392. for _, v := range patch {
  1393. typedV := v.(map[string]interface{})
  1394. mergeValue, ok := typedV[mergeKey]
  1395. if !ok {
  1396. return nil, mergepatch.ErrNoMergeKey(typedV, mergeKey)
  1397. }
  1398. // If we find a value with this merge key value in original, merge the
  1399. // maps. Otherwise append onto original.
  1400. originalMap, originalKey, found, err := findMapInSliceBasedOnKeyValue(original, mergeKey, mergeValue)
  1401. if err != nil {
  1402. return nil, err
  1403. }
  1404. if found {
  1405. var mergedMaps interface{}
  1406. var err error
  1407. // Merge into original.
  1408. mergedMaps, err = mergeMap(originalMap, typedV, schema, mergeOptions)
  1409. if err != nil {
  1410. return nil, err
  1411. }
  1412. original[originalKey] = mergedMaps
  1413. } else {
  1414. original = append(original, v)
  1415. }
  1416. }
  1417. return original, nil
  1418. }
  1419. // deleteFromSlice uses the parallel list to delete the items in a list of scalars
  1420. func deleteFromSlice(current, toDelete []interface{}) []interface{} {
  1421. toDeleteMap := map[interface{}]interface{}{}
  1422. processed := make([]interface{}, 0, len(current))
  1423. for _, v := range toDelete {
  1424. toDeleteMap[v] = true
  1425. }
  1426. for _, v := range current {
  1427. if _, found := toDeleteMap[v]; !found {
  1428. processed = append(processed, v)
  1429. }
  1430. }
  1431. return processed
  1432. }
  1433. // This method no longer panics if any element of the slice is not a map.
  1434. func findMapInSliceBasedOnKeyValue(m []interface{}, key string, value interface{}) (map[string]interface{}, int, bool, error) {
  1435. for k, v := range m {
  1436. typedV, ok := v.(map[string]interface{})
  1437. if !ok {
  1438. return nil, 0, false, fmt.Errorf("value for key %v is not a map", k)
  1439. }
  1440. valueToMatch, ok := typedV[key]
  1441. if ok && valueToMatch == value {
  1442. return typedV, k, true, nil
  1443. }
  1444. }
  1445. return nil, 0, false, nil
  1446. }
  1447. // This function takes a JSON map and sorts all the lists that should be merged
  1448. // by key. This is needed by tests because in JSON, list order is significant,
  1449. // but in Strategic Merge Patch, merge lists do not have significant order.
  1450. // Sorting the lists allows for order-insensitive comparison of patched maps.
  1451. func sortMergeListsByName(mapJSON []byte, schema LookupPatchMeta) ([]byte, error) {
  1452. var m map[string]interface{}
  1453. err := json.Unmarshal(mapJSON, &m)
  1454. if err != nil {
  1455. return nil, mergepatch.ErrBadJSONDoc
  1456. }
  1457. newM, err := sortMergeListsByNameMap(m, schema)
  1458. if err != nil {
  1459. return nil, err
  1460. }
  1461. return json.Marshal(newM)
  1462. }
  1463. // Function sortMergeListsByNameMap recursively sorts the merge lists by its mergeKey in a map.
  1464. func sortMergeListsByNameMap(s map[string]interface{}, schema LookupPatchMeta) (map[string]interface{}, error) {
  1465. newS := map[string]interface{}{}
  1466. for k, v := range s {
  1467. if k == retainKeysDirective {
  1468. typedV, ok := v.([]interface{})
  1469. if !ok {
  1470. return nil, mergepatch.ErrBadPatchFormatForRetainKeys
  1471. }
  1472. v = sortScalars(typedV)
  1473. } else if strings.HasPrefix(k, deleteFromPrimitiveListDirectivePrefix) {
  1474. typedV, ok := v.([]interface{})
  1475. if !ok {
  1476. return nil, mergepatch.ErrBadPatchFormatForPrimitiveList
  1477. }
  1478. v = sortScalars(typedV)
  1479. } else if strings.HasPrefix(k, setElementOrderDirectivePrefix) {
  1480. _, ok := v.([]interface{})
  1481. if !ok {
  1482. return nil, mergepatch.ErrBadPatchFormatForSetElementOrderList
  1483. }
  1484. } else if k != directiveMarker {
  1485. // recurse for map and slice.
  1486. switch typedV := v.(type) {
  1487. case map[string]interface{}:
  1488. subschema, _, err := schema.LookupPatchMetadataForStruct(k)
  1489. if err != nil {
  1490. return nil, err
  1491. }
  1492. v, err = sortMergeListsByNameMap(typedV, subschema)
  1493. if err != nil {
  1494. return nil, err
  1495. }
  1496. case []interface{}:
  1497. subschema, patchMeta, err := schema.LookupPatchMetadataForSlice(k)
  1498. if err != nil {
  1499. return nil, err
  1500. }
  1501. _, patchStrategy, err := extractRetainKeysPatchStrategy(patchMeta.GetPatchStrategies())
  1502. if err != nil {
  1503. return nil, err
  1504. }
  1505. if patchStrategy == mergeDirective {
  1506. var err error
  1507. v, err = sortMergeListsByNameArray(typedV, subschema, patchMeta.GetPatchMergeKey(), true)
  1508. if err != nil {
  1509. return nil, err
  1510. }
  1511. }
  1512. }
  1513. }
  1514. newS[k] = v
  1515. }
  1516. return newS, nil
  1517. }
  1518. // Function sortMergeListsByNameMap recursively sorts the merge lists by its mergeKey in an array.
  1519. func sortMergeListsByNameArray(s []interface{}, schema LookupPatchMeta, mergeKey string, recurse bool) ([]interface{}, error) {
  1520. if len(s) == 0 {
  1521. return s, nil
  1522. }
  1523. // We don't support lists of lists yet.
  1524. t, err := sliceElementType(s)
  1525. if err != nil {
  1526. return nil, err
  1527. }
  1528. // If the elements are not maps...
  1529. if t.Kind() != reflect.Map {
  1530. // Sort the elements, because they may have been merged out of order.
  1531. return deduplicateAndSortScalars(s), nil
  1532. }
  1533. // Elements are maps - if one of the keys of the map is a map or a
  1534. // list, we may need to recurse into it.
  1535. newS := []interface{}{}
  1536. for _, elem := range s {
  1537. if recurse {
  1538. typedElem := elem.(map[string]interface{})
  1539. newElem, err := sortMergeListsByNameMap(typedElem, schema)
  1540. if err != nil {
  1541. return nil, err
  1542. }
  1543. newS = append(newS, newElem)
  1544. } else {
  1545. newS = append(newS, elem)
  1546. }
  1547. }
  1548. // Sort the maps.
  1549. newS = sortMapsBasedOnField(newS, mergeKey)
  1550. return newS, nil
  1551. }
  1552. func sortMapsBasedOnField(m []interface{}, fieldName string) []interface{} {
  1553. mapM := mapSliceFromSlice(m)
  1554. ss := SortableSliceOfMaps{mapM, fieldName}
  1555. sort.Sort(ss)
  1556. newS := sliceFromMapSlice(ss.s)
  1557. return newS
  1558. }
  1559. func mapSliceFromSlice(m []interface{}) []map[string]interface{} {
  1560. newM := []map[string]interface{}{}
  1561. for _, v := range m {
  1562. vt := v.(map[string]interface{})
  1563. newM = append(newM, vt)
  1564. }
  1565. return newM
  1566. }
  1567. func sliceFromMapSlice(s []map[string]interface{}) []interface{} {
  1568. newS := []interface{}{}
  1569. for _, v := range s {
  1570. newS = append(newS, v)
  1571. }
  1572. return newS
  1573. }
  1574. type SortableSliceOfMaps struct {
  1575. s []map[string]interface{}
  1576. k string // key to sort on
  1577. }
  1578. func (ss SortableSliceOfMaps) Len() int {
  1579. return len(ss.s)
  1580. }
  1581. func (ss SortableSliceOfMaps) Less(i, j int) bool {
  1582. iStr := fmt.Sprintf("%v", ss.s[i][ss.k])
  1583. jStr := fmt.Sprintf("%v", ss.s[j][ss.k])
  1584. return sort.StringsAreSorted([]string{iStr, jStr})
  1585. }
  1586. func (ss SortableSliceOfMaps) Swap(i, j int) {
  1587. tmp := ss.s[i]
  1588. ss.s[i] = ss.s[j]
  1589. ss.s[j] = tmp
  1590. }
  1591. func deduplicateAndSortScalars(s []interface{}) []interface{} {
  1592. s = deduplicateScalars(s)
  1593. return sortScalars(s)
  1594. }
  1595. func sortScalars(s []interface{}) []interface{} {
  1596. ss := SortableSliceOfScalars{s}
  1597. sort.Sort(ss)
  1598. return ss.s
  1599. }
  1600. func deduplicateScalars(s []interface{}) []interface{} {
  1601. // Clever algorithm to deduplicate.
  1602. length := len(s) - 1
  1603. for i := 0; i < length; i++ {
  1604. for j := i + 1; j <= length; j++ {
  1605. if s[i] == s[j] {
  1606. s[j] = s[length]
  1607. s = s[0:length]
  1608. length--
  1609. j--
  1610. }
  1611. }
  1612. }
  1613. return s
  1614. }
  1615. type SortableSliceOfScalars struct {
  1616. s []interface{}
  1617. }
  1618. func (ss SortableSliceOfScalars) Len() int {
  1619. return len(ss.s)
  1620. }
  1621. func (ss SortableSliceOfScalars) Less(i, j int) bool {
  1622. iStr := fmt.Sprintf("%v", ss.s[i])
  1623. jStr := fmt.Sprintf("%v", ss.s[j])
  1624. return sort.StringsAreSorted([]string{iStr, jStr})
  1625. }
  1626. func (ss SortableSliceOfScalars) Swap(i, j int) {
  1627. tmp := ss.s[i]
  1628. ss.s[i] = ss.s[j]
  1629. ss.s[j] = tmp
  1630. }
  1631. // Returns the type of the elements of N slice(s). If the type is different,
  1632. // another slice or undefined, returns an error.
  1633. func sliceElementType(slices ...[]interface{}) (reflect.Type, error) {
  1634. var prevType reflect.Type
  1635. for _, s := range slices {
  1636. // Go through elements of all given slices and make sure they are all the same type.
  1637. for _, v := range s {
  1638. currentType := reflect.TypeOf(v)
  1639. if prevType == nil {
  1640. prevType = currentType
  1641. // We don't support lists of lists yet.
  1642. if prevType.Kind() == reflect.Slice {
  1643. return nil, mergepatch.ErrNoListOfLists
  1644. }
  1645. } else {
  1646. if prevType != currentType {
  1647. return nil, fmt.Errorf("list element types are not identical: %v", fmt.Sprint(slices))
  1648. }
  1649. prevType = currentType
  1650. }
  1651. }
  1652. }
  1653. if prevType == nil {
  1654. return nil, fmt.Errorf("no elements in any of the given slices")
  1655. }
  1656. return prevType, nil
  1657. }
  1658. // MergingMapsHaveConflicts returns true if the left and right JSON interface
  1659. // objects overlap with different values in any key. All keys are required to be
  1660. // strings. Since patches of the same Type have congruent keys, this is valid
  1661. // for multiple patch types. This method supports strategic merge patch semantics.
  1662. func MergingMapsHaveConflicts(left, right map[string]interface{}, schema LookupPatchMeta) (bool, error) {
  1663. return mergingMapFieldsHaveConflicts(left, right, schema, "", "")
  1664. }
  1665. func mergingMapFieldsHaveConflicts(
  1666. left, right interface{},
  1667. schema LookupPatchMeta,
  1668. fieldPatchStrategy, fieldPatchMergeKey string,
  1669. ) (bool, error) {
  1670. switch leftType := left.(type) {
  1671. case map[string]interface{}:
  1672. rightType, ok := right.(map[string]interface{})
  1673. if !ok {
  1674. return true, nil
  1675. }
  1676. leftMarker, okLeft := leftType[directiveMarker]
  1677. rightMarker, okRight := rightType[directiveMarker]
  1678. // if one or the other has a directive marker,
  1679. // then we need to consider that before looking at the individual keys,
  1680. // since a directive operates on the whole map.
  1681. if okLeft || okRight {
  1682. // if one has a directive marker and the other doesn't,
  1683. // then we have a conflict, since one is deleting or replacing the whole map,
  1684. // and the other is doing things to individual keys.
  1685. if okLeft != okRight {
  1686. return true, nil
  1687. }
  1688. // if they both have markers, but they are not the same directive,
  1689. // then we have a conflict because they're doing different things to the map.
  1690. if leftMarker != rightMarker {
  1691. return true, nil
  1692. }
  1693. }
  1694. if fieldPatchStrategy == replaceDirective {
  1695. return false, nil
  1696. }
  1697. // Check the individual keys.
  1698. return mapsHaveConflicts(leftType, rightType, schema)
  1699. case []interface{}:
  1700. rightType, ok := right.([]interface{})
  1701. if !ok {
  1702. return true, nil
  1703. }
  1704. return slicesHaveConflicts(leftType, rightType, schema, fieldPatchStrategy, fieldPatchMergeKey)
  1705. case string, float64, bool, int64, nil:
  1706. return !reflect.DeepEqual(left, right), nil
  1707. default:
  1708. return true, fmt.Errorf("unknown type: %v", reflect.TypeOf(left))
  1709. }
  1710. }
  1711. func mapsHaveConflicts(typedLeft, typedRight map[string]interface{}, schema LookupPatchMeta) (bool, error) {
  1712. for key, leftValue := range typedLeft {
  1713. if key != directiveMarker && key != retainKeysDirective {
  1714. if rightValue, ok := typedRight[key]; ok {
  1715. var subschema LookupPatchMeta
  1716. var patchMeta PatchMeta
  1717. var patchStrategy string
  1718. var err error
  1719. switch leftValue.(type) {
  1720. case []interface{}:
  1721. subschema, patchMeta, err = schema.LookupPatchMetadataForSlice(key)
  1722. if err != nil {
  1723. return true, err
  1724. }
  1725. _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.patchStrategies)
  1726. if err != nil {
  1727. return true, err
  1728. }
  1729. case map[string]interface{}:
  1730. subschema, patchMeta, err = schema.LookupPatchMetadataForStruct(key)
  1731. if err != nil {
  1732. return true, err
  1733. }
  1734. _, patchStrategy, err = extractRetainKeysPatchStrategy(patchMeta.patchStrategies)
  1735. if err != nil {
  1736. return true, err
  1737. }
  1738. }
  1739. if hasConflicts, err := mergingMapFieldsHaveConflicts(leftValue, rightValue,
  1740. subschema, patchStrategy, patchMeta.GetPatchMergeKey()); hasConflicts {
  1741. return true, err
  1742. }
  1743. }
  1744. }
  1745. }
  1746. return false, nil
  1747. }
  1748. func slicesHaveConflicts(
  1749. typedLeft, typedRight []interface{},
  1750. schema LookupPatchMeta,
  1751. fieldPatchStrategy, fieldPatchMergeKey string,
  1752. ) (bool, error) {
  1753. elementType, err := sliceElementType(typedLeft, typedRight)
  1754. if err != nil {
  1755. return true, err
  1756. }
  1757. if fieldPatchStrategy == mergeDirective {
  1758. // Merging lists of scalars have no conflicts by definition
  1759. // So we only need to check further if the elements are maps
  1760. if elementType.Kind() != reflect.Map {
  1761. return false, nil
  1762. }
  1763. // Build a map for each slice and then compare the two maps
  1764. leftMap, err := sliceOfMapsToMapOfMaps(typedLeft, fieldPatchMergeKey)
  1765. if err != nil {
  1766. return true, err
  1767. }
  1768. rightMap, err := sliceOfMapsToMapOfMaps(typedRight, fieldPatchMergeKey)
  1769. if err != nil {
  1770. return true, err
  1771. }
  1772. return mapsOfMapsHaveConflicts(leftMap, rightMap, schema)
  1773. }
  1774. // Either we don't have type information, or these are non-merging lists
  1775. if len(typedLeft) != len(typedRight) {
  1776. return true, nil
  1777. }
  1778. // Sort scalar slices to prevent ordering issues
  1779. // We have no way to sort non-merging lists of maps
  1780. if elementType.Kind() != reflect.Map {
  1781. typedLeft = deduplicateAndSortScalars(typedLeft)
  1782. typedRight = deduplicateAndSortScalars(typedRight)
  1783. }
  1784. // Compare the slices element by element in order
  1785. // This test will fail if the slices are not sorted
  1786. for i := range typedLeft {
  1787. if hasConflicts, err := mergingMapFieldsHaveConflicts(typedLeft[i], typedRight[i], schema, "", ""); hasConflicts {
  1788. return true, err
  1789. }
  1790. }
  1791. return false, nil
  1792. }
  1793. func sliceOfMapsToMapOfMaps(slice []interface{}, mergeKey string) (map[string]interface{}, error) {
  1794. result := make(map[string]interface{}, len(slice))
  1795. for _, value := range slice {
  1796. typedValue, ok := value.(map[string]interface{})
  1797. if !ok {
  1798. return nil, fmt.Errorf("invalid element type in merging list:%v", slice)
  1799. }
  1800. mergeValue, ok := typedValue[mergeKey]
  1801. if !ok {
  1802. return nil, fmt.Errorf("cannot find merge key `%s` in merging list element:%v", mergeKey, typedValue)
  1803. }
  1804. result[fmt.Sprintf("%s", mergeValue)] = typedValue
  1805. }
  1806. return result, nil
  1807. }
  1808. func mapsOfMapsHaveConflicts(typedLeft, typedRight map[string]interface{}, schema LookupPatchMeta) (bool, error) {
  1809. for key, leftValue := range typedLeft {
  1810. if rightValue, ok := typedRight[key]; ok {
  1811. if hasConflicts, err := mergingMapFieldsHaveConflicts(leftValue, rightValue, schema, "", ""); hasConflicts {
  1812. return true, err
  1813. }
  1814. }
  1815. }
  1816. return false, nil
  1817. }
  1818. // CreateThreeWayMergePatch reconciles a modified configuration with an original configuration,
  1819. // while preserving any changes or deletions made to the original configuration in the interim,
  1820. // and not overridden by the current configuration. All three documents must be passed to the
  1821. // method as json encoded content. It will return a strategic merge patch, or an error if any
  1822. // of the documents is invalid, or if there are any preconditions that fail against the modified
  1823. // configuration, or, if overwrite is false and there are conflicts between the modified and current
  1824. // configurations. Conflicts are defined as keys changed differently from original to modified
  1825. // than from original to current. In other words, a conflict occurs if modified changes any key
  1826. // in a way that is different from how it is changed in current (e.g., deleting it, changing its
  1827. // value). We also propagate values fields that do not exist in original but are explicitly
  1828. // defined in modified.
  1829. func CreateThreeWayMergePatch(original, modified, current []byte, schema LookupPatchMeta, overwrite bool, fns ...mergepatch.PreconditionFunc) ([]byte, error) {
  1830. originalMap := map[string]interface{}{}
  1831. if len(original) > 0 {
  1832. if err := json.Unmarshal(original, &originalMap); err != nil {
  1833. return nil, mergepatch.ErrBadJSONDoc
  1834. }
  1835. }
  1836. modifiedMap := map[string]interface{}{}
  1837. if len(modified) > 0 {
  1838. if err := json.Unmarshal(modified, &modifiedMap); err != nil {
  1839. return nil, mergepatch.ErrBadJSONDoc
  1840. }
  1841. }
  1842. currentMap := map[string]interface{}{}
  1843. if len(current) > 0 {
  1844. if err := json.Unmarshal(current, &currentMap); err != nil {
  1845. return nil, mergepatch.ErrBadJSONDoc
  1846. }
  1847. }
  1848. // The patch is the difference from current to modified without deletions, plus deletions
  1849. // from original to modified. To find it, we compute deletions, which are the deletions from
  1850. // original to modified, and delta, which is the difference from current to modified without
  1851. // deletions, and then apply delta to deletions as a patch, which should be strictly additive.
  1852. deltaMapDiffOptions := DiffOptions{
  1853. IgnoreDeletions: true,
  1854. SetElementOrder: true,
  1855. }
  1856. deltaMap, err := diffMaps(currentMap, modifiedMap, schema, deltaMapDiffOptions)
  1857. if err != nil {
  1858. return nil, err
  1859. }
  1860. deletionsMapDiffOptions := DiffOptions{
  1861. SetElementOrder: true,
  1862. IgnoreChangesAndAdditions: true,
  1863. }
  1864. deletionsMap, err := diffMaps(originalMap, modifiedMap, schema, deletionsMapDiffOptions)
  1865. if err != nil {
  1866. return nil, err
  1867. }
  1868. mergeOptions := MergeOptions{}
  1869. patchMap, err := mergeMap(deletionsMap, deltaMap, schema, mergeOptions)
  1870. if err != nil {
  1871. return nil, err
  1872. }
  1873. // Apply the preconditions to the patch, and return an error if any of them fail.
  1874. for _, fn := range fns {
  1875. if !fn(patchMap) {
  1876. return nil, mergepatch.NewErrPreconditionFailed(patchMap)
  1877. }
  1878. }
  1879. // If overwrite is false, and the patch contains any keys that were changed differently,
  1880. // then return a conflict error.
  1881. if !overwrite {
  1882. changeMapDiffOptions := DiffOptions{}
  1883. changedMap, err := diffMaps(originalMap, currentMap, schema, changeMapDiffOptions)
  1884. if err != nil {
  1885. return nil, err
  1886. }
  1887. hasConflicts, err := MergingMapsHaveConflicts(patchMap, changedMap, schema)
  1888. if err != nil {
  1889. return nil, err
  1890. }
  1891. if hasConflicts {
  1892. return nil, mergepatch.NewErrConflict(mergepatch.ToYAMLOrError(patchMap), mergepatch.ToYAMLOrError(changedMap))
  1893. }
  1894. }
  1895. return json.Marshal(patchMap)
  1896. }
  1897. func ItemAddedToModifiedSlice(original, modified string) bool { return original > modified }
  1898. func ItemRemovedFromModifiedSlice(original, modified string) bool { return original < modified }
  1899. func ItemMatchesOriginalAndModifiedSlice(original, modified string) bool { return original == modified }
  1900. func CreateDeleteDirective(mergeKey string, mergeKeyValue interface{}) map[string]interface{} {
  1901. return map[string]interface{}{mergeKey: mergeKeyValue, directiveMarker: deleteDirective}
  1902. }
  1903. func mapTypeAssertion(original, patch interface{}) (map[string]interface{}, map[string]interface{}, error) {
  1904. typedOriginal, ok := original.(map[string]interface{})
  1905. if !ok {
  1906. return nil, nil, mergepatch.ErrBadArgType(typedOriginal, original)
  1907. }
  1908. typedPatch, ok := patch.(map[string]interface{})
  1909. if !ok {
  1910. return nil, nil, mergepatch.ErrBadArgType(typedPatch, patch)
  1911. }
  1912. return typedOriginal, typedPatch, nil
  1913. }
  1914. func sliceTypeAssertion(original, patch interface{}) ([]interface{}, []interface{}, error) {
  1915. typedOriginal, ok := original.([]interface{})
  1916. if !ok {
  1917. return nil, nil, mergepatch.ErrBadArgType(typedOriginal, original)
  1918. }
  1919. typedPatch, ok := patch.([]interface{})
  1920. if !ok {
  1921. return nil, nil, mergepatch.ErrBadArgType(typedPatch, patch)
  1922. }
  1923. return typedOriginal, typedPatch, nil
  1924. }
  1925. // extractRetainKeysPatchStrategy process patch strategy, which is a string may contains multiple
  1926. // patch strategies separated by ",". It returns a boolean var indicating if it has
  1927. // retainKeys strategies and a string for the other strategy.
  1928. func extractRetainKeysPatchStrategy(strategies []string) (bool, string, error) {
  1929. switch len(strategies) {
  1930. case 0:
  1931. return false, "", nil
  1932. case 1:
  1933. singleStrategy := strategies[0]
  1934. switch singleStrategy {
  1935. case retainKeysStrategy:
  1936. return true, "", nil
  1937. default:
  1938. return false, singleStrategy, nil
  1939. }
  1940. case 2:
  1941. switch {
  1942. case strategies[0] == retainKeysStrategy:
  1943. return true, strategies[1], nil
  1944. case strategies[1] == retainKeysStrategy:
  1945. return true, strategies[0], nil
  1946. default:
  1947. return false, "", fmt.Errorf("unexpected patch strategy: %v", strategies)
  1948. }
  1949. default:
  1950. return false, "", fmt.Errorf("unexpected patch strategy: %v", strategies)
  1951. }
  1952. }
  1953. // hasAdditionalNewField returns if original map has additional key with non-nil value than modified.
  1954. func hasAdditionalNewField(original, modified map[string]interface{}) bool {
  1955. for k, v := range original {
  1956. if v == nil {
  1957. continue
  1958. }
  1959. if _, found := modified[k]; !found {
  1960. return true
  1961. }
  1962. }
  1963. return false
  1964. }