diff --git a/changelogs/fragments/4736-cmd-runner-skip-if-check.yml b/changelogs/fragments/4736-cmd-runner-skip-if-check.yml new file mode 100644 index 0000000000..3c626b2feb --- /dev/null +++ b/changelogs/fragments/4736-cmd-runner-skip-if-check.yml @@ -0,0 +1,2 @@ +minor_changes: + - cmd_runner module util - added parameters ``check_mode_skip`` and ``check_mode_return`` to ``CmdRunner.context()``, so that the command is not executed when ``check_mode=True`` (https://github.com/ansible-collections/community.general/pull/4736). diff --git a/plugins/module_utils/cmd_runner.py b/plugins/module_utils/cmd_runner.py index 8048ed25ca..d154dbb7ee 100644 --- a/plugins/module_utils/cmd_runner.py +++ b/plugins/module_utils/cmd_runner.py @@ -197,7 +197,7 @@ class CmdRunner(object): if mod_param_name not in self.arg_formats: self.arg_formats[mod_param_name] = _Format.as_default_type(spec['type'], mod_param_name) - def context(self, args_order=None, output_process=None, ignore_value_none=True, **kwargs): + def context(self, args_order=None, output_process=None, ignore_value_none=True, check_mode_skip=False, check_mode_return=None, **kwargs): if output_process is None: output_process = _process_as_is if args_order is None: @@ -209,18 +209,22 @@ class CmdRunner(object): return _CmdRunnerContext(runner=self, args_order=args_order, output_process=output_process, - ignore_value_none=ignore_value_none, **kwargs) + ignore_value_none=ignore_value_none, + check_mode_skip=check_mode_skip, + check_mode_return=check_mode_return, **kwargs) def has_arg_format(self, arg): return arg in self.arg_formats class _CmdRunnerContext(object): - def __init__(self, runner, args_order, output_process, ignore_value_none, **kwargs): + def __init__(self, runner, args_order, output_process, ignore_value_none, check_mode_skip, check_mode_return, **kwargs): self.runner = runner self.args_order = tuple(args_order) self.output_process = output_process self.ignore_value_none = ignore_value_none + self.check_mode_skip = check_mode_skip + self.check_mode_return = check_mode_return self.run_command_args = dict(kwargs) self.environ_update = runner.environ_update @@ -260,6 +264,8 @@ class _CmdRunnerContext(object): except Exception as e: raise FormatError(arg_name, value, runner.arg_formats[arg_name], e) + if self.check_mode_skip and module.check_mode: + return self.check_mode_return results = module.run_command(self.cmd, **self.run_command_args) self.results_rc, self.results_out, self.results_err = results self.results_processed = self.output_process(*results) diff --git a/tests/integration/targets/cmd_runner/library/cmd_echo.py b/tests/integration/targets/cmd_runner/library/cmd_echo.py index 842df7e131..4b9cb8b547 100644 --- a/tests/integration/targets/cmd_runner/library/cmd_echo.py +++ b/tests/integration/targets/cmd_runner/library/cmd_echo.py @@ -6,36 +6,8 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -import sys -DOCUMENTATION = ''' -module: cmd_echo -author: "Alexei Znamensky (@russoz)" -short_description: Simple module for testing -description: - - Simple module test description. -options: - command: - description: aaa - type: list - elements: str - required: true - arg_formats: - description: bbb - type: dict - required: true - arg_order: - description: ccc - type: raw - required: true - arg_values: - description: ddd - type: list - required: true - aa: - description: eee - type: raw -''' +DOCUMENTATION = "" EXAMPLES = "" @@ -51,11 +23,15 @@ def main(): arg_formats=dict(type="dict", default={}), arg_order=dict(type="raw", required=True), arg_values=dict(type="dict", default={}), + check_mode_skip=dict(type="bool", default=False), aa=dict(type="raw"), ), + supports_check_mode=True, ) p = module.params + info = None + arg_formats = {} for arg, fmt_spec in p['arg_formats'].items(): func = getattr(fmt, fmt_spec['func']) @@ -65,11 +41,11 @@ def main(): runner = CmdRunner(module, ['echo', '--'], arg_formats=arg_formats) - info = None - with runner.context(p['arg_order']) as ctx: + with runner.context(p['arg_order'], check_mode_skip=p['check_mode_skip']) as ctx: result = ctx.run(**p['arg_values']) info = ctx.run_info - rc, out, err = result + check = "check" + rc, out, err = result if result is not None else (None, None, None) module.exit_json(rc=rc, out=out, err=err, info=info) diff --git a/tests/integration/targets/cmd_runner/tasks/test_cmd_echo.yml b/tests/integration/targets/cmd_runner/tasks/test_cmd_echo.yml index d00a468c04..ec4375e233 100644 --- a/tests/integration/targets/cmd_runner/tasks/test_cmd_echo.yml +++ b/tests/integration/targets/cmd_runner/tasks/test_cmd_echo.yml @@ -4,8 +4,10 @@ arg_formats: "{{ item.arg_formats|default(omit) }}" arg_order: "{{ item.arg_order }}" arg_values: "{{ item.arg_values|default(omit) }}" + check_mode_skip: "{{ item.check_mode_skip|default(omit) }}" aa: "{{ item.aa|default(omit) }}" register: test_result + check_mode: "{{ item.check_mode|default(omit) }}" ignore_errors: "{{ item.expect_error|default(omit) }}" - name: check results [{{ item.name }}] diff --git a/tests/integration/targets/cmd_runner/vars/main.yml b/tests/integration/targets/cmd_runner/vars/main.yml index ade4646a15..9d2b5fa078 100644 --- a/tests/integration/targets/cmd_runner/vars/main.yml +++ b/tests/integration/targets/cmd_runner/vars/main.yml @@ -82,3 +82,41 @@ cmd_echo_tests: - >- "MissingArgumentValue: Cannot find value for parameter bb" in test_result.module_stderr + + - name: set aa and bb value with check_mode on + arg_formats: + aa: + func: as_opt_eq_val + args: [--answer] + bb: + func: as_bool + args: [--bb-here] + arg_order: 'aa bb' + arg_values: + bb: true + aa: 11 + check_mode: true + assertions: + - test_result.rc == 0 + - test_result.out == "-- --answer=11 --bb-here\n" + - test_result.err == "" + + - name: set aa and bb value with check_mode and check_mode_skip on + arg_formats: + aa: + func: as_opt_eq_val + args: [--answer] + bb: + func: as_bool + args: [--bb-here] + arg_order: 'aa bb' + arg_values: + bb: true + check_mode_skip: true + aa: 11 + check_mode: true + expect_error: true # because if result contains rc != 0, ansible assumes error + assertions: + - test_result.rc == None + - test_result.out == None + - test_result.err == None