diff mbox series

[ovs-dev,v5,5/6] appctl: Add option '--pretty' for pretty-printing JSON output.

Message ID 20240117125539.106700-6-jmeng@redhat.com
State Changes Requested, archived
Delegated to: Simon Horman
Headers show
Series Add global option to output JSON from ovs-appctl cmds. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test fail github build: failed

Commit Message

Jakob Meng Jan. 17, 2024, 12:55 p.m. UTC
From: Jakob Meng <code@jakobmeng.de>

Signed-off-by: Jakob Meng <code@jakobmeng.de>
---
 NEWS                   |  3 +++
 lib/unixctl.c          |  4 ++--
 lib/unixctl.h          |  1 +
 tests/pmd.at           | 29 +++++++++++++++++++++++++++--
 utilities/ovs-appctl.c | 22 +++++++++++++++++++---
 5 files changed, 52 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/NEWS b/NEWS
index 4df02e6b2..94092a38a 100644
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,9 @@  Post-v3.2.0
        on mark and labels.
      * Added new option [-f|--format] to choose the output format, e.g. 'json'
        or 'text' (by default).
+     * Added new option [--pretty] to print JSON output in a readable fashion.
+       E.g. members of objects and elements of arrays are printed one per line,
+       with indentation.
    - Python:
      * Added support for choosing the output format, e.g. 'json' or 'text'.
    - ovs-vsctl:
diff --git a/lib/unixctl.c b/lib/unixctl.c
index 3b9f300ba..1b216795d 100644
--- a/lib/unixctl.c
+++ b/lib/unixctl.c
@@ -553,7 +553,7 @@  unixctl_client_create(const char *path, struct jsonrpc **client)
  * '*err' if not NULL. */
 int
 unixctl_client_transact(struct jsonrpc *client, const char *command, int argc,
-                        char *argv[], char **result, char **err)
+                        char *argv[], int fmt_flags, char **result, char **err)
 {
     struct jsonrpc_msg *request, *reply;
     struct json **json_args, *params;
@@ -590,7 +590,7 @@  unixctl_client_transact(struct jsonrpc *client, const char *command, int argc,
             *result = xstrdup(json_string(reply->result));
         } else if (reply->result->type == JSON_OBJECT ||
                    reply->result->type == JSON_ARRAY) {
-            *result = json_to_string(reply->result, 0);
+            *result = json_to_string(reply->result, fmt_flags);
         } else {
             VLOG_WARN("%s: unexpected result type in JSON rpc reply: %s",
                       jsonrpc_get_name(client),
diff --git a/lib/unixctl.h b/lib/unixctl.h
index 35ef6a548..fe9160894 100644
--- a/lib/unixctl.h
+++ b/lib/unixctl.h
@@ -39,6 +39,7 @@  int unixctl_client_create(const char *path, struct jsonrpc **client);
 int unixctl_client_transact(struct jsonrpc *client,
                             const char *command,
                             int argc, char *argv[],
+                            int fmt_flags,
                             char **result, char **error);
 
 /* Command registration. */
diff --git a/tests/pmd.at b/tests/pmd.at
index 57660c407..cff80da15 100644
--- a/tests/pmd.at
+++ b/tests/pmd.at
@@ -112,8 +112,33 @@  dummy@ovs-dummy: hit:0 missed:0
     p0 1/1: (dummy-pmd: n_rxq=1, n_txq=1, numa_id=0)
 ])
 
-AT_CHECK([ovs-appctl --format json dpif/show], [0], [dnl
-[[{"ofprotos":[{"name":"br0","ports":[{"netdev_type":"dummy-internal","ofp_port":"65534","odp_port":"100","netdev_config":{},"netdev_name":"br0"},{"netdev_type":"dummy-pmd","ofp_port":"1","odp_port":"1","netdev_config":{"numa_id":"0","n_txq":"1","n_rxq":"1"},"netdev_name":"p0"}]}],"name":"dummy@ovs-dummy","stats":{"n_hit":"0","n_missed":"0"}}]]])
+AT_CHECK([ovs-appctl --format json --pretty dpif/show], [0], [dnl
+[[
+  {
+    "name": "dummy@ovs-dummy",
+    "ofprotos": [
+      {
+        "name": "br0",
+        "ports": [
+          {
+            "netdev_config": {
+              },
+            "netdev_name": "br0",
+            "netdev_type": "dummy-internal",
+            "odp_port": "100",
+            "ofp_port": "65534"},
+          {
+            "netdev_config": {
+              "n_rxq": "1",
+              "n_txq": "1",
+              "numa_id": "0"},
+            "netdev_name": "p0",
+            "netdev_type": "dummy-pmd",
+            "odp_port": "1",
+            "ofp_port": "1"}]}],
+    "stats": {
+      "n_hit": "0",
+      "n_missed": "0"}}]]])
 
 OVS_VSWITCHD_STOP
 AT_CLEANUP
diff --git a/utilities/ovs-appctl.c b/utilities/ovs-appctl.c
index 02df8ba97..03c71ffad 100644
--- a/utilities/ovs-appctl.c
+++ b/utilities/ovs-appctl.c
@@ -26,6 +26,7 @@ 
 #include "daemon.h"
 #include "dirs.h"
 #include "openvswitch/dynamic-string.h"
+#include "openvswitch/json.h"
 #include "jsonrpc.h"
 #include "process.h"
 #include "timeval.h"
@@ -39,6 +40,7 @@  static void usage(void);
 /* Parsed command line args. */
 struct cmdl_args {
     enum ovs_output_fmt format;
+    int format_flags;
     char *target;
 };
 
@@ -73,7 +75,7 @@  main(int argc, char *argv[])
 
     if (opt_argv.n > 0) {
         error = unixctl_client_transact(client, "set-options",
-                                        opt_argv.n, opt_argv.names,
+                                        opt_argv.n, opt_argv.names, 0,
                                         &cmd_result, &cmd_error);
 
         if (error) {
@@ -97,7 +99,9 @@  main(int argc, char *argv[])
     cmd_argc = argc - optind;
     cmd_argv = cmd_argc ? argv + optind : NULL;
     error = unixctl_client_transact(client, cmd, cmd_argc, cmd_argv,
-                                    &cmd_result, &cmd_error);
+                                    args->format_flags, &cmd_result,
+                                    &cmd_error);
+
     if (error) {
         ovs_fatal(error, "%s: transaction error", args->target);
     }
@@ -143,6 +147,11 @@  Other options:\n\
   --timeout=SECS     wait at most SECS seconds for a response\n\
   -f, --format=FMT   Output format. One of: 'json', or 'text'\n\
                      ('text', by default)\n\
+  --pretty           By default, JSON in output is printed as compactly as\n\
+                     possible. This option causes JSON in output to be\n\
+                     printed in a more readable fashion. Members of objects\n\
+                     and elements of arrays are printed one per line, with\n\
+                     indentation.\n\
   -h, --help         Print this helpful information\n\
   -V, --version      Display ovs-appctl version information\n",
            program_name, program_name);
@@ -154,6 +163,7 @@  cmdl_args_create(void) {
     struct cmdl_args *args = xmalloc(sizeof *args);
 
     args->format = OVS_OUTPUT_FMT_TEXT;
+    args->format_flags = 0;
     args->target = NULL;
 
     return args;
@@ -173,7 +183,8 @@  parse_command_line(int argc, char *argv[])
 {
     enum {
         OPT_START = UCHAR_MAX + 1,
-        VLOG_OPTION_ENUMS
+        OPT_PRETTY,
+        VLOG_OPTION_ENUMS,
     };
     static const struct option long_options[] = {
         {"target", required_argument, NULL, 't'},
@@ -181,6 +192,7 @@  parse_command_line(int argc, char *argv[])
         {"format", required_argument, NULL, 'f'},
         {"help", no_argument, NULL, 'h'},
         {"option", no_argument, NULL, 'o'},
+        {"pretty", no_argument, NULL, OPT_PRETTY},
         {"version", no_argument, NULL, 'V'},
         {"timeout", required_argument, NULL, 'T'},
         VLOG_LONG_OPTIONS,
@@ -233,6 +245,10 @@  parse_command_line(int argc, char *argv[])
             ovs_cmdl_print_options(long_options);
             exit(EXIT_SUCCESS);
 
+        case OPT_PRETTY:
+            args->format_flags |= JSSF_PRETTY | JSSF_SORT;
+            break;
+
         case 'T':
             if (!str_to_uint(optarg, 10, &timeout) || !timeout) {
                 ovs_fatal(0, "value %s on -T or --timeout is invalid", optarg);