From 86308c3952ad134eb79d96fe6a551b7585198334 Mon Sep 17 00:00:00 2001 From: twalluxio <139105284+twalluxio@users.noreply.github.com> Date: Mon, 18 Sep 2023 10:43:55 +0800 Subject: [PATCH] Parse JSON-style reports in golang side Update the Golang side commands to be able to use this output: 1. Return either the yaml or json (default) output to the console. 2. Users can define the format they want with `--format` flag, like `bin/alluxio info report --format yaml` 3. In JSON format, print properties in a fixed, easy-to-read order 4. In YAML format, print properties alphabetically (since YAML specification regards property order non-significant) Before: ``` {"safeMode":false,"masterVersions":[{"version":"304-SNAPSHOT","host":"localhost","port":19998,"state":"PRIMARY"}],"masterAddress":"localhost:19998","zookeeperAddress":[],"useZookeeper":false,"raftJournalAddress":["localhost:19200"],"useRaftJournal":true,"liveWorkers":1,"lostWorkers":0,"freeCapacity":"1024.00MB","totalCapacityOnTiers":{"MEM":"1024.00MB"},"usedCapacityOnTiers":{"MEM":"0B"},"version":"304-SNAPSHOT","webPort":19999,"started":"09-15-2023 15:54:56:635","uptime":"0 day(s), 0 hour(s), 26 minute(s), and 37 second(s)","rpcPort":19998} ``` After (in JSON): ``` { "rpcPort": 19998, "started": "09-15-2023 15:54:56:635", "uptime": "0 day(s), 0 hour(s), 55 minute(s), and 31 second(s)", "safeMode": false, "version": "304-SNAPSHOT", "webPort": 19999, "masterVersions": [ { "version": "304-SNAPSHOT", "host": "localhost", "port": 19998, "state": "PRIMARY" } ], "masterAddress": "localhost:19998", "zookeeperAddress": [], "useZookeeper": false, "raftJournalAddress": [ "localhost:19200" ], "useRaftJournal": true, "liveWorkers": 1, "lostWorkers": 0, "freeCapacity": "1024.00MB", "totalCapacityOnTiers": { "MEM": "1024.00MB" }, "usedCapacityOnTiers": { "MEM": "0B" } } ``` After (in YAML): ``` freeCapacity: 1024.00MB liveWorkers: 1 lostWorkers: 0 masterAddress: localhost:19998 masterVersions: - host: localhost port: 19998 state: PRIMARY version: 304-SNAPSHOT raftJournalAddress: - localhost:19200 rpcPort: 19998 safeMode: false started: 09-15-2023 15:54:56:635 totalCapacityOnTiers: MEM: 1024.00MB uptime: 0 day(s), 1 hour(s), 1 minute(s), and 36 second(s) useRaftJournal: true useZookeeper: false usedCapacityOnTiers: MEM: 0B version: 304-SNAPSHOT webPort: 19999 zookeeperAddress: [] ``` pr-link: Alluxio/alluxio#18159 change-id: cid-deb6e74552de9afcf45391c6c230a9fe00785e37 --- cli/src/alluxio.org/cli/cmd/info/report.go | 8 +++++++- cli/src/alluxio.org/cli/env/command.go | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/cli/src/alluxio.org/cli/cmd/info/report.go b/cli/src/alluxio.org/cli/cmd/info/report.go index 6b792018ae9a..14fe7e0d3bfd 100644 --- a/cli/src/alluxio.org/cli/cmd/info/report.go +++ b/cli/src/alluxio.org/cli/cmd/info/report.go @@ -32,6 +32,7 @@ var Report = &ReportCommand{ type ReportCommand struct { *env.BaseJavaCommand + format string } func (c *ReportCommand) Base() *env.BaseJavaCommand { @@ -56,6 +57,8 @@ Defaults to summary if no arg is provided return c.Run(args) }, }) + cmd.Flags().StringVar(&c.format, "format", "json", + "Set output format, any of [json, yaml]") return cmd } @@ -78,5 +81,8 @@ func (c *ReportCommand) Run(args []string) error { reportArg = args[0] } // TODO: output all in a serializable format and filter/trim as specified by flags - return c.Base().Run([]string{reportArg}) + if c.format != "json" && c.format != "yaml" { + return stacktrace.NewError("Invalid format %v, must be one of [json, yaml]", c.format) + } + return c.Base().RunAndFormat(c.format, nil, []string{reportArg}) } diff --git a/cli/src/alluxio.org/cli/env/command.go b/cli/src/alluxio.org/cli/env/command.go index a2ee82f3e25b..32e13e98fa93 100644 --- a/cli/src/alluxio.org/cli/env/command.go +++ b/cli/src/alluxio.org/cli/env/command.go @@ -114,7 +114,20 @@ func (c *BaseJavaCommand) RunWithIO(args []string, stdin io.Reader, stdout, stde func (c *BaseJavaCommand) RunAndFormat(format string, stdin io.Reader, args []string) error { switch strings.ToLower(format) { case "json": - return c.RunWithIO(args, stdin, os.Stdout, os.Stderr) + buf := &bytes.Buffer{} + if err := c.RunWithIO(args, stdin, buf, os.Stderr); err != nil { + io.Copy(os.Stdout, buf) + return err + } + var obj json.RawMessage + if err := json.Unmarshal(buf.Bytes(), &obj); err != nil { + return stacktrace.Propagate(err, "error unmarshalling json from java command") + } + prettyJson, err := json.MarshalIndent(obj, "", " ") + if err != nil { + return stacktrace.Propagate(err, "error marshalling json to pretty format") + } + os.Stdout.Write(append(prettyJson, '\n')) case "yaml": buf := &bytes.Buffer{} if err := c.RunWithIO(args, stdin, buf, os.Stderr); err != nil {