diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 0dc8d1a2a2..6c78b31bfc 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -19,6 +19,7 @@ package client_test import ( "context" "fmt" + "reflect" "sync/atomic" "time" @@ -3302,6 +3303,12 @@ var _ = Describe("Patch", func() { By("returning a patch with data containing the annotation change and the resourceVersion change") Expect(data).To(Equal([]byte(fmt.Sprintf(`{"metadata":{"annotations":{"%s":"%s"},"resourceVersion":"%s"}}`, annotationKey, annotationValue, cm.ResourceVersion)))) }) + + It("deeply equals to the same patch", func() { + patch1 := client.MergeFrom(cm) + patch2 := client.MergeFrom(cm) + Expect(reflect.DeepEqual(patch1, patch2)).To(BeTrue()) + }) }) Describe("StrategicMergeFrom", func() { @@ -3380,6 +3387,12 @@ var _ = Describe("Patch", func() { `"spec":{"template":{"spec":{"$setElementOrder/containers":[{"name":"main"},{"name":"sidecar"}],"containers":[{"image":"foo:v2","name":"main"}]}}}}`, dep.ResourceVersion)))) }) + + It("deeply equals to the same patch", func() { + patch1 := client.StrategicMergeFrom(dep) + patch2 := client.StrategicMergeFrom(dep) + Expect(reflect.DeepEqual(patch1, patch2)).To(BeTrue()) + }) }) }) diff --git a/pkg/client/patch.go b/pkg/client/patch.go index 10984c5342..5c5cd5a930 100644 --- a/pkg/client/patch.go +++ b/pkg/client/patch.go @@ -84,11 +84,15 @@ type MergeFromOptions struct { OptimisticLock bool } +type patchHandler interface { + createPatch(originalJSON, modifiedJSON []byte, dataStruct interface{}) ([]byte, error) +} + type mergeFromPatch struct { - patchType types.PatchType - createPatch func(originalJSON, modifiedJSON []byte, dataStruct interface{}) ([]byte, error) - from Object - opts MergeFromOptions + patchType types.PatchType + patchHandler patchHandler + from Object + opts MergeFromOptions } // Type implements Patch. @@ -124,7 +128,7 @@ func (s *mergeFromPatch) Data(obj Object) ([]byte, error) { return nil, err } - data, err := s.createPatch(originalJSON, modifiedJSON, obj) + data, err := s.patchHandler.createPatch(originalJSON, modifiedJSON, obj) if err != nil { return nil, err } @@ -132,11 +136,15 @@ func (s *mergeFromPatch) Data(obj Object) ([]byte, error) { return data, nil } -func createMergePatch(originalJSON, modifiedJSON []byte, _ interface{}) ([]byte, error) { +type mergePatchHandler struct{} + +func (mergePatchHandler) createPatch(originalJSON, modifiedJSON []byte, dataStruct interface{}) ([]byte, error) { return jsonpatch.CreateMergePatch(originalJSON, modifiedJSON) } -func createStrategicMergePatch(originalJSON, modifiedJSON []byte, dataStruct interface{}) ([]byte, error) { +type strategicMergePatchHandler struct{} + +func (strategicMergePatchHandler) createPatch(originalJSON, modifiedJSON []byte, dataStruct interface{}) ([]byte, error) { return strategicpatch.CreateTwoWayMergePatch(originalJSON, modifiedJSON, dataStruct) } @@ -148,7 +156,7 @@ func createStrategicMergePatch(originalJSON, modifiedJSON []byte, dataStruct int // See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ for more details on // the difference between merge-patch and strategic-merge-patch. func MergeFrom(obj Object) Patch { - return &mergeFromPatch{patchType: types.MergePatchType, createPatch: createMergePatch, from: obj} + return &mergeFromPatch{patchType: types.MergePatchType, patchHandler: mergePatchHandler{}, from: obj} } // MergeFromWithOptions creates a Patch that patches using the merge-patch strategy with the given object as base. @@ -158,7 +166,7 @@ func MergeFromWithOptions(obj Object, opts ...MergeFromOption) Patch { for _, opt := range opts { opt.ApplyToMergeFrom(options) } - return &mergeFromPatch{patchType: types.MergePatchType, createPatch: createMergePatch, from: obj, opts: *options} + return &mergeFromPatch{patchType: types.MergePatchType, patchHandler: mergePatchHandler{}, from: obj, opts: *options} } // StrategicMergeFrom creates a Patch that patches using the strategic-merge-patch strategy with the given object as base. @@ -175,7 +183,7 @@ func StrategicMergeFrom(obj Object, opts ...MergeFromOption) Patch { for _, opt := range opts { opt.ApplyToMergeFrom(options) } - return &mergeFromPatch{patchType: types.StrategicMergePatchType, createPatch: createStrategicMergePatch, from: obj, opts: *options} + return &mergeFromPatch{patchType: types.StrategicMergePatchType, patchHandler: strategicMergePatchHandler{}, from: obj, opts: *options} } // mergePatch uses a raw merge strategy to patch the object.