Fix up alignment of columns w/ namespaces.

Fixes #10842

All issues for types that use "extra lines" for extended information.  Two issues fixed: (1) When namespaces are listed an extra column isn't inserted for extra lines and (2) trailing tabs aren't inserted when label columns are specified.

This code should probably move to a more explicit model of putting data into "cells".

The test for this hits https://github.com/golang/go/issues/6416 and so I introduced a "LineDelimiter" writer filter to make white space more visible.
This commit is contained in:
Joe Beda
2015-07-07 11:35:24 -07:00
parent 98b5576a99
commit c15953662e
4 changed files with 207 additions and 4 deletions

View File

@@ -319,6 +319,72 @@ func ExamplePrintPodWithWideFormat() {
// test1 1/2 podPhase 6 10y kubernetes-minion-abcd
}
func ExamplePrintServiceWithNamespacesAndLabels() {
f, tf, codec := NewAPIFactory()
tf.Printer = kubectl.NewHumanReadablePrinter(false, true, false, []string{"l1"})
tf.Client = &client.FakeRESTClient{
Codec: codec,
Client: nil,
}
cmd := NewCmdRun(f, os.Stdout)
svc := &api.ServiceList{
Items: []api.Service{
{
ObjectMeta: api.ObjectMeta{
Name: "svc1",
Namespace: "ns1",
Labels: map[string]string{
"l1": "value",
},
},
Spec: api.ServiceSpec{
Ports: []api.ServicePort{
{Protocol: "UDP", Port: 53},
{Protocol: "TCP", Port: 53},
},
Selector: map[string]string{
"s": "magic",
},
ClusterIP: "10.1.1.1",
},
Status: api.ServiceStatus{},
},
{
ObjectMeta: api.ObjectMeta{
Name: "svc2",
Namespace: "ns2",
Labels: map[string]string{
"l1": "dolla-bill-yall",
},
},
Spec: api.ServiceSpec{
Ports: []api.ServicePort{
{Protocol: "TCP", Port: 80},
{Protocol: "TCP", Port: 8080},
},
Selector: map[string]string{
"s": "kazam",
},
ClusterIP: "10.1.1.2",
},
Status: api.ServiceStatus{},
}},
}
ld := util.NewLineDelimiter(os.Stdout, "|")
defer ld.Flush()
err := f.PrintObject(cmd, svc, ld)
if err != nil {
fmt.Printf("Unexpected error: %v", err)
}
// Output:
// |NAMESPACE NAME LABELS SELECTOR IP(S) PORT(S) L1|
// |ns1 svc1 l1=value s=magic 10.1.1.1 53/UDP value|
// | 53/TCP |
// |ns2 svc2 l1=dolla-bill-yall s=kazam 10.1.1.2 80/TCP dolla-bill-yall|
// | 8080/TCP |
// ||
}
func TestNormalizationFuncGlobalExistance(t *testing.T) {
// This test can be safely deleted when we will not support multiple flag formats
root := NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr)

View File

@@ -475,11 +475,18 @@ func printPodTemplate(pod *api.PodTemplate, w io.Writer, withNamespace bool, wid
}
// Lay out all the other containers on separate lines.
extraLinePrefix := "\t"
if withNamespace {
extraLinePrefix = "\t\t"
}
for _, container := range containers {
_, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", "", container.Name, container.Image, "")
_, err := fmt.Fprintf(w, "%s%s\t%s\t%s", extraLinePrefix, container.Name, container.Image, "")
if err != nil {
return err
}
if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil {
return err
}
}
return nil
}
@@ -522,11 +529,18 @@ func printReplicationController(controller *api.ReplicationController, w io.Writ
}
// Lay out all the other containers on separate lines.
extraLinePrefix := "\t"
if withNamespace {
extraLinePrefix = "\t\t"
}
for _, container := range containers {
_, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", "", container.Name, container.Image, "", "")
_, err := fmt.Fprintf(w, "%s%s\t%s\t%s\t%s", extraLinePrefix, container.Name, container.Image, "", "")
if err != nil {
return err
}
if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil {
return err
}
}
return nil
}
@@ -566,6 +580,10 @@ func printService(svc *api.Service, w io.Writer, withNamespace bool, wide bool,
return err
}
extraLinePrefix := "\t\t\t"
if withNamespace {
extraLinePrefix = "\t\t\t\t"
}
count := len(svc.Spec.Ports)
if len(ips) > count {
count = len(ips)
@@ -580,7 +598,10 @@ func printService(svc *api.Service, w io.Writer, withNamespace bool, wide bool,
port = fmt.Sprintf("%d/%s", svc.Spec.Ports[i].Port, svc.Spec.Ports[i].Protocol)
}
// Lay out additional ports.
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", "", "", "", ip, port); err != nil {
if _, err := fmt.Fprintf(w, "%s%s\t%s", extraLinePrefix, ip, port); err != nil {
return err
}
if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil {
return err
}
}
@@ -626,7 +647,7 @@ func printNamespace(item *api.Namespace, w io.Writer, withNamespace bool, wide b
if withNamespace {
return fmt.Errorf("namespace is not namespaced")
}
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", item.Name, formatLabels(item.Labels), item.Status.Phase); err != nil {
if _, err := fmt.Fprintf(w, "%s\t%s\t%s", item.Name, formatLabels(item.Labels), item.Status.Phase); err != nil {
return err
}
_, err := fmt.Fprint(w, appendLabels(item.Labels, columnLabels))
@@ -945,6 +966,19 @@ func appendLabels(itemLabels map[string]string, columnLabels []string) string {
return buffer.String()
}
// Append a set of tabs for each label column. We need this in the case where
// we have extra lines so that the tabwriter will still line things up.
func appendLabelTabs(columnLabels []string) string {
var buffer bytes.Buffer
for range columnLabels {
buffer.WriteString("\t")
}
buffer.WriteString("\n")
return buffer.String()
}
func formatLabelHeaders(columnLabels []string) []string {
formHead := make([]string, len(columnLabels))
for i, l := range columnLabels {