Add more Node E2E tests to cover pod termination for Sidecar Containers

* A pod with restartable init container that exits with
  a non-zero code is marked as a pod succeeded phase
* A pod with restartable init containers that exits with
  a non-zero code by prestop hook is marked as a pod succeeded phase
* A pod with regular container that exceeds its termination grace period
  seconds is marked as a pod failed phase
* A pod with restartable init containers that exceeds its termination
  grace period seconds is marked as a pod succeeded phase
* A pod with a regular container that exceeded its termination grace
  period seconds by PreStop hook is marked as a pod failed phase
* A pod with restartable init containers that exceeds its termination
  grace period seconds by PreStop hook is marked as a pod succeeded phase

Signed-off-by: Tsubasa Nagasawa <toversus2357@gmail.com>
This commit is contained in:
Tsubasa Nagasawa 2024-09-08 15:33:57 +09:00
parent bd00f83578
commit 82b690ddf6

View File

@ -3651,6 +3651,654 @@ var _ = SIGDescribe(nodefeature.SidecarContainers, "Containers Lifecycle", func(
framework.ExpectNoError(err, "the pod should be deleted before its terminationGracePeriodSeconds if the restartalbe init containers get termination signal correctly") framework.ExpectNoError(err, "the pod should be deleted before its terminationGracePeriodSeconds if the restartalbe init containers get termination signal correctly")
}) })
}) })
ginkgo.When("The restartable init containers exit with non-zero exit code", func() {
ginkgo.It("should mark pod as succeeded if any of the restartable init containers have terminated with non-zero exit code", func(ctx context.Context) {
restartableInit1 := "restartable-init-1"
restartableInit2 := "restartable-init-2"
restartableInit3 := "restartable-init-3"
regular1 := "regular-1"
podTerminationGracePeriodSeconds := int64(30)
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "restartable-init-terminated-with-non-zero-exit-code",
Finalizers: []string{testFinalizer},
},
Spec: v1.PodSpec{
RestartPolicy: v1.RestartPolicyNever,
TerminationGracePeriodSeconds: ptr.To(podTerminationGracePeriodSeconds),
InitContainers: []v1.Container{
{
Name: restartableInit1,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit1, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
},
{
Name: restartableInit2,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit2, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 1,
}),
},
{
Name: restartableInit3,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit3, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
},
},
Containers: []v1.Container{
{
Name: regular1,
Image: busyboxImage,
Command: ExecCommand(regular1, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
},
},
},
}
preparePod(pod)
ginkgo.By("Creating the pod with finalizer")
client := e2epod.NewPodClient(f)
pod = client.Create(ctx, pod)
defer client.RemoveFinalizer(ctx, pod.Name, testFinalizer)
ginkgo.By("Waiting for the pod to be initialized and run")
err := e2epod.WaitForPodRunningInNamespace(ctx, f.ClientSet, pod)
framework.ExpectNoError(err)
ginkgo.By("Deleting the pod")
err = client.Delete(ctx, pod.Name, metav1.DeleteOptions{GracePeriodSeconds: &podTerminationGracePeriodSeconds})
framework.ExpectNoError(err)
ginkgo.By(fmt.Sprintf("Waiting for the pod (%s/%s) to be transitioned into the Succeeded phase", pod.Namespace, pod.Name))
err = e2epod.WaitForPodSuccessInNamespace(ctx, f.ClientSet, pod.Name, f.Namespace.Name)
framework.ExpectNoError(err, "Failed to await for the pod to be terminated: %q", pod.Name)
ginkgo.By(fmt.Sprintf("Fetch the end state of the pod (%s/%s)", pod.Namespace, pod.Name))
pod, err = client.Get(ctx, pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err, "Failed to fetch the end state of the pod: %q", pod.Name)
// regular container is gracefully terminated
expectPodTerminationContainerStatuses(pod.Status.ContainerStatuses, map[string]podTerminationContainerStatus{
regular1: {exitCode: int32(0), reason: "Completed"},
})
// restartable-init-2 that terminated with non-zero exit code is marked as error
expectPodTerminationContainerStatuses(pod.Status.InitContainerStatuses, map[string]podTerminationContainerStatus{
restartableInit1: {exitCode: int32(0), reason: "Completed"},
restartableInit2: {exitCode: int32(1), reason: "Error"},
restartableInit3: {exitCode: int32(0), reason: "Completed"},
})
})
})
ginkgo.When("The restartable init containers exit with non-zero exit code by prestop hook", func() {
ginkgo.It("should mark pod as succeeded if any of the restartable init containers have terminated with non-zero exit code by prestop hook", func(ctx context.Context) {
restartableInit1 := "restartable-init-1"
restartableInit2 := "restartable-init-2"
restartableInit3 := "restartable-init-3"
regular1 := "regular-1"
podTerminationGracePeriodSeconds := int64(30)
makePrestop := func(containerName string, exitCode int) *v1.Lifecycle {
return &v1.Lifecycle{
PreStop: &v1.LifecycleHandler{
Exec: &v1.ExecAction{
Command: ExecCommand(containerName, execCommand{
Delay: 1,
ExitCode: exitCode,
}),
},
},
}
}
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "restartable-init-terminated-with-non-zero-exit-code",
Finalizers: []string{testFinalizer},
},
Spec: v1.PodSpec{
RestartPolicy: v1.RestartPolicyNever,
TerminationGracePeriodSeconds: ptr.To(podTerminationGracePeriodSeconds),
InitContainers: []v1.Container{
{
Name: restartableInit1,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit1, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
Lifecycle: makePrestop(restartableInit1, 0),
},
{
Name: restartableInit2,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit2, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
Lifecycle: makePrestop(restartableInit2, 1),
},
{
Name: restartableInit3,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit3, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
Lifecycle: makePrestop(restartableInit3, 0),
},
},
Containers: []v1.Container{
{
Name: regular1,
Image: busyboxImage,
Command: ExecCommand(regular1, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
},
},
},
}
preparePod(pod)
ginkgo.By("Creating the pod with finalizer")
client := e2epod.NewPodClient(f)
pod = client.Create(ctx, pod)
defer client.RemoveFinalizer(ctx, pod.Name, testFinalizer)
ginkgo.By("Waiting for the pod to be initialized and run")
err := e2epod.WaitForPodRunningInNamespace(ctx, f.ClientSet, pod)
framework.ExpectNoError(err)
ginkgo.By("Deleting the pod")
err = client.Delete(ctx, pod.Name, metav1.DeleteOptions{GracePeriodSeconds: &podTerminationGracePeriodSeconds})
framework.ExpectNoError(err)
ginkgo.By(fmt.Sprintf("Waiting for the pod (%s/%s) to be transitioned into the Succeeded phase", pod.Namespace, pod.Name))
err = e2epod.WaitForPodSuccessInNamespace(ctx, f.ClientSet, pod.Name, f.Namespace.Name)
framework.ExpectNoError(err, "Failed to await for the pod to be terminated: %q", pod.Name)
ginkgo.By(fmt.Sprintf("Fetch the end state of the pod (%s/%s)", pod.Namespace, pod.Name))
pod, err = client.Get(ctx, pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err, "Failed to fetch the end state of the pod: %q", pod.Name)
// regular container is gracefully terminated
expectPodTerminationContainerStatuses(pod.Status.ContainerStatuses, map[string]podTerminationContainerStatus{
regular1: {exitCode: int32(0), reason: "Completed"},
})
// restartable init containers are marked as completed if their prestop hooks are failed
expectPodTerminationContainerStatuses(pod.Status.InitContainerStatuses, map[string]podTerminationContainerStatus{
restartableInit1: {exitCode: int32(0), reason: "Completed"},
restartableInit2: {exitCode: int32(0), reason: "Completed"},
restartableInit3: {exitCode: int32(0), reason: "Completed"},
})
})
})
ginkgo.When("The regular container has exceeded its termination grace period seconds", func() {
ginkgo.It("should mark pod as failed if regular container has exceeded its termination grace period seconds", func(ctx context.Context) {
restartableInit1 := "restartable-init-1"
restartableInit2 := "restartable-init-2"
restartableInit3 := "restartable-init-3"
regular1 := "regular-1"
podTerminationGracePeriodSeconds := int64(5)
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "regular-exceeded-termination-grace-period",
Finalizers: []string{testFinalizer},
},
Spec: v1.PodSpec{
RestartPolicy: v1.RestartPolicyNever,
TerminationGracePeriodSeconds: ptr.To(podTerminationGracePeriodSeconds),
InitContainers: []v1.Container{
{
Name: restartableInit1,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit1, execCommand{
Delay: 600,
TerminationSeconds: 20,
ExitCode: 0,
}),
},
{
Name: restartableInit2,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit2, execCommand{
Delay: 600,
// SIGKILL won't be sent because it only gets triggered 2 seconds after SIGTERM.
TerminationSeconds: 1,
ExitCode: 0,
}),
},
{
Name: restartableInit3,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit3, execCommand{
Delay: 600,
TerminationSeconds: 20,
ExitCode: 0,
}),
},
},
Containers: []v1.Container{
{
Name: regular1,
Image: busyboxImage,
Command: ExecCommand(regular1, execCommand{
Delay: 600,
TerminationSeconds: 20,
ExitCode: 0,
}),
},
},
},
}
preparePod(pod)
ginkgo.By("Creating the pod with finalizer")
client := e2epod.NewPodClient(f)
pod = client.Create(ctx, pod)
defer client.RemoveFinalizer(ctx, pod.Name, testFinalizer)
ginkgo.By("Waiting for the pod to be initialized and run")
err := e2epod.WaitForPodRunningInNamespace(ctx, f.ClientSet, pod)
framework.ExpectNoError(err)
ginkgo.By("Deleting the pod")
err = client.Delete(ctx, pod.Name, metav1.DeleteOptions{GracePeriodSeconds: &podTerminationGracePeriodSeconds})
framework.ExpectNoError(err)
ginkgo.By(fmt.Sprintf("Waiting for the pod (%s/%s) to be transitioned into the Failed phase", pod.Namespace, pod.Name))
err = e2epod.WaitForPodTerminatedInNamespace(ctx, f.ClientSet, pod.Name, "", f.Namespace.Name)
framework.ExpectNoError(err, "Failed to await for the pod to be terminated: %q", pod.Name)
ginkgo.By(fmt.Sprintf("Fetch the end state of the pod (%s/%s)", pod.Namespace, pod.Name))
pod, err = client.Get(ctx, pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err, "Failed to fetch the end state of the pod: %q", pod.Name)
// regular container that exceeds its termination grace period seconds is sigkilled with exit code 137
expectPodTerminationContainerStatuses(pod.Status.ContainerStatuses, map[string]podTerminationContainerStatus{
regular1: {exitCode: int32(137), reason: "Error"},
})
// restartable-init-2 is gracefully terminated within 2 seconds after receiving SIGTERM.
// The other containers that exceed 2 seconds after receiving SIGTERM are sigkilled with exit code 137.
expectPodTerminationContainerStatuses(pod.Status.InitContainerStatuses, map[string]podTerminationContainerStatus{
restartableInit1: {exitCode: int32(137), reason: "Error"},
restartableInit2: {exitCode: int32(0), reason: "Completed"},
restartableInit3: {exitCode: int32(137), reason: "Error"},
})
})
})
ginkgo.When("The restartable init containers have exceeded its termination grace period seconds", func() {
ginkgo.It("should mark pod as succeeded if any of the restartable init containers have exceeded its termination grace period seconds", func(ctx context.Context) {
restartableInit1 := "restartable-init-1"
restartableInit2 := "restartable-init-2"
restartableInit3 := "restartable-init-3"
regular1 := "regular-1"
podTerminationGracePeriodSeconds := int64(5)
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "restartable-init-exceeded-termination-grace-period",
Finalizers: []string{testFinalizer},
},
Spec: v1.PodSpec{
RestartPolicy: v1.RestartPolicyNever,
TerminationGracePeriodSeconds: ptr.To(podTerminationGracePeriodSeconds),
InitContainers: []v1.Container{
{
Name: restartableInit1,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit1, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
},
{
Name: restartableInit2,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit2, execCommand{
Delay: 600,
TerminationSeconds: 20,
ExitCode: 0,
}),
},
{
Name: restartableInit3,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit3, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
},
},
Containers: []v1.Container{
{
Name: regular1,
Image: busyboxImage,
Command: ExecCommand(regular1, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
},
},
},
}
preparePod(pod)
ginkgo.By("Creating the pod with finalizer")
client := e2epod.NewPodClient(f)
pod = client.Create(ctx, pod)
defer client.RemoveFinalizer(ctx, pod.Name, testFinalizer)
ginkgo.By("Waiting for the pod to be initialized and run")
err := e2epod.WaitForPodRunningInNamespace(ctx, f.ClientSet, pod)
framework.ExpectNoError(err)
ginkgo.By("Deleting the pod")
err = client.Delete(ctx, pod.Name, metav1.DeleteOptions{GracePeriodSeconds: &podTerminationGracePeriodSeconds})
framework.ExpectNoError(err)
ginkgo.By(fmt.Sprintf("Waiting for the pod (%s/%s) to be transitioned into the Succeeded phase", pod.Namespace, pod.Name))
err = e2epod.WaitForPodSuccessInNamespace(ctx, f.ClientSet, pod.Name, f.Namespace.Name)
framework.ExpectNoError(err, "Failed to await for the pod to be terminated: %q", pod.Name)
ginkgo.By(fmt.Sprintf("Fetch the end state of the pod (%s/%s)", pod.Namespace, pod.Name))
pod, err = client.Get(ctx, pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err, "Failed to fetch the end state of the pod: %q", pod.Name)
// regular container is gracefully terminated
expectPodTerminationContainerStatuses(pod.Status.ContainerStatuses, map[string]podTerminationContainerStatus{
regular1: {exitCode: int32(0), reason: "Completed"},
})
// restartable-init-2 that exceeds its termination grace period seconds is sigkilled with exit code 137.
// The other containers are gracefully terminated within 2 seconds after receiving SIGTERM
expectPodTerminationContainerStatuses(pod.Status.InitContainerStatuses, map[string]podTerminationContainerStatus{
restartableInit1: {exitCode: int32(0), reason: "Completed"},
restartableInit2: {exitCode: int32(137), reason: "Error"},
restartableInit3: {exitCode: int32(0), reason: "Completed"},
})
})
})
ginkgo.When("The regular containers have exceeded its termination grace period seconds by prestop hook", func() {
ginkgo.It("should mark pod as failed if any of the prestop hook in regular container has exceeded its termination grace period seconds", func(ctx context.Context) {
restartableInit1 := "restartable-init-1"
restartableInit2 := "restartable-init-2"
restartableInit3 := "restartable-init-3"
regular1 := "regular-1"
podTerminationGracePeriodSeconds := int64(5)
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "regular-prestop-exceeded-termination-grace-period",
Finalizers: []string{testFinalizer},
},
Spec: v1.PodSpec{
RestartPolicy: v1.RestartPolicyNever,
TerminationGracePeriodSeconds: ptr.To(podTerminationGracePeriodSeconds),
InitContainers: []v1.Container{
{
Name: restartableInit1,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit1, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
},
{
Name: restartableInit2,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit2, execCommand{
Delay: 600,
TerminationSeconds: 20,
ExitCode: 0,
}),
},
{
Name: restartableInit3,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit3, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
},
},
Containers: []v1.Container{
{
Name: regular1,
Image: busyboxImage,
Command: ExecCommand(regular1, execCommand{
Delay: 600,
TerminationSeconds: 20,
ExitCode: 0,
}),
Lifecycle: &v1.Lifecycle{
PreStop: &v1.LifecycleHandler{
Exec: &v1.ExecAction{
Command: ExecCommand(regular1, execCommand{
Delay: 20,
ExitCode: 0,
}),
},
},
},
},
},
},
}
preparePod(pod)
ginkgo.By("Creating the pod with finalizer")
client := e2epod.NewPodClient(f)
pod = client.Create(ctx, pod)
defer client.RemoveFinalizer(ctx, pod.Name, testFinalizer)
ginkgo.By("Waiting for the pod to be initialized and run")
err := e2epod.WaitForPodRunningInNamespace(ctx, f.ClientSet, pod)
framework.ExpectNoError(err)
ginkgo.By("Deleting the pod")
err = client.Delete(ctx, pod.Name, metav1.DeleteOptions{GracePeriodSeconds: &podTerminationGracePeriodSeconds})
framework.ExpectNoError(err)
ginkgo.By(fmt.Sprintf("Waiting for the pod (%s/%s) to be transitioned into the Failed phase", pod.Namespace, pod.Name))
err = e2epod.WaitForPodTerminatedInNamespace(ctx, f.ClientSet, pod.Name, "", f.Namespace.Name)
framework.ExpectNoError(err, "Failed to await for the pod to be terminated: %q", pod.Name)
ginkgo.By(fmt.Sprintf("Fetch the end state of the pod (%s/%s)", pod.Namespace, pod.Name))
pod, err = client.Get(ctx, pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err, "Failed to fetch the end state of the pod: %q", pod.Name)
// regular container that exceeds its termination grace period seconds is sigkilled with exit code 137
expectPodTerminationContainerStatuses(pod.Status.ContainerStatuses, map[string]podTerminationContainerStatus{
regular1: {exitCode: int32(137), reason: "Error"},
})
// restartable-init-2 that exceed 2 seconds after receiving SIGTERM is sigkilled with exit code 137.
// The other containers are gracefully terminated within 2 seconds after receiving SIGTERM
expectPodTerminationContainerStatuses(pod.Status.InitContainerStatuses, map[string]podTerminationContainerStatus{
restartableInit1: {exitCode: int32(0), reason: "Completed"},
restartableInit2: {exitCode: int32(137), reason: "Error"},
restartableInit3: {exitCode: int32(0), reason: "Completed"},
})
})
})
ginkgo.When("The restartable init containers have exceeded its termination grace period seconds by prestop hook", func() {
ginkgo.It("should mark pod as succeeded if any of the prestop hook in restartable init containers have exceeded its termination grace period seconds", func(ctx context.Context) {
restartableInit1 := "restartable-init-1"
restartableInit2 := "restartable-init-2"
restartableInit3 := "restartable-init-3"
regular1 := "regular-1"
podTerminationGracePeriodSeconds := int64(5)
makePrestop := func(containerName string, delay int) *v1.Lifecycle {
return &v1.Lifecycle{
PreStop: &v1.LifecycleHandler{
Exec: &v1.ExecAction{
Command: ExecCommand(containerName, execCommand{
Delay: delay,
ExitCode: 0,
}),
},
},
}
}
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "restartable-init-prestop-exceeded-termination-grace-period",
Finalizers: []string{testFinalizer},
},
Spec: v1.PodSpec{
RestartPolicy: v1.RestartPolicyNever,
TerminationGracePeriodSeconds: ptr.To(podTerminationGracePeriodSeconds),
InitContainers: []v1.Container{
{
Name: restartableInit1,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit1, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
Lifecycle: makePrestop(restartableInit1, 1),
},
{
Name: restartableInit2,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit2, execCommand{
Delay: 600,
TerminationSeconds: 20,
ExitCode: 0,
}),
Lifecycle: makePrestop(restartableInit1, 30),
},
{
Name: restartableInit3,
Image: busyboxImage,
RestartPolicy: &containerRestartPolicyAlways,
Command: ExecCommand(restartableInit3, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
Lifecycle: makePrestop(restartableInit1, 1),
},
},
Containers: []v1.Container{
{
Name: regular1,
Image: busyboxImage,
Command: ExecCommand(regular1, execCommand{
Delay: 600,
TerminationSeconds: 1,
ExitCode: 0,
}),
},
},
},
}
preparePod(pod)
ginkgo.By("Creating the pod with finalizer")
client := e2epod.NewPodClient(f)
pod = client.Create(ctx, pod)
defer client.RemoveFinalizer(ctx, pod.Name, testFinalizer)
ginkgo.By("Waiting for the pod to be initialized and run")
err := e2epod.WaitForPodRunningInNamespace(ctx, f.ClientSet, pod)
framework.ExpectNoError(err)
ginkgo.By("Deleting the pod")
err = client.Delete(ctx, pod.Name, metav1.DeleteOptions{GracePeriodSeconds: &podTerminationGracePeriodSeconds})
framework.ExpectNoError(err)
ginkgo.By(fmt.Sprintf("Waiting for the pod (%s/%s) to be transitioned into the Succeeded phase", pod.Namespace, pod.Name))
err = e2epod.WaitForPodSuccessInNamespace(ctx, f.ClientSet, pod.Name, f.Namespace.Name)
framework.ExpectNoError(err, "Failed to await for the pod to be terminated: %q", pod.Name)
ginkgo.By(fmt.Sprintf("Fetch the end state of the pod (%s/%s)", pod.Namespace, pod.Name))
pod, err = client.Get(ctx, pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err, "Failed to fetch the end state of the pod: %q", pod.Name)
// regular container is gracefully terminated
expectPodTerminationContainerStatuses(pod.Status.ContainerStatuses, map[string]podTerminationContainerStatus{
regular1: {exitCode: int32(0), reason: "Completed"},
})
// restartable-init-2 that exceed its termination grace period seconds by prestop hook is sigkilled
// with exit code 137.
// The other containers are gracefully terminated within their termination grace period seconds
expectPodTerminationContainerStatuses(pod.Status.InitContainerStatuses, map[string]podTerminationContainerStatus{
restartableInit1: {exitCode: int32(0), reason: "Completed"},
restartableInit2: {exitCode: int32(137), reason: "Error"},
restartableInit3: {exitCode: int32(0), reason: "Completed"},
})
})
})
}) })
}) })