@@ -35,7 +35,7 @@ import (
35
35
)
36
36
37
37
// clientListWatcherFunc knows how to create a ListWatcher
38
- type createListWatcherFunc func (gvk schema.GroupVersionKind , ip * specificInformersMap ) (* cache.ListWatch , error )
38
+ type createListWatcherFunc func (gvk schema.GroupVersionKind , namespace * string , ip * specificInformersMap ) (* cache.ListWatch , error )
39
39
40
40
// newSpecificInformersMap returns a new specificInformersMap (like
41
41
// the generical InformersMap, except that it doesn't implement WaitForCacheSync).
@@ -49,7 +49,7 @@ func newSpecificInformersMap(config *rest.Config,
49
49
config : config ,
50
50
Scheme : scheme ,
51
51
mapper : mapper ,
52
- informersByGVK : make (map [schema. GroupVersionKind ]* MapEntry ),
52
+ informers : make (map [MapKey ]* MapEntry ),
53
53
codecs : serializer .NewCodecFactory (scheme ),
54
54
paramCodec : runtime .NewParameterCodec (scheme ),
55
55
resync : resync ,
@@ -59,6 +59,11 @@ func newSpecificInformersMap(config *rest.Config,
59
59
return ip
60
60
}
61
61
62
+ type MapKey struct {
63
+ gvk schema.GroupVersionKind
64
+ namespace * string
65
+ }
66
+
62
67
// MapEntry contains the cached data for an Informer
63
68
type MapEntry struct {
64
69
// Informer is the cached informer
@@ -80,8 +85,8 @@ type specificInformersMap struct {
80
85
// mapper maps GroupVersionKinds to Resources
81
86
mapper meta.RESTMapper
82
87
83
- // informersByGVK is the cache of informers keyed by groupVersionKind
84
- informersByGVK map [schema. GroupVersionKind ]* MapEntry
88
+ // informers is the cache of informers keyed by groupVersionKind and namespace
89
+ informers map [MapKey ]* MapEntry
85
90
86
91
// codecs is used to create a new REST client
87
92
codecs serializer.CodecFactory
@@ -122,7 +127,7 @@ func (ip *specificInformersMap) Start(stop <-chan struct{}) {
122
127
ip .stop = stop
123
128
124
129
// Start each informer
125
- for _ , informer := range ip .informersByGVK {
130
+ for _ , informer := range ip .informers {
126
131
go informer .Informer .Run (stop )
127
132
}
128
133
@@ -136,27 +141,31 @@ func (ip *specificInformersMap) Start(stop <-chan struct{}) {
136
141
func (ip * specificInformersMap ) HasSyncedFuncs () []cache.InformerSynced {
137
142
ip .mu .RLock ()
138
143
defer ip .mu .RUnlock ()
139
- syncedFuncs := make ([]cache.InformerSynced , 0 , len (ip .informersByGVK ))
140
- for _ , informer := range ip .informersByGVK {
144
+ syncedFuncs := make ([]cache.InformerSynced , 0 , len (ip .informers ))
145
+ for _ , informer := range ip .informers {
141
146
syncedFuncs = append (syncedFuncs , informer .Informer .HasSynced )
142
147
}
143
148
return syncedFuncs
144
149
}
145
150
146
151
// Get will create a new Informer and add it to the map of specificInformersMap if none exists. Returns
147
152
// the Informer from the map.
148
- func (ip * specificInformersMap ) Get (gvk schema.GroupVersionKind , obj runtime.Object ) (bool , * MapEntry , error ) {
153
+ func (ip * specificInformersMap ) Get (gvk schema.GroupVersionKind , obj runtime.Object , namespace * string ) (bool , * MapEntry , error ) {
154
+ key := MapKey {
155
+ gvk : gvk ,
156
+ namespace : namespace ,
157
+ }
149
158
// Return the informer if it is found
150
159
i , started , ok := func () (* MapEntry , bool , bool ) {
151
160
ip .mu .RLock ()
152
161
defer ip .mu .RUnlock ()
153
- i , ok := ip .informersByGVK [ gvk ]
162
+ i , ok := ip .informers [ key ]
154
163
return i , ip .started , ok
155
164
}()
156
165
157
166
if ! ok {
158
167
var err error
159
- if i , started , err = ip .addInformerToMap (gvk , obj ); err != nil {
168
+ if i , started , err = ip .addInformerToMap (key , obj ); err != nil {
160
169
return started , nil , err
161
170
}
162
171
}
@@ -171,20 +180,20 @@ func (ip *specificInformersMap) Get(gvk schema.GroupVersionKind, obj runtime.Obj
171
180
return started , i , nil
172
181
}
173
182
174
- func (ip * specificInformersMap ) addInformerToMap (gvk schema. GroupVersionKind , obj runtime.Object ) (* MapEntry , bool , error ) {
183
+ func (ip * specificInformersMap ) addInformerToMap (key MapKey , obj runtime.Object ) (* MapEntry , bool , error ) {
175
184
ip .mu .Lock ()
176
185
defer ip .mu .Unlock ()
177
186
178
187
// Check the cache to see if we already have an Informer. If we do, return the Informer.
179
188
// This is for the case where 2 routines tried to get the informer when it wasn't in the map
180
189
// so neither returned early, but the first one created it.
181
- if i , ok := ip .informersByGVK [ gvk ]; ok {
190
+ if i , ok := ip .informers [ key ]; ok {
182
191
return i , ip .started , nil
183
192
}
184
193
185
194
// Create a NewSharedIndexInformer and add it to the map.
186
195
var lw * cache.ListWatch
187
- lw , err := ip .createListWatcher (gvk , ip )
196
+ lw , err := ip .createListWatcher (key . gvk , key . namespace , ip )
188
197
if err != nil {
189
198
return nil , false , err
190
199
}
@@ -193,9 +202,9 @@ func (ip *specificInformersMap) addInformerToMap(gvk schema.GroupVersionKind, ob
193
202
})
194
203
i := & MapEntry {
195
204
Informer : ni ,
196
- Reader : CacheReader {indexer : ni .GetIndexer (), groupVersionKind : gvk },
205
+ Reader : CacheReader {indexer : ni .GetIndexer (), groupVersionKind : key . gvk },
197
206
}
198
- ip .informersByGVK [ gvk ] = i
207
+ ip .informers [ key ] = i
199
208
200
209
// Start the Informer if need by
201
210
// TODO(seans): write thorough tests and document what happens here - can you add indexers?
@@ -207,7 +216,7 @@ func (ip *specificInformersMap) addInformerToMap(gvk schema.GroupVersionKind, ob
207
216
}
208
217
209
218
// newListWatch returns a new ListWatch object that can be used to create a SharedIndexInformer.
210
- func createStructuredListWatch (gvk schema.GroupVersionKind , ip * specificInformersMap ) (* cache.ListWatch , error ) {
219
+ func createStructuredListWatch (gvk schema.GroupVersionKind , namespace * string , ip * specificInformersMap ) (* cache.ListWatch , error ) {
211
220
// Kubernetes APIs work against Resources, not GroupVersionKinds. Map the
212
221
// groupVersionKind to the Resource API we will use.
213
222
mapping , err := ip .mapper .RESTMapping (gvk .GroupKind (), gvk .Version )
@@ -225,25 +234,30 @@ func createStructuredListWatch(gvk schema.GroupVersionKind, ip *specificInformer
225
234
return nil , err
226
235
}
227
236
237
+ ns := ip .namespace
238
+ if namespace != nil {
239
+ ns = * namespace
240
+ }
241
+
228
242
// Create a new ListWatch for the obj
229
243
return & cache.ListWatch {
230
244
ListFunc : func (opts metav1.ListOptions ) (runtime.Object , error ) {
231
245
res := listObj .DeepCopyObject ()
232
- isNamespaceScoped := ip . namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot
233
- err := client .Get ().NamespaceIfScoped (ip . namespace , isNamespaceScoped ).Resource (mapping .Resource .Resource ).VersionedParams (& opts , ip .paramCodec ).Do ().Into (res )
246
+ isNamespaceScoped := ns != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot
247
+ err := client .Get ().NamespaceIfScoped (ns , isNamespaceScoped ).Resource (mapping .Resource .Resource ).VersionedParams (& opts , ip .paramCodec ).Do ().Into (res )
234
248
return res , err
235
249
},
236
250
// Setup the watch function
237
251
WatchFunc : func (opts metav1.ListOptions ) (watch.Interface , error ) {
238
252
// Watch needs to be set to true separately
239
253
opts .Watch = true
240
- isNamespaceScoped := ip . namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot
241
- return client .Get ().NamespaceIfScoped (ip . namespace , isNamespaceScoped ).Resource (mapping .Resource .Resource ).VersionedParams (& opts , ip .paramCodec ).Watch ()
254
+ isNamespaceScoped := ns != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot
255
+ return client .Get ().NamespaceIfScoped (ns , isNamespaceScoped ).Resource (mapping .Resource .Resource ).VersionedParams (& opts , ip .paramCodec ).Watch ()
242
256
},
243
257
}, nil
244
258
}
245
259
246
- func createUnstructuredListWatch (gvk schema.GroupVersionKind , ip * specificInformersMap ) (* cache.ListWatch , error ) {
260
+ func createUnstructuredListWatch (gvk schema.GroupVersionKind , namespace * string , ip * specificInformersMap ) (* cache.ListWatch , error ) {
247
261
// Kubernetes APIs work against Resources, not GroupVersionKinds. Map the
248
262
// groupVersionKind to the Resource API we will use.
249
263
mapping , err := ip .mapper .RESTMapping (gvk .GroupKind (), gvk .Version )
@@ -255,20 +269,25 @@ func createUnstructuredListWatch(gvk schema.GroupVersionKind, ip *specificInform
255
269
return nil , err
256
270
}
257
271
272
+ ns := ip .namespace
273
+ if namespace != nil {
274
+ ns = * namespace
275
+ }
276
+
258
277
// Create a new ListWatch for the obj
259
278
return & cache.ListWatch {
260
279
ListFunc : func (opts metav1.ListOptions ) (runtime.Object , error ) {
261
- if ip . namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
262
- return dynamicClient .Resource (mapping .Resource ).Namespace (ip . namespace ).List (opts )
280
+ if ns != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
281
+ return dynamicClient .Resource (mapping .Resource ).Namespace (ns ).List (opts )
263
282
}
264
283
return dynamicClient .Resource (mapping .Resource ).List (opts )
265
284
},
266
285
// Setup the watch function
267
286
WatchFunc : func (opts metav1.ListOptions ) (watch.Interface , error ) {
268
287
// Watch needs to be set to true separately
269
288
opts .Watch = true
270
- if ip . namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
271
- return dynamicClient .Resource (mapping .Resource ).Namespace (ip . namespace ).Watch (opts )
289
+ if ns != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
290
+ return dynamicClient .Resource (mapping .Resource ).Namespace (ns ).Watch (opts )
272
291
}
273
292
return dynamicClient .Resource (mapping .Resource ).Watch (opts )
274
293
},
0 commit comments