From 2d6b699a784357d0b916018f09be2721c86eaa01 Mon Sep 17 00:00:00 2001 From: k8s-infra-cherrypick-robot <90416843+k8s-infra-cherrypick-robot@users.noreply.github.com> Date: Tue, 26 Sep 2023 18:17:05 -0700 Subject: [PATCH] =?UTF-8?q?[release-0.16]=20=20=F0=9F=90=9B=20Correctly=20?= =?UTF-8?q?identify=20if=20patch=20call=20was=20made=20on=20status=20(#251?= =?UTF-8?q?5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * correctly identify if patch was done in status * Add test --------- Co-authored-by: Sonu Kumar Singh --- pkg/client/fake/client.go | 11 ++++++++++- pkg/client/fake/client_test.go | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/pkg/client/fake/client.go b/pkg/client/fake/client.go index d70237e950..b3819926c0 100644 --- a/pkg/client/fake/client.go +++ b/pkg/client/fake/client.go @@ -361,7 +361,7 @@ func (t versionedTracker) Update(gvr schema.GroupVersionResource, obj runtime.Ob isStatus := false // We apply patches using a client-go reaction that ends up calling the trackers Update. As we can't change // that reaction, we use the callstack to figure out if this originated from the status client. - if bytes.Contains(debug.Stack(), []byte("sigs.k8s.io/controller-runtime/pkg/client/fake.(*fakeSubResourceClient).Patch")) { + if bytes.Contains(debug.Stack(), []byte("sigs.k8s.io/controller-runtime/pkg/client/fake.(*fakeSubResourceClient).statusPatch")) { isStatus = true } return t.update(gvr, obj, ns, isStatus, false) @@ -1090,6 +1090,15 @@ func (sw *fakeSubResourceClient) Patch(ctx context.Context, obj client.Object, p body = patchOptions.SubResourceBody } + // this is necessary to identify that last call was made for status patch, through stack trace. + if sw.subResource == "status" { + return sw.statusPatch(body, patch, patchOptions) + } + + return sw.client.patch(body, patch, &patchOptions.PatchOptions) +} + +func (sw *fakeSubResourceClient) statusPatch(body client.Object, patch client.Patch, patchOptions client.SubResourcePatchOptions) error { return sw.client.patch(body, patch, &patchOptions.PatchOptions) } diff --git a/pkg/client/fake/client_test.go b/pkg/client/fake/client_test.go index bc857d7be8..810cf5499c 100644 --- a/pkg/client/fake/client_test.go +++ b/pkg/client/fake/client_test.go @@ -40,6 +40,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/kubernetes/fake" + "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/interceptor" @@ -1590,6 +1591,28 @@ var _ = Describe("Fake client", func() { Expect(objOriginal.Status.Phase).ToNot(Equal(actual.Status.Phase)) }) + It("should be able to change typed objects that have a scale subresource on patch", func() { + obj := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "deploy", + }, + } + cl := NewClientBuilder().WithObjects(obj).Build() + objOriginal := obj.DeepCopy() + + patch := []byte(fmt.Sprintf(`{"spec":{"replicas":%d}}`, 2)) + Expect(cl.SubResource("scale").Patch(context.Background(), obj, client.RawPatch(types.MergePatchType, patch))).NotTo(HaveOccurred()) + + actual := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: obj.Name}} + Expect(cl.Get(context.Background(), client.ObjectKeyFromObject(actual), actual)).To(Succeed()) + + objOriginal.APIVersion = actual.APIVersion + objOriginal.Kind = actual.Kind + objOriginal.ResourceVersion = actual.ResourceVersion + objOriginal.Spec.Replicas = pointer.Int32(2) + Expect(cmp.Diff(objOriginal, actual)).To(BeEmpty()) + }) + It("should not change the status of typed objects that have a status subresource on patch", func() { obj := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{