@@ -77,6 +77,9 @@ type InformersMap struct {
77
77
78
78
// unstructuredInformerByGVK is a cache of informers for unstructured types
79
79
// keyed by groupVersionKind
80
+ // This is separate from informerByGVK because you don't want to
81
+ // request a structured object but get an unstructured informer and
82
+ // vice versa
80
83
unstructuredInformerByGVK map [schema.GroupVersionKind ]* MapEntry
81
84
82
85
// codecs is used to create a new REST client
@@ -100,6 +103,12 @@ type InformersMap struct {
100
103
started bool
101
104
}
102
105
106
+ type mutexMap struct {
107
+ informerByGVK map [schema.GroupVersionKind ]* MapEntry
108
+ // mu guards access to the unstructured map
109
+ mu * sync.RWMutex
110
+ }
111
+
103
112
// Start calls Run on each of the informers and sets started to true. Blocks on the stop channel.
104
113
func (ip * InformersMap ) Start (stop <- chan struct {}) error {
105
114
func () {
@@ -140,28 +149,31 @@ func (ip *InformersMap) WaitForCacheSync(stop <-chan struct{}) bool {
140
149
return cache .WaitForCacheSync (stop , syncedFuncs ... )
141
150
}
142
151
143
- func (ip * InformersMap ) getMapEntry (gvk schema.GroupVersionKind , isUnstructured bool ) (* MapEntry , bool ) {
144
- if isUnstructured {
145
- ip .unstructuredMu .RLock ()
146
- defer ip .unstructuredMu .RUnlock ()
147
- i , ok := ip .unstructuredInformerByGVK [gvk ]
148
- return i , ok
149
- }
150
- ip .mu .RLock ()
151
- defer ip .mu .RUnlock ()
152
- i , ok := ip .informersByGVK [gvk ]
153
- return i , ok
154
-
155
- }
156
-
157
152
// Get will create a new Informer and add it to the map of InformersMap if none exists. Returns
158
153
// the Informer from the map.
159
154
func (ip * InformersMap ) Get (gvk schema.GroupVersionKind , obj runtime.Object ) (* MapEntry , error ) {
160
155
_ , isUnstructured := obj .(* unstructured.Unstructured )
161
156
_ , isUnstructuredList := obj .(* unstructured.UnstructuredList )
162
- isUnstructured = isUnstructured || isUnstructuredList
157
+ mm := mutexMap {
158
+ informerByGVK : ip .informersByGVK ,
159
+ mu : & ip .mu ,
160
+ }
161
+ // If unstructured use the unstructured mutext and map.
162
+ if isUnstructured || isUnstructuredList {
163
+ mm = mutexMap {
164
+ informerByGVK : ip .unstructuredInformerByGVK ,
165
+ mu : & ip .unstructuredMu ,
166
+ }
167
+ }
168
+
163
169
// Return the informer if it is found
164
- i , ok := ip .getMapEntry (gvk , isUnstructured )
170
+ i , ok := func () (* MapEntry , bool ) {
171
+ mm .mu .RLock ()
172
+ defer mm .mu .RUnlock ()
173
+ i , ok := mm .informerByGVK [gvk ]
174
+ return i , ok
175
+
176
+ }()
165
177
if ok {
166
178
return i , nil
167
179
}
@@ -170,20 +182,9 @@ func (ip *InformersMap) Get(gvk schema.GroupVersionKind, obj runtime.Object) (*M
170
182
// need to be locked
171
183
var sync bool
172
184
i , err := func () (* MapEntry , error ) {
173
- var ok bool
174
- var i * MapEntry
175
- // Check the caches to see if we already have an Informer. If we do, return the Informer.
176
- // This is for the case where 2 routines tried to get the informer when it wasn't in the map
177
- // so neither returned early, but the first one created it.
178
- if isUnstructured {
179
- ip .unstructuredMu .Lock ()
180
- defer ip .unstructuredMu .Unlock ()
181
- i , ok = ip .unstructuredInformerByGVK [gvk ]
182
- } else {
183
- ip .mu .Lock ()
184
- defer ip .mu .Unlock ()
185
- i , ok = ip .informersByGVK [gvk ]
186
- }
185
+ mm .mu .Lock ()
186
+ defer mm .mu .Unlock ()
187
+ i , ok = mm .informerByGVK [gvk ]
187
188
if ok {
188
189
return i , nil
189
190
}
@@ -201,7 +202,7 @@ func (ip *InformersMap) Get(gvk schema.GroupVersionKind, obj runtime.Object) (*M
201
202
Informer : ni ,
202
203
Reader : CacheReader {indexer : ni .GetIndexer (), groupVersionKind : gvk },
203
204
}
204
- ip . setMap ( i , gvk , isUnstructured )
205
+ mm . informerByGVK [ gvk ] = i
205
206
206
207
// Start the Informer if need by
207
208
// TODO(seans): write thorough tests and document what happens here - can you add indexers?
@@ -226,16 +227,6 @@ func (ip *InformersMap) Get(gvk schema.GroupVersionKind, obj runtime.Object) (*M
226
227
return i , err
227
228
}
228
229
229
- // setMap - helper function to decide which map to add to.
230
- func (ip * InformersMap ) setMap (i * MapEntry , gvk schema.GroupVersionKind , isUnstructured bool ) {
231
- if isUnstructured {
232
- ip .unstructuredInformerByGVK [gvk ] = i
233
- } else {
234
-
235
- ip .informersByGVK [gvk ] = i
236
- }
237
- }
238
-
239
230
// newListWatch returns a new ListWatch object that can be used to create a SharedIndexInformer.
240
231
func (ip * InformersMap ) newListWatch (gvk schema.GroupVersionKind , isUnstructured bool ) (* cache.ListWatch , error ) {
241
232
// Kubernetes APIs work against Resources, not GroupVersionKinds. Map the
0 commit comments