Merge pull request #6361 from vmarmol/describe

Include ContainerStatus in "describe pod".
pull/6/head
Brendan Burns 2015-04-02 09:23:21 -07:00
commit fdf7ccbcfe
2 changed files with 124 additions and 0 deletions

View File

@ -242,6 +242,8 @@ func describePod(pod *api.Pod, rcs []api.ReplicationController, events *api.Even
fmt.Fprintf(out, "Labels:\t%s\n", formatLabels(pod.Labels))
fmt.Fprintf(out, "Status:\t%s\n", string(pod.Status.Phase))
fmt.Fprintf(out, "Replication Controllers:\t%s\n", printReplicationControllersByLabels(rcs))
fmt.Fprintf(out, "Containers:\n")
describeContainers(pod.Status.ContainerStatuses, out)
if len(pod.Status.Conditions) > 0 {
fmt.Fprint(out, "Conditions:\n Type\tStatus\n")
for _, c := range pod.Status.Conditions {
@ -257,6 +259,50 @@ func describePod(pod *api.Pod, rcs []api.ReplicationController, events *api.Even
})
}
func describeContainers(containers []api.ContainerStatus, out io.Writer) {
for _, container := range containers {
fmt.Fprintf(out, " %v:\n", container.Name)
fmt.Fprintf(out, " Image:\t%s\n", container.Image)
switch {
case container.State.Running != nil:
fmt.Fprintf(out, " State:\tRunning\n")
fmt.Fprintf(out, " Started:\t%v\n", container.State.Running.StartedAt.Time.Format(time.RFC1123Z))
case container.State.Waiting != nil:
fmt.Fprintf(out, " State:\tWaiting\n")
if container.State.Waiting.Reason != "" {
fmt.Fprintf(out, " Reason:\t%s\n", container.State.Waiting.Reason)
}
case container.State.Termination != nil:
fmt.Fprintf(out, " State:\tTerminated\n")
if container.State.Termination.Reason != "" {
fmt.Fprintf(out, " Reason:\t%s\n", container.State.Termination.Reason)
}
if container.State.Termination.Message != "" {
fmt.Fprintf(out, " Message:\t%s\n", container.State.Termination.Message)
}
fmt.Fprintf(out, " Exit Code:\t%d\n", container.State.Termination.ExitCode)
if container.State.Termination.Signal > 0 {
fmt.Fprintf(out, " Signal:\t%d\n", container.State.Termination.Signal)
}
fmt.Fprintf(out, " Started:\t%s\n", container.State.Termination.StartedAt.Time.Format(time.RFC1123Z))
fmt.Fprintf(out, " Finished:\t%s\n", container.State.Termination.FinishedAt.Time.Format(time.RFC1123Z))
default:
fmt.Fprintf(out, " State:\tWaiting\n")
}
fmt.Fprintf(out, " Ready:\t%v\n", printBool(container.Ready))
fmt.Fprintf(out, " Restart Count:\t%d\n", container.RestartCount)
}
}
func printBool(value bool) string {
if value {
return "True"
}
return "False"
}
// ReplicationControllerDescriber generates information about a replication controller
// and the pods it has created.
type ReplicationControllerDescriber struct {

View File

@ -17,6 +17,7 @@ limitations under the License.
package kubectl
import (
"bytes"
"fmt"
"reflect"
"strings"
@ -107,6 +108,83 @@ func TestPodDescribeResultsSorted(t *testing.T) {
VerifyDatesInOrder(out, "\n" /* rowDelimiter */, "\t" /* columnDelimiter */, t)
}
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)
}
}
}
}
func TestDescribers(t *testing.T) {
first := &api.Event{}
second := &api.Pod{}