-
Notifications
You must be signed in to change notification settings - Fork 24k
Avoid internal error when validating argspec #81631
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: devel
Are you sure you want to change the base?
Conversation
@@ -838,6 +838,9 @@ def env_fallback(*args, **kwargs): | |||
|
|||
def set_fallbacks(argument_spec, parameters): | |||
no_log_values = set() | |||
if not isinstance(parameters, Mapping): | |||
# The wrong type is handled somewhere else | |||
return no_log_values |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be silently ignored. It should be an error at "somewhere else" or here directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should raise a TypeError
if any of the arguments is invalid. But yeah, the input validation must happen in the outer layer, in the calling code somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually the caller checked for the right type, but only after calling this function. I've switched the order.
The reason that CI fails is that the last task in the
That no longer happens since this PR fixes that crash, now it results in
which contains the secret value |
The reason why I'll push a change that disables the broken test once CI completes. This should be fixed in another PR. If you want to keep the double type checking with raising |
when: false # TODO FIXME: The code that should prevent 'AGROUND' ending up in the output | ||
# has been broken for some time; its misbehavior was masked by | ||
# the bug fixed in https://github.com/ansible/ansible/pull/81631. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the underlying bug is in the outer validate
method with how we use _list_no_log_values
. An error anywhere in the spec prevents marking any of the options as no_log (and we stop at the first error). Maybe we could accumulate the errors non-fatally the first time.
diff --git a/lib/ansible/module_utils/common/arg_spec.py b/lib/ansible/module_utils/common/arg_spec.py
index d9f716efce..44548c71ec 100644
--- a/lib/ansible/module_utils/common/arg_spec.py
+++ b/lib/ansible/module_utils/common/arg_spec.py
@@ -201,10 +201,10 @@ class ArgumentSpecValidator:
'collection_name': deprecation.get('collection_name'),
})
- try:
- result._no_log_values.update(_list_no_log_values(self.argument_spec, result._validated_parameters))
- except TypeError as te:
- result.errors.append(NoLogError(to_native(te)))
+ no_log_introspection_errors = []
+ result._no_log_values.update(_list_no_log_values(self.argument_spec, result._validated_parameters, no_log_introspection_errors))
+ for error in no_log_introspection_errors:
+ result.errors.append(NoLogError(error))
try:
result._deprecations.extend(_list_deprecations(self.argument_spec, result._validated_parameters))
diff --git a/lib/ansible/module_utils/common/parameters.py b/lib/ansible/module_utils/common/parameters.py
index 386eb875ce..4e146683c5 100644
--- a/lib/ansible/module_utils/common/parameters.py
+++ b/lib/ansible/module_utils/common/parameters.py
@@ -305,7 +305,7 @@ def _list_deprecations(argument_spec, parameters, prefix=''):
return deprecations
-def _list_no_log_values(argument_spec, params):
+def _list_no_log_values(argument_spec, params, errors=None):
"""Return set of no log values
:arg argument_spec: An argument spec dictionary
@@ -324,6 +324,9 @@ def _list_no_log_values(argument_spec, params):
try:
no_log_values.update(_return_datastructure_name(no_log_object))
except TypeError as e:
+ if errors is not None:
+ errors.append('Failed to convert "%s": %s' % (arg_name, to_native(e)))
+ continue
raise TypeError('Failed to convert "%s": %s' % (arg_name, to_native(e)))
# Get no_log values from suboptions
@@ -342,9 +345,19 @@ def _list_no_log_values(argument_spec, params):
@@ -342,9 +345,19 @@ def _list_no_log_values(argument_spec, params):
# Validate dict fields in case they came in as strings
if isinstance(sub_param, string_types):
- sub_param = check_type_dict(sub_param)
+ try:
+ sub_param = check_type_dict(sub_param)
+ except TypeError as e:
+ if errors is not None:
+ errors.append(to_native(e))
+ continue
+ raise
if not isinstance(sub_param, Mapping):
+ if errors is not None:
+ errors.append("Value '{1}' in the sub parameter field '{0}' must by a {2}, "
+ "not '{1.__class__.__name__}'".format(arg_name, sub_param, wanted_type))
+ continue
raise TypeError("Value '{1}' in the sub parameter field '{0}' must by a {2}, "
"not '{1.__class__.__name__}'".format(arg_name, sub_param, wanted_type))
We also call _list_no_log_values
in _validate_sub_spec
, but since _list_no_log_values
is recursive I don't think that's necessary if the outer scope is fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#81672 contains a slightly modified version of your patch.
I think we should fix that first then. |
2.18 task- there are several related things that could use some attention, and some we've already fixed in other branches |
SUMMARY
Reported in ansible-collections/community.docker#680.
When passing a boolean or number to a parameter that expects a dictionary, there is an exception in the fallback handling since it assumes that the value is a dictionary.
Fixes this and adds a regression test.
ISSUE TYPE