From 1a47a21b65d3746a9feeeceea0cf15eaf011efef Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 13 Jan 2023 22:55:48 +0100 Subject: [PATCH] Fix reporting of deprecated arguments for modules. (#79681) --- .../79681-argspec-param-deprecation.yml | 2 + lib/ansible/module_utils/common/arg_spec.py | 18 ++++++-- lib/ansible/module_utils/errors.py | 4 ++ .../targets/argspec/library/argspec.py | 29 ++++++++++++ .../targets/argspec/tasks/main.yml | 45 +++++++++++++++++++ 5 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/79681-argspec-param-deprecation.yml diff --git a/changelogs/fragments/79681-argspec-param-deprecation.yml b/changelogs/fragments/79681-argspec-param-deprecation.yml new file mode 100644 index 00000000000..ac19a47a168 --- /dev/null +++ b/changelogs/fragments/79681-argspec-param-deprecation.yml @@ -0,0 +1,2 @@ +bugfixes: + - "argument spec validation - again report deprecated parameters for Python-based modules. This was accidentally removed in ansible-core 2.11 when argument spec validation was refactored (https://github.com/ansible/ansible/issues/79680, https://github.com/ansible/ansible/pull/79681)." diff --git a/lib/ansible/module_utils/common/arg_spec.py b/lib/ansible/module_utils/common/arg_spec.py index 237279d0456..176268d096f 100644 --- a/lib/ansible/module_utils/common/arg_spec.py +++ b/lib/ansible/module_utils/common/arg_spec.py @@ -12,6 +12,7 @@ from ansible.module_utils.common.parameters import ( _get_legal_inputs, _get_unsupported_parameters, _handle_aliases, + _list_deprecations, _list_no_log_values, _set_defaults, _validate_argument_types, @@ -31,6 +32,7 @@ from ansible.module_utils.common.validation import ( from ansible.module_utils.errors import ( AliasError, AnsibleValidationErrorMultiple, + DeprecationError, MutuallyExclusiveError, NoLogError, RequiredDefaultError, @@ -204,6 +206,11 @@ class ArgumentSpecValidator: except TypeError as te: result.errors.append(NoLogError(to_native(te))) + try: + result._deprecations.extend(_list_deprecations(self.argument_spec, result._validated_parameters)) + except TypeError as te: + result.errors.append(DeprecationError(to_native(te))) + try: result._unsupported_parameters.update( _get_unsupported_parameters( @@ -285,9 +292,14 @@ class ModuleArgumentSpecValidator(ArgumentSpecValidator): result = super(ModuleArgumentSpecValidator, self).validate(parameters) for d in result._deprecations: - deprecate("Alias '{name}' is deprecated. See the module docs for more information".format(name=d['name']), - version=d.get('version'), date=d.get('date'), - collection_name=d.get('collection_name')) + if 'name' in d: + deprecate("Alias '{name}' is deprecated. See the module docs for more information".format(name=d['name']), + version=d.get('version'), date=d.get('date'), + collection_name=d.get('collection_name')) + if 'msg' in d: + deprecate(d['msg'], + version=d.get('version'), date=d.get('date'), + collection_name=d.get('collection_name')) for w in result._warnings: warn('Both option {option} and its alias {alias} are set.'.format(option=w['option'], alias=w['alias'])) diff --git a/lib/ansible/module_utils/errors.py b/lib/ansible/module_utils/errors.py index 3274b85b632..cbbd86c01cb 100644 --- a/lib/ansible/module_utils/errors.py +++ b/lib/ansible/module_utils/errors.py @@ -75,6 +75,10 @@ class ArgumentValueError(AnsibleValidationError): """Error with parameter value""" +class DeprecationError(AnsibleValidationError): + """Error processing parameter deprecations""" + + class ElementError(AnsibleValidationError): """Error when validating elements""" diff --git a/test/integration/targets/argspec/library/argspec.py b/test/integration/targets/argspec/library/argspec.py index 1a1d288d238..2f24bb7492e 100644 --- a/test/integration/targets/argspec/library/argspec.py +++ b/test/integration/targets/argspec/library/argspec.py @@ -139,6 +139,35 @@ def main(): }, }, }, + 'deprecation_aliases': { + 'type': 'str', + 'aliases': [ + 'deprecation_aliases_version', + 'deprecation_aliases_date', + ], + 'deprecated_aliases': [ + { + 'name': 'deprecation_aliases_version', + 'version': '2.0.0', + 'collection_name': 'foo.bar', + }, + { + 'name': 'deprecation_aliases_date', + 'date': '2023-01-01', + 'collection_name': 'foo.bar', + }, + ], + }, + 'deprecation_param_version': { + 'type': 'str', + 'removed_in_version': '2.0.0', + 'removed_from_collection': 'foo.bar', + }, + 'deprecation_param_date': { + 'type': 'str', + 'removed_at_date': '2023-01-01', + 'removed_from_collection': 'foo.bar', + }, }, required_if=( ('state', 'present', ('path', 'content'), True), diff --git a/test/integration/targets/argspec/tasks/main.yml b/test/integration/targets/argspec/tasks/main.yml index 283c922d789..a00d33d7aba 100644 --- a/test/integration/targets/argspec/tasks/main.yml +++ b/test/integration/targets/argspec/tasks/main.yml @@ -366,6 +366,30 @@ foo: bar register: argspec_apply_defaults_one +- argspec: + required: value + required_one_of_one: value + deprecation_aliases_version: value + register: deprecation_alias_version + +- argspec: + required: value + required_one_of_one: value + deprecation_aliases_date: value + register: deprecation_alias_date + +- argspec: + required: value + required_one_of_one: value + deprecation_param_version: value + register: deprecation_param_version + +- argspec: + required: value + required_one_of_one: value + deprecation_param_date: value + register: deprecation_param_date + - assert: that: - argspec_required_fail is failed @@ -446,3 +470,24 @@ - "argspec_apply_defaults_none.apply_defaults == {'foo': none, 'bar': 'baz'}" - "argspec_apply_defaults_empty.apply_defaults == {'foo': none, 'bar': 'baz'}" - "argspec_apply_defaults_one.apply_defaults == {'foo': 'bar', 'bar': 'baz'}" + + - deprecation_alias_version.deprecations | length == 1 + - deprecation_alias_version.deprecations[0].msg == "Alias 'deprecation_aliases_version' is deprecated. See the module docs for more information" + - deprecation_alias_version.deprecations[0].collection_name == 'foo.bar' + - deprecation_alias_version.deprecations[0].version == '2.0.0' + - "'date' not in deprecation_alias_version.deprecations[0]" + - deprecation_alias_date.deprecations | length == 1 + - deprecation_alias_date.deprecations[0].msg == "Alias 'deprecation_aliases_date' is deprecated. See the module docs for more information" + - deprecation_alias_date.deprecations[0].collection_name == 'foo.bar' + - deprecation_alias_date.deprecations[0].date == '2023-01-01' + - "'version' not in deprecation_alias_date.deprecations[0]" + - deprecation_param_version.deprecations | length == 1 + - deprecation_param_version.deprecations[0].msg == "Param 'deprecation_param_version' is deprecated. See the module docs for more information" + - deprecation_param_version.deprecations[0].collection_name == 'foo.bar' + - deprecation_param_version.deprecations[0].version == '2.0.0' + - "'date' not in deprecation_param_version.deprecations[0]" + - deprecation_param_date.deprecations | length == 1 + - deprecation_param_date.deprecations[0].msg == "Param 'deprecation_param_date' is deprecated. See the module docs for more information" + - deprecation_param_date.deprecations[0].collection_name == 'foo.bar' + - deprecation_param_date.deprecations[0].date == '2023-01-01' + - "'version' not in deprecation_param_date.deprecations[0]"