mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 21:47:07 +00:00
Merge pull request #81196 from mkimuram/issue/71748
Speed up block volume e2e test by checking events
This commit is contained in:
commit
efcb62abff
@ -259,8 +259,8 @@ var _ = framework.KubeDescribe("Probing container", func() {
|
|||||||
"involvedObject.namespace": f.Namespace.Name,
|
"involvedObject.namespace": f.Namespace.Name,
|
||||||
"reason": events.ContainerProbeWarning,
|
"reason": events.ContainerProbeWarning,
|
||||||
}.AsSelector().String()
|
}.AsSelector().String()
|
||||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodEvent(
|
framework.ExpectNoError(WaitTimeoutForEvent(
|
||||||
f.ClientSet, pod.Name, f.Namespace.Name, expectedEvent, "0.0.0.0", framework.PodEventTimeout))
|
f.ClientSet, f.Namespace.Name, expectedEvent, "0.0.0.0", framework.PodEventTimeout))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
|
|
||||||
@ -149,3 +151,25 @@ func ObserveEventAfterAction(f *framework.Framework, eventPredicate func(*v1.Eve
|
|||||||
})
|
})
|
||||||
return err == nil, err
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -144,6 +144,6 @@ func expectSandboxFailureEvent(f *framework.Framework, pod *v1.Pod, msg string)
|
|||||||
"involvedObject.namespace": f.Namespace.Name,
|
"involvedObject.namespace": f.Namespace.Name,
|
||||||
"reason": events.FailedCreatePodSandBox,
|
"reason": events.FailedCreatePodSandBox,
|
||||||
}.AsSelector().String()
|
}.AsSelector().String()
|
||||||
framework.ExpectNoError(e2epod.WaitTimeoutForPodEvent(
|
framework.ExpectNoError(WaitTimeoutForEvent(
|
||||||
f.ClientSet, pod.Name, f.Namespace.Name, eventSelector, msg, framework.PodEventTimeout))
|
f.ClientSet, f.Namespace.Name, eventSelector, msg, framework.PodEventTimeout))
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"time"
|
"time"
|
||||||
@ -348,27 +347,6 @@ func WaitForPodRunningInNamespace(c clientset.Interface, pod *v1.Pod) error {
|
|||||||
return WaitTimeoutForPodRunningInNamespace(c, pod.Name, pod.Namespace, podStartTimeout)
|
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.
|
// WaitTimeoutForPodNoLongerRunningInNamespace waits the given timeout duration for the specified pod to stop.
|
||||||
func WaitTimeoutForPodNoLongerRunningInNamespace(c clientset.Interface, podName, namespace string, timeout time.Duration) error {
|
func WaitTimeoutForPodNoLongerRunningInNamespace(c clientset.Interface, podName, namespace string, timeout time.Duration) error {
|
||||||
return wait.PollImmediate(poll, timeout, podCompleted(c, podName, namespace))
|
return wait.PollImmediate(poll, timeout, podCompleted(c, podName, namespace))
|
||||||
|
@ -20,6 +20,7 @@ go_library(
|
|||||||
importpath = "k8s.io/kubernetes/test/e2e/storage/testsuites",
|
importpath = "k8s.io/kubernetes/test/e2e/storage/testsuites",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//pkg/controller/volume/events:go_default_library",
|
||||||
"//pkg/kubelet/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/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/storage/v1:go_default_library",
|
"//staging/src/k8s.io/api/storage/v1:go_default_library",
|
||||||
@ -38,6 +39,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",
|
||||||
"//staging/src/k8s.io/csi-translation-lib: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:go_default_library",
|
||||||
"//test/e2e/framework/log:go_default_library",
|
"//test/e2e/framework/log:go_default_library",
|
||||||
"//test/e2e/framework/metrics:go_default_library",
|
"//test/e2e/framework/metrics:go_default_library",
|
||||||
|
@ -28,7 +28,9 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
volevents "k8s.io/kubernetes/pkg/controller/volume/events"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/events"
|
"k8s.io/kubernetes/pkg/kubelet/events"
|
||||||
|
"k8s.io/kubernetes/test/e2e/common"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
e2elog "k8s.io/kubernetes/test/e2e/framework/log"
|
e2elog "k8s.io/kubernetes/test/e2e/framework/log"
|
||||||
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
|
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
|
||||||
@ -188,27 +190,47 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
|
|||||||
|
|
||||||
ginkgo.By("Creating sc")
|
ginkgo.By("Creating sc")
|
||||||
l.sc, err = l.cs.StorageV1().StorageClasses().Create(l.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")
|
ginkgo.By("Creating pv and pvc")
|
||||||
l.pv, err = l.cs.CoreV1().PersistentVolumes().Create(l.pv)
|
l.pv, err = l.cs.CoreV1().PersistentVolumes().Create(l.pv)
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err, "Failed to create pv")
|
||||||
|
|
||||||
// Prebind pv
|
// Prebind pv
|
||||||
l.pvc.Spec.VolumeName = l.pv.Name
|
l.pvc.Spec.VolumeName = l.pv.Name
|
||||||
l.pvc, err = l.cs.CoreV1().PersistentVolumeClaims(l.ns.Name).Create(l.pvc)
|
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")
|
ginkgo.By("Creating pod")
|
||||||
pod, err := framework.CreateSecPodWithNodeSelection(l.cs, l.ns.Name, []*v1.PersistentVolumeClaim{l.pvc},
|
pod := framework.MakeSecPod(l.ns.Name, []*v1.PersistentVolumeClaim{l.pvc}, nil, false, "", false, false, framework.SELinuxLabel, nil)
|
||||||
nil, false, "", false, false, framework.SELinuxLabel,
|
// Setting node
|
||||||
nil, framework.NodeSelection{Name: l.config.ClientNodeName}, framework.PodStartTimeout)
|
pod.Spec.NodeName = l.config.ClientNodeName
|
||||||
|
pod, err = l.cs.CoreV1().Pods(l.ns.Name).Create(pod)
|
||||||
|
framework.ExpectNoError(err, "Failed to create pod")
|
||||||
defer func() {
|
defer func() {
|
||||||
framework.ExpectNoError(framework.DeletePodWithWait(f, l.cs, pod))
|
framework.ExpectNoError(framework.DeletePodWithWait(f, l.cs, pod), "Failed to delete 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, "Pod phase isn't pending")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,14 +244,30 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
|
|||||||
|
|
||||||
ginkgo.By("Creating sc")
|
ginkgo.By("Creating sc")
|
||||||
l.sc, err = l.cs.StorageV1().StorageClasses().Create(l.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")
|
ginkgo.By("Creating pv and pvc")
|
||||||
l.pvc, err = l.cs.CoreV1().PersistentVolumeClaims(l.ns.Name).Create(l.pvc)
|
l.pvc, err = l.cs.CoreV1().PersistentVolumeClaims(l.ns.Name).Create(l.pvc)
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err, "Failed to create pvc")
|
||||||
|
|
||||||
err = framework.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, l.cs, l.pvc.Namespace, l.pvc.Name, framework.Poll, framework.ClaimProvisionTimeout)
|
eventSelector := fields.Set{
|
||||||
framework.ExpectError(err)
|
"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, "PVC phase isn't pending")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -250,9 +288,9 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
|
|||||||
|
|
||||||
// Run the pod
|
// Run the pod
|
||||||
pod, err = l.cs.CoreV1().Pods(l.ns.Name).Create(pod)
|
pod, err = l.cs.CoreV1().Pods(l.ns.Name).Create(pod)
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err, "Failed to create pod")
|
||||||
defer func() {
|
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")
|
ginkgo.By("Waiting for the pod to fail")
|
||||||
@ -270,7 +308,7 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
|
|||||||
} else {
|
} else {
|
||||||
msg = "has volumeMode Filesystem, but is specified in volumeDevices"
|
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.
|
// Events are unreliable, don't depend on them. They're used only to speed up the test.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e2elog.Logf("Warning: did not get event about mismatched volume use")
|
e2elog.Logf("Warning: did not get event about mismatched volume use")
|
||||||
@ -279,7 +317,7 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
|
|||||||
// Check the pod is still not running
|
// Check the pod is still not running
|
||||||
p, err := l.cs.CoreV1().Pods(l.ns.Name).Get(pod.Name, metav1.GetOptions{})
|
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.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() {
|
ginkgo.It("should not mount / map unused volumes in a pod", func() {
|
||||||
|
Loading…
Reference in New Issue
Block a user