Skip to content

Commit

Permalink
馃悰 allow fakeclient to patch CR with no RV
Browse files Browse the repository at this point in the history
Signed-off-by: Alexandre Mahdhaoui <alexandre.mahdhaoui@gmail.com>
  • Loading branch information
alexandremahdhaoui committed Mar 26, 2024
1 parent e08b286 commit 6574e9d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 2 deletions.
13 changes: 11 additions & 2 deletions pkg/client/fake/client.go
Expand Up @@ -423,9 +423,18 @@ func (t versionedTracker) update(gvr schema.GroupVersionResource, obj runtime.Ob

// If the new object does not have the resource version set and it allows unconditional update,
// default it to the resource version of the existing resource
if accessor.GetResourceVersion() == "" && allowsUnconditionalUpdate(gvk) {
accessor.SetResourceVersion(oldAccessor.GetResourceVersion())
if accessor.GetResourceVersion() == "" {
switch {
case allowsUnconditionalUpdate(gvk):
accessor.SetResourceVersion(oldAccessor.GetResourceVersion())
case bytes.
Contains(debug.Stack(), []byte("sigs.k8s.io/controller-runtime/pkg/client/fake.(*fakeClient).patch")):
// 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 "fakeClient.patch" func.
accessor.SetResourceVersion(oldAccessor.GetResourceVersion())
}
}

if accessor.GetResourceVersion() != oldAccessor.GetResourceVersion() {
return apierrors.NewConflict(gvr.GroupResource(), accessor.GetName(), errors.New("object was modified"))
}
Expand Down
32 changes: 32 additions & 0 deletions pkg/client/fake/client_test.go
Expand Up @@ -550,6 +550,38 @@ var _ = Describe("Fake client", func() {
Expect(obj.ObjectMeta.ResourceVersion).To(Equal("1000"))
})

It("should allow patch with non-set ResourceVersion for a resource that doesn't allow unconditional updates", func() {
schemeBuilder := &scheme.Builder{GroupVersion: schema.GroupVersion{Group: "test", Version: "v1"}}
schemeBuilder.Register(&WithPointerMeta{}, &WithPointerMetaList{})

scheme := runtime.NewScheme()
Expect(schemeBuilder.AddToScheme(scheme)).NotTo(HaveOccurred())

cl := NewClientBuilder().WithScheme(scheme).Build()
original := &WithPointerMeta{
ObjectMeta: &metav1.ObjectMeta{
Name: "obj",
Namespace: "ns2",
}}

err := cl.Create(context.Background(), original)
Expect(err).ToNot(HaveOccurred())

newObj := &WithPointerMeta{
ObjectMeta: &metav1.ObjectMeta{
Name: original.Name,
Namespace: original.Namespace,
Annotations: map[string]string{
"foo": "bar",
},
}}
Expect(cl.Patch(context.Background(), newObj, client.MergeFrom(original))).To(Succeed())

patched := &WithPointerMeta{}
Expect(cl.Get(context.Background(), client.ObjectKeyFromObject(original), patched)).To(Succeed())
Expect(patched.Annotations).To(Equal(map[string]string{"foo": "bar"}))
})

It("should reject updates with non-set ResourceVersion for a resource that doesn't allow unconditional updates", func() {
By("Creating a new binding")
binding := &corev1.Binding{
Expand Down

0 comments on commit 6574e9d

Please sign in to comment.