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")
})
})
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"},
})
})
})
})
})