From 22538374535996da1fb61c7b58e981f2511ed9ef Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Fri, 19 May 2023 05:36:52 +1000 Subject: [PATCH] command - Add option to disable argument var expansion (#80512) * command - Add option to disable argument var expansion * Use test char that isn't an escape sequence --- changelogs/fragments/command-expand-args.yml | 2 + lib/ansible/modules/command.py | 13 ++++++- lib/ansible/plugins/action/shell.py | 6 +++ .../targets/command_shell/tasks/main.yml | 37 +++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/command-expand-args.yml diff --git a/changelogs/fragments/command-expand-args.yml b/changelogs/fragments/command-expand-args.yml new file mode 100644 index 00000000000..9ecd7048f39 --- /dev/null +++ b/changelogs/fragments/command-expand-args.yml @@ -0,0 +1,2 @@ +minor_changes: +- command - Add option ``expand_argument_vars`` to disable argument expansion and use literal values - https://github.com/ansible/ansible/issues/54162 diff --git a/lib/ansible/modules/command.py b/lib/ansible/modules/command.py index 8150ab8792a..a8df4f8f255 100644 --- a/lib/ansible/modules/command.py +++ b/lib/ansible/modules/command.py @@ -40,6 +40,14 @@ attributes: raw: support: full options: + expand_argument_vars: + description: + - Expands the arguments that are variables, for example C($HOME) will be expanded before being passed to the + command to run. + - Set to C(false) to disable expansion and treat the value as a literal argument. + type: bool + default: true + version_added: "2.16" free_form: description: - The command module takes a free form string as a command to run. @@ -235,6 +243,7 @@ def main(): argv=dict(type='list', elements='str'), chdir=dict(type='path'), executable=dict(), + expand_argument_vars=dict(type='bool', default=True), creates=dict(type='path'), removes=dict(type='path'), # The default for this really comes from the action plugin @@ -254,6 +263,7 @@ def main(): stdin = module.params['stdin'] stdin_add_newline = module.params['stdin_add_newline'] strip = module.params['strip_empty_ends'] + expand_argument_vars = module.params['expand_argument_vars'] # we promissed these in 'always' ( _lines get autoaded on action plugin) r = {'changed': False, 'stdout': '', 'stderr': '', 'rc': None, 'cmd': None, 'start': None, 'end': None, 'delta': None, 'msg': ''} @@ -321,7 +331,8 @@ def main(): if not module.check_mode: r['start'] = datetime.datetime.now() r['rc'], r['stdout'], r['stderr'] = module.run_command(args, executable=executable, use_unsafe_shell=shell, encoding=None, - data=stdin, binary_data=(not stdin_add_newline)) + data=stdin, binary_data=(not stdin_add_newline), + expand_user_and_vars=expand_argument_vars) r['end'] = datetime.datetime.now() else: # this is partial check_mode support, since we end up skipping if we get here diff --git a/lib/ansible/plugins/action/shell.py b/lib/ansible/plugins/action/shell.py index 617a373d41a..dd4df461cda 100644 --- a/lib/ansible/plugins/action/shell.py +++ b/lib/ansible/plugins/action/shell.py @@ -4,6 +4,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type +from ansible.errors import AnsibleActionFail from ansible.plugins.action import ActionBase @@ -15,6 +16,11 @@ class ActionModule(ActionBase): # Shell module is implemented via command with a special arg self._task.args['_uses_shell'] = True + # Shell shares the same module code as command. Fail if command + # specific options are set. + if "expand_argument_vars" in self._task.args: + raise AnsibleActionFail(f"Unsupported parameters for ({self._task.action}) module: expand_argument_vars") + command_action = self._shared_loader_obj.action_loader.get('ansible.legacy.command', task=self._task, connection=self._connection, diff --git a/test/integration/targets/command_shell/tasks/main.yml b/test/integration/targets/command_shell/tasks/main.yml index 12a944c48c3..5d3d9a82f41 100644 --- a/test/integration/targets/command_shell/tasks/main.yml +++ b/test/integration/targets/command_shell/tasks/main.yml @@ -284,6 +284,30 @@ that: - "command_result6.stdout == '9cd0697c6a9ff6689f0afb9136fa62e0b3fee903'" +- name: check default var expansion + command: /bin/sh -c 'echo "\$TEST"' + environment: + TEST: z + register: command_result7 + +- name: assert vars were expanded + assert: + that: + - command_result7.stdout == '\\z' + +- name: check disabled var expansion + command: /bin/sh -c 'echo "\$TEST"' + args: + expand_argument_vars: false + environment: + TEST: z + register: command_result8 + +- name: assert vars were not expanded + assert: + that: + - command_result8.stdout == '$TEST' + ## ## shell ## @@ -546,3 +570,16 @@ - command_strip.stderr == 'hello \n ' - command_no_strip.stdout== 'hello \n \r\n' - command_no_strip.stderr == 'hello \n \r\n' + +- name: run shell with expand_argument_vars + shell: echo 'hi' + args: + expand_argument_vars: false + register: shell_expand_failure + ignore_errors: true + +- name: assert shell with expand_arguments_vars failed + assert: + that: + - shell_expand_failure is failed + - "shell_expand_failure.msg == 'Unsupported parameters for (shell) module: expand_argument_vars'"