From e7dcec075a120e23197c54f0710c56acde665b0d Mon Sep 17 00:00:00 2001 From: Sam Abed Date: Fri, 7 Aug 2015 11:45:20 +1000 Subject: [PATCH] show LastTerminationState in kubectl describe pod Signed-off-by: Sam Abed --- docs/user-guide/compute-resources.md | 36 +++++++++-------- pkg/kubectl/describe.go | 58 +++++++++++++++------------- pkg/kubectl/describe_test.go | 23 +++++++++++ 3 files changed, 74 insertions(+), 43 deletions(-) diff --git a/docs/user-guide/compute-resources.md b/docs/user-guide/compute-resources.md index 2687104f312..003a22d8719 100644 --- a/docs/user-guide/compute-resources.md +++ b/docs/user-guide/compute-resources.md @@ -185,26 +185,30 @@ on the pod you are interested in: ```console [12:54:41] $ ./cluster/kubectl.sh describe pod simmemleak-hra99 -Name: simmemleak-hra99 -Namespace: default -Image(s): saadali/simmemleak -Node: kubernetes-minion-tf0f/10.240.216.66 -Labels: name=simmemleak -Status: Running +Name: simmemleak-hra99 +Namespace: default +Image(s): saadali/simmemleak +Node: kubernetes-minion-tf0f/10.240.216.66 +Labels: name=simmemleak +Status: Running Reason: Message: -IP: 10.244.2.75 -Replication Controllers: simmemleak (1/1 replicas created) +IP: 10.244.2.75 +Replication Controllers: simmemleak (1/1 replicas created) Containers: simmemleak: Image: saadali/simmemleak Limits: - cpu: 100m - memory: 50Mi - State: Running - Started: Tue, 07 Jul 2015 12:54:41 -0700 - Ready: False - Restart Count: 5 + cpu: 100m + memory: 50Mi + State: Running + Started: Tue, 07 Jul 2015 12:54:41 -0700 + Last Termination State: Terminated + Exit Code: 1 + Started: Fri, 07 Jul 2015 12:54:30 -0700 + Finished: Fri, 07 Jul 2015 12:54:33 -0700 + Ready: False + Restart Count: 5 Conditions: Type Status Ready False @@ -219,9 +223,7 @@ Events: The `Restart Count: 5` indicates that the `simmemleak` container in this pod was terminated and restarted 5 times. -Once [#10861](http://issue.k8s.io/10861) is resolved the reason for the termination of the last container will also be printed in this output. - -Until then you can call `get pod` with the `-o template -t ...` option to fetch the status of previously terminated containers: +You can call `get pod` with the `-o template -t ...` option to fetch the status of previously terminated containers: ```console [13:59:01] $ ./cluster/kubectl.sh get pod -o template -t '{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-60xbc diff --git a/pkg/kubectl/describe.go b/pkg/kubectl/describe.go index 083bd45dbb8..ba706a97600 100644 --- a/pkg/kubectl/describe.go +++ b/pkg/kubectl/describe.go @@ -500,33 +500,10 @@ func describeContainers(pod *api.Pod, out io.Writer) { fmt.Fprintf(out, " %s:\t%s\n", name, quantity.String()) } - switch { - case state.Running != nil: - fmt.Fprintf(out, " State:\tRunning\n") - fmt.Fprintf(out, " Started:\t%v\n", state.Running.StartedAt.Time.Format(time.RFC1123Z)) - case state.Waiting != nil: - fmt.Fprintf(out, " State:\tWaiting\n") - if state.Waiting.Reason != "" { - fmt.Fprintf(out, " Reason:\t%s\n", state.Waiting.Reason) - } - case state.Terminated != nil: - fmt.Fprintf(out, " State:\tTerminated\n") - if state.Terminated.Reason != "" { - fmt.Fprintf(out, " Reason:\t%s\n", state.Terminated.Reason) - } - if state.Terminated.Message != "" { - fmt.Fprintf(out, " Message:\t%s\n", state.Terminated.Message) - } - fmt.Fprintf(out, " Exit Code:\t%d\n", state.Terminated.ExitCode) - if state.Terminated.Signal > 0 { - fmt.Fprintf(out, " Signal:\t%d\n", state.Terminated.Signal) - } - fmt.Fprintf(out, " Started:\t%s\n", state.Terminated.StartedAt.Time.Format(time.RFC1123Z)) - fmt.Fprintf(out, " Finished:\t%s\n", state.Terminated.FinishedAt.Time.Format(time.RFC1123Z)) - default: - fmt.Fprintf(out, " State:\tWaiting\n") + describeStatus("State", state, out) + if status.LastTerminationState.Terminated != nil { + describeStatus("Last Termination State", status.LastTerminationState, out) } - fmt.Fprintf(out, " Ready:\t%v\n", printBool(status.Ready)) fmt.Fprintf(out, " Restart Count:\t%d\n", status.RestartCount) fmt.Fprintf(out, " Variables:\n") @@ -555,6 +532,35 @@ func envValueFrom(pod *api.Pod, e api.EnvVar) string { return valueFrom } +func describeStatus(stateName string, state api.ContainerState, out io.Writer) { + switch { + case state.Running != nil: + fmt.Fprintf(out, " %s:\tRunning\n", stateName) + fmt.Fprintf(out, " Started:\t%v\n", state.Running.StartedAt.Time.Format(time.RFC1123Z)) + case state.Waiting != nil: + fmt.Fprintf(out, " %s:\tWaiting\n", stateName) + if state.Waiting.Reason != "" { + fmt.Fprintf(out, " Reason:\t%s\n", state.Waiting.Reason) + } + case state.Terminated != nil: + fmt.Fprintf(out, " %s:\tTerminated\n", stateName) + if state.Terminated.Reason != "" { + fmt.Fprintf(out, " Reason:\t%s\n", state.Terminated.Reason) + } + if state.Terminated.Message != "" { + fmt.Fprintf(out, " Message:\t%s\n", state.Terminated.Message) + } + fmt.Fprintf(out, " Exit Code:\t%d\n", state.Terminated.ExitCode) + if state.Terminated.Signal > 0 { + fmt.Fprintf(out, " Signal:\t%d\n", state.Terminated.Signal) + } + fmt.Fprintf(out, " Started:\t%s\n", state.Terminated.StartedAt.Time.Format(time.RFC1123Z)) + fmt.Fprintf(out, " Finished:\t%s\n", state.Terminated.FinishedAt.Time.Format(time.RFC1123Z)) + default: + fmt.Fprintf(out, " %s:\tWaiting\n", stateName) + } +} + func printBool(value bool) string { if value { return "True" diff --git a/pkg/kubectl/describe_test.go b/pkg/kubectl/describe_test.go index a5e63d6f508..5187cf68f1d 100644 --- a/pkg/kubectl/describe_test.go +++ b/pkg/kubectl/describe_test.go @@ -172,6 +172,29 @@ func TestDescribeContainers(t *testing.T) { }, expectedElements: []string{"test", "State", "Terminated", "Ready", "True", "Restart Count", "7", "Image", "image", "Reason", "potato", "Started", "Finished", "Exit Code", "2"}, }, + // Last Terminated + { + container: api.Container{Name: "test", Image: "image"}, + status: api.ContainerStatus{ + Name: "test", + State: api.ContainerState{ + Running: &api.ContainerStateRunning{ + StartedAt: util.NewTime(time.Now()), + }, + }, + LastTerminationState: api.ContainerState{ + Terminated: &api.ContainerStateTerminated{ + StartedAt: util.NewTime(time.Now().Add(time.Second * 3)), + FinishedAt: util.NewTime(time.Now()), + Reason: "crashing", + ExitCode: 3, + }, + }, + Ready: true, + RestartCount: 7, + }, + expectedElements: []string{"test", "State", "Terminated", "Ready", "True", "Restart Count", "7", "Image", "image", "Started", "Finished", "Exit Code", "2", "crashing", "3"}, + }, // No state defaults to waiting. { container: api.Container{Name: "test", Image: "image"},