diff --git a/test/e2e/common/node/lifecycle_hook.go b/test/e2e/common/node/lifecycle_hook.go index eeca6dc3111..8af3b4b2f23 100644 --- a/test/e2e/common/node/lifecycle_hook.go +++ b/test/e2e/common/node/lifecycle_hook.go @@ -33,6 +33,7 @@ import ( e2epod "k8s.io/kubernetes/test/e2e/framework/pod" imageutils "k8s.io/kubernetes/test/utils/image" admissionapi "k8s.io/pod-security-admission/api" + "k8s.io/utils/ptr" "github.com/onsi/ginkgo/v2" "github.com/onsi/gomega" @@ -552,7 +553,7 @@ func validDuration(duration time.Duration, low, high int64) bool { return duration >= time.Second*time.Duration(low) && duration <= time.Second*time.Duration(high) } -var _ = SIGDescribe(feature.PodLifecycleSleepAction, framework.WithFeatureGate(features.PodLifecycleSleepAction), func() { +var _ = SIGDescribe("Lifecycle Sleep Hook", func() { f := framework.NewDefaultFramework("pod-lifecycle-sleep-action") f.NamespacePodSecurityLevel = admissionapi.LevelBaseline var podClient *e2epod.PodClient @@ -561,13 +562,20 @@ var _ = SIGDescribe(feature.PodLifecycleSleepAction, framework.WithFeatureGate(f ginkgo.BeforeEach(func(ctx context.Context) { podClient = e2epod.NewPodClient(f) }) + + /* + Release : v1.32 + Testname: Pod Lifecycle, prestop sleep hook + Description: When a pre-stop handler is specified in the container lifecycle using a 'Sleep' action, then the handler MUST be invoked before the container is terminated. A test pod will be created to verify if its termination time aligns with the sleep time specified when it is terminated. + */ ginkgo.It("valid prestop hook using sleep action", func(ctx context.Context) { lifecycle := &v1.Lifecycle{ PreStop: &v1.LifecycleHandler{ - Sleep: &v1.SleepAction{Seconds: 5}, + Sleep: &v1.SleepAction{Seconds: 15}, }, } podWithHook := getPodWithHook("pod-with-prestop-sleep-hook", imageutils.GetPauseImageName(), lifecycle) + podWithHook.Spec.TerminationGracePeriodSeconds = ptr.To[int64](180) ginkgo.By("create the pod with lifecycle hook using sleep action") podClient.CreateSync(ctx, podWithHook) ginkgo.By("delete the pod with lifecycle hook using sleep action") @@ -575,42 +583,54 @@ var _ = SIGDescribe(feature.PodLifecycleSleepAction, framework.WithFeatureGate(f podClient.DeleteSync(ctx, podWithHook.Name, metav1.DeleteOptions{}, f.Timeouts.PodDelete) cost := time.Since(start) // cost should be - // longer than 5 seconds (pod should sleep for 5 seconds) - // shorter than gracePeriodSeconds (default 30 seconds here) - if !validDuration(cost, 5, 30) { + // longer than 15 seconds (pod should sleep for 15 seconds) + // shorter than gracePeriodSeconds (180 seconds here) + if !validDuration(cost, 15, 120) { framework.Failf("unexpected delay duration before killing the pod, cost = %v", cost) } }) + /* + Release : v1.32 + Testname: Pod Lifecycle, prestop sleep hook with low gracePeriodSeconds + Description: When a pre-stop handler is specified in the container lifecycle using a 'Sleep' action, then the handler MUST be invoked before the container is terminated. A test pod will be created, and its `gracePeriodSeconds` will be modified to a value less than the sleep time before termination. The termination time will then be checked to ensure it aligns with the `gracePeriodSeconds` value. + */ ginkgo.It("reduce GracePeriodSeconds during runtime", func(ctx context.Context) { lifecycle := &v1.Lifecycle{ PreStop: &v1.LifecycleHandler{ - Sleep: &v1.SleepAction{Seconds: 15}, + Sleep: &v1.SleepAction{Seconds: 120}, }, } podWithHook := getPodWithHook("pod-with-prestop-sleep-hook", imageutils.GetPauseImageName(), lifecycle) + podWithHook.Spec.TerminationGracePeriodSeconds = ptr.To[int64](180) ginkgo.By("create the pod with lifecycle hook using sleep action") podClient.CreateSync(ctx, podWithHook) ginkgo.By("delete the pod with lifecycle hook using sleep action") start := time.Now() - podClient.DeleteSync(ctx, podWithHook.Name, *metav1.NewDeleteOptions(2), f.Timeouts.PodDelete) + podClient.DeleteSync(ctx, podWithHook.Name, *metav1.NewDeleteOptions(15), f.Timeouts.PodDelete) cost := time.Since(start) // cost should be - // longer than 2 seconds (we change gracePeriodSeconds to 2 seconds here, and it's less than sleep action) + // longer than 15 seconds (we change gracePeriodSeconds to 15 seconds here, and it's less than sleep action) // shorter than sleep action (to make sure it doesn't take effect) - if !validDuration(cost, 2, 15) { + if !validDuration(cost, 15, 100) { framework.Failf("unexpected delay duration before killing the pod, cost = %v", cost) } }) + /* + Release : v1.32 + Testname: Pod Lifecycle, prestop sleep hook with erroneous startup command + Description: When a pre-stop handler is specified in the container lifecycle using a 'Sleep' action, then the handler MUST be invoked before the container is terminated. A test pod with an erroneous startup command will be created, and upon termination, it will be checked whether it ignored the sleep time. + */ ginkgo.It("ignore terminated container", func(ctx context.Context) { lifecycle := &v1.Lifecycle{ PreStop: &v1.LifecycleHandler{ - Sleep: &v1.SleepAction{Seconds: 20}, + Sleep: &v1.SleepAction{Seconds: 120}, }, } name := "pod-with-prestop-sleep-hook" podWithHook := getPodWithHook(name, imageutils.GetE2EImage(imageutils.BusyBox), lifecycle) + podWithHook.Spec.TerminationGracePeriodSeconds = ptr.To[int64](150) podWithHook.Spec.Containers[0].Command = []string{"/bin/sh"} podWithHook.Spec.Containers[0].Args = []string{"-c", "exit 0"} podWithHook.Spec.RestartPolicy = v1.RestartPolicyNever @@ -623,11 +643,10 @@ var _ = SIGDescribe(feature.PodLifecycleSleepAction, framework.WithFeatureGate(f cost := time.Since(start) // cost should be // shorter than sleep action (container is terminated and sleep action should be ignored) - if !validDuration(cost, 0, 15) { + if !validDuration(cost, 0, 100) { framework.Failf("unexpected delay duration before killing the pod, cost = %v", cost) } }) - }) })