From fe02b543aacae864cf5802ac48b79fcdeab8142b Mon Sep 17 00:00:00 2001 From: kkkkun Date: Tue, 14 Jan 2025 14:36:41 +0800 Subject: [PATCH] Fixes pod status error when it has an error container Signed-off-by: kkkkun --- pkg/printers/internalversion/printers.go | 25 ++- pkg/printers/internalversion/printers_test.go | 178 ++++++++++++++++-- 2 files changed, 180 insertions(+), 23 deletions(-) diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index 196bc40ec08..a6126a073a6 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -956,6 +956,7 @@ func printPod(pod *api.Pod, options printers.GenerateOptions) ([]metav1.TableRow restarts = restartableInitContainerRestarts lastRestartDate = lastRestartableInitContainerRestartDate hasRunning := false + errorReason := "" for i := len(pod.Status.ContainerStatuses) - 1; i >= 0; i-- { container := pod.Status.ContainerStatuses[i] @@ -966,27 +967,33 @@ func printPod(pod *api.Pod, options printers.GenerateOptions) ([]metav1.TableRow lastRestartDate = terminatedDate } } - if container.State.Waiting != nil && container.State.Waiting.Reason != "" { + switch { + case container.State.Waiting != nil && container.State.Waiting.Reason != "": reason = container.State.Waiting.Reason - } else if container.State.Terminated != nil && container.State.Terminated.Reason != "" { - reason = container.State.Terminated.Reason - } else if container.State.Terminated != nil && container.State.Terminated.Reason == "" { - if container.State.Terminated.Signal != 0 { + case container.State.Terminated != nil: + if len(container.State.Terminated.Reason) > 0 { + reason = container.State.Terminated.Reason + } else if container.State.Terminated.Signal != 0 { reason = fmt.Sprintf("Signal:%d", container.State.Terminated.Signal) } else { reason = fmt.Sprintf("ExitCode:%d", container.State.Terminated.ExitCode) } - } else if container.Ready && container.State.Running != nil { + if container.State.Terminated.ExitCode != 0 { + errorReason = reason + } + case container.Ready && container.State.Running != nil: hasRunning = true readyContainers++ } } // change pod status back to "Running" if there is at least one container still reporting as "Running" status - if reason == "Completed" && hasRunning { - if hasPodReadyCondition(pod.Status.Conditions) { + if reason == "Completed" { + if hasRunning && hasPodReadyCondition(pod.Status.Conditions) { reason = "Running" - } else { + } else if errorReason != "" { + reason = errorReason + } else if hasRunning { reason = "NotReady" } } diff --git a/pkg/printers/internalversion/printers_test.go b/pkg/printers/internalversion/printers_test.go index e72cab35696..0837f9ee29f 100644 --- a/pkg/printers/internalversion/printers_test.go +++ b/pkg/printers/internalversion/printers_test.go @@ -1537,9 +1537,8 @@ func TestPrintPod(t *testing.T) { Phase: api.PodSucceeded, ContainerStatuses: []api.ContainerStatus{ { - Ready: false, - RestartCount: 0, - State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "Completed", ExitCode: 0}}, + Ready: false, + State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "Completed", ExitCode: 0}}, }, }, }, @@ -1555,9 +1554,8 @@ func TestPrintPod(t *testing.T) { Phase: api.PodFailed, ContainerStatuses: []api.ContainerStatus{ { - Ready: false, - RestartCount: 0, - State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "Error", ExitCode: 1}}, + Ready: false, + State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "Error", ExitCode: 1}}, }, }, }, @@ -1573,9 +1571,8 @@ func TestPrintPod(t *testing.T) { Phase: api.PodSucceeded, ContainerStatuses: []api.ContainerStatus{ { - Ready: false, - RestartCount: 0, - State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "Completed", ExitCode: 0}}, + Ready: false, + State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "Completed", ExitCode: 0}}, }, }, }, @@ -1588,12 +1585,11 @@ func TestPrintPod(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "test19", DeletionTimestamp: &deleteTime}, Spec: api.PodSpec{Containers: make([]api.Container, 1)}, Status: api.PodStatus{ - Phase: "Running", + Phase: api.PodRunning, ContainerStatuses: []api.ContainerStatus{ { - Ready: false, - RestartCount: 0, - State: api.ContainerState{Running: &api.ContainerStateRunning{}}, + Ready: false, + State: api.ContainerState{Running: &api.ContainerStateRunning{}}, }, }, }, @@ -1605,11 +1601,165 @@ func TestPrintPod(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "test20", DeletionTimestamp: &deleteTime}, Spec: api.PodSpec{Containers: make([]api.Container, 1)}, Status: api.PodStatus{ - Phase: "Pending", + Phase: api.PodPending, }, }, []metav1.TableRow{{Cells: []interface{}{"test20", "0/1", "Terminating", "0", ""}}}, }, + // Test the two containers. They are ready and State are Error/Running + // reference: https://github.com/kubernetes/kubernetes/issues/107713 + { + api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "test21"}, + Spec: api.PodSpec{Containers: make([]api.Container, 2)}, + Status: api.PodStatus{ + Phase: api.PodFailed, + ContainerStatuses: []api.ContainerStatus{ + { + Ready: false, + State: api.ContainerState{Terminated: &api.ContainerStateTerminated{ + FinishedAt: metav1.NewTime(time.Now()), + ExitCode: 1, + Reason: "podCrash"}, + }, + LastTerminationState: api.ContainerState{}, + }, + { + Ready: true, + State: api.ContainerState{Running: &api.ContainerStateRunning{ + StartedAt: metav1.NewTime(time.Now())}, + }, + LastTerminationState: api.ContainerState{}, + }, + }, + }, + }, + []metav1.TableRow{ + { + Cells: []interface{}{"test21", "1/2", "podCrash", "0", ""}, + Conditions: podFailedConditions, + }, + }, + }, + // Test the two containers. They are ready and State are Running/Error + // reference: https://github.com/kubernetes/kubernetes/issues/107713 + { + api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "test22"}, + Spec: api.PodSpec{Containers: make([]api.Container, 2)}, + Status: api.PodStatus{ + Phase: api.PodFailed, + ContainerStatuses: []api.ContainerStatus{ + { + Ready: true, + State: api.ContainerState{Running: &api.ContainerStateRunning{ + StartedAt: metav1.NewTime(time.Now())}, + }, + LastTerminationState: api.ContainerState{}, + }, + { + Ready: false, + State: api.ContainerState{Terminated: &api.ContainerStateTerminated{ + FinishedAt: metav1.NewTime(time.Now()), + ExitCode: 1, + Reason: "podCrash"}, + }, + LastTerminationState: api.ContainerState{}, + }, + }, + }, + }, + []metav1.TableRow{ + { + Cells: []interface{}{"test22", "1/2", "podCrash", "0", ""}, + Conditions: podFailedConditions, + }, + }, + }, + { + // Test the three containers. They are ready and State are Running/Error/Completed + api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "test23"}, + Spec: api.PodSpec{Containers: make([]api.Container, 3)}, + Status: api.PodStatus{ + Phase: "Failed", + ContainerStatuses: []api.ContainerStatus{ + { + Ready: true, + State: api.ContainerState{Running: &api.ContainerStateRunning{ + StartedAt: metav1.NewTime(time.Now())}, + }, + LastTerminationState: api.ContainerState{}, + }, + { + Ready: true, + State: api.ContainerState{Terminated: &api.ContainerStateTerminated{ + FinishedAt: metav1.NewTime(time.Now()), + ExitCode: 1, + Reason: "podCrash"}, + }, + LastTerminationState: api.ContainerState{}, + }, + { + Ready: true, + State: api.ContainerState{Terminated: &api.ContainerStateTerminated{ + FinishedAt: metav1.NewTime(time.Now()), + ExitCode: 0}, + }, + LastTerminationState: api.ContainerState{}, + }, + }, + }, + }, + []metav1.TableRow{ + { + Cells: []interface{}{"test23", "1/3", "podCrash", "0", ""}, + Conditions: podFailedConditions, + }, + }, + }, + { + // Test the three containers. They are notReady and State are Running/Error/Completed + api.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "test24"}, + Spec: api.PodSpec{Containers: make([]api.Container, 3)}, + Status: api.PodStatus{ + Phase: "Failed", + ContainerStatuses: []api.ContainerStatus{ + { + Ready: false, + State: api.ContainerState{Running: &api.ContainerStateRunning{ + StartedAt: metav1.NewTime(time.Now())}, + }, + LastTerminationState: api.ContainerState{}, + }, + { + Ready: false, + State: api.ContainerState{Terminated: &api.ContainerStateTerminated{ + FinishedAt: metav1.NewTime(time.Now()), + ExitCode: 1, + Reason: "podCrash"}, + }, + LastTerminationState: api.ContainerState{}, + }, + { + Ready: false, + State: api.ContainerState{Terminated: &api.ContainerStateTerminated{ + FinishedAt: metav1.NewTime(time.Now()), + ExitCode: 0}, + }, + LastTerminationState: api.ContainerState{}, + }, + }, + }, + }, + []metav1.TableRow{ + { + Cells: []interface{}{"test24", "0/3", "podCrash", "0", ""}, + Conditions: podFailedConditions, + }, + }, + }, } for i, test := range tests {