diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 4cc13107..84c39e62 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -50,6 +50,10 @@ "ImportPath": "github.com/docker/spdystream/spdy", "Rev": "449fdfce4d962303d702fec724ef0ad181c92528" }, + { + "ImportPath": "github.com/evanphx/json-patch", + "Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4" + }, { "ImportPath": "github.com/ghodss/yaml", "Rev": "c7ce16629ff4cd059ed96ed06419dd3856fd3577" @@ -400,207 +404,207 @@ }, { "ImportPath": "k8s.io/apimachinery/pkg/api/apitesting", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/apitesting/fuzzer", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/apitesting/roundtrip", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/equality", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/errors", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/meta", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/api/resource", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/conversion", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/fields", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/labels", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/schema", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/selection", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/types", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/cache", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/clock", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/diff", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/errors", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/framer", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/httpstream", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/intstr", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/json", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/naming", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/net", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/runtime", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/sets", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/validation", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/validation/field", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/wait", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/util/yaml", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/version", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/pkg/watch", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", - "Rev": "dcb88206cd7f3654b224cbfc244e41126f52a13b" + "Rev": "60666be32c5de527b69dabe8e4400b4f0aa897de" }, { "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", diff --git a/dynamic/fake/simple.go b/dynamic/fake/simple.go index c04b7883..eec3cfbc 100644 --- a/dynamic/fake/simple.go +++ b/dynamic/fake/simple.go @@ -331,25 +331,26 @@ func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, panic("math broke") } +// TODO: opts are currently ignored. func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, opts metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) { var uncastRet runtime.Object var err error switch { case len(c.namespace) == 0 && len(subresources) == 0: uncastRet, err = c.client.Fake. - Invokes(testing.NewRootPatchAction(c.resource, name, data), &metav1.Status{Status: "dynamic patch fail"}) + Invokes(testing.NewRootPatchAction(c.resource, name, pt, data), &metav1.Status{Status: "dynamic patch fail"}) case len(c.namespace) == 0 && len(subresources) > 0: uncastRet, err = c.client.Fake. - Invokes(testing.NewRootPatchSubresourceAction(c.resource, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"}) + Invokes(testing.NewRootPatchSubresourceAction(c.resource, name, pt, data, subresources...), &metav1.Status{Status: "dynamic patch fail"}) case len(c.namespace) > 0 && len(subresources) == 0: uncastRet, err = c.client.Fake. - Invokes(testing.NewPatchAction(c.resource, c.namespace, name, data), &metav1.Status{Status: "dynamic patch fail"}) + Invokes(testing.NewPatchAction(c.resource, c.namespace, name, pt, data), &metav1.Status{Status: "dynamic patch fail"}) case len(c.namespace) > 0 && len(subresources) > 0: uncastRet, err = c.client.Fake. - Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"}) + Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, pt, data, subresources...), &metav1.Status{Status: "dynamic patch fail"}) } diff --git a/dynamic/fake/simple_test.go b/dynamic/fake/simple_test.go index cb79c30b..f0991956 100644 --- a/dynamic/fake/simple_test.go +++ b/dynamic/fake/simple_test.go @@ -17,6 +17,7 @@ limitations under the License. package fake import ( + "fmt" "testing" "k8s.io/apimachinery/pkg/api/equality" @@ -24,9 +25,20 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/diff" ) +const ( + testGroup = "testgroup" + testVersion = "testversion" + testResource = "testkinds" + testNamespace = "testns" + testName = "testname" + testKind = "TestKind" + testAPIVersion = "testgroup/testversion" +) + func newUnstructured(apiVersion, kind, namespace, name string) *unstructured.Unstructured { return &unstructured.Unstructured{ Object: map[string]interface{}{ @@ -40,6 +52,12 @@ func newUnstructured(apiVersion, kind, namespace, name string) *unstructured.Uns } } +func newUnstructuredWithSpec(spec map[string]interface{}) *unstructured.Unstructured { + u := newUnstructured(testAPIVersion, testKind, testNamespace, testName) + u.Object["spec"] = spec + return u +} + func TestList(t *testing.T) { scheme := runtime.NewScheme() @@ -64,3 +82,116 @@ func TestList(t *testing.T) { t.Fatal(diff.ObjectGoPrintDiff(expected, listFirst.Items)) } } + +type patchTestCase struct { + name string + object runtime.Object + patchType types.PatchType + patchBytes []byte + wantErrMsg string + expectedPatchedObject runtime.Object +} + +func (tc *patchTestCase) runner(t *testing.T) { + client := NewSimpleDynamicClient(runtime.NewScheme(), tc.object) + resourceInterface := client.Resource(schema.GroupVersionResource{Group: testGroup, Version: testVersion, Resource: testResource}).Namespace(testNamespace) + + got, recErr := resourceInterface.Patch(testName, tc.patchType, tc.patchBytes, metav1.UpdateOptions{}) + + if err := tc.verifyErr(recErr); err != nil { + t.Error(err) + } + + if err := tc.verifyResult(got); err != nil { + t.Error(err) + } + +} + +// verifyErr verifies that the given error returned from Patch is the error +// expected by the test case. +func (tc *patchTestCase) verifyErr(err error) error { + if tc.wantErrMsg != "" && err == nil { + return fmt.Errorf("want error, got nil") + } + + if tc.wantErrMsg == "" && err != nil { + return fmt.Errorf("want no error, got %v", err) + } + + if err != nil { + if want, got := tc.wantErrMsg, err.Error(); want != got { + return fmt.Errorf("incorrect error: want: %q got: %q", want, got) + } + } + return nil +} + +func (tc *patchTestCase) verifyResult(result *unstructured.Unstructured) error { + if tc.expectedPatchedObject == nil && result == nil { + return nil + } + if !equality.Semantic.DeepEqual(result, tc.expectedPatchedObject) { + return fmt.Errorf("unexpected diff in received object: %s", diff.ObjectGoPrintDiff(tc.expectedPatchedObject, result)) + } + return nil +} + +func TestPatch(t *testing.T) { + testCases := []patchTestCase{ + { + name: "jsonpatch fails with merge type", + object: newUnstructuredWithSpec(map[string]interface{}{"foo": "bar"}), + patchType: types.StrategicMergePatchType, + patchBytes: []byte(`[]`), + wantErrMsg: "invalid JSON document", + }, { + name: "jsonpatch works with empty patch", + object: newUnstructuredWithSpec(map[string]interface{}{"foo": "bar"}), + patchType: types.JSONPatchType, + // No-op + patchBytes: []byte(`[]`), + expectedPatchedObject: newUnstructuredWithSpec(map[string]interface{}{"foo": "bar"}), + }, { + name: "jsonpatch works with simple change patch", + object: newUnstructuredWithSpec(map[string]interface{}{"foo": "bar"}), + patchType: types.JSONPatchType, + // change spec.foo from bar to foobar + patchBytes: []byte(`[{"op": "replace", "path": "/spec/foo", "value": "foobar"}]`), + expectedPatchedObject: newUnstructuredWithSpec(map[string]interface{}{"foo": "foobar"}), + }, { + name: "jsonpatch works with simple addition", + object: newUnstructuredWithSpec(map[string]interface{}{"foo": "bar"}), + patchType: types.JSONPatchType, + // add spec.newvalue = dummy + patchBytes: []byte(`[{"op": "add", "path": "/spec/newvalue", "value": "dummy"}]`), + expectedPatchedObject: newUnstructuredWithSpec(map[string]interface{}{"foo": "bar", "newvalue": "dummy"}), + }, { + name: "jsonpatch works with simple deletion", + object: newUnstructuredWithSpec(map[string]interface{}{"foo": "bar", "toremove": "shouldnotbehere"}), + patchType: types.JSONPatchType, + // remove spec.newvalue = dummy + patchBytes: []byte(`[{"op": "remove", "path": "/spec/toremove"}]`), + expectedPatchedObject: newUnstructuredWithSpec(map[string]interface{}{"foo": "bar"}), + }, { + name: "strategic merge patch fails with JSONPatch", + object: newUnstructuredWithSpec(map[string]interface{}{"foo": "bar"}), + patchType: types.StrategicMergePatchType, + // add spec.newvalue = dummy + patchBytes: []byte(`[{"op": "add", "path": "/spec/newvalue", "value": "dummy"}]`), + wantErrMsg: "invalid JSON document", + }, { + name: "merge patch fails as unsupported", + object: newUnstructured(testAPIVersion, testKind, testNamespace, testName), + patchType: types.MergePatchType, + patchBytes: []byte(`{}`), + wantErrMsg: "PatchType is not supported", + }, + // TODO: Add tests for strategic merge using v1.Pod for example to ensure the test cases + // demonstrate expected use cases. + } + + for _, tc := range testCases { + t.Run(tc.name, tc.runner) + } +} diff --git a/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go b/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go index b927dae2..4baee661 100644 --- a/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go +++ b/kubernetes/typed/admissionregistration/v1alpha1/fake/fake_initializerconfiguration.go @@ -112,7 +112,7 @@ func (c *FakeInitializerConfigurations) DeleteCollection(options *v1.DeleteOptio // Patch applies the patch and returns the patched initializerConfiguration. func (c *FakeInitializerConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.InitializerConfiguration, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(initializerconfigurationsResource, name, data, subresources...), &v1alpha1.InitializerConfiguration{}) + Invokes(testing.NewRootPatchSubresourceAction(initializerconfigurationsResource, name, pt, data, subresources...), &v1alpha1.InitializerConfiguration{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go b/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go index e06888cc..d2177bad 100644 --- a/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go +++ b/kubernetes/typed/admissionregistration/v1beta1/fake/fake_mutatingwebhookconfiguration.go @@ -112,7 +112,7 @@ func (c *FakeMutatingWebhookConfigurations) DeleteCollection(options *v1.DeleteO // Patch applies the patch and returns the patched mutatingWebhookConfiguration. func (c *FakeMutatingWebhookConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.MutatingWebhookConfiguration, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(mutatingwebhookconfigurationsResource, name, data, subresources...), &v1beta1.MutatingWebhookConfiguration{}) + Invokes(testing.NewRootPatchSubresourceAction(mutatingwebhookconfigurationsResource, name, pt, data, subresources...), &v1beta1.MutatingWebhookConfiguration{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go b/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go index 1069634e..6be2b393 100644 --- a/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go +++ b/kubernetes/typed/admissionregistration/v1beta1/fake/fake_validatingwebhookconfiguration.go @@ -112,7 +112,7 @@ func (c *FakeValidatingWebhookConfigurations) DeleteCollection(options *v1.Delet // Patch applies the patch and returns the patched validatingWebhookConfiguration. func (c *FakeValidatingWebhookConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ValidatingWebhookConfiguration, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(validatingwebhookconfigurationsResource, name, data, subresources...), &v1beta1.ValidatingWebhookConfiguration{}) + Invokes(testing.NewRootPatchSubresourceAction(validatingwebhookconfigurationsResource, name, pt, data, subresources...), &v1beta1.ValidatingWebhookConfiguration{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go b/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go index fc2808da..eb38bca4 100644 --- a/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go +++ b/kubernetes/typed/apps/v1/fake/fake_controllerrevision.go @@ -119,7 +119,7 @@ func (c *FakeControllerRevisions) DeleteCollection(options *v1.DeleteOptions, li // Patch applies the patch and returns the patched controllerRevision. func (c *FakeControllerRevisions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *appsv1.ControllerRevision, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(controllerrevisionsResource, c.ns, name, data, subresources...), &appsv1.ControllerRevision{}) + Invokes(testing.NewPatchSubresourceAction(controllerrevisionsResource, c.ns, name, pt, data, subresources...), &appsv1.ControllerRevision{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1/fake/fake_daemonset.go b/kubernetes/typed/apps/v1/fake/fake_daemonset.go index 89e72ebd..c06336e9 100644 --- a/kubernetes/typed/apps/v1/fake/fake_daemonset.go +++ b/kubernetes/typed/apps/v1/fake/fake_daemonset.go @@ -131,7 +131,7 @@ func (c *FakeDaemonSets) DeleteCollection(options *v1.DeleteOptions, listOptions // Patch applies the patch and returns the patched daemonSet. func (c *FakeDaemonSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *appsv1.DaemonSet, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(daemonsetsResource, c.ns, name, data, subresources...), &appsv1.DaemonSet{}) + Invokes(testing.NewPatchSubresourceAction(daemonsetsResource, c.ns, name, pt, data, subresources...), &appsv1.DaemonSet{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1/fake/fake_deployment.go b/kubernetes/typed/apps/v1/fake/fake_deployment.go index 2fbd82d6..a5786fd5 100644 --- a/kubernetes/typed/apps/v1/fake/fake_deployment.go +++ b/kubernetes/typed/apps/v1/fake/fake_deployment.go @@ -131,7 +131,7 @@ func (c *FakeDeployments) DeleteCollection(options *v1.DeleteOptions, listOption // Patch applies the patch and returns the patched deployment. func (c *FakeDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *appsv1.Deployment, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, data, subresources...), &appsv1.Deployment{}) + Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, pt, data, subresources...), &appsv1.Deployment{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1/fake/fake_replicaset.go b/kubernetes/typed/apps/v1/fake/fake_replicaset.go index 7b882c86..d6a7c059 100644 --- a/kubernetes/typed/apps/v1/fake/fake_replicaset.go +++ b/kubernetes/typed/apps/v1/fake/fake_replicaset.go @@ -131,7 +131,7 @@ func (c *FakeReplicaSets) DeleteCollection(options *v1.DeleteOptions, listOption // Patch applies the patch and returns the patched replicaSet. func (c *FakeReplicaSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *appsv1.ReplicaSet, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(replicasetsResource, c.ns, name, data, subresources...), &appsv1.ReplicaSet{}) + Invokes(testing.NewPatchSubresourceAction(replicasetsResource, c.ns, name, pt, data, subresources...), &appsv1.ReplicaSet{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1/fake/fake_statefulset.go b/kubernetes/typed/apps/v1/fake/fake_statefulset.go index 3cd643a5..0682a999 100644 --- a/kubernetes/typed/apps/v1/fake/fake_statefulset.go +++ b/kubernetes/typed/apps/v1/fake/fake_statefulset.go @@ -131,7 +131,7 @@ func (c *FakeStatefulSets) DeleteCollection(options *v1.DeleteOptions, listOptio // Patch applies the patch and returns the patched statefulSet. func (c *FakeStatefulSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *appsv1.StatefulSet, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, data, subresources...), &appsv1.StatefulSet{}) + Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, pt, data, subresources...), &appsv1.StatefulSet{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go b/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go index 92419489..8e339d78 100644 --- a/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go +++ b/kubernetes/typed/apps/v1beta1/fake/fake_controllerrevision.go @@ -119,7 +119,7 @@ func (c *FakeControllerRevisions) DeleteCollection(options *v1.DeleteOptions, li // Patch applies the patch and returns the patched controllerRevision. func (c *FakeControllerRevisions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ControllerRevision, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(controllerrevisionsResource, c.ns, name, data, subresources...), &v1beta1.ControllerRevision{}) + Invokes(testing.NewPatchSubresourceAction(controllerrevisionsResource, c.ns, name, pt, data, subresources...), &v1beta1.ControllerRevision{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go b/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go index c4749c52..c33baba5 100644 --- a/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go +++ b/kubernetes/typed/apps/v1beta1/fake/fake_deployment.go @@ -131,7 +131,7 @@ func (c *FakeDeployments) DeleteCollection(options *v1.DeleteOptions, listOption // Patch applies the patch and returns the patched deployment. func (c *FakeDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Deployment, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, data, subresources...), &v1beta1.Deployment{}) + Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, pt, data, subresources...), &v1beta1.Deployment{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go b/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go index b0f194a7..754da5fb 100644 --- a/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go +++ b/kubernetes/typed/apps/v1beta1/fake/fake_statefulset.go @@ -131,7 +131,7 @@ func (c *FakeStatefulSets) DeleteCollection(options *v1.DeleteOptions, listOptio // Patch applies the patch and returns the patched statefulSet. func (c *FakeStatefulSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.StatefulSet, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, data, subresources...), &v1beta1.StatefulSet{}) + Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, pt, data, subresources...), &v1beta1.StatefulSet{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go b/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go index 954ac35d..197f190c 100644 --- a/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go +++ b/kubernetes/typed/apps/v1beta2/fake/fake_controllerrevision.go @@ -119,7 +119,7 @@ func (c *FakeControllerRevisions) DeleteCollection(options *v1.DeleteOptions, li // Patch applies the patch and returns the patched controllerRevision. func (c *FakeControllerRevisions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.ControllerRevision, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(controllerrevisionsResource, c.ns, name, data, subresources...), &v1beta2.ControllerRevision{}) + Invokes(testing.NewPatchSubresourceAction(controllerrevisionsResource, c.ns, name, pt, data, subresources...), &v1beta2.ControllerRevision{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go b/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go index 38a14755..b50747fd 100644 --- a/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go +++ b/kubernetes/typed/apps/v1beta2/fake/fake_daemonset.go @@ -131,7 +131,7 @@ func (c *FakeDaemonSets) DeleteCollection(options *v1.DeleteOptions, listOptions // Patch applies the patch and returns the patched daemonSet. func (c *FakeDaemonSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.DaemonSet, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(daemonsetsResource, c.ns, name, data, subresources...), &v1beta2.DaemonSet{}) + Invokes(testing.NewPatchSubresourceAction(daemonsetsResource, c.ns, name, pt, data, subresources...), &v1beta2.DaemonSet{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go b/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go index cae23224..b74d24ed 100644 --- a/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go +++ b/kubernetes/typed/apps/v1beta2/fake/fake_deployment.go @@ -131,7 +131,7 @@ func (c *FakeDeployments) DeleteCollection(options *v1.DeleteOptions, listOption // Patch applies the patch and returns the patched deployment. func (c *FakeDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.Deployment, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, data, subresources...), &v1beta2.Deployment{}) + Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, pt, data, subresources...), &v1beta2.Deployment{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go b/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go index 05fa7893..ba1de33e 100644 --- a/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go +++ b/kubernetes/typed/apps/v1beta2/fake/fake_replicaset.go @@ -131,7 +131,7 @@ func (c *FakeReplicaSets) DeleteCollection(options *v1.DeleteOptions, listOption // Patch applies the patch and returns the patched replicaSet. func (c *FakeReplicaSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.ReplicaSet, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(replicasetsResource, c.ns, name, data, subresources...), &v1beta2.ReplicaSet{}) + Invokes(testing.NewPatchSubresourceAction(replicasetsResource, c.ns, name, pt, data, subresources...), &v1beta2.ReplicaSet{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go b/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go index fe785128..652c7cbc 100644 --- a/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go +++ b/kubernetes/typed/apps/v1beta2/fake/fake_statefulset.go @@ -131,7 +131,7 @@ func (c *FakeStatefulSets) DeleteCollection(options *v1.DeleteOptions, listOptio // Patch applies the patch and returns the patched statefulSet. func (c *FakeStatefulSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta2.StatefulSet, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, data, subresources...), &v1beta2.StatefulSet{}) + Invokes(testing.NewPatchSubresourceAction(statefulsetsResource, c.ns, name, pt, data, subresources...), &v1beta2.StatefulSet{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go b/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go index 7df83437..6a4bf988 100644 --- a/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go +++ b/kubernetes/typed/autoscaling/v1/fake/fake_horizontalpodautoscaler.go @@ -131,7 +131,7 @@ func (c *FakeHorizontalPodAutoscalers) DeleteCollection(options *v1.DeleteOption // Patch applies the patch and returns the patched horizontalPodAutoscaler. func (c *FakeHorizontalPodAutoscalers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *autoscalingv1.HorizontalPodAutoscaler, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(horizontalpodautoscalersResource, c.ns, name, data, subresources...), &autoscalingv1.HorizontalPodAutoscaler{}) + Invokes(testing.NewPatchSubresourceAction(horizontalpodautoscalersResource, c.ns, name, pt, data, subresources...), &autoscalingv1.HorizontalPodAutoscaler{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go b/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go index 2d860341..514a787c 100644 --- a/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go +++ b/kubernetes/typed/autoscaling/v2beta1/fake/fake_horizontalpodautoscaler.go @@ -131,7 +131,7 @@ func (c *FakeHorizontalPodAutoscalers) DeleteCollection(options *v1.DeleteOption // Patch applies the patch and returns the patched horizontalPodAutoscaler. func (c *FakeHorizontalPodAutoscalers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2beta1.HorizontalPodAutoscaler, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(horizontalpodautoscalersResource, c.ns, name, data, subresources...), &v2beta1.HorizontalPodAutoscaler{}) + Invokes(testing.NewPatchSubresourceAction(horizontalpodautoscalersResource, c.ns, name, pt, data, subresources...), &v2beta1.HorizontalPodAutoscaler{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/autoscaling/v2beta2/fake/fake_horizontalpodautoscaler.go b/kubernetes/typed/autoscaling/v2beta2/fake/fake_horizontalpodautoscaler.go index a19b86e2..c0569f00 100644 --- a/kubernetes/typed/autoscaling/v2beta2/fake/fake_horizontalpodautoscaler.go +++ b/kubernetes/typed/autoscaling/v2beta2/fake/fake_horizontalpodautoscaler.go @@ -131,7 +131,7 @@ func (c *FakeHorizontalPodAutoscalers) DeleteCollection(options *v1.DeleteOption // Patch applies the patch and returns the patched horizontalPodAutoscaler. func (c *FakeHorizontalPodAutoscalers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2beta2.HorizontalPodAutoscaler, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(horizontalpodautoscalersResource, c.ns, name, data, subresources...), &v2beta2.HorizontalPodAutoscaler{}) + Invokes(testing.NewPatchSubresourceAction(horizontalpodautoscalersResource, c.ns, name, pt, data, subresources...), &v2beta2.HorizontalPodAutoscaler{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/batch/v1/fake/fake_job.go b/kubernetes/typed/batch/v1/fake/fake_job.go index f12619bb..06dc25c6 100644 --- a/kubernetes/typed/batch/v1/fake/fake_job.go +++ b/kubernetes/typed/batch/v1/fake/fake_job.go @@ -131,7 +131,7 @@ func (c *FakeJobs) DeleteCollection(options *v1.DeleteOptions, listOptions v1.Li // Patch applies the patch and returns the patched job. func (c *FakeJobs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *batchv1.Job, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(jobsResource, c.ns, name, data, subresources...), &batchv1.Job{}) + Invokes(testing.NewPatchSubresourceAction(jobsResource, c.ns, name, pt, data, subresources...), &batchv1.Job{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go b/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go index d80ef5e6..3985c403 100644 --- a/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go +++ b/kubernetes/typed/batch/v1beta1/fake/fake_cronjob.go @@ -131,7 +131,7 @@ func (c *FakeCronJobs) DeleteCollection(options *v1.DeleteOptions, listOptions v // Patch applies the patch and returns the patched cronJob. func (c *FakeCronJobs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CronJob, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(cronjobsResource, c.ns, name, data, subresources...), &v1beta1.CronJob{}) + Invokes(testing.NewPatchSubresourceAction(cronjobsResource, c.ns, name, pt, data, subresources...), &v1beta1.CronJob{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go b/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go index 75c0b173..2195027d 100644 --- a/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go +++ b/kubernetes/typed/batch/v2alpha1/fake/fake_cronjob.go @@ -131,7 +131,7 @@ func (c *FakeCronJobs) DeleteCollection(options *v1.DeleteOptions, listOptions v // Patch applies the patch and returns the patched cronJob. func (c *FakeCronJobs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2alpha1.CronJob, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(cronjobsResource, c.ns, name, data, subresources...), &v2alpha1.CronJob{}) + Invokes(testing.NewPatchSubresourceAction(cronjobsResource, c.ns, name, pt, data, subresources...), &v2alpha1.CronJob{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go b/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go index dfd51719..aa45c880 100644 --- a/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go +++ b/kubernetes/typed/certificates/v1beta1/fake/fake_certificatesigningrequest.go @@ -123,7 +123,7 @@ func (c *FakeCertificateSigningRequests) DeleteCollection(options *v1.DeleteOpti // Patch applies the patch and returns the patched certificateSigningRequest. func (c *FakeCertificateSigningRequests) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CertificateSigningRequest, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(certificatesigningrequestsResource, name, data, subresources...), &v1beta1.CertificateSigningRequest{}) + Invokes(testing.NewRootPatchSubresourceAction(certificatesigningrequestsResource, name, pt, data, subresources...), &v1beta1.CertificateSigningRequest{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/coordination/v1beta1/fake/fake_lease.go b/kubernetes/typed/coordination/v1beta1/fake/fake_lease.go index 3204e029..0ebf3bff 100644 --- a/kubernetes/typed/coordination/v1beta1/fake/fake_lease.go +++ b/kubernetes/typed/coordination/v1beta1/fake/fake_lease.go @@ -119,7 +119,7 @@ func (c *FakeLeases) DeleteCollection(options *v1.DeleteOptions, listOptions v1. // Patch applies the patch and returns the patched lease. func (c *FakeLeases) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Lease, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(leasesResource, c.ns, name, data, subresources...), &v1beta1.Lease{}) + Invokes(testing.NewPatchSubresourceAction(leasesResource, c.ns, name, pt, data, subresources...), &v1beta1.Lease{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_componentstatus.go b/kubernetes/typed/core/v1/fake/fake_componentstatus.go index d06023d4..18beedc2 100644 --- a/kubernetes/typed/core/v1/fake/fake_componentstatus.go +++ b/kubernetes/typed/core/v1/fake/fake_componentstatus.go @@ -112,7 +112,7 @@ func (c *FakeComponentStatuses) DeleteCollection(options *v1.DeleteOptions, list // Patch applies the patch and returns the patched componentStatus. func (c *FakeComponentStatuses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.ComponentStatus, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(componentstatusesResource, name, data, subresources...), &corev1.ComponentStatus{}) + Invokes(testing.NewRootPatchSubresourceAction(componentstatusesResource, name, pt, data, subresources...), &corev1.ComponentStatus{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/core/v1/fake/fake_configmap.go b/kubernetes/typed/core/v1/fake/fake_configmap.go index b491661f..2361ac3f 100644 --- a/kubernetes/typed/core/v1/fake/fake_configmap.go +++ b/kubernetes/typed/core/v1/fake/fake_configmap.go @@ -119,7 +119,7 @@ func (c *FakeConfigMaps) DeleteCollection(options *v1.DeleteOptions, listOptions // Patch applies the patch and returns the patched configMap. func (c *FakeConfigMaps) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.ConfigMap, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(configmapsResource, c.ns, name, data, subresources...), &corev1.ConfigMap{}) + Invokes(testing.NewPatchSubresourceAction(configmapsResource, c.ns, name, pt, data, subresources...), &corev1.ConfigMap{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_endpoints.go b/kubernetes/typed/core/v1/fake/fake_endpoints.go index 2c9f0de0..d521af40 100644 --- a/kubernetes/typed/core/v1/fake/fake_endpoints.go +++ b/kubernetes/typed/core/v1/fake/fake_endpoints.go @@ -119,7 +119,7 @@ func (c *FakeEndpoints) DeleteCollection(options *v1.DeleteOptions, listOptions // Patch applies the patch and returns the patched endpoints. func (c *FakeEndpoints) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Endpoints, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(endpointsResource, c.ns, name, data, subresources...), &corev1.Endpoints{}) + Invokes(testing.NewPatchSubresourceAction(endpointsResource, c.ns, name, pt, data, subresources...), &corev1.Endpoints{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_event.go b/kubernetes/typed/core/v1/fake/fake_event.go index 68405a54..3444f4be 100644 --- a/kubernetes/typed/core/v1/fake/fake_event.go +++ b/kubernetes/typed/core/v1/fake/fake_event.go @@ -119,7 +119,7 @@ func (c *FakeEvents) DeleteCollection(options *v1.DeleteOptions, listOptions v1. // Patch applies the patch and returns the patched event. func (c *FakeEvents) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Event, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(eventsResource, c.ns, name, data, subresources...), &corev1.Event{}) + Invokes(testing.NewPatchSubresourceAction(eventsResource, c.ns, name, pt, data, subresources...), &corev1.Event{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_event_expansion.go b/kubernetes/typed/core/v1/fake/fake_event_expansion.go index dd3fb839..4b4c90d7 100644 --- a/kubernetes/typed/core/v1/fake/fake_event_expansion.go +++ b/kubernetes/typed/core/v1/fake/fake_event_expansion.go @@ -21,6 +21,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" + types "k8s.io/apimachinery/pkg/types" core "k8s.io/client-go/testing" ) @@ -52,10 +53,13 @@ func (c *FakeEvents) UpdateWithEventNamespace(event *v1.Event) (*v1.Event, error } // PatchWithEventNamespace patches an existing event. Returns the copy of the event the server returns, or an error. +// TODO: Should take a PatchType as an argument probably. func (c *FakeEvents) PatchWithEventNamespace(event *v1.Event, data []byte) (*v1.Event, error) { - action := core.NewRootPatchAction(eventsResource, event.Name, data) + // TODO: Should be configurable to support additional patch strategies. + pt := types.StrategicMergePatchType + action := core.NewRootPatchAction(eventsResource, event.Name, pt, data) if c.ns != "" { - action = core.NewPatchAction(eventsResource, c.ns, event.Name, data) + action = core.NewPatchAction(eventsResource, c.ns, event.Name, pt, data) } obj, err := c.Fake.Invokes(action, event) if obj == nil { diff --git a/kubernetes/typed/core/v1/fake/fake_limitrange.go b/kubernetes/typed/core/v1/fake/fake_limitrange.go index 03c03c5d..d110031f 100644 --- a/kubernetes/typed/core/v1/fake/fake_limitrange.go +++ b/kubernetes/typed/core/v1/fake/fake_limitrange.go @@ -119,7 +119,7 @@ func (c *FakeLimitRanges) DeleteCollection(options *v1.DeleteOptions, listOption // Patch applies the patch and returns the patched limitRange. func (c *FakeLimitRanges) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.LimitRange, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(limitrangesResource, c.ns, name, data, subresources...), &corev1.LimitRange{}) + Invokes(testing.NewPatchSubresourceAction(limitrangesResource, c.ns, name, pt, data, subresources...), &corev1.LimitRange{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_namespace.go b/kubernetes/typed/core/v1/fake/fake_namespace.go index 12b918af..21387b5e 100644 --- a/kubernetes/typed/core/v1/fake/fake_namespace.go +++ b/kubernetes/typed/core/v1/fake/fake_namespace.go @@ -115,7 +115,7 @@ func (c *FakeNamespaces) Delete(name string, options *v1.DeleteOptions) error { // Patch applies the patch and returns the patched namespace. func (c *FakeNamespaces) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Namespace, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(namespacesResource, name, data, subresources...), &corev1.Namespace{}) + Invokes(testing.NewRootPatchSubresourceAction(namespacesResource, name, pt, data, subresources...), &corev1.Namespace{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/core/v1/fake/fake_node.go b/kubernetes/typed/core/v1/fake/fake_node.go index a2bc97b2..bcde116a 100644 --- a/kubernetes/typed/core/v1/fake/fake_node.go +++ b/kubernetes/typed/core/v1/fake/fake_node.go @@ -123,7 +123,7 @@ func (c *FakeNodes) DeleteCollection(options *v1.DeleteOptions, listOptions v1.L // Patch applies the patch and returns the patched node. func (c *FakeNodes) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Node, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(nodesResource, name, data, subresources...), &corev1.Node{}) + Invokes(testing.NewRootPatchSubresourceAction(nodesResource, name, pt, data, subresources...), &corev1.Node{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/core/v1/fake/fake_node_expansion.go b/kubernetes/typed/core/v1/fake/fake_node_expansion.go index eb684fd2..a39022c8 100644 --- a/kubernetes/typed/core/v1/fake/fake_node_expansion.go +++ b/kubernetes/typed/core/v1/fake/fake_node_expansion.go @@ -18,12 +18,16 @@ package fake import ( "k8s.io/api/core/v1" + types "k8s.io/apimachinery/pkg/types" core "k8s.io/client-go/testing" ) +// TODO: Should take a PatchType as an argument probably. func (c *FakeNodes) PatchStatus(nodeName string, data []byte) (*v1.Node, error) { + // TODO: Should be configurable to support additional patch strategies. + pt := types.StrategicMergePatchType obj, err := c.Fake.Invokes( - core.NewRootPatchSubresourceAction(nodesResource, nodeName, data, "status"), &v1.Node{}) + core.NewRootPatchSubresourceAction(nodesResource, nodeName, pt, data, "status"), &v1.Node{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/core/v1/fake/fake_persistentvolume.go b/kubernetes/typed/core/v1/fake/fake_persistentvolume.go index 71e2f2dc..843f3230 100644 --- a/kubernetes/typed/core/v1/fake/fake_persistentvolume.go +++ b/kubernetes/typed/core/v1/fake/fake_persistentvolume.go @@ -123,7 +123,7 @@ func (c *FakePersistentVolumes) DeleteCollection(options *v1.DeleteOptions, list // Patch applies the patch and returns the patched persistentVolume. func (c *FakePersistentVolumes) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.PersistentVolume, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(persistentvolumesResource, name, data, subresources...), &corev1.PersistentVolume{}) + Invokes(testing.NewRootPatchSubresourceAction(persistentvolumesResource, name, pt, data, subresources...), &corev1.PersistentVolume{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go b/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go index a06eca81..d2557c4c 100644 --- a/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go +++ b/kubernetes/typed/core/v1/fake/fake_persistentvolumeclaim.go @@ -131,7 +131,7 @@ func (c *FakePersistentVolumeClaims) DeleteCollection(options *v1.DeleteOptions, // Patch applies the patch and returns the patched persistentVolumeClaim. func (c *FakePersistentVolumeClaims) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.PersistentVolumeClaim, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(persistentvolumeclaimsResource, c.ns, name, data, subresources...), &corev1.PersistentVolumeClaim{}) + Invokes(testing.NewPatchSubresourceAction(persistentvolumeclaimsResource, c.ns, name, pt, data, subresources...), &corev1.PersistentVolumeClaim{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_pod.go b/kubernetes/typed/core/v1/fake/fake_pod.go index bbf39eaf..2dbecbba 100644 --- a/kubernetes/typed/core/v1/fake/fake_pod.go +++ b/kubernetes/typed/core/v1/fake/fake_pod.go @@ -131,7 +131,7 @@ func (c *FakePods) DeleteCollection(options *v1.DeleteOptions, listOptions v1.Li // Patch applies the patch and returns the patched pod. func (c *FakePods) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Pod, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(podsResource, c.ns, name, data, subresources...), &corev1.Pod{}) + Invokes(testing.NewPatchSubresourceAction(podsResource, c.ns, name, pt, data, subresources...), &corev1.Pod{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_podtemplate.go b/kubernetes/typed/core/v1/fake/fake_podtemplate.go index ff242f16..307f3059 100644 --- a/kubernetes/typed/core/v1/fake/fake_podtemplate.go +++ b/kubernetes/typed/core/v1/fake/fake_podtemplate.go @@ -119,7 +119,7 @@ func (c *FakePodTemplates) DeleteCollection(options *v1.DeleteOptions, listOptio // Patch applies the patch and returns the patched podTemplate. func (c *FakePodTemplates) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.PodTemplate, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(podtemplatesResource, c.ns, name, data, subresources...), &corev1.PodTemplate{}) + Invokes(testing.NewPatchSubresourceAction(podtemplatesResource, c.ns, name, pt, data, subresources...), &corev1.PodTemplate{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go b/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go index 64fde0b6..f830d7da 100644 --- a/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go +++ b/kubernetes/typed/core/v1/fake/fake_replicationcontroller.go @@ -132,7 +132,7 @@ func (c *FakeReplicationControllers) DeleteCollection(options *v1.DeleteOptions, // Patch applies the patch and returns the patched replicationController. func (c *FakeReplicationControllers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.ReplicationController, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(replicationcontrollersResource, c.ns, name, data, subresources...), &corev1.ReplicationController{}) + Invokes(testing.NewPatchSubresourceAction(replicationcontrollersResource, c.ns, name, pt, data, subresources...), &corev1.ReplicationController{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_resourcequota.go b/kubernetes/typed/core/v1/fake/fake_resourcequota.go index 069749cc..b521f712 100644 --- a/kubernetes/typed/core/v1/fake/fake_resourcequota.go +++ b/kubernetes/typed/core/v1/fake/fake_resourcequota.go @@ -131,7 +131,7 @@ func (c *FakeResourceQuotas) DeleteCollection(options *v1.DeleteOptions, listOpt // Patch applies the patch and returns the patched resourceQuota. func (c *FakeResourceQuotas) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.ResourceQuota, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(resourcequotasResource, c.ns, name, data, subresources...), &corev1.ResourceQuota{}) + Invokes(testing.NewPatchSubresourceAction(resourcequotasResource, c.ns, name, pt, data, subresources...), &corev1.ResourceQuota{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_secret.go b/kubernetes/typed/core/v1/fake/fake_secret.go index f59ba40b..47dba9ef 100644 --- a/kubernetes/typed/core/v1/fake/fake_secret.go +++ b/kubernetes/typed/core/v1/fake/fake_secret.go @@ -119,7 +119,7 @@ func (c *FakeSecrets) DeleteCollection(options *v1.DeleteOptions, listOptions v1 // Patch applies the patch and returns the patched secret. func (c *FakeSecrets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Secret, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(secretsResource, c.ns, name, data, subresources...), &corev1.Secret{}) + Invokes(testing.NewPatchSubresourceAction(secretsResource, c.ns, name, pt, data, subresources...), &corev1.Secret{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_service.go b/kubernetes/typed/core/v1/fake/fake_service.go index 2ffcdff7..a65de499 100644 --- a/kubernetes/typed/core/v1/fake/fake_service.go +++ b/kubernetes/typed/core/v1/fake/fake_service.go @@ -123,7 +123,7 @@ func (c *FakeServices) Delete(name string, options *v1.DeleteOptions) error { // Patch applies the patch and returns the patched service. func (c *FakeServices) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Service, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(servicesResource, c.ns, name, data, subresources...), &corev1.Service{}) + Invokes(testing.NewPatchSubresourceAction(servicesResource, c.ns, name, pt, data, subresources...), &corev1.Service{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/core/v1/fake/fake_serviceaccount.go b/kubernetes/typed/core/v1/fake/fake_serviceaccount.go index 2b2c5a7b..5b6d8f8b 100644 --- a/kubernetes/typed/core/v1/fake/fake_serviceaccount.go +++ b/kubernetes/typed/core/v1/fake/fake_serviceaccount.go @@ -119,7 +119,7 @@ func (c *FakeServiceAccounts) DeleteCollection(options *v1.DeleteOptions, listOp // Patch applies the patch and returns the patched serviceAccount. func (c *FakeServiceAccounts) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.ServiceAccount, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(serviceaccountsResource, c.ns, name, data, subresources...), &corev1.ServiceAccount{}) + Invokes(testing.NewPatchSubresourceAction(serviceaccountsResource, c.ns, name, pt, data, subresources...), &corev1.ServiceAccount{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/events/v1beta1/fake/fake_event.go b/kubernetes/typed/events/v1beta1/fake/fake_event.go index b210e40a..ef76ec13 100644 --- a/kubernetes/typed/events/v1beta1/fake/fake_event.go +++ b/kubernetes/typed/events/v1beta1/fake/fake_event.go @@ -119,7 +119,7 @@ func (c *FakeEvents) DeleteCollection(options *v1.DeleteOptions, listOptions v1. // Patch applies the patch and returns the patched event. func (c *FakeEvents) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Event, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(eventsResource, c.ns, name, data, subresources...), &v1beta1.Event{}) + Invokes(testing.NewPatchSubresourceAction(eventsResource, c.ns, name, pt, data, subresources...), &v1beta1.Event{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go b/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go index 3a760b31..4c986606 100644 --- a/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go +++ b/kubernetes/typed/extensions/v1beta1/fake/fake_daemonset.go @@ -131,7 +131,7 @@ func (c *FakeDaemonSets) DeleteCollection(options *v1.DeleteOptions, listOptions // Patch applies the patch and returns the patched daemonSet. func (c *FakeDaemonSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.DaemonSet, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(daemonsetsResource, c.ns, name, data, subresources...), &v1beta1.DaemonSet{}) + Invokes(testing.NewPatchSubresourceAction(daemonsetsResource, c.ns, name, pt, data, subresources...), &v1beta1.DaemonSet{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go b/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go index f032a556..7b7df45c 100644 --- a/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go +++ b/kubernetes/typed/extensions/v1beta1/fake/fake_deployment.go @@ -131,7 +131,7 @@ func (c *FakeDeployments) DeleteCollection(options *v1.DeleteOptions, listOption // Patch applies the patch and returns the patched deployment. func (c *FakeDeployments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Deployment, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, data, subresources...), &v1beta1.Deployment{}) + Invokes(testing.NewPatchSubresourceAction(deploymentsResource, c.ns, name, pt, data, subresources...), &v1beta1.Deployment{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go b/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go index 55257a88..01c25214 100644 --- a/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go +++ b/kubernetes/typed/extensions/v1beta1/fake/fake_ingress.go @@ -131,7 +131,7 @@ func (c *FakeIngresses) DeleteCollection(options *v1.DeleteOptions, listOptions // Patch applies the patch and returns the patched ingress. func (c *FakeIngresses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Ingress, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(ingressesResource, c.ns, name, data, subresources...), &v1beta1.Ingress{}) + Invokes(testing.NewPatchSubresourceAction(ingressesResource, c.ns, name, pt, data, subresources...), &v1beta1.Ingress{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go b/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go index 70b5dac2..b97a3441 100644 --- a/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go +++ b/kubernetes/typed/extensions/v1beta1/fake/fake_podsecuritypolicy.go @@ -112,7 +112,7 @@ func (c *FakePodSecurityPolicies) DeleteCollection(options *v1.DeleteOptions, li // Patch applies the patch and returns the patched podSecurityPolicy. func (c *FakePodSecurityPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PodSecurityPolicy, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(podsecuritypoliciesResource, name, data, subresources...), &v1beta1.PodSecurityPolicy{}) + Invokes(testing.NewRootPatchSubresourceAction(podsecuritypoliciesResource, name, pt, data, subresources...), &v1beta1.PodSecurityPolicy{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go b/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go index 2ab8f244..7ed16af9 100644 --- a/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go +++ b/kubernetes/typed/extensions/v1beta1/fake/fake_replicaset.go @@ -131,7 +131,7 @@ func (c *FakeReplicaSets) DeleteCollection(options *v1.DeleteOptions, listOption // Patch applies the patch and returns the patched replicaSet. func (c *FakeReplicaSets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ReplicaSet, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(replicasetsResource, c.ns, name, data, subresources...), &v1beta1.ReplicaSet{}) + Invokes(testing.NewPatchSubresourceAction(replicasetsResource, c.ns, name, pt, data, subresources...), &v1beta1.ReplicaSet{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go b/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go index 7be20229..58667c48 100644 --- a/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go +++ b/kubernetes/typed/networking/v1/fake/fake_networkpolicy.go @@ -119,7 +119,7 @@ func (c *FakeNetworkPolicies) DeleteCollection(options *v1.DeleteOptions, listOp // Patch applies the patch and returns the patched networkPolicy. func (c *FakeNetworkPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *networkingv1.NetworkPolicy, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(networkpoliciesResource, c.ns, name, data, subresources...), &networkingv1.NetworkPolicy{}) + Invokes(testing.NewPatchSubresourceAction(networkpoliciesResource, c.ns, name, pt, data, subresources...), &networkingv1.NetworkPolicy{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go b/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go index 3f2e78b3..5bfbbca4 100644 --- a/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go +++ b/kubernetes/typed/policy/v1beta1/fake/fake_poddisruptionbudget.go @@ -131,7 +131,7 @@ func (c *FakePodDisruptionBudgets) DeleteCollection(options *v1.DeleteOptions, l // Patch applies the patch and returns the patched podDisruptionBudget. func (c *FakePodDisruptionBudgets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PodDisruptionBudget, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(poddisruptionbudgetsResource, c.ns, name, data, subresources...), &v1beta1.PodDisruptionBudget{}) + Invokes(testing.NewPatchSubresourceAction(poddisruptionbudgetsResource, c.ns, name, pt, data, subresources...), &v1beta1.PodDisruptionBudget{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go b/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go index 0df9aa15..32d1989f 100644 --- a/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go +++ b/kubernetes/typed/policy/v1beta1/fake/fake_podsecuritypolicy.go @@ -112,7 +112,7 @@ func (c *FakePodSecurityPolicies) DeleteCollection(options *v1.DeleteOptions, li // Patch applies the patch and returns the patched podSecurityPolicy. func (c *FakePodSecurityPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PodSecurityPolicy, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(podsecuritypoliciesResource, name, data, subresources...), &v1beta1.PodSecurityPolicy{}) + Invokes(testing.NewRootPatchSubresourceAction(podsecuritypoliciesResource, name, pt, data, subresources...), &v1beta1.PodSecurityPolicy{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go b/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go index d93ac829..d57f3393 100644 --- a/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go +++ b/kubernetes/typed/rbac/v1/fake/fake_clusterrole.go @@ -112,7 +112,7 @@ func (c *FakeClusterRoles) DeleteCollection(options *v1.DeleteOptions, listOptio // Patch applies the patch and returns the patched clusterRole. func (c *FakeClusterRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *rbacv1.ClusterRole, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(clusterrolesResource, name, data, subresources...), &rbacv1.ClusterRole{}) + Invokes(testing.NewRootPatchSubresourceAction(clusterrolesResource, name, pt, data, subresources...), &rbacv1.ClusterRole{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go b/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go index a8b2b57f..878473ef 100644 --- a/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go +++ b/kubernetes/typed/rbac/v1/fake/fake_clusterrolebinding.go @@ -112,7 +112,7 @@ func (c *FakeClusterRoleBindings) DeleteCollection(options *v1.DeleteOptions, li // Patch applies the patch and returns the patched clusterRoleBinding. func (c *FakeClusterRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *rbacv1.ClusterRoleBinding, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(clusterrolebindingsResource, name, data, subresources...), &rbacv1.ClusterRoleBinding{}) + Invokes(testing.NewRootPatchSubresourceAction(clusterrolebindingsResource, name, pt, data, subresources...), &rbacv1.ClusterRoleBinding{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/rbac/v1/fake/fake_role.go b/kubernetes/typed/rbac/v1/fake/fake_role.go index f048bbdf..78ef3192 100644 --- a/kubernetes/typed/rbac/v1/fake/fake_role.go +++ b/kubernetes/typed/rbac/v1/fake/fake_role.go @@ -119,7 +119,7 @@ func (c *FakeRoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.L // Patch applies the patch and returns the patched role. func (c *FakeRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *rbacv1.Role, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rolesResource, c.ns, name, data, subresources...), &rbacv1.Role{}) + Invokes(testing.NewPatchSubresourceAction(rolesResource, c.ns, name, pt, data, subresources...), &rbacv1.Role{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go b/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go index c71635fc..6c344cad 100644 --- a/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go +++ b/kubernetes/typed/rbac/v1/fake/fake_rolebinding.go @@ -119,7 +119,7 @@ func (c *FakeRoleBindings) DeleteCollection(options *v1.DeleteOptions, listOptio // Patch applies the patch and returns the patched roleBinding. func (c *FakeRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *rbacv1.RoleBinding, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rolebindingsResource, c.ns, name, data, subresources...), &rbacv1.RoleBinding{}) + Invokes(testing.NewPatchSubresourceAction(rolebindingsResource, c.ns, name, pt, data, subresources...), &rbacv1.RoleBinding{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go b/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go index 13fbce4e..d2d1b1c7 100644 --- a/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go +++ b/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrole.go @@ -112,7 +112,7 @@ func (c *FakeClusterRoles) DeleteCollection(options *v1.DeleteOptions, listOptio // Patch applies the patch and returns the patched clusterRole. func (c *FakeClusterRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ClusterRole, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(clusterrolesResource, name, data, subresources...), &v1alpha1.ClusterRole{}) + Invokes(testing.NewRootPatchSubresourceAction(clusterrolesResource, name, pt, data, subresources...), &v1alpha1.ClusterRole{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go b/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go index 5076543d..3e23e5f6 100644 --- a/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go +++ b/kubernetes/typed/rbac/v1alpha1/fake/fake_clusterrolebinding.go @@ -112,7 +112,7 @@ func (c *FakeClusterRoleBindings) DeleteCollection(options *v1.DeleteOptions, li // Patch applies the patch and returns the patched clusterRoleBinding. func (c *FakeClusterRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ClusterRoleBinding, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(clusterrolebindingsResource, name, data, subresources...), &v1alpha1.ClusterRoleBinding{}) + Invokes(testing.NewRootPatchSubresourceAction(clusterrolebindingsResource, name, pt, data, subresources...), &v1alpha1.ClusterRoleBinding{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go b/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go index 24d8efee..7bd52373 100644 --- a/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go +++ b/kubernetes/typed/rbac/v1alpha1/fake/fake_role.go @@ -119,7 +119,7 @@ func (c *FakeRoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.L // Patch applies the patch and returns the patched role. func (c *FakeRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Role, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rolesResource, c.ns, name, data, subresources...), &v1alpha1.Role{}) + Invokes(testing.NewPatchSubresourceAction(rolesResource, c.ns, name, pt, data, subresources...), &v1alpha1.Role{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go b/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go index cb01ef99..01505031 100644 --- a/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go +++ b/kubernetes/typed/rbac/v1alpha1/fake/fake_rolebinding.go @@ -119,7 +119,7 @@ func (c *FakeRoleBindings) DeleteCollection(options *v1.DeleteOptions, listOptio // Patch applies the patch and returns the patched roleBinding. func (c *FakeRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.RoleBinding, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rolebindingsResource, c.ns, name, data, subresources...), &v1alpha1.RoleBinding{}) + Invokes(testing.NewPatchSubresourceAction(rolebindingsResource, c.ns, name, pt, data, subresources...), &v1alpha1.RoleBinding{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go b/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go index 62a83219..2dbc3f61 100644 --- a/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go +++ b/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrole.go @@ -112,7 +112,7 @@ func (c *FakeClusterRoles) DeleteCollection(options *v1.DeleteOptions, listOptio // Patch applies the patch and returns the patched clusterRole. func (c *FakeClusterRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ClusterRole, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(clusterrolesResource, name, data, subresources...), &v1beta1.ClusterRole{}) + Invokes(testing.NewRootPatchSubresourceAction(clusterrolesResource, name, pt, data, subresources...), &v1beta1.ClusterRole{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go b/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go index c9ab4726..14e20bc2 100644 --- a/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go +++ b/kubernetes/typed/rbac/v1beta1/fake/fake_clusterrolebinding.go @@ -112,7 +112,7 @@ func (c *FakeClusterRoleBindings) DeleteCollection(options *v1.DeleteOptions, li // Patch applies the patch and returns the patched clusterRoleBinding. func (c *FakeClusterRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.ClusterRoleBinding, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(clusterrolebindingsResource, name, data, subresources...), &v1beta1.ClusterRoleBinding{}) + Invokes(testing.NewRootPatchSubresourceAction(clusterrolebindingsResource, name, pt, data, subresources...), &v1beta1.ClusterRoleBinding{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/rbac/v1beta1/fake/fake_role.go b/kubernetes/typed/rbac/v1beta1/fake/fake_role.go index 45b07a00..e31768e4 100644 --- a/kubernetes/typed/rbac/v1beta1/fake/fake_role.go +++ b/kubernetes/typed/rbac/v1beta1/fake/fake_role.go @@ -119,7 +119,7 @@ func (c *FakeRoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.L // Patch applies the patch and returns the patched role. func (c *FakeRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Role, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rolesResource, c.ns, name, data, subresources...), &v1beta1.Role{}) + Invokes(testing.NewPatchSubresourceAction(rolesResource, c.ns, name, pt, data, subresources...), &v1beta1.Role{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go b/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go index 1efd4000..06b93c93 100644 --- a/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go +++ b/kubernetes/typed/rbac/v1beta1/fake/fake_rolebinding.go @@ -119,7 +119,7 @@ func (c *FakeRoleBindings) DeleteCollection(options *v1.DeleteOptions, listOptio // Patch applies the patch and returns the patched roleBinding. func (c *FakeRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.RoleBinding, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(rolebindingsResource, c.ns, name, data, subresources...), &v1beta1.RoleBinding{}) + Invokes(testing.NewPatchSubresourceAction(rolebindingsResource, c.ns, name, pt, data, subresources...), &v1beta1.RoleBinding{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go b/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go index 8ab4421a..e592ed13 100644 --- a/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go +++ b/kubernetes/typed/scheduling/v1alpha1/fake/fake_priorityclass.go @@ -112,7 +112,7 @@ func (c *FakePriorityClasses) DeleteCollection(options *v1.DeleteOptions, listOp // Patch applies the patch and returns the patched priorityClass. func (c *FakePriorityClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.PriorityClass, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(priorityclassesResource, name, data, subresources...), &v1alpha1.PriorityClass{}) + Invokes(testing.NewRootPatchSubresourceAction(priorityclassesResource, name, pt, data, subresources...), &v1alpha1.PriorityClass{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go b/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go index e234fec6..44ce64b5 100644 --- a/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go +++ b/kubernetes/typed/scheduling/v1beta1/fake/fake_priorityclass.go @@ -112,7 +112,7 @@ func (c *FakePriorityClasses) DeleteCollection(options *v1.DeleteOptions, listOp // Patch applies the patch and returns the patched priorityClass. func (c *FakePriorityClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PriorityClass, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(priorityclassesResource, name, data, subresources...), &v1beta1.PriorityClass{}) + Invokes(testing.NewRootPatchSubresourceAction(priorityclassesResource, name, pt, data, subresources...), &v1beta1.PriorityClass{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go b/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go index 90eaccec..273a027f 100644 --- a/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go +++ b/kubernetes/typed/settings/v1alpha1/fake/fake_podpreset.go @@ -119,7 +119,7 @@ func (c *FakePodPresets) DeleteCollection(options *v1.DeleteOptions, listOptions // Patch applies the patch and returns the patched podPreset. func (c *FakePodPresets) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.PodPreset, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(podpresetsResource, c.ns, name, data, subresources...), &v1alpha1.PodPreset{}) + Invokes(testing.NewPatchSubresourceAction(podpresetsResource, c.ns, name, pt, data, subresources...), &v1alpha1.PodPreset{}) if obj == nil { return nil, err diff --git a/kubernetes/typed/storage/v1/fake/fake_storageclass.go b/kubernetes/typed/storage/v1/fake/fake_storageclass.go index 37488a2d..c7531d87 100644 --- a/kubernetes/typed/storage/v1/fake/fake_storageclass.go +++ b/kubernetes/typed/storage/v1/fake/fake_storageclass.go @@ -112,7 +112,7 @@ func (c *FakeStorageClasses) DeleteCollection(options *v1.DeleteOptions, listOpt // Patch applies the patch and returns the patched storageClass. func (c *FakeStorageClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *storagev1.StorageClass, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(storageclassesResource, name, data, subresources...), &storagev1.StorageClass{}) + Invokes(testing.NewRootPatchSubresourceAction(storageclassesResource, name, pt, data, subresources...), &storagev1.StorageClass{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go b/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go index af04b681..86f53e2d 100644 --- a/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go +++ b/kubernetes/typed/storage/v1alpha1/fake/fake_volumeattachment.go @@ -123,7 +123,7 @@ func (c *FakeVolumeAttachments) DeleteCollection(options *v1.DeleteOptions, list // Patch applies the patch and returns the patched volumeAttachment. func (c *FakeVolumeAttachments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.VolumeAttachment, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(volumeattachmentsResource, name, data, subresources...), &v1alpha1.VolumeAttachment{}) + Invokes(testing.NewRootPatchSubresourceAction(volumeattachmentsResource, name, pt, data, subresources...), &v1alpha1.VolumeAttachment{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go b/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go index cbfbab1a..9fc8ca99 100644 --- a/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go +++ b/kubernetes/typed/storage/v1beta1/fake/fake_storageclass.go @@ -112,7 +112,7 @@ func (c *FakeStorageClasses) DeleteCollection(options *v1.DeleteOptions, listOpt // Patch applies the patch and returns the patched storageClass. func (c *FakeStorageClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.StorageClass, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(storageclassesResource, name, data, subresources...), &v1beta1.StorageClass{}) + Invokes(testing.NewRootPatchSubresourceAction(storageclassesResource, name, pt, data, subresources...), &v1beta1.StorageClass{}) if obj == nil { return nil, err } diff --git a/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go b/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go index 04c0c463..043098f4 100644 --- a/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go +++ b/kubernetes/typed/storage/v1beta1/fake/fake_volumeattachment.go @@ -123,7 +123,7 @@ func (c *FakeVolumeAttachments) DeleteCollection(options *v1.DeleteOptions, list // Patch applies the patch and returns the patched volumeAttachment. func (c *FakeVolumeAttachments) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.VolumeAttachment, err error) { obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(volumeattachmentsResource, name, data, subresources...), &v1beta1.VolumeAttachment{}) + Invokes(testing.NewRootPatchSubresourceAction(volumeattachmentsResource, name, pt, data, subresources...), &v1beta1.VolumeAttachment{}) if obj == nil { return nil, err } diff --git a/testing/actions.go b/testing/actions.go index b99f231c..e6db578e 100644 --- a/testing/actions.go +++ b/testing/actions.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" ) func NewRootGetAction(resource schema.GroupVersionResource, name string) GetActionImpl { @@ -152,45 +153,49 @@ func NewUpdateAction(resource schema.GroupVersionResource, namespace string, obj return action } -func NewRootPatchAction(resource schema.GroupVersionResource, name string, patch []byte) PatchActionImpl { +func NewRootPatchAction(resource schema.GroupVersionResource, name string, pt types.PatchType, patch []byte) PatchActionImpl { action := PatchActionImpl{} action.Verb = "patch" action.Resource = resource action.Name = name + action.PatchType = pt action.Patch = patch return action } -func NewPatchAction(resource schema.GroupVersionResource, namespace string, name string, patch []byte) PatchActionImpl { +func NewPatchAction(resource schema.GroupVersionResource, namespace string, name string, pt types.PatchType, patch []byte) PatchActionImpl { action := PatchActionImpl{} action.Verb = "patch" action.Resource = resource action.Namespace = namespace action.Name = name + action.PatchType = pt action.Patch = patch return action } -func NewRootPatchSubresourceAction(resource schema.GroupVersionResource, name string, patch []byte, subresources ...string) PatchActionImpl { +func NewRootPatchSubresourceAction(resource schema.GroupVersionResource, name string, pt types.PatchType, patch []byte, subresources ...string) PatchActionImpl { action := PatchActionImpl{} action.Verb = "patch" action.Resource = resource action.Subresource = path.Join(subresources...) action.Name = name + action.PatchType = pt action.Patch = patch return action } -func NewPatchSubresourceAction(resource schema.GroupVersionResource, namespace, name string, patch []byte, subresources ...string) PatchActionImpl { +func NewPatchSubresourceAction(resource schema.GroupVersionResource, namespace, name string, pt types.PatchType, patch []byte, subresources ...string) PatchActionImpl { action := PatchActionImpl{} action.Verb = "patch" action.Resource = resource action.Subresource = path.Join(subresources...) action.Namespace = namespace action.Name = name + action.PatchType = pt action.Patch = patch return action @@ -396,6 +401,7 @@ type DeleteCollectionAction interface { type PatchAction interface { Action GetName() string + GetPatchType() types.PatchType GetPatch() []byte } @@ -537,8 +543,9 @@ func (a UpdateActionImpl) DeepCopy() Action { type PatchActionImpl struct { ActionImpl - Name string - Patch []byte + Name string + PatchType types.PatchType + Patch []byte } func (a PatchActionImpl) GetName() string { @@ -549,12 +556,17 @@ func (a PatchActionImpl) GetPatch() []byte { return a.Patch } +func (a PatchActionImpl) GetPatchType() types.PatchType { + return a.PatchType +} + func (a PatchActionImpl) DeepCopy() Action { patch := make([]byte, len(a.Patch)) copy(patch, a.Patch) return PatchActionImpl{ ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), Name: a.Name, + PatchType: a.PatchType, Patch: patch, } } diff --git a/testing/fixture.go b/testing/fixture.go index 00c4c49f..90f16f56 100644 --- a/testing/fixture.go +++ b/testing/fixture.go @@ -20,11 +20,13 @@ import ( "fmt" "sync" + "github.com/evanphx/json-patch" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/watch" @@ -137,15 +139,30 @@ func ObjectReaction(tracker ObjectTracker) ReactionFunc { if err != nil { return true, nil, err } - // Only supports strategic merge patch - // TODO: Add support for other Patch types - mergedByte, err := strategicpatch.StrategicMergePatch(old, action.GetPatch(), obj) - if err != nil { - return true, nil, err - } - - if err = json.Unmarshal(mergedByte, obj); err != nil { - return true, nil, err + // Only supports strategic merge patch and JSONPatch as coded. + switch action.GetPatchType() { + case types.JSONPatchType: + patch, err := jsonpatch.DecodePatch(action.GetPatch()) + if err != nil { + return true, nil, err + } + modified, err := patch.Apply(old) + if err != nil { + return true, nil, err + } + if err = json.Unmarshal(modified, obj); err != nil { + return true, nil, err + } + case types.StrategicMergePatchType: + mergedByte, err := strategicpatch.StrategicMergePatch(old, action.GetPatch(), obj) + if err != nil { + return true, nil, err + } + if err = json.Unmarshal(mergedByte, obj); err != nil { + return true, nil, err + } + default: + return true, nil, fmt.Errorf("PatchType is not supported") } if err = tracker.Update(gvr, obj, ns); err != nil { diff --git a/vendor/github.com/evanphx/json-patch/.travis.yml b/vendor/github.com/evanphx/json-patch/.travis.yml new file mode 100644 index 00000000..2092c72c --- /dev/null +++ b/vendor/github.com/evanphx/json-patch/.travis.yml @@ -0,0 +1,16 @@ +language: go + +go: + - 1.8 + - 1.7 + +install: + - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi + - go get github.com/jessevdk/go-flags + +script: + - go get + - go test -cover ./... + +notifications: + email: false diff --git a/vendor/github.com/evanphx/json-patch/LICENSE b/vendor/github.com/evanphx/json-patch/LICENSE new file mode 100644 index 00000000..0eb9b72d --- /dev/null +++ b/vendor/github.com/evanphx/json-patch/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2014, Evan Phoenix +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of the Evan Phoenix nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/evanphx/json-patch/README.md b/vendor/github.com/evanphx/json-patch/README.md new file mode 100644 index 00000000..13b90420 --- /dev/null +++ b/vendor/github.com/evanphx/json-patch/README.md @@ -0,0 +1,284 @@ +# JSON-Patch +`jsonpatch` is a library which provides functionallity for both applying +[RFC6902 JSON patches](http://tools.ietf.org/html/rfc6902) against documents, as +well as for calculating & applying [RFC7396 JSON merge patches](https://tools.ietf.org/html/rfc7396). + +[![GoDoc](https://godoc.org/github.com/evanphx/json-patch?status.svg)](http://godoc.org/github.com/evanphx/json-patch) +[![Build Status](https://travis-ci.org/evanphx/json-patch.svg?branch=master)](https://travis-ci.org/evanphx/json-patch) +[![Report Card](https://goreportcard.com/badge/github.com/evanphx/json-patch)](https://goreportcard.com/report/github.com/evanphx/json-patch) + +# Get It! + +**Latest and greatest**: +```bash +go get -u github.com/evanphx/json-patch +``` + +**Stable Versions**: +* Version 4: `go get -u gopkg.in/evanphx/json-patch.v4` + +(previous versions below `v3` are unavailable) + +# Use It! +* [Create and apply a merge patch](#create-and-apply-a-merge-patch) +* [Create and apply a JSON Patch](#create-and-apply-a-json-patch) +* [Comparing JSON documents](#comparing-json-documents) +* [Combine merge patches](#combine-merge-patches) + +## Create and apply a merge patch +Given both an original JSON document and a modified JSON document, you can create +a [Merge Patch](https://tools.ietf.org/html/rfc7396) document. + +It can describe the changes needed to convert from the original to the +modified JSON document. + +Once you have a merge patch, you can apply it to other JSON documents using the +`jsonpatch.MergePatch(document, patch)` function. + +```go +package main + +import ( + "fmt" + + jsonpatch "github.com/evanphx/json-patch" +) + +func main() { + // Let's create a merge patch from these two documents... + original := []byte(`{"name": "John", "age": 24, "height": 3.21}`) + target := []byte(`{"name": "Jane", "age": 24}`) + + patch, err := jsonpatch.CreateMergePatch(original, target) + if err != nil { + panic(err) + } + + // Now lets apply the patch against a different JSON document... + + alternative := []byte(`{"name": "Tina", "age": 28, "height": 3.75}`) + modifiedAlternative, err := jsonpatch.MergePatch(alternative, patch) + + fmt.Printf("patch document: %s\n", patch) + fmt.Printf("updated alternative doc: %s\n", modifiedAlternative) +} +``` + +When ran, you get the following output: + +```bash +$ go run main.go +patch document: {"height":null,"name":"Jane"} +updated tina doc: {"age":28,"name":"Jane"} +``` + +## Create and apply a JSON Patch +You can create patch objects using `DecodePatch([]byte)`, which can then +be applied against JSON documents. + +The following is an example of creating a patch from two operations, and +applying it against a JSON document. + +```go +package main + +import ( + "fmt" + + jsonpatch "github.com/evanphx/json-patch" +) + +func main() { + original := []byte(`{"name": "John", "age": 24, "height": 3.21}`) + patchJSON := []byte(`[ + {"op": "replace", "path": "/name", "value": "Jane"}, + {"op": "remove", "path": "/height"} + ]`) + + patch, err := jsonpatch.DecodePatch(patchJSON) + if err != nil { + panic(err) + } + + modified, err := patch.Apply(original) + if err != nil { + panic(err) + } + + fmt.Printf("Original document: %s\n", original) + fmt.Printf("Modified document: %s\n", modified) +} +``` + +When ran, you get the following output: + +```bash +$ go run main.go +Original document: {"name": "John", "age": 24, "height": 3.21} +Modified document: {"age":24,"name":"Jane"} +``` + +## Comparing JSON documents +Due to potential whitespace and ordering differences, one cannot simply compare +JSON strings or byte-arrays directly. + +As such, you can instead use `jsonpatch.Equal(document1, document2)` to +determine if two JSON documents are _structurally_ equal. This ignores +whitespace differences, and key-value ordering. + +```go +package main + +import ( + "fmt" + + jsonpatch "github.com/evanphx/json-patch" +) + +func main() { + original := []byte(`{"name": "John", "age": 24, "height": 3.21}`) + similar := []byte(` + { + "age": 24, + "height": 3.21, + "name": "John" + } + `) + different := []byte(`{"name": "Jane", "age": 20, "height": 3.37}`) + + if jsonpatch.Equal(original, similar) { + fmt.Println(`"original" is structurally equal to "similar"`) + } + + if !jsonpatch.Equal(original, different) { + fmt.Println(`"original" is _not_ structurally equal to "similar"`) + } +} +``` + +When ran, you get the following output: +```bash +$ go run main.go +"original" is structurally equal to "similar" +"original" is _not_ structurally equal to "similar" +``` + +## Combine merge patches +Given two JSON merge patch documents, it is possible to combine them into a +single merge patch which can describe both set of changes. + +The resulting merge patch can be used such that applying it results in a +document structurally similar as merging each merge patch to the document +in succession. + +```go +package main + +import ( + "fmt" + + jsonpatch "github.com/evanphx/json-patch" +) + +func main() { + original := []byte(`{"name": "John", "age": 24, "height": 3.21}`) + + nameAndHeight := []byte(`{"height":null,"name":"Jane"}`) + ageAndEyes := []byte(`{"age":4.23,"eyes":"blue"}`) + + // Let's combine these merge patch documents... + combinedPatch, err := jsonpatch.MergeMergePatches(nameAndHeight, ageAndEyes) + if err != nil { + panic(err) + } + + // Apply each patch individual against the original document + withoutCombinedPatch, err := jsonpatch.MergePatch(original, nameAndHeight) + if err != nil { + panic(err) + } + + withoutCombinedPatch, err = jsonpatch.MergePatch(withoutCombinedPatch, ageAndEyes) + if err != nil { + panic(err) + } + + // Apply the combined patch against the original document + + withCombinedPatch, err := jsonpatch.MergePatch(original, combinedPatch) + if err != nil { + panic(err) + } + + // Do both result in the same thing? They should! + if jsonpatch.Equal(withCombinedPatch, withoutCombinedPatch) { + fmt.Println("Both JSON documents are structurally the same!") + } + + fmt.Printf("combined merge patch: %s", combinedPatch) +} +``` + +When ran, you get the following output: +```bash +$ go run main.go +Both JSON documents are structurally the same! +combined merge patch: {"age":4.23,"eyes":"blue","height":null,"name":"Jane"} +``` + +# CLI for comparing JSON documents +You can install the commandline program `json-patch`. + +This program can take multiple JSON patch documents as arguments, +and fed a JSON document from `stdin`. It will apply the patch(es) against +the document and output the modified doc. + +**patch.1.json** +```json +[ + {"op": "replace", "path": "/name", "value": "Jane"}, + {"op": "remove", "path": "/height"} +] +``` + +**patch.2.json** +```json +[ + {"op": "add", "path": "/address", "value": "123 Main St"}, + {"op": "replace", "path": "/age", "value": "21"} +] +``` + +**document.json** +```json +{ + "name": "John", + "age": 24, + "height": 3.21 +} +``` + +You can then run: + +```bash +$ go install github.com/evanphx/json-patch/cmd/json-patch +$ cat document.json | json-patch -p patch.1.json -p patch.2.json +{"address":"123 Main St","age":"21","name":"Jane"} +``` + +# Help It! +Contributions are welcomed! Leave [an issue](https://github.com/evanphx/json-patch/issues) +or [create a PR](https://github.com/evanphx/json-patch/compare). + + +Before creating a pull request, we'd ask that you make sure tests are passing +and that you have added new tests when applicable. + +Contributors can run tests using: + +```bash +go test -cover ./... +``` + +Builds for pull requests are tested automatically +using [TravisCI](https://travis-ci.org/evanphx/json-patch). diff --git a/vendor/github.com/evanphx/json-patch/merge.go b/vendor/github.com/evanphx/json-patch/merge.go new file mode 100644 index 00000000..6806c4c2 --- /dev/null +++ b/vendor/github.com/evanphx/json-patch/merge.go @@ -0,0 +1,383 @@ +package jsonpatch + +import ( + "bytes" + "encoding/json" + "fmt" + "reflect" +) + +func merge(cur, patch *lazyNode, mergeMerge bool) *lazyNode { + curDoc, err := cur.intoDoc() + + if err != nil { + pruneNulls(patch) + return patch + } + + patchDoc, err := patch.intoDoc() + + if err != nil { + return patch + } + + mergeDocs(curDoc, patchDoc, mergeMerge) + + return cur +} + +func mergeDocs(doc, patch *partialDoc, mergeMerge bool) { + for k, v := range *patch { + if v == nil { + if mergeMerge { + (*doc)[k] = nil + } else { + delete(*doc, k) + } + } else { + cur, ok := (*doc)[k] + + if !ok || cur == nil { + pruneNulls(v) + (*doc)[k] = v + } else { + (*doc)[k] = merge(cur, v, mergeMerge) + } + } + } +} + +func pruneNulls(n *lazyNode) { + sub, err := n.intoDoc() + + if err == nil { + pruneDocNulls(sub) + } else { + ary, err := n.intoAry() + + if err == nil { + pruneAryNulls(ary) + } + } +} + +func pruneDocNulls(doc *partialDoc) *partialDoc { + for k, v := range *doc { + if v == nil { + delete(*doc, k) + } else { + pruneNulls(v) + } + } + + return doc +} + +func pruneAryNulls(ary *partialArray) *partialArray { + newAry := []*lazyNode{} + + for _, v := range *ary { + if v != nil { + pruneNulls(v) + newAry = append(newAry, v) + } + } + + *ary = newAry + + return ary +} + +var errBadJSONDoc = fmt.Errorf("Invalid JSON Document") +var errBadJSONPatch = fmt.Errorf("Invalid JSON Patch") +var errBadMergeTypes = fmt.Errorf("Mismatched JSON Documents") + +// MergeMergePatches merges two merge patches together, such that +// applying this resulting merged merge patch to a document yields the same +// as merging each merge patch to the document in succession. +func MergeMergePatches(patch1Data, patch2Data []byte) ([]byte, error) { + return doMergePatch(patch1Data, patch2Data, true) +} + +// MergePatch merges the patchData into the docData. +func MergePatch(docData, patchData []byte) ([]byte, error) { + return doMergePatch(docData, patchData, false) +} + +func doMergePatch(docData, patchData []byte, mergeMerge bool) ([]byte, error) { + doc := &partialDoc{} + + docErr := json.Unmarshal(docData, doc) + + patch := &partialDoc{} + + patchErr := json.Unmarshal(patchData, patch) + + if _, ok := docErr.(*json.SyntaxError); ok { + return nil, errBadJSONDoc + } + + if _, ok := patchErr.(*json.SyntaxError); ok { + return nil, errBadJSONPatch + } + + if docErr == nil && *doc == nil { + return nil, errBadJSONDoc + } + + if patchErr == nil && *patch == nil { + return nil, errBadJSONPatch + } + + if docErr != nil || patchErr != nil { + // Not an error, just not a doc, so we turn straight into the patch + if patchErr == nil { + if mergeMerge { + doc = patch + } else { + doc = pruneDocNulls(patch) + } + } else { + patchAry := &partialArray{} + patchErr = json.Unmarshal(patchData, patchAry) + + if patchErr != nil { + return nil, errBadJSONPatch + } + + pruneAryNulls(patchAry) + + out, patchErr := json.Marshal(patchAry) + + if patchErr != nil { + return nil, errBadJSONPatch + } + + return out, nil + } + } else { + mergeDocs(doc, patch, mergeMerge) + } + + return json.Marshal(doc) +} + +// resemblesJSONArray indicates whether the byte-slice "appears" to be +// a JSON array or not. +// False-positives are possible, as this function does not check the internal +// structure of the array. It only checks that the outer syntax is present and +// correct. +func resemblesJSONArray(input []byte) bool { + input = bytes.TrimSpace(input) + + hasPrefix := bytes.HasPrefix(input, []byte("[")) + hasSuffix := bytes.HasSuffix(input, []byte("]")) + + return hasPrefix && hasSuffix +} + +// CreateMergePatch will return a merge patch document capable of converting +// the original document(s) to the modified document(s). +// The parameters can be bytes of either two JSON Documents, or two arrays of +// JSON documents. +// The merge patch returned follows the specification defined at http://tools.ietf.org/html/draft-ietf-appsawg-json-merge-patch-07 +func CreateMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) { + originalResemblesArray := resemblesJSONArray(originalJSON) + modifiedResemblesArray := resemblesJSONArray(modifiedJSON) + + // Do both byte-slices seem like JSON arrays? + if originalResemblesArray && modifiedResemblesArray { + return createArrayMergePatch(originalJSON, modifiedJSON) + } + + // Are both byte-slices are not arrays? Then they are likely JSON objects... + if !originalResemblesArray && !modifiedResemblesArray { + return createObjectMergePatch(originalJSON, modifiedJSON) + } + + // None of the above? Then return an error because of mismatched types. + return nil, errBadMergeTypes +} + +// createObjectMergePatch will return a merge-patch document capable of +// converting the original document to the modified document. +func createObjectMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) { + originalDoc := map[string]interface{}{} + modifiedDoc := map[string]interface{}{} + + err := json.Unmarshal(originalJSON, &originalDoc) + if err != nil { + return nil, errBadJSONDoc + } + + err = json.Unmarshal(modifiedJSON, &modifiedDoc) + if err != nil { + return nil, errBadJSONDoc + } + + dest, err := getDiff(originalDoc, modifiedDoc) + if err != nil { + return nil, err + } + + return json.Marshal(dest) +} + +// createArrayMergePatch will return an array of merge-patch documents capable +// of converting the original document to the modified document for each +// pair of JSON documents provided in the arrays. +// Arrays of mismatched sizes will result in an error. +func createArrayMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) { + originalDocs := []json.RawMessage{} + modifiedDocs := []json.RawMessage{} + + err := json.Unmarshal(originalJSON, &originalDocs) + if err != nil { + return nil, errBadJSONDoc + } + + err = json.Unmarshal(modifiedJSON, &modifiedDocs) + if err != nil { + return nil, errBadJSONDoc + } + + total := len(originalDocs) + if len(modifiedDocs) != total { + return nil, errBadJSONDoc + } + + result := []json.RawMessage{} + for i := 0; i < len(originalDocs); i++ { + original := originalDocs[i] + modified := modifiedDocs[i] + + patch, err := createObjectMergePatch(original, modified) + if err != nil { + return nil, err + } + + result = append(result, json.RawMessage(patch)) + } + + return json.Marshal(result) +} + +// Returns true if the array matches (must be json types). +// As is idiomatic for go, an empty array is not the same as a nil array. +func matchesArray(a, b []interface{}) bool { + if len(a) != len(b) { + return false + } + if (a == nil && b != nil) || (a != nil && b == nil) { + return false + } + for i := range a { + if !matchesValue(a[i], b[i]) { + return false + } + } + return true +} + +// Returns true if the values matches (must be json types) +// The types of the values must match, otherwise it will always return false +// If two map[string]interface{} are given, all elements must match. +func matchesValue(av, bv interface{}) bool { + if reflect.TypeOf(av) != reflect.TypeOf(bv) { + return false + } + switch at := av.(type) { + case string: + bt := bv.(string) + if bt == at { + return true + } + case float64: + bt := bv.(float64) + if bt == at { + return true + } + case bool: + bt := bv.(bool) + if bt == at { + return true + } + case nil: + // Both nil, fine. + return true + case map[string]interface{}: + bt := bv.(map[string]interface{}) + for key := range at { + if !matchesValue(at[key], bt[key]) { + return false + } + } + for key := range bt { + if !matchesValue(at[key], bt[key]) { + return false + } + } + return true + case []interface{}: + bt := bv.([]interface{}) + return matchesArray(at, bt) + } + return false +} + +// getDiff returns the (recursive) difference between a and b as a map[string]interface{}. +func getDiff(a, b map[string]interface{}) (map[string]interface{}, error) { + into := map[string]interface{}{} + for key, bv := range b { + av, ok := a[key] + // value was added + if !ok { + into[key] = bv + continue + } + // If types have changed, replace completely + if reflect.TypeOf(av) != reflect.TypeOf(bv) { + into[key] = bv + continue + } + // Types are the same, compare values + switch at := av.(type) { + case map[string]interface{}: + bt := bv.(map[string]interface{}) + dst := make(map[string]interface{}, len(bt)) + dst, err := getDiff(at, bt) + if err != nil { + return nil, err + } + if len(dst) > 0 { + into[key] = dst + } + case string, float64, bool: + if !matchesValue(av, bv) { + into[key] = bv + } + case []interface{}: + bt := bv.([]interface{}) + if !matchesArray(at, bt) { + into[key] = bv + } + case nil: + switch bv.(type) { + case nil: + // Both nil, fine. + default: + into[key] = bv + } + default: + panic(fmt.Sprintf("Unknown type:%T in key %s", av, key)) + } + } + // Now add all deleted values as nil + for key := range a { + _, found := b[key] + if !found { + into[key] = nil + } + } + return into, nil +} diff --git a/vendor/github.com/evanphx/json-patch/patch.go b/vendor/github.com/evanphx/json-patch/patch.go new file mode 100644 index 00000000..3d76e9e3 --- /dev/null +++ b/vendor/github.com/evanphx/json-patch/patch.go @@ -0,0 +1,666 @@ +package jsonpatch + +import ( + "bytes" + "encoding/json" + "fmt" + "strconv" + "strings" +) + +const ( + eRaw = iota + eDoc + eAry +) + +type lazyNode struct { + raw *json.RawMessage + doc partialDoc + ary partialArray + which int +} + +type operation map[string]*json.RawMessage + +// Patch is an ordered collection of operations. +type Patch []operation + +type partialDoc map[string]*lazyNode +type partialArray []*lazyNode + +type container interface { + get(key string) (*lazyNode, error) + set(key string, val *lazyNode) error + add(key string, val *lazyNode) error + remove(key string) error +} + +func newLazyNode(raw *json.RawMessage) *lazyNode { + return &lazyNode{raw: raw, doc: nil, ary: nil, which: eRaw} +} + +func (n *lazyNode) MarshalJSON() ([]byte, error) { + switch n.which { + case eRaw: + return json.Marshal(n.raw) + case eDoc: + return json.Marshal(n.doc) + case eAry: + return json.Marshal(n.ary) + default: + return nil, fmt.Errorf("Unknown type") + } +} + +func (n *lazyNode) UnmarshalJSON(data []byte) error { + dest := make(json.RawMessage, len(data)) + copy(dest, data) + n.raw = &dest + n.which = eRaw + return nil +} + +func (n *lazyNode) intoDoc() (*partialDoc, error) { + if n.which == eDoc { + return &n.doc, nil + } + + if n.raw == nil { + return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial document") + } + + err := json.Unmarshal(*n.raw, &n.doc) + + if err != nil { + return nil, err + } + + n.which = eDoc + return &n.doc, nil +} + +func (n *lazyNode) intoAry() (*partialArray, error) { + if n.which == eAry { + return &n.ary, nil + } + + if n.raw == nil { + return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial array") + } + + err := json.Unmarshal(*n.raw, &n.ary) + + if err != nil { + return nil, err + } + + n.which = eAry + return &n.ary, nil +} + +func (n *lazyNode) compact() []byte { + buf := &bytes.Buffer{} + + if n.raw == nil { + return nil + } + + err := json.Compact(buf, *n.raw) + + if err != nil { + return *n.raw + } + + return buf.Bytes() +} + +func (n *lazyNode) tryDoc() bool { + if n.raw == nil { + return false + } + + err := json.Unmarshal(*n.raw, &n.doc) + + if err != nil { + return false + } + + n.which = eDoc + return true +} + +func (n *lazyNode) tryAry() bool { + if n.raw == nil { + return false + } + + err := json.Unmarshal(*n.raw, &n.ary) + + if err != nil { + return false + } + + n.which = eAry + return true +} + +func (n *lazyNode) equal(o *lazyNode) bool { + if n.which == eRaw { + if !n.tryDoc() && !n.tryAry() { + if o.which != eRaw { + return false + } + + return bytes.Equal(n.compact(), o.compact()) + } + } + + if n.which == eDoc { + if o.which == eRaw { + if !o.tryDoc() { + return false + } + } + + if o.which != eDoc { + return false + } + + for k, v := range n.doc { + ov, ok := o.doc[k] + + if !ok { + return false + } + + if v == nil && ov == nil { + continue + } + + if !v.equal(ov) { + return false + } + } + + return true + } + + if o.which != eAry && !o.tryAry() { + return false + } + + if len(n.ary) != len(o.ary) { + return false + } + + for idx, val := range n.ary { + if !val.equal(o.ary[idx]) { + return false + } + } + + return true +} + +func (o operation) kind() string { + if obj, ok := o["op"]; ok && obj != nil { + var op string + + err := json.Unmarshal(*obj, &op) + + if err != nil { + return "unknown" + } + + return op + } + + return "unknown" +} + +func (o operation) path() string { + if obj, ok := o["path"]; ok && obj != nil { + var op string + + err := json.Unmarshal(*obj, &op) + + if err != nil { + return "unknown" + } + + return op + } + + return "unknown" +} + +func (o operation) from() string { + if obj, ok := o["from"]; ok && obj != nil { + var op string + + err := json.Unmarshal(*obj, &op) + + if err != nil { + return "unknown" + } + + return op + } + + return "unknown" +} + +func (o operation) value() *lazyNode { + if obj, ok := o["value"]; ok { + return newLazyNode(obj) + } + + return nil +} + +func isArray(buf []byte) bool { +Loop: + for _, c := range buf { + switch c { + case ' ': + case '\n': + case '\t': + continue + case '[': + return true + default: + break Loop + } + } + + return false +} + +func findObject(pd *container, path string) (container, string) { + doc := *pd + + split := strings.Split(path, "/") + + if len(split) < 2 { + return nil, "" + } + + parts := split[1 : len(split)-1] + + key := split[len(split)-1] + + var err error + + for _, part := range parts { + + next, ok := doc.get(decodePatchKey(part)) + + if next == nil || ok != nil { + return nil, "" + } + + if isArray(*next.raw) { + doc, err = next.intoAry() + + if err != nil { + return nil, "" + } + } else { + doc, err = next.intoDoc() + + if err != nil { + return nil, "" + } + } + } + + return doc, decodePatchKey(key) +} + +func (d *partialDoc) set(key string, val *lazyNode) error { + (*d)[key] = val + return nil +} + +func (d *partialDoc) add(key string, val *lazyNode) error { + (*d)[key] = val + return nil +} + +func (d *partialDoc) get(key string) (*lazyNode, error) { + return (*d)[key], nil +} + +func (d *partialDoc) remove(key string) error { + _, ok := (*d)[key] + if !ok { + return fmt.Errorf("Unable to remove nonexistent key: %s", key) + } + + delete(*d, key) + return nil +} + +func (d *partialArray) set(key string, val *lazyNode) error { + if key == "-" { + *d = append(*d, val) + return nil + } + + idx, err := strconv.Atoi(key) + if err != nil { + return err + } + + sz := len(*d) + if idx+1 > sz { + sz = idx + 1 + } + + ary := make([]*lazyNode, sz) + + cur := *d + + copy(ary, cur) + + if idx >= len(ary) { + return fmt.Errorf("Unable to access invalid index: %d", idx) + } + + ary[idx] = val + + *d = ary + return nil +} + +func (d *partialArray) add(key string, val *lazyNode) error { + if key == "-" { + *d = append(*d, val) + return nil + } + + idx, err := strconv.Atoi(key) + if err != nil { + return err + } + + ary := make([]*lazyNode, len(*d)+1) + + cur := *d + + if idx < -len(ary) || idx >= len(ary) { + return fmt.Errorf("Unable to access invalid index: %d", idx) + } + + if idx < 0 { + idx += len(ary) + } + copy(ary[0:idx], cur[0:idx]) + ary[idx] = val + copy(ary[idx+1:], cur[idx:]) + + *d = ary + return nil +} + +func (d *partialArray) get(key string) (*lazyNode, error) { + idx, err := strconv.Atoi(key) + + if err != nil { + return nil, err + } + + if idx >= len(*d) { + return nil, fmt.Errorf("Unable to access invalid index: %d", idx) + } + + return (*d)[idx], nil +} + +func (d *partialArray) remove(key string) error { + idx, err := strconv.Atoi(key) + if err != nil { + return err + } + + cur := *d + + if idx < -len(cur) || idx >= len(cur) { + return fmt.Errorf("Unable to remove invalid index: %d", idx) + } + if idx < 0 { + idx += len(cur) + } + + ary := make([]*lazyNode, len(cur)-1) + + copy(ary[0:idx], cur[0:idx]) + copy(ary[idx:], cur[idx+1:]) + + *d = ary + return nil + +} + +func (p Patch) add(doc *container, op operation) error { + path := op.path() + + con, key := findObject(doc, path) + + if con == nil { + return fmt.Errorf("jsonpatch add operation does not apply: doc is missing path: \"%s\"", path) + } + + return con.add(key, op.value()) +} + +func (p Patch) remove(doc *container, op operation) error { + path := op.path() + + con, key := findObject(doc, path) + + if con == nil { + return fmt.Errorf("jsonpatch remove operation does not apply: doc is missing path: \"%s\"", path) + } + + return con.remove(key) +} + +func (p Patch) replace(doc *container, op operation) error { + path := op.path() + + con, key := findObject(doc, path) + + if con == nil { + return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing path: %s", path) + } + + _, ok := con.get(key) + if ok != nil { + return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing key: %s", path) + } + + return con.set(key, op.value()) +} + +func (p Patch) move(doc *container, op operation) error { + from := op.from() + + con, key := findObject(doc, from) + + if con == nil { + return fmt.Errorf("jsonpatch move operation does not apply: doc is missing from path: %s", from) + } + + val, err := con.get(key) + if err != nil { + return err + } + + err = con.remove(key) + if err != nil { + return err + } + + path := op.path() + + con, key = findObject(doc, path) + + if con == nil { + return fmt.Errorf("jsonpatch move operation does not apply: doc is missing destination path: %s", path) + } + + return con.set(key, val) +} + +func (p Patch) test(doc *container, op operation) error { + path := op.path() + + con, key := findObject(doc, path) + + if con == nil { + return fmt.Errorf("jsonpatch test operation does not apply: is missing path: %s", path) + } + + val, err := con.get(key) + + if err != nil { + return err + } + + if val == nil { + if op.value().raw == nil { + return nil + } + return fmt.Errorf("Testing value %s failed", path) + } else if op.value() == nil { + return fmt.Errorf("Testing value %s failed", path) + } + + if val.equal(op.value()) { + return nil + } + + return fmt.Errorf("Testing value %s failed", path) +} + +func (p Patch) copy(doc *container, op operation) error { + from := op.from() + + con, key := findObject(doc, from) + + if con == nil { + return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing from path: %s", from) + } + + val, err := con.get(key) + if err != nil { + return err + } + + path := op.path() + + con, key = findObject(doc, path) + + if con == nil { + return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing destination path: %s", path) + } + + return con.set(key, val) +} + +// Equal indicates if 2 JSON documents have the same structural equality. +func Equal(a, b []byte) bool { + ra := make(json.RawMessage, len(a)) + copy(ra, a) + la := newLazyNode(&ra) + + rb := make(json.RawMessage, len(b)) + copy(rb, b) + lb := newLazyNode(&rb) + + return la.equal(lb) +} + +// DecodePatch decodes the passed JSON document as an RFC 6902 patch. +func DecodePatch(buf []byte) (Patch, error) { + var p Patch + + err := json.Unmarshal(buf, &p) + + if err != nil { + return nil, err + } + + return p, nil +} + +// Apply mutates a JSON document according to the patch, and returns the new +// document. +func (p Patch) Apply(doc []byte) ([]byte, error) { + return p.ApplyIndent(doc, "") +} + +// ApplyIndent mutates a JSON document according to the patch, and returns the new +// document indented. +func (p Patch) ApplyIndent(doc []byte, indent string) ([]byte, error) { + var pd container + if doc[0] == '[' { + pd = &partialArray{} + } else { + pd = &partialDoc{} + } + + err := json.Unmarshal(doc, pd) + + if err != nil { + return nil, err + } + + err = nil + + for _, op := range p { + switch op.kind() { + case "add": + err = p.add(&pd, op) + case "remove": + err = p.remove(&pd, op) + case "replace": + err = p.replace(&pd, op) + case "move": + err = p.move(&pd, op) + case "test": + err = p.test(&pd, op) + case "copy": + err = p.copy(&pd, op) + default: + err = fmt.Errorf("Unexpected kind: %s", op.kind()) + } + + if err != nil { + return nil, err + } + } + + if indent != "" { + return json.MarshalIndent(pd, "", indent) + } + + return json.Marshal(pd) +} + +// From http://tools.ietf.org/html/rfc6901#section-4 : +// +// Evaluation of each reference token begins by decoding any escaped +// character sequence. This is performed by first transforming any +// occurrence of the sequence '~1' to '/', and then transforming any +// occurrence of the sequence '~0' to '~'. + +var ( + rfc6901Decoder = strings.NewReplacer("~1", "/", "~0", "~") +) + +func decodePatchKey(k string) string { + return rfc6901Decoder.Replace(k) +}