From 04300826fd0d719bb166905bb6c8a3286a171465 Mon Sep 17 00:00:00 2001 From: Masaki Kimura Date: Thu, 8 Aug 2019 19:08:24 +0000 Subject: [PATCH 1/3] Rename WaitTimeoutForPodEvent to WaitTimeoutForEvent and move it to common/events.go --- test/e2e/common/container_probe.go | 4 ++-- test/e2e/common/events.go | 24 +++++++++++++++++++++++ test/e2e/common/runtimeclass.go | 4 ++-- test/e2e/framework/pod/wait.go | 22 --------------------- test/e2e/storage/testsuites/BUILD | 1 + test/e2e/storage/testsuites/volumemode.go | 4 ++-- 6 files changed, 31 insertions(+), 28 deletions(-) diff --git a/test/e2e/common/container_probe.go b/test/e2e/common/container_probe.go index 585e6fff4bf..fea24588cd8 100644 --- a/test/e2e/common/container_probe.go +++ b/test/e2e/common/container_probe.go @@ -259,8 +259,8 @@ var _ = framework.KubeDescribe("Probing container", func() { "involvedObject.namespace": f.Namespace.Name, "reason": events.ContainerProbeWarning, }.AsSelector().String() - framework.ExpectNoError(e2epod.WaitTimeoutForPodEvent( - f.ClientSet, pod.Name, f.Namespace.Name, expectedEvent, "0.0.0.0", framework.PodEventTimeout)) + framework.ExpectNoError(WaitTimeoutForEvent( + f.ClientSet, f.Namespace.Name, expectedEvent, "0.0.0.0", framework.PodEventTimeout)) }) }) diff --git a/test/e2e/common/events.go b/test/e2e/common/events.go index 8fd5833ef45..1d3b7f45a0e 100644 --- a/test/e2e/common/events.go +++ b/test/e2e/common/events.go @@ -18,6 +18,7 @@ package common import ( "fmt" + "strings" "sync" "time" @@ -27,6 +28,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" + clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" "k8s.io/kubernetes/test/e2e/framework" @@ -149,3 +151,25 @@ func ObserveEventAfterAction(f *framework.Framework, eventPredicate func(*v1.Eve }) return err == nil, err } + +// WaitTimeoutForEvent waits the given timeout duration for an event to occur. +func WaitTimeoutForEvent(c clientset.Interface, namespace, eventSelector, msg string, timeout time.Duration) error { + interval := 2 * time.Second + return wait.PollImmediate(interval, timeout, eventOccurred(c, namespace, eventSelector, msg)) +} + +func eventOccurred(c clientset.Interface, namespace, eventSelector, msg string) wait.ConditionFunc { + options := metav1.ListOptions{FieldSelector: eventSelector} + return func() (bool, error) { + events, err := c.CoreV1().Events(namespace).List(options) + if err != nil { + return false, fmt.Errorf("got error while getting events: %v", err) + } + for _, event := range events.Items { + if strings.Contains(event.Message, msg) { + return true, nil + } + } + return false, nil + } +} diff --git a/test/e2e/common/runtimeclass.go b/test/e2e/common/runtimeclass.go index 6182985019a..f400a48863e 100644 --- a/test/e2e/common/runtimeclass.go +++ b/test/e2e/common/runtimeclass.go @@ -144,6 +144,6 @@ func expectSandboxFailureEvent(f *framework.Framework, pod *v1.Pod, msg string) "involvedObject.namespace": f.Namespace.Name, "reason": events.FailedCreatePodSandBox, }.AsSelector().String() - framework.ExpectNoError(e2epod.WaitTimeoutForPodEvent( - f.ClientSet, pod.Name, f.Namespace.Name, eventSelector, msg, framework.PodEventTimeout)) + framework.ExpectNoError(WaitTimeoutForEvent( + f.ClientSet, f.Namespace.Name, eventSelector, msg, framework.PodEventTimeout)) } diff --git a/test/e2e/framework/pod/wait.go b/test/e2e/framework/pod/wait.go index 8650f763cdf..36503d88b55 100644 --- a/test/e2e/framework/pod/wait.go +++ b/test/e2e/framework/pod/wait.go @@ -20,7 +20,6 @@ import ( "bytes" "errors" "fmt" - "strings" "sync" "text/tabwriter" "time" @@ -348,27 +347,6 @@ func WaitForPodRunningInNamespace(c clientset.Interface, pod *v1.Pod) error { return WaitTimeoutForPodRunningInNamespace(c, pod.Name, pod.Namespace, podStartTimeout) } -// WaitTimeoutForPodEvent waits the given timeout duration for a pod event to occur. -func WaitTimeoutForPodEvent(c clientset.Interface, podName, namespace, eventSelector, msg string, timeout time.Duration) error { - return wait.PollImmediate(poll, timeout, eventOccurred(c, podName, namespace, eventSelector, msg)) -} - -func eventOccurred(c clientset.Interface, podName, namespace, eventSelector, msg string) wait.ConditionFunc { - options := metav1.ListOptions{FieldSelector: eventSelector} - return func() (bool, error) { - events, err := c.CoreV1().Events(namespace).List(options) - if err != nil { - return false, fmt.Errorf("got error while getting pod events: %s", err) - } - for _, event := range events.Items { - if strings.Contains(event.Message, msg) { - return true, nil - } - } - return false, nil - } -} - // WaitTimeoutForPodNoLongerRunningInNamespace waits the given timeout duration for the specified pod to stop. func WaitTimeoutForPodNoLongerRunningInNamespace(c clientset.Interface, podName, namespace string, timeout time.Duration) error { return wait.PollImmediate(poll, timeout, podCompleted(c, podName, namespace)) diff --git a/test/e2e/storage/testsuites/BUILD b/test/e2e/storage/testsuites/BUILD index 59483bfac09..156107edc39 100644 --- a/test/e2e/storage/testsuites/BUILD +++ b/test/e2e/storage/testsuites/BUILD @@ -38,6 +38,7 @@ go_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/csi-translation-lib:go_default_library", + "//test/e2e/common:go_default_library", "//test/e2e/framework:go_default_library", "//test/e2e/framework/log:go_default_library", "//test/e2e/framework/metrics:go_default_library", diff --git a/test/e2e/storage/testsuites/volumemode.go b/test/e2e/storage/testsuites/volumemode.go index be837832f0d..ac94dff7a66 100644 --- a/test/e2e/storage/testsuites/volumemode.go +++ b/test/e2e/storage/testsuites/volumemode.go @@ -29,9 +29,9 @@ import ( "k8s.io/apimachinery/pkg/fields" clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/pkg/kubelet/events" + "k8s.io/kubernetes/test/e2e/common" "k8s.io/kubernetes/test/e2e/framework" e2elog "k8s.io/kubernetes/test/e2e/framework/log" - e2epod "k8s.io/kubernetes/test/e2e/framework/pod" "k8s.io/kubernetes/test/e2e/storage/testpatterns" "k8s.io/kubernetes/test/e2e/storage/utils" ) @@ -270,7 +270,7 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern } else { msg = "has volumeMode Filesystem, but is specified in volumeDevices" } - err = e2epod.WaitTimeoutForPodEvent(l.cs, pod.Name, l.ns.Name, eventSelector, msg, framework.PodStartTimeout) + err = common.WaitTimeoutForEvent(l.cs, l.ns.Name, eventSelector, msg, framework.PodStartTimeout) // Events are unreliable, don't depend on them. They're used only to speed up the test. if err != nil { e2elog.Logf("Warning: did not get event about mismatched volume use") From 00456d0a111e08cf90b259c4c928dfba1c9d7e5c Mon Sep 17 00:00:00 2001 From: Masaki Kimura Date: Thu, 8 Aug 2019 21:29:27 +0000 Subject: [PATCH 2/3] Speed up block volume e2e test by checking events --- test/e2e/storage/testsuites/BUILD | 1 + test/e2e/storage/testsuites/volumemode.go | 50 ++++++++++++++++++++--- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/test/e2e/storage/testsuites/BUILD b/test/e2e/storage/testsuites/BUILD index 156107edc39..7baa11203c8 100644 --- a/test/e2e/storage/testsuites/BUILD +++ b/test/e2e/storage/testsuites/BUILD @@ -20,6 +20,7 @@ go_library( importpath = "k8s.io/kubernetes/test/e2e/storage/testsuites", visibility = ["//visibility:public"], deps = [ + "//pkg/controller/volume/events:go_default_library", "//pkg/kubelet/events:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/storage/v1:go_default_library", diff --git a/test/e2e/storage/testsuites/volumemode.go b/test/e2e/storage/testsuites/volumemode.go index ac94dff7a66..44d6563d50e 100644 --- a/test/e2e/storage/testsuites/volumemode.go +++ b/test/e2e/storage/testsuites/volumemode.go @@ -28,10 +28,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" clientset "k8s.io/client-go/kubernetes" + volevents "k8s.io/kubernetes/pkg/controller/volume/events" "k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/test/e2e/common" "k8s.io/kubernetes/test/e2e/framework" e2elog "k8s.io/kubernetes/test/e2e/framework/log" + e2epod "k8s.io/kubernetes/test/e2e/framework/pod" "k8s.io/kubernetes/test/e2e/storage/testpatterns" "k8s.io/kubernetes/test/e2e/storage/utils" ) @@ -202,13 +204,33 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern framework.ExpectNoError(framework.WaitOnPVandPVC(l.cs, l.ns.Name, l.pv, l.pvc)) ginkgo.By("Creating pod") - pod, err := framework.CreateSecPodWithNodeSelection(l.cs, l.ns.Name, []*v1.PersistentVolumeClaim{l.pvc}, - nil, false, "", false, false, framework.SELinuxLabel, - nil, framework.NodeSelection{Name: l.config.ClientNodeName}, framework.PodStartTimeout) + pod := framework.MakeSecPod(l.ns.Name, []*v1.PersistentVolumeClaim{l.pvc}, nil, false, "", false, false, framework.SELinuxLabel, nil) + // Setting node + pod.Spec.NodeName = l.config.ClientNodeName + pod, err = l.cs.CoreV1().Pods(l.ns.Name).Create(pod) + framework.ExpectNoError(err) defer func() { framework.ExpectNoError(framework.DeletePodWithWait(f, l.cs, pod)) }() - framework.ExpectError(err) + + eventSelector := fields.Set{ + "involvedObject.kind": "Pod", + "involvedObject.name": pod.Name, + "involvedObject.namespace": l.ns.Name, + "reason": events.FailedMountVolume, + }.AsSelector().String() + msg := "Unable to attach or mount volumes" + + err = common.WaitTimeoutForEvent(l.cs, l.ns.Name, eventSelector, msg, framework.PodStartTimeout) + // Events are unreliable, don't depend on the event. It's used only to speed up the test. + if err != nil { + e2elog.Logf("Warning: did not get event about FailedMountVolume") + } + + // Check the pod is still not running + p, err := l.cs.CoreV1().Pods(l.ns.Name).Get(pod.Name, metav1.GetOptions{}) + framework.ExpectNoError(err, "could not re-read the pod after event (or timeout)") + framework.ExpectEqual(p.Status.Phase, v1.PodPending) }) } @@ -228,8 +250,24 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern l.pvc, err = l.cs.CoreV1().PersistentVolumeClaims(l.ns.Name).Create(l.pvc) framework.ExpectNoError(err) - err = framework.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, l.cs, l.pvc.Namespace, l.pvc.Name, framework.Poll, framework.ClaimProvisionTimeout) - framework.ExpectError(err) + eventSelector := fields.Set{ + "involvedObject.kind": "PersistentVolumeClaim", + "involvedObject.name": l.pvc.Name, + "involvedObject.namespace": l.ns.Name, + "reason": volevents.ProvisioningFailed, + }.AsSelector().String() + msg := "does not support block volume provisioning" + + err = common.WaitTimeoutForEvent(l.cs, l.ns.Name, eventSelector, msg, framework.ClaimProvisionTimeout) + // Events are unreliable, don't depend on the event. It's used only to speed up the test. + if err != nil { + e2elog.Logf("Warning: did not get event about provisioing failed") + } + + // Check the pvc is still pending + pvc, err := l.cs.CoreV1().PersistentVolumeClaims(l.ns.Name).Get(l.pvc.Name, metav1.GetOptions{}) + framework.ExpectNoError(err, "Failed to re-read the pvc after event (or timeout)") + framework.ExpectEqual(pvc.Status.Phase, v1.ClaimPending) }) } default: From 2be543d879ac47da14393cd7c81f3299d34cbdf6 Mon Sep 17 00:00:00 2001 From: Masaki Kimura Date: Fri, 16 Aug 2019 16:38:40 +0000 Subject: [PATCH 3/3] Add messages for framework.Expect* in volumeMode tests --- test/e2e/storage/testsuites/volumemode.go | 26 +++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/e2e/storage/testsuites/volumemode.go b/test/e2e/storage/testsuites/volumemode.go index 44d6563d50e..b716604dc8f 100644 --- a/test/e2e/storage/testsuites/volumemode.go +++ b/test/e2e/storage/testsuites/volumemode.go @@ -190,27 +190,27 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern ginkgo.By("Creating sc") l.sc, err = l.cs.StorageV1().StorageClasses().Create(l.sc) - framework.ExpectNoError(err) + framework.ExpectNoError(err, "Failed to create sc") ginkgo.By("Creating pv and pvc") l.pv, err = l.cs.CoreV1().PersistentVolumes().Create(l.pv) - framework.ExpectNoError(err) + framework.ExpectNoError(err, "Failed to create pv") // Prebind pv l.pvc.Spec.VolumeName = l.pv.Name l.pvc, err = l.cs.CoreV1().PersistentVolumeClaims(l.ns.Name).Create(l.pvc) - framework.ExpectNoError(err) + framework.ExpectNoError(err, "Failed to create pvc") - framework.ExpectNoError(framework.WaitOnPVandPVC(l.cs, l.ns.Name, l.pv, l.pvc)) + framework.ExpectNoError(framework.WaitOnPVandPVC(l.cs, l.ns.Name, l.pv, l.pvc), "Failed to bind pv and pvc") ginkgo.By("Creating pod") pod := framework.MakeSecPod(l.ns.Name, []*v1.PersistentVolumeClaim{l.pvc}, nil, false, "", false, false, framework.SELinuxLabel, nil) // Setting node pod.Spec.NodeName = l.config.ClientNodeName pod, err = l.cs.CoreV1().Pods(l.ns.Name).Create(pod) - framework.ExpectNoError(err) + framework.ExpectNoError(err, "Failed to create pod") defer func() { - framework.ExpectNoError(framework.DeletePodWithWait(f, l.cs, pod)) + framework.ExpectNoError(framework.DeletePodWithWait(f, l.cs, pod), "Failed to delete pod") }() eventSelector := fields.Set{ @@ -230,7 +230,7 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern // Check the pod is still not running p, err := l.cs.CoreV1().Pods(l.ns.Name).Get(pod.Name, metav1.GetOptions{}) framework.ExpectNoError(err, "could not re-read the pod after event (or timeout)") - framework.ExpectEqual(p.Status.Phase, v1.PodPending) + framework.ExpectEqual(p.Status.Phase, v1.PodPending, "Pod phase isn't pending") }) } @@ -244,11 +244,11 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern ginkgo.By("Creating sc") l.sc, err = l.cs.StorageV1().StorageClasses().Create(l.sc) - framework.ExpectNoError(err) + framework.ExpectNoError(err, "Failed to create sc") ginkgo.By("Creating pv and pvc") l.pvc, err = l.cs.CoreV1().PersistentVolumeClaims(l.ns.Name).Create(l.pvc) - framework.ExpectNoError(err) + framework.ExpectNoError(err, "Failed to create pvc") eventSelector := fields.Set{ "involvedObject.kind": "PersistentVolumeClaim", @@ -267,7 +267,7 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern // Check the pvc is still pending pvc, err := l.cs.CoreV1().PersistentVolumeClaims(l.ns.Name).Get(l.pvc.Name, metav1.GetOptions{}) framework.ExpectNoError(err, "Failed to re-read the pvc after event (or timeout)") - framework.ExpectEqual(pvc.Status.Phase, v1.ClaimPending) + framework.ExpectEqual(pvc.Status.Phase, v1.ClaimPending, "PVC phase isn't pending") }) } default: @@ -288,9 +288,9 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern // Run the pod pod, err = l.cs.CoreV1().Pods(l.ns.Name).Create(pod) - framework.ExpectNoError(err) + framework.ExpectNoError(err, "Failed to create pod") defer func() { - framework.ExpectNoError(framework.DeletePodWithWait(f, l.cs, pod)) + framework.ExpectNoError(framework.DeletePodWithWait(f, l.cs, pod), "Failed to delete pod") }() ginkgo.By("Waiting for the pod to fail") @@ -317,7 +317,7 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern // Check the pod is still not running p, err := l.cs.CoreV1().Pods(l.ns.Name).Get(pod.Name, metav1.GetOptions{}) framework.ExpectNoError(err, "could not re-read the pod after event (or timeout)") - framework.ExpectEqual(p.Status.Phase, v1.PodPending) + framework.ExpectEqual(p.Status.Phase, v1.PodPending, "Pod phase isn't pending") }) ginkgo.It("should not mount / map unused volumes in a pod", func() {