diff --git a/test/e2e/storage/testpatterns/testpattern.go b/test/e2e/storage/testpatterns/testpattern.go index f76ca315218..c73823215ff 100644 --- a/test/e2e/storage/testpatterns/testpattern.go +++ b/test/e2e/storage/testpatterns/testpattern.go @@ -46,6 +46,8 @@ var ( DynamicPV TestVolType = "DynamicPV" // CSIInlineVolume represents a volume type that is defined inline and provided by a CSI driver. CSIInlineVolume TestVolType = "CSIInlineVolume" + // GenericEphemeralVolume represents a volume type that is defined inline and provisioned through a PVC. + GenericEphemeralVolume TestVolType = "GenericEphemeralVolume" ) // TestSnapshotType represents a snapshot type to be tested in a TestSuite @@ -76,11 +78,16 @@ var ( Name: "Inline-volume (default fs)", VolType: InlineVolume, } - // DefaultFsEphemeralVolume is TestPattern for "Ephemeral-volume (default fs)" - DefaultFsEphemeralVolume = TestPattern{ - Name: "Ephemeral-volume (default fs)", + // DefaultFsCSIEphemeralVolume is TestPattern for "CSI Ephemeral-volume (default fs)" + DefaultFsCSIEphemeralVolume = TestPattern{ + Name: "CSI Ephemeral-volume (default fs)", VolType: CSIInlineVolume, } + // DefaultFsGenericEphemeralVolume is TestPattern for "Generic Ephemeral-volume (default fs)" + DefaultFsGenericEphemeralVolume = TestPattern{ + Name: "Generic Ephemeral-volume (default fs) [Feature:GenericEphemeralVolume]", + VolType: GenericEphemeralVolume, + } // DefaultFsPreprovisionedPV is TestPattern for "Pre-provisioned PV (default fs)" DefaultFsPreprovisionedPV = TestPattern{ Name: "Pre-provisioned PV (default fs)", @@ -100,10 +107,16 @@ var ( VolType: InlineVolume, FsType: "ext3", } - // Ext3EphemeralVolume is TestPattern for "Ephemeral-volume (ext3)" - Ext3EphemeralVolume = TestPattern{ - Name: "Ephemeral-volume (ext3)", - VolType: InlineVolume, + // Ext3CSIEphemeralVolume is TestPattern for "CSI Ephemeral-volume (ext3)" + Ext3CSIEphemeralVolume = TestPattern{ + Name: "CSI Ephemeral-volume (ext3)", + VolType: CSIInlineVolume, + FsType: "ext3", + } + // Ext3GenericEphemeralVolume is TestPattern for "Generic Ephemeral-volume (ext3)" + Ext3GenericEphemeralVolume = TestPattern{ + Name: "Generic Ephemeral-volume (ext3) [Feature:GenericEphemeralVolume]", + VolType: GenericEphemeralVolume, FsType: "ext3", } // Ext3PreprovisionedPV is TestPattern for "Pre-provisioned PV (ext3)" @@ -127,12 +140,18 @@ var ( VolType: InlineVolume, FsType: "ext4", } - // Ext4EphemeralVolume is TestPattern for "Ephemeral-volume (ext4)" - Ext4EphemeralVolume = TestPattern{ - Name: "Ephemeral-volume (ext4)", + // Ext4CSIEphemeralVolume is TestPattern for "CSI Ephemeral-volume (ext4)" + Ext4CSIEphemeralVolume = TestPattern{ + Name: "CSI Ephemeral-volume (ext4)", VolType: CSIInlineVolume, FsType: "ext4", } + // Ext4GenericEphemeralVolume is TestPattern for "Generic Ephemeral-volume (ext4)" + Ext4GenericEphemeralVolume = TestPattern{ + Name: "Generic Ephemeral-volume (ext4) [Feature:GenericEphemeralVolume]", + VolType: GenericEphemeralVolume, + FsType: "ext4", + } // Ext4PreprovisionedPV is TestPattern for "Pre-provisioned PV (ext4)" Ext4PreprovisionedPV = TestPattern{ Name: "Pre-provisioned PV (ext4)", @@ -155,13 +174,20 @@ var ( FsType: "xfs", FeatureTag: "[Slow]", } - // XfsEphemeralVolume is TestPattern for "Ephemeral-volume (xfs)" - XfsEphemeralVolume = TestPattern{ - Name: "Ephemeral-volume (xfs)", + // XfsCSIEphemeralVolume is TestPattern for "CSI Ephemeral-volume (xfs)" + XfsCSIEphemeralVolume = TestPattern{ + Name: "CSI Ephemeral-volume (xfs)", VolType: CSIInlineVolume, FsType: "xfs", FeatureTag: "[Slow]", } + // XfsGenericEphemeralVolume is TestPattern for "Generic Ephemeral-volume (xfs)" + XfsGenericEphemeralVolume = TestPattern{ + Name: "Generic Ephemeral-volume (xfs) [Feature:GenericEphemeralVolume]", + VolType: GenericEphemeralVolume, + FsType: "xfs", + FeatureTag: "[Slow]", + } // XfsPreprovisionedPV is TestPattern for "Pre-provisioned PV (xfs)" XfsPreprovisionedPV = TestPattern{ Name: "Pre-provisioned PV (xfs)", @@ -186,13 +212,20 @@ var ( FsType: "ntfs", FeatureTag: "[sig-windows]", } - // NtfsEphemeralVolume is TestPattern for "Ephemeral-volume (ntfs)" - NtfsEphemeralVolume = TestPattern{ - Name: "Ephemeral-volume (ntfs)", + // NtfsCSIEphemeralVolume is TestPattern for "CSI Ephemeral-volume (ntfs)" + NtfsCSIEphemeralVolume = TestPattern{ + Name: "CSI Ephemeral-volume (ntfs) [alpha]", VolType: CSIInlineVolume, FsType: "ntfs", FeatureTag: "[sig-windows]", } + // NtfsGenericEphemeralVolume is TestPattern for "Generic Ephemeral-volume (ntfs)" + NtfsGenericEphemeralVolume = TestPattern{ + Name: "Generic Ephemeral-volume (ntfs) [Feature:GenericEphemeralVolume]", + VolType: GenericEphemeralVolume, + FsType: "ntfs", + FeatureTag: "[sig-windows]", + } // NtfsPreprovisionedPV is TestPattern for "Pre-provisioned PV (ntfs)" NtfsPreprovisionedPV = TestPattern{ Name: "Pre-provisioned PV (ntfs)", diff --git a/test/e2e/storage/testsuites/base.go b/test/e2e/storage/testsuites/base.go index 9913d73696c..aafbb630f2b 100644 --- a/test/e2e/storage/testsuites/base.go +++ b/test/e2e/storage/testsuites/base.go @@ -168,7 +168,7 @@ func skipUnsupportedTest(driver TestDriver, pattern testpatterns.TestPattern) { _, isSupported = driver.(InlineVolumeTestDriver) case testpatterns.PreprovisionedPV: _, isSupported = driver.(PreprovisionedPVTestDriver) - case testpatterns.DynamicPV: + case testpatterns.DynamicPV, testpatterns.GenericEphemeralVolume: _, isSupported = driver.(DynamicPVTestDriver) case testpatterns.CSIInlineVolume: _, isSupported = driver.(EphemeralTestDriver) @@ -240,7 +240,7 @@ func CreateVolumeResource(driver TestDriver, config *PerTestConfig, pattern test r.VolSource = createVolumeSource(r.Pvc.Name, false /* readOnly */) } } - case testpatterns.DynamicPV: + case testpatterns.DynamicPV, testpatterns.GenericEphemeralVolume: framework.Logf("Creating resource for dynamic PV") if dDriver, ok := driver.(DynamicPVTestDriver); ok { var err error @@ -262,10 +262,16 @@ func CreateVolumeResource(driver TestDriver, config *PerTestConfig, pattern test r.Sc, err = cs.StorageV1().StorageClasses().Create(context.TODO(), r.Sc, metav1.CreateOptions{}) framework.ExpectNoError(err) - if r.Sc != nil { + switch pattern.VolType { + case testpatterns.DynamicPV: r.Pv, r.Pvc = createPVCPVFromDynamicProvisionSC( f, dInfo.Name, claimSize, r.Sc, pattern.VolMode, dInfo.RequiredAccessModes) r.VolSource = createVolumeSource(r.Pvc.Name, false /* readOnly */) + case testpatterns.GenericEphemeralVolume: + driverVolumeSizeRange := dDriver.GetDriverInfo().SupportedSizeRange + claimSize, err := getSizeRangesIntersection(testVolumeSizeRange, driverVolumeSizeRange) + framework.ExpectNoError(err, "determine intersection of test size range %+v and driver size range %+v", testVolumeSizeRange, driverVolumeSizeRange) + r.VolSource = createEphemeralVolumeSource(r.Sc.Name, dInfo.RequiredAccessModes, claimSize, false /* readOnly */) } } case testpatterns.CSIInlineVolume: @@ -297,7 +303,28 @@ func createVolumeSource(pvcName string, readOnly bool) *v1.VolumeSource { ReadOnly: readOnly, }, } +} +func createEphemeralVolumeSource(scName string, accessModes []v1.PersistentVolumeAccessMode, claimSize string, readOnly bool) *v1.VolumeSource { + if len(accessModes) == 0 { + accessModes = []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce} + } + return &v1.VolumeSource{ + Ephemeral: &v1.EphemeralVolumeSource{ + VolumeClaimTemplate: &v1.PersistentVolumeClaimTemplate{ + Spec: v1.PersistentVolumeClaimSpec{ + StorageClassName: &scName, + AccessModes: accessModes, + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceStorage: resource.MustParse(claimSize), + }, + }, + }, + }, + ReadOnly: readOnly, + }, + } } // CleanupResource cleans up VolumeResource diff --git a/test/e2e/storage/testsuites/driveroperations.go b/test/e2e/storage/testsuites/driveroperations.go index 0f54febbe36..5026d8d8f79 100644 --- a/test/e2e/storage/testsuites/driveroperations.go +++ b/test/e2e/storage/testsuites/driveroperations.go @@ -40,15 +40,13 @@ func GetDriverNameWithFeatureTags(driver TestDriver) string { // CreateVolume creates volume for test unless dynamicPV or CSI ephemeral inline volume test func CreateVolume(driver TestDriver, config *PerTestConfig, volType testpatterns.TestVolType) TestVolume { switch volType { - case testpatterns.InlineVolume: - fallthrough - case testpatterns.PreprovisionedPV: + case testpatterns.InlineVolume, testpatterns.PreprovisionedPV: if pDriver, ok := driver.(PreprovisionedVolumeTestDriver); ok { return pDriver.CreateVolume(config, volType) } - case testpatterns.CSIInlineVolume: - fallthrough - case testpatterns.DynamicPV: + case testpatterns.CSIInlineVolume, + testpatterns.GenericEphemeralVolume, + testpatterns.DynamicPV: // No need to create volume default: framework.Failf("Invalid volType specified: %v", volType) diff --git a/test/e2e/storage/testsuites/ephemeral.go b/test/e2e/storage/testsuites/ephemeral.go index 1c7eed0f9c1..47314ab8d95 100644 --- a/test/e2e/storage/testsuites/ephemeral.go +++ b/test/e2e/storage/testsuites/ephemeral.go @@ -18,16 +18,17 @@ package testsuites import ( "context" - "flag" "fmt" - "strings" "github.com/onsi/ginkgo" "github.com/onsi/gomega" v1 "k8s.io/api/core/v1" + storagev1 "k8s.io/api/storage/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilerrors "k8s.io/apimachinery/pkg/util/errors" clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/test/e2e/framework" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" @@ -45,15 +46,24 @@ var _ TestSuite = &ephemeralTestSuite{} // InitEphemeralTestSuite returns ephemeralTestSuite that implements TestSuite interface func InitEphemeralTestSuite() TestSuite { + genericLateBinding := testpatterns.DefaultFsGenericEphemeralVolume + genericLateBinding.Name += " (late-binding)" + genericLateBinding.BindingMode = storagev1.VolumeBindingWaitForFirstConsumer + + genericImmediateBinding := testpatterns.DefaultFsGenericEphemeralVolume + genericImmediateBinding.Name += " (immediate-binding)" + genericImmediateBinding.BindingMode = storagev1.VolumeBindingImmediate + + patterns := []testpatterns.TestPattern{ + testpatterns.DefaultFsCSIEphemeralVolume, + genericLateBinding, + genericImmediateBinding, + } + return &ephemeralTestSuite{ tsInfo: TestSuiteInfo{ - Name: "ephemeral", - TestPatterns: []testpatterns.TestPattern{ - { - Name: "inline ephemeral CSI volume", - VolType: testpatterns.CSIInlineVolume, - }, - }, + Name: "ephemeral", + TestPatterns: patterns, }, } } @@ -71,6 +81,7 @@ func (p *ephemeralTestSuite) DefineTests(driver TestDriver, pattern testpatterns driverCleanup func() testCase *EphemeralTest + resource *VolumeResource } var ( dInfo = driver.GetDriverInfo() @@ -80,9 +91,14 @@ func (p *ephemeralTestSuite) DefineTests(driver TestDriver, pattern testpatterns ginkgo.BeforeEach(func() { ok := false - eDriver, ok = driver.(EphemeralTestDriver) + switch pattern.VolType { + case testpatterns.CSIInlineVolume: + eDriver, ok = driver.(EphemeralTestDriver) + case testpatterns.GenericEphemeralVolume: + _, ok = driver.(DynamicPVTestDriver) + } if !ok { - e2eskipper.Skipf("Driver %s doesn't support ephemeral inline volumes -- skipping", dInfo.Name) + e2eskipper.Skipf("Driver %s doesn't support %q volumes -- skipping", dInfo.Name, pattern.VolType) } }) @@ -93,25 +109,47 @@ func (p *ephemeralTestSuite) DefineTests(driver TestDriver, pattern testpatterns f := framework.NewDefaultFramework("ephemeral") init := func() { + if pattern.VolType == testpatterns.GenericEphemeralVolume { + enabled, err := GenericEphemeralVolumesEnabled(f.ClientSet, f.Namespace.Name) + framework.ExpectNoError(err, "check GenericEphemeralVolume feature") + if !enabled { + e2eskipper.Skipf("Cluster doesn't support %q volumes -- skipping", pattern.VolType) + } + } + l = local{} // Now do the more expensive test initialization. l.config, l.driverCleanup = driver.PrepareTest(f) - l.testCase = &EphemeralTest{ - Client: l.config.Framework.ClientSet, - Namespace: f.Namespace.Name, - DriverName: eDriver.GetCSIDriverName(l.config), - Node: l.config.ClientNodeSelection, - GetVolume: func(volumeNumber int) (map[string]string, bool, bool) { - return eDriver.GetVolume(l.config, volumeNumber) - }, + l.resource = CreateVolumeResource(driver, l.config, pattern, e2evolume.SizeRange{}) + + switch pattern.VolType { + case testpatterns.CSIInlineVolume: + l.testCase = &EphemeralTest{ + Client: l.config.Framework.ClientSet, + Namespace: f.Namespace.Name, + DriverName: eDriver.GetCSIDriverName(l.config), + Node: l.config.ClientNodeSelection, + GetVolume: func(volumeNumber int) (map[string]string, bool, bool) { + return eDriver.GetVolume(l.config, volumeNumber) + }, + } + case testpatterns.GenericEphemeralVolume: + l.testCase = &EphemeralTest{ + Client: l.config.Framework.ClientSet, + Namespace: f.Namespace.Name, + Node: l.config.ClientNodeSelection, + VolSource: l.resource.VolSource, + } } } cleanup := func() { - err := tryFunc(l.driverCleanup) - framework.ExpectNoError(err, "while cleaning up driver") - l.driverCleanup = nil + var cleanUpErrs []error + cleanUpErrs = append(cleanUpErrs, l.resource.CleanupResource()) + cleanUpErrs = append(cleanUpErrs, tryFunc(l.driverCleanup)) + err := utilerrors.NewAggregate(cleanUpErrs) + framework.ExpectNoError(err, "while cleaning up") } ginkgo.It("should create read-only inline ephemeral volume", func() { @@ -143,13 +181,17 @@ func (p *ephemeralTestSuite) DefineTests(driver TestDriver, pattern testpatterns defer cleanup() // We test in read-only mode if that is all that the driver supports, - // otherwise read/write. - _, shared, readOnly := eDriver.GetVolume(l.config, 0) + // otherwise read/write. For PVC, both are assumed to be false. + shared := false + readOnly := false + if eDriver != nil { + _, shared, readOnly = eDriver.GetVolume(l.config, 0) + } l.testCase.RunningPodCheck = func(pod *v1.Pod) interface{} { // Create another pod with the same inline volume attributes. pod2 := StartInPodWithInlineVolume(f.ClientSet, f.Namespace.Name, "inline-volume-tester2", "sleep 100000", - []v1.CSIVolumeSource{*pod.Spec.Volumes[0].CSI}, + []v1.VolumeSource{pod.Spec.Volumes[0].VolumeSource}, readOnly, l.testCase.Node) framework.ExpectNoError(e2epod.WaitForPodRunningInNamespaceSlow(f.ClientSet, pod2.Name, pod2.Namespace), "waiting for second pod with inline volume") @@ -172,15 +214,11 @@ func (p *ephemeralTestSuite) DefineTests(driver TestDriver, pattern testpatterns l.testCase.TestEphemeral() }) - var numInlineVolumes = flag.Int("storage.ephemeral."+strings.Replace(driver.GetDriverInfo().Name, ".", "-", -1)+".numInlineVolumes", - 2, "number of ephemeral inline volumes per pod") - ginkgo.It("should support multiple inline ephemeral volumes", func() { init() defer cleanup() - l.testCase.NumInlineVolumes = *numInlineVolumes - gomega.Expect(*numInlineVolumes).To(gomega.BeNumerically(">", 0), "positive number of inline volumes") + l.testCase.NumInlineVolumes = 2 l.testCase.TestEphemeral() }) } @@ -191,6 +229,7 @@ type EphemeralTest struct { Client clientset.Interface Namespace string DriverName string + VolSource *v1.VolumeSource Node e2epod.NodeSelection // GetVolume returns the volume attributes for a @@ -231,28 +270,36 @@ type EphemeralTest struct { func (t EphemeralTest) TestEphemeral() { client := t.Client gomega.Expect(client).NotTo(gomega.BeNil(), "EphemeralTest.Client is required") - gomega.Expect(t.GetVolume).NotTo(gomega.BeNil(), "EphemeralTest.GetVolume is required") - gomega.Expect(t.DriverName).NotTo(gomega.BeEmpty(), "EphemeralTest.DriverName is required") ginkgo.By(fmt.Sprintf("checking the requested inline volume exists in the pod running on node %+v", t.Node)) command := "mount | grep /mnt/test && sleep 10000" - var csiVolumes []v1.CSIVolumeSource + var volumes []v1.VolumeSource numVolumes := t.NumInlineVolumes if numVolumes == 0 { numVolumes = 1 } for i := 0; i < numVolumes; i++ { - attributes, _, readOnly := t.GetVolume(i) - csi := v1.CSIVolumeSource{ - Driver: t.DriverName, - VolumeAttributes: attributes, + var volume v1.VolumeSource + switch { + case t.GetVolume != nil: + attributes, _, readOnly := t.GetVolume(i) + if readOnly && !t.ReadOnly { + e2eskipper.Skipf("inline ephemeral volume #%d is read-only, but the test needs a read/write volume", i) + } + volume = v1.VolumeSource{ + CSI: &v1.CSIVolumeSource{ + Driver: t.DriverName, + VolumeAttributes: attributes, + }, + } + case t.VolSource != nil: + volume = *t.VolSource + default: + framework.Failf("EphemeralTest has neither GetVolume nor VolSource") } - if readOnly && !t.ReadOnly { - e2eskipper.Skipf("inline ephemeral volume #%d is read-only, but the test needs a read/write volume", i) - } - csiVolumes = append(csiVolumes, csi) + volumes = append(volumes, volume) } - pod := StartInPodWithInlineVolume(client, t.Namespace, "inline-volume-tester", command, csiVolumes, t.ReadOnly, t.Node) + pod := StartInPodWithInlineVolume(client, t.Namespace, "inline-volume-tester", command, volumes, t.ReadOnly, t.Node) defer func() { // pod might be nil now. StopPod(client, pod) @@ -271,6 +318,12 @@ func (t EphemeralTest) TestEphemeral() { StopPod(client, pod) pod = nil // Don't stop twice. + // There should be no dangling PVCs in the namespace now. There might be for + // generic ephemeral volumes, if something went wrong... + pvcs, err := client.CoreV1().PersistentVolumeClaims(t.Namespace).List(context.TODO(), metav1.ListOptions{}) + framework.ExpectNoError(err, "list PVCs") + gomega.Expect(pvcs.Items).Should(gomega.BeEmpty(), "no dangling PVCs") + if t.StoppedPodCheck != nil { t.StoppedPodCheck(actualNodeName, runningPodData) } @@ -278,7 +331,7 @@ func (t EphemeralTest) TestEphemeral() { // StartInPodWithInlineVolume starts a command in a pod with given volume(s) mounted to /mnt/test- directory. // The caller is responsible for checking the pod and deleting it. -func StartInPodWithInlineVolume(c clientset.Interface, ns, podName, command string, csiVolumes []v1.CSIVolumeSource, readOnly bool, node e2epod.NodeSelection) *v1.Pod { +func StartInPodWithInlineVolume(c clientset.Interface, ns, podName, command string, volumes []v1.VolumeSource, readOnly bool, node e2epod.NodeSelection) *v1.Pod { pod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", @@ -303,7 +356,7 @@ func StartInPodWithInlineVolume(c clientset.Interface, ns, podName, command stri } e2epod.SetNodeSelection(&pod.Spec, node) - for i, csiVolume := range csiVolumes { + for i, volume := range volumes { name := fmt.Sprintf("my-volume-%d", i) pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, v1.VolumeMount{ @@ -313,10 +366,8 @@ func StartInPodWithInlineVolume(c clientset.Interface, ns, podName, command stri }) pod.Spec.Volumes = append(pod.Spec.Volumes, v1.Volume{ - Name: name, - VolumeSource: v1.VolumeSource{ - CSI: &csiVolume, - }, + Name: name, + VolumeSource: volume, }) } @@ -328,18 +379,49 @@ func StartInPodWithInlineVolume(c clientset.Interface, ns, podName, command stri // CSIInlineVolumesEnabled checks whether the running cluster has the CSIInlineVolumes feature gate enabled. // It does that by trying to create a pod that uses that feature. func CSIInlineVolumesEnabled(c clientset.Interface, ns string) (bool, error) { + return VolumeSourceEnabled(c, ns, v1.VolumeSource{ + CSI: &v1.CSIVolumeSource{ + Driver: "no-such-driver.example.com", + }, + }) +} + +// GenericEphemeralVolumesEnabled checks whether the running cluster has the GenericEphemeralVolume feature gate enabled. +// It does that by trying to create a pod that uses that feature. +func GenericEphemeralVolumesEnabled(c clientset.Interface, ns string) (bool, error) { + storageClassName := "no-such-storage-class" + return VolumeSourceEnabled(c, ns, v1.VolumeSource{ + Ephemeral: &v1.EphemeralVolumeSource{ + VolumeClaimTemplate: &v1.PersistentVolumeClaimTemplate{ + Spec: v1.PersistentVolumeClaimSpec{ + StorageClassName: &storageClassName, + AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + }) +} + +// VolumeSourceEnabled checks whether a certain kind of volume source is enabled by trying +// to create a pod that uses it. +func VolumeSourceEnabled(c clientset.Interface, ns string, volume v1.VolumeSource) (bool, error) { pod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ - GenerateName: "csi-inline-volume-", + GenerateName: "inline-volume-", }, Spec: v1.PodSpec{ Containers: []v1.Container{ { - Name: "csi-volume-tester", + Name: "volume-tester", Image: "no-such-registry/no-such-image", VolumeMounts: []v1.VolumeMount{ { @@ -352,12 +434,8 @@ func CSIInlineVolumesEnabled(c clientset.Interface, ns string) (bool, error) { RestartPolicy: v1.RestartPolicyNever, Volumes: []v1.Volume{ { - Name: "my-volume", - VolumeSource: v1.VolumeSource{ - CSI: &v1.CSIVolumeSource{ - Driver: "no-such-driver.example.com", - }, - }, + Name: "my-volume", + VolumeSource: volume, }, }, },