diff --git a/changelogs/fragments/2024-module-helper-fixes.yml b/changelogs/fragments/2024-module-helper-fixes.yml new file mode 100644 index 0000000000..3ce3cc71dc --- /dev/null +++ b/changelogs/fragments/2024-module-helper-fixes.yml @@ -0,0 +1,4 @@ +bugfixes: + - module_helper module utils - actually ignoring formatting of parameters with value ``None`` (https://github.com/ansible-collections/community.general/pull/2024). + - module_helper module utils - handling ``ModuleHelperException`` now properly calls ``fail_json()`` (https://github.com/ansible-collections/community.general/pull/2024). + - module_helper module utils - use the command name as-is in ``CmdMixin`` if it fails ``get_bin_path()`` - allowing full path names to be passed (https://github.com/ansible-collections/community.general/pull/2024). diff --git a/plugins/module_utils/module_helper.py b/plugins/module_utils/module_helper.py index 3d145e713e..caf915abbf 100644 --- a/plugins/module_utils/module_helper.py +++ b/plugins/module_utils/module_helper.py @@ -93,6 +93,8 @@ class ArgFormat(object): self.arg_format = (self.stars_deco(stars))(self.arg_format) def to_text(self, value): + if value is None: + return [] func = self.arg_format return [str(p) for p in func(value)] @@ -121,6 +123,7 @@ def module_fails_on_exception(func): except ModuleHelperException as e: if e.update_output: self.update_output(e.update_output) + self.module.fail_json(changed=False, msg=e.msg, exception=traceback.format_exc(), output=self.output, vars=self.vars) except Exception as e: self.vars.msg = "Module failed with exception: {0}".format(str(e).strip()) self.vars.exception = traceback.format_exc() @@ -292,7 +295,10 @@ class CmdMixin(object): extra_params = extra_params or dict() cmd_args = list([self.command]) if isinstance(self.command, str) else list(self.command) - cmd_args[0] = self.module.get_bin_path(cmd_args[0]) + try: + cmd_args[0] = self.module.get_bin_path(cmd_args[0], required=True) + except ValueError: + pass param_list = params if params else self.module.params.keys() for param in param_list: diff --git a/tests/unit/plugins/module_utils/test_module_helper.py b/tests/unit/plugins/module_utils/test_module_helper.py index fb7746a91a..82a8f2c144 100644 --- a/tests/unit/plugins/module_utils/test_module_helper.py +++ b/tests/unit/plugins/module_utils/test_module_helper.py @@ -22,24 +22,38 @@ ARG_FORMATS = dict( True, ["--superflag"]), simple_boolean_false=("--superflag", ArgFormat.BOOLEAN, 0, False, []), + simple_boolean_none=("--superflag", ArgFormat.BOOLEAN, 0, + None, []), single_printf=("--param=%s", ArgFormat.PRINTF, 0, "potatoes", ["--param=potatoes"]), single_printf_no_substitution=("--param", ArgFormat.PRINTF, 0, "potatoes", ["--param"]), + single_printf_none=("--param=%s", ArgFormat.PRINTF, 0, + None, []), multiple_printf=(["--param", "free-%s"], ArgFormat.PRINTF, 0, "potatoes", ["--param", "free-potatoes"]), single_format=("--param={0}", ArgFormat.FORMAT, 0, "potatoes", ["--param=potatoes"]), + single_format_none=("--param={0}", ArgFormat.FORMAT, 0, + None, []), single_format_no_substitution=("--param", ArgFormat.FORMAT, 0, "potatoes", ["--param"]), multiple_format=(["--param", "free-{0}"], ArgFormat.FORMAT, 0, "potatoes", ["--param", "free-potatoes"]), + multiple_format_none=(["--param", "free-{0}"], ArgFormat.FORMAT, 0, + None, []), single_lambda_0star=((lambda v: ["piggies=[{0},{1},{2}]".format(v[0], v[1], v[2])]), None, 0, ['a', 'b', 'c'], ["piggies=[a,b,c]"]), + single_lambda_0star_none=((lambda v: ["piggies=[{0},{1},{2}]".format(v[0], v[1], v[2])]), None, 0, + None, []), single_lambda_1star=((lambda a, b, c: ["piggies=[{0},{1},{2}]".format(a, b, c)]), None, 1, ['a', 'b', 'c'], ["piggies=[a,b,c]"]), + single_lambda_1star_none=((lambda a, b, c: ["piggies=[{0},{1},{2}]".format(a, b, c)]), None, 1, + None, []), single_lambda_2star=(single_lambda_2star, None, 2, - dict(z='c', x='a', y='b'), ["piggies=[a,b,c]"]) + dict(z='c', x='a', y='b'), ["piggies=[a,b,c]"]), + single_lambda_2star_none=(single_lambda_2star, None, 2, + None, []), ) ARG_FORMATS_IDS = sorted(ARG_FORMATS.keys())