Patrick,
Thanks for reaching out on the mailing list. We came across that issue during our biweekly triage meeting where we don’t have time to respond in detail since we are just trying to evaluate all the issues in the queue.
The first problem with allowing arbitrary keys in the argument spec is it goes against the intention of how argument spec validation in Ansible is designed to work. Namely, for each key specified, run the value through check_type_[something] to validate and coerce the data to the correct type.
Argument spec validation in Ansible is not meant to be a generic schema validation mechanism, but rather a somewhat strict input validation system that provides a stable set of defined variables a module can depend on as input. Argument spec validation takes care of defining all parameters in the spec to at least a value of None or provides a default value if specified.
As you pointed out, allowing arbitrary keys means we also need to have a system for handling those. If we allow arbitrary keys and assume the default type (raw) they would pass validation, but may contain completely incorrect data (check_type_raw just returns the passed in value).
To do this properly, we would have add features to the argument spec to allow for setting the default intended type, or some other behavior, so the appropriate checker can be selected for keys that are not explicitly declared. Adding toggles that change behavior is a pattern I try to avoid (“‘type’: ‘dict’ sometimes allow arbitrary keys, but sometimes doesn’t, depending on if have the ‘allow_undefined_keys=True’ parameter set and don’t forget to also set 'default_type_for_undefined_params=‘str’” as a hypothetical example).
This would also allow bogus data in, such as key names with typos. This could confuse and frustrate the user when the modules/role passes validation but they later see errors for undefined variables or default values being used when they thought they had specified a value.
I’m sure there are probably some issues with setting defaults and possibly aliases as well. Most of the challenges would be in _validate_argument_values(), _validate_argument_types(), or _validate_sub_spec().
While it is possible to change argument spec validation to allow arbitrary keys for dictionaries (anything is possible in software), it goes against the design intention of the feature in Ansible and would most likely have a lot of odd ripple effects both in the implementation and in bugs it would introduce.
A better way to get close to accomplishing what you want would be to use ‘type’: ‘list’ with ‘elements’: ‘dict’, as mentioned in the issue. You would have to change the input data from a dict to a list, but it would allow validation of the structure of each element in the list and avoid the problem of arbitrary keys in a dictionary.
{
‘users’: {
‘type’: ‘list’,
‘elements’: ‘dict’,
‘options’: {
‘name’: {‘type’: ‘str’, ‘required’: True},
‘id’: {‘type’: ‘int’},
‘home’: {‘type’: ‘path’, ‘required’: True},
}
},
}