diff --git a/pkg/printers/customcolumn.go b/pkg/printers/customcolumn.go index bba5bc4ced5..3829a0e8d51 100644 --- a/pkg/printers/customcolumn.go +++ b/pkg/printers/customcolumn.go @@ -31,14 +31,6 @@ import ( "k8s.io/client-go/util/jsonpath" ) -const ( - columnwidth = 10 - tabwidth = 4 - padding = 3 - padding_character = ' ' - flags = 0 -) - var jsonRegexp = regexp.MustCompile("^\\{\\.?([^{}]+)\\}$|^\\.?([^{}]+)$") // RelaxedJSONPathExpression attempts to be flexible with JSONPath expressions, it accepts: @@ -163,7 +155,11 @@ func (s *CustomColumnsPrinter) AfterPrint(w io.Writer, res string) error { } func (s *CustomColumnsPrinter) PrintObj(obj runtime.Object, out io.Writer) error { - w := tabwriter.NewWriter(out, columnwidth, tabwidth, padding, padding_character, flags) + if w, found := out.(*tabwriter.Writer); !found { + w = GetNewTabWriter(out) + out = w + defer w.Flush() + } t := reflect.TypeOf(obj) if !s.NoHeaders && t != s.lastType { @@ -171,7 +167,7 @@ func (s *CustomColumnsPrinter) PrintObj(obj runtime.Object, out io.Writer) error for ix := range s.Columns { headers[ix] = s.Columns[ix].Header } - fmt.Fprintln(w, strings.Join(headers, "\t")) + fmt.Fprintln(out, strings.Join(headers, "\t")) s.lastType = t } parsers := make([]*jsonpath.JSONPath, len(s.Columns)) @@ -188,16 +184,16 @@ func (s *CustomColumnsPrinter) PrintObj(obj runtime.Object, out io.Writer) error return err } for ix := range objs { - if err := s.printOneObject(objs[ix], parsers, w); err != nil { + if err := s.printOneObject(objs[ix], parsers, out); err != nil { return err } } } else { - if err := s.printOneObject(obj, parsers, w); err != nil { + if err := s.printOneObject(obj, parsers, out); err != nil { return err } } - return w.Flush() + return nil } func (s *CustomColumnsPrinter) printOneObject(obj runtime.Object, parsers []*jsonpath.JSONPath, out io.Writer) error { diff --git a/pkg/printers/customcolumn_test.go b/pkg/printers/customcolumn_test.go index cb67a4ef701..463b0b21a35 100644 --- a/pkg/printers/customcolumn_test.go +++ b/pkg/printers/customcolumn_test.go @@ -323,3 +323,45 @@ foo baz } } } + +// this mimics how resource/get.go calls the customcolumn printer +func TestIndividualPrintObjOnExistingTabWriter(t *testing.T) { + columns := []printers.Column{ + { + Header: "NAME", + FieldSpec: "{.metadata.name}", + }, + { + Header: "LONG COLUMN NAME", // name is longer than all values of label1 + FieldSpec: "{.metadata.labels.label1}", + }, + { + Header: "LABEL 2", + FieldSpec: "{.metadata.labels.label2}", + }, + } + objects := []*v1.Pod{ + {ObjectMeta: metav1.ObjectMeta{Name: "foo", Labels: map[string]string{"label1": "foo", "label2": "foo"}}}, + {ObjectMeta: metav1.ObjectMeta{Name: "bar", Labels: map[string]string{"label1": "bar", "label2": "bar"}}}, + } + expectedOutput := `NAME LONG COLUMN NAME LABEL 2 +foo foo foo +bar bar bar +` + + buffer := &bytes.Buffer{} + tabWriter := printers.GetNewTabWriter(buffer) + printer := &printers.CustomColumnsPrinter{ + Columns: columns, + Decoder: legacyscheme.Codecs.UniversalDecoder(), + } + for _, obj := range objects { + if err := printer.PrintObj(obj, tabWriter); err != nil { + t.Errorf("unexpected error: %v", err) + } + } + tabWriter.Flush() + if buffer.String() != expectedOutput { + t.Errorf("\nexpected:\n'%s'\nsaw\n'%s'\n", expectedOutput, buffer.String()) + } +}