From d05ad6b1f27a4ce6be32c123e51ee9b978376fe2 Mon Sep 17 00:00:00 2001 From: Thomas Woerner Date: Tue, 22 Feb 2022 14:27:16 +0100 Subject: [PATCH] module_params_get*: Fail on empty string in string list parameters So far it is possible to pass list parameters with empty strings to the modules. The use of empty strings in list does not make a lot of sense, though. The simple solution is to add a check to module_params_get for empty strings in returned lists. The option allow_empty_string can be set to True to allow an empty string in the list with a list len of 1. The option defaults to False. It is needed for some parameters the modules, like for example userauthtype in the user module. It is using "" to reset to the default value. module_params_get_lowercase has been changed to use module_params_get to have one place to add the check. Due to an issue in Ansible it is possible to use the empty string "" for lists with choices, even if the empty list is not part of the choices. Ansible issue https://github.com/ansible/ansible/issues/77108 --- .../module_utils/ansible_freeipa_module.py | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py index 3c25c795..17d02d0e 100644 --- a/plugins/module_utils/ansible_freeipa_module.py +++ b/plugins/module_utils/ansible_freeipa_module.py @@ -398,11 +398,32 @@ else: return value - def module_params_get(module, name): - return _afm_convert(module.params.get(name)) - - def module_params_get_lowercase(module, name): + def module_params_get(module, name, allow_empty_string=False): value = _afm_convert(module.params.get(name)) + + # Fail on empty strings in the list or if allow_empty_string is True + # if there is another entry in the list together with the empty + # string. + # Due to an issue in Ansible it is possible to use the empty string + # "" for lists with choices, even if the empty list is not part of + # the choices. + # Ansible issue https://github.com/ansible/ansible/issues/77108 + if isinstance(value, list): + for val in value: + if isinstance(val, (str, unicode)) and not val: + if not allow_empty_string: + module.fail_json( + msg="Parameter '%s' contains an empty string" % + name) + elif len(value) > 1: + module.fail_json( + msg="Parameter '%s' may not contain another " + "entry together with an empty string" % name) + + return value + + def module_params_get_lowercase(module, name, allow_empty_string=False): + value = module_params_get(module, name, allow_empty_string) if isinstance(value, list): value = [v.lower() for v in value] if isinstance(value, (str, unicode)): @@ -897,7 +918,7 @@ else: finally: temp_kdestroy(ccache_dir, ccache_name) - def params_get(self, name): + def params_get(self, name, allow_empty_string=False): """ Retrieve value set for module parameter. @@ -905,11 +926,13 @@ else: ---------- name: string The name of the parameter to retrieve. + allow_empty_string: bool + The parameter allowes to have empty strings in a list """ - return module_params_get(self, name) + return module_params_get(self, name, allow_empty_string) - def params_get_lowercase(self, name): + def params_get_lowercase(self, name, allow_empty_string=False): """ Retrieve value set for module parameter as lowercase, if not None. @@ -917,9 +940,11 @@ else: ---------- name: string The name of the parameter to retrieve. + allow_empty_string: bool + The parameter allowes to have empty strings in a list """ - return module_params_get_lowercase(self, name) + return module_params_get_lowercase(self, name, allow_empty_string) def params_fail_used_invalid(self, invalid_params, state, action=None): """