mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 07:20:13 +00:00
Merge pull request #122038 from lowang-bh/fixPodshow
show pod Status as phase Failed or Succeeded if it has deletionTimestamp
This commit is contained in:
commit
b669abc181
@ -51,6 +51,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/duration"
|
"k8s.io/apimachinery/pkg/util/duration"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/client-go/util/certificate/csr"
|
"k8s.io/client-go/util/certificate/csr"
|
||||||
|
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||||
"k8s.io/kubernetes/pkg/apis/admissionregistration"
|
"k8s.io/kubernetes/pkg/apis/admissionregistration"
|
||||||
"k8s.io/kubernetes/pkg/apis/apiserverinternal"
|
"k8s.io/kubernetes/pkg/apis/apiserverinternal"
|
||||||
"k8s.io/kubernetes/pkg/apis/apps"
|
"k8s.io/kubernetes/pkg/apis/apps"
|
||||||
@ -865,7 +866,8 @@ func printPod(pod *api.Pod, options printers.GenerateOptions) ([]metav1.TableRow
|
|||||||
lastRestartDate := metav1.NewTime(time.Time{})
|
lastRestartDate := metav1.NewTime(time.Time{})
|
||||||
lastRestartableInitContainerRestartDate := metav1.NewTime(time.Time{})
|
lastRestartableInitContainerRestartDate := metav1.NewTime(time.Time{})
|
||||||
|
|
||||||
reason := string(pod.Status.Phase)
|
podPhase := pod.Status.Phase
|
||||||
|
reason := string(podPhase)
|
||||||
if pod.Status.Reason != "" {
|
if pod.Status.Reason != "" {
|
||||||
reason = pod.Status.Reason
|
reason = pod.Status.Reason
|
||||||
}
|
}
|
||||||
@ -988,7 +990,7 @@ func printPod(pod *api.Pod, options printers.GenerateOptions) ([]metav1.TableRow
|
|||||||
|
|
||||||
if pod.DeletionTimestamp != nil && pod.Status.Reason == node.NodeUnreachablePodReason {
|
if pod.DeletionTimestamp != nil && pod.Status.Reason == node.NodeUnreachablePodReason {
|
||||||
reason = "Unknown"
|
reason = "Unknown"
|
||||||
} else if pod.DeletionTimestamp != nil {
|
} else if pod.DeletionTimestamp != nil && !podutil.IsPodPhaseTerminal(apiv1.PodPhase(podPhase)) {
|
||||||
reason = "Terminating"
|
reason = "Terminating"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1183,6 +1183,7 @@ func TestPrintServiceLoadBalancer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPrintPod(t *testing.T) {
|
func TestPrintPod(t *testing.T) {
|
||||||
|
deleteTime := metav1.NewTime(time.Now().Add(-10 * time.Second))
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
pod api.Pod
|
pod api.Pod
|
||||||
expect []metav1.TableRow
|
expect []metav1.TableRow
|
||||||
@ -1526,6 +1527,88 @@ func TestPrintPod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
[]metav1.TableRow{{Cells: []interface{}{"test15", "0/2", apiv1.PodReasonSchedulingGated, "0", "<unknown>"}}},
|
[]metav1.TableRow{{Cells: []interface{}{"test15", "0/2", apiv1.PodReasonSchedulingGated, "0", "<unknown>"}}},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// Test pod condition succeed
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "test16"},
|
||||||
|
Spec: api.PodSpec{Containers: make([]api.Container, 1)},
|
||||||
|
Status: api.PodStatus{
|
||||||
|
Phase: api.PodSucceeded,
|
||||||
|
ContainerStatuses: []api.ContainerStatus{
|
||||||
|
{
|
||||||
|
Ready: false,
|
||||||
|
RestartCount: 0,
|
||||||
|
State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "Completed", ExitCode: 0}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]metav1.TableRow{{Conditions: podSuccessConditions, Cells: []interface{}{"test16", "0/1", "Completed", "0", "<unknown>"}}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Test pod condition failed
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "test17"},
|
||||||
|
Spec: api.PodSpec{Containers: make([]api.Container, 1)},
|
||||||
|
Status: api.PodStatus{
|
||||||
|
Phase: api.PodFailed,
|
||||||
|
ContainerStatuses: []api.ContainerStatus{
|
||||||
|
{
|
||||||
|
Ready: false,
|
||||||
|
RestartCount: 0,
|
||||||
|
State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "Error", ExitCode: 1}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]metav1.TableRow{{Conditions: podFailedConditions, Cells: []interface{}{"test17", "0/1", "Error", "0", "<unknown>"}}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Test pod condition succeed with deletion
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "test18", DeletionTimestamp: &deleteTime},
|
||||||
|
Spec: api.PodSpec{Containers: make([]api.Container, 1)},
|
||||||
|
Status: api.PodStatus{
|
||||||
|
Phase: api.PodSucceeded,
|
||||||
|
ContainerStatuses: []api.ContainerStatus{
|
||||||
|
{
|
||||||
|
Ready: false,
|
||||||
|
RestartCount: 0,
|
||||||
|
State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "Completed", ExitCode: 0}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]metav1.TableRow{{Conditions: podSuccessConditions, Cells: []interface{}{"test18", "0/1", "Completed", "0", "<unknown>"}}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Test pod condition running with deletion
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "test19", DeletionTimestamp: &deleteTime},
|
||||||
|
Spec: api.PodSpec{Containers: make([]api.Container, 1)},
|
||||||
|
Status: api.PodStatus{
|
||||||
|
Phase: "Running",
|
||||||
|
ContainerStatuses: []api.ContainerStatus{
|
||||||
|
{
|
||||||
|
Ready: false,
|
||||||
|
RestartCount: 0,
|
||||||
|
State: api.ContainerState{Running: &api.ContainerStateRunning{}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]metav1.TableRow{{Cells: []interface{}{"test19", "0/1", "Terminating", "0", "<unknown>"}}},
|
||||||
|
},
|
||||||
|
{ // Test pod condition pending with deletion
|
||||||
|
api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "test20", DeletionTimestamp: &deleteTime},
|
||||||
|
Spec: api.PodSpec{Containers: make([]api.Container, 1)},
|
||||||
|
Status: api.PodStatus{
|
||||||
|
Phase: "Pending",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]metav1.TableRow{{Cells: []interface{}{"test20", "0/1", "Terminating", "0", "<unknown>"}}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
|
@ -811,7 +811,7 @@ func describePod(pod *corev1.Pod, events *corev1.EventList) (string, error) {
|
|||||||
}
|
}
|
||||||
printLabelsMultiline(w, "Labels", pod.Labels)
|
printLabelsMultiline(w, "Labels", pod.Labels)
|
||||||
printAnnotationsMultiline(w, "Annotations", pod.Annotations)
|
printAnnotationsMultiline(w, "Annotations", pod.Annotations)
|
||||||
if pod.DeletionTimestamp != nil {
|
if pod.DeletionTimestamp != nil && pod.Status.Phase != corev1.PodFailed && pod.Status.Phase != corev1.PodSucceeded {
|
||||||
w.Write(LEVEL_0, "Status:\tTerminating (lasts %s)\n", translateTimestampSince(*pod.DeletionTimestamp))
|
w.Write(LEVEL_0, "Status:\tTerminating (lasts %s)\n", translateTimestampSince(*pod.DeletionTimestamp))
|
||||||
w.Write(LEVEL_0, "Termination Grace Period:\t%ds\n", *pod.DeletionGracePeriodSeconds)
|
w.Write(LEVEL_0, "Termination Grace Period:\t%ds\n", *pod.DeletionGracePeriodSeconds)
|
||||||
} else {
|
} else {
|
||||||
|
@ -67,7 +67,7 @@ func TestDescribePod(t *testing.T) {
|
|||||||
gracePeriod := int64(1234)
|
gracePeriod := int64(1234)
|
||||||
condition1 := corev1.PodConditionType("condition1")
|
condition1 := corev1.PodConditionType("condition1")
|
||||||
condition2 := corev1.PodConditionType("condition2")
|
condition2 := corev1.PodConditionType("condition2")
|
||||||
fake := fake.NewSimpleClientset(&corev1.Pod{
|
runningPod := corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
Namespace: "foo",
|
Namespace: "foo",
|
||||||
@ -85,6 +85,7 @@ func TestDescribePod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Status: corev1.PodStatus{
|
Status: corev1.PodStatus{
|
||||||
|
Phase: corev1.PodRunning,
|
||||||
Conditions: []corev1.PodCondition{
|
Conditions: []corev1.PodCondition{
|
||||||
{
|
{
|
||||||
Type: condition1,
|
Type: condition1,
|
||||||
@ -92,18 +93,46 @@ func TestDescribePod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
|
||||||
c := &describeClient{T: t, Namespace: "foo", Interface: fake}
|
|
||||||
d := PodDescriber{c}
|
|
||||||
out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
}
|
||||||
if !strings.Contains(out, "bar") || !strings.Contains(out, "Status:") {
|
tests := []struct {
|
||||||
t.Errorf("unexpected out: %s", out)
|
name string
|
||||||
|
namespace string
|
||||||
|
phase corev1.PodPhase
|
||||||
|
wantOutput []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "foo", namespace: "bar", phase: "Running",
|
||||||
|
wantOutput: []string{"bar", "Status:", "Terminating (lasts 10y)", "Termination Grace Period", "1234s"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod1", namespace: "ns1", phase: "Pending",
|
||||||
|
wantOutput: []string{"pod1", "ns1", "Terminating (lasts 10y)", "Termination Grace Period", "1234s"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod2", namespace: "ns2", phase: "Succeeded",
|
||||||
|
wantOutput: []string{"pod2", "ns2", "Succeeded"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod3", namespace: "ns3", phase: "Failed",
|
||||||
|
wantOutput: []string{"pod3", "ns3", "Failed"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if !strings.Contains(out, "Terminating (lasts 10y)") || !strings.Contains(out, "1234s") {
|
|
||||||
t.Errorf("unexpected out: %s", out)
|
for i, test := range tests {
|
||||||
|
pod := runningPod.DeepCopy()
|
||||||
|
pod.Name, pod.Namespace, pod.Status.Phase = test.name, test.namespace, test.phase
|
||||||
|
fake := fake.NewSimpleClientset(pod)
|
||||||
|
c := &describeClient{T: t, Namespace: pod.Namespace, Interface: fake}
|
||||||
|
d := PodDescriber{c}
|
||||||
|
out, err := d.Describe(pod.Namespace, pod.Name, DescriberSettings{ShowEvents: true})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||||
|
}
|
||||||
|
for _, wantStr := range test.wantOutput {
|
||||||
|
if !strings.Contains(out, wantStr) {
|
||||||
|
t.Errorf("case %d didn't contain want(%s): unexpected out:\n%s", i, wantStr, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user