Commit 567deb5a by Toshio Kuratomi

Add explicit substitution of relative paths on the remote host just in case the…

Add explicit substitution of relative paths on the remote host just in case the connection programs do something unexpected.
parent 8528b207
...@@ -21,6 +21,7 @@ __metaclass__ = type ...@@ -21,6 +21,7 @@ __metaclass__ = type
import distutils.spawn import distutils.spawn
import os import os
import os.path
import subprocess import subprocess
import traceback import traceback
...@@ -83,8 +84,6 @@ class Connection(ConnectionBase): ...@@ -83,8 +84,6 @@ class Connection(ConnectionBase):
local_cmd = [self.chroot_cmd, self.chroot, executable, '-c', cmd] local_cmd = [self.chroot_cmd, self.chroot, executable, '-c', cmd]
self._display.vvv("EXEC %s" % (local_cmd), host=self.chroot) self._display.vvv("EXEC %s" % (local_cmd), host=self.chroot)
# FIXME: cwd= needs to be set to the basedir of the playbook, which
# should come from loader, but is not in the connection plugins
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin, p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
...@@ -99,12 +98,26 @@ class Connection(ConnectionBase): ...@@ -99,12 +98,26 @@ class Connection(ConnectionBase):
stdout, stderr = p.communicate(in_data) stdout, stderr = p.communicate(in_data)
return (p.returncode, stdout, stderr) return (p.returncode, stdout, stderr)
def _prefix_login_path(self, remote_path):
''' Make sure that we put files into a standard path
If a path is relative, then we need to choose where to put it.
ssh chooses $HOME but we aren't guaranteed that a home dir will
exist in any given chroot. So for now we're choosing "/" instead.
This also happens to be the former default.
Can revisit using $HOME instead if it's a problem
'''
if not remote_path.startswith(os.path.sep):
remote_path = os.path.join(os.path.sep, remote_path)
return os.path.normpath(remote_path)
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
''' transfer a file from local to chroot ''' ''' transfer a file from local to chroot '''
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.chroot) self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.chroot)
out_path = self._prefix_login_path(out_path)
try: try:
with open(in_path, 'rb') as in_file: with open(in_path, 'rb') as in_file:
try: try:
...@@ -124,9 +137,9 @@ class Connection(ConnectionBase): ...@@ -124,9 +137,9 @@ class Connection(ConnectionBase):
def fetch_file(self, in_path, out_path): def fetch_file(self, in_path, out_path):
''' fetch a file from chroot to local ''' ''' fetch a file from chroot to local '''
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.chroot) self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.chroot)
in_path = self._prefix_login_path(in_path)
try: try:
p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE)) p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE))
except OSError: except OSError:
......
...@@ -26,19 +26,20 @@ __metaclass__ = type ...@@ -26,19 +26,20 @@ __metaclass__ = type
import distutils.spawn import distutils.spawn
import os import os
import os.path
import subprocess import subprocess
import re import re
from distutils.version import LooseVersion from distutils.version import LooseVersion
import ansible.constants as C import ansible.constants as C
from ansible.errors import AnsibleError, AnsibleFileNotFound from ansible.errors import AnsibleError, AnsibleFileNotFound
from ansible.plugins.connection import ConnectionBase from ansible.plugins.connection import ConnectionBase
BUFSIZE = 65536 BUFSIZE = 65536
class Connection(ConnectionBase): class Connection(ConnectionBase):
''' Local docker based connections '''
transport = 'docker' transport = 'docker'
has_pipelining = True has_pipelining = True
...@@ -53,9 +54,11 @@ class Connection(ConnectionBase): ...@@ -53,9 +54,11 @@ class Connection(ConnectionBase):
# Note: docker supports running as non-root in some configurations. # Note: docker supports running as non-root in some configurations.
# (For instance, setting the UNIX socket file to be readable and # (For instance, setting the UNIX socket file to be readable and
# writable by a specific UNIX group and then putting users into that # writable by a specific UNIX group and then putting users into that
# group). But if the user is getting a permission denied error it # group). Therefore we don't check that the user is root when using
# probably means that docker on their system is only configured to be # this connection. But if the user is getting a permission denied
# connected to by root and they are not running as root. # error it probably means that docker on their system is only
# configured to be connected to by root and they are not running as
# root.
if 'docker_command' in kwargs: if 'docker_command' in kwargs:
self.docker_cmd = kwargs['docker_command'] self.docker_cmd = kwargs['docker_command']
...@@ -79,7 +82,6 @@ class Connection(ConnectionBase): ...@@ -79,7 +82,6 @@ class Connection(ConnectionBase):
def _get_docker_version(self): def _get_docker_version(self):
cmd = [self.docker_cmd, 'version'] cmd = [self.docker_cmd, 'version']
cmd_output = subprocess.check_output(cmd) cmd_output = subprocess.check_output(cmd)
for line in cmd_output.split('\n'): for line in cmd_output.split('\n'):
...@@ -106,7 +108,7 @@ class Connection(ConnectionBase): ...@@ -106,7 +108,7 @@ class Connection(ConnectionBase):
self._connected = True self._connected = True
def exec_command(self, cmd, in_data=None, sudoable=False): def exec_command(self, cmd, in_data=None, sudoable=False):
""" Run a command on the local host """ """ Run a command on the docker host """
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable) super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh' executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh'
...@@ -114,22 +116,32 @@ class Connection(ConnectionBase): ...@@ -114,22 +116,32 @@ class Connection(ConnectionBase):
local_cmd = [self.docker_cmd, "exec", '-i', self._play_context.remote_addr, executable, '-c', cmd] local_cmd = [self.docker_cmd, "exec", '-i', self._play_context.remote_addr, executable, '-c', cmd]
self._display.vvv("EXEC %s" % (local_cmd), host=self._play_context.remote_addr) self._display.vvv("EXEC %s" % (local_cmd), host=self._play_context.remote_addr)
# FIXME: cwd= needs to be set to the basedir of the playbook, which p = subprocess.Popen(local_cmd, shell=False, stdin=subprocess.PIPE,
# should come from loader, but is not in the connection plugins
p = subprocess.Popen(local_cmd,
shell=False,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate(in_data) stdout, stderr = p.communicate(in_data)
return (p.returncode, stdout, stderr) return (p.returncode, stdout, stderr)
def _prefix_login_path(self, remote_path):
''' Make sure that we put files into a standard path
If a path is relative, then we need to choose where to put it.
ssh chooses $HOME but we aren't guaranteed that a home dir will
exist in any given chroot. So for now we're choosing "/" instead.
This also happens to be the former default.
Can revisit using $HOME instead if it's a problem
'''
if not remote_path.startswith(os.path.sep):
remote_path = os.path.join(os.path.sep, remote_path)
return os.path.normpath(remote_path)
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
""" Transfer a file from local to container """ """ Transfer a file from local to docker container """
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr) self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
out_path = self._prefix_login_path(out_path)
if not os.path.exists(in_path): if not os.path.exists(in_path):
raise AnsibleFileNotFound( raise AnsibleFileNotFound(
"file or module does not exist: %s" % in_path) "file or module does not exist: %s" % in_path)
...@@ -161,9 +173,9 @@ class Connection(ConnectionBase): ...@@ -161,9 +173,9 @@ class Connection(ConnectionBase):
def fetch_file(self, in_path, out_path): def fetch_file(self, in_path, out_path):
""" Fetch a file from container to local. """ """ Fetch a file from container to local. """
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr) self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
in_path = self._prefix_login_path(in_path)
# out_path is the final file path, but docker takes a directory, not a # out_path is the final file path, but docker takes a directory, not a
# file path # file path
out_dir = os.path.dirname(out_path) out_dir = os.path.dirname(out_path)
......
...@@ -22,6 +22,7 @@ __metaclass__ = type ...@@ -22,6 +22,7 @@ __metaclass__ = type
import distutils.spawn import distutils.spawn
import os import os
import os.path
import subprocess import subprocess
import traceback import traceback
...@@ -67,8 +68,6 @@ class Connection(ConnectionBase): ...@@ -67,8 +68,6 @@ class Connection(ConnectionBase):
return cmd return cmd
def list_jails(self): def list_jails(self):
# FIXME: cwd= needs to be set to the basedir of the playbook, which
# should come from loader, but is not in the connection plugins
p = subprocess.Popen([self.jls_cmd, '-q', 'name'], p = subprocess.Popen([self.jls_cmd, '-q', 'name'],
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
...@@ -78,8 +77,6 @@ class Connection(ConnectionBase): ...@@ -78,8 +77,6 @@ class Connection(ConnectionBase):
return stdout.split() return stdout.split()
def get_jail_path(self): def get_jail_path(self):
# FIXME: cwd= needs to be set to the basedir of the playbook, which
# should come from loader, but is not in the connection plugins
p = subprocess.Popen([self.jls_cmd, '-j', self.jail, '-q', 'path'], p = subprocess.Popen([self.jls_cmd, '-j', self.jail, '-q', 'path'],
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
...@@ -107,8 +104,6 @@ class Connection(ConnectionBase): ...@@ -107,8 +104,6 @@ class Connection(ConnectionBase):
local_cmd = [self.jexec_cmd, self.jail, executable, '-c', cmd] local_cmd = [self.jexec_cmd, self.jail, executable, '-c', cmd]
self._display.vvv("EXEC %s" % (local_cmd), host=self.jail) self._display.vvv("EXEC %s" % (local_cmd), host=self.jail)
# FIXME: cwd= needs to be set to the basedir of the playbook, which
# should come from loader, but is not in the connection plugins
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin, p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
...@@ -130,11 +125,26 @@ class Connection(ConnectionBase): ...@@ -130,11 +125,26 @@ class Connection(ConnectionBase):
stdout, stderr = p.communicate(in_data) stdout, stderr = p.communicate(in_data)
return (p.returncode, stdout, stderr) return (p.returncode, stdout, stderr)
def _prefix_login_path(self, remote_path):
''' Make sure that we put files into a standard path
If a path is relative, then we need to choose where to put it.
ssh chooses $HOME but we aren't guaranteed that a home dir will
exist in any given chroot. So for now we're choosing "/" instead.
This also happens to be the former default.
Can revisit using $HOME instead if it's a problem
'''
if not remote_path.startswith(os.path.sep):
remote_path = os.path.join(os.path.sep, remote_path)
return os.path.normpath(remote_path)
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
''' transfer a file from local to jail ''' ''' transfer a file from local to jail '''
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.jail) self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.jail)
out_path = self._prefix_login_path(out_path)
try: try:
with open(in_path, 'rb') as in_file: with open(in_path, 'rb') as in_file:
try: try:
...@@ -156,6 +166,7 @@ class Connection(ConnectionBase): ...@@ -156,6 +166,7 @@ class Connection(ConnectionBase):
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.jail) self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.jail)
in_path = self._prefix_login_path(in_path)
try: try:
p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE)) p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE))
except OSError: except OSError:
......
...@@ -23,6 +23,7 @@ __metaclass__ = type ...@@ -23,6 +23,7 @@ __metaclass__ = type
import distutils.spawn import distutils.spawn
import os import os
import os.path
import subprocess import subprocess
import traceback import traceback
...@@ -116,8 +117,6 @@ class Connection(ConnectionBase): ...@@ -116,8 +117,6 @@ class Connection(ConnectionBase):
local_cmd = [self.zlogin_cmd, self.zone, executable, '-c', cmd] local_cmd = [self.zlogin_cmd, self.zone, executable, '-c', cmd]
self._display.vvv("EXEC %s" % (local_cmd), host=self.zone) self._display.vvv("EXEC %s" % (local_cmd), host=self.zone)
# FIXME: cwd= should be set to the basedir of the playbook, which
# should come from loader but is not in the connection plugins
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin, p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
...@@ -139,11 +138,26 @@ class Connection(ConnectionBase): ...@@ -139,11 +138,26 @@ class Connection(ConnectionBase):
stdout, stderr = p.communicate(in_data) stdout, stderr = p.communicate(in_data)
return (p.returncode, stdout, stderr) return (p.returncode, stdout, stderr)
def _prefix_login_path(self, remote_path):
''' Make sure that we put files into a standard path
If a path is relative, then we need to choose where to put it.
ssh chooses $HOME but we aren't guaranteed that a home dir will
exist in any given chroot. So for now we're choosing "/" instead.
This also happens to be the former default.
Can revisit using $HOME instead if it's a problem
'''
if not remote_path.startswith(os.path.sep):
remote_path = os.path.join(os.path.sep, remote_path)
return os.path.normpath(remote_path)
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
''' transfer a file from local to zone ''' ''' transfer a file from local to zone '''
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.zone) self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.zone)
out_path = self._prefix_login_path(out_path)
try: try:
with open(in_path, 'rb') as in_file: with open(in_path, 'rb') as in_file:
try: try:
...@@ -165,6 +179,7 @@ class Connection(ConnectionBase): ...@@ -165,6 +179,7 @@ class Connection(ConnectionBase):
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.zone) self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.zone)
in_path = self._prefix_login_path(in_path)
try: try:
p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE)) p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE))
except OSError: except OSError:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment