diff mbox series

[ovs-dev,v12,5/6] vswitchd: Add JSON output for 'list-commands' command.

Message ID 20240516154117.2306789-6-jmeng@redhat.com
State Changes Requested
Delegated to: Ilya Maximets
Headers show
Series [ovs-dev,v12,1/6] Add global option for JSON output to ovs-appctl. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/intel-ovs-compilation success test: success

Commit Message

Jakob Meng May 16, 2024, 3:41 p.m. UTC
From: Jakob Meng <code@jakobmeng.de>

The 'list-commands' command now supports machine-readable JSON output
in addition to the plain-text output for humans.

Reported-at: https://bugzilla.redhat.com/1824861
Signed-off-by: Jakob Meng <code@jakobmeng.de>
---
 NEWS                  |  1 +
 lib/unixctl.c         | 44 +++++++++++++++++++++++++++++--------------
 tests/ovs-vswitchd.at | 13 +++++++++++++
 3 files changed, 44 insertions(+), 14 deletions(-)

Comments

Ilya Maximets July 3, 2024, 6:32 p.m. UTC | #1
On 5/16/24 17:41, jmeng@redhat.com wrote:
> From: Jakob Meng <code@jakobmeng.de>
> 
> The 'list-commands' command now supports machine-readable JSON output
> in addition to the plain-text output for humans.
> 
> Reported-at: https://bugzilla.redhat.com/1824861
> Signed-off-by: Jakob Meng <code@jakobmeng.de>
> ---
>  NEWS                  |  1 +
>  lib/unixctl.c         | 44 +++++++++++++++++++++++++++++--------------
>  tests/ovs-vswitchd.at | 13 +++++++++++++
>  3 files changed, 44 insertions(+), 14 deletions(-)
> 
> diff --git a/NEWS b/NEWS
> index 0d41061d3..479310d49 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -4,6 +4,7 @@ Post-v3.3.0
>       * 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.
> +     * 'list-commands' now supports output in JSON format.
>     - Python:
>       * Added support for different output formats like 'json' to appctl.py and
>         Python's unixctl classes.
> diff --git a/lib/unixctl.c b/lib/unixctl.c
> index c430eac0b..c84ca125f 100644
> --- a/lib/unixctl.c
> +++ b/lib/unixctl.c
> @@ -107,24 +107,40 @@ static void
>  unixctl_list_commands(struct unixctl_conn *conn, int argc OVS_UNUSED,
>                        const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
>  {
> -    struct ds ds = DS_EMPTY_INITIALIZER;
> -    const struct shash_node **nodes = shash_sort(&commands);
> -    size_t i;
> +    if (unixctl_command_get_output_format(conn) == UNIXCTL_OUTPUT_FMT_JSON) {
> +        struct json *json_commands = json_object_create();
> +        const struct shash_node *node;
>  
> -    ds_put_cstr(&ds, "The available commands are:\n");
> +        SHASH_FOR_EACH (node, &commands) {
> +            const struct unixctl_command *command = node->data;
>  
> -    for (i = 0; i < shash_count(&commands); i++) {
> -        const struct shash_node *node = nodes[i];
> -        const struct unixctl_command *command = node->data;
> -
> -        if (command->usage) {
> -            ds_put_format(&ds, "  %-23s %s\n", node->name, command->usage);
> +            if (command->usage) {
> +                json_object_put_string(json_commands, node->name,
> +                                       command->usage);
> +            }
>          }
> -    }
> -    free(nodes);
> +        unixctl_command_reply_json(conn, json_commands);
> +    } else {
> +        struct ds ds = DS_EMPTY_INITIALIZER;
> +        const struct shash_node **nodes = shash_sort(&commands);
> +        size_t i;
>  
> -    unixctl_command_reply(conn, ds_cstr(&ds));
> -    ds_destroy(&ds);
> +        ds_put_cstr(&ds, "The available commands are:\n");
> +
> +        for (i = 0; i < shash_count(&commands); ++i) {
> +            const struct shash_node *node = nodes[i];
> +            const struct unixctl_command *command = node->data;
> +
> +            if (command->usage) {
> +                ds_put_format(&ds, "  %-23s %s\n", node->name,
> +                              command->usage);
> +            }
> +        }
> +        free(nodes);
> +
> +        unixctl_command_reply(conn, ds_cstr(&ds));
> +        ds_destroy(&ds);
> +    }
>  }
>  
>  static void
> diff --git a/tests/ovs-vswitchd.at b/tests/ovs-vswitchd.at
> index 2db8138f1..4f909603a 100644
> --- a/tests/ovs-vswitchd.at
> +++ b/tests/ovs-vswitchd.at
> @@ -281,3 +281,16 @@ AT_CHECK_UNQUOTED([ovs-appctl --format json --pretty version], [0], [dnl
>    "reply-format": "plain"}])
>  
>  AT_CLEANUP
> +
> +AT_SETUP([ovs-vswitchd list-commands])
> +OVS_VSWITCHD_START
> +
> +AT_CHECK([ovs-appctl list-commands], [0], [ignore])
> +AT_CHECK([ovs-appctl --format json list-commands], [0], [stdout])
> +# Check that ovs-appctl prints a single line without a trailing newline.

There should be a new line. :)

> +AT_CHECK([wc -l stdout], [0], [0 stdout
> +])
> +# Check that ovs-appctl prints text which roughly looks like a JSON object.
> +AT_CHECK([grep -E '^\{"autoattach/show-isid":.*\}$' stdout], [0], [ignore])

You can use './tests/ovstest test-json FILE.json' to check that the result is
a correct JSON file.

Best regards, Ilya Maximets.
diff mbox series

Patch

diff --git a/NEWS b/NEWS
index 0d41061d3..479310d49 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@  Post-v3.3.0
      * 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.
+     * 'list-commands' now supports output in JSON format.
    - Python:
      * Added support for different output formats like 'json' to appctl.py and
        Python's unixctl classes.
diff --git a/lib/unixctl.c b/lib/unixctl.c
index c430eac0b..c84ca125f 100644
--- a/lib/unixctl.c
+++ b/lib/unixctl.c
@@ -107,24 +107,40 @@  static void
 unixctl_list_commands(struct unixctl_conn *conn, int argc OVS_UNUSED,
                       const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
 {
-    struct ds ds = DS_EMPTY_INITIALIZER;
-    const struct shash_node **nodes = shash_sort(&commands);
-    size_t i;
+    if (unixctl_command_get_output_format(conn) == UNIXCTL_OUTPUT_FMT_JSON) {
+        struct json *json_commands = json_object_create();
+        const struct shash_node *node;
 
-    ds_put_cstr(&ds, "The available commands are:\n");
+        SHASH_FOR_EACH (node, &commands) {
+            const struct unixctl_command *command = node->data;
 
-    for (i = 0; i < shash_count(&commands); i++) {
-        const struct shash_node *node = nodes[i];
-        const struct unixctl_command *command = node->data;
-
-        if (command->usage) {
-            ds_put_format(&ds, "  %-23s %s\n", node->name, command->usage);
+            if (command->usage) {
+                json_object_put_string(json_commands, node->name,
+                                       command->usage);
+            }
         }
-    }
-    free(nodes);
+        unixctl_command_reply_json(conn, json_commands);
+    } else {
+        struct ds ds = DS_EMPTY_INITIALIZER;
+        const struct shash_node **nodes = shash_sort(&commands);
+        size_t i;
 
-    unixctl_command_reply(conn, ds_cstr(&ds));
-    ds_destroy(&ds);
+        ds_put_cstr(&ds, "The available commands are:\n");
+
+        for (i = 0; i < shash_count(&commands); ++i) {
+            const struct shash_node *node = nodes[i];
+            const struct unixctl_command *command = node->data;
+
+            if (command->usage) {
+                ds_put_format(&ds, "  %-23s %s\n", node->name,
+                              command->usage);
+            }
+        }
+        free(nodes);
+
+        unixctl_command_reply(conn, ds_cstr(&ds));
+        ds_destroy(&ds);
+    }
 }
 
 static void
diff --git a/tests/ovs-vswitchd.at b/tests/ovs-vswitchd.at
index 2db8138f1..4f909603a 100644
--- a/tests/ovs-vswitchd.at
+++ b/tests/ovs-vswitchd.at
@@ -281,3 +281,16 @@  AT_CHECK_UNQUOTED([ovs-appctl --format json --pretty version], [0], [dnl
   "reply-format": "plain"}])
 
 AT_CLEANUP
+
+AT_SETUP([ovs-vswitchd list-commands])
+OVS_VSWITCHD_START
+
+AT_CHECK([ovs-appctl list-commands], [0], [ignore])
+AT_CHECK([ovs-appctl --format json list-commands], [0], [stdout])
+# Check that ovs-appctl prints a single line without a trailing newline.
+AT_CHECK([wc -l stdout], [0], [0 stdout
+])
+# Check that ovs-appctl prints text which roughly looks like a JSON object.
+AT_CHECK([grep -E '^\{"autoattach/show-isid":.*\}$' stdout], [0], [ignore])
+
+AT_CLEANUP