k8s.io/kubernetes@v1.29.3/pkg/volume/configmap/configmap_test.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package configmap 18 19 import ( 20 "fmt" 21 "io/ioutil" 22 "os" 23 "path/filepath" 24 "reflect" 25 "strings" 26 "testing" 27 28 "k8s.io/api/core/v1" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "k8s.io/apimachinery/pkg/types" 31 clientset "k8s.io/client-go/kubernetes" 32 "k8s.io/client-go/kubernetes/fake" 33 "k8s.io/kubernetes/pkg/volume" 34 "k8s.io/kubernetes/pkg/volume/emptydir" 35 volumetest "k8s.io/kubernetes/pkg/volume/testing" 36 "k8s.io/kubernetes/pkg/volume/util" 37 ) 38 39 func TestMakePayload(t *testing.T) { 40 caseMappingMode := int32(0400) 41 cases := []struct { 42 name string 43 mappings []v1.KeyToPath 44 configMap *v1.ConfigMap 45 mode int32 46 optional bool 47 payload map[string]util.FileProjection 48 success bool 49 }{ 50 { 51 name: "no overrides", 52 configMap: &v1.ConfigMap{ 53 Data: map[string]string{ 54 "foo": "foo", 55 "bar": "bar", 56 }, 57 }, 58 mode: 0644, 59 payload: map[string]util.FileProjection{ 60 "foo": {Data: []byte("foo"), Mode: 0644}, 61 "bar": {Data: []byte("bar"), Mode: 0644}, 62 }, 63 success: true, 64 }, 65 { 66 name: "no overrides binary data", 67 configMap: &v1.ConfigMap{ 68 BinaryData: map[string][]byte{ 69 "foo": []byte("foo"), 70 "bar": []byte("bar"), 71 }, 72 }, 73 mode: 0644, 74 payload: map[string]util.FileProjection{ 75 "foo": {Data: []byte("foo"), Mode: 0644}, 76 "bar": {Data: []byte("bar"), Mode: 0644}, 77 }, 78 success: true, 79 }, 80 { 81 name: "no overrides mixed data", 82 configMap: &v1.ConfigMap{ 83 BinaryData: map[string][]byte{ 84 "foo": []byte("foo"), 85 }, 86 Data: map[string]string{ 87 "bar": "bar", 88 }, 89 }, 90 mode: 0644, 91 payload: map[string]util.FileProjection{ 92 "foo": {Data: []byte("foo"), Mode: 0644}, 93 "bar": {Data: []byte("bar"), Mode: 0644}, 94 }, 95 success: true, 96 }, 97 { 98 name: "basic 1", 99 mappings: []v1.KeyToPath{ 100 { 101 Key: "foo", 102 Path: "path/to/foo.txt", 103 }, 104 }, 105 configMap: &v1.ConfigMap{ 106 Data: map[string]string{ 107 "foo": "foo", 108 "bar": "bar", 109 }, 110 }, 111 mode: 0644, 112 payload: map[string]util.FileProjection{ 113 "path/to/foo.txt": {Data: []byte("foo"), Mode: 0644}, 114 }, 115 success: true, 116 }, 117 { 118 name: "subdirs", 119 mappings: []v1.KeyToPath{ 120 { 121 Key: "foo", 122 Path: "path/to/1/2/3/foo.txt", 123 }, 124 }, 125 configMap: &v1.ConfigMap{ 126 Data: map[string]string{ 127 "foo": "foo", 128 "bar": "bar", 129 }, 130 }, 131 mode: 0644, 132 payload: map[string]util.FileProjection{ 133 "path/to/1/2/3/foo.txt": {Data: []byte("foo"), Mode: 0644}, 134 }, 135 success: true, 136 }, 137 { 138 name: "subdirs 2", 139 mappings: []v1.KeyToPath{ 140 { 141 Key: "foo", 142 Path: "path/to/1/2/3/foo.txt", 143 }, 144 }, 145 configMap: &v1.ConfigMap{ 146 Data: map[string]string{ 147 "foo": "foo", 148 "bar": "bar", 149 }, 150 }, 151 mode: 0644, 152 payload: map[string]util.FileProjection{ 153 "path/to/1/2/3/foo.txt": {Data: []byte("foo"), Mode: 0644}, 154 }, 155 success: true, 156 }, 157 { 158 name: "subdirs 3", 159 mappings: []v1.KeyToPath{ 160 { 161 Key: "foo", 162 Path: "path/to/1/2/3/foo.txt", 163 }, 164 { 165 Key: "bar", 166 Path: "another/path/to/the/esteemed/bar.bin", 167 }, 168 }, 169 configMap: &v1.ConfigMap{ 170 Data: map[string]string{ 171 "foo": "foo", 172 "bar": "bar", 173 }, 174 }, 175 mode: 0644, 176 payload: map[string]util.FileProjection{ 177 "path/to/1/2/3/foo.txt": {Data: []byte("foo"), Mode: 0644}, 178 "another/path/to/the/esteemed/bar.bin": {Data: []byte("bar"), Mode: 0644}, 179 }, 180 success: true, 181 }, 182 { 183 name: "non existent key", 184 mappings: []v1.KeyToPath{ 185 { 186 Key: "zab", 187 Path: "path/to/foo.txt", 188 }, 189 }, 190 configMap: &v1.ConfigMap{ 191 Data: map[string]string{ 192 "foo": "foo", 193 "bar": "bar", 194 }, 195 }, 196 mode: 0644, 197 success: false, 198 }, 199 { 200 name: "mapping with Mode", 201 mappings: []v1.KeyToPath{ 202 { 203 Key: "foo", 204 Path: "foo.txt", 205 Mode: &caseMappingMode, 206 }, 207 { 208 Key: "bar", 209 Path: "bar.bin", 210 Mode: &caseMappingMode, 211 }, 212 }, 213 configMap: &v1.ConfigMap{ 214 Data: map[string]string{ 215 "foo": "foo", 216 "bar": "bar", 217 }, 218 }, 219 mode: 0644, 220 payload: map[string]util.FileProjection{ 221 "foo.txt": {Data: []byte("foo"), Mode: caseMappingMode}, 222 "bar.bin": {Data: []byte("bar"), Mode: caseMappingMode}, 223 }, 224 success: true, 225 }, 226 { 227 name: "mapping with defaultMode", 228 mappings: []v1.KeyToPath{ 229 { 230 Key: "foo", 231 Path: "foo.txt", 232 }, 233 { 234 Key: "bar", 235 Path: "bar.bin", 236 }, 237 }, 238 configMap: &v1.ConfigMap{ 239 Data: map[string]string{ 240 "foo": "foo", 241 "bar": "bar", 242 }, 243 }, 244 mode: 0644, 245 payload: map[string]util.FileProjection{ 246 "foo.txt": {Data: []byte("foo"), Mode: 0644}, 247 "bar.bin": {Data: []byte("bar"), Mode: 0644}, 248 }, 249 success: true, 250 }, 251 { 252 name: "optional non existent key", 253 mappings: []v1.KeyToPath{ 254 { 255 Key: "zab", 256 Path: "path/to/foo.txt", 257 }, 258 }, 259 configMap: &v1.ConfigMap{ 260 Data: map[string]string{ 261 "foo": "foo", 262 "bar": "bar", 263 }, 264 }, 265 mode: 0644, 266 optional: true, 267 payload: map[string]util.FileProjection{}, 268 success: true, 269 }, 270 } 271 272 for _, tc := range cases { 273 actualPayload, err := MakePayload(tc.mappings, tc.configMap, &tc.mode, tc.optional) 274 if err != nil && tc.success { 275 t.Errorf("%v: unexpected failure making payload: %v", tc.name, err) 276 continue 277 } 278 279 if err == nil && !tc.success { 280 t.Errorf("%v: unexpected success making payload", tc.name) 281 continue 282 } 283 284 if !tc.success { 285 continue 286 } 287 288 if e, a := tc.payload, actualPayload; !reflect.DeepEqual(e, a) { 289 t.Errorf("%v: expected and actual payload do not match", tc.name) 290 } 291 } 292 } 293 294 func newTestHost(t *testing.T, clientset clientset.Interface) (string, volume.VolumeHost) { 295 tempDir, err := ioutil.TempDir("", "configmap_volume_test.") 296 if err != nil { 297 t.Fatalf("can't make a temp rootdir: %v", err) 298 } 299 300 return tempDir, volumetest.NewFakeVolumeHost(t, tempDir, clientset, emptydir.ProbeVolumePlugins()) 301 } 302 303 func TestCanSupport(t *testing.T) { 304 pluginMgr := volume.VolumePluginMgr{} 305 tempDir, host := newTestHost(t, nil) 306 defer os.RemoveAll(tempDir) 307 pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host) 308 309 plugin, err := pluginMgr.FindPluginByName(configMapPluginName) 310 if err != nil { 311 t.Fatal("Can't find the plugin by name") 312 } 313 if plugin.GetPluginName() != configMapPluginName { 314 t.Errorf("Wrong name: %s", plugin.GetPluginName()) 315 } 316 if !plugin.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{LocalObjectReference: v1.LocalObjectReference{Name: ""}}}}}) { 317 t.Errorf("Expected true") 318 } 319 if plugin.CanSupport(&volume.Spec{}) { 320 t.Errorf("Expected false") 321 } 322 } 323 324 func TestPlugin(t *testing.T) { 325 var ( 326 testPodUID = types.UID("test_pod_uid") 327 testVolumeName = "test_volume_name" 328 testNamespace = "test_configmap_namespace" 329 testName = "test_configmap_name" 330 331 volumeSpec = volumeSpec(testVolumeName, testName, 0644) 332 configMap = configMap(testNamespace, testName) 333 client = fake.NewSimpleClientset(&configMap) 334 pluginMgr = volume.VolumePluginMgr{} 335 tempDir, host = newTestHost(t, client) 336 ) 337 338 defer os.RemoveAll(tempDir) 339 pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host) 340 341 plugin, err := pluginMgr.FindPluginByName(configMapPluginName) 342 if err != nil { 343 t.Fatal("Can't find the plugin by name") 344 } 345 346 pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}} 347 mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) 348 if err != nil { 349 t.Errorf("Failed to make a new Mounter: %v", err) 350 } 351 if mounter == nil { 352 t.Fatalf("Got a nil Mounter") 353 } 354 355 vName, err := plugin.GetVolumeName(volume.NewSpecFromVolume(volumeSpec)) 356 if err != nil { 357 t.Errorf("Failed to GetVolumeName: %v", err) 358 } 359 if vName != "test_volume_name/test_configmap_name" { 360 t.Errorf("Got unexpected VolumeName %v", vName) 361 } 362 363 volumePath := mounter.GetPath() 364 if !hasPathSuffix(volumePath, "pods/test_pod_uid/volumes/kubernetes.io~configmap/test_volume_name") { 365 t.Errorf("Got unexpected path: %s", volumePath) 366 } 367 368 var mounterArgs volume.MounterArgs 369 group := int64(1001) 370 mounterArgs.FsGroup = &group 371 err = mounter.SetUp(mounterArgs) 372 if err != nil { 373 t.Errorf("Failed to setup volume: %v", err) 374 } 375 if _, err := os.Stat(volumePath); err != nil { 376 if os.IsNotExist(err) { 377 t.Errorf("SetUp() failed, volume path not created: %s", volumePath) 378 } else { 379 t.Errorf("SetUp() failed: %v", err) 380 } 381 } 382 383 doTestConfigMapDataInVolume(volumePath, configMap, t) 384 doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t) 385 } 386 387 // Test the case where the plugin's ready file exists, but the volume dir is not a 388 // mountpoint, which is the state the system will be in after reboot. The dir 389 // should be mounter and the configMap data written to it. 390 func TestPluginReboot(t *testing.T) { 391 var ( 392 testPodUID = types.UID("test_pod_uid3") 393 testVolumeName = "test_volume_name" 394 testNamespace = "test_configmap_namespace" 395 testName = "test_configmap_name" 396 397 volumeSpec = volumeSpec(testVolumeName, testName, 0644) 398 configMap = configMap(testNamespace, testName) 399 client = fake.NewSimpleClientset(&configMap) 400 pluginMgr = volume.VolumePluginMgr{} 401 rootDir, host = newTestHost(t, client) 402 ) 403 404 defer os.RemoveAll(rootDir) 405 pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host) 406 407 plugin, err := pluginMgr.FindPluginByName(configMapPluginName) 408 if err != nil { 409 t.Fatal("Can't find the plugin by name") 410 } 411 412 pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}} 413 mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) 414 if err != nil { 415 t.Errorf("Failed to make a new Mounter: %v", err) 416 } 417 if mounter == nil { 418 t.Fatalf("Got a nil Mounter") 419 } 420 421 podMetadataDir := fmt.Sprintf("%v/pods/test_pod_uid3/plugins/kubernetes.io~configmap/test_volume_name", rootDir) 422 util.SetReady(podMetadataDir) 423 volumePath := mounter.GetPath() 424 if !hasPathSuffix(volumePath, "pods/test_pod_uid3/volumes/kubernetes.io~configmap/test_volume_name") { 425 t.Errorf("Got unexpected path: %s", volumePath) 426 } 427 428 var mounterArgs volume.MounterArgs 429 group := int64(1001) 430 mounterArgs.FsGroup = &group 431 err = mounter.SetUp(mounterArgs) 432 if err != nil { 433 t.Errorf("Failed to setup volume: %v", err) 434 } 435 if _, err := os.Stat(volumePath); err != nil { 436 if os.IsNotExist(err) { 437 t.Errorf("SetUp() failed, volume path not created: %s", volumePath) 438 } else { 439 t.Errorf("SetUp() failed: %v", err) 440 } 441 } 442 443 doTestConfigMapDataInVolume(volumePath, configMap, t) 444 doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t) 445 } 446 447 func TestPluginOptional(t *testing.T) { 448 var ( 449 testPodUID = types.UID("test_pod_uid") 450 testVolumeName = "test_volume_name" 451 testNamespace = "test_configmap_namespace" 452 testName = "test_configmap_name" 453 trueVal = true 454 455 volumeSpec = volumeSpec(testVolumeName, testName, 0644) 456 client = fake.NewSimpleClientset() 457 pluginMgr = volume.VolumePluginMgr{} 458 tempDir, host = newTestHost(t, client) 459 ) 460 volumeSpec.VolumeSource.ConfigMap.Optional = &trueVal 461 462 defer os.RemoveAll(tempDir) 463 pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host) 464 465 plugin, err := pluginMgr.FindPluginByName(configMapPluginName) 466 if err != nil { 467 t.Fatal("Can't find the plugin by name") 468 } 469 470 pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}} 471 mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) 472 if err != nil { 473 t.Errorf("Failed to make a new Mounter: %v", err) 474 } 475 if mounter == nil { 476 t.Errorf("Got a nil Mounter") 477 } 478 479 vName, err := plugin.GetVolumeName(volume.NewSpecFromVolume(volumeSpec)) 480 if err != nil { 481 t.Errorf("Failed to GetVolumeName: %v", err) 482 } 483 if vName != "test_volume_name/test_configmap_name" { 484 t.Errorf("Got unexpected VolumeName %v", vName) 485 } 486 487 volumePath := mounter.GetPath() 488 if !hasPathSuffix(volumePath, "pods/test_pod_uid/volumes/kubernetes.io~configmap/test_volume_name") { 489 t.Errorf("Got unexpected path: %s", volumePath) 490 } 491 492 var mounterArgs volume.MounterArgs 493 group := int64(1001) 494 mounterArgs.FsGroup = &group 495 err = mounter.SetUp(mounterArgs) 496 if err != nil { 497 t.Errorf("Failed to setup volume: %v", err) 498 } 499 if _, err := os.Stat(volumePath); err != nil { 500 if os.IsNotExist(err) { 501 t.Errorf("SetUp() failed, volume path not created: %s", volumePath) 502 } else { 503 t.Errorf("SetUp() failed: %v", err) 504 } 505 } 506 507 datadirSymlink := filepath.Join(volumePath, "..data") 508 datadir, err := os.Readlink(datadirSymlink) 509 if err != nil && os.IsNotExist(err) { 510 t.Fatalf("couldn't find volume path's data dir, %s", datadirSymlink) 511 } else if err != nil { 512 t.Fatalf("couldn't read symlink, %s", datadirSymlink) 513 } 514 datadirPath := filepath.Join(volumePath, datadir) 515 516 infos, err := ioutil.ReadDir(volumePath) 517 if err != nil { 518 t.Fatalf("couldn't find volume path, %s", volumePath) 519 } 520 if len(infos) != 0 { 521 for _, fi := range infos { 522 if fi.Name() != "..data" && fi.Name() != datadir { 523 t.Errorf("empty data directory, %s, is not empty. Contains: %s", datadirSymlink, fi.Name()) 524 } 525 } 526 } 527 528 infos, err = ioutil.ReadDir(datadirPath) 529 if err != nil { 530 t.Fatalf("couldn't find volume data path, %s", datadirPath) 531 } 532 if len(infos) != 0 { 533 t.Errorf("empty data directory, %s, is not empty. Contains: %s", datadirSymlink, infos[0].Name()) 534 } 535 536 doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t) 537 } 538 539 func TestPluginKeysOptional(t *testing.T) { 540 var ( 541 testPodUID = types.UID("test_pod_uid") 542 testVolumeName = "test_volume_name" 543 testNamespace = "test_configmap_namespace" 544 testName = "test_configmap_name" 545 trueVal = true 546 547 volumeSpec = volumeSpec(testVolumeName, testName, 0644) 548 configMap = configMap(testNamespace, testName) 549 client = fake.NewSimpleClientset(&configMap) 550 pluginMgr = volume.VolumePluginMgr{} 551 tempDir, host = newTestHost(t, client) 552 ) 553 volumeSpec.VolumeSource.ConfigMap.Items = []v1.KeyToPath{ 554 {Key: "data-1", Path: "data-1"}, 555 {Key: "data-2", Path: "data-2"}, 556 {Key: "data-3", Path: "data-3"}, 557 {Key: "missing", Path: "missing"}, 558 } 559 volumeSpec.VolumeSource.ConfigMap.Optional = &trueVal 560 561 defer os.RemoveAll(tempDir) 562 pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host) 563 564 plugin, err := pluginMgr.FindPluginByName(configMapPluginName) 565 if err != nil { 566 t.Fatal("Can't find the plugin by name") 567 } 568 569 pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}} 570 mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) 571 if err != nil { 572 t.Errorf("Failed to make a new Mounter: %v", err) 573 } 574 if mounter == nil { 575 t.Errorf("Got a nil Mounter") 576 } 577 578 vName, err := plugin.GetVolumeName(volume.NewSpecFromVolume(volumeSpec)) 579 if err != nil { 580 t.Errorf("Failed to GetVolumeName: %v", err) 581 } 582 if vName != "test_volume_name/test_configmap_name" { 583 t.Errorf("Got unexpected VolumeName %v", vName) 584 } 585 586 volumePath := mounter.GetPath() 587 if !hasPathSuffix(volumePath, "pods/test_pod_uid/volumes/kubernetes.io~configmap/test_volume_name") { 588 t.Errorf("Got unexpected path: %s", volumePath) 589 } 590 591 var mounterArgs volume.MounterArgs 592 group := int64(1001) 593 mounterArgs.FsGroup = &group 594 err = mounter.SetUp(mounterArgs) 595 if err != nil { 596 t.Errorf("Failed to setup volume: %v", err) 597 } 598 if _, err := os.Stat(volumePath); err != nil { 599 if os.IsNotExist(err) { 600 t.Errorf("SetUp() failed, volume path not created: %s", volumePath) 601 } else { 602 t.Errorf("SetUp() failed: %v", err) 603 } 604 } 605 606 doTestConfigMapDataInVolume(volumePath, configMap, t) 607 doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t) 608 } 609 610 func volumeSpec(volumeName, configMapName string, defaultMode int32) *v1.Volume { 611 return &v1.Volume{ 612 Name: volumeName, 613 VolumeSource: v1.VolumeSource{ 614 ConfigMap: &v1.ConfigMapVolumeSource{ 615 LocalObjectReference: v1.LocalObjectReference{ 616 Name: configMapName, 617 }, 618 DefaultMode: &defaultMode, 619 }, 620 }, 621 } 622 } 623 624 func TestInvalidConfigMapSetup(t *testing.T) { 625 var ( 626 testPodUID = types.UID("test_pod_uid") 627 testVolumeName = "test_volume_name" 628 testNamespace = "test_configmap_namespace" 629 testName = "test_configmap_name" 630 631 volumeSpec = volumeSpec(testVolumeName, testName, 0644) 632 configMap = configMap(testNamespace, testName) 633 client = fake.NewSimpleClientset(&configMap) 634 pluginMgr = volume.VolumePluginMgr{} 635 tempDir, host = newTestHost(t, client) 636 ) 637 volumeSpec.VolumeSource.ConfigMap.Items = []v1.KeyToPath{ 638 {Key: "missing", Path: "missing"}, 639 } 640 641 defer os.RemoveAll(tempDir) 642 pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host) 643 644 plugin, err := pluginMgr.FindPluginByName(configMapPluginName) 645 if err != nil { 646 t.Fatal("Can't find the plugin by name") 647 } 648 649 pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}} 650 mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}) 651 if err != nil { 652 t.Errorf("Failed to make a new Mounter: %v", err) 653 } 654 if mounter == nil { 655 t.Errorf("Got a nil Mounter") 656 } 657 658 vName, err := plugin.GetVolumeName(volume.NewSpecFromVolume(volumeSpec)) 659 if err != nil { 660 t.Errorf("Failed to GetVolumeName: %v", err) 661 } 662 if vName != "test_volume_name/test_configmap_name" { 663 t.Errorf("Got unexpected VolumeName %v", vName) 664 } 665 666 volumePath := mounter.GetPath() 667 if !hasPathSuffix(volumePath, "pods/test_pod_uid/volumes/kubernetes.io~configmap/test_volume_name") { 668 t.Errorf("Got unexpected path: %s", volumePath) 669 } 670 671 var mounterArgs volume.MounterArgs 672 group := int64(1001) 673 mounterArgs.FsGroup = &group 674 err = mounter.SetUp(mounterArgs) 675 if err == nil { 676 t.Errorf("Expected setup to fail") 677 } 678 _, err = os.Stat(volumePath) 679 if err == nil { 680 t.Errorf("Expected %s to not exist", volumePath) 681 } 682 683 doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t) 684 } 685 686 func configMap(namespace, name string) v1.ConfigMap { 687 return v1.ConfigMap{ 688 ObjectMeta: metav1.ObjectMeta{ 689 Namespace: namespace, 690 Name: name, 691 }, 692 Data: map[string]string{ 693 "data-1": "value-1", 694 "data-2": "value-2", 695 "data-3": "value-3", 696 }, 697 } 698 } 699 700 func doTestConfigMapDataInVolume(volumePath string, configMap v1.ConfigMap, t *testing.T) { 701 for key, value := range configMap.Data { 702 configMapDataHostPath := filepath.Join(volumePath, key) 703 if _, err := os.Stat(configMapDataHostPath); err != nil { 704 t.Fatalf("SetUp() failed, couldn't find configMap data on disk: %v", configMapDataHostPath) 705 } else { 706 actualValue, err := ioutil.ReadFile(configMapDataHostPath) 707 if err != nil { 708 t.Fatalf("Couldn't read configMap data from: %v", configMapDataHostPath) 709 } 710 711 if value != string(actualValue) { 712 t.Errorf("Unexpected value; expected %q, got %q", value, actualValue) 713 } 714 } 715 } 716 } 717 718 func doTestCleanAndTeardown(plugin volume.VolumePlugin, podUID types.UID, testVolumeName, volumePath string, t *testing.T) { 719 unmounter, err := plugin.NewUnmounter(testVolumeName, podUID) 720 if err != nil { 721 t.Errorf("Failed to make a new Unmounter: %v", err) 722 } 723 if unmounter == nil { 724 t.Fatalf("Got a nil Unmounter") 725 } 726 727 if err := unmounter.TearDown(); err != nil { 728 t.Errorf("Expected success, got: %v", err) 729 } 730 if _, err := os.Stat(volumePath); err == nil { 731 t.Errorf("TearDown() failed, volume path still exists: %s", volumePath) 732 } else if !os.IsNotExist(err) { 733 t.Errorf("TearDown() failed: %v", err) 734 } 735 } 736 737 func hasPathSuffix(s, suffix string) bool { 738 return strings.HasSuffix(s, filepath.FromSlash(suffix)) 739 }