diff --git a/docs/api.rst b/docs/api.rst index 1050e62a..6a1ccdd0 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -544,6 +544,22 @@ Router Class # Use the SSH connection to create a sudo connection. remote_root = router.sudo(username='root', via=remote_machine) + .. method:: docker (container=None, image=None, docker_path=None, \**kwargs) + + Arrange for a context to be constructed in an existing or temporary new + Docker container. One of `container` or `image` must be specified. + + Accepts all parameters accepted by :py:meth:`local`, in addition to: + + :param str container: + Existing container to connect to. Defaults to ``None``. + :param str image: + Image tag to use to construct a temporary container. Defaults to + ``None``. + :param str docker_path: + Filename or complete path to the sudo binary. ``PATH`` will be searched + if given as a filename. Defaults to ``sudo``. + .. method:: sudo (username=None, sudo_path=None, password=None, \**kwargs) Arrange for a context to be constructed over a ``sudo`` invocation. The @@ -554,7 +570,6 @@ Router Class :param str username: The ``sudo`` username; defaults to ``root``. - :param str sudo_path: Absolute or relative path to ``sudo``. Defaults to ``sudo``. :param str password: diff --git a/mitogen/docker.py b/mitogen/docker.py new file mode 100644 index 00000000..a1336821 --- /dev/null +++ b/mitogen/docker.py @@ -0,0 +1,67 @@ +# 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 os +import time + +import mitogen.core +import mitogen.parent + + +LOG = logging.getLogger(__name__) + + +class Stream(mitogen.parent.Stream): + container = None + image = None + docker_path = 'docker' + + def construct(self, container=None, image=None, docker_path=None, **kwargs): + assert container or image + super(Stream, self).construct(**kwargs) + if container: + self.container = container + if image: + self.image = image + if docker_path: + self.docker_path = docker_path + + def connect(self): + super(Stream, self).connect() + self.name = 'docker.' + (self.container or self.image) + + def get_boot_command(self): + bits = [self.docker_path] + if self.container: + bits += ['exec', '-i', self.container] + elif self.image: + bits += ['run', '-i', '--rm', self.image] + bits += super(Stream, self).get_boot_command() + LOG.debug('Docker command line: %r', bits) + print bits + return bits diff --git a/mitogen/master.py b/mitogen/master.py index 59225ece..43a94d71 100644 --- a/mitogen/master.py +++ b/mitogen/master.py @@ -630,6 +630,9 @@ class Router(mitogen.parent.Router): self.broker.shutdown() self.broker.join() + def docker(self, **kwargs): + return self.connect('docker', **kwargs) + def local(self, **kwargs): return self.connect('local', **kwargs) diff --git a/mitogen/parent.py b/mitogen/parent.py index a7c4a6b2..53be0726 100644 --- a/mitogen/parent.py +++ b/mitogen/parent.py @@ -224,6 +224,10 @@ def upgrade_router(econtext): ModuleForwarder(econtext.router, econtext.parent, econtext.importer) +def _docker_method(): + import mitogen.docker + return mitogen.docker.Stream + def _local_method(): return mitogen.parent.Stream @@ -237,6 +241,7 @@ def _sudo_method(): METHOD_NAMES = { + 'docker': _docker_method, 'local': _local_method, 'ssh': _ssh_method, 'sudo': _sudo_method,