Refactor -o option to simplify code 85/13585/2
authorgarciadeblas <gerardo.garciadeblas@telefonica.com>
Mon, 26 Jun 2023 15:41:46 +0000 (17:41 +0200)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Mon, 26 Jun 2023 21:54:29 +0000 (23:54 +0200)
The change includes the implementation of a click option in print_output
module, being used in ns-list, ns-show, vim-list, vim-show, vnf-list and
vnf-show commands.

It also includes a quick validation that the output format is one of the
allowed outputs. It also fixes jsonpath option so that the output is not
embedded in a [] list structure.

Change-Id: I8c33b5faf341c9a4cdd8d488671f2a81ab3b5a3a
Signed-off-by: garciadeblas <gerardo.garciadeblas@telefonica.com>
osmclient/cli_commands/ns.py
osmclient/cli_commands/vim.py
osmclient/cli_commands/vnf.py
osmclient/common/print_output.py
osmclient/scripts/osm.py

index 441ae05..75054fe 100755 (executable)
@@ -38,15 +38,9 @@ logger = logging.getLogger("osmclient")
     is_flag=True,
     help="get more details of the NS (project, vim, deployment status, configuration status.",
 )
-@click.option(
-    "-o",
-    default="table",
-    is_eager=True,
-    callback=print_output.validate_command_output,
-    help="adapt the output as table, yaml, csv, json, jsonpath",
-)
+@print_output.output_option
 @click.pass_context
-def ns_list(ctx, filter, long, o):
+def ns_list(ctx, filter, long, output):
     """list all NS instances
 
     \b
@@ -302,9 +296,7 @@ def ns_list(ctx, filter, long, o):
                     utils.wrap_text(text=error_details, width=40),
                 ]
             )
-    table.align = "l"
-    # print(table)
-    print_output.print_output(o, table.field_names, table._rows)
+    print_output.print_output(output, table.field_names, table._rows)
     print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"')
     print(
         'For more details on the current operation, run "osm ns-op-show OPERATION_ID"'
@@ -319,15 +311,9 @@ def ns_list(ctx, filter, long, o):
     multiple=True,
     help="restricts the information to the fields in the filter",
 )
-@click.option(
-    "-o",
-    default="table",
-    is_eager=True,
-    callback=print_output.validate_command_output,
-    help="adapt the output as table, yaml, csv, json, jsonpath",
-)
+@print_output.output_option
 @click.pass_context
-def ns_show(ctx, name, literal, filter, o):
+def ns_show(ctx, name, literal, filter, output):
     """shows the info of a NS instance
 
     NAME: name or ID of the NS instance
@@ -352,9 +338,7 @@ def ns_show(ctx, name, literal, filter, o):
         for k, v in list(nsr_optdata.items()):
             if not filter or k in filter:
                 table.add_row([k, utils.wrap_text(json.dumps(v, indent=2), width=100)])
-    table.align = "l"
-    print_output.print_output(o, table.field_names, table._rows)
-    # print(table)
+    print_output.print_output(output, table.field_names, table._rows)
 
 
 @click.command(name="ns-create", short_help="creates a new Network Service instance")
index b2a073d..d74ea7b 100755 (executable)
@@ -304,15 +304,9 @@ def vim_delete(ctx, name, force, wait):
     is_flag=True,
     help="get more details of the NS (project, vim, deployment status, configuration status.",
 )
-@click.option(
-    "-o",
-    default="table",
-    is_eager=True,
-    callback=print_output.validate_command_output,
-    help="get more details of the NS (project, vim, deployment status, configuration status.",
-)
+@print_output.output_option
 @click.pass_context
-def vim_list(ctx, filter, long, o):
+def vim_list(ctx, filter, long, output):
     """list all VIM accounts"""
     logger.debug("")
     if filter:
@@ -355,9 +349,7 @@ def vim_list(ctx, filter, long, o):
             table.add_row(
                 [vim["name"], vim["uuid"], vim["_admin"].get("operationalState", "-")]
             )
-    table.align = "l"
-    # print(table)
-    print_output.print_output(o, table.field_names, table._rows)
+    print_output.print_output(output, table.field_names, table._rows)
 
 
 @click.command(name="vim-show", short_help="shows the details of a VIM account")
@@ -368,15 +360,9 @@ def vim_list(ctx, filter, long, o):
     help="restricts the information to the fields in the filter",
 )
 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
-@click.option(
-    "-o",
-    default="table",
-    is_eager=True,
-    callback=print_output.validate_command_output,
-    help="adapt the output as table, yaml, csv, json, jsonpath",
-)
+@print_output.output_option
 @click.pass_context
-def vim_show(ctx, name, filter, literal, o):
+def vim_show(ctx, name, filter, literal, output):
     """shows the details of a VIM account
 
     NAME: name or ID of the VIM account
@@ -395,6 +381,4 @@ def vim_show(ctx, name, filter, literal, o):
     for k, v in list(resp.items()):
         if not filter or k in filter:
             table.add_row([k, utils.wrap_text(text=json.dumps(v, indent=2), width=100)])
-    table.align = "l"
-    # print(table)
-    print_output.print_output(o, table.field_names, table._rows)
+    print_output.print_output(output, table.field_names, table._rows)
index 6c86ff7..974a421 100755 (executable)
@@ -27,7 +27,7 @@ import logging
 logger = logging.getLogger("osmclient")
 
 
-def vnf_list(ctx, ns, filter, long, o):
+def vnf_list(ctx, ns, filter, long, output):
     logger.debug("")
     if ns or filter:
         if ns:
@@ -96,9 +96,7 @@ def vnf_list(ctx, ns, filter, long, o):
                     vnfr["config-status"],
                 ]
             )
-    table.align = "l"
-    # print(table)
-    print_output.print_output(o, table.field_names, table._rows)
+    print_output.print_output(output, table.field_names, table._rows)
 
 
 @click.command(name="vnf-list", short_help="list all NF instances")
@@ -112,18 +110,12 @@ def vnf_list(ctx, ns, filter, long, o):
     help="restricts the list to the NF instances matching the filter.",
 )
 @click.option("--long", is_flag=True, help="get more details")
-@click.option(
-    "-o",
-    default="table",
-    is_eager=True,
-    callback=print_output.validate_command_output,
-    help="adapt the output as table, yaml, csv, json, jsonpath",
-)
+@print_output.output_option
 @click.pass_context
-def vnf_list1(ctx, ns, filter, long, o):
+def vnf_list1(ctx, ns, filter, long, output):
     """list all NF instances"""
     logger.debug("")
-    vnf_list(ctx, ns, filter, long, o)
+    vnf_list(ctx, ns, filter, long, output)
 
 
 @click.command(name="nf-list", short_help="list all NF instances")
@@ -137,15 +129,9 @@ def vnf_list1(ctx, ns, filter, long, o):
     help="restricts the list to the NF instances matching the filter.",
 )
 @click.option("--long", is_flag=True, help="get more details")
-@click.option(
-    "-o",
-    default="table",
-    # is_eager=True,
-    # callback=print_output.validate_command_output,
-    help="adapt the output as table, yaml, csv, json, jsonpath",
-)
+@print_output.output_option
 @click.pass_context
-def nf_list(ctx, ns, filter, long, o):
+def nf_list(ctx, ns, filter, long, output):
     """list all NF instances
 
     \b
@@ -194,7 +180,7 @@ def nf_list(ctx, ns, filter, long, o):
        --filter  vnfd-ref=<VNFD_NAME>,vdur.ip-address=<IP_ADDRESS>
     """
     logger.debug("")
-    vnf_list(ctx, ns, filter, long, o)
+    vnf_list(ctx, ns, filter, long, output)
 
 
 @click.command(name="vnf-show", short_help="shows the info of a VNF instance")
@@ -206,15 +192,9 @@ def nf_list(ctx, ns, filter, long, o):
     help="restricts the information to the fields in the filter",
 )
 @click.option("--kdu", default=None, help="KDU name (whose status will be shown)")
-@click.option(
-    "-o",
-    default="table",
-    is_eager=True,
-    callback=print_output.validate_command_output,
-    help="adapt the output as table, yaml, csv, json, jsonpath",
-)
+@print_output.output_option
 @click.pass_context
-def vnf_show(ctx, name, literal, filter, kdu, o):
+def vnf_show(ctx, name, literal, filter, kdu, output):
     """shows the info of a VNF instance
 
     NAME: name or ID of the VNF instance
@@ -294,6 +274,4 @@ def vnf_show(ctx, name, literal, filter, kdu, o):
     for k, v in list(resp.items()):
         if not filter or k in filter:
             table.add_row([k, utils.wrap_text(text=json.dumps(v, indent=2), width=100)])
-    table.align = "l"
-    # print(table)
-    print_output.print_output(o, table.field_names, table._rows)
+    print_output.print_output(output, table.field_names, table._rows)
index e5bc7f7..a9364c8 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #######################################################################################
+import click
+import logging
 import json
 import yaml
-import click
 from prettytable import PrettyTable
 
 from jsonpath_ng import parse
 
 
+logger = logging.getLogger("osmclient")
+
+
+def evaluate_output_format(ctx, param, value):
+    logger.debug("")
+    if value in ["table", "json", "yaml", "csv"]:
+        return value
+    elif value.startswith("jsonpath="):
+        return value
+    else:
+        raise click.BadParameter(
+            f"{value} is not one of 'table', 'json', 'yaml', 'csv', 'jsonpath'"
+        )
+
+
+output_option = click.option(
+    "-o",
+    "--output",
+    default="table",
+    is_eager=True,
+    callback=evaluate_output_format,
+    help="output format (default: table)",
+)
+
+
+literal_option = click.option(
+    "--literal", is_flag=True, help="print literally, no pretty table"
+)
+
+
 def print_output(format, headers, rows):
+    logger.debug("")
     if format == "table":
         table = PrettyTable(headers)
+        table.align = "l"
         for row in rows:
             table.add_row(row)
         print(table)
-    elif format == "json":
-        data = []
-        for row in rows:
-            data.append(dict(zip(headers, row)))
-        json_data = json.dumps(data)
-        print(json_data)
     elif format == "csv":
         table = PrettyTable(headers)
         for row in rows:
             table.add_row(row)
         print(table.get_csv_string())
-    elif format == "yaml":
+    elif format == "json" or format == "yaml" or format.startswith("jsonpath="):
         data = []
         for row in rows:
-            data.append(dict(zip(headers, row)))
-        yaml_string = yaml.safe_dump(data, sort_keys=False)
-        print(yaml_string)
-    elif format.startswith("jsonpath="):
-        # JSONPath expression
-        json_path_expression = format.partition("=")[-1]
-        json_path = parse(json_path_expression)
-        data = []
-        for row in rows:
-            data.append(dict(zip(headers, row)))
-        # json_data = json.dumps(data)
-        # Apply JSONPath expression on the JSON object
-        results = [match.value for match in json_path.find(data)]
-        print(results)
-    else:
-        print("Valid values for -o are table, yaml, csv, json, jsonpath")
-
-
-def validate_command_output(ctx, param, value):
-    allowed_commands = [
-        "ns-list",
-        "ns-show",
-        "vim-list",
-        "vim-show",
-        "vnf-list",
-        "vnf-show",
-    ]  # List of allowed commands
-
-    if ctx.command.name in allowed_commands:
-        return value
-    # if param:
-    #     print (value)
-    else:
-        raise click.BadParameter(
-            f'Option "{param.name}" is not allowed for this command.'
-        )
+            item = {}
+            for i in range(len(row)):
+                item[headers[i]] = row[i]
+            data.append(item)
+        if format == "json":
+            print(json.dumps(data, indent=4))
+        elif format == "yaml":
+            print(
+                yaml.safe_dump(
+                    data, indent=4, default_flow_style=False, sort_keys=False
+                )
+            )
+        elif format.startswith("jsonpath="):
+            # JSONPath expression
+            json_path_expression = format.partition("=")[-1]
+            logger.debug(f"Jsonpath expression: {json_path_expression}")
+            json_path = parse(json_path_expression)
+            # Apply JSONPath expression on the JSON object
+            results = [match.value for match in json_path.find(data)]
+            for i in results:
+                print(i)
index 0a17948..74bb84b 100755 (executable)
@@ -78,11 +78,6 @@ from requests import RequestException
     count=True,
     help="increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)",
 )
-@click.option(
-    "-o",
-    "--output",
-    help="adapt output format (table, yaml, csv, json, jsonpath)",
-)
 @click.option("--all-projects", default=None, is_flag=True, help="include all projects")
 @click.option(
     "--public/--no-public",