@@ -43,7 +43,7 @@ import (
43
43
// WildcardCache is a cache that operates on a /clusters/* endpoint.
44
44
type WildcardCache interface {
45
45
cache.Cache
46
- getSharedInformer (obj runtime.Object ) (k8scache.SharedIndexInformer , schema.GroupVersionKind , apimeta.RESTScopeName , bool , error )
46
+ getSharedInformer (obj runtime.Object ) (k8scache.SharedIndexInformer , schema.GroupVersionKind , apimeta.RESTScopeName , error )
47
47
}
48
48
49
49
// NewWildcardCache returns a cache.Cache that handles multi-cluster watches
@@ -80,6 +80,8 @@ func NewWildcardCache(config *rest.Config, opts cache.Options) (WildcardCache, e
80
80
Unstructured : make (map [schema.GroupVersionKind ]k8scache.SharedIndexInformer ),
81
81
Metadata : make (map [schema.GroupVersionKind ]k8scache.SharedIndexInformer ),
82
82
},
83
+
84
+ readerFailOnMissingInformer : opts .ReaderFailOnMissingInformer ,
83
85
}
84
86
85
87
opts .NewInformer = func (watcher k8scache.ListerWatcher , obj runtime.Object , duration time.Duration , indexers k8scache.Indexers ) k8scache.SharedIndexInformer {
@@ -121,25 +123,60 @@ type wildcardCache struct {
121
123
scheme * runtime.Scheme
122
124
mapper apimeta.RESTMapper
123
125
tracker informerTracker
126
+
127
+ readerFailOnMissingInformer bool
124
128
}
125
129
126
- func (c * wildcardCache ) getSharedInformer (obj runtime.Object ) (k8scache.SharedIndexInformer , schema.GroupVersionKind , apimeta.RESTScopeName , bool , error ) {
130
+ func (c * wildcardCache ) getSharedInformer (obj runtime.Object ) (k8scache.SharedIndexInformer , schema.GroupVersionKind , apimeta.RESTScopeName , error ) {
127
131
gvk , err := apiutil .GVKForObject (obj , c .scheme )
128
132
if err != nil {
129
- return nil , gvk , "" , false , err
133
+ return nil , gvk , "" , fmt . Errorf ( "failed to get GVK for object: %w" , err )
130
134
}
131
135
136
+ // We need the non-list GVK, so chop off the "List" from the end of the kind.
137
+ gvk .Kind = strings .TrimSuffix (gvk .Kind , "List" )
138
+
132
139
mapping , err := c .mapper .RESTMapping (gvk .GroupKind (), gvk .Version )
133
140
if err != nil {
134
- return nil , gvk , "" , false , err
141
+ return nil , gvk , "" , fmt . Errorf ( "failed to get REST mapping: %w" , err )
135
142
}
136
143
137
144
infs := c .tracker .informersByType (obj )
138
145
c .tracker .lock .RLock ()
139
146
inf , ok := infs [gvk ]
140
147
c .tracker .lock .RUnlock ()
141
148
142
- return inf , gvk , mapping .Scope .Name (), ok , nil
149
+ // we need to create a new informer here.
150
+ if ! ok {
151
+ // we have been instructed to fail if the informer is missing.
152
+ if c .readerFailOnMissingInformer {
153
+ return nil , gvk , "" , & cache.ErrResourceNotCached {}
154
+ }
155
+
156
+ // Let's generate a new object from the chopped GVK, since the original obj might be of *List type.
157
+ o , err := c .scheme .New (gvk )
158
+ if err != nil {
159
+ return nil , gvk , "" , fmt .Errorf ("failed to create object for GVK: %w" , err )
160
+ }
161
+
162
+ // Call GetInformer, but we don't care about the output. We just need to make sure that our NewInformer
163
+ // func has been called, which registers the new informer in our tracker.
164
+ if _ , err := c .Cache .GetInformer (context .TODO (), o .(client.Object )); err != nil {
165
+ return nil , gvk , "" , fmt .Errorf ("failed to create informer: %w" , err )
166
+ }
167
+
168
+ // Now we should be able to find the informer.
169
+ infs := c .tracker .informersByType (obj )
170
+ c .tracker .lock .RLock ()
171
+ inf , ok = infs [gvk ]
172
+ c .tracker .lock .RUnlock ()
173
+
174
+ if ! ok {
175
+ return nil , gvk , "" , fmt .Errorf ("failed to find newly started informer for %v" , gvk )
176
+ }
177
+ }
178
+
179
+ return inf , gvk , mapping .Scope .Name (), nil
143
180
}
144
181
145
182
// IndexField adds an index for the given object kind.
0 commit comments