summaryrefslogtreecommitdiff
path: root/lib/ansible/plugins/connection
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/plugins/connection')
-rw-r--r--lib/ansible/plugins/connection/chroot.py208
-rw-r--r--lib/ansible/plugins/connection/docker.py357
-rw-r--r--lib/ansible/plugins/connection/funcd.py103
-rw-r--r--lib/ansible/plugins/connection/iocage.py83
-rw-r--r--lib/ansible/plugins/connection/jail.py202
-rw-r--r--lib/ansible/plugins/connection/kubectl.py356
-rw-r--r--lib/ansible/plugins/connection/libvirt_lxc.py182
-rw-r--r--lib/ansible/plugins/connection/lxc.py229
-rw-r--r--lib/ansible/plugins/connection/lxd.py126
-rw-r--r--lib/ansible/plugins/connection/oc.py174
-rw-r--r--lib/ansible/plugins/connection/qubes.py160
-rw-r--r--lib/ansible/plugins/connection/saltstack.py106
-rw-r--r--lib/ansible/plugins/connection/zone.py201
13 files changed, 0 insertions, 2487 deletions
diff --git a/lib/ansible/plugins/connection/chroot.py b/lib/ansible/plugins/connection/chroot.py
deleted file mode 100644
index d95497b42b..0000000000
--- a/lib/ansible/plugins/connection/chroot.py
+++ /dev/null
@@ -1,208 +0,0 @@
-# Based on local.py (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
-#
-# (c) 2013, Maykel Moya <mmoya@speedyrails.com>
-# (c) 2015, Toshio Kuratomi <tkuratomi@ansible.com>
-# Copyright (c) 2017 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author: Maykel Moya <mmoya@speedyrails.com>
- connection: chroot
- short_description: Interact with local chroot
- description:
- - Run commands or put/fetch files to an existing chroot on the Ansible controller.
- version_added: "1.1"
- options:
- remote_addr:
- description:
- - The path of the chroot you want to access.
- default: inventory_hostname
- vars:
- - name: ansible_host
- executable:
- description:
- - User specified executable shell
- ini:
- - section: defaults
- key: executable
- env:
- - name: ANSIBLE_EXECUTABLE
- vars:
- - name: ansible_executable
- default: /bin/sh
- chroot_exe:
- version_added: '2.8'
- description:
- - User specified chroot binary
- ini:
- - section: chroot_connection
- key: exe
- env:
- - name: ANSIBLE_CHROOT_EXE
- vars:
- - name: ansible_chroot_exe
- default: chroot
-"""
-
-import os
-import os.path
-import subprocess
-import traceback
-
-from ansible.errors import AnsibleError
-from ansible.module_utils.basic import is_executable
-from ansible.module_utils.common.process import get_bin_path
-from ansible.module_utils.six.moves import shlex_quote
-from ansible.module_utils._text import to_bytes, to_native
-from ansible.plugins.connection import ConnectionBase, BUFSIZE
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class Connection(ConnectionBase):
- ''' Local chroot based connections '''
-
- transport = 'chroot'
- has_pipelining = True
- # su currently has an undiagnosed issue with calculating the file
- # checksums (so copy, for instance, doesn't work right)
- # Have to look into that before re-enabling this
- has_tty = False
-
- default_user = 'root'
-
- def __init__(self, play_context, new_stdin, *args, **kwargs):
- super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
-
- self.chroot = self._play_context.remote_addr
-
- if os.geteuid() != 0:
- raise AnsibleError("chroot connection requires running as root")
-
- # we're running as root on the local system so do some
- # trivial checks for ensuring 'host' is actually a chroot'able dir
- if not os.path.isdir(self.chroot):
- raise AnsibleError("%s is not a directory" % self.chroot)
-
- chrootsh = os.path.join(self.chroot, 'bin/sh')
- # Want to check for a usable bourne shell inside the chroot.
- # is_executable() == True is sufficient. For symlinks it
- # gets really complicated really fast. So we punt on finding that
- # out. As long as it's a symlink we assume that it will work
- if not (is_executable(chrootsh) or (os.path.lexists(chrootsh) and os.path.islink(chrootsh))):
- raise AnsibleError("%s does not look like a chrootable dir (/bin/sh missing)" % self.chroot)
-
- def _connect(self):
- ''' connect to the chroot '''
- if os.path.isabs(self.get_option('chroot_exe')):
- self.chroot_cmd = self.get_option('chroot_exe')
- else:
- try:
- self.chroot_cmd = get_bin_path(self.get_option('chroot_exe'))
- except ValueError as e:
- raise AnsibleError(to_native(e))
-
- super(Connection, self)._connect()
- if not self._connected:
- display.vvv("THIS IS A LOCAL CHROOT DIR", host=self.chroot)
- self._connected = True
-
- def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE):
- ''' run a command on the chroot. This is only needed for implementing
- put_file() get_file() so that we don't have to read the whole file
- into memory.
-
- compared to exec_command() it looses some niceties like being able to
- return the process's exit code immediately.
- '''
- executable = self.get_option('executable')
- local_cmd = [self.chroot_cmd, self.chroot, executable, '-c', cmd]
-
- display.vvv("EXEC %s" % (local_cmd), host=self.chroot)
- local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
- p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
- return p
-
- def exec_command(self, cmd, in_data=None, sudoable=False):
- ''' run a command on the chroot '''
- super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
-
- p = self._buffered_exec_command(cmd)
-
- stdout, stderr = p.communicate(in_data)
- 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):
- ''' transfer a file from local to chroot '''
- super(Connection, self).put_file(in_path, out_path)
- display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.chroot)
-
- 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:
- if not os.fstat(in_file.fileno()).st_size:
- count = ' count=0'
- else:
- count = ''
- try:
- p = self._buffered_exec_command('dd of=%s bs=%s%s' % (out_path, BUFSIZE, count), stdin=in_file)
- except OSError:
- raise AnsibleError("chroot connection requires dd command in the chroot")
- try:
- stdout, stderr = p.communicate()
- except Exception:
- traceback.print_exc()
- raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
- if p.returncode != 0:
- raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
- except IOError:
- raise AnsibleError("file or module does not exist at: %s" % in_path)
-
- def fetch_file(self, in_path, out_path):
- ''' fetch a file from chroot to local '''
- super(Connection, self).fetch_file(in_path, out_path)
- display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.chroot)
-
- 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:
- raise AnsibleError("chroot connection requires dd command in the chroot")
-
- with open(to_bytes(out_path, errors='surrogate_or_strict'), 'wb+') as out_file:
- try:
- chunk = p.stdout.read(BUFSIZE)
- while chunk:
- out_file.write(chunk)
- chunk = p.stdout.read(BUFSIZE)
- except Exception:
- traceback.print_exc()
- raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
- stdout, stderr = p.communicate()
- if p.returncode != 0:
- raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
-
- def close(self):
- ''' terminate the connection; nothing to do here '''
- super(Connection, self).close()
- self._connected = False
diff --git a/lib/ansible/plugins/connection/docker.py b/lib/ansible/plugins/connection/docker.py
deleted file mode 100644
index 380a84d877..0000000000
--- a/lib/ansible/plugins/connection/docker.py
+++ /dev/null
@@ -1,357 +0,0 @@
-# Based on the chroot connection plugin by Maykel Moya
-#
-# (c) 2014, Lorin Hochstein
-# (c) 2015, Leendert Brouwer (https://github.com/objectified)
-# (c) 2015, Toshio Kuratomi <tkuratomi@ansible.com>
-# Copyright (c) 2017 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author:
- - Lorin Hochestein
- - Leendert Brouwer
- connection: docker
- short_description: Run tasks in docker containers
- description:
- - Run commands or put/fetch files to an existing docker container.
- version_added: "2.0"
- options:
- remote_user:
- description:
- - The user to execute as inside the container
- vars:
- - name: ansible_user
- - name: ansible_docker_user
- docker_extra_args:
- description:
- - Extra arguments to pass to the docker command line
- default: ''
- remote_addr:
- description:
- - The name of the container you want to access.
- default: inventory_hostname
- vars:
- - name: ansible_host
- - name: ansible_docker_host
-"""
-
-import distutils.spawn
-import fcntl
-import os
-import os.path
-import subprocess
-import re
-
-from distutils.version import LooseVersion
-
-import ansible.constants as C
-from ansible.compat import selectors
-from ansible.errors import AnsibleError, AnsibleFileNotFound
-from ansible.module_utils.six.moves import shlex_quote
-from ansible.module_utils._text import to_bytes, to_native, to_text
-from ansible.plugins.connection import ConnectionBase, BUFSIZE
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class Connection(ConnectionBase):
- ''' Local docker based connections '''
-
- transport = 'docker'
- has_pipelining = True
-
- def __init__(self, play_context, new_stdin, *args, **kwargs):
- super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
-
- # Note: docker supports running as non-root in some configurations.
- # (For instance, setting the UNIX socket file to be readable and
- # writable by a specific UNIX group and then putting users into that
- # group). Therefore we don't check that the user is root when using
- # this connection. But if the user is getting a permission denied
- # 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.
-
- # Windows uses Powershell modules
- if getattr(self._shell, "_IS_WINDOWS", False):
- self.module_implementation_preferences = ('.ps1', '.exe', '')
-
- if 'docker_command' in kwargs:
- self.docker_cmd = kwargs['docker_command']
- else:
- 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()
- if docker_version == u'dev':
- display.warning(u'Docker version number is "dev". Will assume latest version.')
- if docker_version != u'dev' and LooseVersion(docker_version) < LooseVersion(u'1.3'):
- raise AnsibleError('docker connection type requires docker 1.3 or higher')
-
- # The remote user we will request from docker (if supported)
- self.remote_user = None
- # The actual user which will execute commands in docker (if known)
- self.actual_user = None
-
- if self._play_context.remote_user is not None:
- if docker_version == u'dev' or LooseVersion(docker_version) >= LooseVersion(u'1.7'):
- # Support for specifying the exec user was added in docker 1.7
- self.remote_user = self._play_context.remote_user
- self.actual_user = self.remote_user
- else:
- self.actual_user = self._get_docker_remote_user()
-
- if self.actual_user != self._play_context.remote_user:
- display.warning(u'docker {0} does not support remote_user, using container default: {1}'
- .format(docker_version, self.actual_user or u'?'))
- elif self._display.verbosity > 2:
- # Since we're not setting the actual_user, look it up so we have it for logging later
- # Only do this if display verbosity is high enough that we'll need the value
- # This saves overhead from calling into docker when we don't need to
- self.actual_user = self._get_docker_remote_user()
-
- @staticmethod
- def _sanitize_version(version):
- return re.sub(u'[^0-9a-zA-Z.]', u'', version)
-
- def _old_docker_version(self):
- cmd_args = []
- if self._play_context.docker_extra_args:
- cmd_args += self._play_context.docker_extra_args.split(' ')
-
- old_version_subcommand = ['version']
-
- old_docker_cmd = [self.docker_cmd] + cmd_args + old_version_subcommand
- p = subprocess.Popen(old_docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- cmd_output, err = p.communicate()
-
- return old_docker_cmd, to_native(cmd_output), err, p.returncode
-
- def _new_docker_version(self):
- # no result yet, must be newer Docker version
- cmd_args = []
- if self._play_context.docker_extra_args:
- cmd_args += self._play_context.docker_extra_args.split(' ')
-
- new_version_subcommand = ['version', '--format', "'{{.Server.Version}}'"]
-
- new_docker_cmd = [self.docker_cmd] + cmd_args + new_version_subcommand
- p = subprocess.Popen(new_docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- cmd_output, err = p.communicate()
- return new_docker_cmd, to_native(cmd_output), err, p.returncode
-
- def _get_docker_version(self):
-
- cmd, cmd_output, err, returncode = self._old_docker_version()
- if returncode == 0:
- for line in to_text(cmd_output, errors='surrogate_or_strict').split(u'\n'):
- if line.startswith(u'Server version:'): # old docker versions
- return self._sanitize_version(line.split()[2])
-
- cmd, cmd_output, err, returncode = self._new_docker_version()
- if returncode:
- raise AnsibleError('Docker version check (%s) failed: %s' % (to_native(cmd), to_native(err)))
-
- return self._sanitize_version(to_text(cmd_output, errors='surrogate_or_strict'))
-
- def _get_docker_remote_user(self):
- """ Get the default user configured in the docker container """
- p = subprocess.Popen([self.docker_cmd, 'inspect', '--format', '{{.Config.User}}', self._play_context.remote_addr],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
- out, err = p.communicate()
- out = to_text(out, errors='surrogate_or_strict')
-
- if p.returncode != 0:
- display.warning(u'unable to retrieve default user from docker container: %s %s' % (out, to_text(err)))
- return None
-
- # The default exec user is root, unless it was changed in the Dockerfile with USER
- return out.strip() or u'root'
-
- def _build_exec_cmd(self, cmd):
- """ Build the local docker exec command to run cmd on remote_host
-
- If remote_user is available and is supported by the docker
- version we are using, it will be provided to docker exec.
- """
-
- local_cmd = [self.docker_cmd]
-
- if self._play_context.docker_extra_args:
- local_cmd += self._play_context.docker_extra_args.split(' ')
-
- local_cmd += [b'exec']
-
- if self.remote_user is not None:
- local_cmd += [b'-u', self.remote_user]
-
- # -i is needed to keep stdin open which allows pipelining to work
- local_cmd += [b'-i', self._play_context.remote_addr] + cmd
-
- return local_cmd
-
- def _connect(self, port=None):
- """ Connect to the container. Nothing to do """
- super(Connection, self)._connect()
- if not self._connected:
- display.vvv(u"ESTABLISH DOCKER CONNECTION FOR USER: {0}".format(
- self.actual_user or u'?'), host=self._play_context.remote_addr
- )
- self._connected = True
-
- def exec_command(self, cmd, in_data=None, sudoable=False):
- """ Run a command on the docker host """
- super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
-
- local_cmd = self._build_exec_cmd([self._play_context.executable, '-c', cmd])
-
- display.vvv(u"EXEC {0}".format(to_text(local_cmd)), host=self._play_context.remote_addr)
- display.debug("opening command with Popen()")
-
- local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
-
- p = subprocess.Popen(
- local_cmd,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- )
- display.debug("done running command with Popen()")
-
- if self.become and self.become.expect_prompt() and sudoable:
- fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
- fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) | os.O_NONBLOCK)
- selector = selectors.DefaultSelector()
- selector.register(p.stdout, selectors.EVENT_READ)
- selector.register(p.stderr, selectors.EVENT_READ)
-
- become_output = b''
- try:
- while not self.become.check_success(become_output) and not self.become.check_password_prompt(become_output):
- events = selector.select(self._play_context.timeout)
- if not events:
- stdout, stderr = p.communicate()
- raise AnsibleError('timeout waiting for privilege escalation password prompt:\n' + to_native(become_output))
-
- for key, event in events:
- if key.fileobj == p.stdout:
- chunk = p.stdout.read()
- elif key.fileobj == p.stderr:
- chunk = p.stderr.read()
-
- if not chunk:
- stdout, stderr = p.communicate()
- raise AnsibleError('privilege output closed while waiting for password prompt:\n' + to_native(become_output))
- become_output += chunk
- finally:
- selector.close()
-
- if not self.become.check_success(become_output):
- become_pass = self.become.get_option('become_pass', playcontext=self._play_context)
- p.stdin.write(to_bytes(become_pass, errors='surrogate_or_strict') + b'\n')
- fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK)
- fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) & ~os.O_NONBLOCK)
-
- display.debug("getting output with communicate()")
- stdout, stderr = p.communicate(in_data)
- display.debug("done communicating")
-
- display.debug("done with docker.exec_command()")
- 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):
- """ Transfer a file from local to docker container """
- super(Connection, self).put_file(in_path, out_path)
- 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(to_bytes(in_path, errors='surrogate_or_strict')):
- raise AnsibleFileNotFound(
- "file or module does not exist: %s" % to_native(in_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
- # owner and group of the files are always set to root
- with open(to_bytes(in_path, errors='surrogate_or_strict'), 'rb') as in_file:
- if not os.fstat(in_file.fileno()).st_size:
- count = ' count=0'
- else:
- count = ''
- args = self._build_exec_cmd([self._play_context.executable, "-c", "dd of=%s bs=%s%s" % (out_path, BUFSIZE, count)])
- args = [to_bytes(i, errors='surrogate_or_strict') for i in args]
- try:
- p = subprocess.Popen(args, stdin=in_file,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except OSError:
- raise AnsibleError("docker connection requires dd command in the container to put files")
- stdout, stderr = p.communicate()
-
- if p.returncode != 0:
- raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" %
- (to_native(in_path), to_native(out_path), to_native(stdout), to_native(stderr)))
-
- def fetch_file(self, in_path, out_path):
- """ Fetch a file from container to local. """
- super(Connection, self).fetch_file(in_path, out_path)
- 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
- # 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 = [to_bytes(i, errors='surrogate_or_strict') for i in args]
-
- p = subprocess.Popen(args, stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- p.communicate()
-
- actual_out_path = os.path.join(out_dir, os.path.basename(in_path))
-
- if p.returncode != 0:
- # Older docker doesn't have native support for fetching files command `cp`
- # If `cp` fails, try to use `dd` instead
- args = self._build_exec_cmd([self._play_context.executable, "-c", "dd if=%s bs=%s" % (in_path, BUFSIZE)])
- args = [to_bytes(i, errors='surrogate_or_strict') for i in args]
- with open(to_bytes(actual_out_path, errors='surrogate_or_strict'), 'wb') as out_file:
- try:
- p = subprocess.Popen(args, stdin=subprocess.PIPE,
- stdout=out_file, stderr=subprocess.PIPE)
- except OSError:
- raise AnsibleError("docker connection requires dd command in the container to put files")
- stdout, stderr = p.communicate()
-
- if p.returncode != 0:
- raise AnsibleError("failed to fetch file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
-
- # Rename if needed
- if actual_out_path != out_path:
- os.rename(to_bytes(actual_out_path, errors='strict'), to_bytes(out_path, errors='strict'))
-
- def close(self):
- """ Terminate the connection. Nothing to do for Docker"""
- super(Connection, self).close()
- self._connected = False
diff --git a/lib/ansible/plugins/connection/funcd.py b/lib/ansible/plugins/connection/funcd.py
deleted file mode 100644
index 7bd957550e..0000000000
--- a/lib/ansible/plugins/connection/funcd.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# Based on local.py (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
-# Based on chroot.py (c) 2013, Maykel Moya <mmoya@speedyrails.com>
-# Copyright (c) 2013, Michael Scherer <misc@zarb.org>
-# Copyright (c) 2017 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author: Michael Scherer (@msherer) <misc@zarb.org>
- connection: funcd
- short_description: Use funcd to connect to target
- description:
- - This transport permits you to use Ansible over Func.
- - For people who have already setup func and that wish to play with ansible,
- this permit to move gradually to ansible without having to redo completely the setup of the network.
- version_added: "1.1"
- options:
- remote_addr:
- description:
- - The path of the chroot you want to access.
- default: inventory_hostname
- vars:
- - name: ansible_host
- - name: ansible_func_host
-"""
-
-HAVE_FUNC = False
-try:
- import func.overlord.client as fc
- HAVE_FUNC = True
-except ImportError:
- pass
-
-import os
-import tempfile
-import shutil
-
-from ansible.errors import AnsibleError
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class Connection(object):
- ''' Func-based connections '''
-
- has_pipelining = False
-
- def __init__(self, runner, host, port, *args, **kwargs):
- self.runner = runner
- self.host = host
- # port is unused, this go on func
- self.port = port
-
- def connect(self, port=None):
- if not HAVE_FUNC:
- raise AnsibleError("func is not installed")
-
- self.client = fc.Client(self.host)
- return self
-
- def exec_command(self, cmd, become_user=None, sudoable=False, executable='/bin/sh', in_data=None):
- ''' run a command on the remote minion '''
-
- if in_data:
- raise AnsibleError("Internal Error: this module does not support optimized module pipelining")
-
- # totally ignores privlege escalation
- display.vvv("EXEC %s" % (cmd), host=self.host)
- p = self.client.command.run(cmd)[self.host]
- return (p[0], p[1], p[2])
-
- def _normalize_path(self, path, prefix):
- if not path.startswith(os.path.sep):
- path = os.path.join(os.path.sep, path)
- normpath = os.path.normpath(path)
- return os.path.join(prefix, normpath[1:])
-
- def put_file(self, in_path, out_path):
- ''' transfer a file from local to remote '''
-
- out_path = self._normalize_path(out_path, '/')
- display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.host)
- self.client.local.copyfile.send(in_path, out_path)
-
- def fetch_file(self, in_path, out_path):
- ''' fetch a file from remote to local '''
-
- in_path = self._normalize_path(in_path, '/')
- display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.host)
- # need to use a tmp dir due to difference of semantic for getfile
- # ( who take a # directory as destination) and fetch_file, who
- # take a file directly
- tmpdir = tempfile.mkdtemp(prefix="func_ansible")
- self.client.local.getfile.get(in_path, tmpdir)
- shutil.move(os.path.join(tmpdir, self.host, os.path.basename(in_path)), out_path)
- shutil.rmtree(tmpdir)
-
- def close(self):
- ''' terminate the connection; nothing to do here '''
- pass
diff --git a/lib/ansible/plugins/connection/iocage.py b/lib/ansible/plugins/connection/iocage.py
deleted file mode 100644
index a79a1702c0..0000000000
--- a/lib/ansible/plugins/connection/iocage.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# Based on jail.py
-# (c) 2013, Michael Scherer <misc@zarb.org>
-# (c) 2015, Toshio Kuratomi <tkuratomi@ansible.com>
-# (c) 2016, Stephan Lohse <dev-github@ploek.org>
-# Copyright (c) 2017 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author: Stephan Lohse <dev-github@ploek.org>
- connection: iocage
- short_description: Run tasks in iocage jails
- description:
- - Run commands or put/fetch files to an existing iocage jail
- version_added: "2.0"
- options:
- remote_addr:
- description:
- - Path to the jail
- vars:
- - name: ansible_host
- - name: ansible_iocage_host
- remote_user:
- description:
- - User to execute as inside the jail
- vars:
- - name: ansible_user
- - name: ansible_iocage_user
-"""
-
-import subprocess
-
-from ansible.plugins.connection.jail import Connection as Jail
-from ansible.module_utils._text import to_native
-from ansible.errors import AnsibleError
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class Connection(Jail):
- ''' Local iocage based connections '''
-
- transport = 'iocage'
-
- def __init__(self, play_context, new_stdin, *args, **kwargs):
- self.ioc_jail = play_context.remote_addr
-
- self.iocage_cmd = Jail._search_executable('iocage')
-
- jail_uuid = self.get_jail_uuid()
-
- kwargs[Jail.modified_jailname_key] = 'ioc-{0}'.format(jail_uuid)
-
- display.vvv(u"Jail {iocjail} has been translated to {rawjail}".format(
- iocjail=self.ioc_jail, rawjail=kwargs[Jail.modified_jailname_key]),
- host=kwargs[Jail.modified_jailname_key])
-
- super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
-
- def get_jail_uuid(self):
- p = subprocess.Popen([self.iocage_cmd, 'get', 'host_hostuuid', self.ioc_jail],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
-
- stdout, stderr = p.communicate()
-
- if stdout is not None:
- stdout = to_native(stdout)
-
- if stderr is not None:
- stderr = to_native(stderr)
-
- # otherwise p.returncode would not be set
- p.wait()
-
- if p.returncode != 0:
- raise AnsibleError(u"iocage returned an error: {0}".format(stdout))
-
- return stdout.strip('\n')
diff --git a/lib/ansible/plugins/connection/jail.py b/lib/ansible/plugins/connection/jail.py
deleted file mode 100644
index 161817ba2d..0000000000
--- a/lib/ansible/plugins/connection/jail.py
+++ /dev/null
@@ -1,202 +0,0 @@
-# Based on local.py by Michael DeHaan <michael.dehaan@gmail.com>
-# and chroot.py by Maykel Moya <mmoya@speedyrails.com>
-# Copyright (c) 2013, Michael Scherer <misc@zarb.org>
-# Copyright (c) 2015, Toshio Kuratomi <tkuratomi@ansible.com>
-# Copyright (c) 2017 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author: Ansible Core Team
- connection: jail
- short_description: Run tasks in jails
- description:
- - Run commands or put/fetch files to an existing jail
- version_added: "2.0"
- options:
- remote_addr:
- description:
- - Path to the jail
- default: inventory_hostname
- vars:
- - name: ansible_host
- - name: ansible_jail_host
- remote_user:
- description:
- - User to execute as inside the jail
- vars:
- - name: ansible_user
- - name: ansible_jail_user
-"""
-
-import distutils.spawn
-import os
-import os.path
-import subprocess
-import traceback
-import ansible.constants as C
-
-from ansible.errors import AnsibleError
-from ansible.module_utils.six.moves import shlex_quote
-from ansible.module_utils._text import to_bytes, to_native, to_text
-from ansible.plugins.connection import ConnectionBase, BUFSIZE
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class Connection(ConnectionBase):
- ''' Local BSD Jail based connections '''
-
- modified_jailname_key = 'conn_jail_name'
-
- transport = 'jail'
- # Pipelining may work. Someone needs to test by setting this to True and
- # having pipelining=True in their ansible.cfg
- has_pipelining = True
- has_tty = False
-
- def __init__(self, play_context, new_stdin, *args, **kwargs):
- super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
-
- self.jail = self._play_context.remote_addr
- if self.modified_jailname_key in kwargs:
- self.jail = kwargs[self.modified_jailname_key]
-
- if os.geteuid() != 0:
- raise AnsibleError("jail connection requires running as root")
-
- self.jls_cmd = self._search_executable('jls')
- self.jexec_cmd = self._search_executable('jexec')
-
- if self.jail not in self.list_jails():
- raise AnsibleError("incorrect jail name %s" % self.jail)
-
- @staticmethod
- def _search_executable(executable):
- cmd = distutils.spawn.find_executable(executable)
- if not cmd:
- raise AnsibleError("%s command not found in PATH" % executable)
- return cmd
-
- def list_jails(self):
- p = subprocess.Popen([self.jls_cmd, '-q', 'name'],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
- stdout, stderr = p.communicate()
-
- return to_text(stdout, errors='surrogate_or_strict').split()
-
- def _connect(self):
- ''' connect to the jail; nothing to do here '''
- super(Connection, self)._connect()
- if not self._connected:
- display.vvv(u"ESTABLISH JAIL CONNECTION FOR USER: {0}".format(self._play_context.remote_user), host=self.jail)
- self._connected = True
-
- def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE):
- ''' run a command on the jail. This is only needed for implementing
- put_file() get_file() so that we don't have to read the whole file
- into memory.
-
- compared to exec_command() it looses some niceties like being able to
- return the process's exit code immediately.
- '''
-
- local_cmd = [self.jexec_cmd]
- set_env = ''
-
- if self._play_context.remote_user is not None:
- local_cmd += ['-U', self._play_context.remote_user]
- # update HOME since -U does not update the jail environment
- set_env = 'HOME=~' + self._play_context.remote_user + ' '
-
- local_cmd += [self.jail, self._play_context.executable, '-c', set_env + cmd]
-
- display.vvv("EXEC %s" % (local_cmd,), host=self.jail)
- local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
- p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
- return p
-
- def exec_command(self, cmd, in_data=None, sudoable=False):
- ''' run a command on the jail '''
- super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
-
- p = self._buffered_exec_command(cmd)
-
- stdout, stderr = p.communicate(in_data)
- 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):
- ''' transfer a file from local to jail '''
- super(Connection, self).put_file(in_path, out_path)
- display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.jail)
-
- 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:
- if not os.fstat(in_file.fileno()).st_size:
- count = ' count=0'
- else:
- count = ''
- try:
- p = self._buffered_exec_command('dd of=%s bs=%s%s' % (out_path, BUFSIZE, count), stdin=in_file)
- except OSError:
- raise AnsibleError("jail connection requires dd command in the jail")
- try:
- stdout, stderr = p.communicate()
- except Exception:
- traceback.print_exc()
- raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
- if p.returncode != 0:
- raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, to_native(stdout), to_native(stderr)))
- except IOError:
- raise AnsibleError("file or module does not exist at: %s" % in_path)
-
- def fetch_file(self, in_path, out_path):
- ''' fetch a file from jail to local '''
- super(Connection, self).fetch_file(in_path, out_path)
- display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.jail)
-
- 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:
- raise AnsibleError("jail connection requires dd command in the jail")
-
- with open(to_bytes(out_path, errors='surrogate_or_strict'), 'wb+') as out_file:
- try:
- chunk = p.stdout.read(BUFSIZE)
- while chunk:
- out_file.write(chunk)
- chunk = p.stdout.read(BUFSIZE)
- except Exception:
- traceback.print_exc()
- raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
- stdout, stderr = p.communicate()
- if p.returncode != 0:
- raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, to_native(stdout), to_native(stderr)))
-
- def close(self):
- ''' terminate the connection; nothing to do here '''
- super(Connection, self).close()
- self._connected = False
diff --git a/lib/ansible/plugins/connection/kubectl.py b/lib/ansible/plugins/connection/kubectl.py
deleted file mode 100644
index d8a0fcf697..0000000000
--- a/lib/ansible/plugins/connection/kubectl.py
+++ /dev/null
@@ -1,356 +0,0 @@
-# Based on the docker connection plugin
-#
-# Connection plugin for configuring kubernetes containers with kubectl
-# (c) 2017, XuXinkun <xuxinkun@gmail.com>
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author:
- - xuxinkun
-
- connection: kubectl
-
- short_description: Execute tasks in pods running on Kubernetes.
-
- description:
- - Use the kubectl exec command to run tasks in, or put/fetch files to, pods running on the Kubernetes
- container platform.
-
- version_added: "2.5"
-
- requirements:
- - kubectl (go binary)
-
- options:
- kubectl_pod:
- description:
- - Pod name. Required when the host name does not match pod name.
- default: ''
- vars:
- - name: ansible_kubectl_pod
- env:
- - name: K8S_AUTH_POD
- kubectl_container:
- description:
- - Container name. Required when a pod contains more than one container.
- default: ''
- vars:
- - name: ansible_kubectl_container
- env:
- - name: K8S_AUTH_CONTAINER
- kubectl_namespace:
- description:
- - The namespace of the pod
- default: ''
- vars:
- - name: ansible_kubectl_namespace
- env:
- - name: K8S_AUTH_NAMESPACE
- kubectl_extra_args:
- description:
- - Extra arguments to pass to the kubectl command line.
- default: ''
- vars:
- - name: ansible_kubectl_extra_args
- env:
- - name: K8S_AUTH_EXTRA_ARGS
- kubectl_kubeconfig:
- description:
- - Path to a kubectl config file. Defaults to I(~/.kube/config)
- default: ''
- vars:
- - name: ansible_kubectl_kubeconfig
- - name: ansible_kubectl_config
- env:
- - name: K8S_AUTH_KUBECONFIG
- kubectl_context:
- description:
- - The name of a context found in the K8s config file.
- default: ''
- vars:
- - name: ansible_kubectl_context
- env:
- - name: k8S_AUTH_CONTEXT
- kubectl_host:
- description:
- - URL for accessing the API.
- default: ''
- vars:
- - name: ansible_kubectl_host
- - name: ansible_kubectl_server
- env:
- - name: K8S_AUTH_HOST
- - name: K8S_AUTH_SERVER
- kubectl_username:
- description:
- - Provide a username for authenticating with the API.
- default: ''
- vars:
- - name: ansible_kubectl_username
- - name: ansible_kubectl_user
- env:
- - name: K8S_AUTH_USERNAME
- kubectl_password:
- description:
- - Provide a password for authenticating with the API.
- default: ''
- vars:
- - name: ansible_kubectl_password
- env:
- - name: K8S_AUTH_PASSWORD
- kubectl_token:
- description:
- - API authentication bearer token.
- vars:
- - name: ansible_kubectl_token
- - name: ansible_kubectl_api_key
- env:
- - name: K8S_AUTH_TOKEN
- - name: K8S_AUTH_API_KEY
- client_cert:
- description:
- - Path to a certificate used to authenticate with the API.
- default: ''
- vars:
- - name: ansible_kubectl_cert_file
- - name: ansible_kubectl_client_cert
- env:
- - name: K8S_AUTH_CERT_FILE
- aliases: [ kubectl_cert_file ]
- client_key:
- description:
- - Path to a key file used to authenticate with the API.
- default: ''
- vars:
- - name: ansible_kubectl_key_file
- - name: ansible_kubectl_client_key
- env:
- - name: K8S_AUTH_KEY_FILE
- aliases: [ kubectl_key_file ]
- ca_cert:
- description:
- - Path to a CA certificate used to authenticate with the API.
- default: ''
- vars:
- - name: ansible_kubectl_ssl_ca_cert
- - name: ansible_kubectl_ca_cert
- env:
- - name: K8S_AUTH_SSL_CA_CERT
- aliases: [ kubectl_ssl_ca_cert ]
- validate_certs:
- description:
- - Whether or not to verify the API server's SSL certificate. Defaults to I(true).
- default: ''
- vars:
- - name: ansible_kubectl_verify_ssl
- - name: ansible_kubectl_validate_certs
- env:
- - name: K8S_AUTH_VERIFY_SSL
- aliases: [ kubectl_verify_ssl ]
-"""
-
-import distutils.spawn
-import os
-import os.path
-import subprocess
-
-import ansible.constants as C
-from ansible.parsing.yaml.loader import AnsibleLoader
-from ansible.errors import AnsibleError, AnsibleFileNotFound
-from ansible.module_utils.six.moves import shlex_quote
-from ansible.module_utils._text import to_bytes
-from ansible.plugins.connection import ConnectionBase, BUFSIZE
-from ansible.utils.display import Display
-
-display = Display()
-
-
-CONNECTION_TRANSPORT = 'kubectl'
-
-CONNECTION_OPTIONS = {
- 'kubectl_container': '-c',
- 'kubectl_namespace': '-n',
- 'kubectl_kubeconfig': '--kubeconfig',
- 'kubectl_context': '--context',
- 'kubectl_host': '--server',
- 'kubectl_username': '--username',
- 'kubectl_password': '--password',
- 'client_cert': '--client-certificate',
- 'client_key': '--client-key',
- 'ca_cert': '--certificate-authority',
- 'validate_certs': '--insecure-skip-tls-verify',
- 'kubectl_token': '--token'
-}
-
-
-class Connection(ConnectionBase):
- ''' Local kubectl based connections '''
-
- transport = CONNECTION_TRANSPORT
- connection_options = CONNECTION_OPTIONS
- documentation = DOCUMENTATION
- has_pipelining = True
- transport_cmd = None
-
- def __init__(self, play_context, new_stdin, *args, **kwargs):
- super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
-
- # Note: kubectl runs commands as the user that started the container.
- # It is impossible to set the remote user for a kubectl connection.
- cmd_arg = '{0}_command'.format(self.transport)
- if cmd_arg in kwargs:
- self.transport_cmd = kwargs[cmd_arg]
- else:
- self.transport_cmd = distutils.spawn.find_executable(self.transport)
- if not self.transport_cmd:
- raise AnsibleError("{0} command not found in PATH".format(self.transport))
-
- def _build_exec_cmd(self, cmd):
- """ Build the local kubectl exec command to run cmd on remote_host
- """
- local_cmd = [self.transport_cmd]
-
- # Build command options based on doc string
- doc_yaml = AnsibleLoader(self.documentation).get_single_data()
- for key in doc_yaml.get('options'):
- if key.endswith('verify_ssl') and self.get_option(key) != '':
- # Translate verify_ssl to skip_verify_ssl, and output as string
- skip_verify_ssl = not self.get_option(key)
- local_cmd.append(u'{0}={1}'.format(self.connection_options[key], str(skip_verify_ssl).lower()))
- elif not key.endswith('container') and self.get_option(key) and self.connection_options.get(key):
- cmd_arg = self.connection_options[key]
- local_cmd += [cmd_arg, self.get_option(key)]
-
- extra_args_name = u'{0}_extra_args'.format(self.transport)
- if self.get_option(extra_args_name):
- local_cmd += self.get_option(extra_args_name).split(' ')
-
- pod = self.get_option(u'{0}_pod'.format(self.transport))
- if not pod:
- pod = self._play_context.remote_addr
- # -i is needed to keep stdin open which allows pipelining to work
- local_cmd += ['exec', '-i', pod]
-
- # if the pod has more than one container, then container is required
- container_arg_name = u'{0}_container'.format(self.transport)
- if self.get_option(container_arg_name):
- local_cmd += ['-c', self.get_option(container_arg_name)]
-
- local_cmd += ['--'] + cmd
-
- return local_cmd
-
- def _connect(self, port=None):
- """ Connect to the container. Nothing to do """
- super(Connection, self)._connect()
- if not self._connected:
- display.vvv(u"ESTABLISH {0} CONNECTION".format(self.transport), host=self._play_context.remote_addr)
- self._connected = True
-
- def exec_command(self, cmd, in_data=None, sudoable=False):
- """ Run a command in the container """
- super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
-
- local_cmd = self._build_exec_cmd([self._play_context.executable, '-c', cmd])
-
- display.vvv("EXEC %s" % (local_cmd,), host=self._play_context.remote_addr)
- local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
- p = subprocess.Popen(local_cmd, shell=False, stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
- stdout, stderr = p.communicate(in_data)
- 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):
- """ Transfer a file from local to the container """
- super(Connection, self).put_file(in_path, out_path)
- 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(to_bytes(in_path, errors='surrogate_or_strict')):
- raise AnsibleFileNotFound(
- "file or module does not exist: %s" % in_path)
-
- out_path = shlex_quote(out_path)
- # kubectl doesn't have native support for copying files into
- # running containers, so we use kubectl exec to implement this
- with open(to_bytes(in_path, errors='surrogate_or_strict'), 'rb') as in_file:
- if not os.fstat(in_file.fileno()).st_size:
- count = ' count=0'
- else:
- count = ''
- args = self._build_exec_cmd([self._play_context.executable, "-c", "dd of=%s bs=%s%s" % (out_path, BUFSIZE, count)])
- args = [to_bytes(i, errors='surrogate_or_strict') for i in args]
- try:
- p = subprocess.Popen(args, stdin=in_file,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except OSError:
- raise AnsibleError("kubectl connection requires dd command in the container to put files")
- stdout, stderr = p.communicate()
-
- if p.returncode != 0:
- raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
-
- def fetch_file(self, in_path, out_path):
- """ Fetch a file from container to local. """
- super(Connection, self).fetch_file(in_path, out_path)
- 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_dir = os.path.dirname(out_path)
-
- # kubectl doesn't have native support for fetching files from
- # running containers, so we use kubectl exec to implement this
- args = self._build_exec_cmd([self._play_context.executable, "-c", "dd if=%s bs=%s" % (in_path, BUFSIZE)])
- args = [to_bytes(i, errors='surrogate_or_strict') for i in args]
- actual_out_path = os.path.join(out_dir, os.path.basename(in_path))
- with open(to_bytes(actual_out_path, errors='surrogate_or_strict'), 'wb') as out_file:
- try:
- p = subprocess.Popen(args, stdin=subprocess.PIPE,
- stdout=out_file, stderr=subprocess.PIPE)
- except OSError:
- raise AnsibleError(
- "{0} connection requires dd command in the container to fetch files".format(self.transport)
- )
- stdout, stderr = p.communicate()
-
- if p.returncode != 0:
- raise AnsibleError("failed to fetch file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
-
- if actual_out_path != out_path:
- os.rename(to_bytes(actual_out_path, errors='strict'), to_bytes(out_path, errors='strict'))
-
- def close(self):
- """ Terminate the connection. Nothing to do for kubectl"""
- super(Connection, self).close()
- self._connected = False
diff --git a/lib/ansible/plugins/connection/libvirt_lxc.py b/lib/ansible/plugins/connection/libvirt_lxc.py
deleted file mode 100644
index 99525bcbfb..0000000000
--- a/lib/ansible/plugins/connection/libvirt_lxc.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# Based on local.py (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
-# Based on chroot.py (c) 2013, Maykel Moya <mmoya@speedyrails.com>
-# (c) 2013, Michael Scherer <misc@zarb.org>
-# (c) 2015, Toshio Kuratomi <tkuratomi@ansible.com>
-# (c) 2017 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author: Michael Scherer <misc@zarb.org>
- connection: libvirt_lxc
- short_description: Run tasks in lxc containers via libvirt
- description:
- - Run commands or put/fetch files to an existing lxc container using libvirt
- version_added: "2.0"
- options:
- remote_addr:
- description:
- - Container identifier
- default: The set user as per docker's configuration
- vars:
- - name: ansible_host
- - name: ansible_libvirt_lxc_host
-"""
-
-import distutils.spawn
-import os
-import os.path
-import subprocess
-import traceback
-
-from ansible import constants as C
-from ansible.errors import AnsibleError
-from ansible.module_utils.six.moves import shlex_quote
-from ansible.module_utils._text import to_bytes
-from ansible.plugins.connection import ConnectionBase, BUFSIZE
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class Connection(ConnectionBase):
- ''' Local lxc based connections '''
-
- transport = 'libvirt_lxc'
- has_pipelining = True
- # su currently has an undiagnosed issue with calculating the file
- # checksums (so copy, for instance, doesn't work right)
- # Have to look into that before re-enabling this
- default_user = 'root'
- has_tty = False
-
- def __init__(self, play_context, new_stdin, *args, **kwargs):
- super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
- self.lxc = self._play_context.remote_addr
-
- self.virsh = self._search_executable('virsh')
-
- self._check_domain(self.lxc)
-
- def _search_executable(self, executable):
- cmd = distutils.spawn.find_executable(executable)
- if not cmd:
- raise AnsibleError("%s command not found in PATH") % executable
- return cmd
-
- def _check_domain(self, domain):
- p = subprocess.Popen([self.virsh, '-q', '-c', 'lxc:///', 'dominfo', to_bytes(domain)],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- p.communicate()
- if p.returncode:
- raise AnsibleError("%s is not a lxc defined in libvirt" % domain)
-
- def _connect(self):
- ''' connect to the lxc; nothing to do here '''
- super(Connection, self)._connect()
- if not self._connected:
- display.vvv("THIS IS A LOCAL LXC DIR", host=self.lxc)
- self._connected = True
-
- def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE):
- ''' run a command on the chroot. This is only needed for implementing
- put_file() get_file() so that we don't have to read the whole file
- into memory.
-
- compared to exec_command() it looses some niceties like being able to
- return the process's exit code immediately.
- '''
- executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh'
- local_cmd = [self.virsh, '-q', '-c', 'lxc:///', 'lxc-enter-namespace']
-
- if C.DEFAULT_LIBVIRT_LXC_NOSECLABEL:
- local_cmd += ['--noseclabel']
-
- local_cmd += [self.lxc, '--', executable, '-c', cmd]
-
- display.vvv("EXEC %s" % (local_cmd,), host=self.lxc)
- local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
- p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
- return p
-
- def exec_command(self, cmd, in_data=None, sudoable=False):
- ''' run a command on the chroot '''
- super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
-
- p = self._buffered_exec_command(cmd)
-
- stdout, stderr = p.communicate(in_data)
- 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):
- ''' transfer a file from local to lxc '''
- super(Connection, self).put_file(in_path, out_path)
- display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.lxc)
-
- 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:
- if not os.fstat(in_file.fileno()).st_size:
- count = ' count=0'
- else:
- count = ''
- try:
- p = self._buffered_exec_command('dd of=%s bs=%s%s' % (out_path, BUFSIZE, count), stdin=in_file)
- except OSError:
- raise AnsibleError("chroot connection requires dd command in the chroot")
- try:
- stdout, stderr = p.communicate()
- except Exception:
- traceback.print_exc()
- raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
- if p.returncode != 0:
- raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
- except IOError:
- raise AnsibleError("file or module does not exist at: %s" % in_path)
-
- def fetch_file(self, in_path, out_path):
- ''' fetch a file from lxc to local '''
- super(Connection, self).fetch_file(in_path, out_path)
- display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.lxc)
-
- 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:
- raise AnsibleError("chroot connection requires dd command in the chroot")
-
- with open(to_bytes(out_path, errors='surrogate_or_strict'), 'wb+') as out_file:
- try:
- chunk = p.stdout.read(BUFSIZE)
- while chunk:
- out_file.write(chunk)
- chunk = p.stdout.read(BUFSIZE)
- except Exception:
- traceback.print_exc()
- raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
- stdout, stderr = p.communicate()
- if p.returncode != 0:
- raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
-
- def close(self):
- ''' terminate the connection; nothing to do here '''
- super(Connection, self).close()
- self._connected = False
diff --git a/lib/ansible/plugins/connection/lxc.py b/lib/ansible/plugins/connection/lxc.py
deleted file mode 100644
index 42276a8eab..0000000000
--- a/lib/ansible/plugins/connection/lxc.py
+++ /dev/null
@@ -1,229 +0,0 @@
-# (c) 2015, Joerg Thalheim <joerg@higgsboson.tk>
-# Copyright (c) 2017 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author: Joerg Thalheim <joerg@higgsboson.tk>
- connection: lxc
- short_description: Run tasks in lxc containers via lxc python library
- description:
- - Run commands or put/fetch files to an existing lxc container using lxc python library
- version_added: "2.0"
- options:
- remote_addr:
- description:
- - Container identifier
- default: inventory_hostname
- vars:
- - name: ansible_host
- - name: ansible_lxc_host
- executable:
- default: /bin/sh
- description:
- - Shell executable
- vars:
- - name: ansible_executable
- - name: ansible_lxc_executable
-"""
-
-import os
-import shutil
-import traceback
-import select
-import fcntl
-import errno
-
-HAS_LIBLXC = False
-try:
- import lxc as _lxc
- HAS_LIBLXC = True
-except ImportError:
- pass
-
-from ansible import constants as C
-from ansible import errors
-from ansible.module_utils._text import to_bytes, to_native
-from ansible.plugins.connection import ConnectionBase
-
-
-class Connection(ConnectionBase):
- ''' Local lxc based connections '''
-
- transport = 'lxc'
- has_pipelining = True
- default_user = 'root'
-
- def __init__(self, play_context, new_stdin, *args, **kwargs):
- super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
-
- self.container_name = self._play_context.remote_addr
- self.container = None
-
- def _connect(self):
- ''' connect to the lxc; nothing to do here '''
- super(Connection, self)._connect()
-
- if not HAS_LIBLXC:
- msg = "lxc bindings for python2 are not installed"
- raise errors.AnsibleError(msg)
-
- if self.container:
- return
-
- self._display.vvv("THIS IS A LOCAL LXC DIR", host=self.container_name)
- self.container = _lxc.Container(self.container_name)
- if self.container.state == "STOPPED":
- raise errors.AnsibleError("%s is not running" % self.container_name)
-
- def _communicate(self, pid, in_data, stdin, stdout, stderr):
- buf = {stdout: [], stderr: []}
- read_fds = [stdout, stderr]
- if in_data:
- write_fds = [stdin]
- else:
- write_fds = []
- while len(read_fds) > 0 or len(write_fds) > 0:
- try:
- ready_reads, ready_writes, _ = select.select(read_fds, write_fds, [])
- except select.error as e:
- if e.args[0] == errno.EINTR:
- continue
- raise
- for fd in ready_writes:
- in_data = in_data[os.write(fd, in_data):]
- if len(in_data) == 0:
- write_fds.remove(fd)
- for fd in ready_reads:
- data = os.read(fd, 32768)
- if not data:
- read_fds.remove(fd)
- buf[fd].append(data)
-
- (pid, returncode) = os.waitpid(pid, 0)
-
- return returncode, b"".join(buf[stdout]), b"".join(buf[stderr])
-
- def _set_nonblocking(self, fd):
- flags = fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK
- fcntl.fcntl(fd, fcntl.F_SETFL, flags)
- return fd
-
- def exec_command(self, cmd, in_data=None, sudoable=False):
- ''' run a command on the chroot '''
- super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
-
- # python2-lxc needs bytes. python3-lxc needs text.
- executable = to_native(self._play_context.executable, errors='surrogate_or_strict')
- local_cmd = [executable, '-c', to_native(cmd, errors='surrogate_or_strict')]
-
- read_stdout, write_stdout = None, None
- read_stderr, write_stderr = None, None
- read_stdin, write_stdin = None, None
-
- try:
- read_stdout, write_stdout = os.pipe()
- read_stderr, write_stderr = os.pipe()
-
- kwargs = {
- 'stdout': self._set_nonblocking(write_stdout),
- 'stderr': self._set_nonblocking(write_stderr),
- 'env_policy': _lxc.LXC_ATTACH_CLEAR_ENV
- }
-
- if in_data:
- read_stdin, write_stdin = os.pipe()
- kwargs['stdin'] = self._set_nonblocking(read_stdin)
-
- self._display.vvv("EXEC %s" % (local_cmd), host=self.container_name)
- pid = self.container.attach(_lxc.attach_run_command, local_cmd, **kwargs)
- if pid == -1:
- msg = "failed to attach to container %s" % self.container_name
- raise errors.AnsibleError(msg)
-
- write_stdout = os.close(write_stdout)
- write_stderr = os.close(write_stderr)
- if read_stdin:
- read_stdin = os.close(read_stdin)
-
- return self._communicate(pid,
- in_data,
- write_stdin,
- read_stdout,
- read_stderr)
- finally:
- fds = [read_stdout,
- write_stdout,
- read_stderr,
- write_stderr,
- read_stdin,
- write_stdin]
- for fd in fds:
- if fd:
- os.close(fd)
-
- def put_file(self, in_path, out_path):
- ''' transfer a file from local to lxc '''
- super(Connection, self).put_file(in_path, out_path)
- self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.container_name)
- in_path = to_bytes(in_path, errors='surrogate_or_strict')
- out_path = to_bytes(out_path, errors='surrogate_or_strict')
-
- if not os.path.exists(in_path):
- msg = "file or module does not exist: %s" % in_path
- raise errors.AnsibleFileNotFound(msg)
- try:
- src_file = open(in_path, "rb")
- except IOError:
- traceback.print_exc()
- raise errors.AnsibleError("failed to open input file to %s" % in_path)
- try:
- def write_file(args):
- with open(out_path, 'wb+') as dst_file:
- shutil.copyfileobj(src_file, dst_file)
- try:
- self.container.attach_wait(write_file, None)
- except IOError:
- traceback.print_exc()
- msg = "failed to transfer file to %s" % out_path
- raise errors.AnsibleError(msg)
- finally:
- src_file.close()
-
- def fetch_file(self, in_path, out_path):
- ''' fetch a file from lxc to local '''
- super(Connection, self).fetch_file(in_path, out_path)
- self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.container_name)
- in_path = to_bytes(in_path, errors='surrogate_or_strict')
- out_path = to_bytes(out_path, errors='surrogate_or_strict')
-
- try:
- dst_file = open(out_path, "wb")
- except IOError:
- traceback.print_exc()
- msg = "failed to open output file %s" % out_path
- raise errors.AnsibleError(msg)
- try:
- def write_file(args):
- try:
- with open(in_path, 'rb') as src_file:
- shutil.copyfileobj(src_file, dst_file)
- finally:
- # this is needed in the lxc child process
- # to flush internal python buffers
- dst_file.close()
- try:
- self.container.attach_wait(write_file, None)
- except IOError:
- traceback.print_exc()
- msg = "failed to transfer file from %s to %s" % (in_path, out_path)
- raise errors.AnsibleError(msg)
- finally:
- dst_file.close()
-
- def close(self):
- ''' terminate the connection; nothing to do here '''
- super(Connection, self).close()
- self._connected = False
diff --git a/lib/ansible/plugins/connection/lxd.py b/lib/ansible/plugins/connection/lxd.py
deleted file mode 100644
index 5326cd995c..0000000000
--- a/lib/ansible/plugins/connection/lxd.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# (c) 2016 Matt Clay <matt@mystile.com>
-# (c) 2017 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author: Matt Clay <matt@mystile.com>
- connection: lxd
- short_description: Run tasks in lxc containers via lxc CLI
- description:
- - Run commands or put/fetch files to an existing lxc container using lxc CLI
- version_added: "2.0"
- options:
- remote_addr:
- description:
- - Container identifier
- default: inventory_hostname
- vars:
- - name: ansible_host
- - name: ansible_lxd_host
- executable:
- description:
- - shell to use for execution inside container
- default: /bin/sh
- vars:
- - name: ansible_executable
- - name: ansible_lxd_executable
-"""
-
-import os
-from distutils.spawn import find_executable
-from subprocess import Popen, PIPE
-
-from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound
-from ansible.module_utils._text import to_bytes, to_text
-from ansible.plugins.connection import ConnectionBase
-
-
-class Connection(ConnectionBase):
- """ lxd based connections """
-
- transport = "lxd"
- has_pipelining = True
- default_user = 'root'
-
- def __init__(self, play_context, new_stdin, *args, **kwargs):
- super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
-
- self._host = self._play_context.remote_addr
- self._lxc_cmd = find_executable("lxc")
-
- if not self._lxc_cmd:
- raise AnsibleError("lxc command not found in PATH")
-
- if self._play_context.remote_user is not None and self._play_context.remote_user != 'root':
- self._display.warning('lxd does not support remote_user, using container default: root')
-
- def _connect(self):
- """connect to lxd (nothing to do here) """
- super(Connection, self)._connect()
-
- if not self._connected:
- self._display.vvv(u"ESTABLISH LXD CONNECTION FOR USER: root", host=self._host)
- self._connected = True
-
- def exec_command(self, cmd, in_data=None, sudoable=True):
- """ execute a command on the lxd host """
- super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
-
- self._display.vvv(u"EXEC {0}".format(cmd), host=self._host)
-
- local_cmd = [self._lxc_cmd, "exec", self._host, "--", self._play_context.executable, "-c", cmd]
-
- local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
- in_data = to_bytes(in_data, errors='surrogate_or_strict', nonstring='passthru')
-
- process = Popen(local_cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- stdout, stderr = process.communicate(in_data)
-
- stdout = to_text(stdout)
- stderr = to_text(stderr)
-
- if stderr == "error: Container is not running.\n":
- raise AnsibleConnectionFailure("container not running: %s" % self._host)
-
- if stderr == "error: not found\n":
- raise AnsibleConnectionFailure("container not found: %s" % self._host)
-
- return process.returncode, stdout, stderr
-
- def put_file(self, in_path, out_path):
- """ put a file from local to lxd """
- super(Connection, self).put_file(in_path, out_path)
-
- self._display.vvv(u"PUT {0} TO {1}".format(in_path, out_path), host=self._host)
-
- if not os.path.isfile(to_bytes(in_path, errors='surrogate_or_strict')):
- raise AnsibleFileNotFound("input path is not a file: %s" % in_path)
-
- local_cmd = [self._lxc_cmd, "file", "push", in_path, self._host + "/" + out_path]
-
- local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
-
- process = Popen(local_cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- process.communicate()
-
- def fetch_file(self, in_path, out_path):
- """ fetch a file from lxd to local """
- super(Connection, self).fetch_file(in_path, out_path)
-
- self._display.vvv(u"FETCH {0} TO {1}".format(in_path, out_path), host=self._host)
-
- local_cmd = [self._lxc_cmd, "file", "pull", self._host + "/" + in_path, out_path]
-
- local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
-
- process = Popen(local_cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- process.communicate()
-
- def close(self):
- """ close the connection (nothing to do here) """
- super(Connection, self).close()
-
- self._connected = False
diff --git a/lib/ansible/plugins/connection/oc.py b/lib/ansible/plugins/connection/oc.py
deleted file mode 100644
index 7212e7bce3..0000000000
--- a/lib/ansible/plugins/connection/oc.py
+++ /dev/null
@@ -1,174 +0,0 @@
-# Based on the docker connection plugin
-#
-# Connection plugin for configuring kubernetes containers with kubectl
-# (c) 2017, XuXinkun <xuxinkun@gmail.com>
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author:
- - xuxinkun
-
- connection: oc
-
- short_description: Execute tasks in pods running on OpenShift.
-
- description:
- - Use the oc exec command to run tasks in, or put/fetch files to, pods running on the OpenShift
- container platform.
-
- version_added: "2.5"
-
- requirements:
- - oc (go binary)
-
- options:
- oc_pod:
- description:
- - Pod name. Required when the host name does not match pod name.
- default: ''
- vars:
- - name: ansible_oc_pod
- env:
- - name: K8S_AUTH_POD
- oc_container:
- description:
- - Container name. Required when a pod contains more than one container.
- default: ''
- vars:
- - name: ansible_oc_container
- env:
- - name: K8S_AUTH_CONTAINER
- oc_namespace:
- description:
- - The namespace of the pod
- default: ''
- vars:
- - name: ansible_oc_namespace
- env:
- - name: K8S_AUTH_NAMESPACE
- oc_extra_args:
- description:
- - Extra arguments to pass to the oc command line.
- default: ''
- vars:
- - name: ansible_oc_extra_args
- env:
- - name: K8S_AUTH_EXTRA_ARGS
- oc_kubeconfig:
- description:
- - Path to a oc config file. Defaults to I(~/.kube/conig)
- default: ''
- vars:
- - name: ansible_oc_kubeconfig
- - name: ansible_oc_config
- env:
- - name: K8S_AUTH_KUBECONFIG
- oc_context:
- description:
- - The name of a context found in the K8s config file.
- default: ''
- vars:
- - name: ansible_oc_context
- env:
- - name: k8S_AUTH_CONTEXT
- oc_host:
- description:
- - URL for accessing the API.
- default: ''
- vars:
- - name: ansible_oc_host
- - name: ansible_oc_server
- env:
- - name: K8S_AUTH_HOST
- - name: K8S_AUTH_SERVER
- oc_token:
- description:
- - API authentication bearer token.
- vars:
- - name: ansible_oc_token
- - name: ansible_oc_api_key
- env:
- - name: K8S_AUTH_TOKEN
- - name: K8S_AUTH_API_KEY
- client_cert:
- description:
- - Path to a certificate used to authenticate with the API.
- default: ''
- vars:
- - name: ansible_oc_cert_file
- - name: ansible_oc_client_cert
- env:
- - name: K8S_AUTH_CERT_FILE
- aliases: [ oc_cert_file ]
- client_key:
- description:
- - Path to a key file used to authenticate with the API.
- default: ''
- vars:
- - name: ansible_oc_key_file
- - name: ansible_oc_client_key
- env:
- - name: K8S_AUTH_KEY_FILE
- aliases: [ oc_key_file ]
- ca_cert:
- description:
- - Path to a CA certificate used to authenticate with the API.
- default: ''
- vars:
- - name: ansible_oc_ssl_ca_cert
- - name: ansible_oc_ca_cert
- env:
- - name: K8S_AUTH_SSL_CA_CERT
- aliases: [ oc_ssl_ca_cert ]
- validate_certs:
- description:
- - Whether or not to verify the API server's SSL certificate. Defaults to I(true).
- default: ''
- vars:
- - name: ansible_oc_verify_ssl
- - name: ansible_oc_validate_certs
- env:
- - name: K8S_AUTH_VERIFY_SSL
- aliases: [ oc_verify_ssl ]
-"""
-
-from ansible.plugins.connection.kubectl import Connection as KubectlConnection
-
-
-CONNECTION_TRANSPORT = 'oc'
-
-CONNECTION_OPTIONS = {
- 'oc_container': '-c',
- 'oc_namespace': '-n',
- 'oc_kubeconfig': '--config',
- 'oc_context': '--context',
- 'oc_host': '--server',
- 'client_cert': '--client-certificate',
- 'client_key': '--client-key',
- 'ca_cert': '--certificate-authority',
- 'validate_certs': '--insecure-skip-tls-verify',
- 'oc_token': '--token'
-}
-
-
-class Connection(KubectlConnection):
- ''' Local oc based connections '''
- transport = CONNECTION_TRANSPORT
- connection_options = CONNECTION_OPTIONS
- documentation = DOCUMENTATION
diff --git a/lib/ansible/plugins/connection/qubes.py b/lib/ansible/plugins/connection/qubes.py
deleted file mode 100644
index 58a9467765..0000000000
--- a/lib/ansible/plugins/connection/qubes.py
+++ /dev/null
@@ -1,160 +0,0 @@
-# Based on the buildah connection plugin
-# Copyright (c) 2017 Ansible Project
-# 2018 Kushal Das
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-#
-# Written by: Kushal Das (https://github.com/kushaldas)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-DOCUMENTATION = """
- connection: qubes
- short_description: Interact with an existing QubesOS AppVM
-
- description:
- - Run commands or put/fetch files to an existing Qubes AppVM using qubes tools.
-
- author: Kushal Das (@kushaldas)
-
- version_added: "2.8"
-
- options:
- remote_addr:
- description:
- - vm name
- default: inventory_hostname
- vars:
- - name: ansible_host
- remote_user:
- description:
- - The user to execute as inside the vm.
- default: The *user* account as default in Qubes OS.
- vars:
- - name: ansible_user
-# keyword:
-# - name: hosts
-"""
-
-import shlex
-import shutil
-
-import os
-import base64
-import subprocess
-
-import ansible.constants as C
-from ansible.module_utils._text import to_bytes, to_native
-from ansible.plugins.connection import ConnectionBase, ensure_connect
-from ansible.errors import AnsibleConnectionFailure
-from ansible.utils.display import Display
-
-display = Display()
-
-
-# this _has to be_ named Connection
-class Connection(ConnectionBase):
- """This is a connection plugin for qubes: it uses qubes-run-vm binary to interact with the containers."""
-
- # String used to identify this Connection class from other classes
- transport = 'qubes'
- has_pipelining = True
-
- def __init__(self, play_context, new_stdin, *args, **kwargs):
- super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
-
- self._remote_vmname = self._play_context.remote_addr
- self._connected = False
- # Default username in Qubes
- self.user = "user"
- if self._play_context.remote_user:
- self.user = self._play_context.remote_user
-
- def _qubes(self, cmd=None, in_data=None, shell="qubes.VMShell"):
- """run qvm-run executable
-
- :param cmd: cmd string for remote system
- :param in_data: data passed to qvm-run-vm's stdin
- :return: return code, stdout, stderr
- """
- display.vvvv("CMD: ", cmd)
- if not cmd.endswith("\n"):
- cmd = cmd + "\n"
- local_cmd = []
-
- # For dom0
- local_cmd.extend(["qvm-run", "--pass-io", "--service"])
- if self.user != "user":
- # Means we have a remote_user value
- local_cmd.extend(["-u", self.user])
-
- local_cmd.append(self._remote_vmname)
-
- local_cmd.append(shell)
-
- local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
-
- display.vvvv("Local cmd: ", local_cmd)
-
- display.vvv("RUN %s" % (local_cmd,), host=self._remote_vmname)
- p = subprocess.Popen(local_cmd, shell=False, stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
- # Here we are writing the actual command to the remote bash
- p.stdin.write(to_bytes(cmd, errors='surrogate_or_strict'))
- stdout, stderr = p.communicate(input=in_data)
- return p.returncode, stdout, stderr
-
- def _connect(self):
- """No persistent connection is being maintained."""
- super(Connection, self)._connect()
- self._connected = True
-
- @ensure_connect
- def exec_command(self, cmd, in_data=None, sudoable=False):
- """Run specified command in a running QubesVM """
- super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
-
- display.vvvv("CMD IS: %s" % cmd)
-
- rc, stdout, stderr = self._qubes(cmd)
-
- display.vvvvv("STDOUT %r STDERR %r" % (stderr, stderr))
- return rc, stdout, stderr
-
- def put_file(self, in_path, out_path):
- """ Place a local file located in 'in_path' inside VM at 'out_path' """
- super(Connection, self).put_file(in_path, out_path)
- display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._remote_vmname)
-
- with open(in_path, "rb") as fobj:
- source_data = fobj.read()
-
- retcode, dummy, dummy = self._qubes('cat > "{0}"\n'.format(out_path), source_data, "qubes.VMRootShell")
- # if qubes.VMRootShell service not supported, fallback to qubes.VMShell and
- # hope it will have appropriate permissions
- if retcode == 127:
- retcode, dummy, dummy = self._qubes('cat > "{0}"\n'.format(out_path), source_data)
-
- if retcode != 0:
- raise AnsibleConnectionFailure('Failed to put_file to {0}'.format(out_path))
-
- def fetch_file(self, in_path, out_path):
- """Obtain file specified via 'in_path' from the container and place it at 'out_path' """
- super(Connection, self).fetch_file(in_path, out_path)
- display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._remote_vmname)
-
- # We are running in dom0
- cmd_args_list = ["qvm-run", "--pass-io", self._remote_vmname, "cat {0}".format(in_path)]
- with open(out_path, "wb") as fobj:
- p = subprocess.Popen(cmd_args_list, shell=False, stdout=fobj)
- p.communicate()
- if p.returncode != 0:
- raise AnsibleConnectionFailure('Failed to fetch file to {0}'.format(out_path))
-
- def close(self):
- """ Closing the connection """
- super(Connection, self).close()
- self._connected = False
diff --git a/lib/ansible/plugins/connection/saltstack.py b/lib/ansible/plugins/connection/saltstack.py
deleted file mode 100644
index aacbf048f6..0000000000
--- a/lib/ansible/plugins/connection/saltstack.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# Based on local.py (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
-# Based on chroot.py (c) 2013, Maykel Moya <mmoya@speedyrails.com>
-# Based on func.py
-# (c) 2014, Michael Scherer <misc@zarb.org>
-# (c) 2017 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author: Michael Scherer (@mscherer) <misc@zarb.org>
- connection: saltstack
- short_description: Allow ansible to piggyback on salt minions
- description:
- - This allows you to use existing Saltstack infrastructure to connect to targets.
- version_added: "2.2"
-"""
-
-import re
-import os
-import pty
-import subprocess
-
-from ansible.module_utils._text import to_bytes, to_text
-from ansible.module_utils.six.moves import cPickle
-
-HAVE_SALTSTACK = False
-try:
- import salt.client as sc
- HAVE_SALTSTACK = True
-except ImportError:
- pass
-
-import os
-from ansible import errors
-from ansible.plugins.connection import ConnectionBase
-
-
-class Connection(ConnectionBase):
- ''' Salt-based connections '''
-
- has_pipelining = False
- # while the name of the product is salt, naming that module salt cause
- # trouble with module import
- transport = 'saltstack'
-
- def __init__(self, play_context, new_stdin, *args, **kwargs):
- super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
- self.host = self._play_context.remote_addr
-
- def _connect(self):
- if not HAVE_SALTSTACK:
- raise errors.AnsibleError("saltstack is not installed")
-
- self.client = sc.LocalClient()
- self._connected = True
- return self
-
- def exec_command(self, cmd, sudoable=False, in_data=None):
- ''' run a command on the remote minion '''
- super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
-
- if in_data:
- raise errors.AnsibleError("Internal Error: this module does not support optimized module pipelining")
-
- self._display.vvv("EXEC %s" % (cmd), host=self.host)
- # need to add 'true;' to work around https://github.com/saltstack/salt/issues/28077
- res = self.client.cmd(self.host, 'cmd.exec_code_all', ['bash', 'true;' + cmd])
- if self.host not in res:
- raise errors.AnsibleError("Minion %s didn't answer, check if salt-minion is running and the name is correct" % self.host)
-
- p = res[self.host]
- return (p['retcode'], p['stdout'], p['stderr'])
-
- def _normalize_path(self, path, prefix):
- if not path.startswith(os.path.sep):
- path = os.path.join(os.path.sep, path)
- normpath = os.path.normpath(path)
- return os.path.join(prefix, normpath[1:])
-
- def put_file(self, in_path, out_path):
- ''' transfer a file from local to remote '''
-
- super(Connection, self).put_file(in_path, out_path)
-
- out_path = self._normalize_path(out_path, '/')
- self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.host)
- with open(in_path) as in_fh:
- content = in_fh.read()
- self.client.cmd(self.host, 'file.write', [out_path, content])
-
- # TODO test it
- def fetch_file(self, in_path, out_path):
- ''' fetch a file from remote to local '''
-
- super(Connection, self).fetch_file(in_path, out_path)
-
- in_path = self._normalize_path(in_path, '/')
- self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.host)
- content = self.client.cmd(self.host, 'cp.get_file_str', [in_path])[self.host]
- open(out_path, 'wb').write(content)
-
- def close(self):
- ''' terminate the connection; nothing to do here '''
- pass
diff --git a/lib/ansible/plugins/connection/zone.py b/lib/ansible/plugins/connection/zone.py
deleted file mode 100644
index 119d6e3afb..0000000000
--- a/lib/ansible/plugins/connection/zone.py
+++ /dev/null
@@ -1,201 +0,0 @@
-# Based on local.py (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
-# and chroot.py (c) 2013, Maykel Moya <mmoya@speedyrails.com>
-# and jail.py (c) 2013, Michael Scherer <misc@zarb.org>
-# (c) 2015, Dagobert Michelsen <dam@baltic-online.de>
-# (c) 2015, Toshio Kuratomi <tkuratomi@ansible.com>
-# Copyright (c) 2017 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
- author: Ansible Core Team
- connection: zone
- short_description: Run tasks in a zone instance
- description:
- - Run commands or put/fetch files to an existing zone
- version_added: "2.0"
- options:
- remote_addr:
- description:
- - Zone identifier
- default: inventory_hostname
- vars:
- - name: ansible_host
- - name: ansible_zone_host
-"""
-
-import distutils.spawn
-import os
-import os.path
-import subprocess
-import traceback
-
-from ansible import constants as C
-from ansible.errors import AnsibleError
-from ansible.module_utils.six.moves import shlex_quote
-from ansible.module_utils._text import to_bytes
-from ansible.plugins.connection import ConnectionBase, BUFSIZE
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class Connection(ConnectionBase):
- ''' Local zone based connections '''
-
- transport = 'zone'
- has_pipelining = True
- has_tty = False
-
- def __init__(self, play_context, new_stdin, *args, **kwargs):
- super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
-
- self.zone = self._play_context.remote_addr
-
- if os.geteuid() != 0:
- raise AnsibleError("zone connection requires running as root")
-
- self.zoneadm_cmd = to_bytes(self._search_executable('zoneadm'))
- self.zlogin_cmd = to_bytes(self._search_executable('zlogin'))
-
- if self.zone not in self.list_zones():
- raise AnsibleError("incorrect zone name %s" % self.zone)
-
- @staticmethod
- def _search_executable(executable):
- cmd = distutils.spawn.find_executable(executable)
- if not cmd:
- raise AnsibleError("%s command not found in PATH" % executable)
- return cmd
-
- def list_zones(self):
- process = subprocess.Popen([self.zoneadm_cmd, 'list', '-ip'],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
- zones = []
- for l in process.stdout.readlines():
- # 1:work:running:/zones/work:3126dc59-9a07-4829-cde9-a816e4c5040e:native:shared
- s = l.split(':')
- if s[1] != 'global':
- zones.append(s[1])
-
- return zones
-
- def get_zone_path(self):
- # solaris10vm# zoneadm -z cswbuild list -p
- # -:cswbuild:installed:/zones/cswbuild:479f3c4b-d0c6-e97b-cd04-fd58f2c0238e:native:shared
- process = subprocess.Popen([self.zoneadm_cmd, '-z', to_bytes(self.zone), 'list', '-p'],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
- # stdout, stderr = p.communicate()
- path = process.stdout.readlines()[0].split(':')[3]
- return path + '/root'
-
- def _connect(self):
- ''' connect to the zone; nothing to do here '''
- super(Connection, self)._connect()
- if not self._connected:
- display.vvv("THIS IS A LOCAL ZONE DIR", host=self.zone)
- self._connected = True
-
- def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE):
- ''' run a command on the zone. This is only needed for implementing
- put_file() get_file() so that we don't have to read the whole file
- into memory.
-
- compared to exec_command() it looses some niceties like being able to
- return the process's exit code immediately.
- '''
- # NOTE: zlogin invokes a shell (just like ssh does) so we do not pass
- # this through /bin/sh -c here. Instead it goes through the shell
- # that zlogin selects.
- local_cmd = [self.zlogin_cmd, self.zone, cmd]
- local_cmd = map(to_bytes, local_cmd)
-
- display.vvv("EXEC %s" % (local_cmd), host=self.zone)
- p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
- return p
-
- def exec_command(self, cmd, in_data=None, sudoable=False):
- ''' run a command on the zone '''
- super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
-
- p = self._buffered_exec_command(cmd)
-
- stdout, stderr = p.communicate(in_data)
- 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):
- ''' transfer a file from local to zone '''
- super(Connection, self).put_file(in_path, out_path)
- display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.zone)
-
- out_path = shlex_quote(self._prefix_login_path(out_path))
- try:
- with open(in_path, 'rb') as in_file:
- if not os.fstat(in_file.fileno()).st_size:
- count = ' count=0'
- else:
- count = ''
- try:
- p = self._buffered_exec_command('dd of=%s bs=%s%s' % (out_path, BUFSIZE, count), stdin=in_file)
- except OSError:
- raise AnsibleError("jail connection requires dd command in the jail")
- try:
- stdout, stderr = p.communicate()
- except Exception:
- traceback.print_exc()
- raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
- if p.returncode != 0:
- raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
- except IOError:
- raise AnsibleError("file or module does not exist at: %s" % in_path)
-
- def fetch_file(self, in_path, out_path):
- ''' fetch a file from zone to local '''
- super(Connection, self).fetch_file(in_path, out_path)
- display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.zone)
-
- 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:
- raise AnsibleError("zone connection requires dd command in the zone")
-
- with open(out_path, 'wb+') as out_file:
- try:
- chunk = p.stdout.read(BUFSIZE)
- while chunk:
- out_file.write(chunk)
- chunk = p.stdout.read(BUFSIZE)
- except Exception:
- traceback.print_exc()
- raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
- stdout, stderr = p.communicate()
- if p.returncode != 0:
- raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
-
- def close(self):
- ''' terminate the connection; nothing to do here '''
- super(Connection, self).close()
- self._connected = False