@@ -19,6 +19,7 @@ package testsuites
19
19
import (
20
20
"context"
21
21
"fmt"
22
+ "sync"
22
23
"time"
23
24
24
25
"github.com/onsi/ginkgo"
@@ -74,6 +75,7 @@ func InitProvisioningTestSuite() TestSuite {
74
75
Name : "provisioning" ,
75
76
TestPatterns : []testpatterns.TestPattern {
76
77
testpatterns .DefaultFsDynamicPV ,
78
+ testpatterns .BlockVolModeDynamicPV ,
77
79
testpatterns .NtfsDynamicPV ,
78
80
},
79
81
SupportedSizeRange : volume.SizeRange {
@@ -115,6 +117,10 @@ func (p *provisioningTestSuite) DefineTests(driver TestDriver, pattern testpatte
115
117
if pattern .VolType != testpatterns .DynamicPV {
116
118
e2eskipper .Skipf ("Suite %q does not support %v" , p .tsInfo .Name , pattern .VolType )
117
119
}
120
+ if pattern .VolMode == v1 .PersistentVolumeBlock && ! dInfo .Capabilities [CapBlock ] {
121
+ e2eskipper .Skipf ("Driver %q does not support block volumes - skipping" , dInfo .Name )
122
+ }
123
+
118
124
ok := false
119
125
dDriver , ok = driver .(DynamicPVTestDriver )
120
126
if ! ok {
@@ -147,10 +153,12 @@ func (p *provisioningTestSuite) DefineTests(driver TestDriver, pattern testpatte
147
153
l .pvc = e2epv .MakePersistentVolumeClaim (e2epv.PersistentVolumeClaimConfig {
148
154
ClaimSize : claimSize ,
149
155
StorageClassName : & (l .sc .Name ),
156
+ VolumeMode : & pattern .VolMode ,
150
157
}, l .config .Framework .Namespace .Name )
151
158
l .sourcePVC = e2epv .MakePersistentVolumeClaim (e2epv.PersistentVolumeClaimConfig {
152
159
ClaimSize : claimSize ,
153
160
StorageClassName : & (l .sc .Name ),
161
+ VolumeMode : & pattern .VolMode ,
154
162
}, l .config .Framework .Namespace .Name )
155
163
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 )
156
164
l .testCase = & StorageClassTest {
@@ -160,6 +168,7 @@ func (p *provisioningTestSuite) DefineTests(driver TestDriver, pattern testpatte
160
168
Class : l .sc ,
161
169
ClaimSize : claimSize ,
162
170
ExpectedSize : claimSize ,
171
+ VolumeMode : pattern .VolMode ,
163
172
}
164
173
}
165
174
@@ -175,6 +184,9 @@ func (p *provisioningTestSuite) DefineTests(driver TestDriver, pattern testpatte
175
184
if dInfo .SupportedMountOption == nil {
176
185
e2eskipper .Skipf ("Driver %q does not define supported mount option - skipping" , dInfo .Name )
177
186
}
187
+ if pattern .VolMode == v1 .PersistentVolumeBlock {
188
+ e2eskipper .Skipf ("Block volumes do not support mount options - skipping" )
189
+ }
178
190
179
191
init ()
180
192
defer cleanup ()
@@ -212,26 +224,85 @@ func (p *provisioningTestSuite) DefineTests(driver TestDriver, pattern testpatte
212
224
}
213
225
l .testCase .TestDynamicProvisioning ()
214
226
})
227
+
215
228
ginkgo .It ("should provision storage with pvc data source" , func () {
216
229
if ! dInfo .Capabilities [CapPVCDataSource ] {
217
230
e2eskipper .Skipf ("Driver %q does not support cloning - skipping" , dInfo .Name )
218
231
}
219
-
220
232
init ()
221
233
defer cleanup ()
222
234
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 )
225
238
defer dataSourceCleanup ()
226
239
227
240
l .pvc .Spec .DataSource = dataSource
228
241
l .testCase .PvCheck = func (claim * v1.PersistentVolumeClaim ) {
229
242
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 )
232
252
}
233
253
l .testCase .TestDynamicProvisioning ()
234
254
})
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
+ })
235
306
}
236
307
237
308
// TestDynamicProvisioning tests dynamic provisioning with specified StorageClassTest
@@ -701,27 +772,34 @@ func prepareSnapshotDataSourceForProvisioning(
701
772
}
702
773
703
774
func preparePVCDataSourceForProvisioning (
704
- node e2epod.NodeSelection ,
775
+ f * framework.Framework ,
776
+ config volume.TestConfig ,
705
777
client clientset.Interface ,
706
- dynamicClient dynamic.Interface ,
707
778
source * v1.PersistentVolumeClaim ,
708
779
class * storagev1.StorageClass ,
780
+ mode v1.PersistentVolumeMode ,
781
+ injectContent string ,
709
782
) (* v1.TypedLocalObjectReference , func ()) {
710
783
var err error
711
784
if class != nil {
712
785
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 {})
714
787
framework .ExpectNoError (err )
715
788
}
716
789
717
790
ginkgo .By ("[Initialize dataSource]creating a source PVC" )
718
791
sourcePVC , err := client .CoreV1 ().PersistentVolumeClaims (source .Namespace ).Create (context .TODO (), source , metav1.CreateOptions {})
719
792
framework .ExpectNoError (err )
720
793
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 )
725
803
726
804
dataSourceRef := & v1.TypedLocalObjectReference {
727
805
Kind : "PersistentVolumeClaim" ,
@@ -730,10 +808,17 @@ func preparePVCDataSourceForProvisioning(
730
808
731
809
cleanupFunc := func () {
732
810
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 )
734
812
if err != nil && ! apierrors .IsNotFound (err ) {
735
813
framework .Failf ("Error deleting source PVC %q. Error: %v" , sourcePVC .Name , err )
736
814
}
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
+ }
737
822
}
738
823
739
824
return dataSourceRef , cleanupFunc
0 commit comments