...

Source file src/k8s.io/kubernetes/pkg/volume/iscsi/iscsi_test.go

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

     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 iscsi
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"path/filepath"
    23  	"strings"
    24  	"testing"
    25  
    26  	"k8s.io/mount-utils"
    27  	"k8s.io/utils/exec/testing"
    28  
    29  	v1 "k8s.io/api/core/v1"
    30  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    31  	"k8s.io/apimachinery/pkg/types"
    32  	"k8s.io/client-go/kubernetes/fake"
    33  	utiltesting "k8s.io/client-go/util/testing"
    34  	"k8s.io/kubernetes/pkg/volume"
    35  	volumetest "k8s.io/kubernetes/pkg/volume/testing"
    36  )
    37  
    38  func TestCanSupport(t *testing.T) {
    39  	tmpDir, err := utiltesting.MkTmpdir("iscsi_test")
    40  	if err != nil {
    41  		t.Fatalf("error creating temp dir: %v", err)
    42  	}
    43  	defer os.RemoveAll(tmpDir)
    44  
    45  	plugMgr := volume.VolumePluginMgr{}
    46  	plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
    47  
    48  	plug, err := plugMgr.FindPluginByName("kubernetes.io/iscsi")
    49  	if err != nil {
    50  		t.Fatal("Can't find the plugin by name")
    51  	}
    52  	if plug.GetPluginName() != "kubernetes.io/iscsi" {
    53  		t.Errorf("Wrong name: %s", plug.GetPluginName())
    54  	}
    55  	if plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{}}}) {
    56  		t.Errorf("Expected false")
    57  	}
    58  	if plug.CanSupport(&volume.Spec{}) {
    59  		t.Errorf("Expected false")
    60  	}
    61  	if !plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{ISCSI: &v1.ISCSIVolumeSource{}}}}) {
    62  		t.Errorf("Expected true")
    63  	}
    64  	if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{}}}) {
    65  		t.Errorf("Expected false")
    66  	}
    67  	if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{}}}}) {
    68  		t.Errorf("Expected false")
    69  	}
    70  	if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{ISCSI: &v1.ISCSIPersistentVolumeSource{}}}}}) {
    71  		t.Errorf("Expected true")
    72  	}
    73  }
    74  
    75  func TestGetAccessModes(t *testing.T) {
    76  	tmpDir, err := utiltesting.MkTmpdir("iscsi_test")
    77  	if err != nil {
    78  		t.Fatalf("error creating temp dir: %v", err)
    79  	}
    80  	defer os.RemoveAll(tmpDir)
    81  
    82  	plugMgr := volume.VolumePluginMgr{}
    83  	plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
    84  
    85  	plug, err := plugMgr.FindPersistentPluginByName("kubernetes.io/iscsi")
    86  	if err != nil {
    87  		t.Errorf("Can't find the plugin by name")
    88  	}
    89  	if !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteOnce) || !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadOnlyMany) {
    90  		t.Errorf("Expected two AccessModeTypes:  %s and %s", v1.ReadWriteOnce, v1.ReadOnlyMany)
    91  	}
    92  }
    93  
    94  type fakeDiskManager struct {
    95  	tmpDir string
    96  }
    97  
    98  func NewFakeDiskManager() *fakeDiskManager {
    99  	return &fakeDiskManager{
   100  		tmpDir: utiltesting.MkTmpdirOrDie("iscsi_test"),
   101  	}
   102  }
   103  
   104  func (fake *fakeDiskManager) Cleanup() {
   105  	os.RemoveAll(fake.tmpDir)
   106  }
   107  
   108  func (fake *fakeDiskManager) MakeGlobalPDName(disk iscsiDisk) string {
   109  	return fake.tmpDir
   110  }
   111  
   112  func (fake *fakeDiskManager) MakeGlobalVDPDName(disk iscsiDisk) string {
   113  	return fake.tmpDir
   114  }
   115  
   116  func (fake *fakeDiskManager) AttachDisk(b iscsiDiskMounter) (string, error) {
   117  	globalPath := b.manager.MakeGlobalPDName(*b.iscsiDisk)
   118  	err := os.MkdirAll(globalPath, 0750)
   119  	if err != nil {
   120  		return "", err
   121  	}
   122  	// Simulate the global mount so that the fakeMounter returns the
   123  	// expected number of mounts for the attached disk.
   124  	b.mounter.MountSensitiveWithoutSystemd(globalPath, globalPath, b.fsType, nil, nil)
   125  
   126  	return "/dev/sdb", nil
   127  }
   128  
   129  func (fake *fakeDiskManager) DetachDisk(c iscsiDiskUnmounter, mntPath string) error {
   130  	globalPath := c.manager.MakeGlobalPDName(*c.iscsiDisk)
   131  	err := os.RemoveAll(globalPath)
   132  	if err != nil {
   133  		return err
   134  	}
   135  	return nil
   136  }
   137  
   138  func (fake *fakeDiskManager) DetachBlockISCSIDisk(c iscsiDiskUnmapper, mntPath string) error {
   139  	globalPath := c.manager.MakeGlobalVDPDName(*c.iscsiDisk)
   140  	err := os.RemoveAll(globalPath)
   141  	if err != nil {
   142  		return err
   143  	}
   144  	return nil
   145  }
   146  
   147  func doTestPlugin(t *testing.T, spec *volume.Spec) {
   148  	tmpDir, err := utiltesting.MkTmpdir("iscsi_test")
   149  	if err != nil {
   150  		t.Fatalf("error creating temp dir: %v", err)
   151  	}
   152  	defer os.RemoveAll(tmpDir)
   153  
   154  	plugMgr := volume.VolumePluginMgr{}
   155  	plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
   156  
   157  	plug, err := plugMgr.FindPluginByName("kubernetes.io/iscsi")
   158  	if err != nil {
   159  		t.Errorf("Can't find the plugin by name")
   160  	}
   161  	fakeManager := NewFakeDiskManager()
   162  	defer fakeManager.Cleanup()
   163  	fakeMounter := mount.NewFakeMounter(nil)
   164  	fakeExec := &testingexec.FakeExec{}
   165  	mounter, err := plug.(*iscsiPlugin).newMounterInternal(spec, types.UID("poduid"), fakeManager, fakeMounter, fakeExec, nil)
   166  	if err != nil {
   167  		t.Errorf("Failed to make a new Mounter: %v", err)
   168  	}
   169  	if mounter == nil {
   170  		t.Error("Got a nil Mounter")
   171  	}
   172  
   173  	path := mounter.GetPath()
   174  	expectedPath := filepath.Join(tmpDir, "pods/poduid/volumes/kubernetes.io~iscsi/vol1")
   175  	if path != expectedPath {
   176  		t.Errorf("Unexpected path, expected %q, got: %q", expectedPath, path)
   177  	}
   178  
   179  	if err := mounter.SetUp(volume.MounterArgs{}); err != nil {
   180  		t.Errorf("Expected success, got: %v", err)
   181  	}
   182  	if _, err := os.Stat(path); err != nil {
   183  		if os.IsNotExist(err) {
   184  			t.Errorf("SetUp() failed, volume path not created: %s", path)
   185  		} else {
   186  			t.Errorf("SetUp() failed: %v", err)
   187  		}
   188  	}
   189  
   190  	fakeManager2 := NewFakeDiskManager()
   191  	defer fakeManager2.Cleanup()
   192  	unmounter, err := plug.(*iscsiPlugin).newUnmounterInternal("vol1", types.UID("poduid"), fakeManager2, fakeMounter, fakeExec)
   193  	if err != nil {
   194  		t.Errorf("Failed to make a new Unmounter: %v", err)
   195  	}
   196  	if unmounter == nil {
   197  		t.Error("Got a nil Unmounter")
   198  	}
   199  
   200  	if err := unmounter.TearDown(); err != nil {
   201  		t.Errorf("Expected success, got: %v", err)
   202  	}
   203  	if _, err := os.Stat(path); err == nil {
   204  		t.Errorf("TearDown() failed, volume path still exists: %s", path)
   205  	} else if !os.IsNotExist(err) {
   206  		t.Errorf("TearDown() failed: %v", err)
   207  	}
   208  }
   209  
   210  func TestPluginVolume(t *testing.T) {
   211  	vol := &v1.Volume{
   212  		Name: "vol1",
   213  		VolumeSource: v1.VolumeSource{
   214  			ISCSI: &v1.ISCSIVolumeSource{
   215  				TargetPortal: "127.0.0.1:3260",
   216  				IQN:          "iqn.2014-12.server:storage.target01",
   217  				FSType:       "ext4",
   218  				Lun:          0,
   219  			},
   220  		},
   221  	}
   222  	doTestPlugin(t, volume.NewSpecFromVolume(vol))
   223  }
   224  
   225  func TestPluginPersistentVolume(t *testing.T) {
   226  	vol := &v1.PersistentVolume{
   227  		ObjectMeta: metav1.ObjectMeta{
   228  			Name: "vol1",
   229  		},
   230  		Spec: v1.PersistentVolumeSpec{
   231  			PersistentVolumeSource: v1.PersistentVolumeSource{
   232  				ISCSI: &v1.ISCSIPersistentVolumeSource{
   233  					TargetPortal: "127.0.0.1:3260",
   234  					IQN:          "iqn.2014-12.server:storage.target01",
   235  					FSType:       "ext4",
   236  					Lun:          0,
   237  				},
   238  			},
   239  		},
   240  	}
   241  	doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false))
   242  }
   243  
   244  func TestPersistentClaimReadOnlyFlag(t *testing.T) {
   245  	tmpDir, err := utiltesting.MkTmpdir("iscsi_test")
   246  	if err != nil {
   247  		t.Fatalf("error creating temp dir: %v", err)
   248  	}
   249  	defer os.RemoveAll(tmpDir)
   250  
   251  	pv := &v1.PersistentVolume{
   252  		ObjectMeta: metav1.ObjectMeta{
   253  			Name: "pvA",
   254  		},
   255  		Spec: v1.PersistentVolumeSpec{
   256  			PersistentVolumeSource: v1.PersistentVolumeSource{
   257  				ISCSI: &v1.ISCSIPersistentVolumeSource{
   258  					TargetPortal: "127.0.0.1:3260",
   259  					IQN:          "iqn.2014-12.server:storage.target01",
   260  					FSType:       "ext4",
   261  					Lun:          0,
   262  				},
   263  			},
   264  			ClaimRef: &v1.ObjectReference{
   265  				Name: "claimA",
   266  			},
   267  		},
   268  	}
   269  
   270  	claim := &v1.PersistentVolumeClaim{
   271  		ObjectMeta: metav1.ObjectMeta{
   272  			Name:      "claimA",
   273  			Namespace: "nsA",
   274  		},
   275  		Spec: v1.PersistentVolumeClaimSpec{
   276  			VolumeName: "pvA",
   277  		},
   278  		Status: v1.PersistentVolumeClaimStatus{
   279  			Phase: v1.ClaimBound,
   280  		},
   281  	}
   282  
   283  	client := fake.NewSimpleClientset(pv, claim)
   284  
   285  	plugMgr := volume.VolumePluginMgr{}
   286  	plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, client, nil))
   287  	plug, _ := plugMgr.FindPluginByName(iscsiPluginName)
   288  
   289  	// readOnly bool is supplied by persistent-claim volume source when its mounter creates other volumes
   290  	spec := volume.NewSpecFromPersistentVolume(pv, true)
   291  	pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
   292  	mounter, _ := plug.NewMounter(spec, pod, volume.VolumeOptions{})
   293  	if mounter == nil {
   294  		t.Fatalf("Got a nil Mounter")
   295  	}
   296  
   297  	if !mounter.GetAttributes().ReadOnly {
   298  		t.Errorf("Expected true for mounter.IsReadOnly")
   299  	}
   300  }
   301  
   302  func TestPortalMounter(t *testing.T) {
   303  	if portal := portalMounter("127.0.0.1"); portal != "127.0.0.1:3260" {
   304  		t.Errorf("wrong portal: %s", portal)
   305  	}
   306  	if portal := portalMounter("127.0.0.1:3260"); portal != "127.0.0.1:3260" {
   307  		t.Errorf("wrong portal: %s", portal)
   308  	}
   309  }
   310  
   311  type testcase struct {
   312  	name      string
   313  	defaultNs string
   314  	spec      *volume.Spec
   315  	// Expected return of the test
   316  	expectedName          string
   317  	expectedNs            string
   318  	expectedIface         string
   319  	expectedError         error
   320  	expectedDiscoveryCHAP bool
   321  	expectedSessionCHAP   bool
   322  }
   323  
   324  func TestGetSecretNameAndNamespaceForPV(t *testing.T) {
   325  	tests := []testcase{
   326  		{
   327  			name:      "persistent volume source",
   328  			defaultNs: "default",
   329  			spec: &volume.Spec{
   330  				PersistentVolume: &v1.PersistentVolume{
   331  					Spec: v1.PersistentVolumeSpec{
   332  						PersistentVolumeSource: v1.PersistentVolumeSource{
   333  							ISCSI: &v1.ISCSIPersistentVolumeSource{
   334  								TargetPortal: "127.0.0.1:3260",
   335  								IQN:          "iqn.2014-12.server:storage.target01",
   336  								FSType:       "ext4",
   337  								Lun:          0,
   338  								SecretRef: &v1.SecretReference{
   339  									Name:      "name",
   340  									Namespace: "ns",
   341  								},
   342  							},
   343  						},
   344  					},
   345  				},
   346  			},
   347  			expectedName:  "name",
   348  			expectedNs:    "ns",
   349  			expectedError: nil,
   350  		},
   351  		{
   352  			name:      "persistent volume source without namespace",
   353  			defaultNs: "default",
   354  			spec: &volume.Spec{
   355  				PersistentVolume: &v1.PersistentVolume{
   356  					Spec: v1.PersistentVolumeSpec{
   357  						PersistentVolumeSource: v1.PersistentVolumeSource{
   358  							ISCSI: &v1.ISCSIPersistentVolumeSource{
   359  								TargetPortal: "127.0.0.1:3260",
   360  								IQN:          "iqn.2014-12.server:storage.target01",
   361  								FSType:       "ext4",
   362  								Lun:          0,
   363  								SecretRef: &v1.SecretReference{
   364  									Name: "name",
   365  								},
   366  							},
   367  						},
   368  					},
   369  				},
   370  			},
   371  			expectedName:  "name",
   372  			expectedNs:    "default",
   373  			expectedError: nil,
   374  		},
   375  		{
   376  			name:      "pod volume source",
   377  			defaultNs: "default",
   378  			spec: &volume.Spec{
   379  				Volume: &v1.Volume{
   380  					VolumeSource: v1.VolumeSource{
   381  						ISCSI: &v1.ISCSIVolumeSource{
   382  							TargetPortal: "127.0.0.1:3260",
   383  							IQN:          "iqn.2014-12.server:storage.target01",
   384  							FSType:       "ext4",
   385  							Lun:          0,
   386  						},
   387  					},
   388  				},
   389  			},
   390  			expectedName:  "",
   391  			expectedNs:    "",
   392  			expectedError: nil,
   393  		},
   394  	}
   395  	for _, testcase := range tests {
   396  		resultName, resultNs, err := getISCSISecretNameAndNamespace(testcase.spec, testcase.defaultNs)
   397  		if err != testcase.expectedError || resultName != testcase.expectedName || resultNs != testcase.expectedNs {
   398  			t.Errorf("%s failed: expected err=%v ns=%q name=%q, got %v/%q/%q", testcase.name, testcase.expectedError, testcase.expectedNs, testcase.expectedName,
   399  				err, resultNs, resultName)
   400  		}
   401  	}
   402  
   403  }
   404  
   405  func TestGetISCSIInitiatorInfo(t *testing.T) {
   406  	tests := []testcase{
   407  		{
   408  			name: "persistent volume source",
   409  			spec: &volume.Spec{
   410  				PersistentVolume: &v1.PersistentVolume{
   411  					Spec: v1.PersistentVolumeSpec{
   412  						PersistentVolumeSource: v1.PersistentVolumeSource{
   413  							ISCSI: &v1.ISCSIPersistentVolumeSource{
   414  								TargetPortal:   "127.0.0.1:3260",
   415  								IQN:            "iqn.2014-12.server:storage.target01",
   416  								FSType:         "ext4",
   417  								Lun:            0,
   418  								ISCSIInterface: "tcp",
   419  							},
   420  						},
   421  					},
   422  				},
   423  			},
   424  			expectedIface: "tcp",
   425  			expectedError: nil,
   426  		},
   427  		{
   428  			name: "pod volume source",
   429  			spec: &volume.Spec{
   430  				Volume: &v1.Volume{
   431  					VolumeSource: v1.VolumeSource{
   432  						ISCSI: &v1.ISCSIVolumeSource{
   433  							TargetPortal:   "127.0.0.1:3260",
   434  							IQN:            "iqn.2014-12.server:storage.target01",
   435  							FSType:         "ext4",
   436  							Lun:            0,
   437  							ISCSIInterface: "tcp",
   438  						},
   439  					},
   440  				},
   441  			},
   442  			expectedIface: "tcp",
   443  			expectedError: nil,
   444  		},
   445  	}
   446  	for _, testcase := range tests {
   447  		resultIface, _, err := getISCSIInitiatorInfo(testcase.spec)
   448  		if err != testcase.expectedError || resultIface != testcase.expectedIface {
   449  			t.Errorf("%s failed: expected err=%v iface=%s, got %v/%s", testcase.name, testcase.expectedError, testcase.expectedIface,
   450  				err, resultIface)
   451  		}
   452  	}
   453  }
   454  
   455  func TestGetISCSICHAP(t *testing.T) {
   456  	tests := []testcase{
   457  		{
   458  			name: "persistent volume source",
   459  			spec: &volume.Spec{
   460  				PersistentVolume: &v1.PersistentVolume{
   461  					Spec: v1.PersistentVolumeSpec{
   462  						PersistentVolumeSource: v1.PersistentVolumeSource{
   463  							ISCSI: &v1.ISCSIPersistentVolumeSource{
   464  								DiscoveryCHAPAuth: true,
   465  								SessionCHAPAuth:   true,
   466  							},
   467  						},
   468  					},
   469  				},
   470  			},
   471  			expectedDiscoveryCHAP: true,
   472  			expectedSessionCHAP:   true,
   473  			expectedError:         nil,
   474  		},
   475  		{
   476  			name: "pod volume source",
   477  			spec: &volume.Spec{
   478  				Volume: &v1.Volume{
   479  					VolumeSource: v1.VolumeSource{
   480  						ISCSI: &v1.ISCSIVolumeSource{
   481  							DiscoveryCHAPAuth: true,
   482  							SessionCHAPAuth:   true,
   483  						},
   484  					},
   485  				},
   486  			},
   487  			expectedDiscoveryCHAP: true,
   488  			expectedSessionCHAP:   true,
   489  			expectedError:         nil,
   490  		},
   491  		{
   492  			name:                  "no volume",
   493  			spec:                  &volume.Spec{},
   494  			expectedDiscoveryCHAP: false,
   495  			expectedSessionCHAP:   false,
   496  			expectedError:         fmt.Errorf("Spec does not reference an ISCSI volume type"),
   497  		},
   498  	}
   499  	for _, testcase := range tests {
   500  		resultDiscoveryCHAP, _ := getISCSIDiscoveryCHAPInfo(testcase.spec)
   501  		resultSessionCHAP, err := getISCSISessionCHAPInfo(testcase.spec)
   502  		switch testcase.name {
   503  		case "no volume":
   504  			if err == nil || err.Error() != testcase.expectedError.Error() || resultDiscoveryCHAP != testcase.expectedDiscoveryCHAP || resultSessionCHAP != testcase.expectedSessionCHAP {
   505  				t.Errorf("%s failed: expected err=%v DiscoveryCHAP=%v SessionCHAP=%v, got %v/%v/%v",
   506  					testcase.name, testcase.expectedError, testcase.expectedDiscoveryCHAP, testcase.expectedSessionCHAP,
   507  					err, resultDiscoveryCHAP, resultSessionCHAP)
   508  			}
   509  		default:
   510  			if err != testcase.expectedError || resultDiscoveryCHAP != testcase.expectedDiscoveryCHAP || resultSessionCHAP != testcase.expectedSessionCHAP {
   511  				t.Errorf("%s failed: expected err=%v DiscoveryCHAP=%v SessionCHAP=%v, got %v/%v/%v", testcase.name, testcase.expectedError, testcase.expectedDiscoveryCHAP, testcase.expectedSessionCHAP,
   512  					err, resultDiscoveryCHAP, resultSessionCHAP)
   513  			}
   514  		}
   515  	}
   516  }
   517  
   518  func TestGetVolumeSpec(t *testing.T) {
   519  	path := "plugins/kubernetes.io/iscsi/volumeDevices/iface-default/127.0.0.1:3260-iqn.2014-12.server:storage.target01-lun-0"
   520  	spec, _ := getVolumeSpecFromGlobalMapPath("test", path)
   521  
   522  	portal := spec.PersistentVolume.Spec.PersistentVolumeSource.ISCSI.TargetPortal
   523  	if portal != "127.0.0.1:3260" {
   524  		t.Errorf("wrong portal: %v", portal)
   525  	}
   526  	iqn := spec.PersistentVolume.Spec.PersistentVolumeSource.ISCSI.IQN
   527  	if iqn != "iqn.2014-12.server:storage.target01" {
   528  		t.Errorf("wrong iqn: %v", iqn)
   529  	}
   530  	lun := spec.PersistentVolume.Spec.PersistentVolumeSource.ISCSI.Lun
   531  	if lun != 0 {
   532  		t.Errorf("wrong lun: %v", lun)
   533  	}
   534  	iface := spec.PersistentVolume.Spec.PersistentVolumeSource.ISCSI.ISCSIInterface
   535  	if iface != "default" {
   536  		t.Errorf("wrong ISCSIInterface: %v", iface)
   537  	}
   538  }
   539  
   540  func TestGetVolumeSpec_no_lun(t *testing.T) {
   541  	path := "plugins/kubernetes.io/iscsi/volumeDevices/iface-default/127.0.0.1:3260-iqn.2014-12.server:storage.target01"
   542  	_, err := getVolumeSpecFromGlobalMapPath("test", path)
   543  	if !strings.Contains(err.Error(), "malformatted mnt path") {
   544  		t.Errorf("should get error: malformatted mnt path")
   545  	}
   546  }
   547  
   548  func TestGetVolumeSpec_no_iface(t *testing.T) {
   549  	path := "plugins/kubernetes.io/iscsi/volumeDevices/default/127.0.0.1:3260-iqn.2014-12.server:storage.target01-lun-0"
   550  	_, err := getVolumeSpecFromGlobalMapPath("test", path)
   551  	if !strings.Contains(err.Error(), "failed to retrieve iface") {
   552  		t.Errorf("should get error: failed to retrieve iface")
   553  	}
   554  }
   555  

View as plain text