...

Source file src/k8s.io/kubernetes/pkg/volume/nfs/nfs_test.go

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

     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 nfs
    18  
    19  import (
    20  	"os"
    21  	"path/filepath"
    22  	"testing"
    23  
    24  	"k8s.io/mount-utils"
    25  
    26  	v1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/types"
    29  	"k8s.io/client-go/kubernetes/fake"
    30  	utiltesting "k8s.io/client-go/util/testing"
    31  	"k8s.io/kubernetes/pkg/volume"
    32  	volumetest "k8s.io/kubernetes/pkg/volume/testing"
    33  )
    34  
    35  func TestCanSupport(t *testing.T) {
    36  	tmpDir, err := utiltesting.MkTmpdir("nfs_test")
    37  	if err != nil {
    38  		t.Fatalf("error creating temp dir: %v", err)
    39  	}
    40  	defer os.RemoveAll(tmpDir)
    41  
    42  	plugMgr := volume.VolumePluginMgr{}
    43  	plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
    44  	plug, err := plugMgr.FindPluginByName("kubernetes.io/nfs")
    45  	if err != nil {
    46  		t.Fatal("Can't find the plugin by name")
    47  	}
    48  	if plug.GetPluginName() != "kubernetes.io/nfs" {
    49  		t.Errorf("Wrong name: %s", plug.GetPluginName())
    50  	}
    51  
    52  	if !plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{NFS: &v1.NFSVolumeSource{}}}}) {
    53  		t.Errorf("Expected true")
    54  	}
    55  	if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{NFS: &v1.NFSVolumeSource{}}}}}) {
    56  		t.Errorf("Expected true")
    57  	}
    58  	if plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{}}}) {
    59  		t.Errorf("Expected false")
    60  	}
    61  }
    62  
    63  func TestGetAccessModes(t *testing.T) {
    64  	tmpDir, err := utiltesting.MkTmpdir("nfs_test")
    65  	if err != nil {
    66  		t.Fatalf("error creating temp dir: %v", err)
    67  	}
    68  	defer os.RemoveAll(tmpDir)
    69  
    70  	plugMgr := volume.VolumePluginMgr{}
    71  	plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
    72  
    73  	plug, err := plugMgr.FindPersistentPluginByName("kubernetes.io/nfs")
    74  	if err != nil {
    75  		t.Errorf("Can't find the plugin by name")
    76  	}
    77  	if !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteOnce) || !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadOnlyMany) || !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteMany) {
    78  		t.Errorf("Expected three AccessModeTypes:  %s, %s, and %s", v1.ReadWriteOnce, v1.ReadOnlyMany, v1.ReadWriteMany)
    79  	}
    80  }
    81  
    82  func TestRecycler(t *testing.T) {
    83  	tmpDir, err := utiltesting.MkTmpdir("nfs_test")
    84  	if err != nil {
    85  		t.Fatalf("error creating temp dir: %v", err)
    86  	}
    87  	defer os.RemoveAll(tmpDir)
    88  
    89  	plugMgr := volume.VolumePluginMgr{}
    90  	plugMgr.InitPlugins([]volume.VolumePlugin{&nfsPlugin{nil, volume.VolumeConfig{}}}, nil, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
    91  
    92  	spec := &volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{NFS: &v1.NFSVolumeSource{Path: "/foo"}}}}}
    93  	_, pluginErr := plugMgr.FindRecyclablePluginBySpec(spec)
    94  	if pluginErr != nil {
    95  		t.Errorf("Can't find the plugin by name")
    96  	}
    97  }
    98  
    99  func doTestPlugin(t *testing.T, spec *volume.Spec, expectedDevice string) {
   100  	tmpDir, err := utiltesting.MkTmpdir("nfs_test")
   101  	if err != nil {
   102  		t.Fatalf("error creating temp dir: %v", err)
   103  	}
   104  	defer os.RemoveAll(tmpDir)
   105  
   106  	plugMgr := volume.VolumePluginMgr{}
   107  	plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
   108  	plug, err := plugMgr.FindPluginByName("kubernetes.io/nfs")
   109  	if err != nil {
   110  		t.Errorf("Can't find the plugin by name")
   111  	}
   112  	fake := mount.NewFakeMounter(nil)
   113  	pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
   114  	mounter, err := plug.(*nfsPlugin).newMounterInternal(spec, pod, fake)
   115  	if err != nil {
   116  		t.Errorf("Failed to make a new Mounter: %v", err)
   117  	}
   118  	if mounter == nil {
   119  		t.Errorf("Got a nil Mounter")
   120  	}
   121  	volumePath := mounter.GetPath()
   122  	expectedPath := filepath.Join(tmpDir, "pods/poduid/volumes/kubernetes.io~nfs/vol1")
   123  	if volumePath != expectedPath {
   124  		t.Errorf("Unexpected path, expected %q, got: %q", expectedPath, volumePath)
   125  	}
   126  	if err := mounter.SetUp(volume.MounterArgs{}); err != nil {
   127  		t.Errorf("Expected success, got: %v", err)
   128  	}
   129  	if _, err := os.Stat(volumePath); err != nil {
   130  		if os.IsNotExist(err) {
   131  			t.Errorf("SetUp() failed, volume path not created: %s", volumePath)
   132  		} else {
   133  			t.Errorf("SetUp() failed: %v", err)
   134  		}
   135  	}
   136  	if mounter.(*nfsMounter).readOnly {
   137  		t.Errorf("The volume source should not be read-only and it is.")
   138  	}
   139  	mntDevs, err := fake.List()
   140  	if err != nil {
   141  		t.Errorf("fakeMounter.List() failed: %v", err)
   142  	}
   143  	if len(mntDevs) != 1 {
   144  		t.Errorf("unexpected number of mounted devices. expected: %v, got %v", 1, len(mntDevs))
   145  	} else {
   146  		if mntDevs[0].Type != "nfs" {
   147  			t.Errorf("unexpected type of mounted devices. expected: %v, got %v", "nfs", mntDevs[0].Type)
   148  		}
   149  		if mntDevs[0].Device != expectedDevice {
   150  			t.Errorf("unexpected nfs device, expected %q, got: %q", expectedDevice, mntDevs[0].Device)
   151  		}
   152  	}
   153  	log := fake.GetLog()
   154  	if len(log) != 1 {
   155  		t.Errorf("Mount was not called exactly one time. It was called %d times.", len(log))
   156  	} else {
   157  		if log[0].Action != mount.FakeActionMount {
   158  			t.Errorf("Unexpected mounter action: %#v", log[0])
   159  		}
   160  	}
   161  	fake.ResetLog()
   162  
   163  	unmounter, err := plug.(*nfsPlugin).newUnmounterInternal("vol1", types.UID("poduid"), fake)
   164  	if err != nil {
   165  		t.Errorf("Failed to make a new Unmounter: %v", err)
   166  	}
   167  	if unmounter == nil {
   168  		t.Errorf("Got a nil Unmounter")
   169  	}
   170  	if err := unmounter.TearDown(); err != nil {
   171  		t.Errorf("Expected success, got: %v", err)
   172  	}
   173  	if _, err := os.Stat(volumePath); err == nil {
   174  		t.Errorf("TearDown() failed, volume path still exists: %s", volumePath)
   175  	} else if !os.IsNotExist(err) {
   176  		t.Errorf("TearDown() failed: %v", err)
   177  	}
   178  	log = fake.GetLog()
   179  	if len(log) != 1 {
   180  		t.Errorf("Unmount was not called exactly one time. It was called %d times.", len(log))
   181  	} else {
   182  		if log[0].Action != mount.FakeActionUnmount {
   183  			t.Errorf("Unexpected unmounter action: %#v", log[0])
   184  		}
   185  	}
   186  
   187  	fake.ResetLog()
   188  }
   189  
   190  func TestPluginVolume(t *testing.T) {
   191  	vol := &v1.Volume{
   192  		Name:         "vol1",
   193  		VolumeSource: v1.VolumeSource{NFS: &v1.NFSVolumeSource{Server: "localhost", Path: "/somepath", ReadOnly: false}},
   194  	}
   195  	doTestPlugin(t, volume.NewSpecFromVolume(vol), "localhost:/somepath")
   196  }
   197  
   198  func TestIPV6VolumeSource(t *testing.T) {
   199  	vol := &v1.Volume{
   200  		Name:         "vol1",
   201  		VolumeSource: v1.VolumeSource{NFS: &v1.NFSVolumeSource{Server: "0:0:0:0:0:0:0:1", Path: "/somepath", ReadOnly: false}},
   202  	}
   203  	doTestPlugin(t, volume.NewSpecFromVolume(vol), "[0:0:0:0:0:0:0:1]:/somepath")
   204  }
   205  
   206  func TestIPV4VolumeSource(t *testing.T) {
   207  	vol := &v1.Volume{
   208  		Name:         "vol1",
   209  		VolumeSource: v1.VolumeSource{NFS: &v1.NFSVolumeSource{Server: "127.0.0.1", Path: "/somepath", ReadOnly: false}},
   210  	}
   211  	doTestPlugin(t, volume.NewSpecFromVolume(vol), "127.0.0.1:/somepath")
   212  }
   213  
   214  func TestPluginPersistentVolume(t *testing.T) {
   215  	vol := &v1.PersistentVolume{
   216  		ObjectMeta: metav1.ObjectMeta{
   217  			Name: "vol1",
   218  		},
   219  		Spec: v1.PersistentVolumeSpec{
   220  			PersistentVolumeSource: v1.PersistentVolumeSource{
   221  				NFS: &v1.NFSVolumeSource{Server: "localhost", Path: "/somepath", ReadOnly: false},
   222  			},
   223  		},
   224  	}
   225  
   226  	doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false), "localhost:/somepath")
   227  }
   228  
   229  func TestPersistentClaimReadOnlyFlag(t *testing.T) {
   230  	tmpDir, err := utiltesting.MkTmpdir("nfs_test")
   231  	if err != nil {
   232  		t.Fatalf("error creating temp dir: %v", err)
   233  	}
   234  	defer os.RemoveAll(tmpDir)
   235  
   236  	pv := &v1.PersistentVolume{
   237  		ObjectMeta: metav1.ObjectMeta{
   238  			Name: "pvA",
   239  		},
   240  		Spec: v1.PersistentVolumeSpec{
   241  			PersistentVolumeSource: v1.PersistentVolumeSource{
   242  				NFS: &v1.NFSVolumeSource{},
   243  			},
   244  			ClaimRef: &v1.ObjectReference{
   245  				Name: "claimA",
   246  			},
   247  		},
   248  	}
   249  
   250  	claim := &v1.PersistentVolumeClaim{
   251  		ObjectMeta: metav1.ObjectMeta{
   252  			Name:      "claimA",
   253  			Namespace: "nsA",
   254  		},
   255  		Spec: v1.PersistentVolumeClaimSpec{
   256  			VolumeName: "pvA",
   257  		},
   258  		Status: v1.PersistentVolumeClaimStatus{
   259  			Phase: v1.ClaimBound,
   260  		},
   261  	}
   262  
   263  	client := fake.NewSimpleClientset(pv, claim)
   264  
   265  	plugMgr := volume.VolumePluginMgr{}
   266  	plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, client, nil))
   267  	plug, _ := plugMgr.FindPluginByName(nfsPluginName)
   268  
   269  	// readOnly bool is supplied by persistent-claim volume source when its mounter creates other volumes
   270  	spec := volume.NewSpecFromPersistentVolume(pv, true)
   271  	pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
   272  	mounter, _ := plug.NewMounter(spec, pod, volume.VolumeOptions{})
   273  	if mounter == nil {
   274  		t.Fatalf("Got a nil Mounter")
   275  	}
   276  
   277  	if !mounter.GetAttributes().ReadOnly {
   278  		t.Errorf("Expected true for mounter.IsReadOnly")
   279  	}
   280  }
   281  

View as plain text