Skip to content

Commit f933c8e

Browse files
committed
add wrapper for tablewriter
Signed-off-by: Carlos Panato <ctadeu@gmail.com>
1 parent 6e370f8 commit f933c8e

11 files changed

+253
-0
lines changed

go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/maxbrunsfeld/counterfeiter/v6 v6.11.3
1010
github.com/moby/term v0.5.2
1111
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481
12+
github.com/olekukonko/tablewriter v1.0.8
1213
github.com/sirupsen/logrus v1.9.3
1314
github.com/spf13/cobra v1.9.1
1415
github.com/stretchr/testify v1.10.0
@@ -20,10 +21,17 @@ require (
2021
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
2122
github.com/Masterminds/semver/v3 v3.3.1 // indirect
2223
github.com/davecgh/go-spew v1.1.1 // indirect
24+
github.com/fatih/color v1.15.0 // indirect
2325
github.com/inconshreveable/mousetrap v1.1.0 // indirect
2426
github.com/kr/pretty v0.3.1 // indirect
2527
github.com/magefile/mage v1.15.0 // indirect
28+
github.com/mattn/go-colorable v0.1.13 // indirect
29+
github.com/mattn/go-isatty v0.0.19 // indirect
30+
github.com/mattn/go-runewidth v0.0.16 // indirect
31+
github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 // indirect
32+
github.com/olekukonko/ll v0.0.8 // indirect
2633
github.com/pmezard/go-difflib v1.0.0 // indirect
34+
github.com/rivo/uniseg v0.2.0 // indirect
2735
github.com/spf13/pflag v1.0.6 // indirect
2836
golang.org/x/mod v0.26.0 // indirect
2937
golang.org/x/sync v0.16.0 // indirect

go.sum

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr
1515
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1616
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1717
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
18+
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
19+
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
1820
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
1921
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
2022
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -25,17 +27,32 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
2527
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
2628
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
2729
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
30+
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
31+
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
32+
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
33+
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
34+
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
35+
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
36+
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
2837
github.com/maxbrunsfeld/counterfeiter/v6 v6.11.3 h1:Eaq36EIyJNp7b3qDhjV7jmDVq/yPeW2v4pTqzGbOGB4=
2938
github.com/maxbrunsfeld/counterfeiter/v6 v6.11.3/go.mod h1:6KKUoQBZBW6PDXJtNfqeEjPXMj/ITTk+cWK9t9uS5+E=
3039
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
3140
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
3241
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 h1:Up6+btDp321ZG5/zdSLo48H9Iaq0UQGthrhWC6pCxzE=
3342
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481/go.mod h1:yKZQO8QE2bHlgozqWDiRVqTFlLQSj30K/6SAK8EeYFw=
43+
github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 h1:r3FaAI0NZK3hSmtTDrBVREhKULp8oUeqLT5Eyl2mSPo=
44+
github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
45+
github.com/olekukonko/ll v0.0.8 h1:sbGZ1Fx4QxJXEqL/6IG8GEFnYojUSQ45dJVwN2FH2fc=
46+
github.com/olekukonko/ll v0.0.8/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
47+
github.com/olekukonko/tablewriter v1.0.8 h1:f6wJzHg4QUtJdvrVPKco4QTrAylgaU0+b9br/lJxEiQ=
48+
github.com/olekukonko/tablewriter v1.0.8/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs=
3449
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
3550
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
3651
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
3752
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
3853
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
54+
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
55+
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
3956
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
4057
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
4158
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -61,6 +78,8 @@ golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
6178
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
6279
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
6380
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
81+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
82+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
6483
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
6584
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
6685
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=

util/tablewriter.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package util
18+
19+
import (
20+
"io"
21+
22+
"github.com/olekukonko/tablewriter"
23+
)
24+
25+
// NewTableWriter creates a new table writer with the given output and options.
26+
func NewTableWriter(output io.Writer, options ...tablewriter.Option) *tablewriter.Table {
27+
table := tablewriter.NewWriter(output)
28+
for _, opt := range options {
29+
table.Options(opt)
30+
}
31+
32+
return table
33+
}

util/tablewriter_test.go

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package util
18+
19+
import (
20+
"bytes"
21+
"os"
22+
"path/filepath"
23+
"testing"
24+
25+
"github.com/olekukonko/tablewriter"
26+
"github.com/stretchr/testify/require"
27+
)
28+
29+
// compareGolden compares actual output with golden file.
30+
func compareGolden(t *testing.T, actual, goldenFile string) {
31+
t.Helper()
32+
33+
goldenPath := filepath.Join("testdata", goldenFile)
34+
expected, err := os.ReadFile(goldenPath)
35+
require.NoError(t, err, "Failed to read golden file: %s", goldenPath)
36+
37+
require.Equal(t, string(expected), actual, "Output doesn't match golden file: %s", goldenFile)
38+
}
39+
40+
func TestNewTableWriter(t *testing.T) {
41+
t.Parallel()
42+
43+
t.Run("NoOptions", func(t *testing.T) {
44+
t.Parallel()
45+
46+
var output bytes.Buffer
47+
table := NewTableWriter(&output)
48+
49+
require.NotNil(t, table)
50+
require.IsType(t, &tablewriter.Table{}, table)
51+
52+
table.Header("Name", "Age")
53+
_ = table.Append([]string{"John", "30"})
54+
_ = table.Render()
55+
56+
compareGolden(t, output.String(), "no_options.golden")
57+
})
58+
59+
t.Run("WithSingleOption", func(t *testing.T) {
60+
t.Parallel()
61+
62+
var output bytes.Buffer
63+
table := NewTableWriter(&output, tablewriter.WithMaxWidth(80))
64+
65+
require.NotNil(t, table)
66+
require.IsType(t, &tablewriter.Table{}, table)
67+
68+
table.Header("Name", "Age")
69+
_ = table.Append([]string{"John", "30"})
70+
_ = table.Render()
71+
72+
compareGolden(t, output.String(), "with_single_option.golden")
73+
})
74+
75+
t.Run("WithMultipleOptions", func(t *testing.T) {
76+
t.Parallel()
77+
78+
var output bytes.Buffer
79+
table := NewTableWriter(&output,
80+
tablewriter.WithHeader([]string{"Name", "Age"}),
81+
tablewriter.WithMaxWidth(80),
82+
)
83+
84+
require.NotNil(t, table)
85+
require.IsType(t, &tablewriter.Table{}, table)
86+
87+
_ = table.Append([]string{"John", "30"})
88+
_ = table.Render()
89+
90+
compareGolden(t, output.String(), "with_multiple_options.golden")
91+
})
92+
93+
t.Run("WithHeaderOption", func(t *testing.T) {
94+
t.Parallel()
95+
96+
var output bytes.Buffer
97+
table := NewTableWriter(&output, tablewriter.WithHeader([]string{"Name", "Age"}))
98+
99+
require.NotNil(t, table)
100+
require.IsType(t, &tablewriter.Table{}, table)
101+
102+
_ = table.Append([]string{"John", "30"})
103+
_ = table.Render()
104+
105+
compareGolden(t, output.String(), "with_header_option.golden")
106+
})
107+
108+
t.Run("WithFooterOption", func(t *testing.T) {
109+
t.Parallel()
110+
111+
var output bytes.Buffer
112+
table := NewTableWriter(&output, tablewriter.WithFooter([]string{"Total", "1"}))
113+
114+
require.NotNil(t, table)
115+
require.IsType(t, &tablewriter.Table{}, table)
116+
117+
table.Header("Name", "Age")
118+
_ = table.Append([]string{"John", "30"})
119+
_ = table.Render()
120+
121+
compareGolden(t, output.String(), "with_footer_option.golden")
122+
})
123+
124+
t.Run("EmptyTable", func(t *testing.T) {
125+
t.Parallel()
126+
127+
var output bytes.Buffer
128+
table := NewTableWriter(&output)
129+
130+
require.NotNil(t, table)
131+
require.IsType(t, &tablewriter.Table{}, table)
132+
133+
table.Header("Name", "Age")
134+
_ = table.Render()
135+
136+
compareGolden(t, output.String(), "empty_table.golden")
137+
})
138+
139+
t.Run("MultipleRows", func(t *testing.T) {
140+
t.Parallel()
141+
142+
var output bytes.Buffer
143+
table := NewTableWriter(&output)
144+
145+
require.NotNil(t, table)
146+
require.IsType(t, &tablewriter.Table{}, table)
147+
148+
table.Header("Name", "Age", "City")
149+
_ = table.Append([]string{"John", "30", "New York"})
150+
_ = table.Append([]string{"Jane", "25", "Boston"})
151+
_ = table.Append([]string{"Bob", "35", "Chicago"})
152+
_ = table.Render()
153+
154+
compareGolden(t, output.String(), "multiple_rows.golden")
155+
})
156+
}

util/testdata/empty_table.golden

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
┌──────┬─────┐
2+
│ NAME │ AGE │
3+
└──────┴─────┘

util/testdata/multiple_rows.golden

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
┌──────┬─────┬──────────┐
2+
│ NAME │ AGE │ CITY │
3+
├──────┼─────┼──────────┤
4+
│ John │ 30 │ New York │
5+
│ Jane │ 25 │ Boston │
6+
│ Bob │ 35 │ Chicago │
7+
└──────┴─────┴──────────┘

util/testdata/no_options.golden

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
┌──────┬─────┐
2+
│ NAME │ AGE │
3+
├──────┼─────┤
4+
│ John │ 30 │
5+
└──────┴─────┘
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
┌───────┬─────┐
2+
│ NAME │ AGE │
3+
├───────┼─────┤
4+
│ John │ 30 │
5+
├───────┼─────┤
6+
│ Total │ 1 │
7+
└───────┴─────┘
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
┌──────┬─────┐
2+
│ NAME │ AGE │
3+
├──────┼─────┤
4+
│ John │ 30 │
5+
└──────┴─────┘
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
┌──────┬─────┐
2+
│ NAME │ AGE │
3+
├──────┼─────┤
4+
│ John │ 30 │
5+
└──────┴─────┘

0 commit comments

Comments
 (0)