vendor: remove dep and use vndr
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
parent
16f44674a4
commit
148e72d81e
16131 changed files with 73815 additions and 4235138 deletions
237
vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go
generated
vendored
237
vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go
generated
vendored
|
@ -23,10 +23,8 @@ import (
|
|||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
"k8s.io/apimachinery/pkg/util/mergepatch"
|
||||
forkedjson "k8s.io/apimachinery/third_party/forked/golang/json"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/ghodss/yaml"
|
||||
)
|
||||
|
||||
// An alternate implementation of JSON Merge Patch
|
||||
|
@ -55,110 +53,26 @@ const (
|
|||
// json marshaling and/or unmarshaling operations.
|
||||
type JSONMap map[string]interface{}
|
||||
|
||||
// IsPreconditionFailed returns true if the provided error indicates
|
||||
// a precondition failed.
|
||||
func IsPreconditionFailed(err error) bool {
|
||||
_, ok := err.(errPreconditionFailed)
|
||||
return ok
|
||||
}
|
||||
|
||||
type errPreconditionFailed struct {
|
||||
message string
|
||||
}
|
||||
|
||||
func newErrPreconditionFailed(target map[string]interface{}) errPreconditionFailed {
|
||||
s := fmt.Sprintf("precondition failed for: %v", target)
|
||||
return errPreconditionFailed{s}
|
||||
}
|
||||
|
||||
func (err errPreconditionFailed) Error() string {
|
||||
return err.message
|
||||
}
|
||||
|
||||
type errConflict struct {
|
||||
message string
|
||||
}
|
||||
|
||||
func newErrConflict(patch, current string) errConflict {
|
||||
s := fmt.Sprintf("patch:\n%s\nconflicts with changes made from original to current:\n%s\n", patch, current)
|
||||
return errConflict{s}
|
||||
}
|
||||
|
||||
func (err errConflict) Error() string {
|
||||
return err.message
|
||||
}
|
||||
|
||||
// IsConflict returns true if the provided error indicates
|
||||
// a conflict between the patch and the current configuration.
|
||||
func IsConflict(err error) bool {
|
||||
_, ok := err.(errConflict)
|
||||
return ok
|
||||
}
|
||||
|
||||
var errBadJSONDoc = fmt.Errorf("Invalid JSON document")
|
||||
var errNoListOfLists = fmt.Errorf("Lists of lists are not supported")
|
||||
var errBadPatchFormatForPrimitiveList = fmt.Errorf("Invalid patch format of primitive list")
|
||||
|
||||
// The following code is adapted from github.com/openshift/origin/pkg/util/jsonmerge.
|
||||
// Instead of defining a Delta that holds an original, a patch and a set of preconditions,
|
||||
// the reconcile method accepts a set of preconditions as an argument.
|
||||
|
||||
// PreconditionFunc asserts that an incompatible change is not present within a patch.
|
||||
type PreconditionFunc func(interface{}) bool
|
||||
|
||||
// RequireKeyUnchanged returns a precondition function that fails if the provided key
|
||||
// is present in the patch (indicating that its value has changed).
|
||||
func RequireKeyUnchanged(key string) PreconditionFunc {
|
||||
return func(patch interface{}) bool {
|
||||
patchMap, ok := patch.(map[string]interface{})
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
// The presence of key means that its value has been changed, so the test fails.
|
||||
_, ok = patchMap[key]
|
||||
return !ok
|
||||
}
|
||||
}
|
||||
|
||||
// RequireMetadataKeyUnchanged creates a precondition function that fails
|
||||
// if the metadata.key is present in the patch (indicating its value
|
||||
// has changed).
|
||||
func RequireMetadataKeyUnchanged(key string) PreconditionFunc {
|
||||
return func(patch interface{}) bool {
|
||||
patchMap, ok := patch.(map[string]interface{})
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
patchMap1, ok := patchMap["metadata"]
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
patchMap2, ok := patchMap1.(map[string]interface{})
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
_, ok = patchMap2[key]
|
||||
return !ok
|
||||
}
|
||||
}
|
||||
|
||||
// CreateTwoWayMergePatch creates a patch that can be passed to StrategicMergePatch from an original
|
||||
// document and a modified document, which are passed to the method as json encoded content. It will
|
||||
// return a patch that yields the modified document when applied to the original document, or an error
|
||||
// if either of the two documents is invalid.
|
||||
func CreateTwoWayMergePatch(original, modified []byte, dataStruct interface{}, fns ...PreconditionFunc) ([]byte, error) {
|
||||
func CreateTwoWayMergePatch(original, modified []byte, dataStruct interface{}, fns ...mergepatch.PreconditionFunc) ([]byte, error) {
|
||||
originalMap := map[string]interface{}{}
|
||||
if len(original) > 0 {
|
||||
if err := json.Unmarshal(original, &originalMap); err != nil {
|
||||
return nil, errBadJSONDoc
|
||||
return nil, mergepatch.ErrBadJSONDoc
|
||||
}
|
||||
}
|
||||
|
||||
modifiedMap := map[string]interface{}{}
|
||||
if len(modified) > 0 {
|
||||
if err := json.Unmarshal(modified, &modifiedMap); err != nil {
|
||||
return nil, errBadJSONDoc
|
||||
return nil, mergepatch.ErrBadJSONDoc
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,7 +87,7 @@ func CreateTwoWayMergePatch(original, modified []byte, dataStruct interface{}, f
|
|||
// CreateTwoWayMergeMapPatch creates a patch from an original and modified JSON objects,
|
||||
// encoded JSONMap.
|
||||
// The serialized version of the map can then be passed to StrategicMergeMapPatch.
|
||||
func CreateTwoWayMergeMapPatch(original, modified JSONMap, dataStruct interface{}, fns ...PreconditionFunc) (JSONMap, error) {
|
||||
func CreateTwoWayMergeMapPatch(original, modified JSONMap, dataStruct interface{}, fns ...mergepatch.PreconditionFunc) (JSONMap, error) {
|
||||
t, err := getTagStructType(dataStruct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -187,7 +101,7 @@ func CreateTwoWayMergeMapPatch(original, modified JSONMap, dataStruct interface{
|
|||
// Apply the preconditions to the patch, and return an error if any of them fail.
|
||||
for _, fn := range fns {
|
||||
if !fn(patchMap) {
|
||||
return nil, newErrPreconditionFailed(patchMap)
|
||||
return nil, mergepatch.NewErrPreconditionFailed(patchMap)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,11 +158,24 @@ func diffMaps(original, modified map[string]interface{}, t reflect.Type, ignoreC
|
|||
switch originalValueTyped := originalValue.(type) {
|
||||
case map[string]interface{}:
|
||||
modifiedValueTyped := modifiedValue.(map[string]interface{})
|
||||
fieldType, _, _, err := forkedjson.LookupPatchMetadata(t, key)
|
||||
fieldType, fieldPatchStrategy, _, err := forkedjson.LookupPatchMetadata(t, key)
|
||||
if err != nil {
|
||||
// We couldn't look up metadata for the field
|
||||
// If the values are identical, this doesn't matter, no patch is needed
|
||||
if reflect.DeepEqual(originalValue, modifiedValue) {
|
||||
continue
|
||||
}
|
||||
// Otherwise, return the error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if fieldPatchStrategy == replaceDirective {
|
||||
if !ignoreChangesAndAdditions {
|
||||
patch[key] = modifiedValue
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
patchValue, err := diffMaps(originalValueTyped, modifiedValueTyped, fieldType, ignoreChangesAndAdditions, ignoreDeletions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -263,6 +190,12 @@ func diffMaps(original, modified map[string]interface{}, t reflect.Type, ignoreC
|
|||
modifiedValueTyped := modifiedValue.([]interface{})
|
||||
fieldType, fieldPatchStrategy, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadata(t, key)
|
||||
if err != nil {
|
||||
// We couldn't look up metadata for the field
|
||||
// If the values are identical, this doesn't matter, no patch is needed
|
||||
if reflect.DeepEqual(originalValue, modifiedValue) {
|
||||
continue
|
||||
}
|
||||
// Otherwise, return the error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -332,7 +265,7 @@ func diffLists(original, modified []interface{}, t reflect.Type, mergeKey string
|
|||
return patchList, nil, err
|
||||
case reflect.Slice:
|
||||
// Lists of Lists are not permitted by the api
|
||||
return nil, nil, errNoListOfLists
|
||||
return nil, nil, mergepatch.ErrNoListOfLists
|
||||
default:
|
||||
return diffListsOfScalars(original, modified, ignoreChangesAndAdditions, ignoreDeletions)
|
||||
}
|
||||
|
@ -523,13 +456,13 @@ func StrategicMergePatch(original, patch []byte, dataStruct interface{}) ([]byte
|
|||
originalMap := map[string]interface{}{}
|
||||
err := json.Unmarshal(original, &originalMap)
|
||||
if err != nil {
|
||||
return nil, errBadJSONDoc
|
||||
return nil, mergepatch.ErrBadJSONDoc
|
||||
}
|
||||
|
||||
patchMap := map[string]interface{}{}
|
||||
err = json.Unmarshal(patch, &patchMap)
|
||||
if err != nil {
|
||||
return nil, errBadJSONDoc
|
||||
return nil, mergepatch.ErrBadJSONDoc
|
||||
}
|
||||
|
||||
result, err := StrategicMergeMapPatch(originalMap, patchMap, dataStruct)
|
||||
|
@ -543,12 +476,13 @@ func StrategicMergePatch(original, patch []byte, dataStruct interface{}) ([]byte
|
|||
// StrategicMergePatch applies a strategic merge patch. The original and patch documents
|
||||
// must be JSONMap. A patch can be created from an original and modified document by
|
||||
// calling CreateTwoWayMergeMapPatch.
|
||||
// Warning: the original and patch JSONMap objects are mutated by this function and should not be reused.
|
||||
func StrategicMergeMapPatch(original, patch JSONMap, dataStruct interface{}) (JSONMap, error) {
|
||||
t, err := getTagStructType(dataStruct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mergeMap(original, patch, t, true)
|
||||
return mergeMap(original, patch, t, true, true)
|
||||
}
|
||||
|
||||
func getTagStructType(dataStruct interface{}) (reflect.Type, error) {
|
||||
|
@ -574,7 +508,10 @@ var errBadPatchTypeFmt = "unknown patch type: %s in map: %v"
|
|||
// both the original map and the patch because getting a deep copy of a map in
|
||||
// golang is highly non-trivial.
|
||||
// flag mergeDeleteList controls if using the parallel list to delete or keeping the list.
|
||||
func mergeMap(original, patch map[string]interface{}, t reflect.Type, mergeDeleteList bool) (map[string]interface{}, error) {
|
||||
// If patch contains any null field (e.g. field_1: null) that is not
|
||||
// present in original, then to propagate it to the end result use
|
||||
// ignoreUnmatchedNulls == false.
|
||||
func mergeMap(original, patch map[string]interface{}, t reflect.Type, mergeDeleteList, ignoreUnmatchedNulls bool) (map[string]interface{}, error) {
|
||||
if v, ok := patch[directiveMarker]; ok {
|
||||
if v == replaceDirective {
|
||||
// If the patch contains "$patch: replace", don't merge it, just use the
|
||||
|
@ -612,20 +549,24 @@ func mergeMap(original, patch map[string]interface{}, t reflect.Type, mergeDelet
|
|||
}
|
||||
substrings := strings.SplitN(k, "/", 2)
|
||||
if len(substrings) <= 1 {
|
||||
return nil, errBadPatchFormatForPrimitiveList
|
||||
return nil, mergepatch.ErrBadPatchFormatForPrimitiveList
|
||||
}
|
||||
isDeleteList = true
|
||||
k = substrings[1]
|
||||
}
|
||||
|
||||
// If the value of this key is null, delete the key if it exists in the
|
||||
// original. Otherwise, skip it.
|
||||
// original. Otherwise, check if we want to preserve it or skip it.
|
||||
// Preserving the null value is useful when we want to send an explicit
|
||||
// delete to the API server.
|
||||
if patchV == nil {
|
||||
if _, ok := original[k]; ok {
|
||||
delete(original, k)
|
||||
}
|
||||
|
||||
continue
|
||||
if ignoreUnmatchedNulls {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
_, ok := original[k]
|
||||
|
@ -654,7 +595,7 @@ func mergeMap(original, patch map[string]interface{}, t reflect.Type, mergeDelet
|
|||
typedOriginal := original[k].(map[string]interface{})
|
||||
typedPatch := patchV.(map[string]interface{})
|
||||
var err error
|
||||
original[k], err = mergeMap(typedOriginal, typedPatch, fieldType, mergeDeleteList)
|
||||
original[k], err = mergeMap(typedOriginal, typedPatch, fieldType, mergeDeleteList, ignoreUnmatchedNulls)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -667,7 +608,7 @@ func mergeMap(original, patch map[string]interface{}, t reflect.Type, mergeDelet
|
|||
typedOriginal := original[k].([]interface{})
|
||||
typedPatch := patchV.([]interface{})
|
||||
var err error
|
||||
original[k], err = mergeSlice(typedOriginal, typedPatch, elemType, fieldPatchMergeKey, mergeDeleteList, isDeleteList)
|
||||
original[k], err = mergeSlice(typedOriginal, typedPatch, elemType, fieldPatchMergeKey, mergeDeleteList, isDeleteList, ignoreUnmatchedNulls)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -688,7 +629,7 @@ func mergeMap(original, patch map[string]interface{}, t reflect.Type, mergeDelet
|
|||
// Merge two slices together. Note: This may modify both the original slice and
|
||||
// the patch because getting a deep copy of a slice in golang is highly
|
||||
// non-trivial.
|
||||
func mergeSlice(original, patch []interface{}, elemType reflect.Type, mergeKey string, mergeDeleteList, isDeleteList bool) ([]interface{}, error) {
|
||||
func mergeSlice(original, patch []interface{}, elemType reflect.Type, mergeKey string, mergeDeleteList, isDeleteList, ignoreUnmatchedNulls bool) ([]interface{}, error) {
|
||||
if len(original) == 0 && len(patch) == 0 {
|
||||
return original, nil
|
||||
}
|
||||
|
@ -779,7 +720,7 @@ func mergeSlice(original, patch []interface{}, elemType reflect.Type, mergeKey s
|
|||
var mergedMaps interface{}
|
||||
var err error
|
||||
// Merge into original.
|
||||
mergedMaps, err = mergeMap(originalMap, typedV, elemType, mergeDeleteList)
|
||||
mergedMaps, err = mergeMap(originalMap, typedV, elemType, mergeDeleteList, ignoreUnmatchedNulls)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -864,7 +805,7 @@ func sortMergeListsByNameMap(s map[string]interface{}, t reflect.Type) (map[stri
|
|||
if strings.HasPrefix(k, deleteFromPrimitiveListDirectivePrefix) {
|
||||
typedV, ok := v.([]interface{})
|
||||
if !ok {
|
||||
return nil, errBadPatchFormatForPrimitiveList
|
||||
return nil, mergepatch.ErrBadPatchFormatForPrimitiveList
|
||||
}
|
||||
v = uniqifyAndSortScalars(typedV)
|
||||
} else if k != directiveMarker {
|
||||
|
@ -1045,7 +986,7 @@ func sliceElementType(slices ...[]interface{}) (reflect.Type, error) {
|
|||
prevType = currentType
|
||||
// We don't support lists of lists yet.
|
||||
if prevType.Kind() == reflect.Slice {
|
||||
return nil, errNoListOfLists
|
||||
return nil, mergepatch.ErrNoListOfLists
|
||||
}
|
||||
} else {
|
||||
if prevType != currentType {
|
||||
|
@ -1063,49 +1004,6 @@ func sliceElementType(slices ...[]interface{}) (reflect.Type, error) {
|
|||
return prevType, nil
|
||||
}
|
||||
|
||||
// HasConflicts returns true if the left and right JSON interface objects overlap with
|
||||
// different values in any key. All keys are required to be strings. Since patches of the
|
||||
// same Type have congruent keys, this is valid for multiple patch types. This method
|
||||
// supports JSON merge patch semantics.
|
||||
func HasConflicts(left, right interface{}) (bool, error) {
|
||||
switch typedLeft := left.(type) {
|
||||
case map[string]interface{}:
|
||||
switch typedRight := right.(type) {
|
||||
case map[string]interface{}:
|
||||
for key, leftValue := range typedLeft {
|
||||
rightValue, ok := typedRight[key]
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
return HasConflicts(leftValue, rightValue)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
case []interface{}:
|
||||
switch typedRight := right.(type) {
|
||||
case []interface{}:
|
||||
if len(typedLeft) != len(typedRight) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
for i := range typedLeft {
|
||||
return HasConflicts(typedLeft[i], typedRight[i])
|
||||
}
|
||||
|
||||
return false, nil
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
case string, float64, bool, int, int64, nil:
|
||||
return !reflect.DeepEqual(left, right), nil
|
||||
default:
|
||||
return true, fmt.Errorf("unknown type: %v", reflect.TypeOf(left))
|
||||
}
|
||||
}
|
||||
|
||||
// MergingMapsHaveConflicts returns true if the left and right JSON interface
|
||||
// objects overlap with different values in any key. All keys are required to be
|
||||
// strings. Since patches of the same Type have congruent keys, this is valid
|
||||
|
@ -1148,6 +1046,10 @@ func mergingMapFieldsHaveConflicts(
|
|||
}
|
||||
}
|
||||
|
||||
if fieldPatchStrategy == replaceDirective {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Check the individual keys.
|
||||
return mapsHaveConflicts(leftType, rightType, fieldType)
|
||||
default:
|
||||
|
@ -1282,26 +1184,27 @@ func mapsOfMapsHaveConflicts(typedLeft, typedRight map[string]interface{}, struc
|
|||
// configurations. Conflicts are defined as keys changed differently from original to modified
|
||||
// than from original to current. In other words, a conflict occurs if modified changes any key
|
||||
// in a way that is different from how it is changed in current (e.g., deleting it, changing its
|
||||
// value).
|
||||
func CreateThreeWayMergePatch(original, modified, current []byte, dataStruct interface{}, overwrite bool, fns ...PreconditionFunc) ([]byte, error) {
|
||||
// value). We also propagate values fields that do not exist in original but are explicitly
|
||||
// defined in modified.
|
||||
func CreateThreeWayMergePatch(original, modified, current []byte, dataStruct interface{}, overwrite bool, fns ...mergepatch.PreconditionFunc) ([]byte, error) {
|
||||
originalMap := map[string]interface{}{}
|
||||
if len(original) > 0 {
|
||||
if err := json.Unmarshal(original, &originalMap); err != nil {
|
||||
return nil, errBadJSONDoc
|
||||
return nil, mergepatch.ErrBadJSONDoc
|
||||
}
|
||||
}
|
||||
|
||||
modifiedMap := map[string]interface{}{}
|
||||
if len(modified) > 0 {
|
||||
if err := json.Unmarshal(modified, &modifiedMap); err != nil {
|
||||
return nil, errBadJSONDoc
|
||||
return nil, mergepatch.ErrBadJSONDoc
|
||||
}
|
||||
}
|
||||
|
||||
currentMap := map[string]interface{}{}
|
||||
if len(current) > 0 {
|
||||
if err := json.Unmarshal(current, ¤tMap); err != nil {
|
||||
return nil, errBadJSONDoc
|
||||
return nil, mergepatch.ErrBadJSONDoc
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1324,7 +1227,7 @@ func CreateThreeWayMergePatch(original, modified, current []byte, dataStruct int
|
|||
return nil, err
|
||||
}
|
||||
|
||||
patchMap, err := mergeMap(deletionsMap, deltaMap, t, false)
|
||||
patchMap, err := mergeMap(deletionsMap, deltaMap, t, false, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1332,7 +1235,7 @@ func CreateThreeWayMergePatch(original, modified, current []byte, dataStruct int
|
|||
// Apply the preconditions to the patch, and return an error if any of them fail.
|
||||
for _, fn := range fns {
|
||||
if !fn(patchMap) {
|
||||
return nil, newErrPreconditionFailed(patchMap)
|
||||
return nil, mergepatch.NewErrPreconditionFailed(patchMap)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1350,27 +1253,9 @@ func CreateThreeWayMergePatch(original, modified, current []byte, dataStruct int
|
|||
}
|
||||
|
||||
if hasConflicts {
|
||||
return nil, newErrConflict(toYAMLOrError(patchMap), toYAMLOrError(changedMap))
|
||||
return nil, mergepatch.NewErrConflict(mergepatch.ToYAMLOrError(patchMap), mergepatch.ToYAMLOrError(changedMap))
|
||||
}
|
||||
}
|
||||
|
||||
return json.Marshal(patchMap)
|
||||
}
|
||||
|
||||
func toYAMLOrError(v interface{}) string {
|
||||
y, err := toYAML(v)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
return y
|
||||
}
|
||||
|
||||
func toYAML(v interface{}) (string, error) {
|
||||
y, err := yaml.Marshal(v)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("yaml marshal failed:%v\n%v\n", err, spew.Sdump(v))
|
||||
}
|
||||
|
||||
return string(y), nil
|
||||
}
|
||||
|
|
2370
vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go
generated
vendored
2370
vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue