Skip to content

Commit 0d579bf

Browse files
authored
Merge pull request kubernetes#79796 from jsafrane/block-test-mismatch
Add test for mismatched usage of filesystem/block volumes
2 parents df9d3a8 + 40b1867 commit 0d579bf

File tree

2 files changed

+84
-4
lines changed

2 files changed

+84
-4
lines changed

test/e2e/storage/testsuites/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ go_library(
2020
importpath = "k8s.io/kubernetes/test/e2e/storage/testsuites",
2121
visibility = ["//visibility:public"],
2222
deps = [
23+
"//pkg/kubelet/events:go_default_library",
2324
"//staging/src/k8s.io/api/core/v1:go_default_library",
2425
"//staging/src/k8s.io/api/storage/v1:go_default_library",
2526
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
2627
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
2728
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
2829
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
30+
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
2931
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
3032
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
3133
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",

test/e2e/storage/testsuites/volumemode.go

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@ import (
2424
v1 "k8s.io/api/core/v1"
2525
storagev1 "k8s.io/api/storage/v1"
2626
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
"k8s.io/apimachinery/pkg/fields"
2728
clientset "k8s.io/client-go/kubernetes"
29+
"k8s.io/kubernetes/pkg/kubelet/events"
2830
"k8s.io/kubernetes/test/e2e/framework"
2931
e2elog "k8s.io/kubernetes/test/e2e/framework/log"
32+
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
3033
"k8s.io/kubernetes/test/e2e/storage/testpatterns"
3134
)
3235

@@ -94,6 +97,11 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
9497
// Now do the more expensive test initialization.
9598
l.config, l.testCleanup = driver.PrepareTest(f)
9699
l.intreeOps, l.migratedOps = getMigrationVolumeOpCounts(f.ClientSet, dInfo.InTreePluginName)
100+
}
101+
102+
// manualInit initializes l.genericVolumeTestResource without creating the PV & PVC objects.
103+
manualInit := func() {
104+
init()
97105

98106
fsType := pattern.FsType
99107
volBindMode := storagev1.VolumeBindingImmediate
@@ -167,7 +175,7 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
167175
case testpatterns.PreprovisionedPV:
168176
if pattern.VolMode == v1.PersistentVolumeBlock && !isBlockSupported {
169177
ginkgo.It("should fail to create pod by failing to mount volume [Slow]", func() {
170-
init()
178+
manualInit()
171179
defer cleanup()
172180

173181
var err error
@@ -196,13 +204,12 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
196204
}()
197205
framework.ExpectError(err)
198206
})
199-
// TODO(mkimuram): Add more tests
200207
}
201208

202209
case testpatterns.DynamicPV:
203210
if pattern.VolMode == v1.PersistentVolumeBlock && !isBlockSupported {
204211
ginkgo.It("should fail in binding dynamic provisioned PV to PVC [Slow]", func() {
205-
init()
212+
manualInit()
206213
defer cleanup()
207214

208215
var err error
@@ -218,12 +225,57 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
218225
err = framework.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, l.cs, l.pvc.Namespace, l.pvc.Name, framework.Poll, framework.ClaimProvisionTimeout)
219226
framework.ExpectError(err)
220227
})
221-
// TODO(mkimuram): Add more tests
222228
}
223229
default:
224230
e2elog.Failf("Volume mode test doesn't support volType: %v", pattern.VolType)
225231
}
226232

233+
ginkgo.It("should fail to use a volume in a pod with mismatched mode [Slow]", func() {
234+
skipBlockTest(driver)
235+
init()
236+
l.genericVolumeTestResource = *createGenericVolumeTestResource(driver, l.config, pattern)
237+
defer cleanup()
238+
239+
ginkgo.By("Creating pod")
240+
var err error
241+
pod := framework.MakeSecPod(l.ns.Name, []*v1.PersistentVolumeClaim{l.pvc}, nil, false, "", false, false, framework.SELinuxLabel, nil)
242+
// Change volumeMounts to volumeDevices and the other way around
243+
pod = swapVolumeMode(pod)
244+
245+
// Run the pod
246+
pod, err = l.cs.CoreV1().Pods(l.ns.Name).Create(pod)
247+
framework.ExpectNoError(err)
248+
defer func() {
249+
framework.ExpectNoError(framework.DeletePodWithWait(f, l.cs, pod))
250+
}()
251+
252+
ginkgo.By("Waiting for pod to fail")
253+
// Wait for an event that the pod is invalid.
254+
eventSelector := fields.Set{
255+
"involvedObject.kind": "Pod",
256+
"involvedObject.name": pod.Name,
257+
"involvedObject.namespace": l.ns.Name,
258+
"reason": events.FailedMountVolume,
259+
}.AsSelector().String()
260+
261+
var msg string
262+
if pattern.VolMode == v1.PersistentVolumeBlock {
263+
msg = "has volumeMode Block, but is specified in volumeMounts"
264+
} else {
265+
msg = "has volumeMode Filesystem, but is specified in volumeDevices"
266+
}
267+
err = e2epod.WaitTimeoutForPodEvent(l.cs, pod.Name, l.ns.Name, eventSelector, msg, framework.PodStartTimeout)
268+
// Events are unreliable, don't depend on them. They're used only to speed up the test.
269+
if err != nil {
270+
e2elog.Logf("Warning: did not get event about mismatched volume use")
271+
}
272+
273+
// Check the pod is still not running
274+
p, err := l.cs.CoreV1().Pods(l.ns.Name).Get(pod.Name, metav1.GetOptions{})
275+
framework.ExpectNoError(err, "could not re-read the pod after event (or timeout)")
276+
framework.ExpectEqual(p.Status.Phase, v1.PodPending)
277+
})
278+
227279
}
228280

229281
func generateConfigsForPreprovisionedPVTest(scName string, volBindMode storagev1.VolumeBindingMode,
@@ -254,3 +306,29 @@ func generateConfigsForPreprovisionedPVTest(scName string, volBindMode storagev1
254306

255307
return scConfig, pvConfig, pvcConfig
256308
}
309+
310+
// swapVolumeMode changes volumeMounts to volumeDevices and the other way around
311+
func swapVolumeMode(podTemplate *v1.Pod) *v1.Pod {
312+
pod := podTemplate.DeepCopy()
313+
for c := range pod.Spec.Containers {
314+
container := &pod.Spec.Containers[c]
315+
container.VolumeDevices = []v1.VolumeDevice{}
316+
container.VolumeMounts = []v1.VolumeMount{}
317+
318+
// Change VolumeMounts to VolumeDevices
319+
for _, volumeMount := range podTemplate.Spec.Containers[c].VolumeMounts {
320+
container.VolumeDevices = append(container.VolumeDevices, v1.VolumeDevice{
321+
Name: volumeMount.Name,
322+
DevicePath: volumeMount.MountPath,
323+
})
324+
}
325+
// Change VolumeDevices to VolumeMounts
326+
for _, volumeDevice := range podTemplate.Spec.Containers[c].VolumeDevices {
327+
container.VolumeMounts = append(container.VolumeMounts, v1.VolumeMount{
328+
Name: volumeDevice.Name,
329+
MountPath: volumeDevice.DevicePath,
330+
})
331+
}
332+
}
333+
return pod
334+
}

0 commit comments

Comments
 (0)