Change:
} } <ins> func TestBlockMapperMapDeviceNotSupportAttach(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIDriverRegistry, true)() plug, tmpDir := newTestPlugin(t, nil) defer os.RemoveAll(tmpDir) fakeClient := fakeclient.NewSimpleClientset() attachRequired := false fakeDriver := &v1beta1.CSIDriver{ ObjectMeta: meta.ObjectMeta{ Name: testDriver, }, Spec: v1beta1.CSIDriverSpec{ AttachRequired: &attachRequired, }, } _, err := plug.host.GetKubeClient().StorageV1beta1().CSIDrivers().Create(fakeDriver) if err != nil { t.Fatalf("Failed to create a fakeDriver: %v", err) } host := volumetest.NewFakeVolumeHostWithCSINodeName( tmpDir, fakeClient, nil, "fakeNode", nil, ) plug.host = host csiMapper, _, _, err := prepareBlockMapperTest(plug, "test-pv", t) if err != nil { t.Fatalf("Failed to make a new Mapper: %v", err) } csiMapper.csiClient = setupClient(t, true) devicePath, err := csiMapper.SetUpDevice() if err != nil { t.Fatalf("mapper failed to SetupDevice: %v", err) } globalMapPath, err := csiMapper.GetGlobalMapPath(csiMapper.spec) if err != nil { t.Fatalf("mapper failed to GetGlobalMapPath: %v", err) } // Actual SetupDevice should create a symlink to or a bind mout of device in devicePath. // Create dummy file there before calling MapDevice to test it properly. fd, err := os.Create(devicePath) if err != nil { t.Fatalf("mapper failed to create dummy file in devicePath: %v", err) } if err := fd.Close(); err != nil { t.Fatalf("mapper failed to close dummy file in devicePath: %v", err) } // Map device to global and pod device map path volumeMapPath, volName := csiMapper.GetPodDeviceMapPath() err = csiMapper.MapDevice(devicePath, globalMapPath, volumeMapPath, volName, csiMapper.podUID) if err != nil { t.Fatalf("mapper failed to GetGlobalMapPath: %v", err) } // Check if symlink {globalMapPath}/{podUID} exists globalMapFilePath := filepath.Join(globalMapPath, string(csiMapper.podUID)) if _, err := os.Stat(globalMapFilePath); err != nil { if os.IsNotExist(err) { t.Errorf("mapper.MapDevice failed, symlink in globalMapPath not created: %v", err) t.Errorf("mapper.MapDevice devicePath:%v, globalMapPath: %v, globalMapFilePath: %v", devicePath, globalMapPath, globalMapFilePath) } else { t.Errorf("mapper.MapDevice failed: %v", err) } } // Check if symlink {volumeMapPath}/{volName} exists volumeMapFilePath := filepath.Join(volumeMapPath, volName) if _, err := os.Stat(volumeMapFilePath); err != nil { if os.IsNotExist(err) { t.Errorf("mapper.MapDevice failed, symlink in volumeMapPath not created: %v", err) } else { t.Errorf("mapper.MapDevice failed: %v", err) } } } </ins> func TestBlockMapperTearDownDevice(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()

Discussion:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! If the matter is security related, please disclose it privately via --What happened: During I develop a driver that supports raw block devices but do not need to be attached to nodes, I found it would fail when a pod mount a raw block device. PS: I use cluster-driver register and make requiredAttach as false. kubectl get csidriver csi-xxx -o yaml ! What you expected to happen: Mount a raw block device successfully. How to reproduce it (as minimally and precisely as possible): driver that supports raw block devices but do not need to be attached to nodes, I found it would fail when a pod mount a raw block device. cluster-driver register and make requiredAttach as false. a pod with raw block devices Anything else we need to know?: Environment: Kubernetes version (use ): 1.15 Cloud provider or hardware configuration: BaiduCloud OS (e.g: ): Kernel (e.g. ): Install tools: Network plugin and version (if this is a network-related bug): Others:
/sig storage /assign
I would send a PR later