diff --git a/pkg/kubectl/resource_printer.go b/pkg/kubectl/resource_printer.go index 717d155d838..198f500d522 100644 --- a/pkg/kubectl/resource_printer.go +++ b/pkg/kubectl/resource_printer.go @@ -1474,6 +1474,12 @@ func printNode(node *api.Node, w io.Writer, options PrintOptions) error { if _, err := fmt.Fprintf(w, "%s\t%s\t%s", name, strings.Join(status, ","), translateTimestamp(node.CreationTimestamp)); err != nil { return err } + + if options.Wide { + if _, err := fmt.Fprintf(w, "\t%s", getNodeExternalIP(node)); err != nil { + return err + } + } // Display caller specify column labels first. if _, err := fmt.Fprint(w, AppendLabels(node.Labels, options.ColumnLabels)); err != nil { return err @@ -1482,6 +1488,17 @@ func printNode(node *api.Node, w io.Writer, options PrintOptions) error { return err } +// Returns first external ip of the node or "" if none is found. +func getNodeExternalIP(node *api.Node) string { + for _, address := range node.Status.Addresses { + if address.Type == api.NodeExternalIP { + return address.Address + } + } + + return "" +} + func printNodeList(list *api.NodeList, w io.Writer, options PrintOptions) error { for _, node := range list.Items { if err := printNode(&node, w, options); err != nil { @@ -2179,6 +2196,9 @@ func formatWideHeaders(wide bool, t reflect.Type) []string { if t.String() == "*extensions.ReplicaSet" || t.String() == "*extensions.ReplicaSetList" { return []string{"CONTAINER(S)", "IMAGE(S)", "SELECTOR"} } + if t.String() == "*api.Node" || t.String() == "*api.NodeList" { + return []string{"EXTERNAL-IP"} + } } return nil } diff --git a/pkg/kubectl/resource_printer_test.go b/pkg/kubectl/resource_printer_test.go index 1834332db2f..bfc210cbbeb 100644 --- a/pkg/kubectl/resource_printer_test.go +++ b/pkg/kubectl/resource_printer_test.go @@ -692,6 +692,55 @@ func TestPrintNodeStatus(t *testing.T) { } } +func TestPrintNodeExternalIP(t *testing.T) { + printer := NewHumanReadablePrinter(PrintOptions{ + ColumnLabels: []string{}, + Wide: true, + }) + table := []struct { + node api.Node + externalIP string + }{ + { + node: api.Node{ + ObjectMeta: api.ObjectMeta{Name: "foo1"}, + Status: api.NodeStatus{Addresses: []api.NodeAddress{{Type: api.NodeExternalIP, Address: "1.1.1.1"}}}, + }, + externalIP: "1.1.1.1", + }, + { + node: api.Node{ + ObjectMeta: api.ObjectMeta{Name: "foo2"}, + Status: api.NodeStatus{Addresses: []api.NodeAddress{{Type: api.NodeInternalIP, Address: "1.1.1.1"}}}, + }, + externalIP: "", + }, + { + node: api.Node{ + ObjectMeta: api.ObjectMeta{Name: "foo3"}, + Status: api.NodeStatus{Addresses: []api.NodeAddress{ + {Type: api.NodeLegacyHostIP, Address: "1.1.1.1"}, + {Type: api.NodeExternalIP, Address: "2.2.2.2"}, + {Type: api.NodeInternalIP, Address: "3.3.3.3"}, + {Type: api.NodeExternalIP, Address: "4.4.4.4"}, + }}, + }, + externalIP: "2.2.2.2", + }, + } + + for _, test := range table { + buffer := &bytes.Buffer{} + err := printer.PrintObj(&test.node, buffer) + if err != nil { + t.Fatalf("An error occurred printing Node: %#v", err) + } + if !contains(strings.Fields(buffer.String()), test.externalIP) { + t.Fatalf("Expect printing node %s with external ip %#v, got: %#v", test.node.Name, test.externalIP, buffer.String()) + } + } +} + func contains(fields []string, field string) bool { for _, v := range fields { if v == field {