@@ -274,17 +274,19 @@ func createStructuredListWatch(gvk schema.GroupVersionKind, ip *specificInformer
274
274
ListFunc : func (opts metav1.ListOptions ) (runtime.Object , error ) {
275
275
ip .selectors [gvk ].ApplyToList (& opts )
276
276
res := listObj .DeepCopyObject ()
277
- isNamespaceScoped := ip .namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot
278
- err := client .Get ().NamespaceIfScoped (ip .namespace , isNamespaceScoped ).Resource (mapping .Resource .Resource ).VersionedParams (& opts , ip .paramCodec ).Do (ctx ).Into (res )
277
+ namespace := restrictNamespaceBySelector (ip .namespace , ip .selectors [gvk ])
278
+ isNamespaceScoped := namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot
279
+ err := client .Get ().NamespaceIfScoped (namespace , isNamespaceScoped ).Resource (mapping .Resource .Resource ).VersionedParams (& opts , ip .paramCodec ).Do (ctx ).Into (res )
279
280
return res , err
280
281
},
281
282
// Setup the watch function
282
283
WatchFunc : func (opts metav1.ListOptions ) (watch.Interface , error ) {
283
284
ip .selectors [gvk ].ApplyToList (& opts )
284
285
// Watch needs to be set to true separately
285
286
opts .Watch = true
286
- isNamespaceScoped := ip .namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot
287
- return client .Get ().NamespaceIfScoped (ip .namespace , isNamespaceScoped ).Resource (mapping .Resource .Resource ).VersionedParams (& opts , ip .paramCodec ).Watch (ctx )
287
+ namespace := restrictNamespaceBySelector (ip .namespace , ip .selectors [gvk ])
288
+ isNamespaceScoped := namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot
289
+ return client .Get ().NamespaceIfScoped (namespace , isNamespaceScoped ).Resource (mapping .Resource .Resource ).VersionedParams (& opts , ip .paramCodec ).Watch (ctx )
288
290
},
289
291
}, nil
290
292
}
@@ -313,8 +315,9 @@ func createUnstructuredListWatch(gvk schema.GroupVersionKind, ip *specificInform
313
315
return & cache.ListWatch {
314
316
ListFunc : func (opts metav1.ListOptions ) (runtime.Object , error ) {
315
317
ip .selectors [gvk ].ApplyToList (& opts )
316
- if ip .namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
317
- return dynamicClient .Resource (mapping .Resource ).Namespace (ip .namespace ).List (ctx , opts )
318
+ namespace := restrictNamespaceBySelector (ip .namespace , ip .selectors [gvk ])
319
+ if namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
320
+ return dynamicClient .Resource (mapping .Resource ).Namespace (namespace ).List (ctx , opts )
318
321
}
319
322
return dynamicClient .Resource (mapping .Resource ).List (ctx , opts )
320
323
},
@@ -323,8 +326,9 @@ func createUnstructuredListWatch(gvk schema.GroupVersionKind, ip *specificInform
323
326
ip .selectors [gvk ].ApplyToList (& opts )
324
327
// Watch needs to be set to true separately
325
328
opts .Watch = true
326
- if ip .namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
327
- return dynamicClient .Resource (mapping .Resource ).Namespace (ip .namespace ).Watch (ctx , opts )
329
+ namespace := restrictNamespaceBySelector (ip .namespace , ip .selectors [gvk ])
330
+ if namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
331
+ return dynamicClient .Resource (mapping .Resource ).Namespace (namespace ).Watch (ctx , opts )
328
332
}
329
333
return dynamicClient .Resource (mapping .Resource ).Watch (ctx , opts )
330
334
},
@@ -358,8 +362,9 @@ func createMetadataListWatch(gvk schema.GroupVersionKind, ip *specificInformersM
358
362
return & cache.ListWatch {
359
363
ListFunc : func (opts metav1.ListOptions ) (runtime.Object , error ) {
360
364
ip .selectors [gvk ].ApplyToList (& opts )
361
- if ip .namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
362
- return client .Resource (mapping .Resource ).Namespace (ip .namespace ).List (ctx , opts )
365
+ namespace := restrictNamespaceBySelector (ip .namespace , ip .selectors [gvk ])
366
+ if namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
367
+ return client .Resource (mapping .Resource ).Namespace (namespace ).List (ctx , opts )
363
368
}
364
369
return client .Resource (mapping .Resource ).List (ctx , opts )
365
370
},
@@ -368,8 +373,9 @@ func createMetadataListWatch(gvk schema.GroupVersionKind, ip *specificInformersM
368
373
ip .selectors [gvk ].ApplyToList (& opts )
369
374
// Watch needs to be set to true separately
370
375
opts .Watch = true
371
- if ip .namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
372
- return client .Resource (mapping .Resource ).Namespace (ip .namespace ).Watch (ctx , opts )
376
+ namespace := restrictNamespaceBySelector (ip .namespace , ip .selectors [gvk ])
377
+ if namespace != "" && mapping .Scope .Name () != meta .RESTScopeNameRoot {
378
+ return client .Resource (mapping .Resource ).Namespace (namespace ).Watch (ctx , opts )
373
379
}
374
380
return client .Resource (mapping .Resource ).Watch (ctx , opts )
375
381
},
@@ -386,3 +392,23 @@ func resyncPeriod(resync time.Duration) func() time.Duration {
386
392
return time .Duration (float64 (resync .Nanoseconds ()) * factor )
387
393
}
388
394
}
395
+
396
+ // restrictNamespaceBySelector returns either a global restriction for all ListWatches
397
+ // if not default/empty, or the namespace that a ListWatch for the specific resource
398
+ // is restricted to, based on a specified field selector for metadata.namespace field.
399
+ func restrictNamespaceBySelector (namespaceOpt string , s Selector ) string {
400
+ if namespaceOpt != "" {
401
+ // namespace is already restricted
402
+ return namespaceOpt
403
+ }
404
+ fieldSelector := s .Field
405
+ if fieldSelector == nil || fieldSelector .Empty () {
406
+ return ""
407
+ }
408
+ // check whether a selector includes the namespace field
409
+ value , found := fieldSelector .RequiresExactMatch ("metadata.namespace" )
410
+ if found {
411
+ return value
412
+ }
413
+ return ""
414
+ }
0 commit comments