Merge pull request #222 from dw/dmw

FreeBSD Jail support
pull/225/head
dw 6 years ago committed by GitHub
commit ae7ad88c93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -88,6 +88,18 @@ def _connect_docker(spec):
} }
def _connect_jail(spec):
return {
'method': 'jail',
'kwargs': {
'username': spec['remote_user'],
'container': spec['remote_addr'],
'python_path': spec['python_path'],
'connect_timeout': spec['ansible_ssh_timeout'] or spec['timeout'],
}
}
def _connect_lxc(spec): def _connect_lxc(spec):
return { return {
'method': 'lxc', 'method': 'lxc',
@ -115,6 +127,7 @@ def _connect_sudo(spec):
CONNECTION_METHOD = { CONNECTION_METHOD = {
'docker': _connect_docker, 'docker': _connect_docker,
'jail': _connect_jail,
'local': _connect_local, 'local': _connect_local,
'lxc': _connect_lxc, 'lxc': _connect_lxc,
'lxd': _connect_lxc, 'lxd': _connect_lxc,
@ -515,3 +528,7 @@ class LxcConnection(Connection):
class LxdConnection(Connection): class LxdConnection(Connection):
transport = 'lxd' transport = 'lxd'
class JailConnection(Connection):
transport = 'jail'

@ -0,0 +1,56 @@
# Copyright 2017, David Wilson
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import os.path
import sys
#
# This is not the real Connection implementation module, it simply exists as a
# proxy to the real module, which is loaded using Python's regular import
# mechanism, to prevent Ansible's PluginLoader from making up a fake name that
# results in ansible_mitogen plugin modules being loaded twice: once by
# PluginLoader with a name like "ansible.plugins.connection.mitogen", which is
# stuffed into sys.modules even though attempting to import it will trigger an
# ImportError, and once under its canonical name, "ansible_mitogen.connection".
#
# Therefore we have a proxy module that imports it under the real name, and
# sets up the duff PluginLoader-imported module to just contain objects from
# the real module, so duplicate types don't exist in memory, and things like
# debuggers and isinstance() work predictably.
#
try:
import ansible_mitogen
except ImportError:
base_dir = os.path.dirname(__file__)
sys.path.insert(0, os.path.abspath(os.path.join(base_dir, '../../..')))
del base_dir
from ansible_mitogen.connection import JailConnection as Connection
del os
del sys

@ -68,7 +68,7 @@ def wrap_connection_loader__get(name, play_context, new_stdin, **kwargs):
'mitogen' connection type, passing the original transport name into it as 'mitogen' connection type, passing the original transport name into it as
an argument, so that it can emulate the original type. an argument, so that it can emulate the original type.
""" """
if name in ('ssh', 'local', 'docker', 'lxc', 'lxd'): if name in ('ssh', 'local', 'docker', 'lxc', 'lxd', 'jail'):
name = 'mitogen_' + name name = 'mitogen_' + name
return connection_loader__get(name, play_context, new_stdin, **kwargs) return connection_loader__get(name, play_context, new_stdin, **kwargs)

@ -116,8 +116,8 @@ Noteworthy Differences
* The ``sudo`` become method is available and ``su`` is planned. File bugs to * The ``sudo`` become method is available and ``su`` is planned. File bugs to
register interest in additional methods. register interest in additional methods.
* The ``docker``, ``local``, ``lxc`` and ``ssh`` connection types are * The ``docker``, ``jail``, ``local``, ``lxc``, ``lxd`` and ``ssh`` connection
available, with more planned. File bugs to register interest. types are available, with more planned. File bugs to register interest.
* Local commands execute in a reuseable interpreter created identically to * Local commands execute in a reuseable interpreter created identically to
interpreters on targets. Presently one interpreter per ``become_user`` interpreters on targets. Presently one interpreter per ``become_user``
@ -467,24 +467,29 @@ Sudo
Docker Docker
~~~~~~ ~~~~~~
Docker support is fairly new, expect increased surprises for now. * ``ansible_host``: Name of Docker container (default: inventory hostname).
* ``ansible_host``: Name of Docker container.
* ``ansible_user``: Name of user within the container to execute as. * ``ansible_user``: Name of user within the container to execute as.
FreeBSD Jails
~~~~~~~~~~~~~
* ``ansible_host``: Name of Jail container (default: inventory hostname).
* ``ansible_user``: Name of user within the jail to execute as.
LXC LXC
~~~ ~~~
LXC support is fairly new, expect increased surprises for now. Both ``lxc`` and Both ``lxc`` and ``lxd`` connection plug-ins are hijacked, however the
``lxd`` connection plug-ins are hijacked, however the resulting implementation resulting implementation always uses the ``lxc-attach`` command line tool
always uses the ``lxc-attach`` command line tool rather than th LXC Python rather than the LXC Python bindings, as is usual with the Ansible ``lxd``
bindings. plug-in.
Consequently the ``lxc-attach`` command is required to be available on the host Consequently the ``lxc-attach`` command is required to be available on the host
machine. machine.
* ``ansible_host``: Name of LXC container. * ``ansible_host``: Name of LXC container (default: inventory hostname).
Debugging Debugging

@ -704,7 +704,10 @@ Router Class
Accepts all parameters accepted by :py:meth:`local`, in addition to: Accepts all parameters accepted by :py:meth:`local`, in addition to:
:param str container: :param str container:
Existing container to connect to. Defaults to ``None``. Existing container to connect to. Defaults to :data:`None`.
:param str username:
Username within the container to :func:`setuid` to. Defaults to
:data:`None`, which Docker interprets as ``root``.
:param str image: :param str image:
Image tag to use to construct a temporary container. Defaults to Image tag to use to construct a temporary container. Defaults to
``None``. ``None``.
@ -712,6 +715,22 @@ Router Class
Filename or complete path to the Docker binary. ``PATH`` will be Filename or complete path to the Docker binary. ``PATH`` will be
searched if given as a filename. Defaults to ``docker``. searched if given as a filename. Defaults to ``docker``.
.. method:: jail (container, jexec_path=None, \**kwargs)
Construct a context on the local machine within a FreeBSD jail. The
``jexec`` program must be available.
Accepts all parameters accepted by :py:meth:`local`, in addition to:
:param str container:
Existing container to connect to. Defaults to :data:`None`.
:param str username:
Username within the container to :func:`setuid` to. Defaults to
:data:`None`, which ``jexec`` interprets as ``root``.
:param str jexec_path:
Filename or complete path to the ``jexec`` binary. ``PATH`` will be
searched if given as a filename. Defaults to ``/usr/sbin/jexec``.
.. method:: lxc (container, lxc_attach_path=None, \**kwargs) .. method:: lxc (container, lxc_attach_path=None, \**kwargs)
Construct a context on the local machine within an LXC container. The Construct a context on the local machine within an LXC container. The

@ -488,6 +488,7 @@ class Importer(object):
'docker', 'docker',
'fakessh', 'fakessh',
'fork', 'fork',
'jail',
'lxc', 'lxc',
'master', 'master',
'parent', 'parent',

@ -0,0 +1,63 @@
# Copyright 2017, David Wilson
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import logging
import mitogen.core
import mitogen.parent
LOG = logging.getLogger(__name__)
class Stream(mitogen.parent.Stream):
create_child_args = {
'merge_stdio': True
}
container = None
username = None
jexec_path = '/usr/sbin/jexec'
def construct(self, container, jexec_path=None, username=None, **kwargs):
super(Stream, self).construct(**kwargs)
self.container = container
self.username = username
if jexec_path:
self.jexec_path = jexec_path
def connect(self):
super(Stream, self).connect()
self.name = 'jail.' + self.container
def get_boot_command(self):
bits = [self.jexec_path]
if self.username:
bits += ['-U', self.username]
bits += [self.container]
return bits + super(Stream, self).get_boot_command()

@ -49,7 +49,6 @@ class Stream(mitogen.parent.Stream):
def construct(self, container, lxc_attach_path=None, **kwargs): def construct(self, container, lxc_attach_path=None, **kwargs):
super(Stream, self).construct(**kwargs) super(Stream, self).construct(**kwargs)
if container:
self.container = container self.container = container
if lxc_attach_path: if lxc_attach_path:
self.lxc_attach_path = lxc_attach_apth self.lxc_attach_path = lxc_attach_apth

@ -1008,24 +1008,27 @@ class Router(mitogen.core.Router):
self._context_by_id[context.context_id] = context self._context_by_id[context.context_id] = context
return context return context
def lxc(self, **kwargs):
return self.connect('lxc', **kwargs)
def docker(self, **kwargs): def docker(self, **kwargs):
return self.connect('docker', **kwargs) return self.connect('docker', **kwargs)
def local(self, **kwargs):
return self.connect('local', **kwargs)
def fork(self, **kwargs): def fork(self, **kwargs):
return self.connect('fork', **kwargs) return self.connect('fork', **kwargs)
def sudo(self, **kwargs): def jail(self, **kwargs):
return self.connect('sudo', **kwargs) return self.connect('jail', **kwargs)
def local(self, **kwargs):
return self.connect('local', **kwargs)
def lxc(self, **kwargs):
return self.connect('lxc', **kwargs)
def ssh(self, **kwargs): def ssh(self, **kwargs):
return self.connect('ssh', **kwargs) return self.connect('ssh', **kwargs)
def sudo(self, **kwargs):
return self.connect('sudo', **kwargs)
class ProcessMonitor(object): class ProcessMonitor(object):
def __init__(self): def __init__(self):

Loading…
Cancel
Save