Skip to content

Commit 262268f

Browse files
authored
Merge pull request kubernetes-sigs#2072 from alvaroaleman/support-subresource-modification
⚠️ Add client.SubResourceWriter
2 parents 9489eb5 + d7724aa commit 262268f

16 files changed

+869
-97
lines changed

pkg/client/client.go

Lines changed: 128 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -288,40 +288,152 @@ func (c *client) List(ctx context.Context, obj ObjectList, opts ...ListOption) e
288288
}
289289

290290
// Status implements client.StatusClient.
291-
func (c *client) Status() StatusWriter {
292-
return &statusWriter{client: c}
291+
func (c *client) Status() SubResourceWriter {
292+
return c.SubResource("status")
293293
}
294294

295-
// statusWriter is client.StatusWriter that writes status subresource.
296-
type statusWriter struct {
297-
client *client
295+
func (c *client) SubResource(subResource string) SubResourceWriter {
296+
return &subResourceWriter{client: c, subResource: subResource}
298297
}
299298

300-
// ensure statusWriter implements client.StatusWriter.
301-
var _ StatusWriter = &statusWriter{}
299+
// subResourceWriter is client.SubResourceWriter that writes to subresources.
300+
type subResourceWriter struct {
301+
client *client
302+
subResource string
303+
}
304+
305+
// ensure subResourceWriter implements client.SubResourceWriter.
306+
var _ SubResourceWriter = &subResourceWriter{}
307+
308+
// SubResourceUpdateOptions holds all the possible configuration
309+
// for a subresource update request.
310+
type SubResourceUpdateOptions struct {
311+
UpdateOptions
312+
SubResourceBody Object
313+
}
314+
315+
// ApplyToSubResourceUpdate updates the configuration on the given create options
316+
func (uo *SubResourceUpdateOptions) ApplyToSubResourceUpdate(o *SubResourceUpdateOptions) {
317+
uo.UpdateOptions.ApplyToUpdate(&o.UpdateOptions)
318+
if uo.SubResourceBody != nil {
319+
o.SubResourceBody = uo.SubResourceBody
320+
}
321+
}
322+
323+
// ApplyOptions applies the given options.
324+
func (uo *SubResourceUpdateOptions) ApplyOptions(opts []SubResourceUpdateOption) *SubResourceUpdateOptions {
325+
for _, o := range opts {
326+
o.ApplyToSubResourceUpdate(uo)
327+
}
328+
329+
return uo
330+
}
331+
332+
// SubResourceUpdateAndPatchOption is an option that can be used for either
333+
// a subresource update or patch request.
334+
type SubResourceUpdateAndPatchOption interface {
335+
SubResourceUpdateOption
336+
SubResourcePatchOption
337+
}
338+
339+
// WithSubResourceBody returns an option that uses the given body
340+
// for a subresource Update or Patch operation.
341+
func WithSubResourceBody(body Object) SubResourceUpdateAndPatchOption {
342+
return &withSubresourceBody{body: body}
343+
}
344+
345+
type withSubresourceBody struct {
346+
body Object
347+
}
348+
349+
func (wsr *withSubresourceBody) ApplyToSubResourceUpdate(o *SubResourceUpdateOptions) {
350+
o.SubResourceBody = wsr.body
351+
}
352+
353+
func (wsr *withSubresourceBody) ApplyToSubResourcePatch(o *SubResourcePatchOptions) {
354+
o.SubResourceBody = wsr.body
355+
}
356+
357+
// SubResourceCreateOptions are all the possible configurations for a subresource
358+
// create request.
359+
type SubResourceCreateOptions struct {
360+
CreateOptions
361+
}
362+
363+
// ApplyOptions applies the given options.
364+
func (co *SubResourceCreateOptions) ApplyOptions(opts []SubResourceCreateOption) *SubResourceCreateOptions {
365+
for _, o := range opts {
366+
o.ApplyToSubResourceCreate(co)
367+
}
302368

303-
// Update implements client.StatusWriter.
304-
func (sw *statusWriter) Update(ctx context.Context, obj Object, opts ...UpdateOption) error {
369+
return co
370+
}
371+
372+
// ApplyToSubresourceCreate applies the the configuration on the given create options.
373+
func (co *SubResourceCreateOptions) ApplyToSubresourceCreate(o *SubResourceCreateOptions) {
374+
co.CreateOptions.ApplyToCreate(&co.CreateOptions)
375+
}
376+
377+
// SubResourcePatchOptions holds all possible configurations for a subresource patch
378+
// request.
379+
type SubResourcePatchOptions struct {
380+
PatchOptions
381+
SubResourceBody Object
382+
}
383+
384+
// ApplyOptions applies the given options.
385+
func (po *SubResourcePatchOptions) ApplyOptions(opts []SubResourcePatchOption) *SubResourcePatchOptions {
386+
for _, o := range opts {
387+
o.ApplyToSubResourcePatch(po)
388+
}
389+
390+
return po
391+
}
392+
393+
// ApplyToSubResourcePatch applies the configuration on the given patch options.
394+
func (po *SubResourcePatchOptions) ApplyToSubResourcePatch(o *SubResourcePatchOptions) {
395+
po.PatchOptions.ApplyToPatch(&o.PatchOptions)
396+
if po.SubResourceBody != nil {
397+
o.SubResourceBody = po.SubResourceBody
398+
}
399+
}
400+
401+
func (sw *subResourceWriter) Create(ctx context.Context, obj Object, subResource Object, opts ...SubResourceCreateOption) error {
305402
defer sw.client.resetGroupVersionKind(obj, obj.GetObjectKind().GroupVersionKind())
403+
defer sw.client.resetGroupVersionKind(subResource, subResource.GetObjectKind().GroupVersionKind())
404+
306405
switch obj.(type) {
307406
case *unstructured.Unstructured:
308-
return sw.client.unstructuredClient.UpdateStatus(ctx, obj, opts...)
407+
return sw.client.unstructuredClient.CreateSubResource(ctx, obj, subResource, sw.subResource, opts...)
309408
case *metav1.PartialObjectMetadata:
310409
return fmt.Errorf("cannot update status using only metadata -- did you mean to patch?")
311410
default:
312-
return sw.client.typedClient.UpdateStatus(ctx, obj, opts...)
411+
return sw.client.typedClient.CreateSubResource(ctx, obj, subResource, sw.subResource, opts...)
313412
}
314413
}
315414

316-
// Patch implements client.Client.
317-
func (sw *statusWriter) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error {
415+
// Update implements client.SubResourceWriter.
416+
func (sw *subResourceWriter) Update(ctx context.Context, obj Object, opts ...SubResourceUpdateOption) error {
417+
defer sw.client.resetGroupVersionKind(obj, obj.GetObjectKind().GroupVersionKind())
418+
switch obj.(type) {
419+
case *unstructured.Unstructured:
420+
return sw.client.unstructuredClient.UpdateSubResource(ctx, obj, sw.subResource, opts...)
421+
case *metav1.PartialObjectMetadata:
422+
return fmt.Errorf("cannot update status using only metadata -- did you mean to patch?")
423+
default:
424+
return sw.client.typedClient.UpdateSubResource(ctx, obj, sw.subResource, opts...)
425+
}
426+
}
427+
428+
// Patch implements client.SubResourceWriter.
429+
func (sw *subResourceWriter) Patch(ctx context.Context, obj Object, patch Patch, opts ...SubResourcePatchOption) error {
318430
defer sw.client.resetGroupVersionKind(obj, obj.GetObjectKind().GroupVersionKind())
319431
switch obj.(type) {
320432
case *unstructured.Unstructured:
321-
return sw.client.unstructuredClient.PatchStatus(ctx, obj, patch, opts...)
433+
return sw.client.unstructuredClient.PatchSubResource(ctx, obj, sw.subResource, patch, opts...)
322434
case *metav1.PartialObjectMetadata:
323-
return sw.client.metadataClient.PatchStatus(ctx, obj, patch, opts...)
435+
return sw.client.metadataClient.PatchSubResource(ctx, obj, sw.subResource, patch, opts...)
324436
default:
325-
return sw.client.typedClient.PatchStatus(ctx, obj, patch, opts...)
437+
return sw.client.typedClient.PatchSubResource(ctx, obj, sw.subResource, patch, opts...)
326438
}
327439
}

0 commit comments

Comments
 (0)