diff --git a/lib/ansible/playbook/play_context.py b/lib/ansible/playbook/play_context.py index f5b9434200..c50486e5ea 100644 --- a/lib/ansible/playbook/play_context.py +++ b/lib/ansible/playbook/play_context.py @@ -22,13 +22,13 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type import os -import pipes import pwd import random import re import string from ansible.compat.six import iteritems, string_types +from ansible.compat.six.moves import shlex_quote from ansible import constants as C from ansible.errors import AnsibleError from ansible.module_utils._text import to_bytes @@ -467,7 +467,7 @@ class PlayContext(Base): becomecmd = None randbits = ''.join(random.choice(string.ascii_lowercase) for x in range(32)) success_key = 'BECOME-SUCCESS-%s' % randbits - success_cmd = pipes.quote('echo %s; %s' % (success_key, cmd)) + success_cmd = shlex_quote('echo %s; %s' % (success_key, cmd)) if executable: command = '%s -c %s' % (executable, success_cmd) @@ -496,7 +496,7 @@ class PlayContext(Base): # done for older versions of sudo that do not support the option. # # Passing a quoted compound command to sudo (or sudo -s) - # directly doesn't work, so we shellquote it with pipes.quote() + # directly doesn't work, so we shellquote it with shlex_quote() # and pass the quoted string to the user's shell. # force quick error if password is required but not supplied, should prevent sudo hangs. @@ -518,7 +518,7 @@ class PlayContext(Base): return bool(b_SU_PROMPT_LOCALIZATIONS_RE.match(b_data)) prompt = detect_su_prompt - becomecmd = '%s %s %s -c %s' % (exe, flags, self.become_user, pipes.quote(command)) + becomecmd = '%s %s %s -c %s' % (exe, flags, self.become_user, shlex_quote(command)) elif self.become_method == 'pbrun': @@ -562,7 +562,7 @@ class PlayContext(Base): exe = self.become_exe or 'dzdo' if self.become_pass: prompt = '[dzdo via ansible, key=%s] password: ' % randbits - becomecmd = '%s -p %s -u %s %s' % (exe, pipes.quote(prompt), self.become_user, command) + becomecmd = '%s -p %s -u %s %s' % (exe, shlex_quote(prompt), self.become_user, command) else: becomecmd = '%s -u %s %s' % (exe, self.become_user, command) diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py index d2ef5988e3..c59b6bdd90 100644 --- a/lib/ansible/plugins/action/__init__.py +++ b/lib/ansible/plugins/action/__init__.py @@ -22,7 +22,6 @@ __metaclass__ = type import base64 import json import os -import pipes import random import re import stat @@ -30,9 +29,9 @@ import tempfile import time from abc import ABCMeta, abstractmethod -from ansible.compat.six import binary_type, text_type, iteritems, with_metaclass - from ansible import constants as C +from ansible.compat.six import binary_type, text_type, iteritems, with_metaclass +from ansible.compat.six.moves import shlex_quote from ansible.errors import AnsibleError, AnsibleConnectionFailure from ansible.executor.module_common import modify_module from ansible.module_utils._text import to_bytes, to_native, to_text @@ -596,7 +595,7 @@ class ActionBase(with_metaclass(ABCMeta, object)): # the remote system, which can be read and parsed by the module args_data = "" for k,v in iteritems(module_args): - args_data += '%s=%s ' % (k, pipes.quote(text_type(v))) + args_data += '%s=%s ' % (k, shlex_quote(text_type(v))) self._transfer_data(args_file_path, args_data) elif module_style in ('non_native_want_json', 'binary'): self._transfer_data(args_file_path, json.dumps(module_args)) @@ -748,7 +747,7 @@ class ActionBase(with_metaclass(ABCMeta, object)): # only applied for the default executable to avoid interfering with the raw action cmd = self._connection._shell.append_command(cmd, 'sleep 0') if executable: - cmd = executable + ' -c ' + pipes.quote(cmd) + cmd = executable + ' -c ' + shlex_quote(cmd) display.debug("_low_level_execute_command(): executing: %s" % (cmd,)) diff --git a/lib/ansible/plugins/action/async.py b/lib/ansible/plugins/action/async.py index 6c348c7d9f..e4c67371a1 100644 --- a/lib/ansible/plugins/action/async.py +++ b/lib/ansible/plugins/action/async.py @@ -18,11 +18,11 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type import json -import pipes import random from ansible import constants as C from ansible.compat.six import iteritems +from ansible.compat.six.moves import shlex_quote from ansible.module_utils._text import to_text from ansible.plugins.action import ActionBase @@ -48,8 +48,6 @@ class ActionModule(ActionBase): module_name = self._task.action - - env_string = self._compute_environment_string() module_args = self._task.args.copy() @@ -77,7 +75,7 @@ class ActionModule(ActionBase): elif module_style == 'old': args_data = "" for k, v in iteritems(module_args): - args_data += '%s="%s" ' % (k, pipes.quote(to_text(v))) + args_data += '%s="%s" ' % (k, shlex_quote(to_text(v))) argsfile = self._transfer_data(self._connection._shell.join_path(tmp, 'arguments'), args_data) remote_paths = tmp, remote_module_path, remote_async_module_path diff --git a/lib/ansible/plugins/connection/chroot.py b/lib/ansible/plugins/connection/chroot.py index d067027a91..2c2c35341e 100644 --- a/lib/ansible/plugins/connection/chroot.py +++ b/lib/ansible/plugins/connection/chroot.py @@ -22,11 +22,11 @@ __metaclass__ = type import distutils.spawn import os import os.path -import pipes import subprocess import traceback from ansible import constants as C +from ansible.compat.six.moves import shlex_quote from ansible.errors import AnsibleError from ansible.module_utils.basic import is_executable from ansible.module_utils._text import to_bytes @@ -128,7 +128,7 @@ class Connection(ConnectionBase): super(Connection, self).put_file(in_path, out_path) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.chroot) - out_path = pipes.quote(self._prefix_login_path(out_path)) + out_path = shlex_quote(self._prefix_login_path(out_path)) try: with open(to_bytes(in_path, errors='surrogate_or_strict'), 'rb') as in_file: try: @@ -150,7 +150,7 @@ class Connection(ConnectionBase): super(Connection, self).fetch_file(in_path, out_path) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.chroot) - in_path = pipes.quote(self._prefix_login_path(in_path)) + in_path = shlex_quote(self._prefix_login_path(in_path)) try: p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE)) except OSError: diff --git a/lib/ansible/plugins/connection/docker.py b/lib/ansible/plugins/connection/docker.py index f4b991ad51..8fe4d3f8a5 100644 --- a/lib/ansible/plugins/connection/docker.py +++ b/lib/ansible/plugins/connection/docker.py @@ -27,13 +27,13 @@ __metaclass__ = type import distutils.spawn import os import os.path -import pipes import subprocess import re from distutils.version import LooseVersion import ansible.constants as C +from ansible.compat.six.moves import shlex_quote from ansible.errors import AnsibleError, AnsibleFileNotFound from ansible.module_utils._text import to_bytes from ansible.plugins.connection import ConnectionBase, BUFSIZE @@ -228,7 +228,7 @@ class Connection(ConnectionBase): raise AnsibleFileNotFound( "file or module does not exist: %s" % in_path) - out_path = pipes.quote(out_path) + out_path = shlex_quote(out_path) # Older docker doesn't have native support for copying files into # running containers, so we use docker exec to implement this # Although docker version 1.8 and later provide support, the diff --git a/lib/ansible/plugins/connection/jail.py b/lib/ansible/plugins/connection/jail.py index 93936a0a78..f6bd394ad7 100644 --- a/lib/ansible/plugins/connection/jail.py +++ b/lib/ansible/plugins/connection/jail.py @@ -23,10 +23,10 @@ __metaclass__ = type import distutils.spawn import os import os.path -import pipes import subprocess import traceback +from ansible.compat.six.moves import shlex_quote from ansible.errors import AnsibleError from ansible.module_utils._text import to_bytes from ansible.plugins.connection import ConnectionBase, BUFSIZE @@ -150,7 +150,7 @@ class Connection(ConnectionBase): super(Connection, self).put_file(in_path, out_path) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.jail) - out_path = pipes.quote(self._prefix_login_path(out_path)) + out_path = shlex_quote(self._prefix_login_path(out_path)) try: with open(to_bytes(in_path, errors='surrogate_or_strict'), 'rb') as in_file: try: @@ -172,7 +172,7 @@ class Connection(ConnectionBase): super(Connection, self).fetch_file(in_path, out_path) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.jail) - in_path = pipes.quote(self._prefix_login_path(in_path)) + in_path = shlex_quote(self._prefix_login_path(in_path)) try: p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE)) except OSError: diff --git a/lib/ansible/plugins/connection/libvirt_lxc.py b/lib/ansible/plugins/connection/libvirt_lxc.py index 4ccb66f556..77f377eafb 100644 --- a/lib/ansible/plugins/connection/libvirt_lxc.py +++ b/lib/ansible/plugins/connection/libvirt_lxc.py @@ -23,11 +23,11 @@ __metaclass__ = type import distutils.spawn import os import os.path -import pipes import subprocess import traceback from ansible import constants as C +from ansible.compat.six.moves import shlex_quote from ansible.errors import AnsibleError from ansible.module_utils._text import to_bytes from ansible.plugins.connection import ConnectionBase, BUFSIZE @@ -129,7 +129,7 @@ class Connection(ConnectionBase): super(Connection, self).put_file(in_path, out_path) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.lxc) - out_path = pipes.quote(self._prefix_login_path(out_path)) + out_path = shlex_quote(self._prefix_login_path(out_path)) try: with open(to_bytes(in_path, errors='surrogate_or_strict'), 'rb') as in_file: try: @@ -151,7 +151,7 @@ class Connection(ConnectionBase): super(Connection, self).fetch_file(in_path, out_path) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.lxc) - in_path = pipes.quote(self._prefix_login_path(in_path)) + in_path = shlex_quote(self._prefix_login_path(in_path)) try: p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE)) except OSError: diff --git a/lib/ansible/plugins/connection/ssh.py b/lib/ansible/plugins/connection/ssh.py index cf6df55439..62d1bdedf8 100644 --- a/lib/ansible/plugins/connection/ssh.py +++ b/lib/ansible/plugins/connection/ssh.py @@ -22,7 +22,6 @@ __metaclass__ = type import errno import fcntl import os -import pipes import pty import select import subprocess @@ -30,6 +29,7 @@ import time from ansible import constants as C from ansible.compat.six import PY3, text_type, binary_type +from ansible.compat.six.moves import shlex_quote from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound from ansible.errors import AnsibleOptionsError from ansible.module_utils.basic import BOOLEANS @@ -324,7 +324,7 @@ class Connection(ConnectionBase): Starts the command and communicates with it until it ends. ''' - display_cmd = list(map(pipes.quote, map(to_text, cmd))) + display_cmd = list(map(shlex_quote, map(to_text, cmd))) display.vvv(u'SSH: EXEC {0}'.format(u' '.join(display_cmd)), host=self.host) # Start the given command. If we don't need to pipeline data, we can try @@ -626,9 +626,9 @@ class Connection(ConnectionBase): for method in methods: if method == 'sftp': cmd = self._build_command('sftp', to_bytes(host)) - in_data = u"{0} {1} {2}\n".format(sftp_action, pipes.quote(in_path), pipes.quote(out_path)) + in_data = u"{0} {1} {2}\n".format(sftp_action, shlex_quote(in_path), shlex_quote(out_path)) elif method == 'scp': - cmd = self._build_command('scp', in_path, u'{0}:{1}'.format(host, pipes.quote(out_path))) + cmd = self._build_command('scp', in_path, u'{0}:{1}'.format(host, shlex_quote(out_path))) in_data = None in_data = to_bytes(in_data, nonstring='passthru') diff --git a/lib/ansible/plugins/connection/zone.py b/lib/ansible/plugins/connection/zone.py index 3c1322d3ec..b52ad41022 100644 --- a/lib/ansible/plugins/connection/zone.py +++ b/lib/ansible/plugins/connection/zone.py @@ -24,11 +24,11 @@ __metaclass__ = type import distutils.spawn import os import os.path -import pipes import subprocess import traceback from ansible import constants as C +from ansible.compat.six.moves import shlex_quote from ansible.errors import AnsibleError from ansible.plugins.connection import ConnectionBase, BUFSIZE from ansible.module_utils._text import to_bytes @@ -149,7 +149,7 @@ class Connection(ConnectionBase): super(Connection, self).put_file(in_path, out_path) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.zone) - out_path = pipes.quote(self._prefix_login_path(out_path)) + out_path = shlex_quote(self._prefix_login_path(out_path)) try: with open(in_path, 'rb') as in_file: try: @@ -171,7 +171,7 @@ class Connection(ConnectionBase): super(Connection, self).fetch_file(in_path, out_path) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.zone) - in_path = pipes.quote(self._prefix_login_path(in_path)) + in_path = shlex_quote(self._prefix_login_path(in_path)) try: p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE)) except OSError: diff --git a/lib/ansible/plugins/filter/core.py b/lib/ansible/plugins/filter/core.py index bbd7b295b3..39b92a28f8 100644 --- a/lib/ansible/plugins/filter/core.py +++ b/lib/ansible/plugins/filter/core.py @@ -25,7 +25,6 @@ import itertools import json import os.path import ntpath -import pipes import glob import re import crypt @@ -48,6 +47,7 @@ except: from ansible import errors from ansible.compat.six import iteritems, string_types from ansible.compat.six.moves import reduce +from ansible.compat.six.moves import shlex_quote from ansible.module_utils._text import to_text from ansible.parsing.yaml.dumper import AnsibleDumper from ansible.utils.hashing import md5s, checksum_s @@ -123,7 +123,7 @@ def to_datetime(string, format="%Y-%d-%m %H:%M:%S"): def quote(a): ''' return its argument quoted for shell usage ''' - return pipes.quote(a) + return shlex_quote(a) def fileglob(pathname): ''' return list of matched regular files for glob ''' diff --git a/lib/ansible/plugins/shell/__init__.py b/lib/ansible/plugins/shell/__init__.py index 44af0abb74..1a88009e9e 100644 --- a/lib/ansible/plugins/shell/__init__.py +++ b/lib/ansible/plugins/shell/__init__.py @@ -19,15 +19,16 @@ __metaclass__ = type import os import re -import pipes import ansible.constants as C import time import random from ansible.compat.six import text_type +from ansible.compat.six.moves import shlex_quote _USER_HOME_PATH_RE = re.compile(r'^~[_.A-Za-z0-9][-_.A-Za-z0-9]*$') + class ShellBase(object): def __init__(self): @@ -44,7 +45,7 @@ class ShellBase(object): def env_prefix(self, **kwargs): env = self.env.copy() env.update(kwargs) - return ' '.join(['%s=%s' % (k, pipes.quote(text_type(v))) for k,v in env.items()]) + return ' '.join(['%s=%s' % (k, shlex_quote(text_type(v))) for k,v in env.items()]) def join_path(self, *args): return os.path.join(*args) @@ -60,14 +61,14 @@ class ShellBase(object): def chmod(self, paths, mode): cmd = ['chmod', mode] cmd.extend(paths) - cmd = [pipes.quote(c) for c in cmd] + cmd = [shlex_quote(c) for c in cmd] return ' '.join(cmd) def chown(self, paths, user): cmd = ['chown', user] cmd.extend(paths) - cmd = [pipes.quote(c) for c in cmd] + cmd = [shlex_quote(c) for c in cmd] return ' '.join(cmd) @@ -75,19 +76,19 @@ class ShellBase(object): """Only sets acls for users as that's really all we need""" cmd = ['setfacl', '-m', 'u:%s:%s' % (user, mode)] cmd.extend(paths) - cmd = [pipes.quote(c) for c in cmd] + cmd = [shlex_quote(c) for c in cmd] return ' '.join(cmd) def remove(self, path, recurse=False): - path = pipes.quote(path) + path = shlex_quote(path) cmd = 'rm -f ' if recurse: cmd += '-r ' return cmd + "%s %s" % (path, self._SHELL_REDIRECT_ALLNULL) def exists(self, path): - cmd = ['test', '-e', pipes.quote(path)] + cmd = ['test', '-e', shlex_quote(path)] return ' '.join(cmd) def mkdtemp(self, basefile=None, system=False, mode=None): @@ -138,14 +139,14 @@ class ShellBase(object): # Check that the user_path to expand is safe if user_home_path != '~': if not _USER_HOME_PATH_RE.match(user_home_path): - # pipes.quote will make the shell return the string verbatim - user_home_path = pipes.quote(user_home_path) + # shlex_quote will make the shell return the string verbatim + user_home_path = shlex_quote(user_home_path) return 'echo %s' % user_home_path def build_module_command(self, env_string, shebang, cmd, arg_path=None, rm_tmp=None): # don't quote the cmd if it's an empty string, because this will break pipelining mode if cmd.strip() != '': - cmd = pipes.quote(cmd) + cmd = shlex_quote(cmd) cmd_parts = [] if shebang: diff --git a/lib/ansible/plugins/shell/fish.py b/lib/ansible/plugins/shell/fish.py index ddee24ac6d..c8aa148b5c 100644 --- a/lib/ansible/plugins/shell/fish.py +++ b/lib/ansible/plugins/shell/fish.py @@ -17,9 +17,10 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import pipes from ansible.plugins.shell.sh import ShellModule as ShModule from ansible.compat.six import text_type +from ansible.compat.six.moves import shlex_quote + class ShellModule(ShModule): @@ -40,12 +41,12 @@ class ShellModule(ShModule): def env_prefix(self, **kwargs): env = self.env.copy() env.update(kwargs) - return ' '.join(['set -lx %s %s;' % (k, pipes.quote(text_type(v))) for k,v in env.items()]) + return ' '.join(['set -lx %s %s;' % (k, shlex_quote(text_type(v))) for k,v in env.items()]) def build_module_command(self, env_string, shebang, cmd, arg_path=None, rm_tmp=None): # don't quote the cmd if it's an empty string, because this will break pipelining mode if cmd.strip() != '': - cmd = pipes.quote(cmd) + cmd = shlex_quote(cmd) cmd_parts = [env_string.strip(), shebang.replace("#!", "").strip(), cmd] if arg_path is not None: cmd_parts.append(arg_path) @@ -82,7 +83,7 @@ class ShellModule(ShModule): # Quoting gets complex here. We're writing a python string that's # used by a variety of shells on the remote host to invoke a python # "one-liner". - shell_escaped_path = pipes.quote(path) + shell_escaped_path = shlex_quote(path) test = "set rc flag; [ -r %(p)s ] %(shell_or)s set rc 2; [ -f %(p)s ] %(shell_or)s set rc 1; [ -d %(p)s ] %(shell_and)s set rc 3; %(i)s -V 2>/dev/null %(shell_or)s set rc 4; [ x\"$rc\" != \"xflag\" ] %(shell_and)s echo \"$rc \"%(p)s %(shell_and)s exit 0" % dict(p=shell_escaped_path, i=python_interp, shell_and=self._SHELL_AND, shell_or=self._SHELL_OR) csums = [ u"({0} -c 'import hashlib; BLOCKSIZE = 65536; hasher = hashlib.sha1();{2}afile = open(\"'{1}'\", \"rb\"){2}buf = afile.read(BLOCKSIZE){2}while len(buf) > 0:{2}\thasher.update(buf){2}\tbuf = afile.read(BLOCKSIZE){2}afile.close(){2}print(hasher.hexdigest())' 2>/dev/null)".format(python_interp, shell_escaped_path, self._SHELL_EMBEDDED_PY_EOL), # Python > 2.4 (including python3) diff --git a/lib/ansible/plugins/shell/sh.py b/lib/ansible/plugins/shell/sh.py index 671eb7139e..a12c66c052 100644 --- a/lib/ansible/plugins/shell/sh.py +++ b/lib/ansible/plugins/shell/sh.py @@ -17,8 +17,8 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import pipes +from ansible.compat.six.moves import shlex_quote from ansible.plugins.shell import ShellBase @@ -71,7 +71,7 @@ class ShellModule(ShellBase): # Quoting gets complex here. We're writing a python string that's # used by a variety of shells on the remote host to invoke a python # "one-liner". - shell_escaped_path = pipes.quote(path) + shell_escaped_path = shlex_quote(path) test = "rc=flag; [ -r %(p)s ] %(shell_or)s rc=2; [ -f %(p)s ] %(shell_or)s rc=1; [ -d %(p)s ] %(shell_and)s rc=3; %(i)s -V 2>/dev/null %(shell_or)s rc=4; [ x\"$rc\" != \"xflag\" ] %(shell_and)s echo \"${rc} \"%(p)s %(shell_and)s exit 0" % dict(p=shell_escaped_path, i=python_interp, shell_and=self._SHELL_AND, shell_or=self._SHELL_OR) csums = [ u"({0} -c 'import hashlib; BLOCKSIZE = 65536; hasher = hashlib.sha1();{2}afile = open(\"'{1}'\", \"rb\"){2}buf = afile.read(BLOCKSIZE){2}while len(buf) > 0:{2}\thasher.update(buf){2}\tbuf = afile.read(BLOCKSIZE){2}afile.close(){2}print(hasher.hexdigest())' 2>/dev/null)".format(python_interp, shell_escaped_path, self._SHELL_EMBEDDED_PY_EOL), # Python > 2.4 (including python3) diff --git a/test/units/playbook/test_play_context.py b/test/units/playbook/test_play_context.py index a6b2094ed0..adbd54f2bb 100644 --- a/test/units/playbook/test_play_context.py +++ b/test/units/playbook/test_play_context.py @@ -20,12 +20,12 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type import os -import pipes from ansible.compat.tests import unittest from ansible.compat.tests.mock import patch, MagicMock from ansible import constants as C +from ansible.compat.six.moves import shlex_quote from ansible.cli import CLI from ansible.errors import AnsibleError, AnsibleParserError from ansible.playbook.play_context import PlayContext @@ -181,7 +181,7 @@ class TestPlayContext(unittest.TestCase): play_context.become_pass = 'testpass' play_context.become_method = 'dzdo' cmd = play_context.make_become_cmd(cmd=default_cmd, executable="/bin/bash") - self.assertEqual(cmd, """%s -p %s -u %s %s -c 'echo %s; %s'""" % (dzdo_exe, pipes.quote(play_context.prompt), play_context.become_user, default_exe, play_context.success_key, default_cmd)) + self.assertEqual(cmd, """%s -p %s -u %s %s -c 'echo %s; %s'""" % (dzdo_exe, shlex_quote(play_context.prompt), play_context.become_user, default_exe, play_context.success_key, default_cmd)) class TestTaskAndVariableOverrride(unittest.TestCase): diff --git a/test/units/plugins/action/test_action.py b/test/units/plugins/action/test_action.py index 52083257a7..1542a2d0fc 100644 --- a/test/units/plugins/action/test_action.py +++ b/test/units/plugins/action/test_action.py @@ -20,7 +20,6 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import pipes import os try: @@ -32,6 +31,7 @@ from nose.tools import eq_, raises from ansible import constants as C from ansible.compat.six import text_type +from ansible.compat.six.moves import shlex_quote from ansible.compat.tests import unittest from ansible.compat.tests.mock import patch, MagicMock, mock_open @@ -164,7 +164,7 @@ class TestActionBase(unittest.TestCase): # create a mock connection, so we don't actually try and connect to things def env_prefix(**args): - return ' '.join(['%s=%s' % (k, pipes.quote(text_type(v))) for k,v in args.items()]) + return ' '.join(['%s=%s' % (k, shlex_quote(text_type(v))) for k,v in args.items()]) mock_connection = MagicMock() mock_connection._shell.env_prefix.side_effect = env_prefix diff --git a/test/units/plugins/connection/test_ssh.py b/test/units/plugins/connection/test_ssh.py index 04d456f325..73dc0685ef 100644 --- a/test/units/plugins/connection/test_ssh.py +++ b/test/units/plugins/connection/test_ssh.py @@ -21,13 +21,13 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import pipes from io import StringIO from ansible.compat.tests import unittest from ansible.compat.tests.mock import patch, MagicMock from ansible import constants as C +from ansible.compat.six.moves import shlex_quote from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound from ansible.playbook.play_context import PlayContext from ansible.plugins.connection import ssh @@ -311,7 +311,7 @@ class TestConnectionBaseClass(unittest.TestCase): # Test with C.DEFAULT_SCP_IF_SSH set to smart # Test when SFTP works C.DEFAULT_SCP_IF_SSH = 'smart' - expected_in_data = b' '.join((b'put', to_bytes(pipes.quote('/path/to/in/file')), to_bytes(pipes.quote('/path/to/dest/file')))) + b'\n' + expected_in_data = b' '.join((b'put', to_bytes(shlex_quote('/path/to/in/file')), to_bytes(shlex_quote('/path/to/dest/file')))) + b'\n' conn.put_file('/path/to/in/file', '/path/to/dest/file') conn._run.assert_called_with('some command to run', expected_in_data, checkrc=False) @@ -331,13 +331,13 @@ class TestConnectionBaseClass(unittest.TestCase): # test with C.DEFAULT_SCP_IF_SSH disabled C.DEFAULT_SCP_IF_SSH = False - expected_in_data = b' '.join((b'put', to_bytes(pipes.quote('/path/to/in/file')), to_bytes(pipes.quote('/path/to/dest/file')))) + b'\n' + expected_in_data = b' '.join((b'put', to_bytes(shlex_quote('/path/to/in/file')), to_bytes(shlex_quote('/path/to/dest/file')))) + b'\n' conn.put_file('/path/to/in/file', '/path/to/dest/file') conn._run.assert_called_with('some command to run', expected_in_data, checkrc=False) expected_in_data = b' '.join((b'put', - to_bytes(pipes.quote('/path/to/in/file/with/unicode-fö〩')), - to_bytes(pipes.quote('/path/to/dest/file/with/unicode-fö〩')))) + b'\n' + to_bytes(shlex_quote('/path/to/in/file/with/unicode-fö〩')), + to_bytes(shlex_quote('/path/to/dest/file/with/unicode-fö〩')))) + b'\n' conn.put_file(u'/path/to/in/file/with/unicode-fö〩', u'/path/to/dest/file/with/unicode-fö〩') conn._run.assert_called_with('some command to run', expected_in_data, checkrc=False) @@ -365,7 +365,7 @@ class TestConnectionBaseClass(unittest.TestCase): # Test with C.DEFAULT_SCP_IF_SSH set to smart # Test when SFTP works C.DEFAULT_SCP_IF_SSH = 'smart' - expected_in_data = b' '.join((b'get', to_bytes(pipes.quote('/path/to/in/file')), to_bytes(pipes.quote('/path/to/dest/file')))) + b'\n' + expected_in_data = b' '.join((b'get', to_bytes(shlex_quote('/path/to/in/file')), to_bytes(shlex_quote('/path/to/dest/file')))) + b'\n' conn.fetch_file('/path/to/in/file', '/path/to/dest/file') conn._run.assert_called_with('some command to run', expected_in_data, checkrc=False) @@ -385,13 +385,13 @@ class TestConnectionBaseClass(unittest.TestCase): # test with C.DEFAULT_SCP_IF_SSH disabled C.DEFAULT_SCP_IF_SSH = False - expected_in_data = b' '.join((b'get', to_bytes(pipes.quote('/path/to/in/file')), to_bytes(pipes.quote('/path/to/dest/file')))) + b'\n' + expected_in_data = b' '.join((b'get', to_bytes(shlex_quote('/path/to/in/file')), to_bytes(shlex_quote('/path/to/dest/file')))) + b'\n' conn.fetch_file('/path/to/in/file', '/path/to/dest/file') conn._run.assert_called_with('some command to run', expected_in_data, checkrc=False) expected_in_data = b' '.join((b'get', - to_bytes(pipes.quote('/path/to/in/file/with/unicode-fö〩')), - to_bytes(pipes.quote('/path/to/dest/file/with/unicode-fö〩')))) + b'\n' + to_bytes(shlex_quote('/path/to/in/file/with/unicode-fö〩')), + to_bytes(shlex_quote('/path/to/dest/file/with/unicode-fö〩')))) + b'\n' conn.fetch_file(u'/path/to/in/file/with/unicode-fö〩', u'/path/to/dest/file/with/unicode-fö〩') conn._run.assert_called_with('some command to run', expected_in_data, checkrc=False)