diff --git a/pkg/kubectl/cmd/get/humanreadable_flags_test.go b/pkg/kubectl/cmd/get/humanreadable_flags_test.go index 6b31c48c9d..cc547df42a 100644 --- a/pkg/kubectl/cmd/get/humanreadable_flags_test.go +++ b/pkg/kubectl/cmd/get/humanreadable_flags_test.go @@ -61,7 +61,7 @@ func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) { { name: "\"wide\" output format prints", outputFormat: "wide", - expectedOutput: "NAME\\ +READY\\ +STATUS\\ +RESTARTS\\ +AGE\\ +IP\\ +NODE\\ +NOMINATED NODE\nfoo\\ +0/0\\ +0\\ +\\ +\\ +\\ +\n", + expectedOutput: "NAME\\ +READY\\ +STATUS\\ +RESTARTS\\ +AGE\\ +IP\\ +NODE\\ +NOMINATED NODE\\ +READINESS GATES\nfoo\\ +0/0\\ +0\\ +\\ +\\ +\\ +\\ +\n", }, { name: "no-headers prints output with no headers", @@ -72,7 +72,7 @@ func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) { name: "no-headers and a \"wide\" output format prints output with no headers and additional columns", outputFormat: "wide", noHeaders: true, - expectedOutput: "foo\\ +0/0\\ +0\\ +\\ +\\ +\\ +\n", + expectedOutput: "foo\\ +0/0\\ +0\\ +\\ +\\ +\\ +\\ +\n", }, { name: "show-kind displays the resource's kind, even when printing a single type of resource", diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index 9451562042..0ff288be76 100644 --- a/pkg/printers/internalversion/describe.go +++ b/pkg/printers/internalversion/describe.go @@ -679,6 +679,21 @@ func describePod(pod *api.Pod, events *api.EventList) (string, error) { describeContainers("Init Containers", pod.Spec.InitContainers, pod.Status.InitContainerStatuses, EnvValueRetriever(pod), w, "") } describeContainers("Containers", pod.Spec.Containers, pod.Status.ContainerStatuses, EnvValueRetriever(pod), w, "") + if len(pod.Spec.ReadinessGates) > 0 { + w.Write(LEVEL_0, "Readiness Gates:\n Type\tStatus\n") + for _, g := range pod.Spec.ReadinessGates { + status := "" + for _, c := range pod.Status.Conditions { + if c.Type == g.ConditionType { + status = fmt.Sprintf("%v", c.Status) + break + } + } + w.Write(LEVEL_1, "%v \t%v \n", + g.ConditionType, + status) + } + } if len(pod.Status.Conditions) > 0 { w.Write(LEVEL_0, "Conditions:\n Type\tStatus\n") for _, c := range pod.Status.Conditions { diff --git a/pkg/printers/internalversion/describe_test.go b/pkg/printers/internalversion/describe_test.go index fb0e88b713..25ea2a92a8 100644 --- a/pkg/printers/internalversion/describe_test.go +++ b/pkg/printers/internalversion/describe_test.go @@ -55,6 +55,8 @@ type describeClient struct { func TestDescribePod(t *testing.T) { deletionTimestamp := metav1.Time{Time: time.Now().UTC().AddDate(10, 0, 0)} gracePeriod := int64(1234) + condition1 := api.PodConditionType("condition1") + condition2 := api.PodConditionType("condition2") fake := fake.NewSimpleClientset(&api.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", @@ -62,6 +64,24 @@ func TestDescribePod(t *testing.T) { DeletionTimestamp: &deletionTimestamp, DeletionGracePeriodSeconds: &gracePeriod, }, + Spec: api.PodSpec{ + ReadinessGates: []api.PodReadinessGate{ + { + ConditionType: condition1, + }, + { + ConditionType: condition2, + }, + }, + }, + Status: api.PodStatus{ + Conditions: []api.PodCondition{ + { + Type: condition1, + Status: api.ConditionTrue, + }, + }, + }, }) c := &describeClient{T: t, Namespace: "foo", Interface: fake} d := PodDescriber{c} diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index 1225434cad..9019c70e66 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -86,6 +86,7 @@ func AddHandlers(h printers.PrintHandler) { {Name: "IP", Type: "string", Priority: 1, Description: apiv1.PodStatus{}.SwaggerDoc()["podIP"]}, {Name: "Node", Type: "string", Priority: 1, Description: apiv1.PodSpec{}.SwaggerDoc()["nodeName"]}, {Name: "Nominated Node", Type: "string", Priority: 1, Description: apiv1.PodStatus{}.SwaggerDoc()["nominatedNodeName"]}, + {Name: "Readiness Gates", Type: "string", Priority: 1, Description: apiv1.PodSpec{}.SwaggerDoc()["readinessGates"]}, } h.TableHandler(podColumnDefinitions, printPodList) h.TableHandler(podColumnDefinitions, printPod) @@ -661,11 +662,11 @@ func printPod(pod *api.Pod, options printers.PrintOptions) ([]metav1beta1.TableR } row.Cells = append(row.Cells, pod.Name, fmt.Sprintf("%d/%d", readyContainers, totalContainers), reason, int64(restarts), translateTimestampSince(pod.CreationTimestamp)) - if options.Wide { nodeName := pod.Spec.NodeName nominatedNodeName := pod.Status.NominatedNodeName podIP := pod.Status.PodIP + if podIP == "" { podIP = "" } @@ -675,7 +676,24 @@ func printPod(pod *api.Pod, options printers.PrintOptions) ([]metav1beta1.TableR if nominatedNodeName == "" { nominatedNodeName = "" } - row.Cells = append(row.Cells, podIP, nodeName, nominatedNodeName) + + readinessGates := "" + if len(pod.Spec.ReadinessGates) > 0 { + trueConditions := 0 + for _, readinessGate := range pod.Spec.ReadinessGates { + conditionType := readinessGate.ConditionType + for _, condition := range pod.Status.Conditions { + if condition.Type == conditionType { + if condition.Status == api.ConditionTrue { + trueConditions += 1 + } + break + } + } + } + readinessGates = fmt.Sprintf("%d/%d", trueConditions, len(pod.Spec.ReadinessGates)) + } + row.Cells = append(row.Cells, podIP, nodeName, nominatedNodeName, readinessGates) } return []metav1beta1.TableRow{row}, nil diff --git a/pkg/printers/internalversion/printers_test.go b/pkg/printers/internalversion/printers_test.go index 4107c53927..4635db90b6 100644 --- a/pkg/printers/internalversion/printers_test.go +++ b/pkg/printers/internalversion/printers_test.go @@ -1649,6 +1649,9 @@ func TestPrintPod(t *testing.T) { } func TestPrintPodwide(t *testing.T) { + condition1 := "condition1" + condition2 := "condition2" + condition3 := "condition3" tests := []struct { pod api.Pod expect []metav1beta1.TableRow @@ -1660,8 +1663,29 @@ func TestPrintPodwide(t *testing.T) { Spec: api.PodSpec{ Containers: make([]api.Container, 2), NodeName: "test1", + ReadinessGates: []api.PodReadinessGate{ + { + ConditionType: api.PodConditionType(condition1), + }, + { + ConditionType: api.PodConditionType(condition2), + }, + { + ConditionType: api.PodConditionType(condition3), + }, + }, }, Status: api.PodStatus{ + Conditions: []api.PodCondition{ + { + Type: api.PodConditionType(condition1), + Status: api.ConditionFalse, + }, + { + Type: api.PodConditionType(condition2), + Status: api.ConditionTrue, + }, + }, Phase: "podPhase", PodIP: "1.1.1.1", ContainerStatuses: []api.ContainerStatus{ @@ -1671,7 +1695,7 @@ func TestPrintPodwide(t *testing.T) { NominatedNodeName: "node1", }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), "", "1.1.1.1", "test1", "node1"}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", int64(6), "", "1.1.1.1", "test1", "node1", "1/3"}}}, }, { // Test when the NodeName and PodIP are none @@ -1690,7 +1714,7 @@ func TestPrintPodwide(t *testing.T) { }, }, }, - []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", int64(6), "", "", "", ""}}}, + []metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", int64(6), "", "", "", "", ""}}}, }, } diff --git a/pkg/registry/core/pod/storage/storage_test.go b/pkg/registry/core/pod/storage/storage_test.go index c806fe6441..5a084bc131 100644 --- a/pkg/registry/core/pod/storage/storage_test.go +++ b/pkg/registry/core/pod/storage/storage_test.go @@ -421,8 +421,11 @@ func TestConvertToTableList(t *testing.T) { {Name: "IP", Type: "string", Priority: 1, Description: v1.PodStatus{}.SwaggerDoc()["podIP"]}, {Name: "Node", Type: "string", Priority: 1, Description: v1.PodSpec{}.SwaggerDoc()["nodeName"]}, {Name: "Nominated Node", Type: "string", Priority: 1, Description: v1.PodStatus{}.SwaggerDoc()["nominatedNodeName"]}, + {Name: "Readiness Gates", Type: "string", Priority: 1, Description: v1.PodSpec{}.SwaggerDoc()["readinessGates"]}, } + condition1 := "condition1" + condition2 := "condition2" pod1 := &api.Pod{ ObjectMeta: metav1.ObjectMeta{Namespace: "test", Name: "foo", CreationTimestamp: metav1.NewTime(time.Now().Add(-370 * 24 * time.Hour))}, Spec: api.PodSpec{ @@ -431,8 +434,26 @@ func TestConvertToTableList(t *testing.T) { {Name: "ctr2", Ports: []api.ContainerPort{{ContainerPort: 9376}}}, }, NodeName: "test-node", + ReadinessGates: []api.PodReadinessGate{ + { + ConditionType: api.PodConditionType(condition1), + }, + { + ConditionType: api.PodConditionType(condition2), + }, + }, }, Status: api.PodStatus{ + Conditions: []api.PodCondition{ + { + Type: api.PodConditionType(condition1), + Status: api.ConditionFalse, + }, + { + Type: api.PodConditionType(condition2), + Status: api.ConditionTrue, + }, + }, PodIP: "10.1.2.3", Phase: api.PodPending, ContainerStatuses: []api.ContainerStatus{ @@ -457,7 +478,7 @@ func TestConvertToTableList(t *testing.T) { out: &metav1beta1.Table{ ColumnDefinitions: columns, Rows: []metav1beta1.TableRow{ - {Cells: []interface{}{"", "0/0", "", int64(0), "", "", "", ""}, Object: runtime.RawExtension{Object: &api.Pod{}}}, + {Cells: []interface{}{"", "0/0", "", int64(0), "", "", "", "", ""}, Object: runtime.RawExtension{Object: &api.Pod{}}}, }, }, }, @@ -466,7 +487,7 @@ func TestConvertToTableList(t *testing.T) { out: &metav1beta1.Table{ ColumnDefinitions: columns, Rows: []metav1beta1.TableRow{ - {Cells: []interface{}{"foo", "1/2", "Pending", int64(10), "370d", "10.1.2.3", "test-node", "nominated-node"}, Object: runtime.RawExtension{Object: pod1}}, + {Cells: []interface{}{"foo", "1/2", "Pending", int64(10), "370d", "10.1.2.3", "test-node", "nominated-node", "1/2"}, Object: runtime.RawExtension{Object: pod1}}, }, }, },