From 6ab48d1adc54cca8f578461063d854136b11836d Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Thu, 19 Oct 2023 11:08:47 +0200 Subject: [PATCH 1/2] e2e storage: remove dot at end of ginkgo.It text This is unusual and complicates the upcoming refactoring of test definitions. --- test/e2e/storage/testsuites/disruptive.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/e2e/storage/testsuites/disruptive.go b/test/e2e/storage/testsuites/disruptive.go index 518ab45063f..580d410c35d 100644 --- a/test/e2e/storage/testsuites/disruptive.go +++ b/test/e2e/storage/testsuites/disruptive.go @@ -207,26 +207,26 @@ func (s *disruptiveTestSuite) DefineTests(driver storageframework.TestDriver, pa } multiplePodTests := []multiplePodTest{ { - testItStmt: "Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux].", + testItStmt: "Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]", runTestFile: func(ctx context.Context, c clientset.Interface, f *framework.Framework, pod1, pod2 *v1.Pod) { storageutils.TestVolumeUnmountsFromDeletedPodWithForceOption(ctx, c, f, pod1, false, false, pod2, e2epod.VolumeMountPath1) }, }, { - testItStmt: "Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux].", + testItStmt: "Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]", runTestFile: func(ctx context.Context, c clientset.Interface, f *framework.Framework, pod1, pod2 *v1.Pod) { storageutils.TestVolumeUnmountsFromDeletedPodWithForceOption(ctx, c, f, pod1, true, false, pod2, e2epod.VolumeMountPath1) }, }, { - testItStmt: "Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux].", + testItStmt: "Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]", changeSELinuxContexts: true, runTestFile: func(ctx context.Context, c clientset.Interface, f *framework.Framework, pod1, pod2 *v1.Pod) { storageutils.TestVolumeUnmountsFromDeletedPodWithForceOption(ctx, c, f, pod1, false, false, pod2, e2epod.VolumeMountPath1) }, }, { - testItStmt: "Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux].", + testItStmt: "Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]", changeSELinuxContexts: true, runTestFile: func(ctx context.Context, c clientset.Interface, f *framework.Framework, pod1, pod2 *v1.Pod) { storageutils.TestVolumeUnmountsFromDeletedPodWithForceOption(ctx, c, f, pod1, true, false, pod2, e2epod.VolumeMountPath1) From 27afb7d75d20d7e986095b0d7125da60ba6322f0 Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Tue, 20 Jun 2023 21:11:39 +0200 Subject: [PATCH 2/2] e2e storage: use framework to tag tests This makes it possible to select tests through `ginkgo --label-filter` also for the custom labels. --- test/e2e/framework/ginkgowrapper.go | 20 +++++ test/e2e/framework/ginkgowrapper_test.go | 52 +++++++++++++ .../unittests/features/kube_features.go | 35 +++++++++ test/e2e/storage/csi_volumes.go | 7 +- test/e2e/storage/drivers/csi.go | 11 +-- test/e2e/storage/drivers/in_tree.go | 19 +++-- test/e2e/storage/external/external.go | 7 +- .../storage/framework/driver_operations.go | 10 +-- test/e2e/storage/framework/testdriver.go | 2 +- test/e2e/storage/framework/testpattern.go | 74 ++++++++++--------- test/e2e/storage/framework/testsuite.go | 11 ++- test/e2e/storage/in_tree_volumes.go | 5 +- test/e2e/storage/testsuites/disruptive.go | 2 +- test/e2e/storage/testsuites/multivolume.go | 6 +- .../storage/testsuites/readwriteoncepod.go | 2 +- test/e2e/storage/testsuites/snapshottable.go | 3 +- .../testsuites/snapshottable_stress.go | 3 +- 17 files changed, 196 insertions(+), 73 deletions(-) create mode 100644 test/e2e/framework/ginkgowrapper_test.go create mode 100644 test/e2e/framework/internal/unittests/features/kube_features.go diff --git a/test/e2e/framework/ginkgowrapper.go b/test/e2e/framework/ginkgowrapper.go index f783e1778c9..01d226a578b 100644 --- a/test/e2e/framework/ginkgowrapper.go +++ b/test/e2e/framework/ginkgowrapper.go @@ -21,6 +21,7 @@ import ( "path" "reflect" "regexp" + "slices" "strings" "github.com/onsi/ginkgo/v2" @@ -457,3 +458,22 @@ type label struct { func newLabel(parts ...string) label { return label{parts: parts} } + +// TagsEqual can be used to check whether two tags are the same. +// It's safe to compare e.g. the result of WithSlow() against the result +// of WithSerial(), the result will be false. False is also returned +// when a parameter is some completely different value. +func TagsEqual(a, b interface{}) bool { + al, ok := a.(label) + if !ok { + return false + } + bl, ok := b.(label) + if !ok { + return false + } + if al.extra != bl.extra { + return false + } + return slices.Equal(al.parts, bl.parts) +} diff --git a/test/e2e/framework/ginkgowrapper_test.go b/test/e2e/framework/ginkgowrapper_test.go new file mode 100644 index 00000000000..99125a08eb9 --- /dev/null +++ b/test/e2e/framework/ginkgowrapper_test.go @@ -0,0 +1,52 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package framework + +import ( + "fmt" + "testing" + + "k8s.io/kubernetes/test/e2e/framework/internal/unittests/features" +) + +func TestTagsEqual(t *testing.T) { + testcases := []struct { + a, b interface{} + expectEqual bool + }{ + {1, 2, false}, + {2, 2, false}, + {WithSlow(), 2, false}, + {WithSlow(), WithSerial(), false}, + {WithSerial(), WithSlow(), false}, + {WithSlow(), WithSlow(), true}, + {WithSerial(), WithSerial(), true}, + {WithLabel("hello"), WithLabel("world"), false}, + {WithLabel("hello"), WithLabel("hello"), true}, + {WithFeatureGate(features.Test), WithLabel("Test"), false}, + {WithFeatureGate(features.Test), WithFeatureGate(features.Test), true}, + } + + for _, tc := range testcases { + t.Run(fmt.Sprintf("%v=%v", tc.a, tc.b), func(t *testing.T) { + actualEqual := TagsEqual(tc.a, tc.b) + if actualEqual != tc.expectEqual { + t.Errorf("expected %v, got %v", tc.expectEqual, actualEqual) + } + }) + } +} diff --git a/test/e2e/framework/internal/unittests/features/kube_features.go b/test/e2e/framework/internal/unittests/features/kube_features.go new file mode 100644 index 00000000000..257701c2bb7 --- /dev/null +++ b/test/e2e/framework/internal/unittests/features/kube_features.go @@ -0,0 +1,35 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package features + +import ( + "k8s.io/apimachinery/pkg/util/runtime" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/component-base/featuregate" +) + +const ( + Test featuregate.Feature = "Test" +) + +func init() { + runtime.Must(utilfeature.DefaultMutableFeatureGate.Add(defaultKubernetesFeatureGates)) +} + +var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ + Test: {Default: false, PreRelease: featuregate.Alpha}, +} diff --git a/test/e2e/storage/csi_volumes.go b/test/e2e/storage/csi_volumes.go index 6ca1c27a84f..eec950dc3cd 100644 --- a/test/e2e/storage/csi_volumes.go +++ b/test/e2e/storage/csi_volumes.go @@ -17,12 +17,11 @@ limitations under the License. package storage import ( + "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/drivers" storageframework "k8s.io/kubernetes/test/e2e/storage/framework" "k8s.io/kubernetes/test/e2e/storage/testsuites" "k8s.io/kubernetes/test/e2e/storage/utils" - - "github.com/onsi/ginkgo/v2" ) // List of testDrivers to be executed in below loop @@ -37,8 +36,10 @@ var _ = utils.SIGDescribe("CSI Volumes", func() { for _, initDriver := range csiTestDrivers { curDriver := initDriver() - ginkgo.Context(storageframework.GetDriverNameWithFeatureTags(curDriver), func() { + args := storageframework.GetDriverNameWithFeatureTags(curDriver) + args = append(args, func() { storageframework.DefineTestSuites(curDriver, testsuites.CSISuites) }) + framework.Context(args...) } }) diff --git a/test/e2e/storage/drivers/csi.go b/test/e2e/storage/drivers/csi.go index 9056f5f28a5..e32a1cef21e 100644 --- a/test/e2e/storage/drivers/csi.go +++ b/test/e2e/storage/drivers/csi.go @@ -61,6 +61,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" "k8s.io/klog/v2" + "k8s.io/kubernetes/test/e2e/feature" "k8s.io/kubernetes/test/e2e/framework" e2enode "k8s.io/kubernetes/test/e2e/framework/node" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" @@ -96,7 +97,6 @@ func initHostPathCSIDriver(name string, capabilities map[storageframework.Capabi return &hostpathCSIDriver{ driverInfo: storageframework.DriverInfo{ Name: name, - FeatureTag: "", MaxFileSize: storageframework.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType @@ -488,7 +488,6 @@ func InitMockCSIDriver(driverOpts CSIMockDriverOpts) MockCSITestDriver { return &mockCSIDriver{ driverInfo: storageframework.DriverInfo{ Name: "csi-mock", - FeatureTag: "", MaxFileSize: storageframework.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType @@ -796,7 +795,7 @@ func InitGcePDCSIDriver() storageframework.TestDriver { return &gcePDCSIDriver{ driverInfo: storageframework.DriverInfo{ Name: GCEPDCSIDriverName, - FeatureTag: "[Serial]", + TestTags: []interface{}{framework.WithSerial()}, MaxFileSize: storageframework.FileSizeMedium, SupportedSizeRange: e2evolume.SizeRange{ Min: "5Gi", @@ -855,8 +854,10 @@ func (g *gcePDCSIDriver) SkipUnsupportedTest(pattern storageframework.TestPatter if pattern.FsType == "xfs" { e2eskipper.SkipUnlessNodeOSDistroIs("ubuntu", "custom") } - if pattern.FeatureTag == "[Feature:Windows]" { - e2eskipper.Skipf("Skipping tests for windows since CSI does not support it yet") + for _, tag := range pattern.TestTags { + if framework.TagsEqual(tag, feature.Windows) { + e2eskipper.Skipf("Skipping tests for windows since CSI does not support it yet") + } } } diff --git a/test/e2e/storage/drivers/in_tree.go b/test/e2e/storage/drivers/in_tree.go index 8bd3a12df59..7c68fd63667 100644 --- a/test/e2e/storage/drivers/in_tree.go +++ b/test/e2e/storage/drivers/in_tree.go @@ -51,6 +51,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apiserver/pkg/authentication/serviceaccount" clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/feature" "k8s.io/kubernetes/test/e2e/framework" e2eauth "k8s.io/kubernetes/test/e2e/framework/auth" e2enode "k8s.io/kubernetes/test/e2e/framework/node" @@ -240,7 +241,7 @@ func InitISCSIDriver() storageframework.TestDriver { driverInfo: storageframework.DriverInfo{ Name: "iscsi", InTreePluginName: "kubernetes.io/iscsi", - FeatureTag: "[Feature:Volumes]", + TestTags: []interface{}{feature.Volumes}, MaxFileSize: storageframework.FileSizeMedium, SupportedFsType: sets.NewString( "", // Default fsType @@ -423,7 +424,7 @@ func InitRbdDriver() storageframework.TestDriver { driverInfo: storageframework.DriverInfo{ Name: "rbd", InTreePluginName: "kubernetes.io/rbd", - FeatureTag: "[Feature:Volumes][Serial]", + TestTags: []interface{}{feature.Volumes, framework.WithSerial()}, MaxFileSize: storageframework.FileSizeMedium, SupportedSizeRange: e2evolume.SizeRange{ Min: "1Gi", @@ -553,7 +554,7 @@ func InitCephFSDriver() storageframework.TestDriver { driverInfo: storageframework.DriverInfo{ Name: "ceph", InTreePluginName: "kubernetes.io/cephfs", - FeatureTag: "[Feature:Volumes][Serial]", + TestTags: []interface{}{feature.Volumes, framework.WithSerial()}, MaxFileSize: storageframework.FileSizeMedium, SupportedSizeRange: e2evolume.SizeRange{ Min: "1Gi", @@ -1083,8 +1084,10 @@ func (g *gcePdDriver) GetDriverInfo() *storageframework.DriverInfo { func (g *gcePdDriver) SkipUnsupportedTest(pattern storageframework.TestPattern) { e2eskipper.SkipUnlessProviderIs("gce", "gke") - if pattern.FeatureTag == "[Feature:Windows]" { - e2eskipper.SkipUnlessNodeOSDistroIs("windows") + for _, tag := range pattern.TestTags { + if tag == feature.Windows { + e2eskipper.SkipUnlessNodeOSDistroIs("windows") + } } } @@ -1615,16 +1618,16 @@ func InitLocalDriverWithVolumeType(volumeType utils.LocalVolumeType) func() stor } return func() storageframework.TestDriver { // custom tag to distinguish from tests of other volume types - featureTag := fmt.Sprintf("[LocalVolumeType: %s]", volumeType) + testTags := []interface{}{fmt.Sprintf("[LocalVolumeType: %s]", volumeType)} // For GCE Local SSD volumes, we must run serially if volumeType == utils.LocalVolumeGCELocalSSD { - featureTag += " [Serial]" + testTags = append(testTags, framework.WithSerial()) } return &localDriver{ driverInfo: storageframework.DriverInfo{ Name: "local", InTreePluginName: "kubernetes.io/local-volume", - FeatureTag: featureTag, + TestTags: testTags, MaxFileSize: maxFileSize, SupportedFsType: supportedFsTypes, Capabilities: capabilities, diff --git a/test/e2e/storage/external/external.go b/test/e2e/storage/external/external.go index 85d9d73e76a..bb51fcacd84 100644 --- a/test/e2e/storage/external/external.go +++ b/test/e2e/storage/external/external.go @@ -41,7 +41,6 @@ import ( "k8s.io/kubernetes/test/e2e/storage/testsuites" "k8s.io/kubernetes/test/e2e/storage/utils" - "github.com/onsi/ginkgo/v2" "github.com/onsi/gomega" ) @@ -170,10 +169,12 @@ func AddDriverDefinition(filename string) error { return fmt.Errorf("%q: DriverInfo.Name not set", filename) } - description := "External Storage " + storageframework.GetDriverNameWithFeatureTags(driver) - ginkgo.Describe(description, func() { + args := []interface{}{"External Storage"} + args = append(args, storageframework.GetDriverNameWithFeatureTags(driver)...) + args = append(args, func() { storageframework.DefineTestSuites(driver, testsuites.CSISuites) }) + framework.Describe(args) return nil } diff --git a/test/e2e/storage/framework/driver_operations.go b/test/e2e/storage/framework/driver_operations.go index 1594afef33e..8c850245144 100644 --- a/test/e2e/storage/framework/driver_operations.go +++ b/test/e2e/storage/framework/driver_operations.go @@ -27,14 +27,14 @@ import ( "k8s.io/kubernetes/test/e2e/framework" ) -// GetDriverNameWithFeatureTags returns driver name with feature tags -// For example) +// GetDriverNameWithFeatureTags returns parameters that can be passed to framework.Context. +// For example: // - [Driver: nfs] -// - [Driver: rbd][Feature:Volumes] -func GetDriverNameWithFeatureTags(driver TestDriver) string { +// - [Driver: rbd], feature.Volumes +func GetDriverNameWithFeatureTags(driver TestDriver) []interface{} { dInfo := driver.GetDriverInfo() - return fmt.Sprintf("[Driver: %s]%s", dInfo.Name, dInfo.FeatureTag) + return append([]interface{}{fmt.Sprintf("[Driver: %s]", dInfo.Name)}, dInfo.TestTags...) } // CreateVolume creates volume for test unless dynamicPV or CSI ephemeral inline volume test diff --git a/test/e2e/storage/framework/testdriver.go b/test/e2e/storage/framework/testdriver.go index ba7936874e6..c1e71179f81 100644 --- a/test/e2e/storage/framework/testdriver.go +++ b/test/e2e/storage/framework/testdriver.go @@ -219,7 +219,7 @@ type DriverInfo struct { // plugin if it exists and is empty if this DriverInfo represents a CSI // Driver InTreePluginName string - FeatureTag string // FeatureTag for the driver + TestTags []interface{} // tags for the driver (e.g. framework.WithSlow()) // Maximum single file size supported by this driver MaxFileSize int64 diff --git a/test/e2e/storage/framework/testpattern.go b/test/e2e/storage/framework/testpattern.go index 4abbc06b7a2..941ca22dfdb 100644 --- a/test/e2e/storage/framework/testpattern.go +++ b/test/e2e/storage/framework/testpattern.go @@ -19,6 +19,8 @@ package framework import ( v1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" + "k8s.io/kubernetes/test/e2e/feature" + "k8s.io/kubernetes/test/e2e/framework" e2evolume "k8s.io/kubernetes/test/e2e/framework/volume" ) @@ -77,7 +79,7 @@ func (t TestSnapshotDeletionPolicy) String() string { // TestPattern represents a combination of parameters to be tested in a TestSuite type TestPattern struct { Name string // Name of TestPattern - FeatureTag string // featureTag for the TestSuite + TestTags []interface{} // additional parameters for framework.It, like framework.WithDisruptive() VolType TestVolType // Volume type of the volume FsType string // Fstype of the volume VolMode v1.PersistentVolumeMode // PersistentVolumeMode of the volume @@ -191,38 +193,38 @@ var ( // XfsInlineVolume is TestPattern for "Inline-volume (xfs)" XfsInlineVolume = TestPattern{ - Name: "Inline-volume (xfs)", - VolType: InlineVolume, - FsType: "xfs", - FeatureTag: "[Slow]", + Name: "Inline-volume (xfs)", + VolType: InlineVolume, + FsType: "xfs", + TestTags: []interface{}{framework.WithSlow()}, } // XfsCSIEphemeralVolume is TestPattern for "CSI Ephemeral-volume (xfs)" XfsCSIEphemeralVolume = TestPattern{ - Name: "CSI Ephemeral-volume (xfs)", - VolType: CSIInlineVolume, - FsType: "xfs", - FeatureTag: "[Slow]", + Name: "CSI Ephemeral-volume (xfs)", + VolType: CSIInlineVolume, + FsType: "xfs", + TestTags: []interface{}{framework.WithSlow()}, } // XfsGenericEphemeralVolume is TestPattern for "Generic Ephemeral-volume (xfs)" XfsGenericEphemeralVolume = TestPattern{ - Name: "Generic Ephemeral-volume (xfs)", - VolType: GenericEphemeralVolume, - FsType: "xfs", - FeatureTag: "[Slow]", + Name: "Generic Ephemeral-volume (xfs)", + VolType: GenericEphemeralVolume, + FsType: "xfs", + TestTags: []interface{}{framework.WithSlow()}, } // XfsPreprovisionedPV is TestPattern for "Pre-provisioned PV (xfs)" XfsPreprovisionedPV = TestPattern{ - Name: "Pre-provisioned PV (xfs)", - VolType: PreprovisionedPV, - FsType: "xfs", - FeatureTag: "[Slow]", + Name: "Pre-provisioned PV (xfs)", + VolType: PreprovisionedPV, + FsType: "xfs", + TestTags: []interface{}{framework.WithSlow()}, } // XfsDynamicPV is TestPattern for "Dynamic PV (xfs)" XfsDynamicPV = TestPattern{ Name: "Dynamic PV (xfs)", VolType: DynamicPV, FsType: "xfs", - FeatureTag: "[Slow]", + TestTags: []interface{}{framework.WithSlow()}, SnapshotType: DynamicCreatedSnapshot, SnapshotDeletionPolicy: DeleteSnapshot, } @@ -231,38 +233,38 @@ var ( // NtfsInlineVolume is TestPattern for "Inline-volume (ntfs)" NtfsInlineVolume = TestPattern{ - Name: "Inline-volume (ntfs)", - VolType: InlineVolume, - FsType: "ntfs", - FeatureTag: "[Feature:Windows]", + Name: "Inline-volume (ntfs)", + VolType: InlineVolume, + FsType: "ntfs", + TestTags: []interface{}{feature.Windows}, } // NtfsCSIEphemeralVolume is TestPattern for "CSI Ephemeral-volume (ntfs)" NtfsCSIEphemeralVolume = TestPattern{ - Name: "CSI Ephemeral-volume (ntfs) [alpha]", - VolType: CSIInlineVolume, - FsType: "ntfs", - FeatureTag: "[Feature:Windows]", + Name: "CSI Ephemeral-volume (ntfs) [alpha]", + VolType: CSIInlineVolume, + FsType: "ntfs", + TestTags: []interface{}{feature.Windows}, } // NtfsGenericEphemeralVolume is TestPattern for "Generic Ephemeral-volume (ntfs)" NtfsGenericEphemeralVolume = TestPattern{ - Name: "Generic Ephemeral-volume (ntfs)", - VolType: GenericEphemeralVolume, - FsType: "ntfs", - FeatureTag: "[Feature:Windows]", + Name: "Generic Ephemeral-volume (ntfs)", + VolType: GenericEphemeralVolume, + FsType: "ntfs", + TestTags: []interface{}{feature.Windows}, } // NtfsPreprovisionedPV is TestPattern for "Pre-provisioned PV (ntfs)" NtfsPreprovisionedPV = TestPattern{ - Name: "Pre-provisioned PV (ntfs)", - VolType: PreprovisionedPV, - FsType: "ntfs", - FeatureTag: "[Feature:Windows]", + Name: "Pre-provisioned PV (ntfs)", + VolType: PreprovisionedPV, + FsType: "ntfs", + TestTags: []interface{}{feature.Windows}, } // NtfsDynamicPV is TestPattern for "Dynamic PV (ntfs)" NtfsDynamicPV = TestPattern{ Name: "Dynamic PV (ntfs)", VolType: DynamicPV, FsType: "ntfs", - FeatureTag: "[Feature:Windows]", + TestTags: []interface{}{feature.Windows}, SnapshotDeletionPolicy: DeleteSnapshot, SnapshotType: DynamicCreatedSnapshot, } @@ -369,7 +371,7 @@ var ( VolType: DynamicPV, AllowExpansion: true, FsType: "ntfs", - FeatureTag: "[Feature:Windows]", + TestTags: []interface{}{feature.Windows}, } // BlockVolModeDynamicPVAllowExpansion is TestPattern for "Dynamic PV (block volmode)(allowExpansion)" diff --git a/test/e2e/storage/framework/testsuite.go b/test/e2e/storage/framework/testsuite.go index 2c9ae8a3755..b08cd25a0f5 100644 --- a/test/e2e/storage/framework/testsuite.go +++ b/test/e2e/storage/framework/testsuite.go @@ -46,8 +46,12 @@ type TestSuite interface { // This function actually register tests inside testsuite func RegisterTests(suite TestSuite, driver TestDriver, pattern TestPattern) { tsInfo := suite.GetTestSuiteInfo() - testName := fmt.Sprintf("[Testpattern: %s]%s %s%s", pattern.Name, pattern.FeatureTag, tsInfo.Name, tsInfo.FeatureTag) - ginkgo.Context(testName, func() { + var args []interface{} + args = append(args, fmt.Sprintf("[Testpattern: %s]", pattern.Name)) + args = append(args, pattern.TestTags...) + args = append(args, tsInfo.Name) + args = append(args, tsInfo.TestTags...) + args = append(args, func() { ginkgo.BeforeEach(func() { // skip all the invalid combination of driver and pattern SkipInvalidDriverPatternCombination(driver, pattern) @@ -60,6 +64,7 @@ func RegisterTests(suite TestSuite, driver TestDriver, pattern TestPattern) { // might still needed for specific independent test cases. suite.DefineTests(driver, pattern) }) + framework.Context(args...) } // DefineTestSuites defines tests for all testpatterns and all testSuites for a driver @@ -75,7 +80,7 @@ func DefineTestSuites(driver TestDriver, tsInits []func() TestSuite) { // TestSuiteInfo represents a set of parameters for TestSuite type TestSuiteInfo struct { Name string // name of the TestSuite - FeatureTag string // featureTag for the TestSuite + TestTags []interface{} // additional parameters for framework.It, like framework.WithDisruptive() TestPatterns []TestPattern // Slice of TestPattern for the TestSuite SupportedSizeRange e2evolume.SizeRange // Size range supported by the test suite } diff --git a/test/e2e/storage/in_tree_volumes.go b/test/e2e/storage/in_tree_volumes.go index d7dfc4062fe..10b3e1a7bd1 100644 --- a/test/e2e/storage/in_tree_volumes.go +++ b/test/e2e/storage/in_tree_volumes.go @@ -19,7 +19,6 @@ package storage import ( "os" - "github.com/onsi/ginkgo/v2" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/drivers" storageframework "k8s.io/kubernetes/test/e2e/storage/framework" @@ -80,8 +79,8 @@ var _ = utils.SIGDescribe("In-tree Volumes", func() { for _, initDriver := range testDrivers { curDriver := initDriver() - ginkgo.Context(storageframework.GetDriverNameWithFeatureTags(curDriver), func() { + framework.Context(append(storageframework.GetDriverNameWithFeatureTags(curDriver), func() { storageframework.DefineTestSuites(curDriver, testsuites.BaseSuites) - }) + })...) } }) diff --git a/test/e2e/storage/testsuites/disruptive.go b/test/e2e/storage/testsuites/disruptive.go index 580d410c35d..b6e14500d02 100644 --- a/test/e2e/storage/testsuites/disruptive.go +++ b/test/e2e/storage/testsuites/disruptive.go @@ -42,7 +42,7 @@ func InitCustomDisruptiveTestSuite(patterns []storageframework.TestPattern) stor return &disruptiveTestSuite{ tsInfo: storageframework.TestSuiteInfo{ Name: "disruptive", - FeatureTag: "[Disruptive][LinuxOnly]", + TestTags: []interface{}{framework.WithDisruptive(), framework.WithLabel("LinuxOnly")}, TestPatterns: patterns, }, } diff --git a/test/e2e/storage/testsuites/multivolume.go b/test/e2e/storage/testsuites/multivolume.go index e820c190742..8f3263c8fb9 100644 --- a/test/e2e/storage/testsuites/multivolume.go +++ b/test/e2e/storage/testsuites/multivolume.go @@ -19,6 +19,7 @@ package testsuites import ( "context" "fmt" + "reflect" "time" "github.com/onsi/ginkgo/v2" @@ -26,6 +27,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/errors" clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/feature" "k8s.io/kubernetes/test/e2e/framework" e2enode "k8s.io/kubernetes/test/e2e/framework/node" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" @@ -316,7 +318,7 @@ func (t *multiVolumeTestSuite) DefineTests(driver storageframework.TestDriver, p // [ node1 ] // | | <- same volume mode // [volume1] -> [restored volume1 snapshot] - ginkgo.It("should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly][Feature:VolumeSnapshotDataSource][Feature:VolumeSourceXFS]", func(ctx context.Context) { + f.It("should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly]", feature.VolumeSnapshotDataSource, feature.VolumeSourceXFS, func(ctx context.Context) { init(ctx) ginkgo.DeferCleanup(cleanup) @@ -420,7 +422,7 @@ func (t *multiVolumeTestSuite) DefineTests(driver storageframework.TestDriver, p e2eskipper.Skipf("Driver %q does not support multiple concurrent pods - skipping", dInfo.Name) } - if l.driver.GetDriverInfo().Name == "vsphere" && pattern == storageframework.BlockVolModeDynamicPV { + if l.driver.GetDriverInfo().Name == "vsphere" && reflect.DeepEqual(pattern, storageframework.BlockVolModeDynamicPV) { e2eskipper.Skipf("Driver %q does not support read only raw block volumes - skipping", dInfo.Name) } diff --git a/test/e2e/storage/testsuites/readwriteoncepod.go b/test/e2e/storage/testsuites/readwriteoncepod.go index 4e95460a495..64777cc786c 100644 --- a/test/e2e/storage/testsuites/readwriteoncepod.go +++ b/test/e2e/storage/testsuites/readwriteoncepod.go @@ -60,7 +60,7 @@ func InitCustomReadWriteOncePodTestSuite(patterns []storageframework.TestPattern tsInfo: storageframework.TestSuiteInfo{ Name: "read-write-once-pod", TestPatterns: patterns, - FeatureTag: "[MinimumKubeletVersion:1.27]", + TestTags: []interface{}{framework.WithLabel("MinimumKubeletVersion:1.27")}, }, } } diff --git a/test/e2e/storage/testsuites/snapshottable.go b/test/e2e/storage/testsuites/snapshottable.go index e40fdcc1345..2343cb8e7a6 100644 --- a/test/e2e/storage/testsuites/snapshottable.go +++ b/test/e2e/storage/testsuites/snapshottable.go @@ -33,6 +33,7 @@ import ( "k8s.io/client-go/dynamic" clientset "k8s.io/client-go/kubernetes" "k8s.io/component-helpers/storage/ephemeral" + "k8s.io/kubernetes/test/e2e/feature" "k8s.io/kubernetes/test/e2e/framework" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" e2eoutput "k8s.io/kubernetes/test/e2e/framework/pod/output" @@ -66,7 +67,7 @@ func InitCustomSnapshottableTestSuite(patterns []storageframework.TestPattern) s SupportedSizeRange: e2evolume.SizeRange{ Min: "1Mi", }, - FeatureTag: "[Feature:VolumeSnapshotDataSource]", + TestTags: []interface{}{feature.VolumeSnapshotDataSource}, }, } } diff --git a/test/e2e/storage/testsuites/snapshottable_stress.go b/test/e2e/storage/testsuites/snapshottable_stress.go index a90171c767d..ab5a9da34c1 100644 --- a/test/e2e/storage/testsuites/snapshottable_stress.go +++ b/test/e2e/storage/testsuites/snapshottable_stress.go @@ -28,6 +28,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" errors "k8s.io/apimachinery/pkg/util/errors" clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/test/e2e/feature" "k8s.io/kubernetes/test/e2e/framework" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" e2epv "k8s.io/kubernetes/test/e2e/framework/pv" @@ -67,7 +68,7 @@ func InitCustomSnapshottableStressTestSuite(patterns []storageframework.TestPatt SupportedSizeRange: e2evolume.SizeRange{ Min: "1Mi", }, - FeatureTag: "[Feature:VolumeSnapshotDataSource]", + TestTags: []interface{}{feature.VolumeSnapshotDataSource}, }, } }