From fe454d27a1aa5386801563ffe8dde44064f84302 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 4 Feb 2020 16:14:55 +0100 Subject: [PATCH] Fix removed_in_version to support honor suboptions (#66918) * Add unit tests. * Fix reporting for removed_in_version. * Add changelog. --- .../66918-removed_in_version-fix.yml | 2 ++ lib/ansible/module_utils/basic.py | 4 +-- lib/ansible/module_utils/common/parameters.py | 27 ++++++++++++++----- .../parameters/test_list_deprecations.py | 17 +++++++++--- 4 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 changelogs/fragments/66918-removed_in_version-fix.yml diff --git a/changelogs/fragments/66918-removed_in_version-fix.yml b/changelogs/fragments/66918-removed_in_version-fix.yml new file mode 100644 index 00000000000..5ee244785fb --- /dev/null +++ b/changelogs/fragments/66918-removed_in_version-fix.yml @@ -0,0 +1,2 @@ +bugfixes: +- "Module arguments in suboptions which were marked as deprecated with ``removed_in_version`` did not result in a warning." diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index e55ac189db4..2dad5f49837 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -1428,8 +1428,8 @@ class AnsibleModule(object): self.fail_json(msg="Failure when processing no_log parameters. Module invocation will be hidden. " "%s" % to_native(te), invocation={'module_args': 'HIDDEN DUE TO FAILURE'}) - for msg, version in list_deprecations(spec, param): - deprecate(msg, version) + for message in list_deprecations(spec, param): + deprecate(message['msg'], message['version']) def _check_arguments(self, spec=None, param=None, legal_inputs=None): self._syslog_facility = 'LOG_USER' diff --git a/lib/ansible/module_utils/common/parameters.py b/lib/ansible/module_utils/common/parameters.py index 9b41bc724af..f9991391aa6 100644 --- a/lib/ansible/module_utils/common/parameters.py +++ b/lib/ansible/module_utils/common/parameters.py @@ -115,7 +115,7 @@ def list_no_log_values(argument_spec, params): return no_log_values -def list_deprecations(argument_spec, params): +def list_deprecations(argument_spec, params, prefix=''): """Return a list of deprecations :arg argument_spec: An argument spec dictionary from a module @@ -129,11 +129,26 @@ def list_deprecations(argument_spec, params): deprecations = [] for arg_name, arg_opts in argument_spec.items(): - if arg_opts.get('removed_in_version') is not None and arg_name in params: - deprecations.append({ - 'msg': "Param '%s' is deprecated. See the module docs for more information" % arg_name, - 'version': arg_opts.get('removed_in_version') - }) + if arg_name in params: + if prefix: + sub_prefix = '%s["%s"]' % (prefix, arg_name) + else: + sub_prefix = arg_name + if arg_opts.get('removed_in_version') is not None: + deprecations.append({ + 'msg': "Param '%s' is deprecated. See the module docs for more information" % sub_prefix, + 'version': arg_opts.get('removed_in_version') + }) + # Check sub-argument spec + sub_argument_spec = arg_opts.get('options') + if sub_argument_spec is not None: + sub_arguments = params[arg_name] + if isinstance(sub_arguments, Mapping): + sub_arguments = [sub_arguments] + if isinstance(sub_arguments, list): + for sub_params in sub_arguments: + if isinstance(sub_params, Mapping): + deprecations.extend(list_deprecations(sub_argument_spec, sub_params, prefix=sub_prefix)) return deprecations diff --git a/test/units/module_utils/common/parameters/test_list_deprecations.py b/test/units/module_utils/common/parameters/test_list_deprecations.py index 6a335a23d77..0a17187c041 100644 --- a/test/units/module_utils/common/parameters/test_list_deprecations.py +++ b/test/units/module_utils/common/parameters/test_list_deprecations.py @@ -22,14 +22,23 @@ def params(): def test_list_deprecations(): argument_spec = { - 'old': {'type': 'str', 'removed_in_version': '2.5'} + 'old': {'type': 'str', 'removed_in_version': '2.5'}, + 'foo': {'type': 'dict', 'options': {'old': {'type': 'str', 'removed_in_version': 1.0}}}, + 'bar': {'type': 'list', 'elements': 'dict', 'options': {'old': {'type': 'str', 'removed_in_version': '2.10'}}}, } params = { 'name': 'rod', 'old': 'option', + 'foo': {'old': 'value'}, + 'bar': [{'old': 'value'}, {}], } result = list_deprecations(argument_spec, params) - for item in result: - assert item['msg'] == "Param 'old' is deprecated. See the module docs for more information" - assert item['version'] == '2.5' + assert len(result) == 3 + result.sort(key=lambda entry: entry['msg']) + assert result[0]['msg'] == """Param 'bar["old"]' is deprecated. See the module docs for more information""" + assert result[0]['version'] == '2.10' + assert result[1]['msg'] == """Param 'foo["old"]' is deprecated. See the module docs for more information""" + assert result[1]['version'] == 1.0 + assert result[2]['msg'] == "Param 'old' is deprecated. See the module docs for more information" + assert result[2]['version'] == '2.5'