diff options
author | Sloane Hertel <19572925+s-hertel@users.noreply.github.com> | 2021-11-24 13:09:10 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-24 10:09:10 -0800 |
commit | 2556e330771cfdce5491330638143837f5864524 (patch) | |
tree | a116e33bbc7fdfc45f0c7d8e014fd9ce15d00e4c | |
parent | 8e8c4be23f5f0415662de9f1a21096fa7a7400aa (diff) | |
download | ansible-2556e330771cfdce5491330638143837f5864524.tar.gz |
Skip recursive suboption validation if sub_parameters is not a dict (#75635) (#76190)
* Skip recursive suboption validation if sub_parameters is not a dictionary
* Ensure sub parameter elements is a sequence to prevent iterating over string characters and causing duplicate error messages for the same param
(cherry picked from commit b5ed41edb34a387c560e172ee2928cc8ac9b4959)
4 files changed, 16 insertions, 4 deletions
diff --git a/changelogs/fragments/75635-fix-role-argspec-suboption-validation.yml b/changelogs/fragments/75635-fix-role-argspec-suboption-validation.yml new file mode 100644 index 0000000000..981f2548c3 --- /dev/null +++ b/changelogs/fragments/75635-fix-role-argspec-suboption-validation.yml @@ -0,0 +1,2 @@ +bugfixes: + - validate_argument_spec - Skip suboption validation if the top level option is an invalid type (https://github.com/ansible/ansible/issues/75612). diff --git a/lib/ansible/module_utils/common/parameters.py b/lib/ansible/module_utils/common/parameters.py index 2624bb5092..8bba4d5f32 100644 --- a/lib/ansible/module_utils/common/parameters.py +++ b/lib/ansible/module_utils/common/parameters.py @@ -724,14 +724,17 @@ def _validate_sub_spec(argument_spec, parameters, prefix='', options_context=Non options_context.append(param) # Make sure we can iterate over the elements - if isinstance(parameters[param], dict): + if not isinstance(parameters[param], Sequence) or isinstance(parameters[param], string_types): elements = [parameters[param]] else: elements = parameters[param] for idx, sub_parameters in enumerate(elements): + no_log_values.update(set_fallbacks(sub_spec, sub_parameters)) + if not isinstance(sub_parameters, dict): errors.append(SubParameterTypeError("value of '%s' must be of type dict or list of dicts" % param)) + continue # Set prefix for warning messages new_prefix = prefix + param @@ -739,8 +742,6 @@ def _validate_sub_spec(argument_spec, parameters, prefix='', options_context=Non new_prefix += '[%d]' % idx new_prefix += '.' - no_log_values.update(set_fallbacks(sub_spec, sub_parameters)) - alias_warnings = [] alias_deprecations = [] try: diff --git a/test/integration/targets/roles_arg_spec/roles/test1/meta/argument_specs.yml b/test/integration/targets/roles_arg_spec/roles/test1/meta/argument_specs.yml index 02edac6606..427946e538 100644 --- a/test/integration/targets/roles_arg_spec/roles/test1/meta/argument_specs.yml +++ b/test/integration/targets/roles_arg_spec/roles/test1/meta/argument_specs.yml @@ -73,6 +73,11 @@ argument_specs: some_second_level: type: "bool" default: true + some_more_dict_options: + type: "dict" + options: + some_second_level: + type: "str" some_str_removed_in: type: "str" removed_in: 2.10 diff --git a/test/integration/targets/roles_arg_spec/test_complex_role_fails.yml b/test/integration/targets/roles_arg_spec/test_complex_role_fails.yml index a04785fb12..923e92f719 100644 --- a/test/integration/targets/roles_arg_spec/test_complex_role_fails.yml +++ b/test/integration/targets/roles_arg_spec/test_complex_role_fails.yml @@ -34,7 +34,10 @@ "value of test1_choices must be one of: this paddle game, the astray, this remote control, the chair, got: My dog", "value of some_choices must be one of: choice1, choice2, got: choice4", "argument 'some_second_level' is of type <class 'ansible.parsing.yaml.objects.AnsibleUnicode'> found in 'some_dict_options'. and we were unable to convert to bool: The value 'not-a-bool' is not a valid boolean. ", - "argument 'third_level' is of type <class 'ansible.parsing.yaml.objects.AnsibleUnicode'> found in 'multi_level_option -> second_level'. and we were unable to convert to int: <class 'ansible.parsing.yaml.objects.AnsibleUnicode'> cannot be converted to an int" + "argument 'third_level' is of type <class 'ansible.parsing.yaml.objects.AnsibleUnicode'> found in 'multi_level_option -> second_level'. and we were unable to convert to int: <class 'ansible.parsing.yaml.objects.AnsibleUnicode'> cannot be converted to an int", + "argument 'some_more_dict_options' is of type <class 'ansible.parsing.yaml.objects.AnsibleUnicode'> and we were unable to convert to dict: dictionary requested, could not parse JSON or key=value", + "value of 'some_more_dict_options' must be of type dict or list of dicts", + "dictionary requested, could not parse JSON or key=value", ] tasks: @@ -86,6 +89,7 @@ some_str_removed_in: "foo" some_dict_options: some_second_level: "not-a-bool" + some_more_dict_options: "not-a-dict" multi_level_option: second_level: third_level: "should_be_int" |