1
16
17 package testing
18
19 import (
20 "fmt"
21 "os"
22 "path/filepath"
23 goruntime "runtime"
24 "strings"
25 "sync"
26 "testing"
27 "time"
28
29 "k8s.io/klog/v2"
30
31 "k8s.io/apimachinery/pkg/util/sets"
32 "k8s.io/utils/exec"
33 testingexec "k8s.io/utils/exec/testing"
34 utilstrings "k8s.io/utils/strings"
35
36 v1 "k8s.io/api/core/v1"
37 "k8s.io/apimachinery/pkg/api/resource"
38 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
39 "k8s.io/apimachinery/pkg/types"
40 "k8s.io/apimachinery/pkg/util/uuid"
41 utiltesting "k8s.io/client-go/util/testing"
42 "k8s.io/kubernetes/pkg/volume"
43 "k8s.io/kubernetes/pkg/volume/util"
44 "k8s.io/kubernetes/pkg/volume/util/recyclerclient"
45 volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
46 "k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
47 )
48
49 const (
50
51
52 ExpectProvisionFailureKey = "expect-provision-failure"
53
54
55 UncertainAttachNode = "uncertain-attach-node"
56
57 FailDetachNode = "fail-detach-node"
58
59
60 TimeoutAttachNode = "timeout-attach-node"
61
62 MultiAttachNode = "multi-attach-node"
63
64 TimeoutOnSetupVolumeName = "timeout-setup-volume"
65
66 FailOnSetupVolumeName = "fail-setup-volume"
67
68 TimeoutAndFailOnSetupVolumeName = "timeout-and-fail-setup-volume"
69
70 SuccessAndTimeoutSetupVolumeName = "success-and-timeout-setup-volume-name"
71
72 SuccessAndFailOnSetupVolumeName = "success-and-failed-setup-device-name"
73
74
75 TimeoutOnMountDeviceVolumeName = "timeout-mount-device-volume"
76
77 TimeoutAndFailOnMountDeviceVolumeName = "timeout-and-fail-mount-device-name"
78
79 FailMountDeviceVolumeName = "fail-mount-device-volume-name"
80
81 SuccessAndTimeoutDeviceName = "success-and-timeout-device-name"
82
83 SuccessAndFailOnMountDeviceName = "success-and-failed-mount-device-name"
84
85
86 FailWithInUseVolumeName = "fail-expansion-in-use"
87 FailWithUnSupportedVolumeName = "fail-expansion-unsupported"
88
89 FailVolumeExpansion = "fail-expansion-test"
90
91 AlwaysFailNodeExpansion = "always-fail-node-expansion"
92
93 deviceNotMounted = "deviceNotMounted"
94 deviceMountUncertain = "deviceMountUncertain"
95 deviceMounted = "deviceMounted"
96
97 volumeNotMounted = "volumeNotMounted"
98 volumeMountUncertain = "volumeMountUncertain"
99 volumeMounted = "volumeMounted"
100
101 FailNewMounter = "fail-new-mounter"
102 )
103
104
105
106 type CommandScript struct {
107
108 Cmd string
109
110 Args []string
111
112 Output string
113
114
115 ReturnCode int
116 }
117
118
119
120
121
122
123
124
125
126 func ScriptCommands(fe *testingexec.FakeExec, scripts []CommandScript) {
127 fe.DisableScripts = false
128 for _, script := range scripts {
129 fakeCmd := &testingexec.FakeCmd{}
130 cmdAction := makeFakeCmd(fakeCmd, script.Cmd, script.Args...)
131 outputAction := makeFakeOutput(script.Output, script.ReturnCode)
132 fakeCmd.CombinedOutputScript = append(fakeCmd.CombinedOutputScript, outputAction)
133 fe.CommandScript = append(fe.CommandScript, cmdAction)
134 }
135 }
136
137 func makeFakeCmd(fakeCmd *testingexec.FakeCmd, cmd string, args ...string) testingexec.FakeCommandAction {
138 fc := fakeCmd
139 c := cmd
140 a := args
141 return func(cmd string, args ...string) exec.Cmd {
142 command := testingexec.InitFakeCmd(fc, c, a...)
143 return command
144 }
145 }
146
147 func makeFakeOutput(output string, rc int) testingexec.FakeAction {
148 o := output
149 var e error
150 if rc != 0 {
151 e = testingexec.FakeExitError{Status: rc}
152 }
153 return func() ([]byte, []byte, error) {
154 return []byte(o), nil, e
155 }
156 }
157
158 func ProbeVolumePlugins(config volume.VolumeConfig) []volume.VolumePlugin {
159 if _, ok := config.OtherAttributes["fake-property"]; ok {
160 return []volume.VolumePlugin{
161 &FakeVolumePlugin{
162 PluginName: "fake-plugin",
163 Host: nil,
164
165 },
166 }
167 }
168 return []volume.VolumePlugin{&FakeVolumePlugin{PluginName: "fake-plugin"}}
169 }
170
171
172
173
174
175
176 type FakeVolumePlugin struct {
177 sync.RWMutex
178 PluginName string
179 Host volume.VolumeHost
180 Config volume.VolumeConfig
181 LastProvisionerOptions volume.VolumeOptions
182 NewAttacherCallCount int
183 NewDetacherCallCount int
184 NodeExpandCallCount int
185 VolumeLimits map[string]int64
186 VolumeLimitsError error
187 LimitKey string
188 ProvisionDelaySeconds int
189 SupportsRemount bool
190 SupportsSELinux bool
191 DisableNodeExpansion bool
192 CanSupportFn func(*volume.Spec) bool
193
194
195 NonAttachable bool
196
197
198 WaitForAttachHook func(spec *volume.Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error)
199 UnmountDeviceHook func(globalMountPath string) error
200
201 Mounters []*FakeVolume
202 Unmounters []*FakeVolume
203 Attachers []*FakeVolume
204 Detachers []*FakeVolume
205 BlockVolumeMappers []*FakeVolume
206 BlockVolumeUnmappers []*FakeVolume
207 }
208
209 var _ volume.VolumePlugin = &FakeVolumePlugin{}
210 var _ volume.BlockVolumePlugin = &FakeVolumePlugin{}
211 var _ volume.RecyclableVolumePlugin = &FakeVolumePlugin{}
212 var _ volume.DeletableVolumePlugin = &FakeVolumePlugin{}
213 var _ volume.ProvisionableVolumePlugin = &FakeVolumePlugin{}
214 var _ volume.AttachableVolumePlugin = &FakeVolumePlugin{}
215 var _ volume.VolumePluginWithAttachLimits = &FakeVolumePlugin{}
216 var _ volume.DeviceMountableVolumePlugin = &FakeVolumePlugin{}
217 var _ volume.NodeExpandableVolumePlugin = &FakeVolumePlugin{}
218
219 func (plugin *FakeVolumePlugin) getFakeVolume(list *[]*FakeVolume) *FakeVolume {
220 if list != nil {
221 volumeList := *list
222 if len(volumeList) > 0 {
223 volume := volumeList[0]
224 volume.Lock()
225 defer volume.Unlock()
226 volume.WaitForAttachHook = plugin.WaitForAttachHook
227 volume.UnmountDeviceHook = plugin.UnmountDeviceHook
228 return volume
229 }
230 }
231 volume := &FakeVolume{
232 WaitForAttachHook: plugin.WaitForAttachHook,
233 UnmountDeviceHook: plugin.UnmountDeviceHook,
234 }
235 volume.VolumesAttached = make(map[string]sets.String)
236 volume.DeviceMountState = make(map[string]string)
237 volume.VolumeMountState = make(map[string]string)
238 if list != nil {
239 *list = append(*list, volume)
240 }
241 return volume
242 }
243
244 func (plugin *FakeVolumePlugin) Init(host volume.VolumeHost) error {
245 plugin.Lock()
246 defer plugin.Unlock()
247 plugin.Host = host
248 return nil
249 }
250
251 func (plugin *FakeVolumePlugin) GetPluginName() string {
252 plugin.RLock()
253 defer plugin.RUnlock()
254 return plugin.PluginName
255 }
256
257 func (plugin *FakeVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error) {
258 var volumeName string
259 if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
260 volumeName = spec.Volume.GCEPersistentDisk.PDName
261 } else if spec.Volume != nil && spec.Volume.RBD != nil {
262 volumeName = spec.Volume.RBD.RBDImage
263 } else if spec.PersistentVolume != nil &&
264 spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
265 volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
266 } else if spec.PersistentVolume != nil &&
267 spec.PersistentVolume.Spec.RBD != nil {
268 volumeName = spec.PersistentVolume.Spec.RBD.RBDImage
269 } else if spec.Volume != nil && spec.Volume.CSI != nil {
270 volumeName = spec.Volume.CSI.Driver
271 }
272 if volumeName == "" {
273 volumeName = spec.Name()
274 }
275 return volumeName, nil
276 }
277
278 func (plugin *FakeVolumePlugin) CanSupport(spec *volume.Spec) bool {
279 if plugin.CanSupportFn != nil {
280 return plugin.CanSupportFn(spec)
281 }
282
283 return true
284 }
285
286 func (plugin *FakeVolumePlugin) RequiresRemount(spec *volume.Spec) bool {
287 return plugin.SupportsRemount
288 }
289
290 func (plugin *FakeVolumePlugin) SupportsMountOption() bool {
291 return true
292 }
293
294 func (plugin *FakeVolumePlugin) SupportsBulkVolumeVerification() bool {
295 return false
296 }
297
298 func (plugin *FakeVolumePlugin) SupportsSELinuxContextMount(spec *volume.Spec) (bool, error) {
299 return plugin.SupportsSELinux, nil
300 }
301
302 func (plugin *FakeVolumePlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) {
303 plugin.Lock()
304 defer plugin.Unlock()
305 if spec.Name() == FailNewMounter {
306 return nil, fmt.Errorf("AlwaysFailNewMounter")
307 }
308 fakeVolume := plugin.getFakeVolume(&plugin.Mounters)
309 fakeVolume.Lock()
310 defer fakeVolume.Unlock()
311 fakeVolume.PodUID = pod.UID
312 fakeVolume.VolName = spec.Name()
313 fakeVolume.Plugin = plugin
314 fakeVolume.MetricsNil = volume.MetricsNil{}
315 return fakeVolume, nil
316 }
317
318 func (plugin *FakeVolumePlugin) GetMounters() (Mounters []*FakeVolume) {
319 plugin.RLock()
320 defer plugin.RUnlock()
321 return plugin.Mounters
322 }
323
324 func (plugin *FakeVolumePlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) {
325 plugin.Lock()
326 defer plugin.Unlock()
327 fakeVolume := plugin.getFakeVolume(&plugin.Unmounters)
328 fakeVolume.Lock()
329 defer fakeVolume.Unlock()
330 fakeVolume.PodUID = podUID
331 fakeVolume.VolName = volName
332 fakeVolume.Plugin = plugin
333 fakeVolume.MetricsNil = volume.MetricsNil{}
334 return fakeVolume, nil
335 }
336
337 func (plugin *FakeVolumePlugin) GetUnmounters() (Unmounters []*FakeVolume) {
338 plugin.RLock()
339 defer plugin.RUnlock()
340 return plugin.Unmounters
341 }
342
343
344 func (plugin *FakeVolumePlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.BlockVolumeMapper, error) {
345 plugin.Lock()
346 defer plugin.Unlock()
347 volume := plugin.getFakeVolume(&plugin.BlockVolumeMappers)
348 volume.Lock()
349 defer volume.Unlock()
350 if pod != nil {
351 volume.PodUID = pod.UID
352 }
353 volume.VolName = spec.Name()
354 volume.Plugin = plugin
355 return volume, nil
356 }
357
358
359 func (plugin *FakeVolumePlugin) GetBlockVolumeMapper() (BlockVolumeMappers []*FakeVolume) {
360 plugin.RLock()
361 defer plugin.RUnlock()
362 return plugin.BlockVolumeMappers
363 }
364
365
366 func (plugin *FakeVolumePlugin) NewBlockVolumeUnmapper(volName string, podUID types.UID) (volume.BlockVolumeUnmapper, error) {
367 plugin.Lock()
368 defer plugin.Unlock()
369 volume := plugin.getFakeVolume(&plugin.BlockVolumeUnmappers)
370 volume.Lock()
371 defer volume.Unlock()
372 volume.PodUID = podUID
373 volume.VolName = volName
374 volume.Plugin = plugin
375 return volume, nil
376 }
377
378
379 func (plugin *FakeVolumePlugin) GetBlockVolumeUnmapper() (BlockVolumeUnmappers []*FakeVolume) {
380 plugin.RLock()
381 defer plugin.RUnlock()
382 return plugin.BlockVolumeUnmappers
383 }
384
385 func (plugin *FakeVolumePlugin) NewAttacher() (volume.Attacher, error) {
386 plugin.Lock()
387 defer plugin.Unlock()
388 plugin.NewAttacherCallCount = plugin.NewAttacherCallCount + 1
389 return plugin.getFakeVolume(&plugin.Attachers), nil
390 }
391
392 func (plugin *FakeVolumePlugin) NewDeviceMounter() (volume.DeviceMounter, error) {
393 return plugin.NewAttacher()
394 }
395
396 func (plugin *FakeVolumePlugin) GetAttachers() (Attachers []*FakeVolume) {
397 plugin.RLock()
398 defer plugin.RUnlock()
399 return plugin.Attachers
400 }
401
402 func (plugin *FakeVolumePlugin) GetNewAttacherCallCount() int {
403 plugin.RLock()
404 defer plugin.RUnlock()
405 return plugin.NewAttacherCallCount
406 }
407
408 func (plugin *FakeVolumePlugin) NewDetacher() (volume.Detacher, error) {
409 plugin.Lock()
410 defer plugin.Unlock()
411 plugin.NewDetacherCallCount = plugin.NewDetacherCallCount + 1
412 detacher := plugin.getFakeVolume(&plugin.Detachers)
413 attacherList := plugin.Attachers
414 if len(attacherList) > 0 {
415 detacherList := plugin.Detachers
416 if len(detacherList) > 0 {
417 detacherList[0].VolumesAttached = attacherList[0].VolumesAttached
418 }
419
420 }
421 return detacher, nil
422 }
423
424 func (plugin *FakeVolumePlugin) NewDeviceUnmounter() (volume.DeviceUnmounter, error) {
425 return plugin.NewDetacher()
426 }
427
428 func (plugin *FakeVolumePlugin) GetDetachers() (Detachers []*FakeVolume) {
429 plugin.RLock()
430 defer plugin.RUnlock()
431 return plugin.Detachers
432 }
433
434 func (plugin *FakeVolumePlugin) GetNewDetacherCallCount() int {
435 plugin.RLock()
436 defer plugin.RUnlock()
437 return plugin.NewDetacherCallCount
438 }
439
440 func (plugin *FakeVolumePlugin) CanAttach(spec *volume.Spec) (bool, error) {
441 return !plugin.NonAttachable, nil
442 }
443
444 func (plugin *FakeVolumePlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
445 return true, nil
446 }
447
448 func (plugin *FakeVolumePlugin) Recycle(pvName string, spec *volume.Spec, eventRecorder recyclerclient.RecycleEventRecorder) error {
449 return nil
450 }
451
452 func (plugin *FakeVolumePlugin) NewDeleter(logger klog.Logger, spec *volume.Spec) (volume.Deleter, error) {
453 return &FakeDeleter{"/attributesTransferredFromSpec", volume.MetricsNil{}}, nil
454 }
455
456 func (plugin *FakeVolumePlugin) NewProvisioner(logger klog.Logger, options volume.VolumeOptions) (volume.Provisioner, error) {
457 plugin.Lock()
458 defer plugin.Unlock()
459 plugin.LastProvisionerOptions = options
460 return &FakeProvisioner{options, plugin.Host, plugin.ProvisionDelaySeconds}, nil
461 }
462
463 func (plugin *FakeVolumePlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
464 return []v1.PersistentVolumeAccessMode{}
465 }
466
467 func (plugin *FakeVolumePlugin) ConstructVolumeSpec(volumeName, mountPath string) (volume.ReconstructedVolume, error) {
468 return volume.ReconstructedVolume{
469 Spec: &volume.Spec{
470 Volume: &v1.Volume{
471 Name: volumeName,
472 },
473 },
474 }, nil
475 }
476
477
478 func (plugin *FakeVolumePlugin) ConstructBlockVolumeSpec(podUID types.UID, volumeName, mountPath string) (*volume.Spec, error) {
479 return &volume.Spec{
480 Volume: &v1.Volume{
481 Name: volumeName,
482 },
483 }, nil
484 }
485
486 func (plugin *FakeVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) {
487 return []string{}, nil
488 }
489
490
491 func (plugin *FakeVolumePlugin) ExpandVolumeDevice(spec *volume.Spec, newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error) {
492 return resource.Quantity{}, nil
493 }
494
495 func (plugin *FakeVolumePlugin) RequiresFSResize() bool {
496 return !plugin.DisableNodeExpansion
497 }
498
499 func (plugin *FakeVolumePlugin) NodeExpand(resizeOptions volume.NodeResizeOptions) (bool, error) {
500 plugin.NodeExpandCallCount++
501 if resizeOptions.VolumeSpec.Name() == FailWithInUseVolumeName {
502 return false, volumetypes.NewFailedPreconditionError("volume-in-use")
503 }
504 if resizeOptions.VolumeSpec.Name() == FailWithUnSupportedVolumeName {
505 return false, volumetypes.NewOperationNotSupportedError("volume-unsupported")
506 }
507
508 if resizeOptions.VolumeSpec.Name() == AlwaysFailNodeExpansion {
509 return false, fmt.Errorf("test failure: NodeExpand")
510 }
511
512 if resizeOptions.VolumeSpec.Name() == FailVolumeExpansion {
513 return false, fmt.Errorf("fail volume expansion for volume: %s", FailVolumeExpansion)
514 }
515 return true, nil
516 }
517
518 func (plugin *FakeVolumePlugin) GetVolumeLimits() (map[string]int64, error) {
519 return plugin.VolumeLimits, plugin.VolumeLimitsError
520 }
521
522 func (plugin *FakeVolumePlugin) VolumeLimitKey(spec *volume.Spec) string {
523 return plugin.LimitKey
524 }
525
526
527
528
529 type FakeBasicVolumePlugin struct {
530 Plugin FakeVolumePlugin
531 }
532
533 func (f *FakeBasicVolumePlugin) GetPluginName() string {
534 return f.Plugin.GetPluginName()
535 }
536
537 func (f *FakeBasicVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error) {
538 return f.Plugin.GetVolumeName(spec)
539 }
540
541
542
543
544 func (f *FakeBasicVolumePlugin) CanSupport(spec *volume.Spec) bool {
545 return strings.HasPrefix(spec.Name(), f.GetPluginName())
546 }
547
548 func (f *FakeBasicVolumePlugin) ConstructVolumeSpec(ame, mountPath string) (volume.ReconstructedVolume, error) {
549 return f.Plugin.ConstructVolumeSpec(ame, mountPath)
550 }
551
552 func (f *FakeBasicVolumePlugin) Init(ost volume.VolumeHost) error {
553 return f.Plugin.Init(ost)
554 }
555
556 func (f *FakeBasicVolumePlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) {
557 return f.Plugin.NewMounter(spec, pod, opts)
558 }
559
560 func (f *FakeBasicVolumePlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) {
561 return f.Plugin.NewUnmounter(volName, podUID)
562 }
563
564 func (f *FakeBasicVolumePlugin) RequiresRemount(spec *volume.Spec) bool {
565 return f.Plugin.RequiresRemount(spec)
566 }
567
568 func (f *FakeBasicVolumePlugin) SupportsBulkVolumeVerification() bool {
569 return f.Plugin.SupportsBulkVolumeVerification()
570 }
571
572 func (f *FakeBasicVolumePlugin) SupportsSELinuxContextMount(spec *volume.Spec) (bool, error) {
573 return f.Plugin.SupportsSELinuxContextMount(spec)
574 }
575
576 func (f *FakeBasicVolumePlugin) SupportsMountOption() bool {
577 return f.Plugin.SupportsMountOption()
578 }
579
580 var _ volume.VolumePlugin = &FakeBasicVolumePlugin{}
581
582
583 type FakeDeviceMountableVolumePlugin struct {
584 FakeBasicVolumePlugin
585 }
586
587 func (f *FakeDeviceMountableVolumePlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
588 return true, nil
589 }
590
591 func (f *FakeDeviceMountableVolumePlugin) NewDeviceMounter() (volume.DeviceMounter, error) {
592 return f.Plugin.NewDeviceMounter()
593 }
594
595 func (f *FakeDeviceMountableVolumePlugin) NewDeviceUnmounter() (volume.DeviceUnmounter, error) {
596 return f.Plugin.NewDeviceUnmounter()
597 }
598
599 func (f *FakeDeviceMountableVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) {
600 return f.Plugin.GetDeviceMountRefs(deviceMountPath)
601 }
602
603 var _ volume.VolumePlugin = &FakeDeviceMountableVolumePlugin{}
604 var _ volume.DeviceMountableVolumePlugin = &FakeDeviceMountableVolumePlugin{}
605
606
607 type FakeAttachableVolumePlugin struct {
608 FakeDeviceMountableVolumePlugin
609 }
610
611 func (f *FakeAttachableVolumePlugin) NewAttacher() (volume.Attacher, error) {
612 return f.Plugin.NewAttacher()
613 }
614
615 func (f *FakeAttachableVolumePlugin) NewDetacher() (volume.Detacher, error) {
616 return f.Plugin.NewDetacher()
617 }
618
619 func (f *FakeAttachableVolumePlugin) CanAttach(spec *volume.Spec) (bool, error) {
620 return true, nil
621 }
622
623 var _ volume.VolumePlugin = &FakeAttachableVolumePlugin{}
624 var _ volume.AttachableVolumePlugin = &FakeAttachableVolumePlugin{}
625
626 type FakeFileVolumePlugin struct {
627 }
628
629 func (plugin *FakeFileVolumePlugin) Init(host volume.VolumeHost) error {
630 return nil
631 }
632
633 func (plugin *FakeFileVolumePlugin) GetPluginName() string {
634 return "fake-file-plugin"
635 }
636
637 func (plugin *FakeFileVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error) {
638 return "", nil
639 }
640
641 func (plugin *FakeFileVolumePlugin) CanSupport(spec *volume.Spec) bool {
642 return true
643 }
644
645 func (plugin *FakeFileVolumePlugin) RequiresRemount(spec *volume.Spec) bool {
646 return false
647 }
648
649 func (plugin *FakeFileVolumePlugin) SupportsMountOption() bool {
650 return false
651 }
652
653 func (plugin *FakeFileVolumePlugin) SupportsBulkVolumeVerification() bool {
654 return false
655 }
656
657 func (plugin *FakeFileVolumePlugin) SupportsSELinuxContextMount(spec *volume.Spec) (bool, error) {
658 return false, nil
659 }
660
661 func (plugin *FakeFileVolumePlugin) NewMounter(spec *volume.Spec, podRef *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) {
662 return nil, nil
663 }
664
665 func (plugin *FakeFileVolumePlugin) NewUnmounter(name string, podUID types.UID) (volume.Unmounter, error) {
666 return nil, nil
667 }
668
669 func (plugin *FakeFileVolumePlugin) ConstructVolumeSpec(volumeName, mountPath string) (volume.ReconstructedVolume, error) {
670 return volume.ReconstructedVolume{}, nil
671 }
672
673 func NewFakeFileVolumePlugin() []volume.VolumePlugin {
674 return []volume.VolumePlugin{&FakeFileVolumePlugin{}}
675 }
676
677 type FakeVolume struct {
678 sync.RWMutex
679 PodUID types.UID
680 VolName string
681 Plugin *FakeVolumePlugin
682 volume.MetricsNil
683 VolumesAttached map[string]sets.String
684 DeviceMountState map[string]string
685 VolumeMountState map[string]string
686
687
688 WaitForAttachHook func(spec *volume.Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error)
689 UnmountDeviceHook func(globalMountPath string) error
690
691 SetUpCallCount int
692 TearDownCallCount int
693 AttachCallCount int
694 DetachCallCount int
695 WaitForAttachCallCount int
696 MountDeviceCallCount int
697 UnmountDeviceCallCount int
698 GetDeviceMountPathCallCount int
699 SetUpDeviceCallCount int
700 TearDownDeviceCallCount int
701 MapPodDeviceCallCount int
702 UnmapPodDeviceCallCount int
703 GlobalMapPathCallCount int
704 PodDeviceMapPathCallCount int
705 }
706
707 func getUniqueVolumeName(spec *volume.Spec) (string, error) {
708 var volumeName string
709 if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
710 volumeName = spec.Volume.GCEPersistentDisk.PDName
711 } else if spec.Volume != nil && spec.Volume.RBD != nil {
712 volumeName = spec.Volume.RBD.RBDImage
713 } else if spec.PersistentVolume != nil &&
714 spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
715 volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
716 } else if spec.PersistentVolume != nil &&
717 spec.PersistentVolume.Spec.RBD != nil {
718 volumeName = spec.PersistentVolume.Spec.RBD.RBDImage
719 }
720 if volumeName == "" {
721 volumeName = spec.Name()
722 }
723 return volumeName, nil
724 }
725
726 func (_ *FakeVolume) GetAttributes() volume.Attributes {
727 return volume.Attributes{
728 ReadOnly: false,
729 Managed: true,
730 SELinuxRelabel: true,
731 }
732 }
733
734 func (fv *FakeVolume) SetUp(mounterArgs volume.MounterArgs) error {
735 fv.Lock()
736 defer fv.Unlock()
737 err := fv.setupInternal(mounterArgs)
738 fv.SetUpCallCount++
739 return err
740 }
741
742 func (fv *FakeVolume) setupInternal(mounterArgs volume.MounterArgs) error {
743 if fv.VolName == TimeoutOnSetupVolumeName {
744 fv.VolumeMountState[fv.VolName] = volumeMountUncertain
745 return volumetypes.NewUncertainProgressError("time out on setup")
746 }
747
748 if fv.VolName == FailOnSetupVolumeName {
749 fv.VolumeMountState[fv.VolName] = volumeNotMounted
750 return fmt.Errorf("mounting volume failed")
751 }
752
753 if fv.VolName == TimeoutAndFailOnSetupVolumeName {
754 _, ok := fv.VolumeMountState[fv.VolName]
755 if !ok {
756 fv.VolumeMountState[fv.VolName] = volumeMountUncertain
757 return volumetypes.NewUncertainProgressError("time out on setup")
758 }
759 fv.VolumeMountState[fv.VolName] = volumeNotMounted
760 return fmt.Errorf("mounting volume failed")
761
762 }
763
764 if fv.VolName == SuccessAndFailOnSetupVolumeName {
765 _, ok := fv.VolumeMountState[fv.VolName]
766 if ok {
767 fv.VolumeMountState[fv.VolName] = volumeNotMounted
768 return fmt.Errorf("mounting volume failed")
769 }
770 }
771
772 if fv.VolName == SuccessAndTimeoutSetupVolumeName {
773 _, ok := fv.VolumeMountState[fv.VolName]
774 if ok {
775 fv.VolumeMountState[fv.VolName] = volumeMountUncertain
776 return volumetypes.NewUncertainProgressError("time out on setup")
777 }
778 }
779
780 fv.VolumeMountState[fv.VolName] = volumeNotMounted
781 return fv.SetUpAt(fv.getPath(), mounterArgs)
782 }
783
784 func (fv *FakeVolume) GetSetUpCallCount() int {
785 fv.RLock()
786 defer fv.RUnlock()
787 return fv.SetUpCallCount
788 }
789
790 func (fv *FakeVolume) SetUpAt(dir string, mounterArgs volume.MounterArgs) error {
791 return os.MkdirAll(dir, 0750)
792 }
793
794 func (fv *FakeVolume) GetPath() string {
795 fv.RLock()
796 defer fv.RUnlock()
797 return fv.getPath()
798 }
799
800 func (fv *FakeVolume) getPath() string {
801 return filepath.Join(fv.Plugin.Host.GetPodVolumeDir(fv.PodUID, utilstrings.EscapeQualifiedName(fv.Plugin.PluginName), fv.VolName))
802 }
803
804 func (fv *FakeVolume) TearDown() error {
805 fv.Lock()
806 defer fv.Unlock()
807 fv.TearDownCallCount++
808 return fv.TearDownAt(fv.getPath())
809 }
810
811 func (fv *FakeVolume) GetTearDownCallCount() int {
812 fv.RLock()
813 defer fv.RUnlock()
814 return fv.TearDownCallCount
815 }
816
817 func (fv *FakeVolume) TearDownAt(dir string) error {
818 return os.RemoveAll(dir)
819 }
820
821
822 func (fv *FakeVolume) SetUpDevice() (string, error) {
823 fv.Lock()
824 defer fv.Unlock()
825 if fv.VolName == TimeoutOnMountDeviceVolumeName {
826 fv.DeviceMountState[fv.VolName] = deviceMountUncertain
827 return "", volumetypes.NewUncertainProgressError("mount failed")
828 }
829 if fv.VolName == FailMountDeviceVolumeName {
830 fv.DeviceMountState[fv.VolName] = deviceNotMounted
831 return "", fmt.Errorf("error mapping disk: %s", fv.VolName)
832 }
833
834 if fv.VolName == TimeoutAndFailOnMountDeviceVolumeName {
835 _, ok := fv.DeviceMountState[fv.VolName]
836 if !ok {
837 fv.DeviceMountState[fv.VolName] = deviceMountUncertain
838 return "", volumetypes.NewUncertainProgressError("timed out mounting error")
839 }
840 fv.DeviceMountState[fv.VolName] = deviceNotMounted
841 return "", fmt.Errorf("error mapping disk: %s", fv.VolName)
842 }
843
844 if fv.VolName == SuccessAndTimeoutDeviceName {
845 _, ok := fv.DeviceMountState[fv.VolName]
846 if ok {
847 fv.DeviceMountState[fv.VolName] = deviceMountUncertain
848 return "", volumetypes.NewUncertainProgressError("error mounting state")
849 }
850 }
851 if fv.VolName == SuccessAndFailOnMountDeviceName {
852 _, ok := fv.DeviceMountState[fv.VolName]
853 if ok {
854 return "", fmt.Errorf("error mapping disk: %s", fv.VolName)
855 }
856 }
857
858 fv.DeviceMountState[fv.VolName] = deviceMounted
859 fv.SetUpDeviceCallCount++
860
861 return "", nil
862 }
863
864 func (fv *FakeVolume) GetStagingPath() string {
865 return filepath.Join(fv.Plugin.Host.GetVolumeDevicePluginDir(utilstrings.EscapeQualifiedName(fv.Plugin.PluginName)), "staging", fv.VolName)
866 }
867
868
869 func (fv *FakeVolume) GetSetUpDeviceCallCount() int {
870 fv.RLock()
871 defer fv.RUnlock()
872 return fv.SetUpDeviceCallCount
873 }
874
875
876 func (fv *FakeVolume) GetGlobalMapPath(spec *volume.Spec) (string, error) {
877 fv.Lock()
878 defer fv.Unlock()
879 fv.GlobalMapPathCallCount++
880 return fv.getGlobalMapPath()
881 }
882
883
884 func (fv *FakeVolume) getGlobalMapPath() (string, error) {
885 return filepath.Join(fv.Plugin.Host.GetVolumeDevicePluginDir(utilstrings.EscapeQualifiedName(fv.Plugin.PluginName)), "pluginDependentPath"), nil
886 }
887
888
889 func (fv *FakeVolume) GetGlobalMapPathCallCount() int {
890 fv.RLock()
891 defer fv.RUnlock()
892 return fv.GlobalMapPathCallCount
893 }
894
895
896 func (fv *FakeVolume) GetPodDeviceMapPath() (string, string) {
897 fv.RLock()
898 defer fv.RUnlock()
899 fv.PodDeviceMapPathCallCount++
900 return fv.getPodDeviceMapPath()
901 }
902
903
904 func (fv *FakeVolume) getPodDeviceMapPath() (string, string) {
905 return filepath.Join(fv.Plugin.Host.GetPodVolumeDeviceDir(fv.PodUID, utilstrings.EscapeQualifiedName(fv.Plugin.PluginName))), fv.VolName
906 }
907
908
909 func (fv *FakeVolume) GetPodDeviceMapPathCallCount() int {
910 fv.RLock()
911 defer fv.RUnlock()
912 return fv.PodDeviceMapPathCallCount
913 }
914
915
916 func (fv *FakeVolume) TearDownDevice(mapPath string, devicePath string) error {
917 fv.Lock()
918 defer fv.Unlock()
919 fv.TearDownDeviceCallCount++
920 return nil
921 }
922
923
924 func (fv *FakeVolume) GetTearDownDeviceCallCount() int {
925 fv.RLock()
926 defer fv.RUnlock()
927 return fv.TearDownDeviceCallCount
928 }
929
930
931 func (fv *FakeVolume) UnmapPodDevice() error {
932 fv.Lock()
933 defer fv.Unlock()
934 fv.UnmapPodDeviceCallCount++
935 return nil
936 }
937
938
939 func (fv *FakeVolume) GetUnmapPodDeviceCallCount() int {
940 fv.RLock()
941 defer fv.RUnlock()
942 return fv.UnmapPodDeviceCallCount
943 }
944
945
946 func (fv *FakeVolume) MapPodDevice() (string, error) {
947 fv.Lock()
948 defer fv.Unlock()
949
950 if fv.VolName == TimeoutOnSetupVolumeName {
951 fv.VolumeMountState[fv.VolName] = volumeMountUncertain
952 return "", volumetypes.NewUncertainProgressError("time out on setup")
953 }
954
955 if fv.VolName == FailOnSetupVolumeName {
956 fv.VolumeMountState[fv.VolName] = volumeNotMounted
957 return "", fmt.Errorf("mounting volume failed")
958 }
959
960 if fv.VolName == TimeoutAndFailOnSetupVolumeName {
961 _, ok := fv.VolumeMountState[fv.VolName]
962 if !ok {
963 fv.VolumeMountState[fv.VolName] = volumeMountUncertain
964 return "", volumetypes.NewUncertainProgressError("time out on setup")
965 }
966 fv.VolumeMountState[fv.VolName] = volumeNotMounted
967 return "", fmt.Errorf("mounting volume failed")
968
969 }
970
971 if fv.VolName == SuccessAndFailOnSetupVolumeName {
972 _, ok := fv.VolumeMountState[fv.VolName]
973 if ok {
974 fv.VolumeMountState[fv.VolName] = volumeNotMounted
975 return "", fmt.Errorf("mounting volume failed")
976 }
977 }
978
979 if fv.VolName == SuccessAndTimeoutSetupVolumeName {
980 _, ok := fv.VolumeMountState[fv.VolName]
981 if ok {
982 fv.VolumeMountState[fv.VolName] = volumeMountUncertain
983 return "", volumetypes.NewUncertainProgressError("time out on setup")
984 }
985 }
986
987 fv.VolumeMountState[fv.VolName] = volumeMounted
988 fv.MapPodDeviceCallCount++
989 return "", nil
990 }
991
992
993 func (fv *FakeVolume) GetMapPodDeviceCallCount() int {
994 fv.RLock()
995 defer fv.RUnlock()
996 return fv.MapPodDeviceCallCount
997 }
998
999 func (fv *FakeVolume) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) {
1000 fv.Lock()
1001 defer fv.Unlock()
1002 fv.AttachCallCount++
1003
1004 volumeName, err := getUniqueVolumeName(spec)
1005 if err != nil {
1006 return "", err
1007 }
1008 volumeNodes, exist := fv.VolumesAttached[volumeName]
1009 if exist {
1010 if nodeName == UncertainAttachNode {
1011 return "/dev/vdb-test", nil
1012 }
1013
1014
1015 if nodeName == TimeoutAttachNode {
1016 return "", fmt.Errorf("timed out to attach volume %q to node %q", volumeName, nodeName)
1017 }
1018 if volumeNodes.Has(string(nodeName)) || volumeNodes.Has(MultiAttachNode) || nodeName == MultiAttachNode {
1019 volumeNodes.Insert(string(nodeName))
1020 return "/dev/vdb-test", nil
1021 }
1022 return "", fmt.Errorf("volume %q trying to attach to node %q is already attached to node %q", volumeName, nodeName, volumeNodes)
1023 }
1024
1025 fv.VolumesAttached[volumeName] = sets.NewString(string(nodeName))
1026 if nodeName == UncertainAttachNode || nodeName == TimeoutAttachNode {
1027 return "", fmt.Errorf("timed out to attach volume %q to node %q", volumeName, nodeName)
1028 }
1029 return "/dev/vdb-test", nil
1030 }
1031
1032 func (fv *FakeVolume) GetAttachCallCount() int {
1033 fv.RLock()
1034 defer fv.RUnlock()
1035 return fv.AttachCallCount
1036 }
1037
1038 func (fv *FakeVolume) WaitForAttach(spec *volume.Spec, devicePath string, pod *v1.Pod, spectimeout time.Duration) (string, error) {
1039 fv.Lock()
1040 defer fv.Unlock()
1041 fv.WaitForAttachCallCount++
1042 if fv.WaitForAttachHook != nil {
1043 return fv.WaitForAttachHook(spec, devicePath, pod, spectimeout)
1044 }
1045 return "/dev/sdb", nil
1046 }
1047
1048 func (fv *FakeVolume) GetWaitForAttachCallCount() int {
1049 fv.RLock()
1050 defer fv.RUnlock()
1051 return fv.WaitForAttachCallCount
1052 }
1053
1054 func (fv *FakeVolume) GetDeviceMountPath(spec *volume.Spec) (string, error) {
1055 fv.Lock()
1056 defer fv.Unlock()
1057 fv.GetDeviceMountPathCallCount++
1058 return "", nil
1059 }
1060
1061 func (fv *FakeVolume) mountDeviceInternal(spec *volume.Spec, devicePath string, deviceMountPath string) error {
1062 fv.Lock()
1063 defer fv.Unlock()
1064 if spec.Name() == TimeoutOnMountDeviceVolumeName {
1065 fv.DeviceMountState[spec.Name()] = deviceMountUncertain
1066 return volumetypes.NewUncertainProgressError("mount failed")
1067 }
1068
1069 if spec.Name() == FailMountDeviceVolumeName {
1070 fv.DeviceMountState[spec.Name()] = deviceNotMounted
1071 return fmt.Errorf("error mounting disk: %s", devicePath)
1072 }
1073
1074 if spec.Name() == TimeoutAndFailOnMountDeviceVolumeName {
1075 _, ok := fv.DeviceMountState[spec.Name()]
1076 if !ok {
1077 fv.DeviceMountState[spec.Name()] = deviceMountUncertain
1078 return volumetypes.NewUncertainProgressError("timed out mounting error")
1079 }
1080 fv.DeviceMountState[spec.Name()] = deviceNotMounted
1081 return fmt.Errorf("error mounting disk: %s", devicePath)
1082 }
1083
1084 if spec.Name() == SuccessAndTimeoutDeviceName {
1085 _, ok := fv.DeviceMountState[spec.Name()]
1086 if ok {
1087 fv.DeviceMountState[spec.Name()] = deviceMountUncertain
1088 return volumetypes.NewUncertainProgressError("error mounting state")
1089 }
1090 }
1091
1092 if spec.Name() == SuccessAndFailOnMountDeviceName {
1093 _, ok := fv.DeviceMountState[spec.Name()]
1094 if ok {
1095 return fmt.Errorf("error mounting disk: %s", devicePath)
1096 }
1097 }
1098 fv.DeviceMountState[spec.Name()] = deviceMounted
1099 fv.MountDeviceCallCount++
1100 return nil
1101 }
1102
1103 func (fv *FakeVolume) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string, _ volume.DeviceMounterArgs) error {
1104 return fv.mountDeviceInternal(spec, devicePath, deviceMountPath)
1105 }
1106
1107 func (fv *FakeVolume) GetMountDeviceCallCount() int {
1108 fv.RLock()
1109 defer fv.RUnlock()
1110 return fv.MountDeviceCallCount
1111 }
1112
1113 func (fv *FakeVolume) GetUnmountDeviceCallCount() int {
1114 fv.RLock()
1115 defer fv.RUnlock()
1116 return fv.UnmountDeviceCallCount
1117 }
1118
1119 func (fv *FakeVolume) Detach(volumeName string, nodeName types.NodeName) error {
1120 fv.Lock()
1121 defer fv.Unlock()
1122
1123 node := string(nodeName)
1124 volumeNodes, exist := fv.VolumesAttached[volumeName]
1125 if !exist || !volumeNodes.Has(node) {
1126 return fmt.Errorf("trying to detach volume %q that is not attached to the node %q", volumeName, node)
1127 }
1128
1129 fv.DetachCallCount++
1130 if nodeName == FailDetachNode {
1131 return fmt.Errorf("fail to detach volume %q to node %q", volumeName, nodeName)
1132 }
1133
1134 volumeNodes.Delete(node)
1135 if volumeNodes.Len() == 0 {
1136 delete(fv.VolumesAttached, volumeName)
1137 }
1138
1139 return nil
1140 }
1141
1142 func (fv *FakeVolume) VolumesAreAttached(spec []*volume.Spec, nodeName types.NodeName) (map[*volume.Spec]bool, error) {
1143 fv.Lock()
1144 defer fv.Unlock()
1145 return nil, nil
1146 }
1147
1148 func (fv *FakeVolume) GetDetachCallCount() int {
1149 fv.RLock()
1150 defer fv.RUnlock()
1151 return fv.DetachCallCount
1152 }
1153
1154 func (fv *FakeVolume) UnmountDevice(globalMountPath string) error {
1155 fv.Lock()
1156 defer fv.Unlock()
1157 fv.UnmountDeviceCallCount++
1158 if fv.UnmountDeviceHook != nil {
1159 return fv.UnmountDeviceHook(globalMountPath)
1160 }
1161 return nil
1162 }
1163
1164 type FakeDeleter struct {
1165 path string
1166 volume.MetricsNil
1167 }
1168
1169 func (fd *FakeDeleter) Delete() error {
1170
1171 return nil
1172 }
1173
1174 func (fd *FakeDeleter) GetPath() string {
1175 return fd.path
1176 }
1177
1178 type FakeProvisioner struct {
1179 Options volume.VolumeOptions
1180 Host volume.VolumeHost
1181 ProvisionDelaySeconds int
1182 }
1183
1184 func (fc *FakeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) {
1185
1186 if fc.Options.Parameters != nil {
1187 if _, ok := fc.Options.Parameters[ExpectProvisionFailureKey]; ok {
1188 return nil, fmt.Errorf("expected error")
1189 }
1190 }
1191 fullpath := fmt.Sprintf("/%s/hostpath_pv/%s", os.TempDir(), uuid.NewUUID())
1192
1193 pv := &v1.PersistentVolume{
1194 ObjectMeta: metav1.ObjectMeta{
1195 Name: fc.Options.PVName,
1196 Annotations: map[string]string{
1197 util.VolumeDynamicallyCreatedByKey: "fakeplugin-provisioner",
1198 },
1199 },
1200 Spec: v1.PersistentVolumeSpec{
1201 PersistentVolumeReclaimPolicy: fc.Options.PersistentVolumeReclaimPolicy,
1202 AccessModes: fc.Options.PVC.Spec.AccessModes,
1203 Capacity: v1.ResourceList{
1204 v1.ResourceName(v1.ResourceStorage): fc.Options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)],
1205 },
1206 PersistentVolumeSource: v1.PersistentVolumeSource{
1207 HostPath: &v1.HostPathVolumeSource{
1208 Path: fullpath,
1209 },
1210 },
1211 },
1212 }
1213
1214 if fc.ProvisionDelaySeconds > 0 {
1215 time.Sleep(time.Duration(fc.ProvisionDelaySeconds) * time.Second)
1216 }
1217
1218 return pv, nil
1219 }
1220
1221 var _ volumepathhandler.BlockVolumePathHandler = &FakeVolumePathHandler{}
1222
1223
1224 func NewBlockVolumePathHandler() volumepathhandler.BlockVolumePathHandler {
1225 return &FakeVolumePathHandler{}
1226 }
1227
1228 type FakeVolumePathHandler struct {
1229 sync.RWMutex
1230 }
1231
1232 func (fv *FakeVolumePathHandler) MapDevice(devicePath string, mapDir string, linkName string, bindMount bool) error {
1233
1234 return nil
1235 }
1236
1237 func (fv *FakeVolumePathHandler) UnmapDevice(mapDir string, linkName string, bindMount bool) error {
1238
1239 return nil
1240 }
1241
1242 func (fv *FakeVolumePathHandler) RemoveMapPath(mapPath string) error {
1243
1244 return nil
1245 }
1246
1247 func (fv *FakeVolumePathHandler) IsSymlinkExist(mapPath string) (bool, error) {
1248
1249 return true, nil
1250 }
1251
1252 func (fv *FakeVolumePathHandler) IsDeviceBindMountExist(mapPath string) (bool, error) {
1253
1254 return true, nil
1255 }
1256
1257 func (fv *FakeVolumePathHandler) GetDeviceBindMountRefs(devPath string, mapPath string) ([]string, error) {
1258
1259 return []string{}, nil
1260 }
1261
1262 func (fv *FakeVolumePathHandler) FindGlobalMapPathUUIDFromPod(pluginDir, mapPath string, podUID types.UID) (string, error) {
1263
1264 return "", nil
1265 }
1266
1267 func (fv *FakeVolumePathHandler) AttachFileDevice(path string) (string, error) {
1268
1269 return "", nil
1270 }
1271
1272 func (fv *FakeVolumePathHandler) DetachFileDevice(path string) error {
1273
1274 return nil
1275 }
1276
1277 func (fv *FakeVolumePathHandler) GetLoopDevice(path string) (string, error) {
1278
1279 return "/dev/loop1", nil
1280 }
1281
1282
1283
1284 func FindEmptyDirectoryUsageOnTmpfs() (*resource.Quantity, error) {
1285
1286 if goruntime.GOOS == "windows" {
1287 used, err := resource.ParseQuantity("0")
1288 return &used, err
1289 }
1290 tmpDir, err := utiltesting.MkTmpdir("metrics_du_test")
1291 if err != nil {
1292 return nil, err
1293 }
1294 defer os.RemoveAll(tmpDir)
1295 out, err := exec.New().Command("nice", "-n", "19", "du", "-x", "-s", "-B", "1", tmpDir).CombinedOutput()
1296 if err != nil {
1297 return nil, fmt.Errorf("failed command 'du' on %s with error %v", tmpDir, err)
1298 }
1299 used, err := resource.ParseQuantity(strings.Fields(string(out))[0])
1300 if err != nil {
1301 return nil, fmt.Errorf("failed to parse 'du' output %s due to error %v", out, err)
1302 }
1303 used.Format = resource.BinarySI
1304 return &used, nil
1305 }
1306
1307
1308
1309
1310 func VerifyAttachCallCount(
1311 expectedAttachCallCount int,
1312 fakeVolumePlugin *FakeVolumePlugin) error {
1313 for _, attacher := range fakeVolumePlugin.GetAttachers() {
1314 actualCallCount := attacher.GetAttachCallCount()
1315 if actualCallCount >= expectedAttachCallCount {
1316 return nil
1317 }
1318 }
1319
1320 return fmt.Errorf(
1321 "No attachers have expected AttachCallCount. Expected: <%v>.",
1322 expectedAttachCallCount)
1323 }
1324
1325
1326
1327 func VerifyZeroAttachCalls(fakeVolumePlugin *FakeVolumePlugin) error {
1328 for _, attacher := range fakeVolumePlugin.GetAttachers() {
1329 actualCallCount := attacher.GetAttachCallCount()
1330 if actualCallCount != 0 {
1331 return fmt.Errorf(
1332 "At least one attacher has non-zero AttachCallCount: <%v>.",
1333 actualCallCount)
1334 }
1335 }
1336
1337 return nil
1338 }
1339
1340
1341
1342
1343 func VerifyWaitForAttachCallCount(
1344 expectedWaitForAttachCallCount int,
1345 fakeVolumePlugin *FakeVolumePlugin) error {
1346 for _, attacher := range fakeVolumePlugin.GetAttachers() {
1347 actualCallCount := attacher.GetWaitForAttachCallCount()
1348 if actualCallCount >= expectedWaitForAttachCallCount {
1349 return nil
1350 }
1351 }
1352
1353 return fmt.Errorf(
1354 "No Attachers have expected WaitForAttachCallCount. Expected: <%v>.",
1355 expectedWaitForAttachCallCount)
1356 }
1357
1358
1359
1360 func VerifyZeroWaitForAttachCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
1361 for _, attacher := range fakeVolumePlugin.GetAttachers() {
1362 actualCallCount := attacher.GetWaitForAttachCallCount()
1363 if actualCallCount != 0 {
1364 return fmt.Errorf(
1365 "At least one attacher has non-zero WaitForAttachCallCount: <%v>.",
1366 actualCallCount)
1367 }
1368 }
1369
1370 return nil
1371 }
1372
1373
1374
1375
1376 func VerifyMountDeviceCallCount(
1377 expectedMountDeviceCallCount int,
1378 fakeVolumePlugin *FakeVolumePlugin) error {
1379 for _, attacher := range fakeVolumePlugin.GetAttachers() {
1380 actualCallCount := attacher.GetMountDeviceCallCount()
1381 if actualCallCount >= expectedMountDeviceCallCount {
1382 return nil
1383 }
1384 }
1385
1386 return fmt.Errorf(
1387 "No Attachers have expected MountDeviceCallCount. Expected: <%v>.",
1388 expectedMountDeviceCallCount)
1389 }
1390
1391 func VerifyUnmountDeviceCallCount(expectedCallCount int, fakeVolumePlugin *FakeVolumePlugin) error {
1392 detachers := fakeVolumePlugin.GetDetachers()
1393 if len(detachers) == 0 && (expectedCallCount == 0) {
1394 return nil
1395 }
1396 actualCallCount := 0
1397 for _, detacher := range detachers {
1398 actualCallCount = detacher.GetUnmountDeviceCallCount()
1399 if expectedCallCount == 0 && actualCallCount == expectedCallCount {
1400 return nil
1401 }
1402
1403 if (expectedCallCount > 0) && (actualCallCount >= expectedCallCount) {
1404 return nil
1405 }
1406 }
1407
1408 return fmt.Errorf(
1409 "Expected DeviceUnmount Call %d, got %d",
1410 expectedCallCount, actualCallCount)
1411 }
1412
1413
1414
1415 func VerifyZeroMountDeviceCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
1416 for _, attacher := range fakeVolumePlugin.GetAttachers() {
1417 actualCallCount := attacher.GetMountDeviceCallCount()
1418 if actualCallCount != 0 {
1419 return fmt.Errorf(
1420 "At least one attacher has non-zero MountDeviceCallCount: <%v>.",
1421 actualCallCount)
1422 }
1423 }
1424
1425 return nil
1426 }
1427
1428
1429
1430
1431 func VerifySetUpCallCount(
1432 expectedSetUpCallCount int,
1433 fakeVolumePlugin *FakeVolumePlugin) error {
1434 for _, mounter := range fakeVolumePlugin.GetMounters() {
1435 actualCallCount := mounter.GetSetUpCallCount()
1436 if actualCallCount >= expectedSetUpCallCount {
1437 return nil
1438 }
1439 }
1440
1441 return fmt.Errorf(
1442 "No Mounters have expected SetUpCallCount. Expected: <%v>.",
1443 expectedSetUpCallCount)
1444 }
1445
1446
1447
1448 func VerifyZeroSetUpCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
1449 for _, mounter := range fakeVolumePlugin.GetMounters() {
1450 actualCallCount := mounter.GetSetUpCallCount()
1451 if actualCallCount != 0 {
1452 return fmt.Errorf(
1453 "At least one mounter has non-zero SetUpCallCount: <%v>.",
1454 actualCallCount)
1455 }
1456 }
1457
1458 return nil
1459 }
1460
1461
1462
1463
1464 func VerifyTearDownCallCount(
1465 expectedTearDownCallCount int,
1466 fakeVolumePlugin *FakeVolumePlugin) error {
1467 unmounters := fakeVolumePlugin.GetUnmounters()
1468 if len(unmounters) == 0 && (expectedTearDownCallCount == 0) {
1469 return nil
1470 }
1471
1472 for _, unmounter := range unmounters {
1473 actualCallCount := unmounter.GetTearDownCallCount()
1474 if expectedTearDownCallCount == 0 && actualCallCount == expectedTearDownCallCount {
1475 return nil
1476 }
1477
1478 if (expectedTearDownCallCount > 0) && (actualCallCount >= expectedTearDownCallCount) {
1479 return nil
1480 }
1481 }
1482
1483 return fmt.Errorf(
1484 "No Unmounters have expected SetUpCallCount. Expected: <%v>.",
1485 expectedTearDownCallCount)
1486 }
1487
1488
1489
1490 func VerifyZeroTearDownCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
1491 for _, mounter := range fakeVolumePlugin.GetMounters() {
1492 actualCallCount := mounter.GetTearDownCallCount()
1493 if actualCallCount != 0 {
1494 return fmt.Errorf(
1495 "At least one mounter has non-zero TearDownCallCount: <%v>.",
1496 actualCallCount)
1497 }
1498 }
1499
1500 return nil
1501 }
1502
1503
1504
1505
1506 func VerifyDetachCallCount(
1507 expectedDetachCallCount int,
1508 fakeVolumePlugin *FakeVolumePlugin) error {
1509 for _, detacher := range fakeVolumePlugin.GetDetachers() {
1510 actualCallCount := detacher.GetDetachCallCount()
1511 if actualCallCount == expectedDetachCallCount {
1512 return nil
1513 }
1514 }
1515
1516 return fmt.Errorf(
1517 "No Detachers have expected DetachCallCount. Expected: <%v>.",
1518 expectedDetachCallCount)
1519 }
1520
1521
1522
1523 func VerifyZeroDetachCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
1524 for _, detacher := range fakeVolumePlugin.GetDetachers() {
1525 actualCallCount := detacher.GetDetachCallCount()
1526 if actualCallCount != 0 {
1527 return fmt.Errorf(
1528 "At least one detacher has non-zero DetachCallCount: <%v>.",
1529 actualCallCount)
1530 }
1531 }
1532
1533 return nil
1534 }
1535
1536
1537
1538
1539 func VerifyTearDownDeviceCallCount(
1540 expectedTearDownDeviceCallCount int,
1541 fakeVolumePlugin *FakeVolumePlugin) error {
1542 for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
1543 actualCallCount := unmapper.GetTearDownDeviceCallCount()
1544 if actualCallCount >= expectedTearDownDeviceCallCount {
1545 return nil
1546 }
1547 }
1548
1549 return fmt.Errorf(
1550 "No Unmapper have expected TearDownDeviceCallCount. Expected: <%v>.",
1551 expectedTearDownDeviceCallCount)
1552 }
1553
1554
1555
1556 func VerifyZeroTearDownDeviceCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
1557 for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
1558 actualCallCount := unmapper.GetTearDownDeviceCallCount()
1559 if actualCallCount != 0 {
1560 return fmt.Errorf(
1561 "At least one unmapper has non-zero TearDownDeviceCallCount: <%v>.",
1562 actualCallCount)
1563 }
1564 }
1565
1566 return nil
1567 }
1568
1569
1570
1571
1572 func VerifyUnmapPodDeviceCallCount(
1573 expectedUnmapPodDeviceCallCount int,
1574 fakeVolumePlugin *FakeVolumePlugin) error {
1575 for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
1576 actualCallCount := unmapper.GetUnmapPodDeviceCallCount()
1577 if actualCallCount >= expectedUnmapPodDeviceCallCount {
1578 return nil
1579 }
1580 }
1581
1582 return fmt.Errorf(
1583 "No Unmapper have expected UnmapPodDeviceCallCount. Expected: <%v>.",
1584 expectedUnmapPodDeviceCallCount)
1585 }
1586
1587
1588
1589 func VerifyZeroUnmapPodDeviceCallCount(fakeVolumePlugin *FakeVolumePlugin) error {
1590 for _, unmapper := range fakeVolumePlugin.GetBlockVolumeUnmapper() {
1591 actualCallCount := unmapper.GetUnmapPodDeviceCallCount()
1592 if actualCallCount != 0 {
1593 return fmt.Errorf(
1594 "At least one unmapper has non-zero UnmapPodDeviceCallCount: <%v>.",
1595 actualCallCount)
1596 }
1597 }
1598
1599 return nil
1600 }
1601
1602
1603
1604
1605 func VerifyGetGlobalMapPathCallCount(
1606 expectedGlobalMapPathCallCount int,
1607 fakeVolumePlugin *FakeVolumePlugin) error {
1608 for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
1609 actualCallCount := mapper.GetGlobalMapPathCallCount()
1610 if actualCallCount == expectedGlobalMapPathCallCount {
1611 return nil
1612 }
1613 }
1614
1615 return fmt.Errorf(
1616 "No Mappers have expected GetGlobalMapPathCallCount. Expected: <%v>.",
1617 expectedGlobalMapPathCallCount)
1618 }
1619
1620
1621
1622
1623 func VerifyGetPodDeviceMapPathCallCount(
1624 expectedPodDeviceMapPathCallCount int,
1625 fakeVolumePlugin *FakeVolumePlugin) error {
1626 for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
1627 actualCallCount := mapper.GetPodDeviceMapPathCallCount()
1628 if actualCallCount == expectedPodDeviceMapPathCallCount {
1629 return nil
1630 }
1631 }
1632
1633 return fmt.Errorf(
1634 "No Mappers have expected GetPodDeviceMapPathCallCount. Expected: <%v>.",
1635 expectedPodDeviceMapPathCallCount)
1636 }
1637
1638
1639
1640
1641 func VerifyGetMapPodDeviceCallCount(
1642 expectedMapPodDeviceCallCount int,
1643 fakeVolumePlugin *FakeVolumePlugin) error {
1644 for _, mapper := range fakeVolumePlugin.GetBlockVolumeMapper() {
1645 actualCallCount := mapper.GetMapPodDeviceCallCount()
1646 if actualCallCount >= expectedMapPodDeviceCallCount {
1647 return nil
1648 }
1649 }
1650
1651 return fmt.Errorf(
1652 "No Mapper have expected MapPodDeviceCallCount. Expected: <%v>.",
1653 expectedMapPodDeviceCallCount)
1654 }
1655
1656
1657
1658 func GetTestVolumePluginMgr(t *testing.T) (*volume.VolumePluginMgr, *FakeVolumePlugin) {
1659 plugins := ProbeVolumePlugins(volume.VolumeConfig{})
1660 v := NewFakeVolumeHost(
1661 t,
1662 "",
1663 nil,
1664 plugins,
1665 )
1666 return v.GetPluginMgr(), plugins[0].(*FakeVolumePlugin)
1667 }
1668
1669 func GetTestKubeletVolumePluginMgr(t *testing.T) (*volume.VolumePluginMgr, *FakeVolumePlugin) {
1670 plugins := ProbeVolumePlugins(volume.VolumeConfig{})
1671 v := NewFakeKubeletVolumeHost(
1672 t,
1673 "",
1674 nil,
1675 plugins,
1676 )
1677 return v.GetPluginMgr(), plugins[0].(*FakeVolumePlugin)
1678 }
1679
1680 func GetTestKubeletVolumePluginMgrWithNode(t *testing.T, node *v1.Node) (*volume.VolumePluginMgr, *FakeVolumePlugin) {
1681 plugins := ProbeVolumePlugins(volume.VolumeConfig{})
1682 v := NewFakeKubeletVolumeHost(
1683 t,
1684 "",
1685 nil,
1686 plugins,
1687 )
1688 v.WithNode(node)
1689
1690 return v.GetPluginMgr(), plugins[0].(*FakeVolumePlugin)
1691 }
1692
1693 func GetTestKubeletVolumePluginMgrWithNodeAndRoot(t *testing.T, node *v1.Node, rootDir string) (*volume.VolumePluginMgr, *FakeVolumePlugin) {
1694 plugins := ProbeVolumePlugins(volume.VolumeConfig{})
1695 v := NewFakeKubeletVolumeHost(
1696 t,
1697 rootDir,
1698 nil,
1699 plugins,
1700 )
1701 v.WithNode(node)
1702
1703 return v.GetPluginMgr(), plugins[0].(*FakeVolumePlugin)
1704 }
1705
1706
1707 func CreateTestPVC(capacity string, accessModes []v1.PersistentVolumeAccessMode) *v1.PersistentVolumeClaim {
1708 claim := v1.PersistentVolumeClaim{
1709 ObjectMeta: metav1.ObjectMeta{
1710 Name: "dummy",
1711 Namespace: "default",
1712 },
1713 Spec: v1.PersistentVolumeClaimSpec{
1714 AccessModes: accessModes,
1715 Resources: v1.VolumeResourceRequirements{
1716 Requests: v1.ResourceList{
1717 v1.ResourceName(v1.ResourceStorage): resource.MustParse(capacity),
1718 },
1719 },
1720 },
1721 }
1722 return &claim
1723 }
1724
1725 func MetricsEqualIgnoreTimestamp(a *volume.Metrics, b *volume.Metrics) bool {
1726 available := a.Available == b.Available
1727 capacity := a.Capacity == b.Capacity
1728 used := a.Used == b.Used
1729 inodes := a.Inodes == b.Inodes
1730 inodesFree := a.InodesFree == b.InodesFree
1731 inodesUsed := a.InodesUsed == b.InodesUsed
1732 return available && capacity && used && inodes && inodesFree && inodesUsed
1733 }
1734
1735 func ContainsAccessMode(modes []v1.PersistentVolumeAccessMode, mode v1.PersistentVolumeAccessMode) bool {
1736 for _, m := range modes {
1737 if m == mode {
1738 return true
1739 }
1740 }
1741 return false
1742 }
1743
View as plain text