...

Source file src/k8s.io/kubernetes/pkg/volume/hostpath/host_path_test.go

Documentation: k8s.io/kubernetes/pkg/volume/hostpath

     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  }
   613  

View as plain text