From 579604d2c666c9fc24ec9065b18fb74a6bf4f138 Mon Sep 17 00:00:00 2001 From: Rigel Di Scala Date: Wed, 29 Jul 2020 15:27:45 +0200 Subject: [PATCH] Allow YAML as a CLI import format This changset allows the import of YAML formatted resources. The CLI user can indicate which format to use with the `-f, --format` option. The CLI help text has been amended to reflect the new feature. The AWX CLI `export` subcommand offers the option of formatting the output as YAML or JSON, so it makes sense that the `import` subcommand reflects this. A simple test is also provided. In order to ease the task of testing commands that import resources by reading the stdin, the CLI has been extended to allow specifying an alternative file descriptor for stdin, similarly to stdout and stderr. --- awxkit/awxkit/cli/client.py | 3 ++- awxkit/awxkit/cli/format.py | 4 ++-- awxkit/awxkit/cli/resource.py | 11 +++++++++-- awxkit/test/cli/test_format.py | 26 ++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/awxkit/awxkit/cli/client.py b/awxkit/awxkit/cli/client.py index 8013523921..3feded89dc 100755 --- a/awxkit/awxkit/cli/client.py +++ b/awxkit/awxkit/cli/client.py @@ -70,9 +70,10 @@ class CLI(object): subparsers = {} original_action = None - def __init__(self, stdout=sys.stdout, stderr=sys.stderr): + def __init__(self, stdout=sys.stdout, stderr=sys.stderr, stdin=sys.stdin): self.stdout = stdout self.stderr = stderr + self.stdin = stdin def get_config(self, key): """Helper method for looking up the value of a --conf.xyz flag""" diff --git a/awxkit/awxkit/cli/format.py b/awxkit/awxkit/cli/format.py index e8c5a6903e..d35c61efbb 100644 --- a/awxkit/awxkit/cli/format.py +++ b/awxkit/awxkit/cli/format.py @@ -40,7 +40,7 @@ def add_authentication_arguments(parser, env): def add_output_formatting_arguments(parser, env): - formatting = parser.add_argument_group('output formatting') + formatting = parser.add_argument_group('input/output formatting') formatting.add_argument( '-f', @@ -49,7 +49,7 @@ def add_output_formatting_arguments(parser, env): choices=FORMATTERS.keys(), default=env.get('TOWER_FORMAT', 'json'), help=( - 'specify an output format' + 'specify a format for the input and output' ), ) formatting.add_argument( diff --git a/awxkit/awxkit/cli/resource.py b/awxkit/awxkit/cli/resource.py index f22795fab2..0f9f24dbae 100644 --- a/awxkit/awxkit/cli/resource.py +++ b/awxkit/awxkit/cli/resource.py @@ -1,8 +1,9 @@ +import yaml import json import os -import sys from awxkit import api, config +from awxkit.exceptions import ImportExportError from awxkit.utils import to_str from awxkit.api.pages import Page from awxkit.api.pages.api import EXPORTABLE_RESOURCES @@ -135,7 +136,13 @@ class Import(CustomCommand): parser.print_help() raise SystemExit() - data = json.load(sys.stdin) + format = getattr(client.args, 'conf.format') + if format == 'json': + data = json.load(client.stdin) + elif format == 'yaml': + data = yaml.safe_load(client.stdin) + else: + raise ImportExportError("Unsupported format for Import: " + format) client.authenticate() client.v2.import_assets(data) diff --git a/awxkit/test/cli/test_format.py b/awxkit/test/cli/test_format.py index 7166fb841c..5ab6e55d6c 100644 --- a/awxkit/test/cli/test_format.py +++ b/awxkit/test/cli/test_format.py @@ -1,10 +1,13 @@ +import io import json import yaml from awxkit.api.pages import Page from awxkit.api.pages.users import Users, User +from awxkit.cli import CLI from awxkit.cli.format import format_response +from awxkit.cli.resource import Import def test_json_empty_list(): @@ -44,3 +47,26 @@ def test_yaml_list(): page = Users.from_json(users) formatted = format_response(page, fmt='yaml') assert yaml.safe_load(formatted) == users + + +def test_yaml_import(): + class MockedV2: + def import_assets(self, data): + self._parsed_data = data + + def _dummy_authenticate(): + pass + + yaml_fd = io.StringIO( + """ + workflow_job_templates: + - name: Workflow1 + """ + ) + cli = CLI(stdin=yaml_fd) + cli.parse_args(['--conf.format', 'yaml']) + cli.v2 = MockedV2() + cli.authenticate = _dummy_authenticate + + Import().handle(cli, None) + assert cli.v2._parsed_data['workflow_job_templates'][0]['name']