Change:
Kubectl describe pods id only has top level pod information, without any information related to containers. Taking kube-dns pod as an example, which has 3 containers specified: If a pod with RestartAlways policy, but all contianers are in crashloop, the user cannot interpret the true state based on above information. Proposed to include ContainerStatus here.
Why isn't this redundant with ?
is for kubectl get pods id.

Discussion:
fmt.Fprintf(out, "Labels:t%sn", formatLabels(pod.Labels)) fmt.Fprintf(out, "Status:t%sn", string(pod.Status.Phase)) fmt.Fprintf(out, "Replication Controllers:t%sn", printReplicationControllersByLabels(rcs)) <ins> fmt.Fprintf(out, "Containers:n") describeContainers(pod.Status.ContainerStatuses, out) </ins> if len(pod.Status.Conditions) > 0 { fmt.Fprint(out, "Conditions:n  TypetStatusn") for _, c := range pod.Status.Conditions {

}) } <ins> func describeContainers(containers []api.ContainerStatus, out io.Writer) { for _, container := range containers { fmt.Fprintf(out, "  %v:n", container.Name) fmt.Fprintf(out, "    Image:t%sn", container.Image) switch { case container.State.Running != nil: fmt.Fprintf(out, "    State:tRunningn") fmt.Fprintf(out, "      Started:t%vn", container.State.Running.StartedAt.Time.Format(time.RFC1123Z)) case container.State.Waiting != nil: fmt.Fprintf(out, "    State:tWaitingn") if container.State.Waiting.Reason != "" { fmt.Fprintf(out, "      Reason:t%sn", container.State.Waiting.Reason) } case container.State.Termination != nil: fmt.Fprintf(out, "    State:tTerminatedn") if container.State.Termination.Reason != "" { fmt.Fprintf(out, "      Reason:t%sn", container.State.Termination.Reason) } if container.State.Termination.Message != "" { fmt.Fprintf(out, "      Message:t%sn", container.State.Termination.Message) } fmt.Fprintf(out, "      Exit Code:t%dn", container.State.Termination.ExitCode) if container.State.Termination.Signal > 0 { fmt.Fprintf(out, "      Signal:t%dn", container.State.Termination.Signal) } fmt.Fprintf(out, "      Started:t%sn", container.State.Termination.StartedAt.Time.Format(time.RFC1123Z)) fmt.Fprintf(out, "      Finished:t%sn", container.State.Termination.FinishedAt.Time.Format(time.RFC1123Z)) default: fmt.Fprintf(out, "    State:tWaitingn") } fmt.Fprintf(out, "    Ready:t%vn", printBool(container.Ready)) fmt.Fprintf(out, "    Restart Count:t%dn", container.RestartCount) } } func printBool(value bool) string { if value { return "True" } return "False" } </ins> // ReplicationControllerDescriber generates information about a replication controller // and the pods it has created. type ReplicationControllerDescriber struct {

package kubectl import ( <ins> "bytes" </ins> "fmt" "reflect" "strings"

VerifyDatesInOrder(out, "n" /* rowDelimiter */, "t" /* columnDelimiter */, t) } <ins> func TestDescribeContainers(t *testing.T) { testCases := []struct { input            api.ContainerStatus expectedElements []string }{ // Running state. { input: api.ContainerStatus{ Name: "test", State: api.ContainerState{ Running: &api.ContainerStateRunning{ StartedAt: util.NewTime(time.Now()), }, }, Ready:        true, RestartCount: 7, Image:        "image", }, expectedElements: []string{"test", "State", "Running", "Ready", "True", "Restart Count", "7", "Image", "image", "Started"}, }, // Waiting state. { input: api.ContainerStatus{ Name: "test", State: api.ContainerState{ Waiting: &api.ContainerStateWaiting{ Reason: "potato", }, }, Ready:        true, RestartCount: 7, Image:        "image", }, expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "Reason", "potato"}, }, // Terminated state. { input: api.ContainerStatus{ Name: "test", State: api.ContainerState{ Termination: &api.ContainerStateTerminated{ StartedAt:  util.NewTime(time.Now()), FinishedAt: util.NewTime(time.Now()), Reason:     "potato", ExitCode:   2, }, }, Ready:        true, RestartCount: 7, Image:        "image", }, expectedElements: []string{"test", "State", "Terminated", "Ready", "True", "Restart Count", "7", "Image", "image", "Reason", "potato", "Started", "Finished", "Exit Code", "2"}, }, // No state defaults to waiting. { input: api.ContainerStatus{ Name:         "test", Ready:        true, RestartCount: 7, Image:        "image", }, expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image"}, }, } for i, testCase := range testCases { out := new(bytes.Buffer) describeContainers([]api.ContainerStatus{testCase.input}, out) output := out.String() for _, expected := range testCase.expectedElements { if !strings.Contains(output, expected) { t.Errorf("Test case %d: expected to find %q in output: %q", i, expected, output) } } } } </ins> func TestDescribers(t *testing.T) { first := &api.Event{} second := &api.Pod{}