@@ -36,6 +36,7 @@ import (
3636
3737 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage"
3838 "github.com/container-storage-interface/spec/lib/go/csi"
39+ "github.com/google/uuid"
3940 "github.com/stretchr/testify/assert"
4041 "go.uber.org/mock/gomock"
4142
@@ -234,6 +235,107 @@ func TestNodePublishVolume(t *testing.T) {
234235 },
235236 expectedErr : status .Error (codes .InvalidArgument , fmt .Sprintf ("invalid mountPermissions %s" , "07ab" )),
236237 },
238+ {
239+ desc : "Valid request with service account token and clientID" ,
240+ setup : func (d * Driver ) {
241+ // Mock NodeStageVolume to return success
242+ d .cloud .ResourceGroup = "rg"
243+ d .enableBlobMockMount = true
244+ },
245+ req : & csi.NodePublishVolumeRequest {
246+ VolumeCapability : & csi.VolumeCapability {AccessMode : & volumeCap },
247+ VolumeId : "vol_1" ,
248+ TargetPath : targetTest ,
249+ StagingTargetPath : sourceTest ,
250+ VolumeContext : map [string ]string {
251+ serviceAccountTokenField : `{"api://AzureADTokenExchange":{"token":"test-token","expirationTimestamp":"2023-01-01T00:00:00Z"}}` ,
252+ clientIDField : "client-id-value" ,
253+ },
254+ },
255+ expectedErr : nil ,
256+ },
257+ {
258+ desc : "Valid request with ephemeral volume" ,
259+ setup : func (d * Driver ) {
260+ // Mock NodeStageVolume to return success
261+ d .cloud .ResourceGroup = "rg"
262+ d .enableBlobMockMount = true
263+ },
264+ req : & csi.NodePublishVolumeRequest {
265+ VolumeCapability : & csi.VolumeCapability {AccessMode : & volumeCap },
266+ VolumeId : "vol_1" ,
267+ TargetPath : targetTest ,
268+ StagingTargetPath : sourceTest ,
269+ VolumeContext : map [string ]string {
270+ "csi.storage.k8s.io/ephemeral" : "true" ,
271+ "csi.storage.k8s.io/pod.namespace" : "test-namespace" ,
272+ "containername" : "test-container" , // Add container name to avoid error
273+ },
274+ },
275+ expectedErr : nil ,
276+ },
277+ {
278+ desc : "Volume already mounted" ,
279+ setup : func (d * Driver ) {
280+ // Create the directory and ensure it's seen as already mounted
281+ _ = makeDir ("./false_is_likely" )
282+ },
283+ req : & csi.NodePublishVolumeRequest {
284+ VolumeCapability : & csi.VolumeCapability {AccessMode : & volumeCap },
285+ VolumeId : "vol_1" ,
286+ TargetPath : "./false_is_likely" , // This path will make IsLikelyNotMountPoint return false
287+ StagingTargetPath : sourceTest ,
288+ },
289+ expectedErr : nil ,
290+ cleanup : func (d * Driver ) {
291+ // Clean up the directory
292+ _ = os .RemoveAll ("./false_is_likely" )
293+ },
294+ },
295+ {
296+ desc : "enableBlobMockMount enabled" ,
297+ setup : func (d * Driver ) {
298+ // Enable mock mount
299+ d .enableBlobMockMount = true
300+
301+ // Create a temporary directory for the test
302+ _ = makeDir ("./mock_mount_test" )
303+ },
304+ req : & csi.NodePublishVolumeRequest {
305+ VolumeCapability : & csi.VolumeCapability {AccessMode : & volumeCap },
306+ VolumeId : "vol_1" ,
307+ TargetPath : "./mock_mount_test" ,
308+ StagingTargetPath : sourceTest ,
309+ VolumeContext : map [string ]string {
310+ mountPermissionsField : "0755" ,
311+ },
312+ },
313+ expectedErr : nil ,
314+ cleanup : func (d * Driver ) {
315+ // Disable mock mount
316+ d .enableBlobMockMount = false
317+
318+ // Clean up the directory
319+ _ = os .RemoveAll ("./mock_mount_test" )
320+ },
321+ },
322+ {
323+ desc : "enableBlobMockMount enabled - MakeDir fails" ,
324+ setup : func (d * Driver ) {
325+ // Enable mock mount
326+ d .enableBlobMockMount = true
327+ },
328+ req : & csi.NodePublishVolumeRequest {
329+ VolumeCapability : & csi.VolumeCapability {AccessMode : & volumeCap },
330+ VolumeId : "vol_1" ,
331+ TargetPath : "./azure.go" , // This will fail because it's a file, not a directory
332+ StagingTargetPath : sourceTest ,
333+ VolumeContext : map [string ]string {
334+ mountPermissionsField : "0755" ,
335+ },
336+ },
337+ expectedErr : status .Errorf (codes .Internal , "Could not mount target \" ./azure.go\" : mkdir ./azure.go: not a directory" ),
338+ },
237339 }
238340
239341 // Setup
@@ -273,6 +375,71 @@ func TestNodePublishVolume(t *testing.T) {
273375 assert .NoError (t , err )
274376}
275377
378+ func TestNodePublishVolumeMountError (t * testing.T ) {
379+ d := NewFakeDriver ()
380+ fakeMounter := & fakeMounter {}
381+ fakeExec := & testingexec.FakeExec {ExactOrder : true }
382+ d .mounter = & mount.SafeFormatAndMount {
383+ Interface : fakeMounter ,
384+ Exec : fakeExec ,
385+ }
386+
387+ volumeCap := csi.VolumeCapability_AccessMode {
388+ Mode : csi .VolumeCapability_AccessMode_SINGLE_NODE_WRITER ,
389+ }
390+
391+ // Test case 1: Mount fails with source error
392+ targetPath := "./mount_test_target"
393+ _ = makeDir (targetPath )
394+
395+ req := & csi.NodePublishVolumeRequest {
396+ VolumeId : "vol_1" ,
397+ TargetPath : targetPath ,
398+ StagingTargetPath : "error_mount" , // This will trigger an error in Mount
399+ VolumeCapability : & csi.VolumeCapability {
400+ AccessMode : & volumeCap ,
401+ },
402+ }
403+
404+ // Run the test
405+ _ , err := d .NodePublishVolume (context .Background (), req )
406+ expectedErr := status .Errorf (codes .Internal , "Could not mount \" error_mount\" at \" ./mount_test_target\" : fake Mount: source error" )
407+ if err == nil || err .Error () != expectedErr .Error () {
408+ t .Errorf ("Expected error: %v, got: %v" , expectedErr , err )
409+ }
410+
411+ // Clean up
412+ _ = os .RemoveAll (targetPath )
413+
414+ // Let's try a different approach
415+ // Let's create a custom fakeMounter that returns a specific error for Mount
416+
417+ // We'll continue to use the same fakeMounter
418+ // It's already configured to return an error for paths containing "error_mount"
419+
420+ // Create a test directory that doesn't exist
421+ nonExistentPath := "/tmp/non-existent-path-" + uuid .NewString ()
422+
423+ req = & csi.NodePublishVolumeRequest {
424+ VolumeId : "vol_1" ,
425+ TargetPath : nonExistentPath ,
426+ StagingTargetPath : "error_mount" , // This will trigger an error in Mount
427+ VolumeCapability : & csi.VolumeCapability {
428+ AccessMode : & volumeCap ,
429+ },
430+ }
431+
432+ // Run the test
433+ _ , err = d .NodePublishVolume (context .Background (), req )
434+
435+ // The error should be about failing to mount, not about removing the target
436+ // because the target doesn't exist
437+ expectedErr = status .Errorf (codes .Internal , "Could not mount \" error_mount\" at \" %s\" : fake Mount: source error" , nonExistentPath )
438+ if err == nil || err .Error () != expectedErr .Error () {
439+ t .Errorf ("Expected error: %v, got: %v" , expectedErr , err )
440+ }
441+ }
442+
276443func TestNodePublishVolumeIdempotentMount (t * testing.T ) {
277444 if runtime .GOOS != "linux" || os .Getuid () != 0 {
278445 return
0 commit comments