@@ -18,15 +18,19 @@ package resource
1818
1919import (
2020 "context"
21+ "encoding/json"
2122 "testing"
2223
24+ jsonpatch "github.com/evanphx/json-patch"
2325 "github.com/google/go-cmp/cmp"
2426 kerrors "k8s.io/apimachinery/pkg/api/errors"
2527 "k8s.io/apimachinery/pkg/api/meta"
2628 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2730 "k8s.io/apimachinery/pkg/runtime"
2831 "k8s.io/apimachinery/pkg/runtime/schema"
2932 "sigs.k8s.io/controller-runtime/pkg/client"
33+ "sigs.k8s.io/yaml"
3034
3135 "github.com/crossplane/crossplane-runtime/pkg/errors"
3236 "github.com/crossplane/crossplane-runtime/pkg/resource/fake"
@@ -54,6 +58,14 @@ func TestAPIPatchingApplicator(t *testing.T) {
5458 fakeRESTMapper := meta .NewDefaultRESTMapper ([]schema.GroupVersion {gvk .GroupVersion ()})
5559 fakeRESTMapper .AddSpecific (gvk , gvr , singular , meta .RESTScopeRoot )
5660
61+ // for additive merge patch option test
62+ currentYAML := `
63+ metadata:
64+ resourceVersion: "42"
65+ a: old
66+ b: old
67+ `
68+
5769 type args struct {
5870 ctx context.Context
5971 o client.Object
@@ -221,6 +233,63 @@ func TestAPIPatchingApplicator(t *testing.T) {
221233 err : kerrors .NewConflict (schema.GroupResource {Group : "example.com" , Resource : "things" }, current .GetName (), errors .New (errOptimisticLock )),
222234 },
223235 },
236+ "AdditiveMergePatch" : {
237+ reason : "No error with the old additive behaviour if desired" ,
238+ c : & test.MockClient {
239+ MockGet : test .NewMockGetFn (nil , func (o client.Object ) error {
240+ o .(* unstructured.Unstructured ).Object = map [string ]interface {}{}
241+ return yaml .Unmarshal ([]byte (currentYAML ), & o .(* unstructured.Unstructured ).Object )
242+ }),
243+ MockPatch : func (_ context.Context , o client.Object , patch client.Patch , _ ... client.PatchOption ) error {
244+ bs , err := patch .Data (o )
245+ if err != nil {
246+ return err
247+ }
248+ currentJSON , err := yaml .YAMLToJSON ([]byte (currentYAML ))
249+ if err != nil {
250+ return err
251+ }
252+ patched , err := jsonpatch .MergePatch (currentJSON , bs )
253+ if err != nil {
254+ return err
255+ }
256+ o .(* unstructured.Unstructured ).Object = map [string ]interface {}{}
257+ if err := json .Unmarshal (patched , & o .(* unstructured.Unstructured ).Object ); err != nil {
258+ return err
259+ }
260+ o .SetResourceVersion ("43" )
261+ return nil
262+ },
263+ MockGroupVersionKindFor : test .NewMockGroupVersionKindForFn (nil , gvk ),
264+ MockRESTMapper : test .NewMockRESTMapperFn (fakeRESTMapper ),
265+ },
266+ args : args {
267+ o : & unstructured.Unstructured {
268+ Object : map [string ]interface {}{
269+ "kind" : "Thing" ,
270+ "metadata" : map [string ]interface {}{
271+ "resourceVersion" : "42" ,
272+ },
273+ "b" : "changed" ,
274+ "c" : "added" ,
275+ },
276+ },
277+ ao : []ApplyOption {AdditiveMergePatchApplyOption },
278+ },
279+ want : want {
280+ o : & unstructured.Unstructured {
281+ Object : map [string ]interface {}{
282+ "kind" : "Thing" ,
283+ "metadata" : map [string ]interface {}{
284+ "resourceVersion" : "43" ,
285+ },
286+ "a" : "old" ,
287+ "b" : "changed" ,
288+ "c" : "added" ,
289+ },
290+ },
291+ },
292+ },
224293 }
225294
226295 for name , tc := range cases {
0 commit comments