k8s.io/kubernetes@v1.29.3/pkg/volume/hostpath/host_path_test.go (about) 1 /* 2 Copyright 2014 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 hostpath 18 19 import ( 20 "fmt" 21 "os" 22 "testing" 23 24 v1 "k8s.io/api/core/v1" 25 "k8s.io/apimachinery/pkg/api/resource" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/types" 28 "k8s.io/apimachinery/pkg/util/uuid" 29 "k8s.io/client-go/kubernetes/fake" 30 "k8s.io/klog/v2/ktesting" 31 "k8s.io/kubernetes/pkg/volume" 32 volumetest "k8s.io/kubernetes/pkg/volume/testing" 33 "k8s.io/kubernetes/pkg/volume/util/hostutil" 34 utilpath "k8s.io/utils/path" 35 ) 36 37 func newHostPathType(pathType string) *v1.HostPathType { 38 hostPathType := new(v1.HostPathType) 39 *hostPathType = v1.HostPathType(pathType) 40 return hostPathType 41 } 42 43 func newHostPathTypeList(pathType ...string) []*v1.HostPathType { 44 typeList := []*v1.HostPathType{} 45 for _, ele := range pathType { 46 typeList = append(typeList, newHostPathType(ele)) 47 } 48 49 return typeList 50 } 51 52 func TestCanSupport(t *testing.T) { 53 plugMgr := volume.VolumePluginMgr{} 54 plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), nil /* prober */, volumetest.NewFakeKubeletVolumeHost(t, "fake", nil, nil)) 55 56 plug, err := plugMgr.FindPluginByName(hostPathPluginName) 57 if err != nil { 58 t.Fatal("Can't find the plugin by name") 59 } 60 if plug.GetPluginName() != hostPathPluginName { 61 t.Errorf("Wrong name: %s", plug.GetPluginName()) 62 } 63 if !plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{HostPath: &v1.HostPathVolumeSource{}}}}) { 64 t.Errorf("Expected true") 65 } 66 if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{}}}}}) { 67 t.Errorf("Expected true") 68 } 69 if plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{}}}) { 70 t.Errorf("Expected false") 71 } 72 } 73 74 func TestGetAccessModes(t *testing.T) { 75 plugMgr := volume.VolumePluginMgr{} 76 plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), nil /* prober */, volumetest.NewFakeKubeletVolumeHost(t, "/tmp/fake", nil, nil)) 77 78 plug, err := plugMgr.FindPersistentPluginByName(hostPathPluginName) 79 if err != nil { 80 t.Fatal("Can't find the plugin by name") 81 } 82 if len(plug.GetAccessModes()) != 1 || plug.GetAccessModes()[0] != v1.ReadWriteOnce { 83 t.Errorf("Expected %s PersistentVolumeAccessMode", v1.ReadWriteOnce) 84 } 85 } 86 87 func TestRecycler(t *testing.T) { 88 plugMgr := volume.VolumePluginMgr{} 89 pluginHost := volumetest.NewFakeKubeletVolumeHost(t, "/tmp/fake", nil, nil) 90 plugMgr.InitPlugins([]volume.VolumePlugin{&hostPathPlugin{nil, volume.VolumeConfig{}, false}}, nil, pluginHost) 91 92 spec := &volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{Path: "/foo"}}}}} 93 _, err := plugMgr.FindRecyclablePluginBySpec(spec) 94 if err != nil { 95 t.Errorf("Can't find the plugin by name") 96 } 97 } 98 99 func TestDeleter(t *testing.T) { 100 // Deleter has a hard-coded regex for "/tmp". 101 tempPath := fmt.Sprintf("/tmp/hostpath.%s", uuid.NewUUID()) 102 err := os.MkdirAll(tempPath, 0750) 103 if err != nil { 104 t.Fatalf("Failed to create tmp directory for deleter: %v", err) 105 } 106 defer os.RemoveAll(tempPath) 107 plugMgr := volume.VolumePluginMgr{} 108 plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), nil /* prober */, volumetest.NewFakeKubeletVolumeHost(t, "/tmp/fake", nil, nil)) 109 110 spec := &volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{Path: tempPath}}}}} 111 plug, err := plugMgr.FindDeletablePluginBySpec(spec) 112 if err != nil { 113 t.Fatal("Can't find the plugin by name") 114 } 115 logger, _ := ktesting.NewTestContext(t) 116 deleter, err := plug.NewDeleter(logger, spec) 117 if err != nil { 118 t.Errorf("Failed to make a new Deleter: %v", err) 119 } 120 if deleter.GetPath() != tempPath { 121 t.Errorf("Expected %s but got %s", tempPath, deleter.GetPath()) 122 } 123 if err := deleter.Delete(); err != nil { 124 t.Errorf("Mock Recycler expected to return nil but got %s", err) 125 } 126 if exists, _ := utilpath.Exists(utilpath.CheckFollowSymlink, tempPath); exists { 127 t.Errorf("Temp path expected to be deleted, but was found at %s", tempPath) 128 } 129 } 130 131 func TestDeleterTempDir(t *testing.T) { 132 tests := map[string]struct { 133 expectedFailure bool 134 path string 135 }{ 136 "just-tmp": {true, "/tmp"}, 137 "not-tmp": {true, "/nottmp"}, 138 "good-tmp": {false, "/tmp/scratch"}, 139 } 140 logger, _ := ktesting.NewTestContext(t) 141 for name, test := range tests { 142 plugMgr := volume.VolumePluginMgr{} 143 plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), nil /* prober */, volumetest.NewFakeKubeletVolumeHost(t, "/tmp/fake", nil, nil)) 144 spec := &volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{Path: test.path}}}}} 145 plug, _ := plugMgr.FindDeletablePluginBySpec(spec) 146 deleter, _ := plug.NewDeleter(logger, spec) 147 err := deleter.Delete() 148 if err == nil && test.expectedFailure { 149 t.Errorf("Expected failure for test '%s' but got nil err", name) 150 } 151 if err != nil && !test.expectedFailure { 152 t.Errorf("Unexpected failure for test '%s': %v", name, err) 153 } 154 } 155 } 156 157 func TestProvisioner(t *testing.T) { 158 plugMgr := volume.VolumePluginMgr{} 159 plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{ProvisioningEnabled: true}), 160 nil, 161 volumetest.NewFakeKubeletVolumeHost(t, "/tmp/fake", nil, nil)) 162 spec := &volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{ 163 PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{Path: fmt.Sprintf("/tmp/hostpath.%s", uuid.NewUUID())}}}}} 164 plug, err := plugMgr.FindCreatablePluginBySpec(spec) 165 if err != nil { 166 t.Fatalf("Can't find the plugin by name") 167 } 168 options := volume.VolumeOptions{ 169 PVC: volumetest.CreateTestPVC("1Gi", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}), 170 PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete, 171 } 172 logger, _ := ktesting.NewTestContext(t) 173 creator, err := plug.NewProvisioner(logger, options) 174 if err != nil { 175 t.Fatalf("Failed to make a new Provisioner: %v", err) 176 } 177 178 hostPathCreator, ok := creator.(*hostPathProvisioner) 179 if !ok { 180 t.Fatal("Not a hostPathProvisioner") 181 } 182 hostPathCreator.basePath = fmt.Sprintf("%s.%s", "hostPath_pv", uuid.NewUUID()) 183 184 pv, err := hostPathCreator.Provision(nil, nil) 185 if err != nil { 186 t.Errorf("Unexpected error creating volume: %v", err) 187 } 188 if pv.Spec.HostPath.Path == "" { 189 t.Errorf("Expected pv.Spec.HostPath.Path to not be empty: %#v", pv) 190 } 191 expectedCapacity := resource.NewQuantity(1*1024*1024*1024, resource.BinarySI) 192 actualCapacity := pv.Spec.Capacity[v1.ResourceStorage] 193 expectedAmt := expectedCapacity.Value() 194 actualAmt := actualCapacity.Value() 195 if expectedAmt != actualAmt { 196 t.Errorf("Expected capacity %+v but got %+v", expectedAmt, actualAmt) 197 } 198 199 if pv.Spec.PersistentVolumeReclaimPolicy != v1.PersistentVolumeReclaimDelete { 200 t.Errorf("Expected reclaim policy %+v but got %+v", v1.PersistentVolumeReclaimDelete, pv.Spec.PersistentVolumeReclaimPolicy) 201 } 202 203 os.RemoveAll(hostPathCreator.basePath) 204 205 } 206 207 func TestInvalidHostPath(t *testing.T) { 208 plugMgr := volume.VolumePluginMgr{} 209 plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), nil /* prober */, volumetest.NewFakeKubeletVolumeHost(t, "fake", nil, nil)) 210 211 plug, err := plugMgr.FindPluginByName(hostPathPluginName) 212 if err != nil { 213 t.Fatalf("Unable to find plugin %s by name: %v", hostPathPluginName, err) 214 } 215 spec := &v1.Volume{ 216 Name: "vol1", 217 VolumeSource: v1.VolumeSource{HostPath: &v1.HostPathVolumeSource{Path: "/no/backsteps/allowed/.."}}, 218 } 219 pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}} 220 mounter, err := plug.NewMounter(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{}) 221 if err != nil { 222 t.Fatal(err) 223 } 224 225 err = mounter.SetUp(volume.MounterArgs{}) 226 expectedMsg := "invalid HostPath `/no/backsteps/allowed/..`: must not contain '..'" 227 if err.Error() != expectedMsg { 228 t.Fatalf("expected error `%s` but got `%s`", expectedMsg, err) 229 } 230 } 231 232 func TestPlugin(t *testing.T) { 233 plugMgr := volume.VolumePluginMgr{} 234 plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), nil /* prober */, volumetest.NewFakeKubeletVolumeHost(t, "fake", nil, nil)) 235 236 plug, err := plugMgr.FindPluginByName(hostPathPluginName) 237 if err != nil { 238 t.Fatal("Can't find the plugin by name") 239 } 240 241 volPath := "/tmp/vol1" 242 spec := &v1.Volume{ 243 Name: "vol1", 244 VolumeSource: v1.VolumeSource{HostPath: &v1.HostPathVolumeSource{Path: volPath, Type: newHostPathType(string(v1.HostPathDirectoryOrCreate))}}, 245 } 246 pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}} 247 defer os.RemoveAll(volPath) 248 mounter, err := plug.NewMounter(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{}) 249 if err != nil { 250 t.Errorf("Failed to make a new Mounter: %v", err) 251 } 252 if mounter == nil { 253 t.Fatalf("Got a nil Mounter") 254 } 255 256 path := mounter.GetPath() 257 if path != volPath { 258 t.Errorf("Got unexpected path: %s", path) 259 } 260 261 if err := mounter.SetUp(volume.MounterArgs{}); err != nil { 262 t.Errorf("Expected success, got: %v", err) 263 } 264 265 unmounter, err := plug.NewUnmounter("vol1", types.UID("poduid")) 266 if err != nil { 267 t.Errorf("Failed to make a new Unmounter: %v", err) 268 } 269 if unmounter == nil { 270 t.Fatalf("Got a nil Unmounter") 271 } 272 273 if err := unmounter.TearDown(); err != nil { 274 t.Errorf("Expected success, got: %v", err) 275 } 276 } 277 278 func TestPersistentClaimReadOnlyFlag(t *testing.T) { 279 pv := &v1.PersistentVolume{ 280 ObjectMeta: metav1.ObjectMeta{ 281 Name: "pvA", 282 }, 283 Spec: v1.PersistentVolumeSpec{ 284 PersistentVolumeSource: v1.PersistentVolumeSource{ 285 HostPath: &v1.HostPathVolumeSource{Path: "foo", Type: newHostPathType(string(v1.HostPathDirectoryOrCreate))}, 286 }, 287 ClaimRef: &v1.ObjectReference{ 288 Name: "claimA", 289 }, 290 }, 291 } 292 defer os.RemoveAll("foo") 293 294 claim := &v1.PersistentVolumeClaim{ 295 ObjectMeta: metav1.ObjectMeta{ 296 Name: "claimA", 297 Namespace: "nsA", 298 }, 299 Spec: v1.PersistentVolumeClaimSpec{ 300 VolumeName: "pvA", 301 }, 302 Status: v1.PersistentVolumeClaimStatus{ 303 Phase: v1.ClaimBound, 304 }, 305 } 306 307 client := fake.NewSimpleClientset(pv, claim) 308 309 plugMgr := volume.VolumePluginMgr{} 310 plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), nil /* prober */, volumetest.NewFakeKubeletVolumeHost(t, "/tmp/fake", client, nil)) 311 plug, _ := plugMgr.FindPluginByName(hostPathPluginName) 312 313 // readOnly bool is supplied by persistent-claim volume source when its mounter creates other volumes 314 spec := volume.NewSpecFromPersistentVolume(pv, true) 315 pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}} 316 mounter, _ := plug.NewMounter(spec, pod, volume.VolumeOptions{}) 317 if mounter == nil { 318 t.Fatalf("Got a nil Mounter") 319 } 320 321 if !mounter.GetAttributes().ReadOnly { 322 t.Errorf("Expected true for mounter.IsReadOnly") 323 } 324 } 325 326 func setUp() error { 327 err := os.MkdirAll("/tmp/ExistingFolder", os.FileMode(0755)) 328 if err != nil { 329 return err 330 } 331 332 f, err := os.OpenFile("/tmp/ExistingFolder/foo", os.O_CREATE, os.FileMode(0644)) 333 if err != nil { 334 return err 335 } 336 defer f.Close() 337 338 return nil 339 } 340 341 func tearDown() { 342 os.RemoveAll("/tmp/ExistingFolder") 343 } 344 345 func TestOSFileTypeChecker(t *testing.T) { 346 err := setUp() 347 if err != nil { 348 t.Error(err) 349 } 350 defer tearDown() 351 testCases := []struct { 352 name string 353 path string 354 desiredType string 355 isDir bool 356 isFile bool 357 isSocket bool 358 isBlock bool 359 isChar bool 360 }{ 361 { 362 name: "Existing Folder", 363 path: "/tmp/ExistingFolder", 364 desiredType: string(hostutil.FileTypeDirectory), 365 isDir: true, 366 }, 367 { 368 name: "Existing File", 369 path: "/tmp/ExistingFolder/foo", 370 desiredType: string(hostutil.FileTypeFile), 371 isFile: true, 372 }, 373 { 374 name: "Existing Socket File", 375 path: "/tmp/ExistingFolder/foo", 376 desiredType: string(v1.HostPathSocket), 377 isSocket: true, 378 }, 379 { 380 name: "Existing Character Device", 381 path: "/tmp/ExistingFolder/foo", 382 desiredType: string(v1.HostPathCharDev), 383 isChar: true, 384 }, 385 { 386 name: "Existing Block Device", 387 path: "/tmp/ExistingFolder/foo", 388 desiredType: string(v1.HostPathBlockDev), 389 isBlock: true, 390 }, 391 } 392 393 for i, tc := range testCases { 394 fakeFTC := hostutil.NewFakeHostUtil( 395 map[string]hostutil.FileType{ 396 tc.path: hostutil.FileType(tc.desiredType), 397 }) 398 oftc := newFileTypeChecker(tc.path, fakeFTC) 399 400 path := oftc.GetPath() 401 if path != tc.path { 402 t.Errorf("[%d: %q] got unexpected path: %s", i, tc.name, path) 403 } 404 405 exist := oftc.Exists() 406 if !exist { 407 t.Errorf("[%d: %q] path: %s does not exist", i, tc.name, path) 408 } 409 410 if tc.isDir { 411 if !oftc.IsDir() { 412 t.Errorf("[%d: %q] expected folder, got unexpected: %s", i, tc.name, path) 413 } 414 if oftc.IsFile() { 415 t.Errorf("[%d: %q] expected folder, got unexpected file: %s", i, tc.name, path) 416 } 417 if oftc.IsSocket() { 418 t.Errorf("[%d: %q] expected folder, got unexpected socket file: %s", i, tc.name, path) 419 } 420 if oftc.IsBlock() { 421 t.Errorf("[%d: %q] expected folder, got unexpected block device: %s", i, tc.name, path) 422 } 423 if oftc.IsChar() { 424 t.Errorf("[%d: %q] expected folder, got unexpected character device: %s", i, tc.name, path) 425 } 426 } 427 428 if tc.isFile { 429 if !oftc.IsFile() { 430 t.Errorf("[%d: %q] expected file, got unexpected: %s", i, tc.name, path) 431 } 432 if oftc.IsDir() { 433 t.Errorf("[%d: %q] expected file, got unexpected folder: %s", i, tc.name, path) 434 } 435 if oftc.IsSocket() { 436 t.Errorf("[%d: %q] expected file, got unexpected socket file: %s", i, tc.name, path) 437 } 438 if oftc.IsBlock() { 439 t.Errorf("[%d: %q] expected file, got unexpected block device: %s", i, tc.name, path) 440 } 441 if oftc.IsChar() { 442 t.Errorf("[%d: %q] expected file, got unexpected character device: %s", i, tc.name, path) 443 } 444 } 445 446 if tc.isSocket { 447 if !oftc.IsSocket() { 448 t.Errorf("[%d: %q] expected socket file, got unexpected: %s", i, tc.name, path) 449 } 450 if oftc.IsDir() { 451 t.Errorf("[%d: %q] expected socket file, got unexpected folder: %s", i, tc.name, path) 452 } 453 if oftc.IsFile() { 454 t.Errorf("[%d: %q] expected socket file, got unexpected file: %s", i, tc.name, path) 455 } 456 if oftc.IsBlock() { 457 t.Errorf("[%d: %q] expected socket file, got unexpected block device: %s", i, tc.name, path) 458 } 459 if oftc.IsChar() { 460 t.Errorf("[%d: %q] expected socket file, got unexpected character device: %s", i, tc.name, path) 461 } 462 } 463 464 if tc.isChar { 465 if !oftc.IsChar() { 466 t.Errorf("[%d: %q] expected character device, got unexpected: %s", i, tc.name, path) 467 } 468 if oftc.IsDir() { 469 t.Errorf("[%d: %q] expected character device, got unexpected folder: %s", i, tc.name, path) 470 } 471 if oftc.IsFile() { 472 t.Errorf("[%d: %q] expected character device, got unexpected file: %s", i, tc.name, path) 473 } 474 if oftc.IsSocket() { 475 t.Errorf("[%d: %q] expected character device, got unexpected socket file: %s", i, tc.name, path) 476 } 477 if oftc.IsBlock() { 478 t.Errorf("[%d: %q] expected character device, got unexpected block device: %s", i, tc.name, path) 479 } 480 } 481 482 if tc.isBlock { 483 if !oftc.IsBlock() { 484 t.Errorf("[%d: %q] expected block device, got unexpected: %s", i, tc.name, path) 485 } 486 if oftc.IsDir() { 487 t.Errorf("[%d: %q] expected block device, got unexpected folder: %s", i, tc.name, path) 488 } 489 if oftc.IsFile() { 490 t.Errorf("[%d: %q] expected block device, got unexpected file: %s", i, tc.name, path) 491 } 492 if oftc.IsSocket() { 493 t.Errorf("[%d: %q] expected block device, got unexpected socket file: %s", i, tc.name, path) 494 } 495 if oftc.IsChar() { 496 t.Errorf("[%d: %q] expected block device, got unexpected character device: %s", i, tc.name, path) 497 } 498 } 499 } 500 501 } 502 503 type fakeHostPathTypeChecker struct { 504 name string 505 path string 506 exists bool 507 isDir bool 508 isFile bool 509 isSocket bool 510 isBlock bool 511 isChar bool 512 validpathType []*v1.HostPathType 513 invalidpathType []*v1.HostPathType 514 } 515 516 func (ftc *fakeHostPathTypeChecker) MakeFile() error { return nil } 517 func (ftc *fakeHostPathTypeChecker) MakeDir() error { return nil } 518 func (ftc *fakeHostPathTypeChecker) Exists() bool { return ftc.exists } 519 func (ftc *fakeHostPathTypeChecker) IsFile() bool { return ftc.isFile } 520 func (ftc *fakeHostPathTypeChecker) IsDir() bool { return ftc.isDir } 521 func (ftc *fakeHostPathTypeChecker) IsBlock() bool { return ftc.isBlock } 522 func (ftc *fakeHostPathTypeChecker) IsChar() bool { return ftc.isChar } 523 func (ftc *fakeHostPathTypeChecker) IsSocket() bool { return ftc.isSocket } 524 func (ftc *fakeHostPathTypeChecker) GetPath() string { return ftc.path } 525 526 func TestHostPathTypeCheckerInternal(t *testing.T) { 527 testCases := []fakeHostPathTypeChecker{ 528 { 529 name: "Existing Folder", 530 path: "/existingFolder", 531 isDir: true, 532 exists: true, 533 validpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate), string(v1.HostPathDirectory)), 534 invalidpathType: newHostPathTypeList(string(v1.HostPathFileOrCreate), string(v1.HostPathFile), 535 string(v1.HostPathSocket), string(v1.HostPathCharDev), string(v1.HostPathBlockDev)), 536 }, 537 { 538 name: "New Folder", 539 path: "/newFolder", 540 isDir: false, 541 exists: false, 542 validpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate)), 543 invalidpathType: newHostPathTypeList(string(v1.HostPathDirectory), string(v1.HostPathFile), 544 string(v1.HostPathSocket), string(v1.HostPathCharDev), string(v1.HostPathBlockDev)), 545 }, 546 { 547 name: "Existing File", 548 path: "/existingFile", 549 isFile: true, 550 exists: true, 551 validpathType: newHostPathTypeList(string(v1.HostPathFileOrCreate), string(v1.HostPathFile)), 552 invalidpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate), string(v1.HostPathDirectory), 553 string(v1.HostPathSocket), string(v1.HostPathCharDev), string(v1.HostPathBlockDev)), 554 }, 555 { 556 name: "New File", 557 path: "/newFile", 558 isFile: false, 559 exists: false, 560 validpathType: newHostPathTypeList(string(v1.HostPathFileOrCreate)), 561 invalidpathType: newHostPathTypeList(string(v1.HostPathDirectory), 562 string(v1.HostPathSocket), string(v1.HostPathCharDev), string(v1.HostPathBlockDev)), 563 }, 564 { 565 name: "Existing Socket", 566 path: "/existing.socket", 567 isSocket: true, 568 isFile: true, 569 exists: true, 570 validpathType: newHostPathTypeList(string(v1.HostPathSocket), string(v1.HostPathFileOrCreate), string(v1.HostPathFile)), 571 invalidpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate), string(v1.HostPathDirectory), 572 string(v1.HostPathCharDev), string(v1.HostPathBlockDev)), 573 }, 574 { 575 name: "Existing Character Device", 576 path: "/existing.char", 577 isChar: true, 578 isFile: true, 579 exists: true, 580 validpathType: newHostPathTypeList(string(v1.HostPathCharDev), string(v1.HostPathFileOrCreate), string(v1.HostPathFile)), 581 invalidpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate), string(v1.HostPathDirectory), 582 string(v1.HostPathSocket), string(v1.HostPathBlockDev)), 583 }, 584 { 585 name: "Existing Block Device", 586 path: "/existing.block", 587 isBlock: true, 588 isFile: true, 589 exists: true, 590 validpathType: newHostPathTypeList(string(v1.HostPathBlockDev), string(v1.HostPathFileOrCreate), string(v1.HostPathFile)), 591 invalidpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate), string(v1.HostPathDirectory), 592 string(v1.HostPathSocket), string(v1.HostPathCharDev)), 593 }, 594 } 595 596 for i, tc := range testCases { 597 for _, pathType := range tc.validpathType { 598 err := checkTypeInternal(&tc, pathType) 599 if err != nil { 600 t.Errorf("[%d: %q] [%q] expected nil, got %v", i, tc.name, string(*pathType), err) 601 } 602 } 603 604 for _, pathType := range tc.invalidpathType { 605 checkResult := checkTypeInternal(&tc, pathType) 606 if checkResult == nil { 607 t.Errorf("[%d: %q] [%q] expected error, got nil", i, tc.name, string(*pathType)) 608 } 609 } 610 } 611 612 }