1
16
17 package csi
18
19 import (
20 "context"
21 "fmt"
22 "os"
23 "path/filepath"
24 "reflect"
25 "testing"
26
27 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/status"
29
30 api "k8s.io/api/core/v1"
31 storagev1 "k8s.io/api/storage/v1"
32 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
33 fakeclient "k8s.io/client-go/kubernetes/fake"
34 "k8s.io/kubernetes/pkg/volume"
35 volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
36 )
37
38 func prepareBlockMapperTest(plug *csiPlugin, specVolumeName string, t *testing.T) (*csiBlockMapper, *volume.Spec, *api.PersistentVolume, error) {
39 registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t)
40 pv := makeTestPV(specVolumeName, 10, testDriver, testVol)
41 spec := volume.NewSpecFromPersistentVolume(pv, pv.Spec.PersistentVolumeSource.CSI.ReadOnly)
42 mapper, err := plug.NewBlockVolumeMapper(
43 spec,
44 &api.Pod{ObjectMeta: metav1.ObjectMeta{UID: testPodUID, Namespace: testns, Name: testPod}},
45 volume.VolumeOptions{},
46 )
47 if err != nil {
48 return nil, nil, nil, fmt.Errorf("failed to make a new Mapper: %w", err)
49 }
50 csiMapper := mapper.(*csiBlockMapper)
51 return csiMapper, spec, pv, nil
52 }
53
54 func TestBlockMapperGetGlobalMapPath(t *testing.T) {
55 plug, tmpDir := newTestPlugin(t, nil)
56 defer os.RemoveAll(tmpDir)
57
58
59 testCases := []struct {
60 name string
61 specVolumeName string
62 path string
63 }{
64 {
65 name: "simple specName",
66 specVolumeName: "spec-0",
67 path: filepath.Join(tmpDir, fmt.Sprintf("plugins/kubernetes.io/csi/volumeDevices/%s/%s", "spec-0", "dev")),
68 },
69 {
70 name: "specName with dots",
71 specVolumeName: "test.spec.1",
72 path: filepath.Join(tmpDir, fmt.Sprintf("plugins/kubernetes.io/csi/volumeDevices/%s/%s", "test.spec.1", "dev")),
73 },
74 }
75 for _, tc := range testCases {
76 t.Logf("test case: %s", tc.name)
77 csiMapper, spec, _, err := prepareBlockMapperTest(plug, tc.specVolumeName, t)
78 if err != nil {
79 t.Fatalf("Failed to make a new Mapper: %v", err)
80 }
81
82 path, err := csiMapper.GetGlobalMapPath(spec)
83 if err != nil {
84 t.Errorf("mapper GetGlobalMapPath failed: %v", err)
85 }
86
87 if tc.path != path {
88 t.Errorf("expecting path %s, got %s", tc.path, path)
89 }
90 }
91 }
92
93 func TestBlockMapperGetStagingPath(t *testing.T) {
94 plug, tmpDir := newTestPlugin(t, nil)
95 defer os.RemoveAll(tmpDir)
96
97 testCases := []struct {
98 name string
99 specVolumeName string
100 path string
101 }{
102 {
103 name: "simple specName",
104 specVolumeName: "spec-0",
105 path: filepath.Join(tmpDir, fmt.Sprintf("plugins/kubernetes.io/csi/volumeDevices/staging/%s", "spec-0")),
106 },
107 {
108 name: "specName with dots",
109 specVolumeName: "test.spec.1",
110 path: filepath.Join(tmpDir, fmt.Sprintf("plugins/kubernetes.io/csi/volumeDevices/staging/%s", "test.spec.1")),
111 },
112 }
113 for _, tc := range testCases {
114 t.Logf("test case: %s", tc.name)
115 csiMapper, _, _, err := prepareBlockMapperTest(plug, tc.specVolumeName, t)
116 if err != nil {
117 t.Fatalf("Failed to make a new Mapper: %v", err)
118 }
119
120 path := csiMapper.GetStagingPath()
121
122 if tc.path != path {
123 t.Errorf("expecting path %s, got %s", tc.path, path)
124 }
125 }
126 }
127
128 func TestBlockMapperGetPublishPath(t *testing.T) {
129 plug, tmpDir := newTestPlugin(t, nil)
130 defer os.RemoveAll(tmpDir)
131
132 testCases := []struct {
133 name string
134 specVolumeName string
135 path string
136 }{
137 {
138 name: "simple specName",
139 specVolumeName: "spec-0",
140 path: filepath.Join(tmpDir, fmt.Sprintf("plugins/kubernetes.io/csi/volumeDevices/publish/%s/%s", "spec-0", testPodUID)),
141 },
142 {
143 name: "specName with dots",
144 specVolumeName: "test.spec.1",
145 path: filepath.Join(tmpDir, fmt.Sprintf("plugins/kubernetes.io/csi/volumeDevices/publish/%s/%s", "test.spec.1", testPodUID)),
146 },
147 }
148 for _, tc := range testCases {
149 t.Logf("test case: %s", tc.name)
150 csiMapper, _, _, err := prepareBlockMapperTest(plug, tc.specVolumeName, t)
151 if err != nil {
152 t.Fatalf("Failed to make a new Mapper: %v", err)
153 }
154
155 path := csiMapper.getPublishPath()
156
157 if tc.path != path {
158 t.Errorf("expecting path %s, got %s", tc.path, path)
159 }
160 }
161 }
162
163 func TestBlockMapperGetDeviceMapPath(t *testing.T) {
164 plug, tmpDir := newTestPlugin(t, nil)
165 defer os.RemoveAll(tmpDir)
166
167 testCases := []struct {
168 name string
169 specVolumeName string
170 path string
171 }{
172 {
173 name: "simple specName",
174 specVolumeName: "spec-0",
175 path: filepath.Join(tmpDir, fmt.Sprintf("pods/%s/volumeDevices/kubernetes.io~csi", testPodUID)),
176 },
177 {
178 name: "specName with dots",
179 specVolumeName: "test.spec.1",
180 path: filepath.Join(tmpDir, fmt.Sprintf("pods/%s/volumeDevices/kubernetes.io~csi", testPodUID)),
181 },
182 }
183 for _, tc := range testCases {
184 t.Logf("test case: %s", tc.name)
185 csiMapper, _, _, err := prepareBlockMapperTest(plug, tc.specVolumeName, t)
186 if err != nil {
187 t.Fatalf("Failed to make a new Mapper: %v", err)
188 }
189
190 path, volName := csiMapper.GetPodDeviceMapPath()
191
192 if tc.path != path {
193 t.Errorf("expecting path %s, got %s", tc.path, path)
194 }
195
196 if tc.specVolumeName != volName {
197 t.Errorf("expecting volName %s, got %s", tc.specVolumeName, volName)
198 }
199 }
200 }
201
202 func TestBlockMapperSetupDevice(t *testing.T) {
203 plug, tmpDir := newTestPlugin(t, nil)
204 defer os.RemoveAll(tmpDir)
205
206 csiMapper, _, pv, err := prepareBlockMapperTest(plug, "test-pv", t)
207 if err != nil {
208 t.Fatalf("Failed to make a new Mapper: %v", err)
209 }
210
211 pvName := pv.GetName()
212 nodeName := string(plug.host.GetNodeName())
213
214 csiMapper.csiClient = setupClient(t, true)
215
216 attachID := getAttachmentName(csiMapper.volumeID, string(csiMapper.driverName), string(nodeName))
217 attachment := makeTestAttachment(attachID, nodeName, pvName)
218 attachment.Status.Attached = true
219 _, err = csiMapper.k8s.StorageV1().VolumeAttachments().Create(context.TODO(), attachment, metav1.CreateOptions{})
220 if err != nil {
221 t.Fatalf("failed to setup VolumeAttachment: %v", err)
222 }
223 t.Log("created attachment ", attachID)
224
225 stagingPath, err := csiMapper.SetUpDevice()
226 if err != nil {
227 t.Fatalf("mapper failed to SetupDevice: %v", err)
228 }
229
230
231 svols := csiMapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodeStagedVolumes()
232 svol, ok := svols[csiMapper.volumeID]
233 if !ok {
234 t.Error("csi server may not have received NodeStageVolume call")
235 }
236 if svol.Path != stagingPath {
237 t.Errorf("csi server expected device path %s, got %s", stagingPath, svol.Path)
238 }
239 }
240
241 func TestBlockMapperSetupDeviceError(t *testing.T) {
242 plug, tmpDir := newTestPlugin(t, nil)
243 defer os.RemoveAll(tmpDir)
244
245 csiMapper, _, pv, err := prepareBlockMapperTest(plug, "test-pv", t)
246 if err != nil {
247 t.Fatalf("Failed to make a new Mapper: %v", err)
248 }
249
250 pvName := pv.GetName()
251 nodeName := string(plug.host.GetNodeName())
252
253 csiMapper.csiClient = setupClient(t, true)
254 fClient := csiMapper.csiClient.(*fakeCsiDriverClient)
255 fClient.nodeClient.SetNextError(status.Error(codes.InvalidArgument, "mock final error"))
256
257 attachID := getAttachmentName(csiMapper.volumeID, string(csiMapper.driverName), string(nodeName))
258 attachment := makeTestAttachment(attachID, nodeName, pvName)
259 attachment.Status.Attached = true
260 _, err = csiMapper.k8s.StorageV1().VolumeAttachments().Create(context.Background(), attachment, metav1.CreateOptions{})
261 if err != nil {
262 t.Fatalf("failed to setup VolumeAttachment: %v", err)
263 }
264 t.Log("created attachment ", attachID)
265
266 stagingPath, err := csiMapper.SetUpDevice()
267 if err == nil {
268 t.Fatal("mapper unexpectedly succeeded")
269 }
270
271
272
273 dataDir := getVolumeDeviceDataDir(pv.ObjectMeta.Name, plug.host)
274 if _, err := os.Stat(dataDir); err == nil {
275 t.Errorf("volume publish data directory %s was not deleted", dataDir)
276 }
277 devDir := getVolumeDeviceDataDir(pv.ObjectMeta.Name, plug.host)
278 if _, err := os.Stat(devDir); err == nil {
279 t.Errorf("volume publish device directory %s was not deleted", devDir)
280 }
281
282 if _, err := os.Stat(stagingPath); err == nil {
283 t.Errorf("volume staging path %s was not deleted", stagingPath)
284 }
285 }
286
287 func TestBlockMapperSetupDeviceNoClientError(t *testing.T) {
288 transientError := volumetypes.NewTransientOperationFailure("")
289 plug, tmpDir := newTestPlugin(t, nil)
290 defer os.RemoveAll(tmpDir)
291
292 csiMapper, _, pv, err := prepareBlockMapperTest(plug, "test-pv", t)
293 if err != nil {
294 t.Fatalf("Failed to make a new Mapper: %v", err)
295 }
296
297 pvName := pv.GetName()
298 nodeName := string(plug.host.GetNodeName())
299
300 csiMapper.csiClient = setupClient(t, true)
301
302 attachID := getAttachmentName(csiMapper.volumeID, string(csiMapper.driverName), string(nodeName))
303 attachment := makeTestAttachment(attachID, nodeName, pvName)
304 attachment.Status.Attached = true
305 _, err = csiMapper.k8s.StorageV1().VolumeAttachments().Create(context.TODO(), attachment, metav1.CreateOptions{})
306 if err != nil {
307 t.Fatalf("failed to setup VolumeAttachment: %v", err)
308 }
309 t.Log("created attachment ", attachID)
310
311
312
313 csiMapper.csiClient = nil
314 csiMapper.csiClientGetter.csiClient = nil
315
316 csiMapper.csiClientGetter.driverName = "unknown-driver"
317
318 _, err = csiMapper.SetUpDevice()
319 if err == nil {
320 t.Errorf("test should fail, but no error occurred")
321 } else if reflect.TypeOf(transientError) != reflect.TypeOf(err) {
322 t.Fatalf("expected exitError type: %v got: %v (%v)", reflect.TypeOf(transientError), reflect.TypeOf(err), err)
323 }
324 }
325
326 func TestBlockMapperMapPodDevice(t *testing.T) {
327 plug, tmpDir := newTestPlugin(t, nil)
328 defer os.RemoveAll(tmpDir)
329
330 csiMapper, _, pv, err := prepareBlockMapperTest(plug, "test-pv", t)
331 if err != nil {
332 t.Fatalf("Failed to make a new Mapper: %v", err)
333 }
334
335 pvName := pv.GetName()
336 nodeName := string(plug.host.GetNodeName())
337
338 csiMapper.csiClient = setupClient(t, true)
339
340 attachID := getAttachmentName(csiMapper.volumeID, string(csiMapper.driverName), nodeName)
341 attachment := makeTestAttachment(attachID, nodeName, pvName)
342 attachment.Status.Attached = true
343 _, err = csiMapper.k8s.StorageV1().VolumeAttachments().Create(context.Background(), attachment, metav1.CreateOptions{})
344 if err != nil {
345 t.Fatalf("failed to setup VolumeAttachment: %v", err)
346 }
347 t.Log("created attachment ", attachID)
348
349
350 path, err := csiMapper.MapPodDevice()
351 if err != nil {
352 t.Fatalf("mapper failed to GetGlobalMapPath: %v", err)
353 }
354
355
356 pvols := csiMapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes()
357 pvol, ok := pvols[csiMapper.volumeID]
358 if !ok {
359 t.Error("csi server may not have received NodePublishVolume call")
360 }
361
362 publishPath := csiMapper.getPublishPath()
363 if pvol.Path != publishPath {
364 t.Errorf("csi server expected path %s, got %s", publishPath, pvol.Path)
365 }
366 if path != publishPath {
367 t.Errorf("csi server expected path %s, but MapPodDevice returned %s", publishPath, path)
368 }
369 }
370
371 func TestBlockMapperMapPodDeviceNotSupportAttach(t *testing.T) {
372 fakeClient := fakeclient.NewSimpleClientset()
373 attachRequired := false
374 fakeDriver := &storagev1.CSIDriver{
375 ObjectMeta: metav1.ObjectMeta{
376 Name: testDriver,
377 },
378 Spec: storagev1.CSIDriverSpec{
379 AttachRequired: &attachRequired,
380 },
381 }
382 _, err := fakeClient.StorageV1().CSIDrivers().Create(context.TODO(), fakeDriver, metav1.CreateOptions{})
383 if err != nil {
384 t.Fatalf("Failed to create a fakeDriver: %v", err)
385 }
386
387
388
389
390 plug, tmpDir := newTestPlugin(t, fakeClient)
391 defer os.RemoveAll(tmpDir)
392
393 csiMapper, _, _, err := prepareBlockMapperTest(plug, "test-pv", t)
394 if err != nil {
395 t.Fatalf("Failed to make a new Mapper: %v", err)
396 }
397 csiMapper.csiClient = setupClient(t, true)
398
399
400 path, err := csiMapper.MapPodDevice()
401 if err != nil {
402 t.Fatalf("mapper failed to GetGlobalMapPath: %v", err)
403 }
404 publishPath := csiMapper.getPublishPath()
405 if path != publishPath {
406 t.Errorf("path %s and %s doesn't match", path, publishPath)
407 }
408 }
409
410 func TestBlockMapperMapPodDeviceWithPodInfo(t *testing.T) {
411 fakeClient := fakeclient.NewSimpleClientset()
412 attachRequired := false
413 podInfo := true
414 fakeDriver := &storagev1.CSIDriver{
415 ObjectMeta: metav1.ObjectMeta{
416 Name: testDriver,
417 },
418 Spec: storagev1.CSIDriverSpec{
419 PodInfoOnMount: &podInfo,
420 AttachRequired: &attachRequired,
421 },
422 }
423 _, err := fakeClient.StorageV1().CSIDrivers().Create(context.TODO(), fakeDriver, metav1.CreateOptions{})
424 if err != nil {
425 t.Fatalf("Failed to create a fakeDriver: %v", err)
426 }
427
428
429
430
431 plug, tmpDir := newTestPlugin(t, fakeClient)
432 defer os.RemoveAll(tmpDir)
433
434 csiMapper, _, _, err := prepareBlockMapperTest(plug, "test-pv", t)
435 if err != nil {
436 t.Fatalf("Failed to make a new Mapper: %v", err)
437 }
438 csiMapper.csiClient = setupClient(t, true)
439
440
441 _, err = csiMapper.MapPodDevice()
442 if err != nil {
443 t.Fatalf("mapper failed to GetGlobalMapPath: %v", err)
444 }
445 pvols := csiMapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes()
446 pvol, ok := pvols[csiMapper.volumeID]
447 if !ok {
448 t.Error("csi server may not have received NodePublishVolume call")
449 }
450
451 if !reflect.DeepEqual(pvol.VolumeContext, map[string]string{"csi.storage.k8s.io/pod.uid": "test-pod", "csi.storage.k8s.io/serviceAccount.name": "", "csi.storage.k8s.io/pod.name": "test-pod", "csi.storage.k8s.io/pod.namespace": "test-ns", "csi.storage.k8s.io/ephemeral": "false"}) {
452 t.Error("csi mapper check pod info failed")
453 }
454 }
455
456 func TestBlockMapperMapPodDeviceNoClientError(t *testing.T) {
457 transientError := volumetypes.NewTransientOperationFailure("")
458 plug, tmpDir := newTestPlugin(t, nil)
459 defer os.RemoveAll(tmpDir)
460
461 csiMapper, _, pv, err := prepareBlockMapperTest(plug, "test-pv", t)
462 if err != nil {
463 t.Fatalf("Failed to make a new Mapper: %v", err)
464 }
465
466 pvName := pv.GetName()
467 nodeName := string(plug.host.GetNodeName())
468
469 csiMapper.csiClient = setupClient(t, true)
470
471 attachID := getAttachmentName(csiMapper.volumeID, string(csiMapper.driverName), nodeName)
472 attachment := makeTestAttachment(attachID, nodeName, pvName)
473 attachment.Status.Attached = true
474 _, err = csiMapper.k8s.StorageV1().VolumeAttachments().Create(context.Background(), attachment, metav1.CreateOptions{})
475 if err != nil {
476 t.Fatalf("failed to setup VolumeAttachment: %v", err)
477 }
478 t.Log("created attachment ", attachID)
479
480
481
482 csiMapper.csiClient = nil
483 csiMapper.csiClientGetter.csiClient = nil
484
485 csiMapper.csiClientGetter.driverName = "unknown-driver"
486
487 _, err = csiMapper.MapPodDevice()
488 if err == nil {
489 t.Errorf("test should fail, but no error occurred")
490 } else if reflect.TypeOf(transientError) != reflect.TypeOf(err) {
491 t.Fatalf("expected exitError type: %v got: %v (%v)", reflect.TypeOf(transientError), reflect.TypeOf(err), err)
492 }
493 }
494
495 func TestBlockMapperTearDownDevice(t *testing.T) {
496 plug, tmpDir := newTestPlugin(t, nil)
497 defer os.RemoveAll(tmpDir)
498
499 _, spec, pv, err := prepareBlockMapperTest(plug, "test-pv", t)
500 if err != nil {
501 t.Fatalf("Failed to make a new Mapper: %v", err)
502 }
503
504
505 dir := getVolumeDeviceDataDir(pv.ObjectMeta.Name, plug.host)
506 if err := os.MkdirAll(dir, 0755); err != nil && !os.IsNotExist(err) {
507 t.Errorf("failed to create dir [%s]: %v", dir, err)
508 }
509
510 if err := saveVolumeData(
511 dir,
512 volDataFileName,
513 map[string]string{
514 volDataKey.specVolID: pv.ObjectMeta.Name,
515 volDataKey.driverName: testDriver,
516 volDataKey.volHandle: testVol,
517 },
518 ); err != nil {
519 t.Fatalf("failed to save volume data: %v", err)
520 }
521
522 unmapper, err := plug.NewBlockVolumeUnmapper(pv.ObjectMeta.Name, testPodUID)
523 if err != nil {
524 t.Fatalf("failed to make a new Unmapper: %v", err)
525 }
526
527 csiUnmapper := unmapper.(*csiBlockMapper)
528 csiUnmapper.csiClient = setupClient(t, true)
529
530 globalMapPath, err := csiUnmapper.GetGlobalMapPath(spec)
531 if err != nil {
532 t.Fatalf("unmapper failed to GetGlobalMapPath: %v", err)
533 }
534
535 err = csiUnmapper.TearDownDevice(globalMapPath, "/dev/test")
536 if err != nil {
537 t.Fatal(err)
538 }
539
540
541 pubs := csiUnmapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes()
542 if _, ok := pubs[csiUnmapper.volumeID]; ok {
543 t.Error("csi server may not have received NodeUnpublishVolume call")
544 }
545
546
547 vols := csiUnmapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodeStagedVolumes()
548 if _, ok := vols[csiUnmapper.volumeID]; ok {
549 t.Error("csi server may not have received NodeUnstageVolume call")
550 }
551 }
552
553 func TestBlockMapperTearDownDeviceNoClientError(t *testing.T) {
554 transientError := volumetypes.NewTransientOperationFailure("")
555 plug, tmpDir := newTestPlugin(t, nil)
556 defer os.RemoveAll(tmpDir)
557
558 _, spec, pv, err := prepareBlockMapperTest(plug, "test-pv", t)
559 if err != nil {
560 t.Fatalf("Failed to make a new Mapper: %v", err)
561 }
562
563
564 dir := getVolumeDeviceDataDir(pv.ObjectMeta.Name, plug.host)
565 if err := os.MkdirAll(dir, 0755); err != nil && !os.IsNotExist(err) {
566 t.Errorf("failed to create dir [%s]: %v", dir, err)
567 }
568
569 if err := saveVolumeData(
570 dir,
571 volDataFileName,
572 map[string]string{
573 volDataKey.specVolID: pv.ObjectMeta.Name,
574 volDataKey.driverName: testDriver,
575 volDataKey.volHandle: testVol,
576 },
577 ); err != nil {
578 t.Fatalf("failed to save volume data: %v", err)
579 }
580
581 unmapper, err := plug.NewBlockVolumeUnmapper(pv.ObjectMeta.Name, testPodUID)
582 if err != nil {
583 t.Fatalf("failed to make a new Unmapper: %v", err)
584 }
585
586 csiUnmapper := unmapper.(*csiBlockMapper)
587 csiUnmapper.csiClient = setupClient(t, true)
588
589 globalMapPath, err := csiUnmapper.GetGlobalMapPath(spec)
590 if err != nil {
591 t.Fatalf("unmapper failed to GetGlobalMapPath: %v", err)
592 }
593
594
595
596 csiUnmapper.csiClient = nil
597 csiUnmapper.csiClientGetter.csiClient = nil
598
599 csiUnmapper.csiClientGetter.driverName = "unknown-driver"
600
601 err = csiUnmapper.TearDownDevice(globalMapPath, "/dev/test")
602 if err == nil {
603 t.Errorf("test should fail, but no error occurred")
604 } else if reflect.TypeOf(transientError) != reflect.TypeOf(err) {
605 t.Fatalf("expected exitError type: %v got: %v (%v)", reflect.TypeOf(transientError), reflect.TypeOf(err), err)
606 }
607 }
608
609 func TestVolumeSetupTeardown(t *testing.T) {
610
611
612
613 plug, tmpDir := newTestPlugin(t, nil)
614 defer os.RemoveAll(tmpDir)
615
616 csiMapper, spec, pv, err := prepareBlockMapperTest(plug, "test-pv", t)
617 if err != nil {
618 t.Fatalf("Failed to make a new Mapper: %v", err)
619 }
620
621 pvName := pv.GetName()
622 nodeName := string(plug.host.GetNodeName())
623
624 csiMapper.csiClient = setupClient(t, true)
625
626 attachID := getAttachmentName(csiMapper.volumeID, string(csiMapper.driverName), string(nodeName))
627 attachment := makeTestAttachment(attachID, nodeName, pvName)
628 attachment.Status.Attached = true
629 _, err = csiMapper.k8s.StorageV1().VolumeAttachments().Create(context.TODO(), attachment, metav1.CreateOptions{})
630 if err != nil {
631 t.Fatalf("failed to setup VolumeAttachment: %v", err)
632 }
633 t.Log("created attachment ", attachID)
634
635 stagingPath, err := csiMapper.SetUpDevice()
636 if err != nil {
637 t.Fatalf("mapper failed to SetupDevice: %v", err)
638 }
639
640 svols := csiMapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodeStagedVolumes()
641 svol, ok := svols[csiMapper.volumeID]
642 if !ok {
643 t.Error("csi server may not have received NodeStageVolume call")
644 }
645 if svol.Path != stagingPath {
646 t.Errorf("csi server expected device path %s, got %s", stagingPath, svol.Path)
647 }
648
649 path, err := csiMapper.MapPodDevice()
650 if err != nil {
651 t.Fatalf("mapper failed to GetGlobalMapPath: %v", err)
652 }
653 pvols := csiMapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes()
654 pvol, ok := pvols[csiMapper.volumeID]
655 if !ok {
656 t.Error("csi server may not have received NodePublishVolume call")
657 }
658 publishPath := csiMapper.getPublishPath()
659 if pvol.Path != publishPath {
660 t.Errorf("csi server expected path %s, got %s", publishPath, pvol.Path)
661 }
662 if path != publishPath {
663 t.Errorf("csi server expected path %s, but MapPodDevice returned %s", publishPath, path)
664 }
665
666 unmapper, err := plug.NewBlockVolumeUnmapper(pv.ObjectMeta.Name, testPodUID)
667 if err != nil {
668 t.Fatalf("failed to make a new Unmapper: %v", err)
669 }
670
671 csiUnmapper := unmapper.(*csiBlockMapper)
672 csiUnmapper.csiClient = csiMapper.csiClient
673
674 globalMapPath, err := csiUnmapper.GetGlobalMapPath(spec)
675 if err != nil {
676 t.Fatalf("unmapper failed to GetGlobalMapPath: %v", err)
677 }
678
679 err = csiUnmapper.UnmapPodDevice()
680 if err != nil {
681 t.Errorf("unmapper failed to call UnmapPodDevice: %v", err)
682 }
683
684
685 unmapper, err = plug.NewBlockVolumeUnmapper(pv.ObjectMeta.Name, "")
686 if err != nil {
687 t.Fatalf("failed to make a new Unmapper: %v", err)
688 }
689 csiUnmapper = unmapper.(*csiBlockMapper)
690 csiUnmapper.csiClient = csiMapper.csiClient
691
692 err = csiUnmapper.TearDownDevice(globalMapPath, "/dev/test")
693 if err != nil {
694 t.Fatal(err)
695 }
696 pubs := csiUnmapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes()
697 if _, ok := pubs[csiUnmapper.volumeID]; ok {
698 t.Error("csi server may not have received NodeUnpublishVolume call")
699 }
700 vols := csiUnmapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodeStagedVolumes()
701 if _, ok := vols[csiUnmapper.volumeID]; ok {
702 t.Error("csi server may not have received NodeUnstageVolume call")
703 }
704
705
706 dataDir := getVolumeDeviceDataDir(pv.ObjectMeta.Name, plug.host)
707 if _, err := os.Stat(dataDir); err == nil {
708 t.Errorf("volume publish data directory %s was not deleted", dataDir)
709 }
710 devDir := getVolumeDeviceDataDir(pv.ObjectMeta.Name, plug.host)
711 if _, err := os.Stat(devDir); err == nil {
712 t.Errorf("volume publish device directory %s was not deleted", devDir)
713 }
714 if _, err := os.Stat(publishPath); err == nil {
715 t.Errorf("volume publish path %s was not deleted", publishPath)
716 }
717 publishDir := filepath.Dir(publishPath)
718 if _, err := os.Stat(publishDir); err == nil {
719 t.Errorf("volume publish parent directory %s was not deleted", publishDir)
720 }
721 if _, err := os.Stat(stagingPath); err == nil {
722 t.Errorf("volume staging path %s was not deleted", stagingPath)
723 }
724 }
725
726 func TestUnmapPodDeviceNoClientError(t *testing.T) {
727 transientError := volumetypes.NewTransientOperationFailure("")
728 plug, tmpDir := newTestPlugin(t, nil)
729 defer os.RemoveAll(tmpDir)
730
731 csiMapper, spec, pv, err := prepareBlockMapperTest(plug, "test-pv", t)
732 if err != nil {
733 t.Fatalf("Failed to make a new Mapper: %v", err)
734 }
735
736 pvName := pv.GetName()
737 nodeName := string(plug.host.GetNodeName())
738
739 csiMapper.csiClient = setupClient(t, true)
740
741 attachID := getAttachmentName(csiMapper.volumeID, string(csiMapper.driverName), string(nodeName))
742 attachment := makeTestAttachment(attachID, nodeName, pvName)
743 attachment.Status.Attached = true
744 _, err = csiMapper.k8s.StorageV1().VolumeAttachments().Create(context.TODO(), attachment, metav1.CreateOptions{})
745 if err != nil {
746 t.Fatalf("failed to setup VolumeAttachment: %v", err)
747 }
748 t.Log("created attachment ", attachID)
749
750 stagingPath, err := csiMapper.SetUpDevice()
751 if err != nil {
752 t.Fatalf("mapper failed to SetupDevice: %v", err)
753 }
754
755 svols := csiMapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodeStagedVolumes()
756 svol, ok := svols[csiMapper.volumeID]
757 if !ok {
758 t.Error("csi server may not have received NodeStageVolume call")
759 }
760 if svol.Path != stagingPath {
761 t.Errorf("csi server expected device path %s, got %s", stagingPath, svol.Path)
762 }
763
764 path, err := csiMapper.MapPodDevice()
765 if err != nil {
766 t.Fatalf("mapper failed to GetGlobalMapPath: %v", err)
767 }
768 pvols := csiMapper.csiClient.(*fakeCsiDriverClient).nodeClient.GetNodePublishedVolumes()
769 pvol, ok := pvols[csiMapper.volumeID]
770 if !ok {
771 t.Error("csi server may not have received NodePublishVolume call")
772 }
773 publishPath := csiMapper.getPublishPath()
774 if pvol.Path != publishPath {
775 t.Errorf("csi server expected path %s, got %s", publishPath, pvol.Path)
776 }
777 if path != publishPath {
778 t.Errorf("csi server expected path %s, but MapPodDevice returned %s", publishPath, path)
779 }
780
781 unmapper, err := plug.NewBlockVolumeUnmapper(pv.ObjectMeta.Name, testPodUID)
782 if err != nil {
783 t.Fatalf("failed to make a new Unmapper: %v", err)
784 }
785
786 csiUnmapper := unmapper.(*csiBlockMapper)
787 csiUnmapper.csiClient = csiMapper.csiClient
788
789 _, err = csiUnmapper.GetGlobalMapPath(spec)
790 if err != nil {
791 t.Fatalf("unmapper failed to GetGlobalMapPath: %v", err)
792 }
793
794
795
796 csiUnmapper.csiClient = nil
797 csiUnmapper.csiClientGetter.csiClient = nil
798
799 csiUnmapper.csiClientGetter.driverName = "unknown-driver"
800
801 err = csiUnmapper.UnmapPodDevice()
802 if err == nil {
803 t.Errorf("test should fail, but no error occurred")
804 } else if reflect.TypeOf(transientError) != reflect.TypeOf(err) {
805 t.Fatalf("expected exitError type: %v got: %v (%v)", reflect.TypeOf(transientError), reflect.TypeOf(err), err)
806 }
807 }
808
View as plain text