From 40a46e1412f5a0c92ce7572e188d108e8f530455 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Fri, 25 Feb 2022 14:00:00 -0700 Subject: [PATCH] add ability to specify etcd snapshot list output format (#5132) --- pkg/cli/cmds/etcd_snapshot.go | 6 ++- pkg/cli/cmds/server.go | 1 + pkg/cli/etcdsnapshot/etcd_snapshot.go | 58 +++++++++++++++++++++------ pkg/daemons/config/types.go | 1 + 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/pkg/cli/cmds/etcd_snapshot.go b/pkg/cli/cmds/etcd_snapshot.go index 3325821b10..046d82832f 100644 --- a/pkg/cli/cmds/etcd_snapshot.go +++ b/pkg/cli/cmds/etcd_snapshot.go @@ -128,7 +128,11 @@ func NewEtcdSnapshotSubcommands(delete, list, prune, save func(ctx *cli.Context) SkipFlagParsing: false, SkipArgReorder: true, Action: list, - Flags: EtcdSnapshotFlags, + Flags: append(EtcdSnapshotFlags, &cli.StringFlag{ + Name: "o,output", + Usage: "(db) List format. Default: standard. Optional: json", + Destination: &ServerConfig.EtcdListFormat, + }), }, { Name: "prune", diff --git a/pkg/cli/cmds/server.go b/pkg/cli/cmds/server.go index fb5956bb8b..402cfbb97a 100644 --- a/pkg/cli/cmds/server.go +++ b/pkg/cli/cmds/server.go @@ -86,6 +86,7 @@ type Server struct { EtcdSnapshotCron string EtcdSnapshotRetention int EtcdSnapshotCompress bool + EtcdListFormat string EtcdS3 bool EtcdS3Endpoint string EtcdS3EndpointCA string diff --git a/pkg/cli/etcdsnapshot/etcd_snapshot.go b/pkg/cli/etcdsnapshot/etcd_snapshot.go index 4a3b3b0f91..e138e8db6d 100644 --- a/pkg/cli/etcdsnapshot/etcd_snapshot.go +++ b/pkg/cli/etcdsnapshot/etcd_snapshot.go @@ -1,10 +1,12 @@ package etcdsnapshot import ( + "encoding/json" "errors" "fmt" "os" "path/filepath" + "strings" "text/tabwriter" "time" @@ -17,6 +19,7 @@ import ( util2 "github.com/rancher/k3s/pkg/util" "github.com/rancher/wrangler/pkg/signals" "github.com/urfave/cli" + "gopkg.in/yaml.v2" ) // commandSetup setups up common things needed @@ -40,6 +43,7 @@ func commandSetup(app *cli.Context, cfg *cmds.Server, sc *server.Config) (string sc.ControlConfig.EtcdSnapshotName = cfg.EtcdSnapshotName sc.ControlConfig.EtcdSnapshotDir = cfg.EtcdSnapshotDir sc.ControlConfig.EtcdSnapshotCompress = cfg.EtcdSnapshotCompress + sc.ControlConfig.EtcdListFormat = strings.ToLower(cfg.EtcdListFormat) sc.ControlConfig.EtcdS3 = cfg.EtcdS3 sc.ControlConfig.EtcdS3Endpoint = cfg.EtcdS3Endpoint sc.ControlConfig.EtcdS3EndpointCA = cfg.EtcdS3EndpointCA @@ -152,6 +156,17 @@ func List(app *cli.Context) error { return list(app, &cmds.ServerConfig) } +var etcdListFormats = []string{"json", "yaml"} + +func validEtcdListFormat(format string) bool { + for _, supportedFormat := range etcdListFormats { + if format == supportedFormat { + return true + } + } + return false +} + func list(app *cli.Context, cfg *cmds.Server) error { var serverConfig server.Config @@ -171,21 +186,38 @@ func list(app *cli.Context, cfg *cmds.Server) error { return err } - w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) - defer w.Flush() + if cfg.EtcdListFormat != "" && !validEtcdListFormat(cfg.EtcdListFormat) { + return errors.New("invalid output format: " + cfg.EtcdListFormat) + } - if cfg.EtcdS3 { - fmt.Fprint(w, "Name\tSize\tCreated\n") - for _, s := range sf { - if s.NodeName == "s3" { - fmt.Fprintf(w, "%s\t%d\t%s\n", s.Name, s.Size, s.CreatedAt.Format(time.RFC3339)) - } + switch cfg.EtcdListFormat { + case "json": + if err := json.NewEncoder(os.Stdout).Encode(sf); err != nil { + return err } - } else { - fmt.Fprint(w, "Name\tLocation\tSize\tCreated\n") - for _, s := range sf { - if s.NodeName != "s3" { - fmt.Fprintf(w, "%s\t%s\t%d\t%s\n", s.Name, s.Location, s.Size, s.CreatedAt.Format(time.RFC3339)) + return nil + case "yaml": + if err := yaml.NewEncoder(os.Stdout).Encode(sf); err != nil { + return err + } + return nil + default: + w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) + defer w.Flush() + + if cfg.EtcdS3 { + fmt.Fprint(w, "Name\tSize\tCreated\n") + for _, s := range sf { + if s.NodeName == "s3" { + fmt.Fprintf(w, "%s\t%d\t%s\n", s.Name, s.Size, s.CreatedAt.Format(time.RFC3339)) + } + } + } else { + fmt.Fprint(w, "Name\tLocation\tSize\tCreated\n") + for _, s := range sf { + if s.NodeName != "s3" { + fmt.Fprintf(w, "%s\t%s\t%d\t%s\n", s.Name, s.Location, s.Size, s.CreatedAt.Format(time.RFC3339)) + } } } } diff --git a/pkg/daemons/config/types.go b/pkg/daemons/config/types.go index 390ea5cb9d..aac2206922 100644 --- a/pkg/daemons/config/types.go +++ b/pkg/daemons/config/types.go @@ -173,6 +173,7 @@ type Control struct { EtcdSnapshotCron string EtcdSnapshotRetention int EtcdSnapshotCompress bool + EtcdListFormat string EtcdS3 bool EtcdS3Endpoint string EtcdS3EndpointCA string