Allow for returning map[string]interface{} from patch.

pull/6/head
Wojciech Tyczynski 2016-12-30 11:19:22 +01:00
parent 8f99b74466
commit d08abdb187
6 changed files with 41 additions and 27 deletions

View File

@ -244,7 +244,7 @@ func (e *eventLogger) eventObserve(newEvent *v1.Event) (*v1.Event, []byte, error
newData, _ := json.Marshal(event) newData, _ := json.Marshal(event)
oldData, _ := json.Marshal(eventCopy2) oldData, _ := json.Marshal(eventCopy2)
patch, err = strategicpatch.CreateStrategicMergePatch(oldData, newData, event) patch, err = strategicpatch.CreateTwoWayMergePatch(oldData, newData, event)
} }
// record our new observation // record our new observation

View File

@ -111,10 +111,10 @@ func (nsu *nodeStatusUpdater) UpdateNodeStatuses() error {
} }
patchBytes, err := patchBytes, err :=
strategicpatch.CreateStrategicMergePatch(oldData, newData, node) strategicpatch.CreateTwoWayMergePatch(oldData, newData, node)
if err != nil { if err != nil {
return fmt.Errorf( return fmt.Errorf(
"failed to CreateStrategicMergePatch for node %q. %v", "failed to CreateTwoWayMergePatch for node %q. %v",
nodeName, nodeName,
err) err)
} }

View File

@ -607,11 +607,11 @@ func patchResource(
if err != nil { if err != nil {
return nil, err return nil, err
} }
currentPatch, err := strategicpatch.CreateStrategicMergePatch(originalObjJS, currentObjectJS, versionedObj) currentPatch, err := strategicpatch.CreateTwoWayMergePatch(originalObjJS, currentObjectJS, versionedObj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
originalPatch, err := strategicpatch.CreateStrategicMergePatch(originalObjJS, originalPatchedObjJS, versionedObj) originalPatch, err := strategicpatch.CreateTwoWayMergePatch(originalObjJS, originalPatchedObjJS, versionedObj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1090,7 +1090,7 @@ func getPatchedJS(patchType types.PatchType, originalJS, patchJS []byte, obj run
case types.MergePatchType: case types.MergePatchType:
return jsonpatch.MergePatch(originalJS, patchJS) return jsonpatch.MergePatch(originalJS, patchJS)
case types.StrategicMergePatchType: case types.StrategicMergePatchType:
return strategicpatch.StrategicMergePatchData(originalJS, patchJS, obj) return strategicpatch.StrategicMergePatch(originalJS, patchJS, obj)
default: default:
// only here as a safety net - go-restful filters content-type // only here as a safety net - go-restful filters content-type
return nil, fmt.Errorf("unknown Content-Type header for patch: %v", patchType) return nil, fmt.Errorf("unknown Content-Type header for patch: %v", patchType)

View File

@ -215,7 +215,7 @@ func (tc *patchTestCase) Run(t *testing.T) {
continue continue
case types.StrategicMergePatchType: case types.StrategicMergePatchType:
patch, err = strategicpatch.CreateStrategicMergePatch(originalObjJS, changedJS, versionedObj) patch, err = strategicpatch.CreateTwoWayMergePatch(originalObjJS, changedJS, versionedObj)
if err != nil { if err != nil {
t.Errorf("%s: unexpected error: %v", tc.name, err) t.Errorf("%s: unexpected error: %v", tc.name, err)
return return

View File

@ -261,7 +261,7 @@ func getPatchedJSON(patchType types.PatchType, originalJS, patchJS []byte, obj r
return jsonpatch.MergePatch(originalJS, patchJS) return jsonpatch.MergePatch(originalJS, patchJS)
case types.StrategicMergePatchType: case types.StrategicMergePatchType:
return strategicpatch.StrategicMergePatchData(originalJS, patchJS, obj) return strategicpatch.StrategicMergePatch(originalJS, patchJS, obj)
default: default:
// only here as a safety net - go-restful filters content-type // only here as a safety net - go-restful filters content-type

View File

@ -48,6 +48,13 @@ const (
deleteFromPrimitiveListDirectivePrefix = "$deleteFromPrimitiveList" deleteFromPrimitiveListDirectivePrefix = "$deleteFromPrimitiveList"
) )
// JSONMap is a representations of JSON object encoded as map[string]interface{}
// where the children can be either map[string]interface{}, []interface{} or
// primitive type).
// Operating on JSONMap representation is much faster as it doesn't require any
// json marshaling and/or unmarshaling operations.
type JSONMap map[string]interface{}
// IsPreconditionFailed returns true if the provided error indicates // IsPreconditionFailed returns true if the provided error indicates
// a precondition failed. // a precondition failed.
func IsPreconditionFailed(err error) bool { func IsPreconditionFailed(err error) bool {
@ -136,11 +143,6 @@ func RequireMetadataKeyUnchanged(key string) PreconditionFunc {
} }
} }
// Deprecated: Use the synonym CreateTwoWayMergePatch, instead.
func CreateStrategicMergePatch(original, modified []byte, dataStruct interface{}) ([]byte, error) {
return CreateTwoWayMergePatch(original, modified, dataStruct)
}
// CreateTwoWayMergePatch creates a patch that can be passed to StrategicMergePatch from an original // 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 // 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 // return a patch that yields the modified document when applied to the original document, or an error
@ -160,12 +162,24 @@ func CreateTwoWayMergePatch(original, modified []byte, dataStruct interface{}, f
} }
} }
patchMap, err := CreateTwoWayMergeMapPatch(originalMap, modifiedMap, dataStruct, fns...)
if err != nil {
return nil, err
}
return json.Marshal(patchMap)
}
// 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) {
t, err := getTagStructType(dataStruct) t, err := getTagStructType(dataStruct)
if err != nil { if err != nil {
return nil, err return nil, err
} }
patchMap, err := diffMaps(originalMap, modifiedMap, t, false, false) patchMap, err := diffMaps(original, modified, t, false, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -177,7 +191,7 @@ func CreateTwoWayMergePatch(original, modified []byte, dataStruct interface{}, f
} }
} }
return json.Marshal(patchMap) return patchMap, nil
} }
// Returns a (recursive) strategic merge patch that yields modified when applied to original. // Returns a (recursive) strategic merge patch that yields modified when applied to original.
@ -494,12 +508,6 @@ loopB:
return patch, nil return patch, nil
} }
// Deprecated: StrategicMergePatchData is deprecated. Use the synonym StrategicMergePatch,
// instead, which follows the naming convention of evanphx/json-patch.
func StrategicMergePatchData(original, patch []byte, dataStruct interface{}) ([]byte, error) {
return StrategicMergePatch(original, patch, dataStruct)
}
// StrategicMergePatch applies a strategic merge patch. The patch and the original document // StrategicMergePatch applies a strategic merge patch. The patch and the original document
// must be json encoded content. A patch can be created from an original and a modified document // must be json encoded content. A patch can be created from an original and a modified document
// by calling CreateStrategicMergePatch. // by calling CreateStrategicMergePatch.
@ -524,12 +532,7 @@ func StrategicMergePatch(original, patch []byte, dataStruct interface{}) ([]byte
return nil, errBadJSONDoc return nil, errBadJSONDoc
} }
t, err := getTagStructType(dataStruct) result, err := StrategicMergeMapPatch(originalMap, patchMap, dataStruct)
if err != nil {
return nil, err
}
result, err := mergeMap(originalMap, patchMap, t, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -537,6 +540,17 @@ func StrategicMergePatch(original, patch []byte, dataStruct interface{}) ([]byte
return json.Marshal(result) return json.Marshal(result)
} }
// 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.
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)
}
func getTagStructType(dataStruct interface{}) (reflect.Type, error) { func getTagStructType(dataStruct interface{}) (reflect.Type, error) {
if dataStruct == nil { if dataStruct == nil {
return nil, fmt.Errorf(errBadArgTypeFmt, "struct", "nil") return nil, fmt.Errorf(errBadArgTypeFmt, "struct", "nil")