Skip to content

Commit 8b4fd41

Browse files
authored
Merge pull request kubernetes#81960 from pohly/ephemeral-tests
ephemeral volume tests
2 parents f0c600d + 5088b2e commit 8b4fd41

File tree

26 files changed

+390
-209
lines changed

26 files changed

+390
-209
lines changed

test/e2e/storage/csi_mock_volume.go

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -370,10 +370,14 @@ var _ = utils.SIGDescribe("CSI mock volume", func() {
370370
framework.ExpectNoError(err, "failed to test for CSIInlineVolumes")
371371
}
372372

373+
ginkgo.By("Deleting the previously created pod")
374+
err = e2epod.DeletePodWithWait(m.cs, pod)
375+
framework.ExpectNoError(err, "while deleting")
376+
373377
ginkgo.By("Checking CSI driver logs")
374378
// The driver is deployed as a statefulset with stable pod names
375379
driverPodName := "csi-mockplugin-0"
376-
err = checkPodInfo(m.cs, f.Namespace.Name, driverPodName, "mock", pod, test.expectPodInfo, test.expectEphemeral, csiInlineVolumesEnabled)
380+
err = checkPodLogs(m.cs, f.Namespace.Name, driverPodName, "mock", pod, test.expectPodInfo, test.expectEphemeral, csiInlineVolumesEnabled)
377381
framework.ExpectNoError(err)
378382
})
379383
}
@@ -719,8 +723,9 @@ func startPausePodWithVolumeSource(cs clientset.Interface, volumeSource v1.Volum
719723
return cs.CoreV1().Pods(ns).Create(pod)
720724
}
721725

722-
// checkPodInfo tests that NodePublish was called with expected volume_context
723-
func checkPodInfo(cs clientset.Interface, namespace, driverPodName, driverContainerName string, pod *v1.Pod, expectPodInfo, ephemeralVolume, csiInlineVolumesEnabled bool) error {
726+
// checkPodLogs tests that NodePublish was called with expected volume_context and (for ephemeral inline volumes)
727+
// has the matching NodeUnpublish
728+
func checkPodLogs(cs clientset.Interface, namespace, driverPodName, driverContainerName string, pod *v1.Pod, expectPodInfo, ephemeralVolume, csiInlineVolumesEnabled bool) error {
724729
expectedAttributes := map[string]string{
725730
"csi.storage.k8s.io/pod.name": pod.Name,
726731
"csi.storage.k8s.io/pod.namespace": namespace,
@@ -741,6 +746,8 @@ func checkPodInfo(cs clientset.Interface, namespace, driverPodName, driverContai
741746
// Find NodePublish in the logs
742747
foundAttributes := sets.NewString()
743748
logLines := strings.Split(log, "\n")
749+
numNodePublishVolume := 0
750+
numNodeUnpublishVolume := 0
744751
for _, line := range logLines {
745752
if !strings.HasPrefix(line, "gRPCCall:") {
746753
continue
@@ -759,19 +766,23 @@ func checkPodInfo(cs clientset.Interface, namespace, driverPodName, driverContai
759766
e2elog.Logf("Could not parse CSI driver log line %q: %s", line, err)
760767
continue
761768
}
762-
if call.Method != "/csi.v1.Node/NodePublishVolume" {
763-
continue
764-
}
765-
// Check that NodePublish had expected attributes
766-
for k, v := range expectedAttributes {
767-
vv, found := call.Request.VolumeContext[k]
768-
if found && v == vv {
769-
foundAttributes.Insert(k)
770-
e2elog.Logf("Found volume attribute %s: %s", k, v)
769+
switch call.Method {
770+
case "/csi.v1.Node/NodePublishVolume":
771+
numNodePublishVolume++
772+
if numNodePublishVolume == 1 {
773+
// Check that NodePublish had expected attributes for first volume
774+
for k, v := range expectedAttributes {
775+
vv, found := call.Request.VolumeContext[k]
776+
if found && v == vv {
777+
foundAttributes.Insert(k)
778+
e2elog.Logf("Found volume attribute %s: %s", k, v)
779+
}
780+
}
771781
}
782+
case "/csi.v1.Node/NodeUnpublishVolume":
783+
e2elog.Logf("Found NodeUnpublishVolume: %+v", call)
784+
numNodeUnpublishVolume++
772785
}
773-
// Process just the first NodePublish, the rest of the log is useless.
774-
break
775786
}
776787
if expectPodInfo {
777788
if foundAttributes.Len() != len(expectedAttributes) {
@@ -782,6 +793,9 @@ func checkPodInfo(cs clientset.Interface, namespace, driverPodName, driverContai
782793
if foundAttributes.Len() != 0 {
783794
return fmt.Errorf("some unexpected volume attributes were found: %+v", foundAttributes.List())
784795
}
796+
if numNodePublishVolume != numNodeUnpublishVolume {
797+
return fmt.Errorf("number of NodePublishVolume %d != number of NodeUnpublishVolume %d", numNodePublishVolume, numNodeUnpublishVolume)
798+
}
785799
return nil
786800
}
787801

test/e2e/storage/csi_volumes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ var csiTestDrivers = []func() testsuites.TestDriver{
4242

4343
// List of testSuites to be executed in below loop
4444
var csiTestSuites = []func() testsuites.TestSuite{
45+
testsuites.InitEphemeralTestSuite,
4546
testsuites.InitVolumesTestSuite,
4647
testsuites.InitVolumeIOTestSuite,
4748
testsuites.InitVolumeModeTestSuite,

test/e2e/storage/drivers/csi.go

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,12 @@ const (
6262

6363
// hostpathCSI
6464
type hostpathCSIDriver struct {
65-
driverInfo testsuites.DriverInfo
66-
manifests []string
65+
driverInfo testsuites.DriverInfo
66+
manifests []string
67+
volumeAttributes []map[string]string
6768
}
6869

69-
func initHostPathCSIDriver(name string, capabilities map[testsuites.Capability]bool, manifests ...string) testsuites.TestDriver {
70+
func initHostPathCSIDriver(name string, capabilities map[testsuites.Capability]bool, volumeAttributes []map[string]string, manifests ...string) testsuites.TestDriver {
7071
return &hostpathCSIDriver{
7172
driverInfo: testsuites.DriverInfo{
7273
Name: name,
@@ -77,13 +78,15 @@ func initHostPathCSIDriver(name string, capabilities map[testsuites.Capability]b
7778
),
7879
Capabilities: capabilities,
7980
},
80-
manifests: manifests,
81+
manifests: manifests,
82+
volumeAttributes: volumeAttributes,
8183
}
8284
}
8385

8486
var _ testsuites.TestDriver = &hostpathCSIDriver{}
8587
var _ testsuites.DynamicPVTestDriver = &hostpathCSIDriver{}
8688
var _ testsuites.SnapshottableTestDriver = &hostpathCSIDriver{}
89+
var _ testsuites.EphemeralTestDriver = &hostpathCSIDriver{}
8790

8891
// InitHostPathCSIDriver returns hostpathCSIDriver that implements TestDriver interface
8992
func InitHostPathCSIDriver() testsuites.TestDriver {
@@ -97,16 +100,20 @@ func InitHostPathCSIDriver() testsuites.TestDriver {
97100
}
98101
return initHostPathCSIDriver("csi-hostpath",
99102
capabilities,
100-
"test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml",
103+
// Volume attributes don't matter, but we have to provide at least one map.
104+
[]map[string]string{
105+
{"foo": "bar"},
106+
},
101107
"test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml",
102108
"test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml",
103109
"test/e2e/testing-manifests/storage-csi/external-snapshotter/rbac.yaml",
104110
"test/e2e/testing-manifests/storage-csi/external-resizer/rbac.yaml",
105111
"test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-attacher.yaml",
112+
"test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-driverinfo.yaml",
113+
"test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-plugin.yaml",
106114
"test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-provisioner.yaml",
107-
"test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-snapshotter.yaml",
108115
"test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-resizer.yaml",
109-
"test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpathplugin.yaml",
116+
"test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-snapshotter.yaml",
110117
"test/e2e/testing-manifests/storage-csi/hostpath/hostpath/e2e-test-rbac.yaml",
111118
)
112119
}
@@ -116,6 +123,9 @@ func (h *hostpathCSIDriver) GetDriverInfo() *testsuites.DriverInfo {
116123
}
117124

118125
func (h *hostpathCSIDriver) SkipUnsupportedTest(pattern testpatterns.TestPattern) {
126+
if pattern.VolType == testpatterns.CSIInlineVolume && len(h.volumeAttributes) == 0 {
127+
framework.Skipf("%s has no volume attributes defined, doesn't support ephemeral inline volumes", h.driverInfo.Name)
128+
}
119129
}
120130

121131
func (h *hostpathCSIDriver) GetDynamicProvisionStorageClass(config *testsuites.PerTestConfig, fsType string) *storagev1.StorageClass {
@@ -127,6 +137,14 @@ func (h *hostpathCSIDriver) GetDynamicProvisionStorageClass(config *testsuites.P
127137
return testsuites.GetStorageClass(provisioner, parameters, nil, ns, suffix)
128138
}
129139

140+
func (h *hostpathCSIDriver) GetVolume(config *testsuites.PerTestConfig, volumeNumber int) (map[string]string, bool, bool) {
141+
return h.volumeAttributes[volumeNumber%len(h.volumeAttributes)], false /* not shared */, false /* read-write */
142+
}
143+
144+
func (h *hostpathCSIDriver) GetCSIDriverName(config *testsuites.PerTestConfig) string {
145+
return config.GetUniqueDriverName()
146+
}
147+
130148
func (h *hostpathCSIDriver) GetSnapshotClass(config *testsuites.PerTestConfig) *unstructured.Unstructured {
131149
snapshotter := config.GetUniqueDriverName()
132150
parameters := map[string]string{}
@@ -205,7 +223,6 @@ var _ testsuites.DynamicPVTestDriver = &mockCSIDriver{}
205223
// InitMockCSIDriver returns a mockCSIDriver that implements TestDriver interface
206224
func InitMockCSIDriver(driverOpts CSIMockDriverOpts) testsuites.TestDriver {
207225
driverManifests := []string{
208-
"test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml",
209226
"test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml",
210227
"test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml",
211228
"test/e2e/testing-manifests/storage-csi/external-resizer/rbac.yaml",
@@ -305,7 +322,7 @@ func (m *mockCSIDriver) PrepareTest(f *framework.Framework) (*testsuites.PerTest
305322
NodeName: config.ClientNodeName,
306323
PodInfo: m.podInfo,
307324
CanAttach: &m.attachable,
308-
VolumeLifecycleModes: []storagev1beta1.VolumeLifecycleMode{
325+
VolumeLifecycleModes: &[]storagev1beta1.VolumeLifecycleMode{
309326
storagev1beta1.VolumeLifecyclePersistent,
310327
storagev1beta1.VolumeLifecycleEphemeral,
311328
},
@@ -329,7 +346,10 @@ func (m *mockCSIDriver) PrepareTest(f *framework.Framework) (*testsuites.PerTest
329346
func InitHostPathV0CSIDriver() testsuites.TestDriver {
330347
return initHostPathCSIDriver("csi-hostpath-v0",
331348
map[testsuites.Capability]bool{testsuites.CapPersistence: true, testsuites.CapMultiPODs: true},
332-
"test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml",
349+
nil, /* no volume attributes -> no ephemeral volume testing */
350+
// Using the current set of rbac.yaml files is problematic here because they don't
351+
// match the version of the rules that were written for the releases of external-attacher
352+
// and external-provisioner that we are using here. It happens to work in practice...
333353
"test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml",
334354
"test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml",
335355
"test/e2e/testing-manifests/storage-csi/hostpath/hostpath-v0/csi-hostpath-attacher.yaml",
@@ -423,7 +443,6 @@ func (g *gcePDCSIDriver) PrepareTest(f *framework.Framework) (*testsuites.PerTes
423443
createGCESecrets(f.ClientSet, f.Namespace.Name)
424444

425445
manifests := []string{
426-
"test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml",
427446
"test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml",
428447
"test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml",
429448
"test/e2e/testing-manifests/storage-csi/gce-pd/csi-controller-rbac.yaml",

test/e2e/storage/external/external.go

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,25 @@ type driverDefinition struct {
179179
// TODO (?): load from file
180180
}
181181

182-
// InlineVolumeAttributes defines one or more set of attributes for
183-
// use as inline ephemeral volumes. At least one set of attributes
184-
// has to be defined to enable testing of inline ephemeral volumes.
185-
// If a test needs more volumes than defined, some of the defined
182+
// InlineVolumes defines one or more volumes for use as inline
183+
// ephemeral volumes. At least one such volume has to be
184+
// defined to enable testing of inline ephemeral volumes. If
185+
// a test needs more volumes than defined, some of the defined
186186
// volumes will be used multiple times.
187187
//
188188
// DriverInfo.Name is used as name of the driver in the inline volume.
189-
InlineVolumeAttributes []map[string]string
189+
InlineVolumes []struct {
190+
// Attributes are passed as NodePublishVolumeReq.volume_context.
191+
// Can be empty.
192+
Attributes map[string]string
193+
// Shared defines whether the resulting volume is
194+
// shared between different pods (i.e. changes made
195+
// in one pod are visible in another)
196+
Shared bool
197+
// ReadOnly must be set to true if the driver does not
198+
// support mounting as read/write.
199+
ReadOnly bool
200+
}
190201

191202
// ClaimSize defines the desired size of dynamically
192203
// provisioned volumes. Default is "5GiB".
@@ -221,7 +232,7 @@ func (d *driverDefinition) SkipUnsupportedTest(pattern testpatterns.TestPattern)
221232
supported = true
222233
}
223234
case testpatterns.CSIInlineVolume:
224-
supported = len(d.InlineVolumeAttributes) != 0
235+
supported = len(d.InlineVolumes) != 0
225236
}
226237
if !supported {
227238
framework.Skipf("Driver %q does not support volume type %q - skipping", d.DriverInfo.Name, pattern.VolType)
@@ -294,11 +305,12 @@ func (d *driverDefinition) GetClaimSize() string {
294305
return d.ClaimSize
295306
}
296307

297-
func (d *driverDefinition) GetVolumeAttributes(config *testsuites.PerTestConfig, volumeNumber int) map[string]string {
298-
if len(d.InlineVolumeAttributes) == 0 {
308+
func (d *driverDefinition) GetVolume(config *testsuites.PerTestConfig, volumeNumber int) (map[string]string, bool, bool) {
309+
if len(d.InlineVolumes) == 0 {
299310
framework.Skipf("%s does not have any InlineVolumeAttributes defined", d.DriverInfo.Name)
300311
}
301-
return d.InlineVolumeAttributes[volumeNumber%len(d.InlineVolumeAttributes)]
312+
volume := d.InlineVolumes[volumeNumber%len(d.InlineVolumes)]
313+
return volume.Attributes, volume.Shared, volume.ReadOnly
302314
}
303315

304316
func (d *driverDefinition) GetCSIDriverName(config *testsuites.PerTestConfig) string {

0 commit comments

Comments
 (0)