diff --git a/pkg/multiproject/neg/informerset/informerset.go b/pkg/multiproject/neg/informerset/informerset.go index 23dcb4cda8..c0ab4dd6f0 100644 --- a/pkg/multiproject/neg/informerset/informerset.go +++ b/pkg/multiproject/neg/informerset/informerset.go @@ -4,19 +4,16 @@ import ( "fmt" networkclient "github.com/GoogleCloudPlatform/gke-networking-api/client/network/clientset/versioned" - informernetwork "github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/network/v1" + networkinformers "github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions" nodetopologyclient "github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/clientset/versioned" - informernodetopology "github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/nodetopology/v1" + nodetopologyinformers "github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - informerv1 "k8s.io/client-go/informers/core/v1" - discoveryinformer "k8s.io/client-go/informers/discovery/v1" - informernetworking "k8s.io/client-go/informers/networking/v1" + "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" "k8s.io/ingress-gce/pkg/multiproject/common/filteredinformer" svcnegclient "k8s.io/ingress-gce/pkg/svcneg/client/clientset/versioned" - informersvcneg "k8s.io/ingress-gce/pkg/svcneg/client/informers/externalversions/svcneg/v1beta1" - "k8s.io/ingress-gce/pkg/utils" + svcneginformers "k8s.io/ingress-gce/pkg/svcneg/client/informers/externalversions" "k8s.io/ingress-gce/pkg/utils/endpointslices" "k8s.io/klog/v2" ) @@ -24,6 +21,11 @@ import ( // InformerSet manages all shared informers used by multiproject controllers. // It provides centralized initialization and lifecycle management. type InformerSet struct { + kubeFactory informers.SharedInformerFactory + svcNegFactory svcneginformers.SharedInformerFactory + networkFactory networkinformers.SharedInformerFactory + nodetopologyFactory nodetopologyinformers.SharedInformerFactory + // Core Kubernetes informers (always present) Ingress cache.SharedIndexInformer Service cache.SharedIndexInformer @@ -51,80 +53,48 @@ func NewInformerSet( nodeTopologyClient nodetopologyclient.Interface, resyncPeriod metav1.Duration, ) *InformerSet { - informers := &InformerSet{} - - // Create core Kubernetes informers - informers.Ingress = informernetworking.NewIngressInformer( - kubeClient, - metav1.NamespaceAll, - resyncPeriod.Duration, - utils.NewNamespaceIndexer(), - ) - - informers.Service = informerv1.NewServiceInformer( - kubeClient, - metav1.NamespaceAll, - resyncPeriod.Duration, - utils.NewNamespaceIndexer(), - ) + infSet := &InformerSet{} - informers.Pod = informerv1.NewPodInformer( - kubeClient, - metav1.NamespaceAll, - resyncPeriod.Duration, - utils.NewNamespaceIndexer(), - ) + infSet.kubeFactory = informers.NewSharedInformerFactory(kubeClient, resyncPeriod.Duration) + if svcNegClient != nil { + infSet.svcNegFactory = svcneginformers.NewSharedInformerFactory(svcNegClient, resyncPeriod.Duration) + } + if networkClient != nil { + infSet.networkFactory = networkinformers.NewSharedInformerFactory(networkClient, resyncPeriod.Duration) + } + if nodeTopologyClient != nil { + infSet.nodetopologyFactory = nodetopologyinformers.NewSharedInformerFactory(nodeTopologyClient, resyncPeriod.Duration) + } - informers.Node = informerv1.NewNodeInformer( - kubeClient, - resyncPeriod.Duration, - utils.NewNamespaceIndexer(), - ) + // Create core Kubernetes informers from factory + infSet.Ingress = infSet.kubeFactory.Networking().V1().Ingresses().Informer() + infSet.Service = infSet.kubeFactory.Core().V1().Services().Informer() + infSet.Pod = infSet.kubeFactory.Core().V1().Pods().Informer() + infSet.Node = infSet.kubeFactory.Core().V1().Nodes().Informer() // EndpointSlice informer with custom indexers for NEG controller - informers.EndpointSlice = discoveryinformer.NewEndpointSliceInformer( - kubeClient, - metav1.NamespaceAll, - resyncPeriod.Duration, - cache.Indexers{ - cache.NamespaceIndex: cache.MetaNamespaceIndexFunc, - endpointslices.EndpointSlicesByServiceIndex: endpointslices.EndpointSlicesByServiceFunc, - }, - ) - - // Create CRD informers if clients are available - if svcNegClient != nil { - informers.SvcNeg = informersvcneg.NewServiceNetworkEndpointGroupInformer( - svcNegClient, - metav1.NamespaceAll, - resyncPeriod.Duration, - utils.NewNamespaceIndexer(), - ) + endpointSliceInformer := infSet.kubeFactory.Discovery().V1().EndpointSlices().Informer() + if err := endpointSliceInformer.AddIndexers(cache.Indexers{ + endpointslices.EndpointSlicesByServiceIndex: endpointslices.EndpointSlicesByServiceFunc, + }); err != nil { + klog.Fatalf("failed to add indexers to endpointSlice informer: %v", err) } + infSet.EndpointSlice = endpointSliceInformer - if networkClient != nil { - informers.Network = informernetwork.NewNetworkInformer( - networkClient, - resyncPeriod.Duration, - utils.NewNamespaceIndexer(), - ) - - informers.GkeNetworkParams = informernetwork.NewGKENetworkParamSetInformer( - networkClient, - resyncPeriod.Duration, - utils.NewNamespaceIndexer(), - ) + // Create CRD informers if factories are available + if infSet.svcNegFactory != nil { + infSet.SvcNeg = infSet.svcNegFactory.Networking().V1beta1().ServiceNetworkEndpointGroups().Informer() } - if nodeTopologyClient != nil { - informers.NodeTopology = informernodetopology.NewNodeTopologyInformer( - nodeTopologyClient, - resyncPeriod.Duration, - utils.NewNamespaceIndexer(), - ) + if infSet.networkFactory != nil { + infSet.Network = infSet.networkFactory.Networking().V1().Networks().Informer() + infSet.GkeNetworkParams = infSet.networkFactory.Networking().V1().GKENetworkParamSets().Informer() } - return informers + if infSet.nodetopologyFactory != nil { + infSet.NodeTopology = infSet.nodetopologyFactory.Networking().V1().NodeTopologies().Informer() + } + return infSet } // Start starts all informers and waits for their caches to sync. @@ -147,18 +117,19 @@ func (i *InformerSet) Start(stopCh <-chan struct{}, logger klog.Logger) error { default: } - // Start all core informers - startInformer(i.Ingress, stopCh) - startInformer(i.Service, stopCh) - startInformer(i.Pod, stopCh) - startInformer(i.Node, stopCh) - startInformer(i.EndpointSlice, stopCh) - - // Start optional informers - startInformer(i.SvcNeg, stopCh) - startInformer(i.Network, stopCh) - startInformer(i.GkeNetworkParams, stopCh) - startInformer(i.NodeTopology, stopCh) + // Start factories + if i.kubeFactory != nil { + i.kubeFactory.Start(stopCh) + } + if i.svcNegFactory != nil { + i.svcNegFactory.Start(stopCh) + } + if i.networkFactory != nil { + i.networkFactory.Start(stopCh) + } + if i.nodetopologyFactory != nil { + i.nodetopologyFactory.Start(stopCh) + } i.started = true @@ -271,11 +242,3 @@ func (i *InformerSet) hasSyncedFuncs() []func() bool { return funcs } - -// startInformer starts the informer if it is non-nil. -func startInformer(inf cache.SharedIndexInformer, stopCh <-chan struct{}) { - if inf == nil { - return - } - go inf.Run(stopCh) -} diff --git a/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/factory.go b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/factory.go new file mode 100644 index 0000000000..a6f207d5c0 --- /dev/null +++ b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/factory.go @@ -0,0 +1,262 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + reflect "reflect" + sync "sync" + time "time" + + versioned "github.com/GoogleCloudPlatform/gke-networking-api/client/network/clientset/versioned" + internalinterfaces "github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/internalinterfaces" + network "github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/network" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + transform cache.TransformFunc + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool + // wg tracks how many goroutines were started. + wg sync.WaitGroup + // shuttingDown is true when Shutdown has been called. It may still be running + // because it needs to wait for goroutines. + shuttingDown bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// WithTransform sets a transform on all informers. +func WithTransform(transform cache.TransformFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.transform = transform + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + if f.shuttingDown { + return + } + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + f.wg.Add(1) + // We need a new variable in each loop iteration, + // otherwise the goroutine would use the loop variable + // and that keeps changing. + informer := informer + go func() { + defer f.wg.Done() + informer.Run(stopCh) + }() + f.startedInformers[informerType] = true + } + } +} + +func (f *sharedInformerFactory) Shutdown() { + f.lock.Lock() + f.shuttingDown = true + f.lock.Unlock() + + // Will return immediately if there is nothing to wait for. + f.wg.Wait() +} + +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + informer.SetTransform(f.transform) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +// +// It is typically used like this: +// +// ctx, cancel := context.Background() +// defer cancel() +// factory := NewSharedInformerFactory(client, resyncPeriod) +// defer factory.WaitForStop() // Returns immediately if nothing was started. +// genericInformer := factory.ForResource(resource) +// typedInformer := factory.SomeAPIGroup().V1().SomeType() +// factory.Start(ctx.Done()) // Start processing these informers. +// synced := factory.WaitForCacheSync(ctx.Done()) +// for v, ok := range synced { +// if !ok { +// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) +// return +// } +// } +// +// // Creating informers can also be created after Start, but then +// // Start must be called again: +// anotherGenericInformer := factory.ForResource(resource) +// factory.Start(ctx.Done()) +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + // Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync. + Start(stopCh <-chan struct{}) + + // Shutdown marks a factory as shutting down. At that point no new + // informers can be started anymore and Start will return without + // doing anything. + // + // In addition, Shutdown blocks until all goroutines have terminated. For that + // to happen, the close channel(s) that they were started with must be closed, + // either before Shutdown gets called or while it is waiting. + // + // Shutdown may be called multiple times, even concurrently. All such calls will + // block until all goroutines have terminated. + Shutdown() + + // WaitForCacheSync blocks until all started informers' caches were synced + // or the stop channel gets closed. + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // InformerFor returns the SharedIndexInformer for obj using an internal + // client. + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + + Networking() network.Interface +} + +func (f *sharedInformerFactory) Networking() network.Interface { + return network.New(f, f.namespace, f.tweakListOptions) +} diff --git a/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/generic.go b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/generic.go new file mode 100644 index 0000000000..7d9caf1bfa --- /dev/null +++ b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/generic.go @@ -0,0 +1,68 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + "fmt" + + v1 "github.com/GoogleCloudPlatform/gke-networking-api/apis/network/v1" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=networking.gke.io, Version=v1 + case v1.SchemeGroupVersion.WithResource("gkenetworkparamsets"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1().GKENetworkParamSets().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("networks"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1().Networks().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("networkinterfaces"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1().NetworkInterfaces().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("subnetworks"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1().Subnetworks().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/network/interface.go b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/network/interface.go new file mode 100644 index 0000000000..ab755e66f0 --- /dev/null +++ b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/network/interface.go @@ -0,0 +1,46 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package network + +import ( + internalinterfaces "github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/internalinterfaces" + v1 "github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/network/v1" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1 provides access to shared informers for resources in V1. + V1() v1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/factory.go b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/factory.go new file mode 100644 index 0000000000..d387b69978 --- /dev/null +++ b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/factory.go @@ -0,0 +1,262 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + reflect "reflect" + sync "sync" + time "time" + + versioned "github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/clientset/versioned" + internalinterfaces "github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/internalinterfaces" + nodetopology "github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/nodetopology" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + transform cache.TransformFunc + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool + // wg tracks how many goroutines were started. + wg sync.WaitGroup + // shuttingDown is true when Shutdown has been called. It may still be running + // because it needs to wait for goroutines. + shuttingDown bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// WithTransform sets a transform on all informers. +func WithTransform(transform cache.TransformFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.transform = transform + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + if f.shuttingDown { + return + } + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + f.wg.Add(1) + // We need a new variable in each loop iteration, + // otherwise the goroutine would use the loop variable + // and that keeps changing. + informer := informer + go func() { + defer f.wg.Done() + informer.Run(stopCh) + }() + f.startedInformers[informerType] = true + } + } +} + +func (f *sharedInformerFactory) Shutdown() { + f.lock.Lock() + f.shuttingDown = true + f.lock.Unlock() + + // Will return immediately if there is nothing to wait for. + f.wg.Wait() +} + +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + informer.SetTransform(f.transform) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +// +// It is typically used like this: +// +// ctx, cancel := context.Background() +// defer cancel() +// factory := NewSharedInformerFactory(client, resyncPeriod) +// defer factory.WaitForStop() // Returns immediately if nothing was started. +// genericInformer := factory.ForResource(resource) +// typedInformer := factory.SomeAPIGroup().V1().SomeType() +// factory.Start(ctx.Done()) // Start processing these informers. +// synced := factory.WaitForCacheSync(ctx.Done()) +// for v, ok := range synced { +// if !ok { +// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) +// return +// } +// } +// +// // Creating informers can also be created after Start, but then +// // Start must be called again: +// anotherGenericInformer := factory.ForResource(resource) +// factory.Start(ctx.Done()) +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + // Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync. + Start(stopCh <-chan struct{}) + + // Shutdown marks a factory as shutting down. At that point no new + // informers can be started anymore and Start will return without + // doing anything. + // + // In addition, Shutdown blocks until all goroutines have terminated. For that + // to happen, the close channel(s) that they were started with must be closed, + // either before Shutdown gets called or while it is waiting. + // + // Shutdown may be called multiple times, even concurrently. All such calls will + // block until all goroutines have terminated. + Shutdown() + + // WaitForCacheSync blocks until all started informers' caches were synced + // or the stop channel gets closed. + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // InformerFor returns the SharedIndexInformer for obj using an internal + // client. + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + + Networking() nodetopology.Interface +} + +func (f *sharedInformerFactory) Networking() nodetopology.Interface { + return nodetopology.New(f, f.namespace, f.tweakListOptions) +} diff --git a/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/generic.go b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/generic.go new file mode 100644 index 0000000000..6b54cb9076 --- /dev/null +++ b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/generic.go @@ -0,0 +1,62 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + "fmt" + + v1 "github.com/GoogleCloudPlatform/gke-networking-api/apis/nodetopology/v1" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=networking.gke.io, Version=v1 + case v1.SchemeGroupVersion.WithResource("nodetopologies"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1().NodeTopologies().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/nodetopology/interface.go b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/nodetopology/interface.go new file mode 100644 index 0000000000..0f37c9a121 --- /dev/null +++ b/vendor/github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/nodetopology/interface.go @@ -0,0 +1,46 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package nodetopology + +import ( + internalinterfaces "github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/internalinterfaces" + v1 "github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/nodetopology/v1" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1 provides access to shared informers for resources in V1. + V1() v1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 4100e2fbf4..262c4be932 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -84,7 +84,9 @@ github.com/GoogleCloudPlatform/gke-networking-api/client/network/clientset/versi github.com/GoogleCloudPlatform/gke-networking-api/client/network/clientset/versioned/scheme github.com/GoogleCloudPlatform/gke-networking-api/client/network/clientset/versioned/typed/network/v1 github.com/GoogleCloudPlatform/gke-networking-api/client/network/clientset/versioned/typed/network/v1/fake +github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/internalinterfaces +github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/network github.com/GoogleCloudPlatform/gke-networking-api/client/network/informers/externalversions/network/v1 github.com/GoogleCloudPlatform/gke-networking-api/client/network/listers/network/v1 github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/clientset/versioned @@ -92,7 +94,9 @@ github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/clientset/ github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/clientset/versioned/scheme github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/clientset/versioned/typed/nodetopology/v1 github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/clientset/versioned/typed/nodetopology/v1/fake +github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/internalinterfaces +github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/nodetopology github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/informers/externalversions/nodetopology/v1 github.com/GoogleCloudPlatform/gke-networking-api/client/nodetopology/listers/nodetopology/v1 # github.com/GoogleCloudPlatform/k8s-cloud-provider v1.32.0