Skip to content

Commit

Permalink
add test case to show it will not override other status fields when u…
Browse files Browse the repository at this point in the history
…pdating

Signed-off-by: Troy Connor <troy0820@users.noreply.github.com>
  • Loading branch information
troy0820 committed Sep 9, 2023
1 parent b6a7a0e commit 7b6b975
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 24 deletions.
32 changes: 8 additions & 24 deletions pkg/client/fake/client.go
Expand Up @@ -400,9 +400,10 @@ func (t versionedTracker) update(gvr schema.GroupVersionResource, obj runtime.Ob

if t.withStatusSubresource.Has(gvk) {
if isStatus { // copy everything but status and metadata.ResourceVersion from original object
if err := copyNonStatusFrom(oldObject, obj); err != nil {
if err := copyStatusFrom(obj, oldObject); err != nil {
return fmt.Errorf("failed to copy non-status field for object with status subresouce: %w", err)
}
obj = oldObject.DeepCopyObject().(client.Object)
} else { // copy status from original object
if err := copyStatusFrom(oldObject, obj); err != nil {
return fmt.Errorf("failed to copy the status for object with status subresource: %w", err)
Expand Down Expand Up @@ -949,6 +950,7 @@ func dryPatch(action testing.PatchActionImpl, tracker testing.ObjectTracker) (ru
return obj, nil
}

//lint:ignore U1000 function is causing errors with status updates
func copyNonStatusFrom(old, new runtime.Object) error {
newClientObject, ok := new.(client.Object)
if !ok {
Expand Down Expand Up @@ -1108,30 +1110,12 @@ func (sw *fakeSubResourceClient) Create(ctx context.Context, obj client.Object,
func (sw *fakeSubResourceClient) Update(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) error {
updateOptions := client.SubResourceUpdateOptions{}
updateOptions.ApplyOptions(opts)
gvr, err := getGVRFromObject(obj, sw.client.scheme)
if err != nil {
return err
}
o, err := sw.client.tracker.Get(gvr, obj.GetNamespace(), obj.GetName())
if err != nil {
return err
}
gvk, err := apiutil.GVKForObject(obj, sw.client.scheme)
if err != nil {
return err
}
body := o
if sw.client.tracker.withStatusSubresource.Has(gvk) {
err := copyStatusFrom(obj, body)
if err != nil {
return err
}
}
bodyObj := body.(client.Object)
if bodyObj.GetResourceVersion() != obj.GetResourceVersion() {
return apierrors.NewConflict(gvr.GroupResource(), obj.GetName(), fmt.Errorf("resource version conflict"))

body := obj
if updateOptions.SubResourceBody != nil {
body = updateOptions.SubResourceBody
}
return sw.client.update(bodyObj, true, &updateOptions.UpdateOptions)
return sw.client.update(body, true, &updateOptions.UpdateOptions)
}

func (sw *fakeSubResourceClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.SubResourcePatchOption) error {
Expand Down
30 changes: 30 additions & 0 deletions pkg/client/fake/client_test.go
Expand Up @@ -1479,6 +1479,36 @@ var _ = Describe("Fake client", func() {
objOriginal.Status.NodeInfo.MachineID = "machine-id-from-status-update"
Expect(cmp.Diff(objOriginal, actual)).To(BeEmpty())
})
It("should not overwrite status fields of typed objects that have a status subresource on status update", func() {
obj := &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node",
},
Spec: corev1.NodeSpec{
PodCIDR: "old-cidr",
},
Status: corev1.NodeStatus{
NodeInfo: corev1.NodeSystemInfo{
MachineID: "machine-id",
},
},
}
cl := NewClientBuilder().WithStatusSubresource(obj).WithObjects(obj).Build()
objOriginal := obj.DeepCopy()

obj.Status.Phase = corev1.NodeRunning
Expect(cl.Status().Update(context.Background(), obj)).NotTo(HaveOccurred())

actual := &corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: obj.Name}}
Expect(cl.Get(context.Background(), client.ObjectKeyFromObject(actual), actual)).NotTo(HaveOccurred())

objOriginal.APIVersion = actual.APIVersion
objOriginal.Kind = actual.Kind
objOriginal.ResourceVersion = actual.ResourceVersion
Expect(cmp.Diff(objOriginal, actual)).ToNot(BeEmpty())
Expect(objOriginal.Status.NodeInfo.MachineID).To(Equal(actual.Status.NodeInfo.MachineID))
Expect(objOriginal.Status.Phase).ToNot(Equal(actual.Status.Phase))
})

It("should not change the status of typed objects that have a status subresource on patch", func() {
obj := &corev1.Node{
Expand Down

0 comments on commit 7b6b975

Please sign in to comment.