mirror of
https://github.com/juanfont/headscale.git
synced 2026-07-11 10:31:14 +09:00
cli: consolidate output and table rendering
This commit is contained in:
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -51,9 +50,7 @@ var listAPIKeys = &cobra.Command{
|
||||
}
|
||||
|
||||
return printListOutput(cmd, response.GetApiKeys(), func() error {
|
||||
tableData := make(pterm.TableData, 1, 1+len(response.GetApiKeys()))
|
||||
tableData[0] = []string{"ID", "Prefix", colExpiration, colCreated}
|
||||
|
||||
rows := make([][]string, 0, len(response.GetApiKeys()))
|
||||
for _, key := range response.GetApiKeys() {
|
||||
expiration := "-"
|
||||
|
||||
@@ -61,7 +58,7 @@ var listAPIKeys = &cobra.Command{
|
||||
expiration = ColourTime(key.GetExpiration().AsTime())
|
||||
}
|
||||
|
||||
tableData = append(tableData, []string{
|
||||
rows = append(rows, []string{
|
||||
strconv.FormatUint(key.GetId(), util.Base10),
|
||||
key.GetPrefix(),
|
||||
expiration,
|
||||
@@ -69,7 +66,7 @@ var listAPIKeys = &cobra.Command{
|
||||
})
|
||||
}
|
||||
|
||||
return pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
|
||||
return renderTable([]string{"ID", "Prefix", colExpiration, colCreated}, rows)
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -52,18 +51,7 @@ var listPreAuthKeys = &cobra.Command{
|
||||
}
|
||||
|
||||
return printListOutput(cmd, response.GetPreAuthKeys(), func() error {
|
||||
tableData := make(pterm.TableData, 1, 1+len(response.GetPreAuthKeys()))
|
||||
tableData[0] = []string{
|
||||
"ID",
|
||||
"Key/Prefix",
|
||||
"Reusable",
|
||||
"Ephemeral",
|
||||
"Used",
|
||||
colExpiration,
|
||||
colCreated,
|
||||
"Owner",
|
||||
}
|
||||
|
||||
rows := make([][]string, 0, len(response.GetPreAuthKeys()))
|
||||
for _, key := range response.GetPreAuthKeys() {
|
||||
expiration := "-"
|
||||
if key.GetExpiration() != nil {
|
||||
@@ -79,7 +67,7 @@ var listPreAuthKeys = &cobra.Command{
|
||||
owner = "-"
|
||||
}
|
||||
|
||||
tableData = append(tableData, []string{
|
||||
rows = append(rows, []string{
|
||||
strconv.FormatUint(key.GetId(), util.Base10),
|
||||
key.GetKey(),
|
||||
strconv.FormatBool(key.GetReusable()),
|
||||
@@ -91,7 +79,16 @@ var listPreAuthKeys = &cobra.Command{
|
||||
})
|
||||
}
|
||||
|
||||
return pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
|
||||
return renderTable([]string{
|
||||
"ID",
|
||||
"Key/Prefix",
|
||||
"Reusable",
|
||||
"Ephemeral",
|
||||
"Used",
|
||||
colExpiration,
|
||||
colCreated,
|
||||
"Owner",
|
||||
}, rows)
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -120,13 +120,7 @@ func filterPreReleasesIfStable(versionFunc func() string) func(string) bool {
|
||||
}
|
||||
|
||||
// If we are on a stable release, filter out pre-releases.
|
||||
for _, ignore := range prereleases {
|
||||
if strings.Contains(tag, ignore) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return isPreReleaseVersion(tag)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/juanfont/headscale/hscontrol/util/zlog/zf"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -194,12 +193,10 @@ var listUsersCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
return printListOutput(cmd, response.GetUsers(), func() error {
|
||||
tableData := make(pterm.TableData, 1, 1+len(response.GetUsers()))
|
||||
|
||||
tableData[0] = []string{"ID", "Name", "Username", "Email", colCreated}
|
||||
rows := make([][]string, 0, len(response.GetUsers()))
|
||||
for _, user := range response.GetUsers() {
|
||||
tableData = append(
|
||||
tableData,
|
||||
rows = append(
|
||||
rows,
|
||||
[]string{
|
||||
strconv.FormatUint(user.GetId(), util.Base10),
|
||||
user.GetDisplayName(),
|
||||
@@ -210,7 +207,7 @@ var listUsersCmd = &cobra.Command{
|
||||
)
|
||||
}
|
||||
|
||||
return pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
|
||||
return renderTable([]string{"ID", "Name", "Username", "Email", colCreated}, rows)
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
+23
-18
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/juanfont/headscale/hscontrol/util/zlog/zf"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc"
|
||||
@@ -161,7 +162,8 @@ func newHeadscaleCLIWithConfig() (context.Context, v1.HeadscaleServiceClient, *g
|
||||
return nil, nil, nil, nil, errAPIKeyNotSet
|
||||
}
|
||||
|
||||
grpcOptions = append(grpcOptions,
|
||||
grpcOptions = append(
|
||||
grpcOptions,
|
||||
grpc.WithPerRPCCredentials(tokenAuth{
|
||||
token: apiKey,
|
||||
}),
|
||||
@@ -175,11 +177,13 @@ func newHeadscaleCLIWithConfig() (context.Context, v1.HeadscaleServiceClient, *g
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
grpcOptions = append(grpcOptions,
|
||||
grpcOptions = append(
|
||||
grpcOptions,
|
||||
grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),
|
||||
)
|
||||
} else {
|
||||
grpcOptions = append(grpcOptions,
|
||||
grpcOptions = append(
|
||||
grpcOptions,
|
||||
grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")),
|
||||
)
|
||||
}
|
||||
@@ -268,9 +272,19 @@ func confirmAction(cmd *cobra.Command, prompt string) bool {
|
||||
return util.YesNo(prompt)
|
||||
}
|
||||
|
||||
// renderTable prints a human-readable pterm table with the given header row
|
||||
// and data rows, using the shared header styling.
|
||||
func renderTable(header []string, rows [][]string) error {
|
||||
tableData := make(pterm.TableData, 0, 1+len(rows))
|
||||
tableData = append(tableData, header)
|
||||
tableData = append(tableData, rows...)
|
||||
|
||||
return pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
|
||||
}
|
||||
|
||||
// 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.
|
||||
// requested it serialises data as JSON/YAML; otherwise it calls the render
|
||||
// callback to produce the human-readable pterm table.
|
||||
func printListOutput(
|
||||
cmd *cobra.Command,
|
||||
data any,
|
||||
@@ -292,24 +306,15 @@ func printError(err error, outputFormat string) {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
e := errOutput{Error: err.Error()}
|
||||
|
||||
var formatted []byte
|
||||
|
||||
switch outputFormat {
|
||||
case outputFormatJSON:
|
||||
formatted, _ = json.MarshalIndent(e, "", "\t") //nolint:errchkjson // errOutput contains only a string field
|
||||
case outputFormatJSONLine:
|
||||
formatted, _ = json.Marshal(e) //nolint:errchkjson // errOutput contains only a string field
|
||||
case outputFormatYAML:
|
||||
formatted, _ = yaml.Marshal(e)
|
||||
default:
|
||||
if outputFormat == "" {
|
||||
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "%s\n", formatted)
|
||||
// formatOutput cannot fail here: errOutput is a single string field.
|
||||
out, _ := formatOutput(errOutput{Error: err.Error()}, "", outputFormat)
|
||||
fmt.Fprintf(os.Stderr, "%s\n", out)
|
||||
}
|
||||
|
||||
func hasMachineOutputFlag() bool {
|
||||
|
||||
Reference in New Issue
Block a user