mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
CmdRunner bugfix (#7200)
* cmd_runner module utils: fix bug when passing absolute path not in standard search paths * improved tests * changed /usr/bin/echo to /bin/echo for the sake of alpine * fixed error messaging for last testcase * add condition to test cases, and remove macos from troubling ones * fix templating * fix templating * exclude centos 6 from testcases copying echo to tmp dir * try different way of specifying version * trying trick for old jinjas * use os.path.isabs() to determine if path is absolute * add changelog frag * Update plugins/module_utils/cmd_runner.py Co-authored-by: Felix Fontein <felix@fontein.de> * Update changelogs/fragments/7200-cmd-runner-abs-path.yml Co-authored-by: Felix Fontein <felix@fontein.de> --------- Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
parent
568814fc3e
commit
8fa667eeb7
7 changed files with 162 additions and 13 deletions
2
changelogs/fragments/7200-cmd-runner-abs-path.yml
Normal file
2
changelogs/fragments/7200-cmd-runner-abs-path.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bugfixes:
|
||||
- CmdRunner module utils - does not attempt to resolve path if executable is a relative or absolute path (https://github.com/ansible-collections/community.general/pull/7200).
|
|
@ -6,6 +6,7 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import os
|
||||
from functools import wraps
|
||||
|
||||
from ansible.module_utils.common.collections import is_sequence
|
||||
|
@ -204,12 +205,17 @@ class CmdRunner(object):
|
|||
environ_update = {}
|
||||
self.environ_update = environ_update
|
||||
|
||||
self.command[0] = module.get_bin_path(self.command[0], opt_dirs=path_prefix, required=True)
|
||||
_cmd = self.command[0]
|
||||
self.command[0] = _cmd if (os.path.isabs(_cmd) or '/' in _cmd) else module.get_bin_path(_cmd, opt_dirs=path_prefix, required=True)
|
||||
|
||||
for mod_param_name, spec in iteritems(module.argument_spec):
|
||||
if mod_param_name not in self.arg_formats:
|
||||
self.arg_formats[mod_param_name] = _Format.as_default_type(spec.get('type', 'str'), mod_param_name)
|
||||
|
||||
@property
|
||||
def binary(self):
|
||||
return self.command[0]
|
||||
|
||||
def __call__(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
|
||||
|
|
|
@ -21,6 +21,8 @@ from ansible_collections.community.general.plugins.module_utils.cmd_runner impor
|
|||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
cmd=dict(type="str", default="echo"),
|
||||
path_prefix=dict(type="str"),
|
||||
arg_formats=dict(type="dict", default={}),
|
||||
arg_order=dict(type="raw", required=True),
|
||||
arg_values=dict(type="dict", default={}),
|
||||
|
@ -41,7 +43,7 @@ def main():
|
|||
|
||||
arg_formats[arg] = func(*args)
|
||||
|
||||
runner = CmdRunner(module, ['echo', '--'], arg_formats=arg_formats)
|
||||
runner = CmdRunner(module, [module.params["cmd"], '--'], arg_formats=arg_formats, path_prefix=module.params["path_prefix"])
|
||||
|
||||
with runner.context(p['arg_order'], check_mode_skip=p['check_mode_skip']) as ctx:
|
||||
result = ctx.run(**p['arg_values'])
|
||||
|
|
7
tests/integration/targets/cmd_runner/meta/main.yml
Normal file
7
tests/integration/targets/cmd_runner/meta/main.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_remote_tmp_dir
|
|
@ -6,3 +6,4 @@
|
|||
ansible.builtin.include_tasks:
|
||||
file: test_cmd_echo.yml
|
||||
loop: "{{ cmd_echo_tests }}"
|
||||
when: item.condition | default(true) | bool
|
||||
|
|
|
@ -3,17 +3,26 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: test cmd_echo [{{ item.name }}]
|
||||
cmd_echo:
|
||||
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: create copy of /bin/echo ({{ item.name }})
|
||||
ansible.builtin.copy:
|
||||
src: /bin/echo
|
||||
dest: "{{ item.copy_to }}/echo"
|
||||
mode: "755"
|
||||
when: item.copy_to is defined
|
||||
|
||||
- name: check results [{{ item.name }}]
|
||||
- name: test cmd_echo module ({{ item.name }})
|
||||
cmd_echo:
|
||||
cmd: "{{ item.cmd | default(omit) }}"
|
||||
path_prefix: "{{ item.path_prefix | default(omit) }}"
|
||||
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 }})
|
||||
assert:
|
||||
that: "{{ item.assertions }}"
|
||||
|
|
|
@ -138,3 +138,125 @@ cmd_echo_tests:
|
|||
- test_result.rc == 0
|
||||
- test_result.out == "-- --answer=11 --tt-arg potatoes\n"
|
||||
- test_result.err == ""
|
||||
|
||||
- name: use cmd echo
|
||||
cmd: echo
|
||||
arg_formats:
|
||||
aa:
|
||||
func: as_opt_eq_val
|
||||
args: [--answer]
|
||||
tt:
|
||||
func: as_opt_val
|
||||
args: [--tt-arg]
|
||||
arg_order: 'aa tt'
|
||||
arg_values:
|
||||
tt: potatoes
|
||||
aa: 11
|
||||
assertions:
|
||||
- test_result.rc == 0
|
||||
- test_result.out == "-- --answer=11 --tt-arg potatoes\n"
|
||||
- test_result.err == ""
|
||||
|
||||
- name: use cmd /bin/echo
|
||||
cmd: /bin/echo
|
||||
arg_formats:
|
||||
aa:
|
||||
func: as_opt_eq_val
|
||||
args: [--answer]
|
||||
tt:
|
||||
func: as_opt_val
|
||||
args: [--tt-arg]
|
||||
arg_order: 'aa tt'
|
||||
arg_values:
|
||||
tt: potatoes
|
||||
aa: 11
|
||||
assertions:
|
||||
- test_result.rc == 0
|
||||
- test_result.out == "-- --answer=11 --tt-arg potatoes\n"
|
||||
- test_result.err == ""
|
||||
|
||||
# this will not be in the regular set of paths get_bin_path() searches
|
||||
- name: use cmd {{ remote_tmp_dir }}/echo
|
||||
condition: >
|
||||
{{
|
||||
ansible_distribution != "MacOSX" and
|
||||
not (ansible_distribution == "CentOS" and ansible_distribution_major_version is version('7.0', '<'))
|
||||
}}
|
||||
copy_to: "{{ remote_tmp_dir }}"
|
||||
cmd: "{{ remote_tmp_dir }}/echo"
|
||||
arg_formats:
|
||||
aa:
|
||||
func: as_opt_eq_val
|
||||
args: [--answer]
|
||||
tt:
|
||||
func: as_opt_val
|
||||
args: [--tt-arg]
|
||||
arg_order: 'aa tt'
|
||||
arg_values:
|
||||
tt: potatoes
|
||||
aa: 11
|
||||
assertions:
|
||||
- test_result.rc == 0
|
||||
- test_result.out == "-- --answer=11 --tt-arg potatoes\n"
|
||||
- test_result.err == ""
|
||||
|
||||
- name: use cmd echo with path_prefix {{ remote_tmp_dir }}
|
||||
cmd: echo
|
||||
condition: >
|
||||
{{
|
||||
ansible_distribution != "MacOSX" and
|
||||
not (ansible_distribution == "CentOS" and ansible_distribution_major_version is version('7.0', '<'))
|
||||
}}
|
||||
copy_to: "{{ remote_tmp_dir }}"
|
||||
path_prefix: "{{ remote_tmp_dir }}"
|
||||
arg_formats:
|
||||
aa:
|
||||
func: as_opt_eq_val
|
||||
args: [--answer]
|
||||
tt:
|
||||
func: as_opt_val
|
||||
args: [--tt-arg]
|
||||
arg_order: 'aa tt'
|
||||
arg_values:
|
||||
tt: potatoes
|
||||
aa: 11
|
||||
assertions:
|
||||
- test_result.rc == 0
|
||||
- test_result.out == "-- --answer=11 --tt-arg potatoes\n"
|
||||
- test_result.err == ""
|
||||
|
||||
- name: use cmd never-existed
|
||||
cmd: never-existed
|
||||
arg_formats:
|
||||
aa:
|
||||
func: as_opt_eq_val
|
||||
args: [--answer]
|
||||
tt:
|
||||
func: as_opt_val
|
||||
args: [--tt-arg]
|
||||
arg_order: 'aa tt'
|
||||
arg_values:
|
||||
tt: potatoes
|
||||
aa: 11
|
||||
expect_error: true
|
||||
assertions:
|
||||
- >
|
||||
"Failed to find required executable" in test_result.msg
|
||||
|
||||
- name: use cmd /usr/bin/never-existed
|
||||
cmd: /usr/bin/never-existed
|
||||
arg_formats:
|
||||
aa:
|
||||
func: as_opt_eq_val
|
||||
args: [--answer]
|
||||
tt:
|
||||
func: as_opt_val
|
||||
args: [--tt-arg]
|
||||
arg_order: 'aa tt'
|
||||
arg_values:
|
||||
tt: potatoes
|
||||
aa: 11
|
||||
expect_error: true
|
||||
assertions:
|
||||
- >
|
||||
"No such file or directory" in test_result.msg
|
||||
|
|
Loading…
Reference in a new issue