Skip to content

Commit 412bf7a

Browse files
create a cluser scoped cache separately
Signed-off-by: varshaprasad96 <[email protected]>
1 parent 50bfd90 commit 412bf7a

File tree

2 files changed

+61
-14
lines changed

2 files changed

+61
-14
lines changed

pkg/cache/multi_namespace_cache.go

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const globalCache = "_cluster-scope"
4141
// MultiNamespacedCacheBuilder - Builder function to create a new multi-namespaced cache.
4242
// This will scope the cache to a list of namespaces. Listing for all namespaces
4343
// will list for all the namespaces that this knows about. By default this will create
44-
// a global cache for cluster scoped resource (having empty namespace). Note that this is not intended
44+
// a global cache for cluster scoped resource. Note that this is not intended
4545
// to be used for excluding namespaces, this is better done via a Predicate. Also note that
4646
// you may face performance issues when using this with a high number of namespaces.
4747
func MultiNamespacedCacheBuilder(namespaces []string) NewCacheFunc {
@@ -59,9 +59,6 @@ func MultiNamespacedCacheBuilder(namespaces []string) NewCacheFunc {
5959
return nil, fmt.Errorf("error creating global cache %v", err)
6060
}
6161

62-
// add global cache to the cacheMap
63-
caches[globalCache] = gCache
64-
6562
for _, ns := range namespaces {
6663
opts.Namespace = ns
6764
c, err := New(config, opts)
@@ -70,7 +67,7 @@ func MultiNamespacedCacheBuilder(namespaces []string) NewCacheFunc {
7067
}
7168
caches[ns] = c
7269
}
73-
return &multiNamespaceCache{namespaceToCache: caches, Scheme: opts.Scheme, RESTMapper: opts.Mapper}, nil
70+
return &multiNamespaceCache{namespaceToCache: caches, Scheme: opts.Scheme, RESTMapper: opts.Mapper, clusterCache: gCache}, nil
7471
}
7572
}
7673

@@ -82,6 +79,7 @@ type multiNamespaceCache struct {
8279
namespaceToCache map[string]Cache
8380
Scheme *runtime.Scheme
8481
RESTMapper meta.RESTMapper
82+
clusterCache Cache
8583
}
8684

8785
var _ Cache = &multiNamespaceCache{}
@@ -96,6 +94,21 @@ func (c *multiNamespaceCache) GetInformer(ctx context.Context, obj client.Object
9694
}
9795
informers[ns] = informer
9896
}
97+
98+
isNamespaced, err := objectutil.IsAPINamespaced(obj, c.Scheme, c.RESTMapper)
99+
if err != nil {
100+
return nil, err
101+
}
102+
103+
if !isNamespaced {
104+
clusterCacheInf, err := c.clusterCache.GetInformer(ctx, obj)
105+
if err != nil {
106+
return nil, err
107+
}
108+
informers[globalCache] = clusterCacheInf
109+
110+
}
111+
99112
return &multiNamespaceInformer{namespaceToInformer: informers}, nil
100113
}
101114

@@ -108,10 +121,33 @@ func (c *multiNamespaceCache) GetInformerForKind(ctx context.Context, gvk schema
108121
}
109122
informers[ns] = informer
110123
}
124+
125+
isNamespaced, err := objectutil.IsAPINamespacedWithGVK(gvk, c.Scheme, c.RESTMapper)
126+
if err != nil {
127+
return nil, err
128+
}
129+
130+
if !isNamespaced {
131+
clusterCacheInf, err := c.clusterCache.GetInformerForKind(ctx, gvk)
132+
if err != nil {
133+
return nil, err
134+
}
135+
informers[globalCache] = clusterCacheInf
136+
}
137+
111138
return &multiNamespaceInformer{namespaceToInformer: informers}, nil
112139
}
113140

114141
func (c *multiNamespaceCache) Start(ctx context.Context) error {
142+
// start global cache
143+
go func() {
144+
err := c.clusterCache.Start(ctx)
145+
if err != nil {
146+
log.Error(err, "cluster scoped cache failed to start")
147+
}
148+
}()
149+
150+
// start namespaced caches
115151
for ns, cache := range c.namespaceToCache {
116152
go func(ns string, cache Cache) {
117153
err := cache.Start(ctx)
@@ -120,6 +156,7 @@ func (c *multiNamespaceCache) Start(ctx context.Context) error {
120156
}
121157
}(ns, cache)
122158
}
159+
123160
<-ctx.Done()
124161
return nil
125162
}
@@ -131,6 +168,11 @@ func (c *multiNamespaceCache) WaitForCacheSync(ctx context.Context) bool {
131168
synced = s
132169
}
133170
}
171+
172+
// check if cluster scoped cache has synced
173+
if !c.clusterCache.WaitForCacheSync(ctx) {
174+
synced = false
175+
}
134176
return synced
135177
}
136178

@@ -140,6 +182,10 @@ func (c *multiNamespaceCache) IndexField(ctx context.Context, obj client.Object,
140182
return err
141183
}
142184
}
185+
186+
if err := c.clusterCache.IndexField(ctx, obj, field, extractValue); err != nil {
187+
return fmt.Errorf("error adding index on object with cluster scoped cache %v", err)
188+
}
143189
return nil
144190
}
145191

@@ -151,8 +197,7 @@ func (c *multiNamespaceCache) Get(ctx context.Context, key client.ObjectKey, obj
151197

152198
if !isNamespaced {
153199
// Look into the global cache to fetch the object
154-
cache := c.namespaceToCache[globalCache]
155-
return cache.Get(ctx, key, obj)
200+
return c.clusterCache.Get(ctx, key, obj)
156201
}
157202

158203
cache, ok := c.namespaceToCache[key.Namespace]
@@ -174,8 +219,7 @@ func (c *multiNamespaceCache) List(ctx context.Context, list client.ObjectList,
174219

175220
if !isNamespaced {
176221
// Look at the global cache to get the objects with the specified GVK
177-
cache := c.namespaceToCache[globalCache]
178-
return cache.List(ctx, list, opts...)
222+
return c.clusterCache.List(ctx, list, opts...)
179223
}
180224

181225
if listOpts.Namespace != corev1.NamespaceAll {
@@ -199,10 +243,7 @@ func (c *multiNamespaceCache) List(ctx context.Context, list client.ObjectList,
199243
limitSet := listOpts.Limit > 0
200244

201245
var resourceVersion string
202-
for ns, cache := range c.namespaceToCache {
203-
if ns == globalCache {
204-
continue
205-
}
246+
for _, cache := range c.namespaceToCache {
206247
listObj := list.DeepCopyObject().(client.ObjectList)
207248
err = cache.List(ctx, listObj, &listOpts)
208249
if err != nil {

pkg/internal/objectutil/objectutil.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,13 @@ func IsAPINamespaced(obj runtime.Object, scheme *runtime.Scheme, restmapper apim
5555
return false, err
5656
}
5757

58-
restmapping, err := restmapper.RESTMapping(schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind})
58+
return IsAPINamespacedWithGVK(gvk, scheme, restmapper)
59+
}
60+
61+
// IsAPINamespacedWithGVK returns true if the object having the provided
62+
// GVK is namespace scoped.
63+
func IsAPINamespacedWithGVK(gk schema.GroupVersionKind, scheme *runtime.Scheme, restmapper apimeta.RESTMapper) (bool, error) {
64+
restmapping, err := restmapper.RESTMapping(schema.GroupKind{Group: gk.Group, Kind: gk.Kind})
5965
if err != nil {
6066
return false, fmt.Errorf("failed to get restmapping: %w", err)
6167
}

0 commit comments

Comments
 (0)