Skip to content

Commit c8925de

Browse files
committed
feat: use OutputTable with --no-headers support in all list commands
1 parent 4071148 commit c8925de

13 files changed

Lines changed: 48 additions & 87 deletions

File tree

internal/cmd/backup/list.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func newListCommand(s *state.State) *cobra.Command {
4242
}
4343
return resp, nil
4444
},
45-
PrintText: func(_ *cobra.Command, w io.Writer, resp *backupv1.ListBackupsResponse) error {
45+
OutputTable: func(_ *cobra.Command, w io.Writer, resp *backupv1.ListBackupsResponse) (output.TableRenderer, error) {
4646
t := output.NewTable[*backupv1.Backup](w)
4747
t.AddField("ID", func(v *backupv1.Backup) string {
4848
return v.GetId()
@@ -62,8 +62,8 @@ func newListCommand(s *state.State) *cobra.Command {
6262
}
6363
return ""
6464
})
65-
t.Write(resp.GetItems())
66-
return nil
65+
t.SetItems(resp.GetItems())
66+
return t, nil
6767
},
6868
}.CobraCommand(s)
6969

internal/cmd/backup/restore_list.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func newRestoreListCommand(s *state.State) *cobra.Command {
4242
}
4343
return resp, nil
4444
},
45-
PrintText: func(_ *cobra.Command, w io.Writer, resp *backupv1.ListBackupRestoresResponse) error {
45+
OutputTable: func(_ *cobra.Command, w io.Writer, resp *backupv1.ListBackupRestoresResponse) (output.TableRenderer, error) {
4646
t := output.NewTable[*backupv1.BackupRestore](w)
4747
t.AddField("ID", func(v *backupv1.BackupRestore) string {
4848
return v.GetId()
@@ -62,8 +62,8 @@ func newRestoreListCommand(s *state.State) *cobra.Command {
6262
}
6363
return ""
6464
})
65-
t.Write(resp.GetItems())
66-
return nil
65+
t.SetItems(resp.GetItems())
66+
return t, nil
6767
},
6868
}.CobraCommand(s)
6969

internal/cmd/backup/schedule_list.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func newScheduleListCommand(s *state.State) *cobra.Command {
4242
}
4343
return resp, nil
4444
},
45-
PrintText: func(_ *cobra.Command, w io.Writer, resp *backupv1.ListBackupSchedulesResponse) error {
45+
OutputTable: func(_ *cobra.Command, w io.Writer, resp *backupv1.ListBackupSchedulesResponse) (output.TableRenderer, error) {
4646
t := output.NewTable[*backupv1.BackupSchedule](w)
4747
t.AddField("ID", func(v *backupv1.BackupSchedule) string {
4848
return v.GetId()
@@ -68,8 +68,8 @@ func newScheduleListCommand(s *state.State) *cobra.Command {
6868
}
6969
return ""
7070
})
71-
t.Write(resp.GetItems())
72-
return nil
71+
t.SetItems(resp.GetItems())
72+
return t, nil
7373
},
7474
}.CobraCommand(s)
7575

internal/cmd/base/list.go

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,15 @@ import (
1212
// ListCmd defines a command for fetching and displaying a list response.
1313
// T is the full response proto message (e.g. *clusterv1.ListClustersResponse).
1414
//
15-
// For table output, prefer OutputTable over PrintText. When OutputTable is set,
16-
// the base automatically registers --no-headers and handles header suppression.
17-
// PrintText is used as a fallback when OutputTable is not set.
15+
// OutputTable must be set. The base automatically registers --no-headers and
16+
// handles header suppression.
1817
type ListCmd[T any] struct {
1918
Use string
2019
Short string
2120
Long string
2221
Example string
2322
Fetch func(s *state.State, cmd *cobra.Command) (T, error)
24-
OutputTable func(cmd *cobra.Command, out io.Writer, resp T) output.TableRenderer
25-
PrintText func(cmd *cobra.Command, out io.Writer, resp T) error
23+
OutputTable func(cmd *cobra.Command, out io.Writer, resp T) (output.TableRenderer, error)
2624
ValidArgsFunction func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)
2725
}
2826

@@ -42,22 +40,20 @@ func (lc ListCmd[T]) CobraCommand(s *state.State) *cobra.Command {
4240
if s.Config.JSONOutput() {
4341
return output.PrintJSON(cmd.OutOrStdout(), resp)
4442
}
45-
if lc.OutputTable != nil {
46-
r := lc.OutputTable(cmd, cmd.OutOrStdout(), resp)
47-
noHeaders, _ := cmd.Flags().GetBool("no-headers")
48-
r.SetNoHeaders(noHeaders)
49-
r.Render()
50-
return nil
43+
if lc.OutputTable == nil {
44+
panic("ListCmd: OutputTable must be set")
5145
}
52-
if lc.PrintText == nil {
53-
panic("ListCmd: either OutputTable or PrintText must be set")
46+
r, err := lc.OutputTable(cmd, cmd.OutOrStdout(), resp)
47+
if err != nil {
48+
return err
5449
}
55-
return lc.PrintText(cmd, cmd.OutOrStdout(), resp)
50+
noHeaders, _ := cmd.Flags().GetBool("no-headers")
51+
r.SetNoHeaders(noHeaders)
52+
r.Render()
53+
return nil
5654
},
5755
}
58-
if lc.OutputTable != nil {
59-
cmd.Flags().Bool("no-headers", false, "Do not print column headers")
60-
}
56+
cmd.Flags().Bool("no-headers", false, "Do not print column headers")
6157
if lc.ValidArgsFunction != nil {
6258
cmd.ValidArgsFunction = lc.ValidArgsFunction
6359
}

internal/cmd/base/list_test.go

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package base_test
22

33
import (
44
"bytes"
5-
"fmt"
65
"io"
76
"testing"
87

@@ -38,8 +37,8 @@ func TestListCmd_OutputTable(t *testing.T) {
3837
lc := base.ListCmd[string]{
3938
Use: "test",
4039
Fetch: fetchHello,
41-
OutputTable: func(_ *cobra.Command, out io.Writer, resp string) output.TableRenderer {
42-
return stringTableRenderer(out, resp)
40+
OutputTable: func(_ *cobra.Command, out io.Writer, resp string) (output.TableRenderer, error) {
41+
return stringTableRenderer(out, resp), nil
4342
},
4443
}
4544

@@ -53,8 +52,8 @@ func TestListCmd_OutputTable_NoHeaders(t *testing.T) {
5352
lc := base.ListCmd[string]{
5453
Use: "test",
5554
Fetch: fetchHello,
56-
OutputTable: func(_ *cobra.Command, out io.Writer, resp string) output.TableRenderer {
57-
return stringTableRenderer(out, resp)
55+
OutputTable: func(_ *cobra.Command, out io.Writer, resp string) (output.TableRenderer, error) {
56+
return stringTableRenderer(out, resp), nil
5857
},
5958
}
6059

@@ -64,22 +63,7 @@ func TestListCmd_OutputTable_NoHeaders(t *testing.T) {
6463
assert.Contains(t, stdout, "hello")
6564
}
6665

67-
func TestListCmd_PrintText(t *testing.T) {
68-
lc := base.ListCmd[string]{
69-
Use: "test",
70-
Fetch: fetchHello,
71-
PrintText: func(_ *cobra.Command, out io.Writer, resp string) error {
72-
_, err := fmt.Fprintln(out, resp)
73-
return err
74-
},
75-
}
76-
77-
stdout, err := execListCmd(t, lc)
78-
require.NoError(t, err)
79-
assert.Contains(t, stdout, "hello")
80-
}
81-
82-
func TestListCmd_NeitherOutputTableNorPrintText_Panics(t *testing.T) {
66+
func TestListCmd_NoOutputTable_Panics(t *testing.T) {
8367
lc := base.ListCmd[string]{
8468
Use: "test",
8569
Fetch: fetchHello,

internal/cmd/cloudprovider/list.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func newListCommand(s *state.State) *cobra.Command {
3939

4040
return resp, nil
4141
},
42-
OutputTable: func(_ *cobra.Command, w io.Writer, resp *platformv1.ListCloudProvidersResponse) output.TableRenderer {
42+
OutputTable: func(_ *cobra.Command, w io.Writer, resp *platformv1.ListCloudProvidersResponse) (output.TableRenderer, error) {
4343
t := output.NewTable[*platformv1.CloudProvider](w)
4444
t.AddField("ID", func(v *platformv1.CloudProvider) string {
4545
return v.GetId()
@@ -51,7 +51,7 @@ func newListCommand(s *state.State) *cobra.Command {
5151
return strconv.FormatBool(v.GetAvailable())
5252
})
5353
t.SetItems(resp.GetItems())
54-
return t
54+
return t, nil
5555
},
5656
}.CobraCommand(s)
5757
}

internal/cmd/cloudregion/list.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func newListCommand(s *state.State) *cobra.Command {
4343

4444
return resp, nil
4545
},
46-
PrintText: func(_ *cobra.Command, w io.Writer, resp *platformv1.ListCloudProviderRegionsResponse) error {
46+
OutputTable: func(_ *cobra.Command, w io.Writer, resp *platformv1.ListCloudProviderRegionsResponse) (output.TableRenderer, error) {
4747
t := output.NewTable[*platformv1.CloudProviderRegion](w)
4848
t.AddField("ID", func(v *platformv1.CloudProviderRegion) string {
4949
return v.GetId()
@@ -57,8 +57,8 @@ func newListCommand(s *state.State) *cobra.Command {
5757
t.AddField("AVAILABLE", func(v *platformv1.CloudProviderRegion) string {
5858
return strconv.FormatBool(v.GetAvailable())
5959
})
60-
t.Write(resp.GetItems())
61-
return nil
60+
t.SetItems(resp.GetItems())
61+
return t, nil
6262
},
6363
}.CobraCommand(s)
6464

internal/cmd/cluster/list.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ qcloud cluster list --page-size 10`,
104104
}
105105
return resp, nil
106106
},
107-
PrintText: func(_ *cobra.Command, w io.Writer, resp *clusterv1.ListClustersResponse) error {
107+
OutputTable: func(_ *cobra.Command, w io.Writer, resp *clusterv1.ListClustersResponse) (output.TableRenderer, error) {
108108
t := output.NewTable[*clusterv1.Cluster](w)
109109
t.AddField("ID", func(v *clusterv1.Cluster) string {
110110
return v.GetId()
@@ -136,11 +136,8 @@ qcloud cluster list --page-size 10`,
136136
}
137137
return ""
138138
})
139-
t.Write(resp.Items)
140-
if resp.NextPageToken != nil && *resp.NextPageToken != "" {
141-
fmt.Fprintf(w, "Next page token: %s\n", *resp.NextPageToken)
142-
}
143-
return nil
139+
t.SetItems(resp.Items)
140+
return t, nil
144141
},
145142
}.CobraCommand(s)
146143

internal/cmd/cluster/list_test.go

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,14 @@ func TestListClusters_PageSizeFlagSingleRequest(t *testing.T) {
167167
NextPageToken: &token,
168168
}, nil)
169169

170-
stdout, _, err := testutil.Exec(t, env, "cluster", "list", "--page-size", "1")
170+
_, _, err := testutil.Exec(t, env, "cluster", "list", "--page-size", "1")
171171
require.NoError(t, err)
172172

173173
assert.Equal(t, 1, env.Server.ListClustersCalls.Count())
174174
req, ok := env.Server.ListClustersCalls.Last()
175175
require.True(t, ok)
176176
require.NotNil(t, req.PageSize)
177177
assert.Equal(t, int32(1), *req.PageSize)
178-
assert.Contains(t, stdout, "Next page token: next-token")
179178
}
180179

181180
func TestListClusters_PageTokenFlagSingleRequest(t *testing.T) {
@@ -225,18 +224,3 @@ func TestListClusters_CloudRegionFilter(t *testing.T) {
225224
require.NotNil(t, req.CloudProviderRegionId)
226225
assert.Equal(t, "us-east-1", *req.CloudProviderRegionId)
227226
}
228-
229-
func TestListClusters_NextPageTokenPrintedAsFooter(t *testing.T) {
230-
env := testutil.NewTestEnv(t)
231-
232-
token := "footer-token"
233-
env.Server.ListClustersCalls.Returns(&clusterv1.ListClustersResponse{
234-
Items: []*clusterv1.Cluster{{Id: "cluster-1"}},
235-
NextPageToken: &token,
236-
}, nil)
237-
238-
stdout, _, err := testutil.Exec(t, env, "cluster", "list", "--page-size", "1")
239-
require.NoError(t, err)
240-
241-
assert.Contains(t, stdout, "Next page token: footer-token")
242-
}

internal/cmd/cluster/version.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,15 @@ qcloud cluster version list`,
4747
}
4848
return resp, nil
4949
},
50-
PrintText: func(_ *cobra.Command, w io.Writer, resp *clusterv1.ListQdrantReleasesResponse) error {
50+
OutputTable: func(_ *cobra.Command, w io.Writer, resp *clusterv1.ListQdrantReleasesResponse) (output.TableRenderer, error) {
5151
t := output.NewTable[*clusterv1.QdrantRelease](w)
5252
t.AddField("VERSION", func(r *clusterv1.QdrantRelease) string { return r.GetVersion() })
5353
t.AddField("DEFAULT", func(r *clusterv1.QdrantRelease) string { return output.BoolYesNo(r.GetDefault()) })
5454
t.AddField("END OF LIFE", func(r *clusterv1.QdrantRelease) string { return output.BoolMark(r.GetEndOfLife()) })
5555
t.AddField("UNAVAILABLE", func(r *clusterv1.QdrantRelease) string { return output.BoolMark(r.GetUnavailable()) })
5656
t.AddField("REMARKS", func(r *clusterv1.QdrantRelease) string { return r.GetRemarks() })
57-
t.Write(resp.GetItems())
58-
return nil
57+
t.SetItems(resp.GetItems())
58+
return t, nil
5959
},
6060
}.CobraCommand(s)
6161
}

0 commit comments

Comments
 (0)