mirror of
https://github.com/juanfont/headscale.git
synced 2026-02-21 12:10:30 +09:00
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:
@@ -48,44 +48,33 @@ 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(), "")
|
||||
}
|
||||
|
||||
tableData := pterm.TableData{
|
||||
{"ID", "Prefix", "Expiration", "Created"},
|
||||
}
|
||||
|
||||
for _, key := range response.GetApiKeys() {
|
||||
expiration := "-"
|
||||
|
||||
if key.GetExpiration() != nil {
|
||||
expiration = ColourTime(key.GetExpiration().AsTime())
|
||||
return printListOutput(cmd, response.GetApiKeys(), func() error {
|
||||
tableData := pterm.TableData{
|
||||
{"ID", "Prefix", "Expiration", "Created"},
|
||||
}
|
||||
|
||||
tableData = append(tableData, []string{
|
||||
strconv.FormatUint(key.GetId(), util.Base10),
|
||||
key.GetPrefix(),
|
||||
expiration,
|
||||
key.GetCreatedAt().AsTime().Format(HeadscaleDateTimeFormat),
|
||||
})
|
||||
}
|
||||
for _, key := range response.GetApiKeys() {
|
||||
expiration := "-"
|
||||
|
||||
err = pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
|
||||
if err != nil {
|
||||
return fmt.Errorf("rendering table: %w", err)
|
||||
}
|
||||
if key.GetExpiration() != nil {
|
||||
expiration = ColourTime(key.GetExpiration().AsTime())
|
||||
}
|
||||
|
||||
return nil
|
||||
tableData = append(tableData, []string{
|
||||
strconv.FormatUint(key.GetId(), util.Base10),
|
||||
key.GetPrefix(),
|
||||
expiration,
|
||||
key.GetCreatedAt().AsTime().Format(HeadscaleDateTimeFormat),
|
||||
})
|
||||
}
|
||||
|
||||
return pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
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()
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
|
||||
@@ -48,63 +48,54 @@ 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(), "")
|
||||
}
|
||||
|
||||
tableData := pterm.TableData{
|
||||
{
|
||||
"ID",
|
||||
"Key/Prefix",
|
||||
"Reusable",
|
||||
"Ephemeral",
|
||||
"Used",
|
||||
"Expiration",
|
||||
"Created",
|
||||
"Owner",
|
||||
},
|
||||
}
|
||||
|
||||
for _, key := range response.GetPreAuthKeys() {
|
||||
expiration := "-"
|
||||
if key.GetExpiration() != nil {
|
||||
expiration = ColourTime(key.GetExpiration().AsTime())
|
||||
return printListOutput(cmd, response.GetPreAuthKeys(), func() error {
|
||||
tableData := pterm.TableData{
|
||||
{
|
||||
"ID",
|
||||
"Key/Prefix",
|
||||
"Reusable",
|
||||
"Ephemeral",
|
||||
"Used",
|
||||
"Expiration",
|
||||
"Created",
|
||||
"Owner",
|
||||
},
|
||||
}
|
||||
|
||||
var owner string
|
||||
if len(key.GetAclTags()) > 0 {
|
||||
owner = strings.Join(key.GetAclTags(), "\n")
|
||||
} else if key.GetUser() != nil {
|
||||
owner = key.GetUser().GetName()
|
||||
} else {
|
||||
owner = "-"
|
||||
for _, key := range response.GetPreAuthKeys() {
|
||||
expiration := "-"
|
||||
if key.GetExpiration() != nil {
|
||||
expiration = ColourTime(key.GetExpiration().AsTime())
|
||||
}
|
||||
|
||||
var owner string
|
||||
if len(key.GetAclTags()) > 0 {
|
||||
owner = strings.Join(key.GetAclTags(), "\n")
|
||||
} else if key.GetUser() != nil {
|
||||
owner = key.GetUser().GetName()
|
||||
} else {
|
||||
owner = "-"
|
||||
}
|
||||
|
||||
tableData = append(tableData, []string{
|
||||
strconv.FormatUint(key.GetId(), 10),
|
||||
key.GetKey(),
|
||||
strconv.FormatBool(key.GetReusable()),
|
||||
strconv.FormatBool(key.GetEphemeral()),
|
||||
strconv.FormatBool(key.GetUsed()),
|
||||
expiration,
|
||||
key.GetCreatedAt().AsTime().Format("2006-01-02 15:04:05"),
|
||||
owner,
|
||||
})
|
||||
}
|
||||
|
||||
tableData = append(tableData, []string{
|
||||
strconv.FormatUint(key.GetId(), 10),
|
||||
key.GetKey(),
|
||||
strconv.FormatBool(key.GetReusable()),
|
||||
strconv.FormatBool(key.GetEphemeral()),
|
||||
strconv.FormatBool(key.GetUsed()),
|
||||
expiration,
|
||||
key.GetCreatedAt().AsTime().Format("2006-01-02 15:04:05"),
|
||||
owner,
|
||||
})
|
||||
}
|
||||
|
||||
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()
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
|
||||
@@ -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,30 +192,23 @@ 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(
|
||||
tableData,
|
||||
[]string{
|
||||
strconv.FormatUint(user.GetId(), 10),
|
||||
user.GetDisplayName(),
|
||||
user.GetName(),
|
||||
user.GetEmail(),
|
||||
user.GetCreatedAt().AsTime().Format("2006-01-02 15:04:05"),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
tableData := pterm.TableData{{"ID", "Name", "Username", "Email", "Created"}}
|
||||
for _, user := range response.GetUsers() {
|
||||
tableData = append(
|
||||
tableData,
|
||||
[]string{
|
||||
strconv.FormatUint(user.GetId(), 10),
|
||||
user.GetDisplayName(),
|
||||
user.GetName(),
|
||||
user.GetEmail(),
|
||||
user.GetCreatedAt().AsTime().Format("2006-01-02 15:04:05"),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
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()
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user