@@ -37,6 +37,10 @@ type Factory struct {
3737 // TODO(skuznets) we should be able to figure this out from the output dir, ideally
3838 ClientsetPackagePath string
3939
40+ // SingleClusterClientPackagePath is the root directory under which single-cluster-aware clients exist.
41+ // e.g. "k8s.io/client-go/kubernetes"
42+ SingleClusterClientPackagePath string `marker:""`
43+
4044 // SingleClusterInformerPackagePath is the package under which the cluster-unaware listers are exposed.
4145 // e.g. "k8s.io/client-go/informers"
4246 SingleClusterInformerPackagePath string
@@ -52,6 +56,7 @@ func (f *Factory) WriteContent(w io.Writer) error {
5256 "groups" : f .Groups ,
5357 "packagePath" : f .PackagePath ,
5458 "clientsetPackagePath" : f .ClientsetPackagePath ,
59+ "singleClusterClientPackagePath" : f .SingleClusterClientPackagePath ,
5560 "singleClusterInformerPackagePath" : f .SingleClusterInformerPackagePath ,
5661 "useUpstreamInterfaces" : f .SingleClusterInformerPackagePath != "" ,
5762 }
@@ -80,6 +85,9 @@ import (
8085 "k8s.io/client-go/tools/cache"
8186
8287 clientset "{{.clientsetPackagePath}}"
88+ {{if not .useUpstreamInterfaces -}}
89+ scopedclientset "{{.singleClusterClientPackagePath}}"
90+ {{end -}}
8391 {{if .useUpstreamInterfaces -}}
8492 upstreaminformers "{{.singleClusterInformerPackagePath}}"
8593 {{end -}}
@@ -96,6 +104,9 @@ type SharedInformerOption func(*SharedInformerOptions) *SharedInformerOptions
96104type SharedInformerOptions struct {
97105 customResync map[reflect.Type]time.Duration
98106 tweakListOptions internalinterfaces.TweakListOptionsFunc
107+ {{if not .useUpstreamInterfaces -}}
108+ namespace string
109+ {{end -}}
99110}
100111
101112type sharedInformerFactory struct {
@@ -264,4 +275,136 @@ func (f *scopedDynamicSharedInformerFactory) ForResource(resource schema.GroupVe
264275func (f *scopedDynamicSharedInformerFactory) Start(stopCh <-chan struct{}) {
265276 f.sharedInformerFactory.Start(stopCh)
266277}
278+
279+ {{if not .useUpstreamInterfaces -}}
280+ // WithNamespace limits the SharedInformerFactory to the specified namespace.
281+ func WithNamespace(namespace string) SharedInformerOption {
282+ return func(opts *SharedInformerOptions) *SharedInformerOptions {
283+ opts.namespace = namespace
284+ return opts
285+ }
286+ }
287+
288+ type sharedScopedInformerFactory struct {
289+ client scopedclientset.Interface
290+ namespace string
291+ tweakListOptions internalinterfaces.TweakListOptionsFunc
292+ lock sync.Mutex
293+ defaultResync time.Duration
294+ customResync map[reflect.Type]time.Duration
295+
296+ informers map[reflect.Type]cache.SharedIndexInformer
297+ // startedInformers is used for tracking which informers have been started.
298+ // This allows Start() to be called multiple times safely.
299+ startedInformers map[reflect.Type]bool
300+ }
301+
302+ // NewSharedScopedInformerFactory constructs a new instance of SharedInformerFactory for some or all namespaces.
303+ func NewSharedScopedInformerFactory(client scopedclientset.Interface, defaultResync time.Duration, namespace string) SharedScopedInformerFactory {
304+ return NewSharedScopedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace))
305+ }
306+
307+ // NewSharedScopedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
308+ func NewSharedScopedInformerFactoryWithOptions(client scopedclientset.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedScopedInformerFactory {
309+ factory := &sharedScopedInformerFactory{
310+ client: client,
311+ defaultResync: defaultResync,
312+ informers: make(map[reflect.Type]cache.SharedIndexInformer),
313+ startedInformers: make(map[reflect.Type]bool),
314+ customResync: make(map[reflect.Type]time.Duration),
315+ }
316+
317+ opts := &SharedInformerOptions{
318+ customResync: make(map[reflect.Type]time.Duration),
319+ }
320+
321+ // Apply all options
322+ for _, opt := range options {
323+ opts = opt(opts)
324+ }
325+
326+ // Forward options to the factory
327+ factory.customResync = opts.customResync
328+ factory.tweakListOptions = opts.tweakListOptions
329+ factory.namespace = opts.namespace
330+
331+ return factory
332+ }
333+
334+ // Start initializes all requested informers.
335+ func (f *sharedScopedInformerFactory) Start(stopCh <-chan struct{}) {
336+ f.lock.Lock()
337+ defer f.lock.Unlock()
338+
339+ for informerType, informer := range f.informers {
340+ if !f.startedInformers[informerType] {
341+ go informer.Run(stopCh)
342+ f.startedInformers[informerType] = true
343+ }
344+ }
345+ }
346+
347+ // WaitForCacheSync waits for all started informers' cache were synced.
348+ func (f *sharedScopedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
349+ informers := func()map[reflect.Type]cache.SharedIndexInformer{
350+ f.lock.Lock()
351+ defer f.lock.Unlock()
352+
353+ informers := map[reflect.Type]cache.SharedIndexInformer{}
354+ for informerType, informer := range f.informers {
355+ if f.startedInformers[informerType] {
356+ informers[informerType] = informer
357+ }
358+ }
359+ return informers
360+ }()
361+
362+ res := map[reflect.Type]bool{}
363+ for informType, informer := range informers {
364+ res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
365+ }
366+ return res
367+ }
368+
369+ // InformerFor returns the SharedIndexInformer for obj using an internal
370+ // client.
371+ func (f *sharedScopedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewScopedInformerFunc) cache.SharedIndexInformer {
372+ f.lock.Lock()
373+ defer f.lock.Unlock()
374+
375+ informerType := reflect.TypeOf(obj)
376+ informer, exists := f.informers[informerType]
377+ if exists {
378+ return informer
379+ }
380+
381+ resyncPeriod, exists := f.customResync[informerType]
382+ if !exists {
383+ resyncPeriod = f.defaultResync
384+ }
385+
386+ informer = newFunc(f.client, resyncPeriod)
387+ f.informers[informerType] = informer
388+
389+ return informer
390+ }
391+
392+ // SharedScopedInformerFactory provides shared informers for resources in all known
393+ // API group versions, scoped to one workspace.
394+ type SharedScopedInformerFactory interface {
395+ internalinterfaces.SharedScopedInformerFactory
396+ ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
397+ WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
398+
399+ {{range .groups}} {{.GoName}}() {{.Group.PackageName}}informers.Interface
400+ {{end -}}
401+ }
402+
403+
404+ {{range .groups}}
405+ func (f *sharedScopedInformerFactory) {{.GoName}}() {{.Group.PackageName}}informers.Interface {
406+ return {{.Group.PackageName}}informers.NewScoped(f, f.namespace, f.tweakListOptions)
407+ }
408+ {{end}}
409+ {{end}}
267410`
0 commit comments