From 1b947eaf92b6833d2a4fd019a30d7b85406f1778 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Thu, 21 Apr 2022 15:06:31 -0400 Subject: [PATCH] arg_spec - Return aliases in validation result and update aliases (#77576) When looking up the `no_log` setting for a parameter that is an alias in `AnsibleModule._log_invocation()`, the alias value will always be an empty dictionary since `self.aliases` on the `AnsibleModule` instance is never updated after initialization. Since the `no_log` setting is on the canonical parameter not the alias, an incorrect warning is issued if the parameter matches `PASSWORD_MATCH`. This PR returns the aliases dictionary as an attribute of the `ValidationResult` and updates the `aliases` attribute on the `AnsibleModule` instance. --- .../fragments/77576-arg_spec-no_log-aliases.yml | 2 ++ lib/ansible/module_utils/basic.py | 1 + lib/ansible/module_utils/common/arg_spec.py | 6 +++--- test/units/module_utils/basic/test_argument_spec.py | 13 +++++++++++++ .../module_utils/common/arg_spec/test_aliases.py | 5 +++++ 5 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/77576-arg_spec-no_log-aliases.yml diff --git a/changelogs/fragments/77576-arg_spec-no_log-aliases.yml b/changelogs/fragments/77576-arg_spec-no_log-aliases.yml new file mode 100644 index 00000000000..4dfce34cbb7 --- /dev/null +++ b/changelogs/fragments/77576-arg_spec-no_log-aliases.yml @@ -0,0 +1,2 @@ +bugfixes: + - arg_spec - Fix incorrect ``no_log`` warning when a parameter alias is used (https://github.com/ansible/ansible/pull/77576) diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index 17fcf94ee00..331ca924025 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -502,6 +502,7 @@ class AnsibleModule(object): self.validation_result = self.validator.validate(self.params) self.params.update(self.validation_result.validated_parameters) self.no_log_values.update(self.validation_result._no_log_values) + self.aliases.update(self.validation_result._aliases) try: error = self.validation_result.errors[0] diff --git a/lib/ansible/module_utils/common/arg_spec.py b/lib/ansible/module_utils/common/arg_spec.py index d3846659c79..9fa2b4d2c9a 100644 --- a/lib/ansible/module_utils/common/arg_spec.py +++ b/lib/ansible/module_utils/common/arg_spec.py @@ -61,6 +61,7 @@ class ValidationResult: self._validated_parameters = deepcopy(parameters) self._deprecations = [] self._warnings = [] + self._aliases = {} self.errors = AnsibleValidationErrorMultiple() """ :class:`~ansible.module_utils.errors.AnsibleValidationErrorMultiple` containing all @@ -180,12 +181,11 @@ class ArgumentSpecValidator: alias_warnings = [] alias_deprecations = [] try: - aliases = _handle_aliases(self.argument_spec, result._validated_parameters, alias_warnings, alias_deprecations) + result._aliases.update(_handle_aliases(self.argument_spec, result._validated_parameters, alias_warnings, alias_deprecations)) except (TypeError, ValueError) as e: - aliases = {} result.errors.append(AliasError(to_native(e))) - legal_inputs = _get_legal_inputs(self.argument_spec, result._validated_parameters, aliases) + legal_inputs = _get_legal_inputs(self.argument_spec, result._validated_parameters, result._aliases) for option, alias in alias_warnings: result._warnings.append({'option': option, 'alias': alias}) diff --git a/test/units/module_utils/basic/test_argument_spec.py b/test/units/module_utils/basic/test_argument_spec.py index 48b05ec4a9c..20bfb01eac1 100644 --- a/test/units/module_utils/basic/test_argument_spec.py +++ b/test/units/module_utils/basic/test_argument_spec.py @@ -709,3 +709,16 @@ def test_no_log_none(stdin, capfd): # makes it into am.no_log_values. Instead we can check for the warning # emitted by am._log_invocation. assert len(get_warning_messages()) > 0 + + +@pytest.mark.parametrize("stdin", [{"pass": "testing"}], indirect=["stdin"]) +def test_no_log_alias(stdin, capfd): + """Given module parameters that use an alias for a parameter that matches + PASSWORD_MATCH and has no_log=True set, a warning should not be issued. + """ + arg_spec = { + "other_pass": {"no_log": True, "aliases": ["pass"]}, + } + am = basic.AnsibleModule(arg_spec) + + assert len(get_warning_messages()) == 0 diff --git a/test/units/module_utils/common/arg_spec/test_aliases.py b/test/units/module_utils/common/arg_spec/test_aliases.py index f4c96c74e53..1c1e243a7b1 100644 --- a/test/units/module_utils/common/arg_spec/test_aliases.py +++ b/test/units/module_utils/common/arg_spec/test_aliases.py @@ -95,6 +95,11 @@ def test_aliases(arg_spec, parameters, expected, deprecation, warning): assert isinstance(result, ValidationResult) assert result.validated_parameters == expected assert result.error_messages == [] + assert result._aliases == { + alias: param + for param, value in arg_spec.items() + for alias in value.get("aliases", []) + } if deprecation: assert deprecation == result._deprecations[0]