Generify client-go

This adds a generic implementation of a clientset, and uses it to
replace the template code in generated clientsets for the default
methods. The templates are preserved as-is (or as close as they can
be) for use in extensions, whether for resources or subresources.

Clientsets with no extensions are reduced to their main getter, their
interface, their specific struct, and their constructor. All method
implementations are provided by the generic implementation. The
dedicated interface is preserved so that each clientset can have its
own set of methods, and the dedicated struct is preserved to allow
extensions and expansions to be defined where necessary.

Instead of handling the variants (with/without namespace, list, apply)
with a complex sequence of if statements, build up an index into an
array containing the various declarations.

The namespaced/non-namespaced distinction matters in the code
templates, but not in the methods themselves, so drop all the
non-namespaced variants and pass in "" explicitly.

Signed-off-by: Stephen Kitt <skitt@redhat.com>
This commit is contained in:
Stephen Kitt
2023-10-13 09:56:04 +02:00
parent 75bcc7d6df
commit 3734f5bf9b
12 changed files with 605 additions and 200 deletions

View File

@@ -0,0 +1,360 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package gentype
import (
"context"
json "encoding/json"
"fmt"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
"k8s.io/client-go/util/consistencydetector"
"k8s.io/client-go/util/watchlist"
"k8s.io/klog/v2"
)
// objectWithMeta matches objects implementing both runtime.Object and metav1.Object.
type objectWithMeta interface {
runtime.Object
metav1.Object
}
// namedObject matches comparable objects implementing GetName(); it is intended for use with apply declarative configurations.
type namedObject interface {
comparable
GetName() *string
}
// Client represents a client, optionally namespaced, with no support for lists or apply declarative configurations.
type Client[T objectWithMeta] struct {
resource string
client rest.Interface
namespace string // "" for non-namespaced clients
newObject func() T
parameterCodec runtime.ParameterCodec
}
// ClientWithList represents a client with support for lists.
type ClientWithList[T objectWithMeta, L runtime.Object] struct {
*Client[T]
alsoLister[T, L]
}
// ClientWithApply represents a client with support for apply declarative configurations.
type ClientWithApply[T objectWithMeta, C namedObject] struct {
*Client[T]
alsoApplier[T, C]
}
// ClientWithListAndApply represents a client with support for lists and apply declarative configurations.
type ClientWithListAndApply[T objectWithMeta, L runtime.Object, C namedObject] struct {
*Client[T]
alsoLister[T, L]
alsoApplier[T, C]
}
// Helper types for composition
type alsoLister[T objectWithMeta, L runtime.Object] struct {
client *Client[T]
newList func() L
}
type alsoApplier[T objectWithMeta, C namedObject] struct {
client *Client[T]
}
// NewClient constructs a client, namespaced or not, with no support for lists or apply.
// Non-namespaced clients are constructed by passing an empty namespace ("").
func NewClient[T objectWithMeta](
resource string, client rest.Interface, parameterCodec runtime.ParameterCodec, namespace string, emptyObjectCreator func() T,
) *Client[T] {
return &Client[T]{
resource: resource,
client: client,
parameterCodec: parameterCodec,
namespace: namespace,
newObject: emptyObjectCreator,
}
}
// NewClientWithList constructs a namespaced client with support for lists.
func NewClientWithList[T objectWithMeta, L runtime.Object](
resource string, client rest.Interface, parameterCodec runtime.ParameterCodec, namespace string, emptyObjectCreator func() T,
emptyListCreator func() L,
) *ClientWithList[T, L] {
typeClient := NewClient[T](resource, client, parameterCodec, namespace, emptyObjectCreator)
return &ClientWithList[T, L]{
typeClient,
alsoLister[T, L]{typeClient, emptyListCreator},
}
}
// NewClientWithApply constructs a namespaced client with support for apply declarative configurations.
func NewClientWithApply[T objectWithMeta, C namedObject](
resource string, client rest.Interface, parameterCodec runtime.ParameterCodec, namespace string, emptyObjectCreator func() T,
) *ClientWithApply[T, C] {
typeClient := NewClient[T](resource, client, parameterCodec, namespace, emptyObjectCreator)
return &ClientWithApply[T, C]{
typeClient,
alsoApplier[T, C]{typeClient},
}
}
// NewClientWithListAndApply constructs a client with support for lists and applying declarative configurations.
func NewClientWithListAndApply[T objectWithMeta, L runtime.Object, C namedObject](
resource string, client rest.Interface, parameterCodec runtime.ParameterCodec, namespace string, emptyObjectCreator func() T,
emptyListCreator func() L,
) *ClientWithListAndApply[T, L, C] {
typeClient := NewClient[T](resource, client, parameterCodec, namespace, emptyObjectCreator)
return &ClientWithListAndApply[T, L, C]{
typeClient,
alsoLister[T, L]{typeClient, emptyListCreator},
alsoApplier[T, C]{typeClient},
}
}
// GetClient returns the REST interface.
func (c *Client[T]) GetClient() rest.Interface {
return c.client
}
// GetNamespace returns the client's namespace, if any.
func (c *Client[T]) GetNamespace() string {
return c.namespace
}
// Get takes name of the resource, and returns the corresponding object, and an error if there is any.
func (c *Client[T]) Get(ctx context.Context, name string, options metav1.GetOptions) (T, error) {
result := c.newObject()
err := c.client.Get().
NamespaceIfScoped(c.namespace, c.namespace != "").
Resource(c.resource).
Name(name).
VersionedParams(&options, c.parameterCodec).
Do(ctx).
Into(result)
return result, err
}
// List takes label and field selectors, and returns the list of resources that match those selectors.
func (l *alsoLister[T, L]) List(ctx context.Context, opts metav1.ListOptions) (L, error) {
if watchListOptions, hasWatchListOptionsPrepared, watchListOptionsErr := watchlist.PrepareWatchListOptionsFromListOptions(opts); watchListOptionsErr != nil {
klog.Warningf("Failed preparing watchlist options for $.type|resource$, falling back to the standard LIST semantics, err = %v", watchListOptionsErr)
} else if hasWatchListOptionsPrepared {
result, err := l.watchList(ctx, watchListOptions)
if err == nil {
consistencydetector.CheckWatchListFromCacheDataConsistencyIfRequested(ctx, "watchlist request for "+l.client.resource, l.list, opts, result)
return result, nil
}
klog.Warningf("The watchlist request for %s ended with an error, falling back to the standard LIST semantics, err = %v", l.client.resource, err)
}
result, err := l.list(ctx, opts)
if err == nil {
consistencydetector.CheckListFromCacheDataConsistencyIfRequested(ctx, "list request for "+l.client.resource, l.list, opts, result)
}
return result, err
}
func (l *alsoLister[T, L]) list(ctx context.Context, opts metav1.ListOptions) (L, error) {
list := l.newList()
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
err := l.client.client.Get().
NamespaceIfScoped(l.client.namespace, l.client.namespace != "").
Resource(l.client.resource).
VersionedParams(&opts, l.client.parameterCodec).
Timeout(timeout).
Do(ctx).
Into(list)
return list, err
}
// watchList establishes a watch stream with the server and returns the list of resources.
func (l *alsoLister[T, L]) watchList(ctx context.Context, opts metav1.ListOptions) (result L, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = l.newList()
err = l.client.client.Get().
NamespaceIfScoped(l.client.namespace, l.client.namespace != "").
Resource(l.client.resource).
VersionedParams(&opts, l.client.parameterCodec).
Timeout(timeout).
WatchList(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested resources.
func (c *Client[T]) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
NamespaceIfScoped(c.namespace, c.namespace != "").
Resource(c.resource).
VersionedParams(&opts, c.parameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a resource and creates it. Returns the server's representation of the resource, and an error, if there is any.
func (c *Client[T]) Create(ctx context.Context, obj T, opts metav1.CreateOptions) (T, error) {
result := c.newObject()
err := c.client.Post().
NamespaceIfScoped(c.namespace, c.namespace != "").
Resource(c.resource).
VersionedParams(&opts, c.parameterCodec).
Body(obj).
Do(ctx).
Into(result)
return result, err
}
// Update takes the representation of a resource and updates it. Returns the server's representation of the resource, and an error, if there is any.
func (c *Client[T]) Update(ctx context.Context, obj T, opts metav1.UpdateOptions) (T, error) {
result := c.newObject()
err := c.client.Put().
NamespaceIfScoped(c.namespace, c.namespace != "").
Resource(c.resource).
Name(obj.GetName()).
VersionedParams(&opts, c.parameterCodec).
Body(obj).
Do(ctx).
Into(result)
return result, err
}
// UpdateStatus updates the status subresource of a resource. Returns the server's representation of the resource, and an error, if there is any.
func (c *Client[T]) UpdateStatus(ctx context.Context, obj T, opts metav1.UpdateOptions) (T, error) {
result := c.newObject()
err := c.client.Put().
NamespaceIfScoped(c.namespace, c.namespace != "").
Resource(c.resource).
Name(obj.GetName()).
SubResource("status").
VersionedParams(&opts, c.parameterCodec).
Body(obj).
Do(ctx).
Into(result)
return result, err
}
// Delete takes name of the resource and deletes it. Returns an error if one occurs.
func (c *Client[T]) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
return c.client.Delete().
NamespaceIfScoped(c.namespace, c.namespace != "").
Resource(c.resource).
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (l *alsoLister[T, L]) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return l.client.client.Delete().
NamespaceIfScoped(l.client.namespace, l.client.namespace != "").
Resource(l.client.resource).
VersionedParams(&listOpts, l.client.parameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched resource.
func (c *Client[T]) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (T, error) {
result := c.newObject()
err := c.client.Patch(pt).
NamespaceIfScoped(c.namespace, c.namespace != "").
Resource(c.resource).
Name(name).
SubResource(subresources...).
VersionedParams(&opts, c.parameterCodec).
Body(data).
Do(ctx).
Into(result)
return result, err
}
// Apply takes the given apply declarative configuration, applies it and returns the applied resource.
func (a *alsoApplier[T, C]) Apply(ctx context.Context, obj C, opts metav1.ApplyOptions) (T, error) {
result := a.client.newObject()
if obj == *new(C) {
return *new(T), fmt.Errorf("object provided to Apply must not be nil")
}
patchOpts := opts.ToPatchOptions()
data, err := json.Marshal(obj)
if err != nil {
return *new(T), err
}
if obj.GetName() == nil {
return *new(T), fmt.Errorf("obj.Name must be provided to Apply")
}
err = a.client.client.Patch(types.ApplyPatchType).
NamespaceIfScoped(a.client.namespace, a.client.namespace != "").
Resource(a.client.resource).
Name(*obj.GetName()).
VersionedParams(&patchOpts, a.client.parameterCodec).
Body(data).
Do(ctx).
Into(result)
return result, err
}
// Apply takes the given apply declarative configuration, applies it to the status subresource and returns the applied resource.
func (a *alsoApplier[T, C]) ApplyStatus(ctx context.Context, obj C, opts metav1.ApplyOptions) (T, error) {
if obj == *new(C) {
return *new(T), fmt.Errorf("object provided to Apply must not be nil")
}
patchOpts := opts.ToPatchOptions()
data, err := json.Marshal(obj)
if err != nil {
return *new(T), err
}
if obj.GetName() == nil {
return *new(T), fmt.Errorf("obj.Name must be provided to Apply")
}
result := a.client.newObject()
err = a.client.client.Patch(types.ApplyPatchType).
NamespaceIfScoped(a.client.namespace, a.client.namespace != "").
Resource(a.client.resource).
Name(*obj.GetName()).
SubResource("status").
VersionedParams(&patchOpts, a.client.parameterCodec).
Body(data).
Do(ctx).
Into(result)
return result, err
}

View File

@@ -30,7 +30,7 @@ type CertificateSigningRequestExpansion interface {
func (c *certificateSigningRequests) UpdateApproval(ctx context.Context, certificateSigningRequest *certificates.CertificateSigningRequest, opts metav1.UpdateOptions) (result *certificates.CertificateSigningRequest, err error) { func (c *certificateSigningRequests) UpdateApproval(ctx context.Context, certificateSigningRequest *certificates.CertificateSigningRequest, opts metav1.UpdateOptions) (result *certificates.CertificateSigningRequest, err error) {
result = &certificates.CertificateSigningRequest{} result = &certificates.CertificateSigningRequest{}
err = c.client.Put(). err = c.GetClient().Put().
Resource("certificatesigningrequests"). Resource("certificatesigningrequests").
Name(certificateSigningRequest.Name). Name(certificateSigningRequest.Name).
VersionedParams(&opts, scheme.ParameterCodec). VersionedParams(&opts, scheme.ParameterCodec).

View File

@@ -48,11 +48,11 @@ type EventExpansion interface {
// event; it must either match this event client's namespace, or this event // event; it must either match this event client's namespace, or this event
// client must have been created with the "" namespace. // client must have been created with the "" namespace.
func (e *events) CreateWithEventNamespace(event *v1.Event) (*v1.Event, error) { func (e *events) CreateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
if e.ns != "" && event.Namespace != e.ns { if e.GetNamespace() != "" && event.Namespace != e.GetNamespace() {
return nil, fmt.Errorf("can't create an event with namespace '%v' in namespace '%v'", event.Namespace, e.ns) return nil, fmt.Errorf("can't create an event with namespace '%v' in namespace '%v'", event.Namespace, e.GetNamespace())
} }
result := &v1.Event{} result := &v1.Event{}
err := e.client.Post(). err := e.GetClient().Post().
NamespaceIfScoped(event.Namespace, len(event.Namespace) > 0). NamespaceIfScoped(event.Namespace, len(event.Namespace) > 0).
Resource("events"). Resource("events").
Body(event). Body(event).
@@ -67,11 +67,11 @@ func (e *events) CreateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
// created with the "" namespace. Update also requires the ResourceVersion to be set in the event // created with the "" namespace. Update also requires the ResourceVersion to be set in the event
// object. // object.
func (e *events) UpdateWithEventNamespace(event *v1.Event) (*v1.Event, error) { func (e *events) UpdateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
if e.ns != "" && event.Namespace != e.ns { if e.GetNamespace() != "" && event.Namespace != e.GetNamespace() {
return nil, fmt.Errorf("can't update an event with namespace '%v' in namespace '%v'", event.Namespace, e.ns) return nil, fmt.Errorf("can't update an event with namespace '%v' in namespace '%v'", event.Namespace, e.GetNamespace())
} }
result := &v1.Event{} result := &v1.Event{}
err := e.client.Put(). err := e.GetClient().Put().
NamespaceIfScoped(event.Namespace, len(event.Namespace) > 0). NamespaceIfScoped(event.Namespace, len(event.Namespace) > 0).
Resource("events"). Resource("events").
Name(event.Name). Name(event.Name).
@@ -87,11 +87,11 @@ func (e *events) UpdateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
// match this event client's namespace, or this event client must have been // match this event client's namespace, or this event client must have been
// created with the "" namespace. // created with the "" namespace.
func (e *events) PatchWithEventNamespace(incompleteEvent *v1.Event, data []byte) (*v1.Event, error) { func (e *events) PatchWithEventNamespace(incompleteEvent *v1.Event, data []byte) (*v1.Event, error) {
if e.ns != "" && incompleteEvent.Namespace != e.ns { if e.GetNamespace() != "" && incompleteEvent.Namespace != e.GetNamespace() {
return nil, fmt.Errorf("can't patch an event with namespace '%v' in namespace '%v'", incompleteEvent.Namespace, e.ns) return nil, fmt.Errorf("can't patch an event with namespace '%v' in namespace '%v'", incompleteEvent.Namespace, e.GetNamespace())
} }
result := &v1.Event{} result := &v1.Event{}
err := e.client.Patch(types.StrategicMergePatchType). err := e.GetClient().Patch(types.StrategicMergePatchType).
NamespaceIfScoped(incompleteEvent.Namespace, len(incompleteEvent.Namespace) > 0). NamespaceIfScoped(incompleteEvent.Namespace, len(incompleteEvent.Namespace) > 0).
Resource("events"). Resource("events").
Name(incompleteEvent.Name). Name(incompleteEvent.Name).
@@ -109,8 +109,8 @@ func (e *events) Search(scheme *runtime.Scheme, objOrRef runtime.Object) (*v1.Ev
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(e.ns) > 0 && ref.Namespace != e.ns { if len(e.GetNamespace()) > 0 && ref.Namespace != e.GetNamespace() {
return nil, fmt.Errorf("won't be able to find any events of namespace '%v' in namespace '%v'", ref.Namespace, e.ns) return nil, fmt.Errorf("won't be able to find any events of namespace '%v' in namespace '%v'", ref.Namespace, e.GetNamespace())
} }
stringRefKind := string(ref.Kind) stringRefKind := string(ref.Kind)
var refKind *string var refKind *string

View File

@@ -32,6 +32,6 @@ type NamespaceExpansion interface {
// Finalize takes the representation of a namespace to update. Returns the server's representation of the namespace, and an error, if it occurs. // Finalize takes the representation of a namespace to update. Returns the server's representation of the namespace, and an error, if it occurs.
func (c *namespaces) Finalize(ctx context.Context, namespace *v1.Namespace, opts metav1.UpdateOptions) (result *v1.Namespace, err error) { func (c *namespaces) Finalize(ctx context.Context, namespace *v1.Namespace, opts metav1.UpdateOptions) (result *v1.Namespace, err error) {
result = &v1.Namespace{} result = &v1.Namespace{}
err = c.client.Put().Resource("namespaces").Name(namespace.Name).VersionedParams(&opts, scheme.ParameterCodec).SubResource("finalize").Body(namespace).Do(ctx).Into(result) err = c.GetClient().Put().Resource("namespaces").Name(namespace.Name).VersionedParams(&opts, scheme.ParameterCodec).SubResource("finalize").Body(namespace).Do(ctx).Into(result)
return return
} }

View File

@@ -34,7 +34,7 @@ type NodeExpansion interface {
// the node that the server returns, or an error. // the node that the server returns, or an error.
func (c *nodes) PatchStatus(ctx context.Context, nodeName string, data []byte) (*v1.Node, error) { func (c *nodes) PatchStatus(ctx context.Context, nodeName string, data []byte) (*v1.Node, error) {
result := &v1.Node{} result := &v1.Node{}
err := c.client.Patch(types.StrategicMergePatchType). err := c.GetClient().Patch(types.StrategicMergePatchType).
Resource("nodes"). Resource("nodes").
Name(nodeName). Name(nodeName).
SubResource("status"). SubResource("status").

View File

@@ -47,33 +47,33 @@ type PodExpansion interface {
// Bind applies the provided binding to the named pod in the current namespace (binding.Namespace is ignored). // Bind applies the provided binding to the named pod in the current namespace (binding.Namespace is ignored).
func (c *pods) Bind(ctx context.Context, binding *v1.Binding, opts metav1.CreateOptions) error { func (c *pods) Bind(ctx context.Context, binding *v1.Binding, opts metav1.CreateOptions) error {
return c.client.Post().Namespace(c.ns).Resource("pods").Name(binding.Name).VersionedParams(&opts, scheme.ParameterCodec).SubResource("binding").Body(binding).Do(ctx).Error() return c.GetClient().Post().Namespace(c.GetNamespace()).Resource("pods").Name(binding.Name).VersionedParams(&opts, scheme.ParameterCodec).SubResource("binding").Body(binding).Do(ctx).Error()
} }
// Evict submits a policy/v1beta1 Eviction request to the pod's eviction subresource. // Evict submits a policy/v1beta1 Eviction request to the pod's eviction subresource.
// Equivalent to calling EvictV1beta1. // Equivalent to calling EvictV1beta1.
// Deprecated: Use EvictV1() (supported in 1.22+) or EvictV1beta1(). // Deprecated: Use EvictV1() (supported in 1.22+) or EvictV1beta1().
func (c *pods) Evict(ctx context.Context, eviction *policyv1beta1.Eviction) error { func (c *pods) Evict(ctx context.Context, eviction *policyv1beta1.Eviction) error {
return c.client.Post().Namespace(c.ns).Resource("pods").Name(eviction.Name).SubResource("eviction").Body(eviction).Do(ctx).Error() return c.GetClient().Post().Namespace(c.GetNamespace()).Resource("pods").Name(eviction.Name).SubResource("eviction").Body(eviction).Do(ctx).Error()
} }
func (c *pods) EvictV1beta1(ctx context.Context, eviction *policyv1beta1.Eviction) error { func (c *pods) EvictV1beta1(ctx context.Context, eviction *policyv1beta1.Eviction) error {
return c.client.Post().Namespace(c.ns).Resource("pods").Name(eviction.Name).SubResource("eviction").Body(eviction).Do(ctx).Error() return c.GetClient().Post().Namespace(c.GetNamespace()).Resource("pods").Name(eviction.Name).SubResource("eviction").Body(eviction).Do(ctx).Error()
} }
func (c *pods) EvictV1(ctx context.Context, eviction *policyv1.Eviction) error { func (c *pods) EvictV1(ctx context.Context, eviction *policyv1.Eviction) error {
return c.client.Post().Namespace(c.ns).Resource("pods").Name(eviction.Name).SubResource("eviction").Body(eviction).Do(ctx).Error() return c.GetClient().Post().Namespace(c.GetNamespace()).Resource("pods").Name(eviction.Name).SubResource("eviction").Body(eviction).Do(ctx).Error()
} }
// Get constructs a request for getting the logs for a pod // Get constructs a request for getting the logs for a pod
func (c *pods) GetLogs(name string, opts *v1.PodLogOptions) *restclient.Request { func (c *pods) GetLogs(name string, opts *v1.PodLogOptions) *restclient.Request {
return c.client.Get().Namespace(c.ns).Name(name).Resource("pods").SubResource("log").VersionedParams(opts, scheme.ParameterCodec) return c.GetClient().Get().Namespace(c.GetNamespace()).Name(name).Resource("pods").SubResource("log").VersionedParams(opts, scheme.ParameterCodec)
} }
// ProxyGet returns a response of the pod by calling it through the proxy. // ProxyGet returns a response of the pod by calling it through the proxy.
func (c *pods) ProxyGet(scheme, name, port, path string, params map[string]string) restclient.ResponseWrapper { func (c *pods) ProxyGet(scheme, name, port, path string, params map[string]string) restclient.ResponseWrapper {
request := c.client.Get(). request := c.GetClient().Get().
Namespace(c.ns). Namespace(c.GetNamespace()).
Resource("pods"). Resource("pods").
SubResource("proxy"). SubResource("proxy").
Name(net.JoinSchemeNamePort(scheme, name, port)). Name(net.JoinSchemeNamePort(scheme, name, port)).

View File

@@ -28,8 +28,8 @@ type ServiceExpansion interface {
// ProxyGet returns a response of the service by calling it through the proxy. // ProxyGet returns a response of the service by calling it through the proxy.
func (c *services) ProxyGet(scheme, name, port, path string, params map[string]string) restclient.ResponseWrapper { func (c *services) ProxyGet(scheme, name, port, path string, params map[string]string) restclient.ResponseWrapper {
request := c.client.Get(). request := c.GetClient().Get().
Namespace(c.ns). Namespace(c.GetNamespace()).
Resource("services"). Resource("services").
SubResource("proxy"). SubResource("proxy").
Name(net.JoinSchemeNamePort(scheme, name, port)). Name(net.JoinSchemeNamePort(scheme, name, port)).

View File

@@ -44,11 +44,11 @@ type EventExpansion interface {
// it must either match this event client's namespace, or this event client must // it must either match this event client's namespace, or this event client must
// have been created with the "" namespace. // have been created with the "" namespace.
func (e *events) CreateWithEventNamespace(event *v1beta1.Event) (*v1beta1.Event, error) { func (e *events) CreateWithEventNamespace(event *v1beta1.Event) (*v1beta1.Event, error) {
if e.ns != "" && event.Namespace != e.ns { if e.GetNamespace() != "" && event.Namespace != e.GetNamespace() {
return nil, fmt.Errorf("can't create an event with namespace '%v' in namespace '%v'", event.Namespace, e.ns) return nil, fmt.Errorf("can't create an event with namespace '%v' in namespace '%v'", event.Namespace, e.GetNamespace())
} }
result := &v1beta1.Event{} result := &v1beta1.Event{}
err := e.client.Post(). err := e.GetClient().Post().
NamespaceIfScoped(event.Namespace, len(event.Namespace) > 0). NamespaceIfScoped(event.Namespace, len(event.Namespace) > 0).
Resource("events"). Resource("events").
Body(event). Body(event).
@@ -64,11 +64,11 @@ func (e *events) CreateWithEventNamespace(event *v1beta1.Event) (*v1beta1.Event,
// created with the "" namespace. // created with the "" namespace.
// Update also requires the ResourceVersion to be set in the event object. // Update also requires the ResourceVersion to be set in the event object.
func (e *events) UpdateWithEventNamespace(event *v1beta1.Event) (*v1beta1.Event, error) { func (e *events) UpdateWithEventNamespace(event *v1beta1.Event) (*v1beta1.Event, error) {
if e.ns != "" && event.Namespace != e.ns { if e.GetNamespace() != "" && event.Namespace != e.GetNamespace() {
return nil, fmt.Errorf("can't update an event with namespace '%v' in namespace '%v'", event.Namespace, e.ns) return nil, fmt.Errorf("can't update an event with namespace '%v' in namespace '%v'", event.Namespace, e.GetNamespace())
} }
result := &v1beta1.Event{} result := &v1beta1.Event{}
err := e.client.Put(). err := e.GetClient().Put().
NamespaceIfScoped(event.Namespace, len(event.Namespace) > 0). NamespaceIfScoped(event.Namespace, len(event.Namespace) > 0).
Resource("events"). Resource("events").
Name(event.Name). Name(event.Name).
@@ -84,11 +84,11 @@ func (e *events) UpdateWithEventNamespace(event *v1beta1.Event) (*v1beta1.Event,
// The namespace must either match this event client's namespace, or this event client must // The namespace must either match this event client's namespace, or this event client must
// have been created with the "" namespace. // have been created with the "" namespace.
func (e *events) PatchWithEventNamespace(event *v1beta1.Event, data []byte) (*v1beta1.Event, error) { func (e *events) PatchWithEventNamespace(event *v1beta1.Event, data []byte) (*v1beta1.Event, error) {
if e.ns != "" && event.Namespace != e.ns { if e.GetNamespace() != "" && event.Namespace != e.GetNamespace() {
return nil, fmt.Errorf("can't patch an event with namespace '%v' in namespace '%v'", event.Namespace, e.ns) return nil, fmt.Errorf("can't patch an event with namespace '%v' in namespace '%v'", event.Namespace, e.GetNamespace())
} }
result := &v1beta1.Event{} result := &v1beta1.Event{}
err := e.client.Patch(types.StrategicMergePatchType). err := e.GetClient().Patch(types.StrategicMergePatchType).
NamespaceIfScoped(event.Namespace, len(event.Namespace) > 0). NamespaceIfScoped(event.Namespace, len(event.Namespace) > 0).
Resource("events"). Resource("events").
Name(event.Name). Name(event.Name).

View File

@@ -31,5 +31,5 @@ type DeploymentExpansion interface {
// Rollback applied the provided DeploymentRollback to the named deployment in the current namespace. // Rollback applied the provided DeploymentRollback to the named deployment in the current namespace.
func (c *deployments) Rollback(ctx context.Context, deploymentRollback *v1beta1.DeploymentRollback, opts metav1.CreateOptions) error { func (c *deployments) Rollback(ctx context.Context, deploymentRollback *v1beta1.DeploymentRollback, opts metav1.CreateOptions) error {
return c.client.Post().Namespace(c.ns).Resource("deployments").Name(deploymentRollback.Name).VersionedParams(&opts, scheme.ParameterCodec).SubResource("rollback").Body(deploymentRollback).Do(ctx).Error() return c.GetClient().Post().Namespace(c.GetNamespace()).Resource("deployments").Name(deploymentRollback.Name).VersionedParams(&opts, scheme.ParameterCodec).SubResource("rollback").Body(deploymentRollback).Do(ctx).Error()
} }

View File

@@ -28,7 +28,7 @@ type EvictionExpansion interface {
} }
func (c *evictions) Evict(ctx context.Context, eviction *policy.Eviction) error { func (c *evictions) Evict(ctx context.Context, eviction *policy.Eviction) error {
return c.client.Post(). return c.GetClient().Post().
AbsPath("/api/v1"). AbsPath("/api/v1").
Namespace(eviction.Namespace). Namespace(eviction.Namespace).
Resource("pods"). Resource("pods").

View File

@@ -28,7 +28,7 @@ type EvictionExpansion interface {
} }
func (c *evictions) Evict(ctx context.Context, eviction *policy.Eviction) error { func (c *evictions) Evict(ctx context.Context, eviction *policy.Eviction) error {
return c.client.Post(). return c.GetClient().Post().
AbsPath("/api/v1"). AbsPath("/api/v1").
Namespace(eviction.Namespace). Namespace(eviction.Namespace).
Resource("pods"). Resource("pods").

View File

@@ -176,6 +176,10 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
"CheckListFromCacheDataConsistencyIfRequested": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/consistencydetector", Name: "CheckListFromCacheDataConsistencyIfRequested"}), "CheckListFromCacheDataConsistencyIfRequested": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/consistencydetector", Name: "CheckListFromCacheDataConsistencyIfRequested"}),
"CheckWatchListFromCacheDataConsistencyIfRequested": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/consistencydetector", Name: "CheckWatchListFromCacheDataConsistencyIfRequested"}), "CheckWatchListFromCacheDataConsistencyIfRequested": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/consistencydetector", Name: "CheckWatchListFromCacheDataConsistencyIfRequested"}),
"PrepareWatchListOptionsFromListOptions": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/watchlist", Name: "PrepareWatchListOptionsFromListOptions"}), "PrepareWatchListOptionsFromListOptions": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/watchlist", Name: "PrepareWatchListOptionsFromListOptions"}),
"Client": c.Universe.Type(types.Name{Package: "k8s.io/client-go/gentype", Name: "Client"}),
"ClientWithList": c.Universe.Type(types.Name{Package: "k8s.io/client-go/gentype", Name: "ClientWithList"}),
"ClientWithApply": c.Universe.Type(types.Name{Package: "k8s.io/client-go/gentype", Name: "ClientWithApply"}),
"ClientWithListAndApply": c.Universe.Type(types.Name{Package: "k8s.io/client-go/gentype", Name: "ClientWithListAndApply"}),
} }
if generateApply { if generateApply {
@@ -210,55 +214,31 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
} }
sw.Do(interfaceTemplate4, m) sw.Do(interfaceTemplate4, m)
structNamespaced := namespaced
if tags.NonNamespaced { if tags.NonNamespaced {
sw.Do(structNonNamespaced, m) structNamespaced = nonNamespaced
sw.Do(newStructNonNamespaced, m)
} else {
sw.Do(structNamespaced, m)
sw.Do(newStructNamespaced, m)
} }
if tags.NoVerbs { if tags.NoVerbs {
sw.Do(structType[noList|noApply], m)
sw.Do(newStruct[structNamespaced|noList|noApply], m)
return sw.Error() return sw.Error()
} }
if tags.HasVerb("get") { listableOrAppliable := noList | noApply
sw.Do(getTemplate, m)
}
if tags.HasVerb("list") { if tags.HasVerb("list") {
sw.Do(listTemplate, m) listableOrAppliable |= withList
sw.Do(privateListTemplate, m)
sw.Do(watchListTemplate, m)
}
if tags.HasVerb("watch") {
sw.Do(watchTemplate, m)
} }
if tags.HasVerb("create") {
sw.Do(createTemplate, m)
}
if tags.HasVerb("update") {
sw.Do(updateTemplate, m)
}
if tags.HasVerb("updateStatus") {
sw.Do(updateStatusTemplate, m)
}
if tags.HasVerb("delete") {
sw.Do(deleteTemplate, m)
}
if tags.HasVerb("deleteCollection") {
sw.Do(deleteCollectionTemplate, m)
}
if tags.HasVerb("patch") {
sw.Do(patchTemplate, m)
}
if tags.HasVerb("apply") && generateApply { if tags.HasVerb("apply") && generateApply {
sw.Do(applyTemplate, m) listableOrAppliable |= withApply
}
if tags.HasVerb("applyStatus") && generateApply {
sw.Do(applyStatusTemplate, m)
} }
sw.Do(structType[listableOrAppliable], m)
sw.Do(newStruct[structNamespaced|listableOrAppliable], m)
// generate expansion methods // generate expansion methods
for _, e := range tags.Extensions { for _, e := range tags.Extensions {
if e.HasVerb("apply") && !generateApply { if e.HasVerb("apply") && !generateApply {
@@ -387,7 +367,8 @@ func buildDefaultVerbTemplates(generateApply bool) map[string]string {
m := map[string]string{ m := map[string]string{
"create": `Create(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (*$.resultType|raw$, error)`, "create": `Create(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (*$.resultType|raw$, error)`,
"update": `Update(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (*$.resultType|raw$, error)`, "update": `Update(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (*$.resultType|raw$, error)`,
"updateStatus": `UpdateStatus(ctx context.Context, $.inputType|private$ *$.type|raw$, opts $.UpdateOptions|raw$) (*$.type|raw$, error)`, "updateStatus": `// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
UpdateStatus(ctx context.Context, $.inputType|private$ *$.type|raw$, opts $.UpdateOptions|raw$) (*$.type|raw$, error)`,
"delete": `Delete(ctx context.Context, name string, opts $.DeleteOptions|raw$) error`, "delete": `Delete(ctx context.Context, name string, opts $.DeleteOptions|raw$) error`,
"deleteCollection": `DeleteCollection(ctx context.Context, opts $.DeleteOptions|raw$, listOpts $.ListOptions|raw$) error`, "deleteCollection": `DeleteCollection(ctx context.Context, opts $.DeleteOptions|raw$, listOpts $.ListOptions|raw$) error`,
"get": `Get(ctx context.Context, name string, opts $.GetOptions|raw$) (*$.resultType|raw$, error)`, "get": `Get(ctx context.Context, name string, opts $.GetOptions|raw$) (*$.resultType|raw$, error)`,
@@ -397,7 +378,8 @@ func buildDefaultVerbTemplates(generateApply bool) map[string]string {
} }
if generateApply { if generateApply {
m["apply"] = `Apply(ctx context.Context, $.inputType|private$ *$.inputApplyConfig|raw$, opts $.ApplyOptions|raw$) (result *$.resultType|raw$, err error)` m["apply"] = `Apply(ctx context.Context, $.inputType|private$ *$.inputApplyConfig|raw$, opts $.ApplyOptions|raw$) (result *$.resultType|raw$, err error)`
m["applyStatus"] = `ApplyStatus(ctx context.Context, $.inputType|private$ *$.inputApplyConfig|raw$, opts $.ApplyOptions|raw$) (result *$.resultType|raw$, err error)` m["applyStatus"] = `// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus().
ApplyStatus(ctx context.Context, $.inputType|private$ *$.inputApplyConfig|raw$, opts $.ApplyOptions|raw$) (result *$.resultType|raw$, err error)`
} }
return m return m
} }
@@ -429,41 +411,173 @@ var interfaceTemplate4 = `
} }
` `
// template for the struct that implements the type's interface // struct and constructor variants
var structNamespaced = ` const (
// $.type|privatePlural$ implements $.type|public$Interface // The following values are bits in a bitmask.
type $.type|privatePlural$ struct { // The values which can be set indicate namespace support, list support, and apply support;
client $.RESTClientInterface|raw$ // to make the declarations easier to read (like a truth table), corresponding zero-values
ns string // are also declared.
} namespaced = 0
` noList = 0
noApply = 0
nonNamespaced = 1 << iota
withList
withApply
)
// template for the struct that implements the type's interface // The following string slices are similar to maps, but with combinable keys used as indices.
var structNonNamespaced = ` // Each entry defines whether it supports lists and/or apply, and if namespacedness matters,
// $.type|privatePlural$ implements $.type|public$Interface // namespaces; each bit is then toggled:
type $.type|privatePlural$ struct { // * noList, noApply: index 0;
client $.RESTClientInterface|raw$ // * withList, noApply: index 2;
} // * noList, withApply: index 4;
` // * withList, withApply: index 6.
// When namespacedness matters, the namespaced variants are the same as the above, and
// the non-namespaced variants are offset by 1.
// Go enforces index unicity in these kinds of declarations.
var newStructNamespaced = ` // struct declarations
// new$.type|publicPlural$ returns a $.type|publicPlural$ // Namespacedness does not matter
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client, namespace string) *$.type|privatePlural$ { var structType = []string{
return &$.type|privatePlural${ noList | noApply: `
client: c.RESTClient(), // $.type|privatePlural$ implements $.type|public$Interface
ns: namespace, type $.type|privatePlural$ struct {
*$.Client|raw$[*$.resultType|raw$]
} }
} `,
` withList | noApply: `
// $.type|privatePlural$ implements $.type|public$Interface
var newStructNonNamespaced = ` type $.type|privatePlural$ struct {
// new$.type|publicPlural$ returns a $.type|publicPlural$ *$.ClientWithList|raw$[*$.resultType|raw$, *$.resultType|raw$List]
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ {
return &$.type|privatePlural${
client: c.RESTClient(),
} }
`,
noList | withApply: `
// $.type|privatePlural$ implements $.type|public$Interface
type $.type|privatePlural$ struct {
*$.ClientWithApply|raw$[*$.resultType|raw$, *$.inputApplyConfig|raw$]
}
`,
withList | withApply: `
// $.type|privatePlural$ implements $.type|public$Interface
type $.type|privatePlural$ struct {
*$.ClientWithListAndApply|raw$[*$.resultType|raw$, *$.resultType|raw$List, *$.inputApplyConfig|raw$]
}
`,
} }
`
// Constructors for the struct, in all variants
// Namespacedness matters
var newStruct = []string{
namespaced | noList | noApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client, namespace string) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClient[*$.resultType|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
namespace,
func() *$.resultType|raw$ { return &$.resultType|raw${} }),
}
}
`,
namespaced | noList | withApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client, namespace string) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithApply[*$.resultType|raw$, *$.inputApplyConfig|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
namespace,
func() *$.resultType|raw$ { return &$.resultType|raw${} }),
}
}
`,
namespaced | withList | noApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client, namespace string) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithList[*$.resultType|raw$, *$.resultType|raw$List](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
namespace,
func() *$.resultType|raw$ { return &$.resultType|raw${} },
func() *$.resultType|raw$List { return &$.resultType|raw$List{} }),
}
}
`,
namespaced | withList | withApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client, namespace string) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithListAndApply[*$.resultType|raw$, *$.resultType|raw$List, *$.inputApplyConfig|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
namespace,
func() *$.resultType|raw$ { return &$.resultType|raw${} },
func() *$.resultType|raw$List { return &$.resultType|raw$List{} }),
}
}
`,
nonNamespaced | noList | noApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClient[*$.resultType|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
"",
func() *$.resultType|raw$ { return &$.resultType|raw${} }),
}
}
`,
nonNamespaced | noList | withApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithApply[*$.resultType|raw$, *$.inputApplyConfig|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
"",
func() *$.resultType|raw$ { return &$.resultType|raw${} }),
}
}
`,
nonNamespaced | withList | noApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithList[*$.resultType|raw$, *$.resultType|raw$List](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
"",
func() *$.resultType|raw$ { return &$.resultType|raw${} },
func() *$.resultType|raw$List { return &$.resultType|raw$List{} }),
}
}
`,
nonNamespaced | withList | withApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithListAndApply[*$.resultType|raw$, *$.resultType|raw$List, *$.inputApplyConfig|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
"",
func() *$.resultType|raw$ { return &$.resultType|raw${} },
func() *$.resultType|raw$List { return &$.resultType|raw$List{} }),
}
}
`,
}
var listTemplate = ` var listTemplate = `
// List takes label and field selectors, and returns the list of $.resultType|publicPlural$ that match those selectors. // List takes label and field selectors, and returns the list of $.resultType|publicPlural$ that match those selectors.
func (c *$.type|privatePlural$) List(ctx context.Context, opts $.ListOptions|raw$) (*$.resultType|raw$List, error) { func (c *$.type|privatePlural$) List(ctx context.Context, opts $.ListOptions|raw$) (*$.resultType|raw$List, error) {
@@ -493,8 +607,8 @@ func (c *$.type|privatePlural$) list(ctx context.Context, opts $.ListOptions|raw
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
} }
result = &$.resultType|raw$List{} result = &$.resultType|raw$List{}
err = c.client.Get(). err = c.GetClient().Get().
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
VersionedParams(&opts, $.schemeParameterCodec|raw$). VersionedParams(&opts, $.schemeParameterCodec|raw$).
Timeout(timeout). Timeout(timeout).
@@ -512,8 +626,8 @@ func (c *$.type|privatePlural$) List(ctx context.Context, $.type|private$Name st
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
} }
result = &$.resultType|raw$List{} result = &$.resultType|raw$List{}
err = c.client.Get(). err = c.GetClient().Get().
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
Name($.type|private$Name). Name($.type|private$Name).
SubResource("$.subresourcePath$"). SubResource("$.subresourcePath$").
@@ -529,8 +643,8 @@ var getTemplate = `
// Get takes name of the $.type|private$, and returns the corresponding $.resultType|private$ object, and an error if there is any. // Get takes name of the $.type|private$, and returns the corresponding $.resultType|private$ object, and an error if there is any.
func (c *$.type|privatePlural$) Get(ctx context.Context, name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) { func (c *$.type|privatePlural$) Get(ctx context.Context, name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${} result = &$.resultType|raw${}
err = c.client.Get(). err = c.GetClient().Get().
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
Name(name). Name(name).
VersionedParams(&options, $.schemeParameterCodec|raw$). VersionedParams(&options, $.schemeParameterCodec|raw$).
@@ -544,8 +658,8 @@ var getSubresourceTemplate = `
// Get takes name of the $.type|private$, and returns the corresponding $.resultType|raw$ object, and an error if there is any. // Get takes name of the $.type|private$, and returns the corresponding $.resultType|raw$ object, and an error if there is any.
func (c *$.type|privatePlural$) Get(ctx context.Context, $.type|private$Name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) { func (c *$.type|privatePlural$) Get(ctx context.Context, $.type|private$Name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${} result = &$.resultType|raw${}
err = c.client.Get(). err = c.GetClient().Get().
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
Name($.type|private$Name). Name($.type|private$Name).
SubResource("$.subresourcePath$"). SubResource("$.subresourcePath$").
@@ -559,8 +673,8 @@ func (c *$.type|privatePlural$) Get(ctx context.Context, $.type|private$Name str
var deleteTemplate = ` var deleteTemplate = `
// Delete takes name of the $.type|private$ and deletes it. Returns an error if one occurs. // Delete takes name of the $.type|private$ and deletes it. Returns an error if one occurs.
func (c *$.type|privatePlural$) Delete(ctx context.Context, name string, opts $.DeleteOptions|raw$) error { func (c *$.type|privatePlural$) Delete(ctx context.Context, name string, opts $.DeleteOptions|raw$) error {
return c.client.Delete(). return c.GetClient().Delete().
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
Name(name). Name(name).
Body(&opts). Body(&opts).
@@ -569,30 +683,12 @@ func (c *$.type|privatePlural$) Delete(ctx context.Context, name string, opts $.
} }
` `
var deleteCollectionTemplate = `
// DeleteCollection deletes a collection of objects.
func (c *$.type|privatePlural$) DeleteCollection(ctx context.Context, opts $.DeleteOptions|raw$, listOpts $.ListOptions|raw$) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil{
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|resource$").
VersionedParams(&listOpts, $.schemeParameterCodec|raw$).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
`
var createSubresourceTemplate = ` var createSubresourceTemplate = `
// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. // Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *$.type|privatePlural$) Create(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (result *$.resultType|raw$, err error) { func (c *$.type|privatePlural$) Create(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${} result = &$.resultType|raw${}
err = c.client.Post(). err = c.GetClient().Post().
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
Name($.type|private$Name). Name($.type|private$Name).
SubResource("$.subresourcePath$"). SubResource("$.subresourcePath$").
@@ -608,8 +704,8 @@ var createTemplate = `
// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. // Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *$.type|privatePlural$) Create(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (result *$.resultType|raw$, err error) { func (c *$.type|privatePlural$) Create(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${} result = &$.resultType|raw${}
err = c.client.Post(). err = c.GetClient().Post().
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
VersionedParams(&opts, $.schemeParameterCodec|raw$). VersionedParams(&opts, $.schemeParameterCodec|raw$).
Body($.inputType|private$). Body($.inputType|private$).
@@ -623,8 +719,8 @@ var updateSubresourceTemplate = `
// Update takes the top resource name and the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. // Update takes the top resource name and the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *$.type|privatePlural$) Update(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (result *$.resultType|raw$, err error) { func (c *$.type|privatePlural$) Update(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${} result = &$.resultType|raw${}
err = c.client.Put(). err = c.GetClient().Put().
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
Name($.type|private$Name). Name($.type|private$Name).
SubResource("$.subresourcePath$"). SubResource("$.subresourcePath$").
@@ -640,8 +736,8 @@ var updateTemplate = `
// Update takes the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. // Update takes the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *$.type|privatePlural$) Update(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (result *$.resultType|raw$, err error) { func (c *$.type|privatePlural$) Update(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${} result = &$.resultType|raw${}
err = c.client.Put(). err = c.GetClient().Put().
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
Name($.inputType|private$.Name). Name($.inputType|private$.Name).
VersionedParams(&opts, $.schemeParameterCodec|raw$). VersionedParams(&opts, $.schemeParameterCodec|raw$).
@@ -652,24 +748,6 @@ func (c *$.type|privatePlural$) Update(ctx context.Context, $.inputType|private$
} }
` `
var updateStatusTemplate = `
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *$.type|privatePlural$) UpdateStatus(ctx context.Context, $.type|private$ *$.type|raw$, opts $.UpdateOptions|raw$) (result *$.type|raw$, err error) {
result = &$.type|raw${}
err = c.client.Put().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|resource$").
Name($.type|private$.Name).
SubResource("status").
VersionedParams(&opts, $.schemeParameterCodec|raw$).
Body($.type|private$).
Do(ctx).
Into(result)
return
}
`
var watchTemplate = ` var watchTemplate = `
// Watch returns a $.watchInterface|raw$ that watches the requested $.type|privatePlural$. // Watch returns a $.watchInterface|raw$ that watches the requested $.type|privatePlural$.
func (c *$.type|privatePlural$) Watch(ctx context.Context, opts $.ListOptions|raw$) ($.watchInterface|raw$, error) { func (c *$.type|privatePlural$) Watch(ctx context.Context, opts $.ListOptions|raw$) ($.watchInterface|raw$, error) {
@@ -678,9 +756,8 @@ func (c *$.type|privatePlural$) Watch(ctx context.Context, opts $.ListOptions|ra
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
} }
opts.Watch = true opts.Watch = true
return c.client.Get(). return c.GetClient().Get().
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
VersionedParams(&opts, $.schemeParameterCodec|raw$). VersionedParams(&opts, $.schemeParameterCodec|raw$).
Timeout(timeout). Timeout(timeout).
Watch(ctx) Watch(ctx)
@@ -710,8 +787,8 @@ var patchTemplate = `
// Patch applies the patch and returns the patched $.resultType|private$. // Patch applies the patch and returns the patched $.resultType|private$.
func (c *$.type|privatePlural$) Patch(ctx context.Context, name string, pt $.PatchType|raw$, data []byte, opts $.PatchOptions|raw$, subresources ...string) (result *$.resultType|raw$, err error) { func (c *$.type|privatePlural$) Patch(ctx context.Context, name string, pt $.PatchType|raw$, data []byte, opts $.PatchOptions|raw$, subresources ...string) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${} result = &$.resultType|raw${}
err = c.client.Patch(pt). err = c.GetClient().Patch(pt).
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
Name(name). Name(name).
SubResource(subresources...). SubResource(subresources...).
@@ -739,8 +816,8 @@ func (c *$.type|privatePlural$) Apply(ctx context.Context, $.inputType|private$
return nil, fmt.Errorf("$.inputType|private$.Name must be provided to Apply") return nil, fmt.Errorf("$.inputType|private$.Name must be provided to Apply")
} }
result = &$.resultType|raw${} result = &$.resultType|raw${}
err = c.client.Patch($.ApplyPatchType|raw$). err = c.GetClient().Patch($.ApplyPatchType|raw$).
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
Name(*name). Name(*name).
VersionedParams(&patchOpts, $.schemeParameterCodec|raw$). VersionedParams(&patchOpts, $.schemeParameterCodec|raw$).
@@ -751,38 +828,6 @@ func (c *$.type|privatePlural$) Apply(ctx context.Context, $.inputType|private$
} }
` `
var applyStatusTemplate = `
// ApplyStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus().
func (c *$.type|privatePlural$) ApplyStatus(ctx context.Context, $.inputType|private$ *$.inputApplyConfig|raw$, opts $.ApplyOptions|raw$) (result *$.resultType|raw$, err error) {
if $.inputType|private$ == nil {
return nil, fmt.Errorf("$.inputType|private$ provided to Apply must not be nil")
}
patchOpts := opts.ToPatchOptions()
data, err := $.jsonMarshal|raw$($.inputType|private$)
if err != nil {
return nil, err
}
name := $.inputType|private$.Name
if name == nil {
return nil, fmt.Errorf("$.inputType|private$.Name must be provided to Apply")
}
result = &$.resultType|raw${}
err = c.client.Patch($.ApplyPatchType|raw$).
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|resource$").
Name(*name).
SubResource("status").
VersionedParams(&patchOpts, $.schemeParameterCodec|raw$).
Body(data).
Do(ctx).
Into(result)
return
}
`
var applySubresourceTemplate = ` var applySubresourceTemplate = `
// Apply takes top resource name and the apply declarative configuration for $.subresourcePath$, // Apply takes top resource name and the apply declarative configuration for $.subresourcePath$,
// applies it and returns the applied $.resultType|private$, and an error, if there is any. // applies it and returns the applied $.resultType|private$, and an error, if there is any.
@@ -797,8 +842,8 @@ func (c *$.type|privatePlural$) Apply(ctx context.Context, $.type|private$Name s
} }
result = &$.resultType|raw${} result = &$.resultType|raw${}
err = c.client.Patch($.ApplyPatchType|raw$). err = c.GetClient().Patch($.ApplyPatchType|raw$).
$if .namespaced$Namespace(c.ns).$end$ $if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$"). Resource("$.type|resource$").
Name($.type|private$Name). Name($.type|private$Name).
SubResource("$.subresourcePath$"). SubResource("$.subresourcePath$").