@@ -36,6 +36,7 @@ import (
36
36
37
37
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage"
38
38
"github.com/container-storage-interface/spec/lib/go/csi"
39
+ "github.com/google/uuid"
39
40
"github.com/stretchr/testify/assert"
40
41
"go.uber.org/mock/gomock"
41
42
@@ -234,6 +235,113 @@ func TestNodePublishVolume(t *testing.T) {
234
235
},
235
236
expectedErr : status .Error (codes .InvalidArgument , fmt .Sprintf ("invalid mountPermissions %s" , "07ab" )),
236
237
},
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 (_ * 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 (_ * 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 : func () error {
338
+ if runtime .GOOS == "windows" {
339
+ t .Skip ("Skipping test on " , runtime .GOOS )
340
+ return nil
341
+ }
342
+ return status .Errorf (codes .Internal , "Could not mount target \" ./azure.go\" : mkdir ./azure.go: not a directory" )
343
+ }(),
344
+ },
237
345
}
238
346
239
347
// Setup
@@ -273,6 +381,71 @@ func TestNodePublishVolume(t *testing.T) {
273
381
assert .NoError (t , err )
274
382
}
275
383
384
+ func TestNodePublishVolumeMountError (t * testing.T ) {
385
+ d := NewFakeDriver ()
386
+ fakeMounter := & fakeMounter {}
387
+ fakeExec := & testingexec.FakeExec {ExactOrder : true }
388
+ d .mounter = & mount.SafeFormatAndMount {
389
+ Interface : fakeMounter ,
390
+ Exec : fakeExec ,
391
+ }
392
+
393
+ volumeCap := csi.VolumeCapability_AccessMode {
394
+ Mode : csi .VolumeCapability_AccessMode_SINGLE_NODE_WRITER ,
395
+ }
396
+
397
+ // Test case 1: Mount fails with source error
398
+ targetPath := "./mount_test_target"
399
+ _ = makeDir (targetPath )
400
+
401
+ req := & csi.NodePublishVolumeRequest {
402
+ VolumeId : "vol_1" ,
403
+ TargetPath : targetPath ,
404
+ StagingTargetPath : "error_mount" , // This will trigger an error in Mount
405
+ VolumeCapability : & csi.VolumeCapability {
406
+ AccessMode : & volumeCap ,
407
+ },
408
+ }
409
+
410
+ // Run the test
411
+ _ , err := d .NodePublishVolume (context .Background (), req )
412
+ expectedErr := status .Errorf (codes .Internal , "Could not mount \" error_mount\" at \" ./mount_test_target\" : fake Mount: source error" )
413
+ if err == nil || err .Error () != expectedErr .Error () {
414
+ t .Errorf ("Expected error: %v, got: %v" , expectedErr , err )
415
+ }
416
+
417
+ // Clean up
418
+ _ = os .RemoveAll (targetPath )
419
+
420
+ // Let's try a different approach
421
+ // Let's create a custom fakeMounter that returns a specific error for Mount
422
+
423
+ // We'll continue to use the same fakeMounter
424
+ // It's already configured to return an error for paths containing "error_mount"
425
+
426
+ // Create a test directory that doesn't exist
427
+ nonExistentPath := "/tmp/non-existent-path-" + uuid .NewString ()
428
+
429
+ req = & csi.NodePublishVolumeRequest {
430
+ VolumeId : "vol_1" ,
431
+ TargetPath : nonExistentPath ,
432
+ StagingTargetPath : "error_mount" , // This will trigger an error in Mount
433
+ VolumeCapability : & csi.VolumeCapability {
434
+ AccessMode : & volumeCap ,
435
+ },
436
+ }
437
+
438
+ // Run the test
439
+ _ , err = d .NodePublishVolume (context .Background (), req )
440
+
441
+ // The error should be about failing to mount, not about removing the target
442
+ // because the target doesn't exist
443
+ expectedErr = status .Errorf (codes .Internal , "Could not mount \" error_mount\" at \" %s\" : fake Mount: source error" , nonExistentPath )
444
+ if err == nil || err .Error () != expectedErr .Error () {
445
+ t .Errorf ("Expected error: %v, got: %v" , expectedErr , err )
446
+ }
447
+ }
448
+
276
449
func TestNodePublishVolumeIdempotentMount (t * testing.T ) {
277
450
if runtime .GOOS != "linux" || os .Getuid () != 0 {
278
451
return
0 commit comments