Repository: kubernetes/kubernetes (language: go)

Issue:
[Flaking Test] ci-kubernetes-unit (TestReconcileElectionStep)
### Which jobs are flaking?

master-blocking:
- ci-kubernetes-unit 

### Which tests are flaking?

`k8s.io/kubernetes/pkg/controlplane/controller/leaderelection.leaderelection`

### Since when has it been flaking?

[2024-07-27 06:40:22 +0000 UTC ci-kubernetes-unit](https://prow.k8s.io/view/gs/kubernetes-jenkins/logs/ci-kubernetes-unit/1817087405295931392)
[7/26/2024, 9:23:33 PM ci-kubernetes-unit-windows-master](https://prow.k8s.io/view/gs/kubernetes-jenkins/logs/ci-kubernetes-unit-windows-master/1816864433415131136)
[7/26/2024, 9:23:33 AM ci-kubernetes-unit-windows-master](https://prow.k8s.io/view/gs/kubernetes-jenkins/logs/ci-kubernetes-unit-windows-master/1816683237792026624)

### Testgrid link

https://testgrid.k8s.io/sig-release-master-blocking#ci-kubernetes-unit

### Reason for failure (if possible)

```
Failed
=== RUN   TestReconcileElectionStep/candidates_exist,_should_only_elect_leader_from_acked_candidates
    leaderelection_controller_test.go:373: reconcileElectionStep() requeue = 0s, want true
    leaderelection_controller_test.go:384: leases.coordination.k8s.io "component-A" not found
--- FAIL: TestReconcileElectionStep/candidates_exist,_should_only_elect_leader_from_acked_candidates (0.11s)

```

### Anything else we need to know?

_No response_

### Relevant SIG(s)

/sig api-machinery
cc @kubernetes/release-team-release-signal 


Discussion / hints:
This issue is currently awaiting triage.

If a SIG or subproject determines this is a relevant issue, they will accept it by applying the `triage/accepted` label and provide further guidance.

The `triage/accepted` label can be added by org members by writing `/triage accepted` in a comment.


<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>

Fix patch:
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 6c473339eee66..4ee8e863aa1d3 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
@@ -228,6 +228,7 @@ type SharedInformerFactory interface {
 
 	// 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
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 90319bd215a76..a22336a31f64c 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
@@ -228,6 +228,7 @@ type SharedInformerFactory interface {
 
 	// 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
diff --git a/staging/src/k8s.io/client-go/informers/factory.go b/staging/src/k8s.io/client-go/informers/factory.go
index f2fef0e0b2e3f..86c24551ef98d 100644
--- a/staging/src/k8s.io/client-go/informers/factory.go
+++ b/staging/src/k8s.io/client-go/informers/factory.go
@@ -247,6 +247,7 @@ type SharedInformerFactory interface {
 
 	// 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
diff --git a/staging/src/k8s.io/client-go/tools/leaderelection/leasecandidate.go b/staging/src/k8s.io/client-go/tools/leaderelection/leasecandidate.go
index c75fc3bdf76ea..74cf5bb5c25ff 100644
--- a/staging/src/k8s.io/client-go/tools/leaderelection/leasecandidate.go
+++ b/staging/src/k8s.io/client-go/tools/leaderelection/leasecandidate.go
@@ -120,7 +120,7 @@ func NewCandidate(clientset kubernetes.Interface,
 func (c *LeaseCandidate) Run(ctx context.Context) {
 	defer c.queue.ShutDown()
 
-	go c.informerFactory.Start(ctx.Done())
+	c.informerFactory.Start(ctx.Done())
 	if !cache.WaitForNamedCacheSync("leasecandidateclient", ctx.Done(), c.hasSynced) {
 		return
 	}
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 ee69aac35d986..b27cfeb0a3ced 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
@@ -299,7 +299,8 @@ type SharedInformerFactory interface {
 
 	// Start initializes all requested informers. They are handled in goroutines
 	// which run until the stop channel gets closed.
-        Start(stopCh <-chan struct{})
+	// 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
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 17c25f261a9c0..a3cd3f40e4bfe 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
@@ -228,6 +228,7 @@ type SharedInformerFactory interface {
 
 	// 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
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 9cefe3d0cc0d6..4628bbb862d59 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
@@ -228,6 +228,7 @@ type SharedInformerFactory interface {
 
 	// 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
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 a07237c90e4e0..5efa771d5eb6b 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
@@ -231,6 +231,7 @@ type SharedInformerFactory interface {
 
 	// 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
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 77e5c720e88b2..bdefa336fef95 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
@@ -229,6 +229,7 @@ type SharedInformerFactory interface {
 
 	// 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
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 f886fdf5e24c3..f282ac17b61a7 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
@@ -228,6 +228,7 @@ type SharedInformerFactory interface {
 
 	// 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
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 3cf42a74bd981..9774cfb8857e6 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
@@ -228,6 +228,7 @@ type SharedInformerFactory interface {
 
 	// 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
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 52c8c24219ce9..cc782bf7c0143 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
@@ -228,6 +228,7 @@ type SharedInformerFactory interface {
 
 	// 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
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 ccdfc8a8ff197..46b47b6576262 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
@@ -228,6 +228,7 @@ type SharedInformerFactory interface {
 
 	// 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


Test patch:
diff --git a/pkg/controller/garbagecollector/garbagecollector_test.go b/pkg/controller/garbagecollector/garbagecollector_test.go
index 6d2fdf7f9340f..2439fb732d4d4 100644
--- a/pkg/controller/garbagecollector/garbagecollector_test.go
+++ b/pkg/controller/garbagecollector/garbagecollector_test.go
@@ -223,7 +223,7 @@ func setupGC(t *testing.T, config *restclient.Config) garbageCollector {
 		t.Fatal(err)
 	}
 	stop := make(chan struct{})
-	go sharedInformers.Start(stop)
+	sharedInformers.Start(stop)
 	return garbageCollector{gc, stop}
 }
 
diff --git a/pkg/controller/validatingadmissionpolicystatus/controller_test.go b/pkg/controller/validatingadmissionpolicystatus/controller_test.go
index 17056cbb47b1b..e7ed6681c731d 100644
--- a/pkg/controller/validatingadmissionpolicystatus/controller_test.go
+++ b/pkg/controller/validatingadmissionpolicystatus/controller_test.go
@@ -113,7 +113,7 @@ func TestTypeChecking(t *testing.T) {
 			if err != nil {
 				t.Fatalf("cannot create controller: %v", err)
 			}
-			go informerFactory.Start(ctx.Done())
+			informerFactory.Start(ctx.Done())
 			go controller.Run(ctx, 1)
 			err = wait.PollUntilContextCancel(ctx, time.Second, false, func(ctx context.Context) (done bool, err error) {
 				name := policy.Name
diff --git a/pkg/controller/volume/ephemeral/controller_test.go b/pkg/controller/volume/ephemeral/controller_test.go
index 034bc25ed5937..8d9cffbadb403 100644
--- a/pkg/controller/volume/ephemeral/controller_test.go
+++ b/pkg/controller/volume/ephemeral/controller_test.go
@@ -152,7 +152,7 @@ func TestSyncHandler(t *testing.T) {
 			ec, _ := c.(*ephemeralController)
 
 			// Ensure informers are up-to-date.
-			go informerFactory.Start(ctx.Done())
+			informerFactory.Start(ctx.Done())
 			informerFactory.WaitForCacheSync(ctx.Done())
 			cache.WaitForCacheSync(ctx.Done(), podInformer.Informer().HasSynced, pvcInformer.Informer().HasSynced)
 
diff --git a/pkg/controlplane/controller/leaderelection/leaderelection_controller_test.go b/pkg/controlplane/controller/leaderelection/leaderelection_controller_test.go
index 3458aa96df214..412452c9ce43a 100644
--- a/pkg/controlplane/controller/leaderelection/leaderelection_controller_test.go
+++ b/pkg/controlplane/controller/leaderelection/leaderelection_controller_test.go
@@ -32,8 +32,6 @@ import (
 	"k8s.io/client-go/informers"
 	"k8s.io/client-go/kubernetes/fake"
 	"k8s.io/utils/ptr"
-
-	"k8s.io/client-go/tools/cache"
 )
 
 func TestReconcileElectionStep(t *testing.T) {
@@ -339,7 +337,7 @@ func TestReconcileElectionStep(t *testing.T) {
 			ctx := context.Background()
 			client := fake.NewSimpleClientset()
 			informerFactory := informers.NewSharedInformerFactory(client, 0)
-			_ = informerFactory.Coordination().V1alpha1().LeaseCandidates().Lister()
+
 			controller, err := NewController(
 				informerFactory.Coordination().V1().Leases(),
 				informerFactory.Coordination().V1alpha1().LeaseCandidates(),
@@ -349,8 +347,7 @@ func TestReconcileElectionStep(t *testing.T) {
 			if err != nil {
 				t.Fatal(err)
 			}
-			go informerFactory.Start(ctx.Done())
-			informerFactory.WaitForCacheSync(ctx.Done())
+
 			// Set up the fake client with the existing lease
 			if tc.existingLease != nil {
 				_, err = client.CoordinationV1().Leases(tc.existingLease.Namespace).Create(ctx, tc.existingLease, metav1.CreateOptions{})
@@ -366,7 +363,10 @@ func TestReconcileElectionStep(t *testing.T) {
 					t.Fatal(err)
 				}
 			}
-			cache.WaitForCacheSync(ctx.Done(), controller.leaseCandidateInformer.Informer().HasSynced)
+
+			informerFactory.Start(ctx.Done())
+			informerFactory.WaitForCacheSync(ctx.Done())
+
 			requeue, err := controller.reconcileElectionStep(ctx, tc.leaseNN)
 
 			if (requeue != 0) != tc.expectedRequeue {
@@ -639,7 +639,7 @@ func TestController(t *testing.T) {
 				t.Fatal(err)
 			}
 
-			go informerFactory.Start(ctx.Done())
+			informerFactory.Start(ctx.Done())
 			go controller.Run(ctx, 1)
 
 			go func() {
diff --git a/pkg/controlplane/controller/leaderelection/leasecandidategc_controller_test.go b/pkg/controlplane/controller/leaderelection/leasecandidategc_controller_test.go
index b081f715e94c3..b845d62b8dd89 100644
--- a/pkg/controlplane/controller/leaderelection/leasecandidategc_controller_test.go
+++ b/pkg/controlplane/controller/leaderelection/leasecandidategc_controller_test.go
@@ -115,7 +115,7 @@ func TestLeaseCandidateGCController(t *testing.T) {
 			leaseCandidateInformer := informerFactory.Coordination().V1alpha1().LeaseCandidates()
 			controller := NewLeaseCandidateGC(client, 10*time.Millisecond, leaseCandidateInformer)
 
-			go informerFactory.Start(ctx.Done())
+			informerFactory.Start(ctx.Done())
 			informerFactory.WaitForCacheSync(ctx.Done())
 
 			// Create lease candidates
diff --git a/pkg/proxy/config/api_test.go b/pkg/proxy/config/api_test.go
index 1bd9619b808f7..3c9f09307af49 100644
--- a/pkg/proxy/config/api_test.go
+++ b/pkg/proxy/config/api_test.go
@@ -60,7 +60,7 @@ func TestNewServicesSourceApi_UpdatesAndMultipleServices(t *testing.T) {
 
 	serviceConfig := NewServiceConfig(ctx, sharedInformers.Core().V1().Services(), time.Minute)
 	serviceConfig.RegisterEventHandler(handler)
-	go sharedInformers.Start(stopCh)
+	sharedInformers.Start(stopCh)
 	go serviceConfig.Run(stopCh)
 
 	// Add the first service
@@ -141,7 +141,7 @@ func TestNewEndpointsSourceApi_UpdatesAndMultipleEndpoints(t *testing.T) {
 
 	endpointsliceConfig := NewEndpointSliceConfig(ctx, sharedInformers.Discovery().V1().EndpointSlices(), time.Minute)
 	endpointsliceConfig.RegisterEventHandler(handler)
-	go sharedInformers.Start(stopCh)
+	sharedInformers.Start(stopCh)
 	go endpointsliceConfig.Run(stopCh)
 
 	// Add the first endpoints
diff --git a/pkg/proxy/config/config_test.go b/pkg/proxy/config/config_test.go
index 58e9cfa12c327..88802c3667a02 100644
--- a/pkg/proxy/config/config_test.go
+++ b/pkg/proxy/config/config_test.go
@@ -240,7 +240,7 @@ func TestNewServiceAddedAndNotified(t *testing.T) {
 	config := NewServiceConfig(ctx, sharedInformers.Core().V1().Services(), time.Minute)
 	handler := NewServiceHandlerMock()
 	config.RegisterEventHandler(handler)
-	go sharedInformers.Start(stopCh)
+	sharedInformers.Start(stopCh)
 	go config.Run(stopCh)
 
 	service := &v1.Service{
@@ -265,7 +265,7 @@ func TestServiceAddedRemovedSetAndNotified(t *testing.T) {
 	config := NewServiceConfig(ctx, sharedInformers.Core().V1().Services(), time.Minute)
 	handler := NewServiceHandlerMock()
 	config.RegisterEventHandler(handler)
-	go sharedInformers.Start(stopCh)
+	sharedInformers.Start(stopCh)
 	go config.Run(stopCh)
 
 	service1 := &v1.Service{
@@ -304,7 +304,7 @@ func TestNewServicesMultipleHandlersAddedAndNotified(t *testing.T) {
 	handler2 := NewServiceHandlerMock()
 	config.RegisterEventHandler(handler)
 	config.RegisterEventHandler(handler2)
-	go sharedInformers.Start(stopCh)
+	sharedInformers.Start(stopCh)
 	go config.Run(stopCh)
 
 	service1 := &v1.Service{
@@ -339,7 +339,7 @@ func TestNewEndpointsMultipleHandlersAddedAndNotified(t *testing.T) {
 	handler2 := NewEndpointSliceHandlerMock()
 	config.RegisterEventHandler(handler)
 	config.RegisterEventHandler(handler2)
-	go sharedInformers.Start(stopCh)
+	sharedInformers.Start(stopCh)
 	go config.Run(stopCh)
 
 	endpoints1 := &discoveryv1.EndpointSlice{
@@ -386,7 +386,7 @@ func TestNewEndpointsMultipleHandlersAddRemoveSetAndNotified(t *testing.T) {
 	handler2 := NewEndpointSliceHandlerMock()
 	config.RegisterEventHandler(handler)
 	config.RegisterEventHandler(handler2)
-	go sharedInformers.Start(stopCh)
+	sharedInformers.Start(stopCh)
 	go config.Run(stopCh)
 
 	endpoints1 := &discoveryv1.EndpointSlice{