1
16
17 package e2enode
18
19 import (
20 "context"
21 "fmt"
22
23 v1 "k8s.io/api/core/v1"
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 "k8s.io/apimachinery/pkg/util/uuid"
26 "k8s.io/kubernetes/test/e2e/framework"
27 e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
28 testutils "k8s.io/kubernetes/test/utils"
29 admissionapi "k8s.io/pod-security-admission/api"
30
31 "github.com/onsi/ginkgo/v2"
32 "github.com/onsi/gomega"
33 )
34
35
36
37
38 var _ = SIGDescribe("Pod SIGKILL [LinuxOnly]", framework.WithNodeConformance(), func() {
39 f := framework.NewDefaultFramework("sigkill-test")
40 f.NamespacePodSecurityLevel = admissionapi.LevelBaseline
41
42 podName := "sigkill-pod-" + string(uuid.NewUUID())
43 containerName := "sigkill-target-container"
44 podSpec := getSigkillTargetPod(podName, containerName)
45 ginkgo.Context("", func() {
46 ginkgo.BeforeEach(func() {
47 ginkgo.By("setting up the pod to be used in the test")
48 e2epod.NewPodClient(f).Create(context.TODO(), podSpec)
49 })
50
51 ginkgo.It("The containers terminated forcefully by Sigkill should have the correct exit code(137) and reason (Error)", func() {
52
53 ginkgo.By(fmt.Sprintf("Waiting for the pod (%v/%v) to be running", f.Namespace.Name, podSpec.Name))
54 err := e2epod.WaitForPodNameRunningInNamespace(context.TODO(), f.ClientSet, podSpec.Name, f.Namespace.Name)
55 framework.ExpectNoError(err, "Failed to await for the pod to be running: %q", podSpec.Name)
56
57
58 err = e2epod.WaitForPodCondition(context.TODO(), f.ClientSet, f.Namespace.Name, podSpec.Name, "Ready", f.Timeouts.PodStart, testutils.PodRunningReady)
59 framework.ExpectNoError(err, "Failed to await Pod (%v/%v) become ready after registering signal handler: %v", f.Namespace.Name, podSpec.Name, err)
60
61 ginkgo.By(fmt.Sprintf("Deleting the pod (%v/%v) to set a deletion timestamp", f.Namespace.Name, podSpec.Name))
62 err = e2epod.NewPodClient(f).Delete(context.TODO(), podSpec.Name, metav1.DeleteOptions{})
63 framework.ExpectNoError(err, "Failed to delete the pod: %q", podSpec.Name)
64
65 ginkgo.By(fmt.Sprintf("Waiting for the pod (%v/%v) to be transitioned to the terminated phase", f.Namespace.Name, podSpec.Name))
66 err = e2epod.WaitForPodTerminatedInNamespace(context.TODO(), f.ClientSet, podSpec.Name, "", f.Namespace.Name)
67 framework.ExpectNoError(err, "Failed to await for the pod to be terminated: %q", podSpec.Name)
68
69 ginkgo.By(fmt.Sprintf("Fetching the end state of the pod (%v/%v)", f.Namespace.Name, podSpec.Name))
70 pod, err := e2epod.NewPodClient(f).Get(context.TODO(), podSpec.Name, metav1.GetOptions{})
71 framework.ExpectNoError(err, "Failed to fetch the end state of the pod: %q", podSpec.Name)
72
73 ginkgo.By(fmt.Sprintf("Verify the pod (%v/%v) container is in the terminated state", pod.Namespace, podSpec.Name))
74 gomega.Expect(pod.Status.ContainerStatuses).Should(gomega.HaveLen(1), "The pod container has %v status", len(pod.Status.ContainerStatuses))
75 containerStatus := pod.Status.ContainerStatuses[0]
76 gomega.Expect(containerStatus.State.Terminated).ShouldNot(gomega.BeNil(), "The pod container is in not in the Terminated state")
77
78 ginkgo.By(fmt.Sprintf("Verifying the exit code for the terminated container is 137 for pod (%v/%v)", pod.Namespace, podSpec.Name))
79 gomega.Expect(containerStatus.State.Terminated.ExitCode).Should(gomega.Equal(int32(137)))
80
81 ginkgo.By(fmt.Sprintf("Verify exit reason of the pod (%v/%v) container", f.Namespace.Name, podSpec.Name))
82 gomega.Expect(containerStatus.State.Terminated.Reason).Should(gomega.Equal("Error"), "Container terminated by sigkill expect Error but got %v", containerStatus.State.Terminated.Reason)
83 })
84
85 ginkgo.AfterEach(func() {
86 ginkgo.By(fmt.Sprintf("Deleting pod by removing finalizers: %s", podSpec.Name))
87 e2epod.NewPodClient(f).RemoveFinalizer(context.TODO(), podSpec.Name, testFinalizer)
88
89 ginkgo.By(fmt.Sprintf("Confirm the pod was successfully deleted: %s", podSpec.Name))
90 e2epod.WaitForPodNotFoundInNamespace(context.TODO(), f.ClientSet, podSpec.Name, f.Namespace.Name, f.Timeouts.PodDelete)
91 })
92 })
93 })
94
95 func getSigkillTargetPod(podName string, ctnName string) *v1.Pod {
96 gracePeriod := int64(5)
97 return &v1.Pod{
98 ObjectMeta: metav1.ObjectMeta{
99 Name: podName,
100
101
102 Finalizers: []string{testFinalizer},
103 },
104 Spec: v1.PodSpec{
105 RestartPolicy: v1.RestartPolicyNever,
106 Containers: []v1.Container{
107 {
108 Name: ctnName,
109 Image: busyboxImage,
110
111
112
113 Command: []string{
114 "sh",
115 "-c",
116 "trap \"echo SIGTERM caught\" SIGTERM SIGINT; touch /tmp/healthy; /bin/sleep 1000",
117 },
118
119 ReadinessProbe: &v1.Probe{
120 InitialDelaySeconds: 1,
121 TimeoutSeconds: 2,
122 ProbeHandler: v1.ProbeHandler{
123 Exec: &v1.ExecAction{
124 Command: []string{"/bin/sh", "-c", "cat /tmp/healthy"},
125 },
126 },
127 },
128 },
129 },
130 TerminationGracePeriodSeconds: &gracePeriod,
131 },
132 }
133 }
134
View as plain text