Skip to content

Commit 611684e

Browse files
committed
Provide a truly lazy restmapper
Rework WithLazyDiscovery to use DeferredDiscoveryRESTMapper that will lazily query the provided client for discovery information to do REST mappings.
1 parent 3c4deba commit 611684e

File tree

2 files changed

+28
-79
lines changed

2 files changed

+28
-79
lines changed

pkg/client/apiutil/dynamicrestmapper.go

Lines changed: 28 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ package apiutil
1818

1919
import (
2020
"sync"
21-
"sync/atomic"
2221

2322
"golang.org/x/time/rate"
2423
"k8s.io/apimachinery/pkg/api/meta"
2524
"k8s.io/apimachinery/pkg/runtime/schema"
2625
"k8s.io/client-go/discovery"
26+
"k8s.io/client-go/discovery/cached/memory"
2727
"k8s.io/client-go/rest"
2828
"k8s.io/client-go/restmapper"
2929
)
@@ -37,9 +37,6 @@ type dynamicRESTMapper struct {
3737
newMapper func() (meta.RESTMapper, error)
3838

3939
lazy bool
40-
// Used for lazy init.
41-
inited uint32
42-
initMtx sync.Mutex
4340
}
4441

4542
// DynamicRESTMapperOption is a functional option on the dynamicRESTMapper.
@@ -76,30 +73,43 @@ func WithCustomMapper(newMapper func() (meta.RESTMapper, error)) DynamicRESTMapp
7673
// RESTMapper dynamically discovers resource types at runtime. opts
7774
// configure the RESTMapper.
7875
func NewDynamicRESTMapper(cfg *rest.Config, opts ...DynamicRESTMapperOption) (meta.RESTMapper, error) {
79-
client, err := discovery.NewDiscoveryClientForConfig(cfg)
80-
if err != nil {
81-
return nil, err
82-
}
8376
drm := &dynamicRESTMapper{
8477
limiter: rate.NewLimiter(rate.Limit(defaultRefillRate), defaultLimitSize),
85-
newMapper: func() (meta.RESTMapper, error) {
86-
groupResources, err := restmapper.GetAPIGroupResources(client)
87-
if err != nil {
88-
return nil, err
89-
}
90-
return restmapper.NewDiscoveryRESTMapper(groupResources), nil
91-
},
9278
}
9379
for _, opt := range opts {
94-
if err = opt(drm); err != nil {
80+
if err := opt(drm); err != nil {
9581
return nil, err
9682
}
9783
}
98-
if !drm.lazy {
99-
if err := drm.setStaticMapper(); err != nil {
84+
85+
if drm.newMapper == nil {
86+
// If custom mapper is not set, we wse NewDeferredDiscoveryRESTMapper for lazy loading
87+
// or standard NewDiscoveryRESTMapper for other cases.
88+
client, err := discovery.NewDiscoveryClientForConfig(cfg)
89+
if err != nil {
10090
return nil, err
10191
}
92+
93+
if !drm.lazy {
94+
drm.newMapper = func() (meta.RESTMapper, error) {
95+
groupResources, err := restmapper.GetAPIGroupResources(client)
96+
if err != nil {
97+
return nil, err
98+
}
99+
100+
return restmapper.NewDiscoveryRESTMapper(groupResources), nil
101+
}
102+
} else {
103+
drm.newMapper = func() (meta.RESTMapper, error) {
104+
return restmapper.NewDeferredDiscoveryRESTMapper(memory.NewMemCacheClient(client)), nil
105+
}
106+
}
107+
}
108+
109+
if err := drm.setStaticMapper(); err != nil {
110+
return nil, err
102111
}
112+
103113
return drm, nil
104114
}
105115

@@ -124,23 +134,6 @@ func (drm *dynamicRESTMapper) setStaticMapper() error {
124134
return nil
125135
}
126136

127-
// init initializes drm only once if drm is lazy.
128-
func (drm *dynamicRESTMapper) init() (err error) {
129-
// skip init if drm is not lazy or has initialized
130-
if !drm.lazy || atomic.LoadUint32(&drm.inited) != 0 {
131-
return nil
132-
}
133-
134-
drm.initMtx.Lock()
135-
defer drm.initMtx.Unlock()
136-
if drm.inited == 0 {
137-
if err = drm.setStaticMapper(); err == nil {
138-
atomic.StoreUint32(&drm.inited, 1)
139-
}
140-
}
141-
return err
142-
}
143-
144137
// checkAndReload attempts to call the given callback, which is assumed to be dependent
145138
// on the data in the restmapper.
146139
//
@@ -198,9 +191,6 @@ func (drm *dynamicRESTMapper) checkAndReload(checkNeedsReload func() error) erro
198191
// TODO: wrap reload errors on NoKindMatchError with go 1.13 errors.
199192

200193
func (drm *dynamicRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
201-
if err := drm.init(); err != nil {
202-
return schema.GroupVersionKind{}, err
203-
}
204194
var gvk schema.GroupVersionKind
205195
err := drm.checkAndReload(func() error {
206196
var err error
@@ -211,9 +201,6 @@ func (drm *dynamicRESTMapper) KindFor(resource schema.GroupVersionResource) (sch
211201
}
212202

213203
func (drm *dynamicRESTMapper) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) {
214-
if err := drm.init(); err != nil {
215-
return nil, err
216-
}
217204
var gvks []schema.GroupVersionKind
218205
err := drm.checkAndReload(func() error {
219206
var err error
@@ -224,10 +211,6 @@ func (drm *dynamicRESTMapper) KindsFor(resource schema.GroupVersionResource) ([]
224211
}
225212

226213
func (drm *dynamicRESTMapper) ResourceFor(input schema.GroupVersionResource) (schema.GroupVersionResource, error) {
227-
if err := drm.init(); err != nil {
228-
return schema.GroupVersionResource{}, err
229-
}
230-
231214
var gvr schema.GroupVersionResource
232215
err := drm.checkAndReload(func() error {
233216
var err error
@@ -238,9 +221,6 @@ func (drm *dynamicRESTMapper) ResourceFor(input schema.GroupVersionResource) (sc
238221
}
239222

240223
func (drm *dynamicRESTMapper) ResourcesFor(input schema.GroupVersionResource) ([]schema.GroupVersionResource, error) {
241-
if err := drm.init(); err != nil {
242-
return nil, err
243-
}
244224
var gvrs []schema.GroupVersionResource
245225
err := drm.checkAndReload(func() error {
246226
var err error
@@ -251,9 +231,6 @@ func (drm *dynamicRESTMapper) ResourcesFor(input schema.GroupVersionResource) ([
251231
}
252232

253233
func (drm *dynamicRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) {
254-
if err := drm.init(); err != nil {
255-
return nil, err
256-
}
257234
var mapping *meta.RESTMapping
258235
err := drm.checkAndReload(func() error {
259236
var err error
@@ -264,9 +241,6 @@ func (drm *dynamicRESTMapper) RESTMapping(gk schema.GroupKind, versions ...strin
264241
}
265242

266243
func (drm *dynamicRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) {
267-
if err := drm.init(); err != nil {
268-
return nil, err
269-
}
270244
var mappings []*meta.RESTMapping
271245
err := drm.checkAndReload(func() error {
272246
var err error
@@ -277,9 +251,6 @@ func (drm *dynamicRESTMapper) RESTMappings(gk schema.GroupKind, versions ...stri
277251
}
278252

279253
func (drm *dynamicRESTMapper) ResourceSingularizer(resource string) (string, error) {
280-
if err := drm.init(); err != nil {
281-
return "", err
282-
}
283254
var singular string
284255
err := drm.checkAndReload(func() error {
285256
var err error

pkg/client/apiutil/dynamicrestmapper_test.go

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package apiutil
1818

1919
import (
20-
"fmt"
2120
"time"
2221

2322
. "github.com/onsi/ginkgo/v2"
@@ -145,27 +144,6 @@ var _ = Describe("Dynamic REST Mapper", func() {
145144
By("ensuring that it was only refreshed once")
146145
Expect(count).To(Equal(1))
147146
})
148-
149-
It("should lazily initialize if the lazy option is used", func() {
150-
var err error
151-
var failedOnce bool
152-
mockErr := fmt.Errorf("mock failed once")
153-
mapper, err = NewDynamicRESTMapper(cfg, WithLazyDiscovery, WithCustomMapper(func() (meta.RESTMapper, error) {
154-
// Make newMapper fail once
155-
if !failedOnce {
156-
failedOnce = true
157-
return nil, mockErr
158-
}
159-
baseMapper := meta.NewDefaultRESTMapper(nil)
160-
addToMapper(baseMapper)
161-
return baseMapper, nil
162-
}))
163-
Expect(err).NotTo(HaveOccurred())
164-
Expect(mapper.(*dynamicRESTMapper).staticMapper).To(BeNil())
165-
166-
Expect(callWithTarget()).To(MatchError(mockErr))
167-
Expect(callWithTarget()).To(Succeed())
168-
})
169147
}
170148

171149
Describe("KindFor", func() {

0 commit comments

Comments
 (0)