From b90dec015700c6a0ce31248c88cadd68decd96a5 Mon Sep 17 00:00:00 2001 From: Solly Ross Date: Fri, 17 May 2019 14:34:49 -0700 Subject: [PATCH] Add PatchStatus, options to UpdateStatus This adds .Status().Patch to the client for patching status, and makes sure that .Status().Update takes update options like normal update does. --- pkg/client/client.go | 15 ++++++++++++--- pkg/client/fake/client.go | 10 ++++++++-- pkg/client/fake/client_test.go | 4 ++-- pkg/client/interfaces.go | 2 +- pkg/client/typed_client.go | 28 +++++++++++++++++++++++++++- pkg/client/unstructured_client.go | 27 +++++++++++++++++++++++++-- 6 files changed, 75 insertions(+), 11 deletions(-) diff --git a/pkg/client/client.go b/pkg/client/client.go index 646d86a87e..43facbfba6 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -171,10 +171,19 @@ type statusWriter struct { var _ StatusWriter = &statusWriter{} // Update implements client.StatusWriter -func (sw *statusWriter) Update(ctx context.Context, obj runtime.Object) error { +func (sw *statusWriter) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOptionFunc) error { _, ok := obj.(*unstructured.Unstructured) if ok { - return sw.client.unstructuredClient.UpdateStatus(ctx, obj) + return sw.client.unstructuredClient.UpdateStatus(ctx, obj, opts...) } - return sw.client.typedClient.UpdateStatus(ctx, obj) + return sw.client.typedClient.UpdateStatus(ctx, obj, opts...) +} + +// Patch implements client.Client +func (sw *statusWriter) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOptionFunc) error { + _, ok := obj.(*unstructured.Unstructured) + if ok { + return sw.client.unstructuredClient.PatchStatus(ctx, obj, patch, opts...) + } + return sw.client.typedClient.PatchStatus(ctx, obj, patch, opts...) } diff --git a/pkg/client/fake/client.go b/pkg/client/fake/client.go index d3e6f747dc..7a348a5867 100644 --- a/pkg/client/fake/client.go +++ b/pkg/client/fake/client.go @@ -244,8 +244,14 @@ type fakeStatusWriter struct { client *fakeClient } -func (sw *fakeStatusWriter) Update(ctx context.Context, obj runtime.Object) error { +func (sw *fakeStatusWriter) Update(ctx context.Context, obj runtime.Object, opts ...client.UpdateOptionFunc) error { // TODO(droot): This results in full update of the obj (spec + status). Need // a way to update status field only. - return sw.client.Update(ctx, obj) + return sw.client.Update(ctx, obj, opts...) +} + +func (sw *fakeStatusWriter) Patch(ctx context.Context, obj runtime.Object, patch client.Patch, opts ...client.PatchOptionFunc) error { + // TODO(droot): This results in full update of the obj (spec + status). Need + // a way to update status field only. + return sw.client.Patch(ctx, obj, patch, opts...) } diff --git a/pkg/client/fake/client_test.go b/pkg/client/fake/client_test.go index c65c24620c..ad173fae01 100644 --- a/pkg/client/fake/client_test.go +++ b/pkg/client/fake/client_test.go @@ -167,7 +167,7 @@ var _ = Describe("Fake client", func() { Namespace: "ns2", }, } - err := cl.Create(nil, newcm, client.CreateDryRunAll()) + err := cl.Create(nil, newcm, client.CreateDryRunAll) Expect(err).To(BeNil()) By("Getting the new configmap") @@ -193,7 +193,7 @@ var _ = Describe("Fake client", func() { "test-key": "new-value", }, } - err := cl.Update(nil, newcm, client.UpdateDryRunAll()) + err := cl.Update(nil, newcm, client.UpdateDryRunAll) Expect(err).To(BeNil()) By("Getting the new configmap") diff --git a/pkg/client/interfaces.go b/pkg/client/interfaces.go index 03a70d7f1f..e4ca8be85c 100644 --- a/pkg/client/interfaces.go +++ b/pkg/client/interfaces.go @@ -89,7 +89,7 @@ type StatusWriter interface { // Update updates the fields corresponding to the status subresource for the // given obj. obj must be a struct pointer so that obj can be updated // with the content returned by the Server. - Update(ctx context.Context, obj runtime.Object) error + Update(ctx context.Context, obj runtime.Object, opts ...UpdateOptionFunc) error // Patch patches the given object's subresource. obj must be a struct // pointer so that obj can be updated with the content returned by the diff --git a/pkg/client/typed_client.go b/pkg/client/typed_client.go index 50f2817001..76f429b650 100644 --- a/pkg/client/typed_client.go +++ b/pkg/client/typed_client.go @@ -141,7 +141,7 @@ func (c *typedClient) List(ctx context.Context, obj runtime.Object, opts ...List } // UpdateStatus used by StatusWriter to write status. -func (c *typedClient) UpdateStatus(ctx context.Context, obj runtime.Object) error { +func (c *typedClient) UpdateStatus(ctx context.Context, obj runtime.Object, opts ...UpdateOptionFunc) error { o, err := c.cache.getObjMeta(obj) if err != nil { return err @@ -156,6 +156,32 @@ func (c *typedClient) UpdateStatus(ctx context.Context, obj runtime.Object) erro Name(o.GetName()). SubResource("status"). Body(obj). + VersionedParams((&UpdateOptions{}).ApplyOptions(opts).AsUpdateOptions(), c.paramCodec). + Context(ctx). + Do(). + Into(obj) +} + +// PatchStatus used by StatusWriter to write status. +func (c *typedClient) PatchStatus(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOptionFunc) error { + o, err := c.cache.getObjMeta(obj) + if err != nil { + return err + } + + data, err := patch.Data(obj) + if err != nil { + return err + } + + patchOpts := &PatchOptions{} + return o.Patch(patch.Type()). + NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()). + Resource(o.resource()). + Name(o.GetName()). + SubResource("status"). + Body(data). + VersionedParams(patchOpts.ApplyOptions(opts).AsPatchOptions(), c.paramCodec). Context(ctx). Do(). Into(obj) diff --git a/pkg/client/unstructured_client.go b/pkg/client/unstructured_client.go index d182bf3552..f13dd18854 100644 --- a/pkg/client/unstructured_client.go +++ b/pkg/client/unstructured_client.go @@ -160,7 +160,7 @@ func (uc *unstructuredClient) List(_ context.Context, obj runtime.Object, opts . return nil } -func (uc *unstructuredClient) UpdateStatus(_ context.Context, obj runtime.Object) error { +func (uc *unstructuredClient) UpdateStatus(_ context.Context, obj runtime.Object, opts ...UpdateOptionFunc) error { u, ok := obj.(*unstructured.Unstructured) if !ok { return fmt.Errorf("unstructured client did not understand object: %T", obj) @@ -169,7 +169,30 @@ func (uc *unstructuredClient) UpdateStatus(_ context.Context, obj runtime.Object if err != nil { return err } - i, err := r.UpdateStatus(u, metav1.UpdateOptions{}) + i, err := r.UpdateStatus(u, *(&UpdateOptions{}).ApplyOptions(opts).AsUpdateOptions()) + if err != nil { + return err + } + u.Object = i.Object + return nil +} + +func (uc *unstructuredClient) PatchStatus(_ context.Context, obj runtime.Object, patch Patch, opts ...PatchOptionFunc) error { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return fmt.Errorf("unstructured client did not understand object: %T", obj) + } + r, err := uc.getResourceInterface(u.GroupVersionKind(), u.GetNamespace()) + if err != nil { + return err + } + + data, err := patch.Data(obj) + if err != nil { + return err + } + + i, err := r.Patch(u.GetName(), patch.Type(), data, *(&PatchOptions{}).ApplyOptions(opts).AsPatchOptions(), "status") if err != nil { return err }