cmd/headscale/cli: add printListOutput to centralise table-vs-JSON branching

Add a helper that checks the --output flag and either serialises as
JSON/YAML or invokes a table-rendering callback. This removes the
repeated format,_ := cmd.Flags().GetString("output") + if-branch from
the five list commands.
This commit is contained in:
Kristoffer Dalby
2026-02-18 14:30:07 +00:00
parent 8891ec9835
commit d6c39e65a5
5 changed files with 102 additions and 139 deletions

View File

@@ -48,19 +48,12 @@ var listAPIKeys = &cobra.Command{
Short: "List the Api keys for headscale",
Aliases: []string{"ls", "show"},
RunE: grpcRunE(func(ctx context.Context, client v1.HeadscaleServiceClient, cmd *cobra.Command, args []string) error {
format, _ := cmd.Flags().GetString("output")
request := &v1.ListApiKeysRequest{}
response, err := client.ListApiKeys(ctx, request)
response, err := client.ListApiKeys(ctx, &v1.ListApiKeysRequest{})
if err != nil {
return fmt.Errorf("listing api keys: %w", err)
}
if format != "" {
return printOutput(cmd, response.GetApiKeys(), "")
}
return printListOutput(cmd, response.GetApiKeys(), func() error {
tableData := pterm.TableData{
{"ID", "Prefix", "Expiration", "Created"},
}
@@ -80,12 +73,8 @@ var listAPIKeys = &cobra.Command{
})
}
err = pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
if err != nil {
return fmt.Errorf("rendering table: %w", err)
}
return nil
return pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
})
}),
}

View File

@@ -136,36 +136,24 @@ var listNodesCmd = &cobra.Command{
Short: "List nodes",
Aliases: []string{"ls", "show"},
RunE: grpcRunE(func(ctx context.Context, client v1.HeadscaleServiceClient, cmd *cobra.Command, args []string) error {
format, _ := cmd.Flags().GetString("output")
user, err := cmd.Flags().GetString("user")
if err != nil {
return fmt.Errorf("getting user flag: %w", err)
}
request := &v1.ListNodesRequest{
User: user,
}
response, err := client.ListNodes(ctx, request)
response, err := client.ListNodes(ctx, &v1.ListNodesRequest{User: user})
if err != nil {
return fmt.Errorf("listing nodes: %w", err)
}
if format != "" {
return printOutput(cmd, response.GetNodes(), "")
}
return printListOutput(cmd, response.GetNodes(), func() error {
tableData, err := nodesToPtables(user, response.GetNodes())
if err != nil {
return fmt.Errorf("converting to table: %w", err)
}
err = pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
if err != nil {
return fmt.Errorf("rendering table: %w", err)
}
return nil
return pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
})
}),
}
@@ -174,15 +162,12 @@ var listNodeRoutesCmd = &cobra.Command{
Short: "List routes available on nodes",
Aliases: []string{"lsr", "routes"},
RunE: grpcRunE(func(ctx context.Context, client v1.HeadscaleServiceClient, cmd *cobra.Command, args []string) error {
format, _ := cmd.Flags().GetString("output")
identifier, err := cmd.Flags().GetUint64("identifier")
if err != nil {
return fmt.Errorf("getting identifier flag: %w", err)
}
request := &v1.ListNodesRequest{}
response, err := client.ListNodes(ctx, request)
response, err := client.ListNodes(ctx, &v1.ListNodesRequest{})
if err != nil {
return fmt.Errorf("listing nodes: %w", err)
}
@@ -202,18 +187,9 @@ var listNodeRoutesCmd = &cobra.Command{
return (n.GetSubnetRoutes() != nil && len(n.GetSubnetRoutes()) > 0) || (n.GetApprovedRoutes() != nil && len(n.GetApprovedRoutes()) > 0) || (n.GetAvailableRoutes() != nil && len(n.GetAvailableRoutes()) > 0)
})
if format != "" {
return printOutput(cmd, nodes, "")
}
tableData := nodeRoutesToPtables(nodes)
err = pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
if err != nil {
return fmt.Errorf("rendering table: %w", err)
}
return nil
return printListOutput(cmd, nodes, func() error {
return pterm.DefaultTable.WithHasHeader().WithData(nodeRoutesToPtables(nodes)).Render()
})
}),
}

View File

@@ -48,17 +48,12 @@ var listPreAuthKeys = &cobra.Command{
Short: "List all preauthkeys",
Aliases: []string{"ls", "show"},
RunE: grpcRunE(func(ctx context.Context, client v1.HeadscaleServiceClient, cmd *cobra.Command, args []string) error {
format, _ := cmd.Flags().GetString("output")
response, err := client.ListPreAuthKeys(ctx, &v1.ListPreAuthKeysRequest{})
if err != nil {
return fmt.Errorf("listing preauthkeys: %w", err)
}
if format != "" {
return printOutput(cmd, response.GetPreAuthKeys(), "")
}
return printListOutput(cmd, response.GetPreAuthKeys(), func() error {
tableData := pterm.TableData{
{
"ID",
@@ -99,12 +94,8 @@ var listPreAuthKeys = &cobra.Command{
})
}
err = pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
if err != nil {
return fmt.Errorf("rendering table: %w", err)
}
return nil
return pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
})
}),
}

View File

@@ -171,8 +171,6 @@ var listUsersCmd = &cobra.Command{
Short: "List all the users",
Aliases: []string{"ls", "show"},
RunE: grpcRunE(func(ctx context.Context, client v1.HeadscaleServiceClient, cmd *cobra.Command, args []string) error {
format, _ := cmd.Flags().GetString("output")
request := &v1.ListUsersRequest{}
id, _ := cmd.Flags().GetInt64("identifier")
@@ -194,10 +192,7 @@ var listUsersCmd = &cobra.Command{
return fmt.Errorf("listing users: %w", err)
}
if format != "" {
return printOutput(cmd, response.GetUsers(), "")
}
return printListOutput(cmd, response.GetUsers(), func() error {
tableData := pterm.TableData{{"ID", "Name", "Username", "Email", "Created"}}
for _, user := range response.GetUsers() {
tableData = append(
@@ -212,12 +207,8 @@ var listUsersCmd = &cobra.Command{
)
}
err = pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
if err != nil {
return fmt.Errorf("rendering table: %w", err)
}
return nil
return pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
})
}),
}

View File

@@ -209,6 +209,22 @@ func printOutput(cmd *cobra.Command, result any, override string) error {
return nil
}
// printListOutput checks the --output flag: when a machine-readable format is
// requested it serialises data as JSON/YAML; otherwise it calls renderTable
// to produce the human-readable pterm table.
func printListOutput(
cmd *cobra.Command,
data any,
renderTable func() error,
) error {
format, _ := cmd.Flags().GetString("output")
if format != "" {
return printOutput(cmd, data, "")
}
return renderTable()
}
// printError writes err to stderr, formatting it as JSON/YAML when the
// --output flag requests machine-readable output. Used exclusively by
// Execute() so that every error surfaces in the format the caller asked for.