github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/strategicpatch/patch.go (about)

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