Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions pkg/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,7 @@ U5wwSivyi7vmegHKmblOzNVKA5qPO8zWzqBC
Expect(actualData).To(BeComparableTo(data))
Expect(actualData).To(BeComparableTo(obj.Object["data"]))

// Apply with ResourceVersion set
data = map[string]any{
"a-new-key": "a-new-value",
}
Expand All @@ -974,6 +975,28 @@ U5wwSivyi7vmegHKmblOzNVKA5qPO8zWzqBC

Expect(actualData).To(BeComparableTo(data))
Expect(actualData).To(BeComparableTo(obj.Object["data"]))

// Apply with ResourceVersion unset
obj.SetResourceVersion("")
data = map[string]any{
"another-new-key": "another-new-value",
}
obj.Object["data"] = data
unstructured.RemoveNestedField(obj.Object, "metadata", "managedFields")

err = cl.Apply(ctx, client.ApplyConfigurationFromUnstructured(obj), &client.ApplyOptions{FieldManager: "test-manager"})
Expect(err).NotTo(HaveOccurred())

cm, err = clientset.CoreV1().ConfigMaps(obj.GetNamespace()).Get(ctx, obj.GetName(), metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())

actualData = map[string]any{}
for k, v := range cm.Data {
actualData[k] = v
}

Expect(actualData).To(BeComparableTo(data))
Expect(actualData).To(BeComparableTo(obj.Object["data"]))
})
})

Expand All @@ -999,6 +1022,23 @@ U5wwSivyi7vmegHKmblOzNVKA5qPO8zWzqBC
Expect(cm.Data).To(BeComparableTo(data))
Expect(cm.Data).To(BeComparableTo(obj.Data))

// Apply with ResourceVersion set
data = map[string]string{
"a-new-key": "a-new-value",
}
obj.Data = data

err = cl.Apply(ctx, obj, &client.ApplyOptions{FieldManager: "test-manager"})
Expect(err).NotTo(HaveOccurred())

cm, err = clientset.CoreV1().ConfigMaps(ptr.Deref(obj.GetNamespace(), "")).Get(ctx, ptr.Deref(obj.GetName(), ""), metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())

Expect(cm.Data).To(BeComparableTo(data))
Expect(cm.Data).To(BeComparableTo(obj.Data))

// Apply with ResourceVersion unset
obj.ResourceVersion = ptr.To("")
data = map[string]string{
"a-new-key": "a-new-value",
}
Expand Down
19 changes: 19 additions & 0 deletions pkg/client/fake/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2875,11 +2875,20 @@ var _ = Describe("Fake client", func() {
Expect(cl.Get(ctx, client.ObjectKeyFromObject(cm), cm)).To(Succeed())
Expect(cm.Data).To(BeComparableTo(map[string]string{"some": "data"}))

// Apply with ResourceVersion set
obj.Data = map[string]string{"other": "data"}
Expect(cl.Apply(ctx, obj, &client.ApplyOptions{FieldManager: "test-manager"})).To(Succeed())

Expect(cl.Get(ctx, client.ObjectKeyFromObject(cm), cm)).To(Succeed())
Expect(cm.Data).To(BeComparableTo(map[string]string{"other": "data"}))

// Apply with ResourceVersion unset
obj.ResourceVersion = ptr.To("")
obj.Data = map[string]string{"another": "data"}
Expect(cl.Apply(ctx, obj, &client.ApplyOptions{FieldManager: "test-manager"})).To(Succeed())

Expect(cl.Get(ctx, client.ObjectKeyFromObject(cm), cm)).To(Succeed())
Expect(cm.Data).To(BeComparableTo(map[string]string{"another": "data"}))
})

It("returns a conflict when trying to Create an object with UID set through Apply", func(ctx SpecContext) {
Expand Down Expand Up @@ -2931,12 +2940,22 @@ var _ = Describe("Fake client", func() {
Expect(cl.Get(ctx, client.ObjectKeyFromObject(result), result)).To(Succeed())
Expect(result.Object["spec"]).To(Equal(map[string]any{"some": "data"}))

// Apply with ResourceVersion set
Expect(unstructured.SetNestedField(obj.Object, map[string]any{"other": "data"}, "spec")).To(Succeed())
applyConfig2 := client.ApplyConfigurationFromUnstructured(obj)
Expect(cl.Apply(ctx, applyConfig2, &client.ApplyOptions{FieldManager: "test-manager"})).To(Succeed())

Expect(cl.Get(ctx, client.ObjectKeyFromObject(result), result)).To(Succeed())
Expect(result.Object["spec"]).To(Equal(map[string]any{"other": "data"}))

// Apply with ResourceVersion unset
obj.SetResourceVersion("")
Expect(unstructured.SetNestedField(obj.Object, map[string]any{"another": "data"}, "spec")).To(Succeed())
applyConfig3 := client.ApplyConfigurationFromUnstructured(obj)
Expect(cl.Apply(ctx, applyConfig3, &client.ApplyOptions{FieldManager: "test-manager"})).To(Succeed())

Expect(cl.Get(ctx, client.ObjectKeyFromObject(result), result)).To(Succeed())
Expect(result.Object["spec"]).To(Equal(map[string]any{"another": "data"}))
})

It("supports server-side apply of a custom resource via Apply method after List with a non-list kind", func(ctx SpecContext) {
Expand Down
7 changes: 5 additions & 2 deletions pkg/client/fake/versioned_tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,14 @@ func (t versionedTracker) updateObject(
// apiserver accepts such a patch, but it does so we just copy that behavior.
// Kubernetes apiserver behavior can be checked like this:
// `kubectl patch configmap foo --patch '{"metadata":{"annotations":{"foo":"bar"},"resourceVersion":null}}' -v=9`
case bytes.
Contains(debug.Stack(), []byte("sigs.k8s.io/controller-runtime/pkg/client/fake.(*fakeClient).Patch")):
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())
case bytes.Contains(debug.Stack(), []byte("sigs.k8s.io/controller-runtime/pkg/client/fake.(*fakeClient).Apply")):
// 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.Apply" func.
accessor.SetResourceVersion(oldAccessor.GetResourceVersion())
}
}

Expand Down
Loading