diff --git a/go.mod b/go.mod index bf810c3b..0b2b9576 100644 --- a/go.mod +++ b/go.mod @@ -8,10 +8,10 @@ godebug default=go1.25 require ( golang.org/x/time v0.14.0 - k8s.io/api v0.0.0-20260205113801-e9022605bb35 - k8s.io/apimachinery v0.0.0-20260205113442-4c7488a521c8 - k8s.io/client-go v0.0.0-20260205114233-c148db951165 - k8s.io/code-generator v0.0.0-20260205115111-463a0e4e573b + k8s.io/api v0.0.0-20260205193817-6f99b47a2bbd + k8s.io/apimachinery v0.0.0-20260205233455-f12546b4989d + k8s.io/client-go v0.0.0-20260206035242-67ce5196123a + k8s.io/code-generator v0.0.0-20260206040502-0f34ff6ed017 k8s.io/klog/v2 v2.130.1 k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 k8s.io/utils v0.0.0-20260108192941-914a6e750570 diff --git a/go.sum b/go.sum index 61435f02..c25ace6b 100644 --- a/go.sum +++ b/go.sum @@ -115,14 +115,14 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.0.0-20260205113801-e9022605bb35 h1:lHgQvL1WjC+tgpYo/jfpsJZqv6b7tT2KF9hzFNu94tY= -k8s.io/api v0.0.0-20260205113801-e9022605bb35/go.mod h1:GZUpeSi8zsYiS/GDA9jMt0/+n6PAFNj8Z/eK2Rd/IvQ= -k8s.io/apimachinery v0.0.0-20260205113442-4c7488a521c8 h1:5AXoKfbrtljIl5TR+nXYLwDz5yFrOKT37HtZ9hZFo5s= -k8s.io/apimachinery v0.0.0-20260205113442-4c7488a521c8/go.mod h1:hQkG060WLAG1TIkYsu5lj3tb6YdNpKe5Zrr2UPGg+/k= -k8s.io/client-go v0.0.0-20260205114233-c148db951165 h1:dTRT4218J/dNz/U1z39x7bneMXQplVCnxnut21ZXwDI= -k8s.io/client-go v0.0.0-20260205114233-c148db951165/go.mod h1:Ue1JeE+EGNtbDdyQ9ZBKRK/GGQDf8cRVdrjhmJWQxiU= -k8s.io/code-generator v0.0.0-20260205115111-463a0e4e573b h1:bMKc+BEOllTyV+pr/sE1rBZzTbsIKDVWss+5ftiTED0= -k8s.io/code-generator v0.0.0-20260205115111-463a0e4e573b/go.mod h1:vVn41PppVruI/Yr27nPiT+KHo9fyRiBNSmV11czODWs= +k8s.io/api v0.0.0-20260205193817-6f99b47a2bbd h1:tgzQul+6n5AQYpFcrhpV9fn7dLVlLG7J+7GkXPe8LOg= +k8s.io/api v0.0.0-20260205193817-6f99b47a2bbd/go.mod h1:GZUpeSi8zsYiS/GDA9jMt0/+n6PAFNj8Z/eK2Rd/IvQ= +k8s.io/apimachinery v0.0.0-20260205233455-f12546b4989d h1:bxuu4ynFTom/p7dq3+D7rcM500tuOXgMoEY7OqtmboE= +k8s.io/apimachinery v0.0.0-20260205233455-f12546b4989d/go.mod h1:hQkG060WLAG1TIkYsu5lj3tb6YdNpKe5Zrr2UPGg+/k= +k8s.io/client-go v0.0.0-20260206035242-67ce5196123a h1:auN2L5YlnujjNGN4fRrWZdEbXbCwdNM+C3yH7NFov3s= +k8s.io/client-go v0.0.0-20260206035242-67ce5196123a/go.mod h1:hsICy6wbUdtAQzzHyhNbTFeOKp9Uzdt5AYPPFwF+ucQ= +k8s.io/code-generator v0.0.0-20260206040502-0f34ff6ed017 h1:dQ/S71ndt9MkU9hpmBueo9pNLxCit1LHWlCtFGDJmM4= +k8s.io/code-generator v0.0.0-20260206040502-0f34ff6ed017/go.mod h1:KP4dpswTGq3absCF0P5pjfVrV/FEwgyhgo4pPaBsrxI= k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b h1:gMplByicHV/TJBizHd9aVEsTYoJBnnUAT5MHlTkbjhQ= k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= diff --git a/pkg/generated/informers/externalversions/factory.go b/pkg/generated/informers/externalversions/factory.go index d04a0c45..34835afd 100644 --- a/pkg/generated/informers/externalversions/factory.go +++ b/pkg/generated/informers/externalversions/factory.go @@ -43,6 +43,7 @@ type sharedInformerFactory struct { defaultResync time.Duration customResync map[reflect.Type]time.Duration transform cache.TransformFunc + informerName *cache.InformerName informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -89,6 +90,21 @@ func WithTransform(transform cache.TransformFunc) SharedInformerOption { } } +// WithInformerName sets the InformerName for informer identity used in metrics. +// The InformerName must be created via cache.NewInformerName() at startup, +// which validates global uniqueness. Each informer type will register its +// GVR under this name. +func WithInformerName(informerName *cache.InformerName) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.informerName = informerName + return factory + } +} + +func (f *sharedInformerFactory) InformerName() *cache.InformerName { + return f.informerName +} + // NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { return NewSharedInformerFactoryWithOptions(client, defaultResync) @@ -153,6 +169,7 @@ func (f *sharedInformerFactory) Shutdown() { // Will return immediately if there is nothing to wait for. f.wg.Wait() + f.informerName.Release() } func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { diff --git a/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go index 71c802ba..380687f6 100644 --- a/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -34,7 +34,26 @@ type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexI type SharedInformerFactory interface { Start(stopCh <-chan struct{}) InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer + InformerName() *cache.InformerName } // TweakListOptionsFunc is a function that transforms a v1.ListOptions. type TweakListOptionsFunc func(*v1.ListOptions) + +// InformerOptions holds the options for creating an informer. +type InformerOptions struct { + // ResyncPeriod is the resync period for this informer. + // If not set, defaults to 0 (no resync). + ResyncPeriod time.Duration + + // Indexers are the indexers for this informer. + Indexers cache.Indexers + + // InformerName is used to uniquely identify this informer for metrics. + // If not set, metrics will not be published for this informer. + // Use cache.NewInformerName() to create an InformerName at startup. + InformerName *cache.InformerName + + // TweakListOptions is an optional function to modify the list options. + TweakListOptions TweakListOptionsFunc +} diff --git a/pkg/generated/informers/externalversions/samplecontroller/v1alpha1/foo.go b/pkg/generated/informers/externalversions/samplecontroller/v1alpha1/foo.go index 658033c2..67436566 100644 --- a/pkg/generated/informers/externalversions/samplecontroller/v1alpha1/foo.go +++ b/pkg/generated/informers/externalversions/samplecontroller/v1alpha1/foo.go @@ -24,6 +24,7 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" watch "k8s.io/apimachinery/pkg/watch" cache "k8s.io/client-go/tools/cache" apissamplecontrollerv1alpha1 "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" @@ -49,48 +50,61 @@ type fooInformer struct { // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewFooInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredFooInformer(client, namespace, resyncPeriod, indexers, nil) + return NewFooInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers}) } // NewFilteredFooInformer constructs a new informer for Foo type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewFilteredFooInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( + return NewFooInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions}) +} + +// NewFooInformerWithOptions constructs a new informer for Foo type with additional options. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFooInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer { + gvr := schema.GroupVersionResource{Group: "samplecontroller.k8s.io", Version: "v1alpha1", Resource: "foos"} + identifier := options.InformerName.WithResource(gvr) + tweakListOptions := options.TweakListOptions + return cache.NewSharedIndexInformerWithOptions( cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + ListFunc: func(opts v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.SamplecontrollerV1alpha1().Foos(namespace).List(context.Background(), options) + return client.SamplecontrollerV1alpha1().Foos(namespace).List(context.Background(), opts) }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + WatchFunc: func(opts v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.SamplecontrollerV1alpha1().Foos(namespace).Watch(context.Background(), options) + return client.SamplecontrollerV1alpha1().Foos(namespace).Watch(context.Background(), opts) }, - ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + ListWithContextFunc: func(ctx context.Context, opts v1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.SamplecontrollerV1alpha1().Foos(namespace).List(ctx, options) + return client.SamplecontrollerV1alpha1().Foos(namespace).List(ctx, opts) }, - WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + WatchFuncWithContext: func(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.SamplecontrollerV1alpha1().Foos(namespace).Watch(ctx, options) + return client.SamplecontrollerV1alpha1().Foos(namespace).Watch(ctx, opts) }, }, client), &apissamplecontrollerv1alpha1.Foo{}, - resyncPeriod, - indexers, + cache.SharedIndexInformerOptions{ + ResyncPeriod: options.ResyncPeriod, + Indexers: options.Indexers, + Identifier: identifier, + }, ) } func (f *fooInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredFooInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) + return NewFooInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions}) } func (f *fooInformer) Informer() cache.SharedIndexInformer {