1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
From: Maciej Szulik <maszulik@redhat.com>
Date: Tue, 6 Jul 2021 14:04:46 +0200
Subject: Hide long and multiline strings when printing
Description: Currently both long strings and multiline strings can potentially
"break" printing. I'm adding extra formatting to ensure we cut strings either
at newline or at 100 chars with information that more information is available.
Origin: upstream, https://github.com/kubernetes/kubernetes/pull/103514
---
.../cli-runtime/pkg/printers/tableprinter.go | 25 +++++++-
.../cli-runtime/pkg/printers/tableprinter_test.go | 67 ++++++++++++++++++++++
2 files changed, 91 insertions(+), 1 deletion(-)
diff --git a/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go b/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go
index 56bd05a..58ae790 100644
--- a/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go
+++ b/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go
@@ -32,6 +32,8 @@ import (
"k8s.io/apimachinery/pkg/watch"
)
+const maxStringLength = 100
+
var _ ResourcePrinter = &HumanReadablePrinter{}
type printHandler struct {
@@ -209,7 +211,28 @@ func printTable(table *metav1.Table, output io.Writer, options PrintOptions) err
fmt.Fprint(output, "\t")
}
if cell != nil {
- fmt.Fprint(output, cell)
+ switch val := cell.(type) {
+ case string:
+ print := val
+ more := 0
+ // cut to maxStringLength
+ if len(val) > maxStringLength {
+ more = len(print) - maxStringLength
+ print = print[:maxStringLength]
+ }
+ // and also check for newlines
+ newline := strings.Index(print, "\n")
+ if newline >= 0 {
+ more = more + len(print) - newline
+ print = print[:newline]
+ }
+ fmt.Fprint(output, print)
+ if more > 0 {
+ fmt.Fprintf(output, " + %d more...", more)
+ }
+ default:
+ fmt.Fprint(output, val)
+ }
}
}
fmt.Fprintln(output)
diff --git a/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter_test.go b/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter_test.go
index 2bdd626..770067c 100644
--- a/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter_test.go
+++ b/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter_test.go
@@ -722,3 +722,70 @@ func TestUnknownTypePrinting(t *testing.T) {
t.Errorf("An error was expected from printing unknown type")
}
}
+
+func TestStringPrinting(t *testing.T) {
+ tests := []struct {
+ columns []metav1.TableColumnDefinition
+ rows []metav1.TableRow
+ expected string
+ }{
+ // multiline string
+ {
+ columns: []metav1.TableColumnDefinition{
+ {Name: "Name", Type: "string"},
+ {Name: "Age", Type: "string"},
+ {Name: "Description", Type: "string"},
+ },
+ rows: []metav1.TableRow{
+ {Cells: []interface{}{"test1", "20h", "This is first line\nThis is second line\nThis is third line\nand another one\n"}},
+ },
+ expected: `NAME AGE DESCRIPTION
+test1 20h This is first line + 56 more...
+`,
+ },
+ // lengthy string
+ {
+ columns: []metav1.TableColumnDefinition{
+ {Name: "Name", Type: "string"},
+ {Name: "Age", Type: "string"},
+ {Name: "Description", Type: "string"},
+ },
+ rows: []metav1.TableRow{
+ {Cells: []interface{}{"test1", "20h", "This is first line which is long and goes for on and on and on an on and on and on and on and on and on and on and on and on and on and on"}},
+ },
+ expected: `NAME AGE DESCRIPTION
+test1 20h This is first line which is long and goes for on and on and on an on and on and on and on and on and + 38 more...
+`,
+ },
+ // lengthy string + newline
+ {
+ columns: []metav1.TableColumnDefinition{
+ {Name: "Name", Type: "string"},
+ {Name: "Age", Type: "string"},
+ {Name: "Description", Type: "string"},
+ },
+ rows: []metav1.TableRow{
+ {Cells: []interface{}{"test1", "20h", "This is first\n line which is long and goes for on and on and on an on and on and on and on and on and on and on and on and on and on and on"}},
+ },
+ expected: `NAME AGE DESCRIPTION
+test1 20h This is first + 126 more...
+`,
+ },
+ }
+
+ for _, test := range tests {
+ // Create the table from the columns and rows.
+ table := &metav1.Table{
+ ColumnDefinitions: test.columns,
+ Rows: test.rows,
+ }
+ // Print the table
+ out := bytes.NewBuffer([]byte{})
+ printer := NewTablePrinter(PrintOptions{})
+ printer.PrintObj(table, out)
+
+ if test.expected != out.String() {
+ t.Errorf("Table printing error: expected \n(%s), got \n(%s)", test.expected, out.String())
+ }
+ }
+}
|