Skip recursive suboption validation if sub_parameters is not a dict (#75635)

* 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
This commit is contained in:
Sloane Hertel 2021-11-01 12:06:49 -04:00 committed by GitHub
parent 7bec196061
commit b5ed41edb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 16 additions and 4 deletions

View File

@ -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).

View File

@ -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:

View File

@ -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

View File

@ -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:
@ -76,6 +79,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"