Change:
Which test(s) are flaking: TestAttacherWithCSIDriver Reason for failure: This is flaking rarely enough that it is not caught by our CI jobs, which currently tolerate up to 2 unit test failures per run (!). With that toleration removed in , this flake has been seen (). Reproducible with the following steps: a test binary for the affected package: the affected test using the tool (setting the timeout to a generous timeout relative to the normal test runtime of .02 seconds): failures are seen, look at the logs to see the details about the error: /sig storage cc
/assign can you help investigate this flake?
I have found the root cause. /assign
filed to address this issue.

Discussion:
csiAttacher := attacher.(*csiAttacher) <ins> // FIXME: We need to ensure this goroutine exits in the test. </ins> go func(spec *volume.Spec, nodename string, fail bool) { attachID, err := csiAttacher.Attach(spec, types.NodeName(nodename)) if !fail && err != nil {

} csiAttacher := attacher.(*csiAttacher) <ins> // FIXME: We need to ensure this goroutine exits in the test. </ins> go func(spec *volume.Spec, nodename string, fail bool) { attachID, err := csiAttacher.Attach(spec, types.NodeName(nodename)) if fail != (err != nil) {

plug, _, tmpDir, _ := newTestWatchPlugin(t, fakeClient, true) defer os.RemoveAll(tmpDir) <ins> attachmentWatchCreated := make(chan core.Action) // Make sure this is the first reactor fakeClient.Fake.PrependWatchReactor("volumeattachments", func(action core.Action) (bool, watch.Interface, error) { select { case <-attachmentWatchCreated: // already closed default: // The attacher is already watching the attachment, notify the test goroutine to // update the status of attachment. // TODO: In theory this still has a race condition, because the actual watch is created by // the next reactor in the chain and we unblock the test goroutine before returning here. close(attachmentWatchCreated) } return false, nil, nil }) </ins> attacher, err := plug.NewAttacher() if err != nil { t.Fatalf("failed to create new attacher: %v", err)

} var wg sync.WaitGroup wg.Add(1) <del> go func(volSpec *volume.Spec, expectAttach bool) { attachID, err := csiAttacher.Attach(volSpec, types.NodeName("fakeNode")) </del> <ins> go func(volSpec *volume.Spec) { attachID, err := csiAttacher.Attach(volSpec, "fakeNode") </ins> defer wg.Done() if err != nil {

if attachID != "" { t.Errorf("Expected empty attachID, got %q", attachID) } <del> }(spec, test.expectVolumeAttachment) </del> <ins> }(spec) </ins> if test.expectVolumeAttachment { expectedAttachID := getAttachmentName("test-vol", test.driver, "fakeNode") status := storage.VolumeAttachmentStatus{ Attached: true, } <ins> // We want to ensure the watcher, which is created in csiAttacher, // has been started before updating the status of attachment. <-attachmentWatchCreated </ins> markVolumeAttached(t, csiAttacher.k8s, nil, expectedAttachID, status) } wg.Wait()

} factory.Start(wait.NeverStop) <ins> ctx, cancel := context.WithTimeout(context.Background(), TestInformerSyncTimeout) defer cancel() for ty, ok := range factory.WaitForCacheSync(ctx.Done()) { if !ok { t.Fatalf("failed to sync: %#v", ty) } } </ins> host := volumetest.NewFakeVolumeHostWithCSINodeName(t, tmpDir,

t.Fatalf("cannot assert plugin to be type csiPlugin") } <del> // Wait until the informer in CSI volume plugin has all CSIDrivers. wait.PollImmediate(TestInformerSyncPeriod, TestInformerSyncTimeout, func() (bool, error) { return csiDriverInformer.Informer().HasSynced(), nil }) if volumeAttachmentInformer != nil { wait.PollImmediate(TestInformerSyncPeriod, TestInformerSyncTimeout, func() (bool, error) { return volumeAttachmentInformer.Informer().HasSynced(), nil }) } </del> return csiPlug, fakeWatcher, tmpDir, fakeClient }