@@ -20,11 +20,9 @@ import (
20
20
"context"
21
21
"fmt"
22
22
"reflect"
23
- "sync"
24
23
25
24
"github.com/kubernetes-sigs/controller-runtime/pkg/client/apiutil"
26
25
"k8s.io/apimachinery/pkg/api/meta"
27
- "k8s.io/apimachinery/pkg/apis/meta/v1"
28
26
"k8s.io/apimachinery/pkg/runtime"
29
27
"k8s.io/apimachinery/pkg/runtime/serializer"
30
28
"k8s.io/client-go/kubernetes/scheme"
@@ -60,209 +58,93 @@ func New(config *rest.Config, options Options) (Client, error) {
60
58
}
61
59
}
62
60
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 ),
72
70
}
73
71
74
72
return c , nil
75
73
}
76
74
77
- var _ Client = & populatingClient {}
75
+ var _ Client = & client {}
78
76
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 initialized
78
+ // new clients at the time they are used, and caches the client.
79
+ type client struct {
80
+ cache clientCache
81
+ paramCodec runtime.ParameterCodec
151
82
}
152
83
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 )
163
87
if err != nil {
164
88
return err
165
89
}
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 ()).
178
93
Body (obj ).
179
94
Do ().
180
95
Into (obj )
181
96
}
182
97
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 )
186
101
if err != nil {
187
102
return err
188
103
}
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 ()).
202
108
Body (obj ).
203
109
Do ().
204
110
Into (obj )
205
111
}
206
112
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 )
210
116
if err != nil {
211
117
return err
212
118
}
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 ()).
224
123
Do ().
225
124
Error ()
226
125
}
227
126
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 )
231
130
if err != nil {
232
131
return err
233
132
}
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 )
247
137
}
248
138
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 )
252
142
if err != nil {
253
143
return err
254
144
}
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 ()).
266
148
Body (obj ).
267
149
VersionedParams (opts .AsListOptions (), c .paramCodec ).
268
150
Do ().
0 commit comments