Skip to content

Commit 0046b4c

Browse files
authored
Merge pull request kubernetes#88242 from jsafrane/cloning-test
Add block cloning test
2 parents cfa5f20 + 347d841 commit 0046b4c

File tree

2 files changed

+99
-14
lines changed

2 files changed

+99
-14
lines changed

test/e2e/storage/testsuites/provisioning.go

Lines changed: 98 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package testsuites
1919
import (
2020
"context"
2121
"fmt"
22+
"sync"
2223
"time"
2324

2425
"github.com/onsi/ginkgo"
@@ -74,6 +75,7 @@ func InitProvisioningTestSuite() TestSuite {
7475
Name: "provisioning",
7576
TestPatterns: []testpatterns.TestPattern{
7677
testpatterns.DefaultFsDynamicPV,
78+
testpatterns.BlockVolModeDynamicPV,
7779
testpatterns.NtfsDynamicPV,
7880
},
7981
SupportedSizeRange: volume.SizeRange{
@@ -115,6 +117,10 @@ func (p *provisioningTestSuite) DefineTests(driver TestDriver, pattern testpatte
115117
if pattern.VolType != testpatterns.DynamicPV {
116118
e2eskipper.Skipf("Suite %q does not support %v", p.tsInfo.Name, pattern.VolType)
117119
}
120+
if pattern.VolMode == v1.PersistentVolumeBlock && !dInfo.Capabilities[CapBlock] {
121+
e2eskipper.Skipf("Driver %q does not support block volumes - skipping", dInfo.Name)
122+
}
123+
118124
ok := false
119125
dDriver, ok = driver.(DynamicPVTestDriver)
120126
if !ok {
@@ -147,10 +153,12 @@ func (p *provisioningTestSuite) DefineTests(driver TestDriver, pattern testpatte
147153
l.pvc = e2epv.MakePersistentVolumeClaim(e2epv.PersistentVolumeClaimConfig{
148154
ClaimSize: claimSize,
149155
StorageClassName: &(l.sc.Name),
156+
VolumeMode: &pattern.VolMode,
150157
}, l.config.Framework.Namespace.Name)
151158
l.sourcePVC = e2epv.MakePersistentVolumeClaim(e2epv.PersistentVolumeClaimConfig{
152159
ClaimSize: claimSize,
153160
StorageClassName: &(l.sc.Name),
161+
VolumeMode: &pattern.VolMode,
154162
}, l.config.Framework.Namespace.Name)
155163
framework.Logf("In creating storage class object and pvc objects for driver - sc: %v, pvc: %v, src-pvc: %v", l.sc, l.pvc, l.sourcePVC)
156164
l.testCase = &StorageClassTest{
@@ -160,6 +168,7 @@ func (p *provisioningTestSuite) DefineTests(driver TestDriver, pattern testpatte
160168
Class: l.sc,
161169
ClaimSize: claimSize,
162170
ExpectedSize: claimSize,
171+
VolumeMode: pattern.VolMode,
163172
}
164173
}
165174

@@ -175,6 +184,9 @@ func (p *provisioningTestSuite) DefineTests(driver TestDriver, pattern testpatte
175184
if dInfo.SupportedMountOption == nil {
176185
e2eskipper.Skipf("Driver %q does not define supported mount option - skipping", dInfo.Name)
177186
}
187+
if pattern.VolMode == v1.PersistentVolumeBlock {
188+
e2eskipper.Skipf("Block volumes do not support mount options - skipping")
189+
}
178190

179191
init()
180192
defer cleanup()
@@ -212,26 +224,85 @@ func (p *provisioningTestSuite) DefineTests(driver TestDriver, pattern testpatte
212224
}
213225
l.testCase.TestDynamicProvisioning()
214226
})
227+
215228
ginkgo.It("should provision storage with pvc data source", func() {
216229
if !dInfo.Capabilities[CapPVCDataSource] {
217230
e2eskipper.Skipf("Driver %q does not support cloning - skipping", dInfo.Name)
218231
}
219-
220232
init()
221233
defer cleanup()
222234

223-
dc := l.config.Framework.DynamicClient
224-
dataSource, dataSourceCleanup := preparePVCDataSourceForProvisioning(l.config.ClientNodeSelection, l.cs, dc, l.sourcePVC, l.sc)
235+
testConfig := convertTestConfig(l.config)
236+
expectedContent := fmt.Sprintf("Hello from namespace %s", f.Namespace.Name)
237+
dataSource, dataSourceCleanup := preparePVCDataSourceForProvisioning(f, testConfig, l.cs, l.sourcePVC, l.sc, pattern.VolMode, expectedContent)
225238
defer dataSourceCleanup()
226239

227240
l.pvc.Spec.DataSource = dataSource
228241
l.testCase.PvCheck = func(claim *v1.PersistentVolumeClaim) {
229242
ginkgo.By("checking whether the created volume has the pre-populated data")
230-
command := fmt.Sprintf("grep '%s' /mnt/test/initialData", claim.Namespace)
231-
RunInPodWithVolume(l.cs, claim.Namespace, claim.Name, "pvc-datasource-tester", command, l.config.ClientNodeSelection)
243+
tests := []volume.Test{
244+
{
245+
Volume: *createVolumeSource(claim.Name, false /* readOnly */),
246+
Mode: pattern.VolMode,
247+
File: "index.html",
248+
ExpectedContent: expectedContent,
249+
},
250+
}
251+
volume.TestVolumeClient(f, testConfig, nil, "", tests)
232252
}
233253
l.testCase.TestDynamicProvisioning()
234254
})
255+
256+
ginkgo.It("should provision storage with pvc data source in parallel [Slow]", func() {
257+
// Test cloning a single volume multiple times.
258+
if !dInfo.Capabilities[CapPVCDataSource] {
259+
e2eskipper.Skipf("Driver %q does not support cloning - skipping", dInfo.Name)
260+
}
261+
if pattern.VolMode == v1.PersistentVolumeBlock && !dInfo.Capabilities[CapBlock] {
262+
e2eskipper.Skipf("Driver %q does not support block volumes - skipping", dInfo.Name)
263+
}
264+
265+
init()
266+
defer cleanup()
267+
268+
testConfig := convertTestConfig(l.config)
269+
expectedContent := fmt.Sprintf("Hello from namespace %s", f.Namespace.Name)
270+
dataSource, dataSourceCleanup := preparePVCDataSourceForProvisioning(f, testConfig, l.cs, l.sourcePVC, l.sc, pattern.VolMode, expectedContent)
271+
defer dataSourceCleanup()
272+
l.pvc.Spec.DataSource = dataSource
273+
274+
var wg sync.WaitGroup
275+
for i := 0; i < 5; i++ {
276+
wg.Add(1)
277+
go func(i int) {
278+
defer ginkgo.GinkgoRecover()
279+
defer wg.Done()
280+
ginkgo.By(fmt.Sprintf("Cloning volume nr. %d", i))
281+
// Each go routine must have its own pod prefix
282+
myTestConfig := testConfig
283+
myTestConfig.Prefix = fmt.Sprintf("%s-%d", myTestConfig.Prefix, i)
284+
285+
// Each go routine must have its own testCase copy to store their claim
286+
myTestCase := *l.testCase
287+
myTestCase.Claim = myTestCase.Claim.DeepCopy()
288+
myTestCase.Class = nil // Do not create/delete the storage class in TestDynamicProvisioning, it already exists.
289+
myTestCase.PvCheck = func(claim *v1.PersistentVolumeClaim) {
290+
ginkgo.By(fmt.Sprintf("checking whether the created volume %d has the pre-populated data", i))
291+
tests := []volume.Test{
292+
{
293+
Volume: *createVolumeSource(claim.Name, false /* readOnly */),
294+
Mode: pattern.VolMode,
295+
File: "index.html",
296+
ExpectedContent: expectedContent,
297+
},
298+
}
299+
volume.TestVolumeClient(f, myTestConfig, nil, "", tests)
300+
}
301+
myTestCase.TestDynamicProvisioning()
302+
}(i)
303+
}
304+
wg.Wait()
305+
})
235306
}
236307

237308
// TestDynamicProvisioning tests dynamic provisioning with specified StorageClassTest
@@ -701,27 +772,34 @@ func prepareSnapshotDataSourceForProvisioning(
701772
}
702773

703774
func preparePVCDataSourceForProvisioning(
704-
node e2epod.NodeSelection,
775+
f *framework.Framework,
776+
config volume.TestConfig,
705777
client clientset.Interface,
706-
dynamicClient dynamic.Interface,
707778
source *v1.PersistentVolumeClaim,
708779
class *storagev1.StorageClass,
780+
mode v1.PersistentVolumeMode,
781+
injectContent string,
709782
) (*v1.TypedLocalObjectReference, func()) {
710783
var err error
711784
if class != nil {
712785
ginkgo.By("[Initialize dataSource]creating a StorageClass " + class.Name)
713-
_, err = client.StorageV1().StorageClasses().Create(context.TODO(), class, metav1.CreateOptions{})
786+
class, err = client.StorageV1().StorageClasses().Create(context.TODO(), class, metav1.CreateOptions{})
714787
framework.ExpectNoError(err)
715788
}
716789

717790
ginkgo.By("[Initialize dataSource]creating a source PVC")
718791
sourcePVC, err := client.CoreV1().PersistentVolumeClaims(source.Namespace).Create(context.TODO(), source, metav1.CreateOptions{})
719792
framework.ExpectNoError(err)
720793

721-
// write namespace to the /mnt/test (= the volume).
722-
ginkgo.By("[Initialize dataSource]write data to volume")
723-
command := fmt.Sprintf("echo '%s' > /mnt/test/initialData", sourcePVC.GetNamespace())
724-
RunInPodWithVolume(client, sourcePVC.Namespace, sourcePVC.Name, "pvc-datasource-writer", command, node)
794+
tests := []volume.Test{
795+
{
796+
Volume: *createVolumeSource(sourcePVC.Name, false /* readOnly */),
797+
Mode: mode,
798+
File: "index.html",
799+
ExpectedContent: injectContent,
800+
},
801+
}
802+
volume.InjectContent(f, config, nil, "", tests)
725803

726804
dataSourceRef := &v1.TypedLocalObjectReference{
727805
Kind: "PersistentVolumeClaim",
@@ -730,10 +808,17 @@ func preparePVCDataSourceForProvisioning(
730808

731809
cleanupFunc := func() {
732810
framework.Logf("deleting source PVC %q/%q", sourcePVC.Namespace, sourcePVC.Name)
733-
err = client.CoreV1().PersistentVolumeClaims(sourcePVC.Namespace).Delete(context.TODO(), sourcePVC.Name, nil)
811+
err := client.CoreV1().PersistentVolumeClaims(sourcePVC.Namespace).Delete(context.TODO(), sourcePVC.Name, nil)
734812
if err != nil && !apierrors.IsNotFound(err) {
735813
framework.Failf("Error deleting source PVC %q. Error: %v", sourcePVC.Name, err)
736814
}
815+
if class != nil {
816+
framework.Logf("deleting class %q", class.Name)
817+
err := client.StorageV1().StorageClasses().Delete(context.TODO(), class.Name, nil)
818+
if err != nil && !apierrors.IsNotFound(err) {
819+
framework.Failf("Error deleting storage class %q. Error: %v", class.Name, err)
820+
}
821+
}
737822
}
738823

739824
return dataSourceRef, cleanupFunc

test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-plugin.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ spec:
6565
name: csi-data-dir
6666

6767
- name: hostpath
68-
image: quay.io/k8scsi/hostpathplugin:v1.3.0-rc1
68+
image: quay.io/k8scsi/hostpathplugin:v1.4.0-rc1
6969
args:
7070
- "--drivername=hostpath.csi.k8s.io"
7171
- "--v=5"

0 commit comments

Comments
 (0)