From ad790723423accefe3b952248c368f2210452215 Mon Sep 17 00:00:00 2001 From: Mahe Tardy Date: Mon, 12 Feb 2024 20:27:35 +0100 Subject: [PATCH] cmd/tetra: use text/tabwriter to format tp list output Also add the support of load error by reusing the metric state recap. Previously, the output of `tetra tp list` was a bit chaotic, for example, with 2 policies, with one with a loading error, it looked like the following: [1] invalid enabled:false filterID:0 namespace:(global) sensors: loadError: "policy handler 'tracing' failed loading policy 'invalid': tracing [...] [2] block-binary enabled:true filterID:0 namespace:(global) sensors:gkp-sensor-1 Now, using text/tabwriter, we redact the errors (use -o json for full output) and put everything in columns: ID NAME STATE FILTERID NAMESPACE SENSORS 1 invalid load_error 0 (global) 2 block-binary enabled 0 (global) gkp-sensor-1 Signed-off-by: Mahe Tardy --- cmd/tetra/tracingpolicy/tracingpolicy.go | 29 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/cmd/tetra/tracingpolicy/tracingpolicy.go b/cmd/tetra/tracingpolicy/tracingpolicy.go index caee48fbf1d..d9cc50f1dc7 100644 --- a/cmd/tetra/tracingpolicy/tracingpolicy.go +++ b/cmd/tetra/tracingpolicy/tracingpolicy.go @@ -7,6 +7,7 @@ import ( "fmt" "os" "strings" + "text/tabwriter" "github.com/cilium/tetragon/api/v1/tetragon" "github.com/cilium/tetragon/cmd/tetra/common" @@ -113,7 +114,8 @@ func New() *cobra.Command { var tpListOutputFlag string tpListCmd := &cobra.Command{ Use: "list", - Short: "list tracing policies", + Short: "list loaded tracing policies", + Long: "List loaded tracing policies, use the JSON output format for full output.", Args: cobra.ExactArgs(0), PreRunE: func(_ *cobra.Command, _ []string) error { if tpListOutputFlag != "json" && tpListOutputFlag != "text" { @@ -130,13 +132,18 @@ func New() *cobra.Command { return fmt.Errorf("failed to list tracing policies: %w", err) } - if tpListOutputFlag == "json" { + switch tpListOutputFlag { + case "json": b, err := res.MarshalJSON() if err != nil { return fmt.Errorf("failed to generate json: %w", err) } cmd.Println(string(b)) - } else { + case "text": + // tabwriter config imitates kubectl default output, i.e. 3 spaces padding + w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 0, 3, ' ', 0) + fmt.Fprintln(w, "ID\tNAME\tSTATE\tFILTERID\tNAMESPACE\tSENSORS") + for _, pol := range res.Policies { namespace := pol.Namespace if namespace == "" { @@ -167,14 +174,16 @@ func New() *cobra.Command { } } - cmd.Printf("[%d] %s enabled:%t filterID:%d namespace:%s sensors:%s\n", pol.Id, pol.Name, pol.Enabled, pol.FilterId, namespace, sensors) - if pol.Info != "" { - cmd.Printf("\tinfo: %s\n", pol.Info) - } - if pol.Error != "" && pol.Error != "" { - cmd.Printf("\terror: %s\n", pol.Error) - } + fmt.Fprintf(w, "%d\t%s\t%s\t%d\t%s\t%s\t\n", + pol.Id, + pol.Name, + strings.ToLower(pol.State.String()), + pol.FilterId, + namespace, + sensors, + ) } + w.Flush() } return nil