Unverified Commit 07cf5fa0 authored by Kubernetes Prow Robot's avatar Kubernetes Prow Robot Committed by GitHub

Merge pull request #72434 from pohly/storage-volume-testsuites-config

e2e/storage: delay CreateDriver, simplify APIs and test definition
parents f99728e6 ec3655a1
...@@ -67,11 +67,9 @@ go_library( ...@@ -67,11 +67,9 @@ go_library(
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library", "//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library",
"//test/e2e/framework:go_default_library", "//test/e2e/framework:go_default_library",
"//test/e2e/framework/metrics:go_default_library", "//test/e2e/framework/metrics:go_default_library",
"//test/e2e/framework/podlogs:go_default_library",
"//test/e2e/framework/providers/gce:go_default_library", "//test/e2e/framework/providers/gce:go_default_library",
"//test/e2e/framework/testfiles:go_default_library", "//test/e2e/framework/testfiles:go_default_library",
"//test/e2e/storage/drivers:go_default_library", "//test/e2e/storage/drivers:go_default_library",
"//test/e2e/storage/testpatterns:go_default_library",
"//test/e2e/storage/testsuites:go_default_library", "//test/e2e/storage/testsuites:go_default_library",
"//test/e2e/storage/utils:go_default_library", "//test/e2e/storage/utils:go_default_library",
"//test/utils/image:go_default_library", "//test/utils/image:go_default_library",
......
...@@ -18,15 +18,13 @@ package storage ...@@ -18,15 +18,13 @@ package storage
import ( import (
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
"k8s.io/kubernetes/test/e2e/framework"
"k8s.io/kubernetes/test/e2e/storage/drivers" "k8s.io/kubernetes/test/e2e/storage/drivers"
"k8s.io/kubernetes/test/e2e/storage/testpatterns"
"k8s.io/kubernetes/test/e2e/storage/testsuites" "k8s.io/kubernetes/test/e2e/storage/testsuites"
"k8s.io/kubernetes/test/e2e/storage/utils" "k8s.io/kubernetes/test/e2e/storage/utils"
) )
// List of testDrivers to be executed in below loop // List of testDrivers to be executed in below loop
var testDrivers = []func(config testsuites.TestConfig) testsuites.TestDriver{ var testDrivers = []func() testsuites.TestDriver{
drivers.InitNFSDriver, drivers.InitNFSDriver,
drivers.InitGlusterFSDriver, drivers.InitGlusterFSDriver,
drivers.InitISCSIDriver, drivers.InitISCSIDriver,
...@@ -59,41 +57,13 @@ var testSuites = []func() testsuites.TestSuite{ ...@@ -59,41 +57,13 @@ var testSuites = []func() testsuites.TestSuite{
testsuites.InitProvisioningTestSuite, testsuites.InitProvisioningTestSuite,
} }
func intreeTunePattern(patterns []testpatterns.TestPattern) []testpatterns.TestPattern {
return patterns
}
// This executes testSuites for in-tree volumes. // This executes testSuites for in-tree volumes.
var _ = utils.SIGDescribe("In-tree Volumes", func() { var _ = utils.SIGDescribe("In-tree Volumes", func() {
f := framework.NewDefaultFramework("volumes")
var (
// Common configuration options for all drivers.
config = testsuites.TestConfig{
Framework: f,
Prefix: "in-tree",
}
)
for _, initDriver := range testDrivers { for _, initDriver := range testDrivers {
curDriver := initDriver(config) curDriver := initDriver()
curConfig := curDriver.GetDriverInfo().Config
Context(testsuites.GetDriverNameWithFeatureTags(curDriver), func() {
BeforeEach(func() {
// Reset config. The driver might have modified its copy
// in a previous test.
curDriver.GetDriverInfo().Config = curConfig
// setupDriver
curDriver.CreateDriver()
})
AfterEach(func() { Context(testsuites.GetDriverNameWithFeatureTags(curDriver), func() {
// Cleanup driver testsuites.DefineTestSuite(curDriver, testSuites)
curDriver.CleanupDriver()
})
testsuites.RunTestSuite(f, curDriver, testSuites, intreeTunePattern)
}) })
} }
}) })
...@@ -143,10 +143,11 @@ func testVolumeProvisioning(c clientset.Interface, ns string) { ...@@ -143,10 +143,11 @@ func testVolumeProvisioning(c clientset.Interface, ns string) {
} }
for _, test := range tests { for _, test := range tests {
class := newStorageClass(test, ns, "" /* suffix */) test.Client = c
claim := newClaim(test, ns, "" /* suffix */) test.Class = newStorageClass(test, ns, "" /* suffix */)
claim.Spec.StorageClassName = &class.Name test.Claim = newClaim(test, ns, "" /* suffix */)
testsuites.TestDynamicProvisioning(test, c, claim, class) test.Claim.Spec.StorageClassName = &test.Class.Name
test.TestDynamicProvisioning()
} }
} }
...@@ -301,6 +302,7 @@ func addTaint(c clientset.Interface, ns string, nodes []v1.Node, podZone string) ...@@ -301,6 +302,7 @@ func addTaint(c clientset.Interface, ns string, nodes []v1.Node, podZone string)
func testRegionalDelayedBinding(c clientset.Interface, ns string, pvcCount int) { func testRegionalDelayedBinding(c clientset.Interface, ns string, pvcCount int) {
test := testsuites.StorageClassTest{ test := testsuites.StorageClassTest{
Client: c,
Name: "Regional PD storage class with waitForFirstConsumer test on GCE", Name: "Regional PD storage class with waitForFirstConsumer test on GCE",
Provisioner: "kubernetes.io/gce-pd", Provisioner: "kubernetes.io/gce-pd",
Parameters: map[string]string{ Parameters: map[string]string{
...@@ -312,14 +314,14 @@ func testRegionalDelayedBinding(c clientset.Interface, ns string, pvcCount int) ...@@ -312,14 +314,14 @@ func testRegionalDelayedBinding(c clientset.Interface, ns string, pvcCount int)
} }
suffix := "delayed-regional" suffix := "delayed-regional"
class := newStorageClass(test, ns, suffix) test.Class = newStorageClass(test, ns, suffix)
var claims []*v1.PersistentVolumeClaim var claims []*v1.PersistentVolumeClaim
for i := 0; i < pvcCount; i++ { for i := 0; i < pvcCount; i++ {
claim := newClaim(test, ns, suffix) claim := newClaim(test, ns, suffix)
claim.Spec.StorageClassName = &class.Name claim.Spec.StorageClassName = &test.Class.Name
claims = append(claims, claim) claims = append(claims, claim)
} }
pvs, node := testsuites.TestBindingWaitForFirstConsumerMultiPVC(test, c, claims, class, nil /* node selector */, false /* expect unschedulable */) pvs, node := test.TestBindingWaitForFirstConsumerMultiPVC(claims, nil /* node selector */, false /* expect unschedulable */)
if node == nil { if node == nil {
framework.Failf("unexpected nil node found") framework.Failf("unexpected nil node found")
} }
...@@ -345,17 +347,20 @@ func testRegionalAllowedTopologies(c clientset.Interface, ns string) { ...@@ -345,17 +347,20 @@ func testRegionalAllowedTopologies(c clientset.Interface, ns string) {
} }
suffix := "topo-regional" suffix := "topo-regional"
class := newStorageClass(test, ns, suffix) test.Client = c
test.Class = newStorageClass(test, ns, suffix)
zones := getTwoRandomZones(c) zones := getTwoRandomZones(c)
addAllowedTopologiesToStorageClass(c, class, zones) addAllowedTopologiesToStorageClass(c, test.Class, zones)
claim := newClaim(test, ns, suffix) test.Claim = newClaim(test, ns, suffix)
claim.Spec.StorageClassName = &class.Name test.Claim.Spec.StorageClassName = &test.Class.Name
pv := testsuites.TestDynamicProvisioning(test, c, claim, class)
pv := test.TestDynamicProvisioning()
checkZonesFromLabelAndAffinity(pv, sets.NewString(zones...), true) checkZonesFromLabelAndAffinity(pv, sets.NewString(zones...), true)
} }
func testRegionalAllowedTopologiesWithDelayedBinding(c clientset.Interface, ns string, pvcCount int) { func testRegionalAllowedTopologiesWithDelayedBinding(c clientset.Interface, ns string, pvcCount int) {
test := testsuites.StorageClassTest{ test := testsuites.StorageClassTest{
Client: c,
Name: "Regional PD storage class with allowedTopologies and waitForFirstConsumer test on GCE", Name: "Regional PD storage class with allowedTopologies and waitForFirstConsumer test on GCE",
Provisioner: "kubernetes.io/gce-pd", Provisioner: "kubernetes.io/gce-pd",
Parameters: map[string]string{ Parameters: map[string]string{
...@@ -367,16 +372,16 @@ func testRegionalAllowedTopologiesWithDelayedBinding(c clientset.Interface, ns s ...@@ -367,16 +372,16 @@ func testRegionalAllowedTopologiesWithDelayedBinding(c clientset.Interface, ns s
} }
suffix := "topo-delayed-regional" suffix := "topo-delayed-regional"
class := newStorageClass(test, ns, suffix) test.Class = newStorageClass(test, ns, suffix)
topoZones := getTwoRandomZones(c) topoZones := getTwoRandomZones(c)
addAllowedTopologiesToStorageClass(c, class, topoZones) addAllowedTopologiesToStorageClass(c, test.Class, topoZones)
var claims []*v1.PersistentVolumeClaim var claims []*v1.PersistentVolumeClaim
for i := 0; i < pvcCount; i++ { for i := 0; i < pvcCount; i++ {
claim := newClaim(test, ns, suffix) claim := newClaim(test, ns, suffix)
claim.Spec.StorageClassName = &class.Name claim.Spec.StorageClassName = &test.Class.Name
claims = append(claims, claim) claims = append(claims, claim)
} }
pvs, node := testsuites.TestBindingWaitForFirstConsumerMultiPVC(test, c, claims, class, nil /* node selector */, false /* expect unschedulable */) pvs, node := test.TestBindingWaitForFirstConsumerMultiPVC(claims, nil /* node selector */, false /* expect unschedulable */)
if node == nil { if node == nil {
framework.Failf("unexpected nil node found") framework.Failf("unexpected nil node found")
} }
......
...@@ -31,6 +31,7 @@ go_library( ...@@ -31,6 +31,7 @@ go_library(
"//staging/src/k8s.io/client-go/dynamic:go_default_library", "//staging/src/k8s.io/client-go/dynamic:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//test/e2e/framework:go_default_library", "//test/e2e/framework:go_default_library",
"//test/e2e/framework/podlogs:go_default_library",
"//test/e2e/storage/testpatterns:go_default_library", "//test/e2e/storage/testpatterns:go_default_library",
"//test/e2e/storage/utils:go_default_library", "//test/e2e/storage/utils:go_default_library",
"//test/utils/image:go_default_library", "//test/utils/image:go_default_library",
......
...@@ -17,7 +17,9 @@ limitations under the License. ...@@ -17,7 +17,9 @@ limitations under the License.
package testsuites package testsuites
import ( import (
"context"
"fmt" "fmt"
"regexp"
"time" "time"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
...@@ -32,6 +34,7 @@ import ( ...@@ -32,6 +34,7 @@ import (
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
"k8s.io/kubernetes/test/e2e/framework/podlogs"
"k8s.io/kubernetes/test/e2e/storage/testpatterns" "k8s.io/kubernetes/test/e2e/storage/testpatterns"
) )
...@@ -39,10 +42,10 @@ import ( ...@@ -39,10 +42,10 @@ import (
type TestSuite interface { type TestSuite interface {
// getTestSuiteInfo returns the TestSuiteInfo for this TestSuite // getTestSuiteInfo returns the TestSuiteInfo for this TestSuite
getTestSuiteInfo() TestSuiteInfo getTestSuiteInfo() TestSuiteInfo
// skipUnsupportedTest skips the test if this TestSuite is not suitable to be tested with the combination of TestPattern and TestDriver // defineTest defines tests of the testpattern for the driver.
skipUnsupportedTest(testpatterns.TestPattern, TestDriver) // Called inside a Ginkgo context that reflects the current driver and test pattern,
// execTest executes test of the testpattern for the driver // so the test suite can define tests directly with ginkgo.It.
execTest(TestDriver, testpatterns.TestPattern) defineTests(TestDriver, testpatterns.TestPattern)
} }
// TestSuiteInfo represents a set of parameters for TestSuite // TestSuiteInfo represents a set of parameters for TestSuite
...@@ -54,11 +57,8 @@ type TestSuiteInfo struct { ...@@ -54,11 +57,8 @@ type TestSuiteInfo struct {
// TestResource represents an interface for resources that is used by TestSuite // TestResource represents an interface for resources that is used by TestSuite
type TestResource interface { type TestResource interface {
// setupResource sets up test resources to be used for the tests with the // cleanupResource cleans up the test resources created when setting up the resource
// combination of TestDriver and TestPattern cleanupResource()
setupResource(TestDriver, testpatterns.TestPattern)
// cleanupResource clean up the test resources created in SetupResource
cleanupResource(TestDriver, testpatterns.TestPattern)
} }
func getTestNameStr(suite TestSuite, pattern testpatterns.TestPattern) string { func getTestNameStr(suite TestSuite, pattern testpatterns.TestPattern) string {
...@@ -66,27 +66,34 @@ func getTestNameStr(suite TestSuite, pattern testpatterns.TestPattern) string { ...@@ -66,27 +66,34 @@ func getTestNameStr(suite TestSuite, pattern testpatterns.TestPattern) string {
return fmt.Sprintf("[Testpattern: %s]%s %s%s", pattern.Name, pattern.FeatureTag, tsInfo.name, tsInfo.featureTag) return fmt.Sprintf("[Testpattern: %s]%s %s%s", pattern.Name, pattern.FeatureTag, tsInfo.name, tsInfo.featureTag)
} }
// RunTestSuite runs all testpatterns of all testSuites for a driver // DefineTestSuite defines tests for all testpatterns and all testSuites for a driver
func RunTestSuite(f *framework.Framework, driver TestDriver, tsInits []func() TestSuite, tunePatternFunc func([]testpatterns.TestPattern) []testpatterns.TestPattern) { func DefineTestSuite(driver TestDriver, tsInits []func() TestSuite) {
for _, testSuiteInit := range tsInits { for _, testSuiteInit := range tsInits {
suite := testSuiteInit() suite := testSuiteInit()
patterns := tunePatternFunc(suite.getTestSuiteInfo().testPatterns) for _, pattern := range suite.getTestSuiteInfo().testPatterns {
p := pattern
for _, pattern := range patterns { Context(getTestNameStr(suite, p), func() {
suite.execTest(driver, pattern) BeforeEach(func() {
// Skip unsupported tests to avoid unnecessary resource initialization
skipUnsupportedTest(driver, p)
})
suite.defineTests(driver, p)
})
} }
} }
} }
// skipUnsupportedTest will skip tests if the combination of driver, testsuite, and testpattern // skipUnsupportedTest will skip tests if the combination of driver, and testpattern
// is not suitable to be tested. // is not suitable to be tested.
// Whether it needs to be skipped is checked by following steps: // Whether it needs to be skipped is checked by following steps:
// 1. Check if Whether SnapshotType is supported by driver from its interface // 1. Check if Whether SnapshotType is supported by driver from its interface
// 2. Check if Whether volType is supported by driver from its interface // 2. Check if Whether volType is supported by driver from its interface
// 3. Check if fsType is supported // 3. Check if fsType is supported
// 4. Check with driver specific logic // 4. Check with driver specific logic
// 5. Check with testSuite specific logic //
func skipUnsupportedTest(suite TestSuite, driver TestDriver, pattern testpatterns.TestPattern) { // Test suites can also skip tests inside their own defineTests function or in
// individual tests.
func skipUnsupportedTest(driver TestDriver, pattern testpatterns.TestPattern) {
dInfo := driver.GetDriverInfo() dInfo := driver.GetDriverInfo()
var isSupported bool var isSupported bool
...@@ -130,9 +137,6 @@ func skipUnsupportedTest(suite TestSuite, driver TestDriver, pattern testpattern ...@@ -130,9 +137,6 @@ func skipUnsupportedTest(suite TestSuite, driver TestDriver, pattern testpattern
// 4. Check with driver specific logic // 4. Check with driver specific logic
driver.SkipUnsupportedTest(pattern) driver.SkipUnsupportedTest(pattern)
// 5. Check with testSuite specific logic
suite.skipUnsupportedTest(pattern, driver)
} }
// genericVolumeTestResource is a generic implementation of TestResource that wil be able to // genericVolumeTestResource is a generic implementation of TestResource that wil be able to
...@@ -141,40 +145,45 @@ func skipUnsupportedTest(suite TestSuite, driver TestDriver, pattern testpattern ...@@ -141,40 +145,45 @@ func skipUnsupportedTest(suite TestSuite, driver TestDriver, pattern testpattern
// Also, see subpath.go in the same directory for how to extend and use it. // Also, see subpath.go in the same directory for how to extend and use it.
type genericVolumeTestResource struct { type genericVolumeTestResource struct {
driver TestDriver driver TestDriver
config *PerTestConfig
pattern testpatterns.TestPattern
volType string volType string
volSource *v1.VolumeSource volSource *v1.VolumeSource
pvc *v1.PersistentVolumeClaim pvc *v1.PersistentVolumeClaim
pv *v1.PersistentVolume pv *v1.PersistentVolume
sc *storagev1.StorageClass sc *storagev1.StorageClass
driverTestResource interface{} volume TestVolume
} }
var _ TestResource = &genericVolumeTestResource{} var _ TestResource = &genericVolumeTestResource{}
// setupResource sets up genericVolumeTestResource func createGenericVolumeTestResource(driver TestDriver, config *PerTestConfig, pattern testpatterns.TestPattern) *genericVolumeTestResource {
func (r *genericVolumeTestResource) setupResource(driver TestDriver, pattern testpatterns.TestPattern) { r := genericVolumeTestResource{
r.driver = driver driver: driver,
config: config,
pattern: pattern,
}
dInfo := driver.GetDriverInfo() dInfo := driver.GetDriverInfo()
f := dInfo.Config.Framework f := config.Framework
cs := f.ClientSet cs := f.ClientSet
fsType := pattern.FsType fsType := pattern.FsType
volType := pattern.VolType volType := pattern.VolType
// Create volume for pre-provisioned volume tests // Create volume for pre-provisioned volume tests
r.driverTestResource = CreateVolume(driver, volType) r.volume = CreateVolume(driver, config, volType)
switch volType { switch volType {
case testpatterns.InlineVolume: case testpatterns.InlineVolume:
framework.Logf("Creating resource for inline volume") framework.Logf("Creating resource for inline volume")
if iDriver, ok := driver.(InlineVolumeTestDriver); ok { if iDriver, ok := driver.(InlineVolumeTestDriver); ok {
r.volSource = iDriver.GetVolumeSource(false, fsType, r.driverTestResource) r.volSource = iDriver.GetVolumeSource(false, fsType, r.volume)
r.volType = dInfo.Name r.volType = dInfo.Name
} }
case testpatterns.PreprovisionedPV: case testpatterns.PreprovisionedPV:
framework.Logf("Creating resource for pre-provisioned PV") framework.Logf("Creating resource for pre-provisioned PV")
if pDriver, ok := driver.(PreprovisionedPVTestDriver); ok { if pDriver, ok := driver.(PreprovisionedPVTestDriver); ok {
pvSource, volumeNodeAffinity := pDriver.GetPersistentVolumeSource(false, fsType, r.driverTestResource) pvSource, volumeNodeAffinity := pDriver.GetPersistentVolumeSource(false, fsType, r.volume)
if pvSource != nil { if pvSource != nil {
r.volSource, r.pv, r.pvc = createVolumeSourceWithPVCPV(f, dInfo.Name, pvSource, volumeNodeAffinity, false) r.volSource, r.pv, r.pvc = createVolumeSourceWithPVCPV(f, dInfo.Name, pvSource, volumeNodeAffinity, false)
} }
...@@ -184,7 +193,7 @@ func (r *genericVolumeTestResource) setupResource(driver TestDriver, pattern tes ...@@ -184,7 +193,7 @@ func (r *genericVolumeTestResource) setupResource(driver TestDriver, pattern tes
framework.Logf("Creating resource for dynamic PV") framework.Logf("Creating resource for dynamic PV")
if dDriver, ok := driver.(DynamicPVTestDriver); ok { if dDriver, ok := driver.(DynamicPVTestDriver); ok {
claimSize := dDriver.GetClaimSize() claimSize := dDriver.GetClaimSize()
r.sc = dDriver.GetDynamicProvisionStorageClass(fsType) r.sc = dDriver.GetDynamicProvisionStorageClass(r.config, fsType)
By("creating a StorageClass " + r.sc.Name) By("creating a StorageClass " + r.sc.Name)
var err error var err error
...@@ -204,13 +213,14 @@ func (r *genericVolumeTestResource) setupResource(driver TestDriver, pattern tes ...@@ -204,13 +213,14 @@ func (r *genericVolumeTestResource) setupResource(driver TestDriver, pattern tes
if r.volSource == nil { if r.volSource == nil {
framework.Skipf("Driver %s doesn't support %v -- skipping", dInfo.Name, volType) framework.Skipf("Driver %s doesn't support %v -- skipping", dInfo.Name, volType)
} }
return &r
} }
// cleanupResource cleans up genericVolumeTestResource // cleanupResource cleans up genericVolumeTestResource
func (r *genericVolumeTestResource) cleanupResource(driver TestDriver, pattern testpatterns.TestPattern) { func (r *genericVolumeTestResource) cleanupResource() {
dInfo := driver.GetDriverInfo() f := r.config.Framework
f := dInfo.Config.Framework volType := r.pattern.VolType
volType := pattern.VolType
if r.pvc != nil || r.pv != nil { if r.pvc != nil || r.pv != nil {
switch volType { switch volType {
...@@ -241,7 +251,9 @@ func (r *genericVolumeTestResource) cleanupResource(driver TestDriver, pattern t ...@@ -241,7 +251,9 @@ func (r *genericVolumeTestResource) cleanupResource(driver TestDriver, pattern t
} }
// Cleanup volume for pre-provisioned volume tests // Cleanup volume for pre-provisioned volume tests
DeleteVolume(driver, volType, r.driverTestResource) if r.volume != nil {
r.volume.DeleteVolume()
}
} }
func createVolumeSourceWithPVCPV( func createVolumeSourceWithPVCPV(
...@@ -354,7 +366,7 @@ func deleteStorageClass(cs clientset.Interface, className string) { ...@@ -354,7 +366,7 @@ func deleteStorageClass(cs clientset.Interface, className string) {
// the testsuites package whereas framework.VolumeTestConfig is merely // the testsuites package whereas framework.VolumeTestConfig is merely
// an implementation detail. It contains fields that have no effect, // an implementation detail. It contains fields that have no effect,
// which makes it unsuitable for use in the testsuits public API. // which makes it unsuitable for use in the testsuits public API.
func convertTestConfig(in *TestConfig) framework.VolumeTestConfig { func convertTestConfig(in *PerTestConfig) framework.VolumeTestConfig {
if in.ServerConfig != nil { if in.ServerConfig != nil {
return *in.ServerConfig return *in.ServerConfig
} }
...@@ -388,3 +400,42 @@ func getSnapshot(claimName string, ns, snapshotClassName string) *unstructured.U ...@@ -388,3 +400,42 @@ func getSnapshot(claimName string, ns, snapshotClassName string) *unstructured.U
return snapshot return snapshot
} }
// StartPodLogs begins capturing log output and events from current
// and future pods running in the namespace of the framework. That
// ends when the returned cleanup function is called.
//
// The output goes to log files (when using --report-dir, as in the
// CI) or the output stream (otherwise).
func StartPodLogs(f *framework.Framework) func() {
ctx, cancel := context.WithCancel(context.Background())
cs := f.ClientSet
ns := f.Namespace
to := podlogs.LogOutput{
StatusWriter: GinkgoWriter,
}
if framework.TestContext.ReportDir == "" {
to.LogWriter = GinkgoWriter
} else {
test := CurrentGinkgoTestDescription()
reg := regexp.MustCompile("[^a-zA-Z0-9_-]+")
// We end the prefix with a slash to ensure that all logs
// end up in a directory named after the current test.
//
// TODO: use a deeper directory hierarchy once gubernator
// supports that (https://github.com/kubernetes/test-infra/issues/10289).
to.LogPathPrefix = framework.TestContext.ReportDir + "/" +
reg.ReplaceAllString(test.FullTestText, "_") + "/"
}
podlogs.CopyAllLogs(ctx, cs, ns.Name, to)
// pod events are something that the framework already collects itself
// after a failed test. Logging them live is only useful for interactive
// debugging, not when we collect reports.
if framework.TestContext.ReportDir == "" {
podlogs.WatchPods(ctx, cs, ns.Name, GinkgoWriter)
}
return cancel
}
...@@ -37,13 +37,13 @@ func GetDriverNameWithFeatureTags(driver TestDriver) string { ...@@ -37,13 +37,13 @@ func GetDriverNameWithFeatureTags(driver TestDriver) string {
} }
// CreateVolume creates volume for test unless dynamicPV test // CreateVolume creates volume for test unless dynamicPV test
func CreateVolume(driver TestDriver, volType testpatterns.TestVolType) interface{} { func CreateVolume(driver TestDriver, config *PerTestConfig, volType testpatterns.TestVolType) TestVolume {
switch volType { switch volType {
case testpatterns.InlineVolume: case testpatterns.InlineVolume:
fallthrough fallthrough
case testpatterns.PreprovisionedPV: case testpatterns.PreprovisionedPV:
if pDriver, ok := driver.(PreprovisionedVolumeTestDriver); ok { if pDriver, ok := driver.(PreprovisionedVolumeTestDriver); ok {
return pDriver.CreateVolume(volType) return pDriver.CreateVolume(config, volType)
} }
case testpatterns.DynamicPV: case testpatterns.DynamicPV:
// No need to create volume // No need to create volume
...@@ -53,22 +53,6 @@ func CreateVolume(driver TestDriver, volType testpatterns.TestVolType) interface ...@@ -53,22 +53,6 @@ func CreateVolume(driver TestDriver, volType testpatterns.TestVolType) interface
return nil return nil
} }
// DeleteVolume deletes volume for test unless dynamicPV test
func DeleteVolume(driver TestDriver, volType testpatterns.TestVolType, testResource interface{}) {
switch volType {
case testpatterns.InlineVolume:
fallthrough
case testpatterns.PreprovisionedPV:
if pDriver, ok := driver.(PreprovisionedVolumeTestDriver); ok {
pDriver.DeleteVolume(volType, testResource)
}
case testpatterns.DynamicPV:
// No need to delete volume
default:
framework.Failf("Invalid volType specified: %v", volType)
}
}
// GetStorageClass constructs a new StorageClass instance // GetStorageClass constructs a new StorageClass instance
// with a unique name that is based on namespace + suffix. // with a unique name that is based on namespace + suffix.
func GetStorageClass( func GetStorageClass(
...@@ -119,8 +103,3 @@ func GetSnapshotClass( ...@@ -119,8 +103,3 @@ func GetSnapshotClass(
return snapshotClass return snapshotClass
} }
// GetUniqueDriverName returns unique driver name that can be used parallelly in tests
func GetUniqueDriverName(driver TestDriver) string {
return fmt.Sprintf("%s-%s", driver.GetDriverInfo().Name, driver.GetDriverInfo().Config.Framework.UniqueName)
}
...@@ -25,35 +25,53 @@ import ( ...@@ -25,35 +25,53 @@ import (
"k8s.io/kubernetes/test/e2e/storage/testpatterns" "k8s.io/kubernetes/test/e2e/storage/testpatterns"
) )
// TestDriver represents an interface for a driver to be tested in TestSuite // TestDriver represents an interface for a driver to be tested in TestSuite.
// Except for GetDriverInfo, all methods will be called at test runtime and thus
// can use framework.Skipf, framework.Fatal, Gomega assertions, etc.
type TestDriver interface { type TestDriver interface {
// GetDriverInfo returns DriverInfo for the TestDriver // GetDriverInfo returns DriverInfo for the TestDriver. This must be static
// information.
GetDriverInfo() *DriverInfo GetDriverInfo() *DriverInfo
// CreateDriver creates all driver resources that is required for TestDriver method
// except CreateVolume // SkipUnsupportedTest skips test if Testpattern is not
CreateDriver() // suitable to test with the TestDriver. It gets called after
// CreateDriver cleanup all the resources that is created in CreateDriver // parsing parameters of the test suite and before the
CleanupDriver() // framework is initialized. Cheap tests that just check
// SkipUnsupportedTest skips test in Testpattern is not suitable to test with the TestDriver // parameters like the cloud provider can and should be
// done in SkipUnsupportedTest to avoid setting up more
// expensive resources like framework.Framework. Tests that
// depend on a connection to the cluster can be done in
// PrepareTest once the framework is ready.
SkipUnsupportedTest(testpatterns.TestPattern) SkipUnsupportedTest(testpatterns.TestPattern)
// PrepareTest is called at test execution time each time a new test case is about to start.
// It sets up all necessary resources and returns the per-test configuration
// plus a cleanup function that frees all allocated resources.
PrepareTest(f *framework.Framework) (*PerTestConfig, func())
}
// TestVolume is the result of PreprovisionedVolumeTestDriver.CreateVolume.
// The only common functionality is to delete it. Individual driver interfaces
// have additional methods that work with volumes created by them.
type TestVolume interface {
DeleteVolume()
} }
// PreprovisionedVolumeTestDriver represents an interface for a TestDriver that has pre-provisioned volume // PreprovisionedVolumeTestDriver represents an interface for a TestDriver that has pre-provisioned volume
type PreprovisionedVolumeTestDriver interface { type PreprovisionedVolumeTestDriver interface {
TestDriver TestDriver
// CreateVolume creates a pre-provisioned volume. // CreateVolume creates a pre-provisioned volume of the desired volume type.
CreateVolume(testpatterns.TestVolType) interface{} CreateVolume(config *PerTestConfig, volumeType testpatterns.TestVolType) TestVolume
// DeleteVolume deletes a volume that is created in CreateVolume
DeleteVolume(testpatterns.TestVolType, interface{})
} }
// InlineVolumeTestDriver represents an interface for a TestDriver that supports InlineVolume // InlineVolumeTestDriver represents an interface for a TestDriver that supports InlineVolume
type InlineVolumeTestDriver interface { type InlineVolumeTestDriver interface {
PreprovisionedVolumeTestDriver PreprovisionedVolumeTestDriver
// GetVolumeSource returns a volumeSource for inline volume. // GetVolumeSource returns a volumeSource for inline volume.
// It will set readOnly and fsType to the volumeSource, if TestDriver supports both of them. // It will set readOnly and fsType to the volumeSource, if TestDriver supports both of them.
// It will return nil, if the TestDriver doesn't support either of the parameters. // It will return nil, if the TestDriver doesn't support either of the parameters.
GetVolumeSource(readOnly bool, fsType string, testResource interface{}) *v1.VolumeSource GetVolumeSource(readOnly bool, fsType string, testVolume TestVolume) *v1.VolumeSource
} }
// PreprovisionedPVTestDriver represents an interface for a TestDriver that supports PreprovisionedPV // PreprovisionedPVTestDriver represents an interface for a TestDriver that supports PreprovisionedPV
...@@ -62,8 +80,7 @@ type PreprovisionedPVTestDriver interface { ...@@ -62,8 +80,7 @@ type PreprovisionedPVTestDriver interface {
// GetPersistentVolumeSource returns a PersistentVolumeSource with volume node affinity for pre-provisioned Persistent Volume. // GetPersistentVolumeSource returns a PersistentVolumeSource with volume node affinity for pre-provisioned Persistent Volume.
// It will set readOnly and fsType to the PersistentVolumeSource, if TestDriver supports both of them. // It will set readOnly and fsType to the PersistentVolumeSource, if TestDriver supports both of them.
// It will return nil, if the TestDriver doesn't support either of the parameters. // It will return nil, if the TestDriver doesn't support either of the parameters.
// Volume node affinity is optional, it will be nil for volumes which does not have volume node affinity. GetPersistentVolumeSource(readOnly bool, fsType string, testVolume TestVolume) (*v1.PersistentVolumeSource, *v1.VolumeNodeAffinity)
GetPersistentVolumeSource(readOnly bool, fsType string, testResource interface{}) (*v1.PersistentVolumeSource, *v1.VolumeNodeAffinity)
} }
// DynamicPVTestDriver represents an interface for a TestDriver that supports DynamicPV // DynamicPVTestDriver represents an interface for a TestDriver that supports DynamicPV
...@@ -72,7 +89,7 @@ type DynamicPVTestDriver interface { ...@@ -72,7 +89,7 @@ type DynamicPVTestDriver interface {
// GetDynamicProvisionStorageClass returns a StorageClass dynamic provision Persistent Volume. // GetDynamicProvisionStorageClass returns a StorageClass dynamic provision Persistent Volume.
// It will set fsType to the StorageClass, if TestDriver supports it. // It will set fsType to the StorageClass, if TestDriver supports it.
// It will return nil, if the TestDriver doesn't support it. // It will return nil, if the TestDriver doesn't support it.
GetDynamicProvisionStorageClass(fsType string) *storagev1.StorageClass GetDynamicProvisionStorageClass(config *PerTestConfig, fsType string) *storagev1.StorageClass
// GetClaimSize returns the size of the volume that is to be provisioned ("5Gi", "1Mi"). // GetClaimSize returns the size of the volume that is to be provisioned ("5Gi", "1Mi").
// The size must be chosen so that the resulting volume is large enough for all // The size must be chosen so that the resulting volume is large enough for all
...@@ -85,7 +102,7 @@ type SnapshottableTestDriver interface { ...@@ -85,7 +102,7 @@ type SnapshottableTestDriver interface {
TestDriver TestDriver
// GetSnapshotClass returns a SnapshotClass to create snapshot. // GetSnapshotClass returns a SnapshotClass to create snapshot.
// It will return nil, if the TestDriver doesn't support it. // It will return nil, if the TestDriver doesn't support it.
GetSnapshotClass() *unstructured.Unstructured GetSnapshotClass(config *PerTestConfig) *unstructured.Unstructured
} }
// Capability represents a feature that a volume plugin supports // Capability represents a feature that a volume plugin supports
...@@ -106,7 +123,7 @@ const ( ...@@ -106,7 +123,7 @@ const (
CapMultiPODs Capability = "multipods" CapMultiPODs Capability = "multipods"
) )
// DriverInfo represents a combination of parameters to be used in implementation of TestDriver // DriverInfo represents static information about a TestDriver.
type DriverInfo struct { type DriverInfo struct {
Name string // Name of the driver Name string // Name of the driver
FeatureTag string // FeatureTag for the driver FeatureTag string // FeatureTag for the driver
...@@ -116,14 +133,15 @@ type DriverInfo struct { ...@@ -116,14 +133,15 @@ type DriverInfo struct {
SupportedMountOption sets.String // Map of string for supported mount option SupportedMountOption sets.String // Map of string for supported mount option
RequiredMountOption sets.String // Map of string for required mount option (Optional) RequiredMountOption sets.String // Map of string for required mount option (Optional)
Capabilities map[Capability]bool // Map that represents plugin capabilities Capabilities map[Capability]bool // Map that represents plugin capabilities
Config TestConfig // Test configuration for the current test.
} }
// TestConfig represents parameters that control test execution. // PerTestConfig represents parameters that control test execution.
// They can still be modified after defining tests, for example // One instance gets allocated for each test and is then passed
// in a BeforeEach or when creating the driver. // via pointer to functions involved in the test.
type TestConfig struct { type PerTestConfig struct {
// The test driver for the test.
Driver TestDriver
// Some short word that gets inserted into dynamically // Some short word that gets inserted into dynamically
// generated entities (pods, paths) as first part of the name // generated entities (pods, paths) as first part of the name
// to make debugging easier. Can be the same for different // to make debugging easier. Can be the same for different
...@@ -148,8 +166,9 @@ type TestConfig struct { ...@@ -148,8 +166,9 @@ type TestConfig struct {
// the configuration that then has to be used to run tests. // the configuration that then has to be used to run tests.
// The values above are ignored for such tests. // The values above are ignored for such tests.
ServerConfig *framework.VolumeTestConfig ServerConfig *framework.VolumeTestConfig
}
// TopologyEnabled indicates that the Topology feature gate // GetUniqueDriverName returns unique driver name that can be used parallelly in tests
// should be enabled in external-provisioner func (config *PerTestConfig) GetUniqueDriverName() string {
TopologyEnabled bool return config.Driver.GetDriverInfo().Name + "-" + config.Framework.UniqueName
} }
...@@ -74,87 +74,65 @@ func (t *volumeIOTestSuite) getTestSuiteInfo() TestSuiteInfo { ...@@ -74,87 +74,65 @@ func (t *volumeIOTestSuite) getTestSuiteInfo() TestSuiteInfo {
return t.tsInfo return t.tsInfo
} }
func (t *volumeIOTestSuite) skipUnsupportedTest(pattern testpatterns.TestPattern, driver TestDriver) { func (t *volumeIOTestSuite) defineTests(driver TestDriver, pattern testpatterns.TestPattern) {
} type local struct {
config *PerTestConfig
func createVolumeIOTestInput(pattern testpatterns.TestPattern, resource genericVolumeTestResource) volumeIOTestInput { testCleanup func()
var fsGroup *int64
driver := resource.driver
dInfo := driver.GetDriverInfo()
f := dInfo.Config.Framework
fileSizes := createFileSizes(dInfo.MaxFileSize)
volSource := resource.volSource
if volSource == nil {
framework.Skipf("Driver %q does not define volumeSource - skipping", dInfo.Name)
}
if dInfo.Capabilities[CapFsGroup] { resource *genericVolumeTestResource
fsGroupVal := int64(1234)
fsGroup = &fsGroupVal
} }
var (
return volumeIOTestInput{ dInfo = driver.GetDriverInfo()
f: f, l local
name: dInfo.Name, )
config: &dInfo.Config,
volSource: *volSource, // No preconditions to test. Normally they would be in a BeforeEach here.
testFile: fmt.Sprintf("%s_io_test_%s", dInfo.Name, f.Namespace.Name),
podSec: v1.PodSecurityContext{ // This intentionally comes after checking the preconditions because it
FSGroup: fsGroup, // registers its own BeforeEach which creates the namespace. Beware that it
}, // also registers an AfterEach which renders f unusable. Any code using
fileSizes: fileSizes, // f must run inside an It or Context callback.
f := framework.NewDefaultFramework("volumeio")
init := func() {
l = local{}
// Now do the more expensive test initialization.
l.config, l.testCleanup = driver.PrepareTest(f)
l.resource = createGenericVolumeTestResource(driver, l.config, pattern)
if l.resource.volSource == nil {
framework.Skipf("Driver %q does not define volumeSource - skipping", dInfo.Name)
}
} }
}
func (t *volumeIOTestSuite) execTest(driver TestDriver, pattern testpatterns.TestPattern) {
Context(getTestNameStr(t, pattern), func() {
var (
resource genericVolumeTestResource
input volumeIOTestInput
needsCleanup bool
)
BeforeEach(func() {
needsCleanup = false
// Skip unsupported tests to avoid unnecessary resource initialization
skipUnsupportedTest(t, driver, pattern)
needsCleanup = true
// Setup test resource for driver and testpattern
resource = genericVolumeTestResource{}
resource.setupResource(driver, pattern)
// Create test input
input = createVolumeIOTestInput(pattern, resource)
})
AfterEach(func() {
if needsCleanup {
resource.cleanupResource(driver, pattern)
}
})
execTestVolumeIO(&input) cleanup := func() {
}) if l.resource != nil {
} l.resource.cleanupResource()
l.resource = nil
}
type volumeIOTestInput struct { if l.testCleanup != nil {
f *framework.Framework l.testCleanup()
name string l.testCleanup = nil
config *TestConfig }
volSource v1.VolumeSource }
testFile string
podSec v1.PodSecurityContext
fileSizes []int64
}
func execTestVolumeIO(input *volumeIOTestInput) {
It("should write files of various sizes, verify size, validate content [Slow]", func() { It("should write files of various sizes, verify size, validate content [Slow]", func() {
f := input.f init()
cs := f.ClientSet defer cleanup()
err := testVolumeIO(f, cs, convertTestConfig(input.config), input.volSource, &input.podSec, input.testFile, input.fileSizes) cs := f.ClientSet
fileSizes := createFileSizes(dInfo.MaxFileSize)
testFile := fmt.Sprintf("%s_io_test_%s", dInfo.Name, f.Namespace.Name)
var fsGroup *int64
if dInfo.Capabilities[CapFsGroup] {
fsGroupVal := int64(1234)
fsGroup = &fsGroupVal
}
podSec := v1.PodSecurityContext{
FSGroup: fsGroup,
}
err := testVolumeIO(f, cs, convertTestConfig(l.config), *l.resource.volSource, &podSec, testFile, fileSizes)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
}) })
} }
......
...@@ -89,101 +89,80 @@ func skipExecTest(driver TestDriver) { ...@@ -89,101 +89,80 @@ func skipExecTest(driver TestDriver) {
} }
} }
func createVolumesTestInput(pattern testpatterns.TestPattern, resource genericVolumeTestResource) volumesTestInput { func (t *volumesTestSuite) defineTests(driver TestDriver, pattern testpatterns.TestPattern) {
var fsGroup *int64 type local struct {
driver := resource.driver config *PerTestConfig
dInfo := driver.GetDriverInfo() testCleanup func()
f := dInfo.Config.Framework
volSource := resource.volSource
if volSource == nil { resource *genericVolumeTestResource
framework.Skipf("Driver %q does not define volumeSource - skipping", dInfo.Name) }
var dInfo = driver.GetDriverInfo()
var l local
// No preconditions to test. Normally they would be in a BeforeEach here.
// This intentionally comes after checking the preconditions because it
// registers its own BeforeEach which creates the namespace. Beware that it
// also registers an AfterEach which renders f unusable. Any code using
// f must run inside an It or Context callback.
f := framework.NewDefaultFramework("volumeio")
init := func() {
l = local{}
// Now do the more expensive test initialization.
l.config, l.testCleanup = driver.PrepareTest(f)
l.resource = createGenericVolumeTestResource(driver, l.config, pattern)
if l.resource.volSource == nil {
framework.Skipf("Driver %q does not define volumeSource - skipping", dInfo.Name)
}
} }
if dInfo.Capabilities[CapFsGroup] { cleanup := func() {
fsGroupVal := int64(1234) if l.resource != nil {
fsGroup = &fsGroupVal l.resource.cleanupResource()
l.resource = nil
}
if l.testCleanup != nil {
l.testCleanup()
l.testCleanup = nil
}
} }
return volumesTestInput{ It("should be mountable", func() {
f: f, skipPersistenceTest(driver)
name: dInfo.Name, init()
config: &dInfo.Config, defer func() {
fsGroup: fsGroup, framework.VolumeTestCleanup(f, convertTestConfig(l.config))
resource: resource, cleanup()
fsType: pattern.FsType, }()
tests: []framework.VolumeTest{
tests := []framework.VolumeTest{
{ {
Volume: *volSource, Volume: *l.resource.volSource,
File: "index.html", File: "index.html",
// Must match content // Must match content
ExpectedContent: fmt.Sprintf("Hello from %s from namespace %s", ExpectedContent: fmt.Sprintf("Hello from %s from namespace %s",
dInfo.Name, f.Namespace.Name), dInfo.Name, f.Namespace.Name),
}, },
}, }
} config := convertTestConfig(l.config)
} framework.InjectHtml(f.ClientSet, config, tests[0].Volume, tests[0].ExpectedContent)
var fsGroup *int64
func (t *volumesTestSuite) execTest(driver TestDriver, pattern testpatterns.TestPattern) { if dInfo.Capabilities[CapFsGroup] {
Context(getTestNameStr(t, pattern), func() { fsGroupVal := int64(1234)
var ( fsGroup = &fsGroupVal
resource genericVolumeTestResource }
input volumesTestInput framework.TestVolumeClient(f.ClientSet, config, fsGroup, pattern.FsType, tests)
needsCleanup bool
)
BeforeEach(func() {
needsCleanup = false
// Skip unsupported tests to avoid unnecessary resource initialization
skipUnsupportedTest(t, driver, pattern)
needsCleanup = true
// Setup test resource for driver and testpattern
resource = genericVolumeTestResource{}
resource.setupResource(driver, pattern)
// Create test input
input = createVolumesTestInput(pattern, resource)
})
AfterEach(func() {
if needsCleanup {
resource.cleanupResource(driver, pattern)
}
})
testVolumes(&input)
}) })
}
type volumesTestInput struct {
f *framework.Framework
name string
config *TestConfig
fsGroup *int64
fsType string
tests []framework.VolumeTest
resource genericVolumeTestResource
}
func testVolumes(input *volumesTestInput) {
It("should be mountable", func() {
f := input.f
cs := f.ClientSet
defer framework.VolumeTestCleanup(f, convertTestConfig(input.config))
skipPersistenceTest(input.resource.driver)
volumeTest := input.tests
config := convertTestConfig(input.config)
framework.InjectHtml(cs, config, volumeTest[0].Volume, volumeTest[0].ExpectedContent)
framework.TestVolumeClient(cs, config, input.fsGroup, input.fsType, input.tests)
})
It("should allow exec of files on the volume", func() { It("should allow exec of files on the volume", func() {
f := input.f skipExecTest(driver)
skipExecTest(input.resource.driver) init()
defer cleanup()
testScriptInPod(f, input.resource.volType, input.resource.volSource, input.resource.driver.GetDriverInfo().Config.ClientNodeSelector) testScriptInPod(f, l.resource.volType, l.resource.volSource, l.config.ClientNodeSelector)
}) })
} }
......
...@@ -212,21 +212,22 @@ func testZonalDelayedBinding(c clientset.Interface, ns string, specifyAllowedTop ...@@ -212,21 +212,22 @@ func testZonalDelayedBinding(c clientset.Interface, ns string, specifyAllowedTop
action := "creating claims with class with waitForFirstConsumer" action := "creating claims with class with waitForFirstConsumer"
suffix := "delayed" suffix := "delayed"
var topoZone string var topoZone string
class := newStorageClass(test, ns, suffix) test.Client = c
test.Class = newStorageClass(test, ns, suffix)
if specifyAllowedTopology { if specifyAllowedTopology {
action += " and allowedTopologies" action += " and allowedTopologies"
suffix += "-topo" suffix += "-topo"
topoZone = getRandomClusterZone(c) topoZone = getRandomClusterZone(c)
addSingleZoneAllowedTopologyToStorageClass(c, class, topoZone) addSingleZoneAllowedTopologyToStorageClass(c, test.Class, topoZone)
} }
By(action) By(action)
var claims []*v1.PersistentVolumeClaim var claims []*v1.PersistentVolumeClaim
for i := 0; i < pvcCount; i++ { for i := 0; i < pvcCount; i++ {
claim := newClaim(test, ns, suffix) claim := newClaim(test, ns, suffix)
claim.Spec.StorageClassName = &class.Name claim.Spec.StorageClassName = &test.Class.Name
claims = append(claims, claim) claims = append(claims, claim)
} }
pvs, node := testsuites.TestBindingWaitForFirstConsumerMultiPVC(test, c, claims, class, nil /* node selector */, false /* expect unschedulable */) pvs, node := test.TestBindingWaitForFirstConsumerMultiPVC(claims, nil /* node selector */, false /* expect unschedulable */)
if node == nil { if node == nil {
framework.Failf("unexpected nil node found") framework.Failf("unexpected nil node found")
} }
...@@ -439,10 +440,11 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { ...@@ -439,10 +440,11 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() {
By("Testing " + test.Name) By("Testing " + test.Name)
suffix := fmt.Sprintf("%d", i) suffix := fmt.Sprintf("%d", i)
class := newStorageClass(test, ns, suffix) test.Client = c
claim := newClaim(test, ns, suffix) test.Class = newStorageClass(test, ns, suffix)
claim.Spec.StorageClassName = &class.Name test.Claim = newClaim(test, ns, suffix)
testsuites.TestDynamicProvisioning(test, c, claim, class) test.Claim.Spec.StorageClassName = &test.Class.Name
test.TestDynamicProvisioning()
} }
// Run the last test with storage.k8s.io/v1beta1 on pvc // Run the last test with storage.k8s.io/v1beta1 on pvc
...@@ -454,9 +456,11 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { ...@@ -454,9 +456,11 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
defer deleteStorageClass(c, class.Name) defer deleteStorageClass(c, class.Name)
claim := newClaim(*betaTest, ns, "beta") betaTest.Client = c
claim.Spec.StorageClassName = &(class.Name) betaTest.Class = nil
testsuites.TestDynamicProvisioning(*betaTest, c, claim, nil) betaTest.Claim = newClaim(*betaTest, ns, "beta")
betaTest.Claim.Spec.StorageClassName = &(class.Name)
(*betaTest).TestDynamicProvisioning()
} }
}) })
...@@ -464,6 +468,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { ...@@ -464,6 +468,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() {
framework.SkipUnlessProviderIs("gce", "gke") framework.SkipUnlessProviderIs("gce", "gke")
test := testsuites.StorageClassTest{ test := testsuites.StorageClassTest{
Client: c,
Name: "HDD PD on GCE/GKE", Name: "HDD PD on GCE/GKE",
CloudProviders: []string{"gce", "gke"}, CloudProviders: []string{"gce", "gke"},
Provisioner: "kubernetes.io/gce-pd", Provisioner: "kubernetes.io/gce-pd",
...@@ -478,12 +483,12 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { ...@@ -478,12 +483,12 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() {
testsuites.PVWriteReadSingleNodeCheck(c, claim, volume, testsuites.NodeSelection{}) testsuites.PVWriteReadSingleNodeCheck(c, claim, volume, testsuites.NodeSelection{})
}, },
} }
class := newStorageClass(test, ns, "reclaimpolicy") test.Class = newStorageClass(test, ns, "reclaimpolicy")
retain := v1.PersistentVolumeReclaimRetain retain := v1.PersistentVolumeReclaimRetain
class.ReclaimPolicy = &retain test.Class.ReclaimPolicy = &retain
claim := newClaim(test, ns, "reclaimpolicy") test.Claim = newClaim(test, ns, "reclaimpolicy")
claim.Spec.StorageClassName = &class.Name test.Claim.Spec.StorageClassName = &test.Class.Name
pv := testsuites.TestDynamicProvisioning(test, c, claim, class) pv := test.TestDynamicProvisioning()
By(fmt.Sprintf("waiting for the provisioned PV %q to enter phase %s", pv.Name, v1.VolumeReleased)) By(fmt.Sprintf("waiting for the provisioned PV %q to enter phase %s", pv.Name, v1.VolumeReleased))
framework.ExpectNoError(framework.WaitForPersistentVolumePhase(v1.VolumeReleased, c, pv.Name, 1*time.Second, 30*time.Second)) framework.ExpectNoError(framework.WaitForPersistentVolumePhase(v1.VolumeReleased, c, pv.Name, 1*time.Second, 30*time.Second))
...@@ -717,17 +722,18 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { ...@@ -717,17 +722,18 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() {
By("creating a StorageClass") By("creating a StorageClass")
test := testsuites.StorageClassTest{ test := testsuites.StorageClassTest{
Client: c,
Name: "external provisioner test", Name: "external provisioner test",
Provisioner: externalPluginName, Provisioner: externalPluginName,
ClaimSize: "1500Mi", ClaimSize: "1500Mi",
ExpectedSize: "1500Mi", ExpectedSize: "1500Mi",
} }
class := newStorageClass(test, ns, "external") test.Class = newStorageClass(test, ns, "external")
claim := newClaim(test, ns, "external") test.Claim = newClaim(test, ns, "external")
claim.Spec.StorageClassName = &(class.Name) test.Claim.Spec.StorageClassName = &test.Class.Name
By("creating a claim with a external provisioning annotation") By("creating a claim with a external provisioning annotation")
testsuites.TestDynamicProvisioning(test, c, claim, class) test.TestDynamicProvisioning()
}) })
}) })
...@@ -737,13 +743,14 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { ...@@ -737,13 +743,14 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() {
By("creating a claim with no annotation") By("creating a claim with no annotation")
test := testsuites.StorageClassTest{ test := testsuites.StorageClassTest{
Client: c,
Name: "default", Name: "default",
ClaimSize: "2Gi", ClaimSize: "2Gi",
ExpectedSize: "2Gi", ExpectedSize: "2Gi",
} }
claim := newClaim(test, ns, "default") test.Claim = newClaim(test, ns, "default")
testsuites.TestDynamicProvisioning(test, c, claim, nil) test.TestDynamicProvisioning()
}) })
// Modifying the default storage class can be disruptive to other tests that depend on it // Modifying the default storage class can be disruptive to other tests that depend on it
...@@ -816,6 +823,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { ...@@ -816,6 +823,7 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() {
serverUrl := "http://" + pod.Status.PodIP + ":8081" serverUrl := "http://" + pod.Status.PodIP + ":8081"
By("creating a StorageClass") By("creating a StorageClass")
test := testsuites.StorageClassTest{ test := testsuites.StorageClassTest{
Client: c,
Name: "Gluster Dynamic provisioner test", Name: "Gluster Dynamic provisioner test",
Provisioner: "kubernetes.io/glusterfs", Provisioner: "kubernetes.io/glusterfs",
ClaimSize: "2Gi", ClaimSize: "2Gi",
...@@ -823,13 +831,13 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { ...@@ -823,13 +831,13 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() {
Parameters: map[string]string{"resturl": serverUrl}, Parameters: map[string]string{"resturl": serverUrl},
} }
suffix := fmt.Sprintf("glusterdptest") suffix := fmt.Sprintf("glusterdptest")
class := newStorageClass(test, ns, suffix) test.Class = newStorageClass(test, ns, suffix)
By("creating a claim object with a suffix for gluster dynamic provisioner") By("creating a claim object with a suffix for gluster dynamic provisioner")
claim := newClaim(test, ns, suffix) test.Claim = newClaim(test, ns, suffix)
claim.Spec.StorageClassName = &class.Name test.Claim.Spec.StorageClassName = &test.Class.Name
testsuites.TestDynamicProvisioning(test, c, claim, class) test.TestDynamicProvisioning()
}) })
}) })
...@@ -928,12 +936,13 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() { ...@@ -928,12 +936,13 @@ var _ = utils.SIGDescribe("Dynamic Provisioning", func() {
} }
By("creating a claim with class with allowedTopologies set") By("creating a claim with class with allowedTopologies set")
suffix := "topology" suffix := "topology"
class := newStorageClass(test, ns, suffix) test.Client = c
test.Class = newStorageClass(test, ns, suffix)
zone := getRandomClusterZone(c) zone := getRandomClusterZone(c)
addSingleZoneAllowedTopologyToStorageClass(c, class, zone) addSingleZoneAllowedTopologyToStorageClass(c, test.Class, zone)
claim := newClaim(test, ns, suffix) test.Claim = newClaim(test, ns, suffix)
claim.Spec.StorageClassName = &class.Name test.Claim.Spec.StorageClassName = &test.Class.Name
pv := testsuites.TestDynamicProvisioning(test, c, claim, class) pv := test.TestDynamicProvisioning()
checkZoneFromLabelAndAffinity(pv, zone, true) checkZoneFromLabelAndAffinity(pv, zone, true)
} }
}) })
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment