From 349fb42f548ff41c63fee7e3b92b691cc11dba8c Mon Sep 17 00:00:00 2001 From: Thomas Steinbach Date: Fri, 4 Dec 2015 03:24:44 +0100 Subject: [PATCH 1/2] Allow setup of docker remote connections --- lib/ansible/playbook/play_context.py | 5 +++++ lib/ansible/plugins/connection/docker.py | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/ansible/playbook/play_context.py b/lib/ansible/playbook/play_context.py index 5c02093980..414036dc9b 100644 --- a/lib/ansible/playbook/play_context.py +++ b/lib/ansible/playbook/play_context.py @@ -50,6 +50,7 @@ except ImportError: MAGIC_VARIABLE_MAPPING = dict( connection = ('ansible_connection',), + connection_args = ('ansible_connection_args',), remote_addr = ('ansible_ssh_host', 'ansible_host'), remote_user = ('ansible_ssh_user', 'ansible_user'), port = ('ansible_ssh_port', 'ansible_port'), @@ -136,6 +137,7 @@ class PlayContext(Base): # connection fields, some are inherited from Base: # (connection, port, remote_user, environment, no_log) + _connection_args = FieldAttribute(isa='string') _remote_addr = FieldAttribute(isa='string') _password = FieldAttribute(isa='string') _private_key_file = FieldAttribute(isa='string', default=C.DEFAULT_PRIVATE_KEY_FILE) @@ -243,6 +245,9 @@ class PlayContext(Base): if options.connection: self.connection = options.connection + if hasattr(options, 'connection_args') and options.connection_args: + self.connection_args = options.connection_args + self.remote_user = options.remote_user self.private_key_file = options.private_key_file self.ssh_common_args = options.ssh_common_args diff --git a/lib/ansible/plugins/connection/docker.py b/lib/ansible/plugins/connection/docker.py index 4e08f56a09..96d4355f92 100644 --- a/lib/ansible/plugins/connection/docker.py +++ b/lib/ansible/plugins/connection/docker.py @@ -69,12 +69,15 @@ class Connection(ConnectionBase): # root. if 'docker_command' in kwargs: - self.docker_cmd = kwargs['docker_command'] + self.docker_cmd = [kwargs['docker_command']] else: - self.docker_cmd = distutils.spawn.find_executable('docker') - if not self.docker_cmd: + self.docker_cmd = [distutils.spawn.find_executable('docker')] + if not self.docker_cmd[0]: raise AnsibleError("docker command not found in PATH") + if play_context.connection_args: + self.docker_cmd = self.docker_cmd + play_context.connection_args.split(' ') + self.can_copy_bothways = False docker_version = self._get_docker_version() @@ -91,7 +94,7 @@ class Connection(ConnectionBase): def _get_docker_version(self): - cmd = [self.docker_cmd, 'version'] + cmd = self.docker_cmd + ['version'] cmd_output = subprocess.check_output(cmd) for line in cmd_output.split('\n'): @@ -99,10 +102,7 @@ class Connection(ConnectionBase): return self._sanitize_version(line.split()[2]) # no result yet, must be newer Docker version - new_docker_cmd = [ - self.docker_cmd, - 'version', '--format', "'{{.Server.Version}}'" - ] + new_docker_cmd = self.docker_cmd + ['version', '--format', "'{{.Server.Version}}'"] cmd_output = subprocess.check_output(new_docker_cmd) @@ -123,7 +123,7 @@ class Connection(ConnectionBase): executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh' # -i is needed to keep stdin open which allows pipelining to work - 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] display.vvv("EXEC %s" % (local_cmd), host=self._play_context.remote_addr) p = subprocess.Popen(local_cmd, shell=False, stdin=subprocess.PIPE, @@ -158,7 +158,7 @@ class Connection(ConnectionBase): if self.can_copy_bothways: # only docker >= 1.8.1 can do this natively - args = [ self.docker_cmd, "cp", in_path, "%s:%s" % (self._play_context.remote_addr, out_path) ] + args = self.docker_cmd + ["cp", in_path, "%s:%s" % (self._play_context.remote_addr, out_path) ] p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: @@ -168,7 +168,7 @@ class Connection(ConnectionBase): # Older docker doesn't have native support for copying files into # running containers, so we use docker exec to implement this executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh' - args = [self.docker_cmd, "exec", "-i", self._play_context.remote_addr, executable, "-c", + args = self.docker_cmd + ["exec", "-i", self._play_context.remote_addr, executable, "-c", "dd of={0} bs={1}".format(out_path, BUFSIZE)] with open(in_path, 'rb') as in_file: try: @@ -191,7 +191,7 @@ class Connection(ConnectionBase): # file path out_dir = os.path.dirname(out_path) - args = [self.docker_cmd, "cp", "%s:%s" % (self._play_context.remote_addr, in_path), out_dir] + args = self.docker_cmd + ["cp", "%s:%s" % (self._play_context.remote_addr, in_path), out_dir] p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) From 870160b8ed73e58280d0374c1c7be9939972eb47 Mon Sep 17 00:00:00 2001 From: Thomas Steinbach Date: Thu, 24 Mar 2016 22:09:41 +0100 Subject: [PATCH 2/2] fixed some breaks after merging ansible/devel --- lib/ansible/playbook/play_context.py | 5 +---- lib/ansible/plugins/connection/docker.py | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/ansible/playbook/play_context.py b/lib/ansible/playbook/play_context.py index cb8692800c..6f276067d7 100644 --- a/lib/ansible/playbook/play_context.py +++ b/lib/ansible/playbook/play_context.py @@ -50,7 +50,6 @@ except ImportError: MAGIC_VARIABLE_MAPPING = dict( connection = ('ansible_connection',), - docker_extra_args = ('ansible_docker_extra_args',), remote_addr = ('ansible_ssh_host', 'ansible_host'), remote_user = ('ansible_ssh_user', 'ansible_user'), port = ('ansible_ssh_port', 'ansible_port'), @@ -66,6 +65,7 @@ MAGIC_VARIABLE_MAPPING = dict( become_exe = ('ansible_become_exe',), become_flags = ('ansible_become_flags',), ssh_common_args = ('ansible_ssh_common_args',), + docker_extra_args= ('ansible_docker_extra_args',), sftp_extra_args = ('ansible_sftp_extra_args',), scp_extra_args = ('ansible_scp_extra_args',), ssh_extra_args = ('ansible_ssh_extra_args',), @@ -258,9 +258,6 @@ class PlayContext(Base): lower precedence than those set on the play or host. ''' - if options.connection: - self.connection = options.connection - # privilege escalation self.become = options.become self.become_method = options.become_method diff --git a/lib/ansible/plugins/connection/docker.py b/lib/ansible/plugins/connection/docker.py index 66184d10f7..df6c870710 100644 --- a/lib/ansible/plugins/connection/docker.py +++ b/lib/ansible/plugins/connection/docker.py @@ -68,10 +68,10 @@ class Connection(ConnectionBase): # root. if 'docker_command' in kwargs: - self.docker_cmd = [kwargs['docker_command']] + self.docker_cmd = kwargs['docker_command'] else: - self.docker_cmd = [distutils.spawn.find_executable('docker')] - if not self.docker_cmd[0]: + self.docker_cmd = distutils.spawn.find_executable('docker') + if not self.docker_cmd: raise AnsibleError("docker command not found in PATH") docker_version = self._get_docker_version() @@ -106,7 +106,13 @@ class Connection(ConnectionBase): def _get_docker_version(self): - cmd = self.docker_cmd + ['version'] + cmd = [self.docker_cmd] + + if self._play_context.docker_extra_args: + cmd += self._play_context.docker_extra_args.split(' ') + + cmd += ['version'] + cmd_output = subprocess.check_output(cmd) for line in cmd_output.split('\n'): @@ -114,7 +120,10 @@ class Connection(ConnectionBase): return self._sanitize_version(line.split()[2]) # no result yet, must be newer Docker version - new_docker_cmd = self.docker_cmd + ['version', '--format', "'{{.Server.Version}}'"] + new_docker_cmd = [ + self.docker_cmd, + 'version', '--format', "'{{.Server.Version}}'" + ] cmd_output = subprocess.check_output(new_docker_cmd)