From c0addb352e284feda34667f0a36c06da9f1cf2a6 Mon Sep 17 00:00:00 2001 From: Joe Betz Date: Thu, 5 Mar 2026 20:06:01 -0500 Subject: [PATCH 1/4] Fix informer factory generation and add test --- .../src/k8s.io/client-go/informers/factory.go | 4 +- .../cmd/informer-gen/generators/factory.go | 4 +- .../informers/externalversions/factory.go | 4 +- .../externalversions/factory_test.go | 111 ++++++++++++++++++ 4 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 staging/src/k8s.io/code-generator/examples/single/informers/externalversions/factory_test.go diff --git a/staging/src/k8s.io/client-go/informers/factory.go b/staging/src/k8s.io/client-go/informers/factory.go index c7c735fed27..19901079f8b 100644 --- a/staging/src/k8s.io/client-go/informers/factory.go +++ b/staging/src/k8s.io/client-go/informers/factory.go @@ -256,7 +256,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer diff --git a/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/factory.go b/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/factory.go index b3ab50d0944..237de9342fa 100644 --- a/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/factory.go +++ b/staging/src/k8s.io/code-generator/cmd/informer-gen/generators/factory.go @@ -313,7 +313,9 @@ func (f *sharedInformerFactory) InformerFor(obj {{.runtimeObject|raw}}, newFunc } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer diff --git a/staging/src/k8s.io/code-generator/examples/single/informers/externalversions/factory.go b/staging/src/k8s.io/code-generator/examples/single/informers/externalversions/factory.go index 4d3d6384997..326e025b95a 100644 --- a/staging/src/k8s.io/code-generator/examples/single/informers/externalversions/factory.go +++ b/staging/src/k8s.io/code-generator/examples/single/informers/externalversions/factory.go @@ -237,7 +237,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer diff --git a/staging/src/k8s.io/code-generator/examples/single/informers/externalversions/factory_test.go b/staging/src/k8s.io/code-generator/examples/single/informers/externalversions/factory_test.go new file mode 100644 index 00000000000..bc1911121e5 --- /dev/null +++ b/staging/src/k8s.io/code-generator/examples/single/informers/externalversions/factory_test.go @@ -0,0 +1,111 @@ +/* +Copyright 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 + + http://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. +*/ + +package externalversions + +import ( + "slices" + "testing" + "time" + + "k8s.io/client-go/tools/cache" + singleapiv1 "k8s.io/code-generator/examples/single/api/v1" + "k8s.io/code-generator/examples/single/clientset/versioned" +) + +// TestTransforms verified that transform calls are applied as expected. +func TestTransforms(t *testing.T) { + tests := []struct { + name string + useFactoryTransform bool + usePerInformerTransform bool + wantTransformCalls []string + }{ + { + name: "no transforms", + wantTransformCalls: nil, + }, + { + name: "no factory transform preserves per-informer transform", + usePerInformerTransform: true, + wantTransformCalls: []string{"per-informer"}, + }, + { + name: "factory transform applied when no per-informer transform", + useFactoryTransform: true, + wantTransformCalls: []string{"factory"}, + }, + { + name: "factory transform overrides per-informer transform", + useFactoryTransform: true, + usePerInformerTransform: true, + wantTransformCalls: []string{"factory"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var transformCalls []string + makeTransform := func(name string) cache.TransformFunc { + return func(obj interface{}) (interface{}, error) { + transformCalls = append(transformCalls, name) + return obj, nil + } + } + + var opts []SharedInformerOption + if tt.useFactoryTransform { + opts = append(opts, WithTransform(makeTransform("factory"))) + } + factory := NewSharedInformerFactoryWithOptions(nil, 0, opts...) + + var wrapper *transformTrackingInformer + newFunc := func(_ versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + inner := cache.NewSharedIndexInformer(nil, &singleapiv1.TestType{}, resyncPeriod, cache.Indexers{}) + wrapper = &transformTrackingInformer{SharedIndexInformer: inner} + if tt.usePerInformerTransform { + err := wrapper.SetTransform(makeTransform("per-informer")) + if err != nil { + t.Fatalf("failed to set transform: %v", err) + } + } + return wrapper + } + factory.InformerFor(&singleapiv1.TestType{}, newFunc) + + if wrapper.lastTransform != nil { + _, err := wrapper.lastTransform(nil) + if err != nil { + t.Fatalf("failed to invoke transform: %v", err) + } + } + + if !slices.Equal(transformCalls, tt.wantTransformCalls) { + t.Errorf("transform calls: got %v, want %v", transformCalls, tt.wantTransformCalls) + } + }) + } +} + +type transformTrackingInformer struct { + cache.SharedIndexInformer + lastTransform cache.TransformFunc +} + +func (s *transformTrackingInformer) SetTransform(handler cache.TransformFunc) error { + s.lastTransform = handler + return s.SharedIndexInformer.SetTransform(handler) +} From e433cbcb5bb982ba666ad01b6f8567b6e2695a34 Mon Sep 17 00:00:00 2001 From: Joe Betz Date: Thu, 5 Mar 2026 20:18:03 -0500 Subject: [PATCH 2/4] generate code --- .../pkg/client/informers/externalversions/factory.go | 4 +++- .../pkg/client/informers/externalversions/factory.go | 4 +++- .../HyphenGroup/informers/externalversions/factory.go | 4 +++- .../examples/MixedCase/informers/externalversions/factory.go | 4 +++- .../examples/apiserver/informers/externalversions/factory.go | 4 +++- .../examples/crd/informers/externalversions/factory.go | 4 +++- .../pkg/client/informers/externalversions/factory.go | 4 +++- .../pkg/generated/informers/externalversions/factory.go | 4 +++- .../pkg/generated/informers/externalversions/factory.go | 4 +++- 9 files changed, 27 insertions(+), 9 deletions(-) diff --git a/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go b/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go index 48e1179dffd..1d9136ad6bb 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go +++ b/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/informers/externalversions/factory.go @@ -237,7 +237,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go index 83706c6fd3a..c0a30f6e99f 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go @@ -237,7 +237,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer diff --git a/staging/src/k8s.io/code-generator/examples/HyphenGroup/informers/externalversions/factory.go b/staging/src/k8s.io/code-generator/examples/HyphenGroup/informers/externalversions/factory.go index f700857f03c..1439634fefb 100644 --- a/staging/src/k8s.io/code-generator/examples/HyphenGroup/informers/externalversions/factory.go +++ b/staging/src/k8s.io/code-generator/examples/HyphenGroup/informers/externalversions/factory.go @@ -237,7 +237,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer diff --git a/staging/src/k8s.io/code-generator/examples/MixedCase/informers/externalversions/factory.go b/staging/src/k8s.io/code-generator/examples/MixedCase/informers/externalversions/factory.go index a00ff52e03b..63894f50d5c 100644 --- a/staging/src/k8s.io/code-generator/examples/MixedCase/informers/externalversions/factory.go +++ b/staging/src/k8s.io/code-generator/examples/MixedCase/informers/externalversions/factory.go @@ -237,7 +237,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer diff --git a/staging/src/k8s.io/code-generator/examples/apiserver/informers/externalversions/factory.go b/staging/src/k8s.io/code-generator/examples/apiserver/informers/externalversions/factory.go index b07ea3fff29..250c5a2dc2b 100644 --- a/staging/src/k8s.io/code-generator/examples/apiserver/informers/externalversions/factory.go +++ b/staging/src/k8s.io/code-generator/examples/apiserver/informers/externalversions/factory.go @@ -240,7 +240,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer diff --git a/staging/src/k8s.io/code-generator/examples/crd/informers/externalversions/factory.go b/staging/src/k8s.io/code-generator/examples/crd/informers/externalversions/factory.go index cfa6fd1b9bc..31e536b5801 100644 --- a/staging/src/k8s.io/code-generator/examples/crd/informers/externalversions/factory.go +++ b/staging/src/k8s.io/code-generator/examples/crd/informers/externalversions/factory.go @@ -240,7 +240,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer diff --git a/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/factory.go b/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/factory.go index fc458aa973e..2c6348fad7e 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/factory.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/factory.go @@ -237,7 +237,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer diff --git a/staging/src/k8s.io/sample-apiserver/pkg/generated/informers/externalversions/factory.go b/staging/src/k8s.io/sample-apiserver/pkg/generated/informers/externalversions/factory.go index ee53ec161d5..099ebf18522 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/generated/informers/externalversions/factory.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/generated/informers/externalversions/factory.go @@ -237,7 +237,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer diff --git a/staging/src/k8s.io/sample-controller/pkg/generated/informers/externalversions/factory.go b/staging/src/k8s.io/sample-controller/pkg/generated/informers/externalversions/factory.go index 20bf3c1e916..22d543ae630 100644 --- a/staging/src/k8s.io/sample-controller/pkg/generated/informers/externalversions/factory.go +++ b/staging/src/k8s.io/sample-controller/pkg/generated/informers/externalversions/factory.go @@ -237,7 +237,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer From 9c99d5f6c06a2a9f1441b268948fab3e6c665058 Mon Sep 17 00:00:00 2001 From: KunWuLuan Date: Wed, 24 Sep 2025 13:51:51 +0800 Subject: [PATCH 3/4] Test that scheduler transform is set as expected in newPodInformer --- pkg/scheduler/scheduler_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go index 4fde61f0f78..1a5121560a0 100644 --- a/pkg/scheduler/scheduler_test.go +++ b/pkg/scheduler/scheduler_test.go @@ -29,6 +29,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/onsi/gomega" + "github.com/stretchr/testify/require" v1 "k8s.io/api/core/v1" eventsv1 "k8s.io/api/events/v1" @@ -1463,3 +1464,29 @@ func (f fakePermitPlugin) Permit(ctx context.Context, state fwk.CycleState, p *v } var _ fwk.PermitPlugin = &fakePermitPlugin{} + +func TestNewInformerFactoryTrim(t *testing.T) { + cs := fake.NewClientset() + informerFactory := NewInformerFactory(cs, 0) + pd := &v1.Pod{ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, Spec: v1.PodSpec{}} + pd.SetManagedFields([]metav1.ManagedFieldsEntry{ + { + Manager: "update", + Operation: metav1.ManagedFieldsOperationApply, + APIVersion: "apps/v1", + }, + }) + lister := informerFactory.Core().V1().Pods().Lister() + + informerFactory.Start(nil) + informerFactory.WaitForCacheSync(nil) + _, err := cs.CoreV1().Pods("default").Create(context.Background(), pd, metav1.CreateOptions{}) + require.NoError(t, err) + time.Sleep(time.Millisecond * 10) + p, err := lister.Pods("default").Get("test") + require.NoError(t, err) + require.Equal(t, []metav1.ManagedFieldsEntry(nil), p.GetManagedFields()) +} From a8c551e627aa55ae602d7c98fcd3316a652b882f Mon Sep 17 00:00:00 2001 From: Joe Betz Date: Thu, 5 Mar 2026 20:49:00 -0500 Subject: [PATCH 4/4] Fix test --- pkg/scheduler/scheduler_test.go | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go index 1a5121560a0..9e4e6f95fc4 100644 --- a/pkg/scheduler/scheduler_test.go +++ b/pkg/scheduler/scheduler_test.go @@ -1467,26 +1467,29 @@ var _ fwk.PermitPlugin = &fakePermitPlugin{} func TestNewInformerFactoryTrim(t *testing.T) { cs := fake.NewClientset() - informerFactory := NewInformerFactory(cs, 0) + pd := &v1.Pod{ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "default", - }, Spec: v1.PodSpec{}} - pd.SetManagedFields([]metav1.ManagedFieldsEntry{ - { - Manager: "update", - Operation: metav1.ManagedFieldsOperationApply, - APIVersion: "apps/v1", + ManagedFields: []metav1.ManagedFieldsEntry{ + { + Manager: "update", + Operation: metav1.ManagedFieldsOperationApply, + APIVersion: "apps/v1", + }, }, - }) + }} + require.NoError(t, cs.Tracker().Add(pd)) + + informerFactory := NewInformerFactory(cs, 0) lister := informerFactory.Core().V1().Pods().Lister() - informerFactory.Start(nil) - informerFactory.WaitForCacheSync(nil) - _, err := cs.CoreV1().Pods("default").Create(context.Background(), pd, metav1.CreateOptions{}) - require.NoError(t, err) - time.Sleep(time.Millisecond * 10) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + informerFactory.Start(ctx.Done()) + informerFactory.WaitForCacheSync(ctx.Done()) + p, err := lister.Pods("default").Get("test") require.NoError(t, err) - require.Equal(t, []metav1.ManagedFieldsEntry(nil), p.GetManagedFields()) + require.Empty(t, p.GetManagedFields(), "expected managedFields to be trimmed by the transform") }