8000 feat: add JSON output format to many CLI commands by deansheather · Pull Request #6082 · coder/coder · GitHub
[go: up one dir, main page]

Skip to content

feat: add JSON output format to many CLI commands #6082

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension
8000
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fixup! feat: add JSON output format to many CLI commands
  • Loading branch information
deansheather committed Feb 7, 2023
commit 1ad2a4cfa17be02022ac7a4144f883519bfd7294
84 changes: 32 additions & 52 deletions cli/cliui/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (s stringWrapper) String() string {
}

type tableTest1 struct {
Name string `table:"name"`
Name string `table:"name,default_sort"`
NotIncluded string // no table tag
Age int `table:"age"`
Roles []string `table:"roles"`
Expand All @@ -39,21 +39,45 @@ type tableTest1 struct {
}

type tableTest2 struct {
Name stringWrapper `table:"name"`
Name stringWrapper `table:"name,default_sort"`
Age int `table:"age"`
NotIncluded string `table:"-"`
}

type tableTest3 struct {
NotIncluded string // no table tag
Sub tableTest2 `table:"inner,recursive"`
Sub tableTest2 `table:"inner,recursive,default_sort"`
}

func Test_DisplayTable(t *testing.T) {
t.Parallel()

someTime := time.Date(2022, 8, 2, 15, 49, 10, 0, time.UTC)

// Not sorted by name or age to test sorting.
in := []tableTest1{
{
Name: "bar",
Age: 20,
Roles: []string{"a"},
Sub1: tableTest2{
Name: stringWrapper{str: "bar1"},
Age: 21,
},
Sub2: nil,
Sub3: tableTest3{
Sub: tableTest2{
Name: stringWrapper{str: "bar3"},
Age: 23,
},
},
Sub4: tableTest2{
Name: stringWrapper{str: "bar4"},
Age: 24,
},
Time: someTime,
TimePtr: nil,
},
{
Name: "foo",
Age: 10,
Expand All @@ -79,28 +103,6 @@ func Test_DisplayTable(t *testing.T) {
Time: someTime,
TimePtr: &someTime,
},
{
Name: "bar",
Age: 20,
Roles: []string{"a"},
Sub1: tableTest2{
Name: stringWrapper{str: "bar1"},
Age: 21,
},
Sub2: nil,
Sub3: tableTest3{
Sub: tableTest2{
Name: stringWrapper{str: "bar3"},
Age: 23,
},
},
Sub4: tableTest2{
Name: stringWrapper{str: "bar4"},
Age: 24,
},
Time: someTime,
TimePtr: nil,
},
{
Name: "baz",
Age: 30,
Expand Down Expand Up @@ -132,9 +134,9 @@ func Test_DisplayTable(t *testing.T) {

expected := `
NAME AGE ROLES SUB 1 NAME SUB 1 AGE SUB 2 NAME SUB 2 AGE SUB 3 INNER NAME SUB 3 INNER AGE SUB 4 TIME TIME PTR
foo 10 [a b c] foo1 11 foo2 12 foo3 13 {foo4 14 } 2022-08-02T15:49:10Z 2022-08-02T15:49:10Z
bar 20 [a] bar1 21 <nil> <nil> bar3 23 {bar4 24 } 2022-08-02T15:49:10Z <nil>
baz 30 [] baz1 31 <nil> <nil> baz3 33 {baz4 34 } 2022-08-02T15:49:10Z <nil>
foo 10 [a b c] foo1 11 foo2 12 foo3 13 {foo4 14 } 2022-08-02T15:49:10Z 2022-08-02T15:49:10Z
`

// Test with non-pointer values.
Expand All @@ -154,17 +156,17 @@ baz 30 [] baz1 31 <nil> <nil> baz3
compareTables(t, expected, out)
})

t.Run("Sort", func(t *testing.T) {
t.Run("CustomSort", func(t *testing.T) {
t.Parallel()

expected := `
NAME AGE ROLES SUB 1 NAME SUB 1 AGE SUB 2 NAME SUB 2 AGE SUB 3 INNER NAME SUB 3 INNER AGE SUB 4 TIME TIME PTR
foo 10 [a b c] foo1 11 foo2 12 foo3 13 {foo4 14 } 2022-08-02T15:49:10Z 2022-08-02T15:49:10Z
bar 20 [a] bar1 21 <nil> <nil> bar3 23 {bar4 24 } 2022-08-02T15:49:10Z <nil>
baz 30 [] baz1 31 <nil> <nil> baz3 33 {baz4 34 } 2022-08-02T15:49:10Z <nil>
foo 10 [a b c] foo1 11 foo2 12 foo3 13 {foo4 14 } 2022-08-02T15:49:10Z 2022-08-02T15:49:10Z
`

out, err := cliui.DisplayTable(in, "name", nil)
out, err := cliui.DisplayTable(in, "age", nil)
log.Println("rendered table:\n" + out)
require.NoError(t, err)
compareTables(t, expected, out)
Expand All @@ -175,9 +177,9 @@ foo 10 [a b c] foo1 11 foo2 12 foo3

expected := `
NAME SUB 1 NAME SUB 3 INNER NAME TIME
foo foo1 foo3 2022-08-02T15:49:10Z
bar bar1 bar3 2022-08-02T15:49:10Z
baz baz1 baz3 2022-08-02T15:49:10Z
foo foo1 foo3 2022-08-02T15:49:10Z
`

out, err := cliui.DisplayTable(in, "", []string{"name", "sub_1_name", "sub_3 inner name", "time"})
Expand Down Expand Up @@ -327,28 +329,6 @@ baz baz1 baz3 2022-08-02T15:49:10Z
})
}

func Test_TableHeaders(t *testing.T) {
t.Parallel()
s := []tableTest1{}
expectedFields := []string{
"name",
"age",
"roles",
"sub_1_name",
"sub_1_age",
"sub_2_name",
"sub_2_age",
"sub_3_inner_name",
"sub_3_inner_age",
"sub_4",
"time",
"time_ptr",
}
headers, err := cliui.TableHeaders(s)
require.NoError(t, err)
require.EqualValues(t, expectedFields, headers)
}

// compareTables normalizes the incoming table lines
func compareTables(t *testing.T, expected, out string) {
t.Helper()
Expand Down
4 changes: 3 additions & 1 deletion enterprise/cli/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ func featuresList() *cobra.Command {
return err
}

// This uses custom formatting as the JSON output outputs an object
// as opposed to a list from the table output.
out := ""
switch outputFormat {
case "table", "":
Expand Down Expand Up @@ -88,7 +90,7 @@ func featuresList() *cobra.Command {
}

type featureRow struct {
Name codersdk.FeatureName `table:"name"`
Name codersdk.FeatureName `table:"name,default_sort"`
Entitlement string `table:"entitlement"`
Enabled bool `table:"enabled"`
Limit *int64 `table:"limit"`
Expand Down
26 changes: 19 additions & 7 deletions enterprise/cli/grouplist.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ import (
)

func groupList() *cobra.Command {
formatter := cliui.NewOutputFormatter(
cliui.TableFormat([]groupTableRow{}, nil),
cliui.JSONFormat(),
)

cmd := &cobra.Command{
Use: "list",
Short: "List user groups",
Expand Down Expand Up @@ -44,7 +49,8 @@ func groupList() *cobra.Command {
return nil
}

out, err := displayGroups(groups...)
rows := groupsToRows(groups...)
out, err := formatter.Format(cmd.Context(), rows)
if err != nil {< 67E6 /span>
return xerrors.Errorf("display groups: %w", err)
}
Expand All @@ -53,17 +59,23 @@ func groupList() *cobra.Command {
return nil
},
}

formatter.AttachFlags(cmd)
return cmd
}

type groupTableRow struct {
Name string `table:"name"`
OrganizationID uuid.UUID `table:"organization_id"`
Members []string `table:"members"`
AvatarURL string `table:"avatar_url"`
// For json output:
Group codersdk.Group `table:"-"`

// For table output:
Name string `json:"-" table:"name,default_sort"`
OrganizationID uuid.UUID `json:"-" table:"organization_id"`
Members []string `json:"-" table:"members"`
AvatarURL string `json:"-" table:"avatar_url"`
}

func displayGroups(groups ...codersdk.Group) (string, error) {
func groupsToRows(groups ...codersdk.Group) []groupTableRow {
rows := make([]groupTableRow, 0, len(groups))
for _, group := range groups {
members := make([]string, 0, len(group.Members))
Expand All @@ -78,5 +90,5 @@ func displayGroups(groups ...codersdk.Group) (string, error) {
})
}

return cliui.DisplayTable(rows, "name", nil)
return rows
}
0