Skip to content

Commit ea9472d

Browse files
committed
cleanup client/config
1 parent d791801 commit ea9472d

File tree

3 files changed

+196
-224
lines changed

3 files changed

+196
-224
lines changed

pkg/client/client.go

Lines changed: 48 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@ import (
2020
"context"
2121
"fmt"
2222
"reflect"
23-
"sync"
2423

2524
"github.com/kubernetes-sigs/controller-runtime/pkg/client/apiutil"
2625
"k8s.io/apimachinery/pkg/api/meta"
27-
"k8s.io/apimachinery/pkg/apis/meta/v1"
2826
"k8s.io/apimachinery/pkg/runtime"
2927
"k8s.io/apimachinery/pkg/runtime/serializer"
3028
"k8s.io/client-go/kubernetes/scheme"
@@ -60,209 +58,93 @@ func New(config *rest.Config, options Options) (Client, error) {
6058
}
6159
}
6260

63-
c := &populatingClient{
64-
config: config,
65-
scheme: options.Scheme,
66-
mapper: options.Mapper,
67-
codecs: serializer.NewCodecFactory(options.Scheme),
68-
paramCodec: runtime.NewParameterCodec(options.Scheme),
69-
clientsByType: make(map[reflect.Type]rest.Interface),
70-
resourcesByType: make(map[reflect.Type]string),
71-
mappingByType: make(map[reflect.Type]*meta.RESTMapping),
61+
c := &client{
62+
cache: clientCache{
63+
config: config,
64+
scheme: options.Scheme,
65+
mapper: options.Mapper,
66+
codecs: serializer.NewCodecFactory(options.Scheme),
67+
resourceByType: make(map[reflect.Type]*resourceMeta),
68+
},
69+
paramCodec: runtime.NewParameterCodec(options.Scheme),
7270
}
7371

7472
return c, nil
7573
}
7674

77-
var _ Client = &populatingClient{}
75+
var _ Client = &client{}
7876

79-
// populatingClient is an Client that reads and writes directly from/to an API server. It lazily initialized
80-
// new clients when they are used.
81-
type populatingClient struct {
82-
config *rest.Config
83-
scheme *runtime.Scheme
84-
mapper meta.RESTMapper
85-
86-
codecs serializer.CodecFactory
87-
paramCodec runtime.ParameterCodec
88-
clientsByType map[reflect.Type]rest.Interface
89-
mappingByType map[reflect.Type]*meta.RESTMapping
90-
resourcesByType map[reflect.Type]string
91-
mu sync.RWMutex
92-
}
93-
94-
// makeClient maps obj to a Kubernetes Resource and constructs a populatingClient for that Resource.
95-
func (c *populatingClient) makeClient(obj runtime.Object) (rest.Interface, *meta.RESTMapping, string, error) {
96-
gvk, err := apiutil.GVKForObject(obj, c.scheme)
97-
if err != nil {
98-
return nil, nil, "", err
99-
}
100-
client, err := apiutil.RESTClientForGVK(gvk, c.config, c.codecs)
101-
if err != nil {
102-
return nil, nil, "", err
103-
}
104-
mapping, err := c.mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
105-
if err != nil {
106-
return nil, nil, "", err
107-
}
108-
return client, mapping, mapping.Resource, nil
109-
}
110-
111-
// clientFor returns a raw rest.Client for the given object type.
112-
func (c *populatingClient) clientFor(obj runtime.Object) (rest.Interface, *meta.RESTMapping, string, error) {
113-
typ := reflect.TypeOf(obj)
114-
115-
// It's better to do creation work twice than to not let multiple
116-
// people make requests at once
117-
c.mu.RLock()
118-
client, known := c.clientsByType[typ]
119-
resource, _ := c.resourcesByType[typ]
120-
mapping, _ := c.mappingByType[typ]
121-
c.mu.RUnlock()
122-
123-
// Initialize a new Client
124-
if !known {
125-
var err error
126-
client, mapping, resource, err = c.makeClient(obj)
127-
if err != nil {
128-
return nil, mapping, "", err
129-
}
130-
c.mu.Lock()
131-
defer c.mu.Unlock()
132-
c.clientsByType[typ] = client
133-
c.resourcesByType[typ] = resource
134-
c.mappingByType[typ] = mapping
135-
}
136-
137-
return client, mapping, resource, nil
138-
}
139-
140-
func (c *populatingClient) metaAndClientFor(obj runtime.Object) (v1.Object, rest.Interface, *meta.RESTMapping, string, error) {
141-
client, mapping, resource, err := c.clientFor(obj)
142-
if err != nil {
143-
return nil, nil, nil, "", err
144-
}
145-
146-
meta, err := meta.Accessor(obj)
147-
if err != nil {
148-
return nil, nil, nil, "", err
149-
}
150-
return meta, client, mapping, resource, err
77+
// client is a client.Client that reads and writes directly from/to an API server. It lazily initializes
78+
// new clients at the time they are used, and caches the client.
79+
type client struct {
80+
cache clientCache
81+
paramCodec runtime.ParameterCodec
15182
}
15283

153-
func isNamespaced(mapping *meta.RESTMapping) bool {
154-
if mapping.Scope.Name() == meta.RESTScopeNameRoot {
155-
return false
156-
}
157-
return true
158-
}
159-
160-
// Create implements Client
161-
func (c *populatingClient) Create(ctx context.Context, obj runtime.Object) error {
162-
meta, client, mapping, resource, err := c.metaAndClientFor(obj)
84+
// Create implements client.Client
85+
func (c *client) Create(ctx context.Context, obj runtime.Object) error {
86+
o, err := c.cache.getObjMeta(obj)
16387
if err != nil {
16488
return err
16589
}
166-
167-
if isNamespaced(mapping) {
168-
return client.Post().
169-
Namespace(meta.GetNamespace()).
170-
Resource(resource).
171-
Body(obj).
172-
Do().
173-
Into(obj)
174-
}
175-
176-
return client.Post().
177-
Resource(resource).
90+
return o.Post().
91+
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
92+
Resource(o.resource()).
17893
Body(obj).
17994
Do().
18095
Into(obj)
18196
}
18297

183-
// Update implements Client
184-
func (c *populatingClient) Update(ctx context.Context, obj runtime.Object) error {
185-
meta, client, mapping, resource, err := c.metaAndClientFor(obj)
98+
// Update implements client.Client
99+
func (c *client) Update(ctx context.Context, obj runtime.Object) error {
100+
o, err := c.cache.getObjMeta(obj)
186101
if err != nil {
187102
return err
188103
}
189-
if isNamespaced(mapping) {
190-
return client.Put().
191-
Namespace(meta.GetNamespace()).
192-
Resource(resource).
193-
Name(meta.GetName()).
194-
Body(obj).
195-
Do().
196-
Into(obj)
197-
}
198-
199-
return client.Put().
200-
Resource(resource).
201-
Name(meta.GetName()).
104+
return o.Put().
105+
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
106+
Resource(o.resource()).
107+
Name(o.GetName()).
202108
Body(obj).
203109
Do().
204110
Into(obj)
205111
}
206112

207-
// Delete implements Client
208-
func (c *populatingClient) Delete(ctx context.Context, obj runtime.Object) error {
209-
meta, client, mapping, resource, err := c.metaAndClientFor(obj)
113+
// Delete implements client.Client
114+
func (c *client) Delete(ctx context.Context, obj runtime.Object) error {
115+
o, err := c.cache.getObjMeta(obj)
210116
if err != nil {
211117
return err
212118
}
213-
if isNamespaced(mapping) {
214-
return client.Delete().
215-
Namespace(meta.GetNamespace()).
216-
Resource(resource).
217-
Name(meta.GetName()).
218-
Do().
219-
Error()
220-
}
221-
return client.Delete().
222-
Resource(resource).
223-
Name(meta.GetName()).
119+
return o.Delete().
120+
NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
121+
Resource(o.resource()).
122+
Name(o.GetName()).
224123
Do().
225124
Error()
226125
}
227126

228-
// Get implements Client
229-
func (c *populatingClient) Get(ctx context.Context, key ObjectKey, obj runtime.Object) error {
230-
_, client, mapping, resource, err := c.metaAndClientFor(obj)
127+
// Get implements client.Client
128+
func (c *client) Get(ctx context.Context, key ObjectKey, obj runtime.Object) error {
129+
r, err := c.cache.getResource(obj)
231130
if err != nil {
232131
return err
233132
}
234-
if isNamespaced(mapping) {
235-
return client.Get().
236-
Namespace(key.Namespace).
237-
Resource(resource).
238-
Name(key.Name).
239-
Do().
240-
Into(obj)
241-
}
242-
return client.Get().
243-
Resource(resource).
244-
Name(key.Name).
245-
Do().
246-
Into(obj)
133+
return r.Get().
134+
NamespaceIfScoped(key.Namespace, r.isNamespaced()).
135+
Resource(r.resource()).
136+
Name(key.Name).Do().Into(obj)
247137
}
248138

249-
// List implements Client
250-
func (c *populatingClient) List(ctx context.Context, opts *ListOptions, obj runtime.Object) error {
251-
_, client, mapping, resource, err := c.metaAndClientFor(obj)
139+
// List implements client.Client
140+
func (c *client) List(ctx context.Context, opts *ListOptions, obj runtime.Object) error {
141+
r, err := c.cache.getResource(obj)
252142
if err != nil {
253143
return err
254144
}
255-
if isNamespaced(mapping) && opts != nil && len(opts.Namespace) > 0 {
256-
return client.Get().
257-
Namespace(opts.Namespace).
258-
Resource(resource).
259-
Body(obj).
260-
VersionedParams(opts.AsListOptions(), c.paramCodec).
261-
Do().
262-
Into(obj)
263-
}
264-
return client.Get().
265-
Resource(resource).
145+
return r.Get().
146+
NamespaceIfScoped(opts.Namespace, r.isNamespaced()).
147+
Resource(r.resource()).
266148
Body(obj).
267149
VersionedParams(opts.AsListOptions(), c.paramCodec).
268150
Do().

0 commit comments

Comments
 (0)