From bba2a42e4467309d80b0e558f758b77d74500ca7 Mon Sep 17 00:00:00 2001 From: David Wilson Date: Sun, 29 Apr 2018 01:37:53 +0100 Subject: [PATCH] ansible: add mitogen_sudo method, split out connection subclasses. Slowly moving towards real implementations in those files. --- ansible_mitogen/connection.py | 40 +++--- .../plugins/connection/mitogen_docker.py | 23 +--- .../plugins/connection/mitogen_jail.py | 23 +--- .../plugins/connection/mitogen_local.py | 25 +--- .../plugins/connection/mitogen_lxc.py | 23 +--- .../plugins/connection/mitogen_lxd.py | 23 +--- .../plugins/connection/mitogen_machinectl.py | 2 + .../plugins/connection/mitogen_setns.py | 2 + .../plugins/connection/mitogen_ssh.py | 25 +--- .../plugins/connection/mitogen_sudo.py | 43 +++++++ docs/ansible.rst | 116 ++++++++++-------- 11 files changed, 163 insertions(+), 182 deletions(-) create mode 100644 ansible_mitogen/plugins/connection/mitogen_sudo.py diff --git a/ansible_mitogen/connection.py b/ansible_mitogen/connection.py index e4d2d786..3350fd3b 100644 --- a/ansible_mitogen/connection.py +++ b/ansible_mitogen/connection.py @@ -146,6 +146,21 @@ def _connect_sudo(spec): } +def _connect_mitogen_sudo(spec): + # sudo as a first-class proxied connection, not a become method. + return { + 'method': 'sudo', + 'kwargs': { + 'username': spec['remote_user'], + 'password': spec['password'], + 'python_path': spec['python_path'], + 'sudo_path': spec['become_exe'], + 'connect_timeout': spec['timeout'], + 'sudo_args': spec['sudo_args'], + } + } + + CONNECTION_METHOD = { 'docker': _connect_docker, 'jail': _connect_jail, @@ -156,6 +171,7 @@ CONNECTION_METHOD = { 'setns': _connect_setns, 'ssh': _connect_ssh, 'sudo': _connect_sudo, + 'mitogen_sudo': _connect_mitogen_sudo, } @@ -576,27 +592,3 @@ class Connection(ansible.plugins.connection.ConnectionBase): in_path=in_path, out_path=out_path ) - - -class SshConnection(Connection): - transport = 'ssh' - - -class LocalConnection(Connection): - transport = 'local' - - -class DockerConnection(Connection): - transport = 'docker' - - -class LxcConnection(Connection): - transport = 'lxc' - - -class LxdConnection(Connection): - transport = 'lxd' - - -class JailConnection(Connection): - transport = 'jail' diff --git a/ansible_mitogen/plugins/connection/mitogen_docker.py b/ansible_mitogen/plugins/connection/mitogen_docker.py index 70a90147..a98273e0 100644 --- a/ansible_mitogen/plugins/connection/mitogen_docker.py +++ b/ansible_mitogen/plugins/connection/mitogen_docker.py @@ -29,21 +29,6 @@ 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: @@ -51,6 +36,8 @@ except ImportError: sys.path.insert(0, os.path.abspath(os.path.join(base_dir, '../../..'))) del base_dir -from ansible_mitogen.connection import DockerConnection as Connection -del os -del sys +import ansible_mitogen.connection + + +class Connection(ansible_mitogen.connection.Connection): + transport = 'docker' diff --git a/ansible_mitogen/plugins/connection/mitogen_jail.py b/ansible_mitogen/plugins/connection/mitogen_jail.py index 24fcb91f..1c57bb38 100644 --- a/ansible_mitogen/plugins/connection/mitogen_jail.py +++ b/ansible_mitogen/plugins/connection/mitogen_jail.py @@ -29,21 +29,6 @@ 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: @@ -51,6 +36,8 @@ except ImportError: 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 +import ansible_mitogen.connection + + +class Connection(ansible_mitogen.connection.Connection): + transport = 'jail' diff --git a/ansible_mitogen/plugins/connection/mitogen_local.py b/ansible_mitogen/plugins/connection/mitogen_local.py index fc1a8565..ebc20788 100644 --- a/ansible_mitogen/plugins/connection/mitogen_local.py +++ b/ansible_mitogen/plugins/connection/mitogen_local.py @@ -29,28 +29,15 @@ 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 + import ansible_mitogen.connection 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 LocalConnection as Connection -del os -del sys +import ansible_mitogen.connection + + +class Connection(ansible_mitogen.connection.Connection): + transport = 'local' diff --git a/ansible_mitogen/plugins/connection/mitogen_lxc.py b/ansible_mitogen/plugins/connection/mitogen_lxc.py index 48d4e03d..2195aa3c 100644 --- a/ansible_mitogen/plugins/connection/mitogen_lxc.py +++ b/ansible_mitogen/plugins/connection/mitogen_lxc.py @@ -29,21 +29,6 @@ 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: @@ -51,6 +36,8 @@ except ImportError: sys.path.insert(0, os.path.abspath(os.path.join(base_dir, '../../..'))) del base_dir -from ansible_mitogen.connection import LxcConnection as Connection -del os -del sys +import ansible_mitogen.connection + + +class Connection(ansible_mitogen.connection.Connection): + transport = 'lxc' diff --git a/ansible_mitogen/plugins/connection/mitogen_lxd.py b/ansible_mitogen/plugins/connection/mitogen_lxd.py index 91fcd0b7..5d1391b9 100644 --- a/ansible_mitogen/plugins/connection/mitogen_lxd.py +++ b/ansible_mitogen/plugins/connection/mitogen_lxd.py @@ -29,21 +29,6 @@ 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: @@ -51,6 +36,8 @@ except ImportError: sys.path.insert(0, os.path.abspath(os.path.join(base_dir, '../../..'))) del base_dir -from ansible_mitogen.connection import LxdConnection as Connection -del os -del sys +import ansible_mitogen.connection + + +class Connection(ansible_mitogen.connection.Connection): + transport = 'lxd' diff --git a/ansible_mitogen/plugins/connection/mitogen_machinectl.py b/ansible_mitogen/plugins/connection/mitogen_machinectl.py index d312c819..e71496a3 100644 --- a/ansible_mitogen/plugins/connection/mitogen_machinectl.py +++ b/ansible_mitogen/plugins/connection/mitogen_machinectl.py @@ -36,6 +36,8 @@ except ImportError: sys.path.insert(0, os.path.abspath(os.path.join(base_dir, '../../..'))) del base_dir +import ansible_mitogen.connection + class Connection(ansible_mitogen.connection.Connection): transport = 'machinectl' diff --git a/ansible_mitogen/plugins/connection/mitogen_setns.py b/ansible_mitogen/plugins/connection/mitogen_setns.py index 7221d6b1..5f131655 100644 --- a/ansible_mitogen/plugins/connection/mitogen_setns.py +++ b/ansible_mitogen/plugins/connection/mitogen_setns.py @@ -36,6 +36,8 @@ except ImportError: sys.path.insert(0, os.path.abspath(os.path.join(base_dir, '../../..'))) del base_dir +import ansible_mitogen.connection + class Connection(ansible_mitogen.connection.Connection): transport = 'setns' diff --git a/ansible_mitogen/plugins/connection/mitogen_ssh.py b/ansible_mitogen/plugins/connection/mitogen_ssh.py index e0a30672..6a5c10f8 100644 --- a/ansible_mitogen/plugins/connection/mitogen_ssh.py +++ b/ansible_mitogen/plugins/connection/mitogen_ssh.py @@ -29,28 +29,15 @@ 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 + import ansible_mitogen.connection 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 SshConnection as Connection -del os -del sys +import ansible_mitogen.connection + + +class Connection(ansible_mitogen.connection.Connection): + transport = 'ssh' diff --git a/ansible_mitogen/plugins/connection/mitogen_sudo.py b/ansible_mitogen/plugins/connection/mitogen_sudo.py new file mode 100644 index 00000000..a6cb8bd2 --- /dev/null +++ b/ansible_mitogen/plugins/connection/mitogen_sudo.py @@ -0,0 +1,43 @@ +# 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 + +try: + import ansible_mitogen.connection +except ImportError: + base_dir = os.path.dirname(__file__) + sys.path.insert(0, os.path.abspath(os.path.join(base_dir, '../../..'))) + del base_dir + +import ansible_mitogen.connection + + +class Connection(ansible_mitogen.connection.Connection): + transport = 'mitogen_sudo' diff --git a/docs/ansible.rst b/docs/ansible.rst index a87382e0..ad739cb5 100644 --- a/docs/ansible.rst +++ b/docs/ansible.rst @@ -122,8 +122,9 @@ Noteworthy Differences `lxc `_, `lxd `_, and `ssh `_ - built-in connection types are supported, along with a Mitogen-specific - ``setns`` container type. File bugs to register interest in more. + built-in connection types are supported, along with Mitogen-specific + :ref:`machinectl `, :ref:`mitogen_sudo `, and + :ref:`setns ` types. File bugs to register interest in others. * Local commands execute in a reuseable interpreter created identically to interpreters on targets. Presently one interpreter per ``become_user`` @@ -455,13 +456,15 @@ connection delegation is supported. * ``ansible_user``: Name of user within the container to execute as. +.. _machinectl: + Machinectl ~~~~~~~~~~ -Behaves like `machinectl +Behaves like `machinectl third party plugin `_ except -connection delegation is supported. This is a lightweight wrapper around the -``setns`` method below. +connection delegation is supported. This is a light wrapper around the +:ref:`setns ` method. * ``ansible_host``: Name of Docker container (default: inventory hostname). * ``ansible_user``: Name of user within the container to execute as. @@ -469,17 +472,44 @@ connection delegation is supported. This is a lightweight wrapper around the as ``/bin/machinectl``. -Sudo -~~~~ +FreeBSD Jails +~~~~~~~~~~~~~ + +Behaves like `jail +`_ except +connection delegation is supported. + +* ``ansible_host``: Name of jail (default: inventory hostname). +* ``ansible_user``: Name of user within the jail to execute as. + + +Local +~~~~~ + +Behaves like `local +`_ except +connection delegation is supported. * ``ansible_python_interpreter`` -* ``ansible_sudo_exe``, ``ansible_become_exe`` -* ``ansible_sudo_user``, ``ansible_become_user`` (default: ``root``) -* ``ansible_sudo_pass``, ``ansible_become_pass`` (default: assume passwordless) -* ``sudo_flags``, ``become_flags`` -* ansible.cfg: ``timeout`` +LXC +~~~ + +Behaves like `lxc +`_ and `lxd +`_ except +connection delegation is supported, and the ``lxc-attach`` tool is always used +rather than the LXC Python bindings, as is usual with the ``lxc`` method. + +The ``lxc-attach`` command must be available on the host machine. + +* ``ansible_python_interpreter`` +* ``ansible_host``: Name of LXC container (default: inventory hostname). + + +.. _setns: + Setns ~~~~~ @@ -503,6 +533,32 @@ root process. as ``/bin/machinectl``. +.. _sudo: + +Sudo +~~~~ + +Sudo can be used as a connection method that supports connection delegation, or +as a become method. + +When used as a become method: + +* ``ansible_python_interpreter`` +* ``ansible_sudo_exe``, ``ansible_become_exe`` +* ``ansible_sudo_user``, ``ansible_become_user`` (default: ``root``) +* ``ansible_sudo_pass``, ``ansible_become_pass`` (default: assume passwordless) +* ``sudo_flags``, ``become_flags`` +* ansible.cfg: ``timeout`` + +When used as the ``mitogen_sudo`` connection method: + +* The inventory hostname is ignored, and may be any value. +* ``ansible_user``: username to sudo as. +* ``ansible_password``: password to sudo as. +* ``sudo_flags``, ``become_flags`` +* ``ansible_python_interpreter`` + + SSH ~~~ @@ -520,42 +576,6 @@ connection delegation is supported. * ``ssh_args``, ``ssh_common_args``, ``ssh_extra_args`` -FreeBSD Jails -~~~~~~~~~~~~~ - -Behaves like `jail -`_ except -connection delegation is supported. - -* ``ansible_host``: Name of jail (default: inventory hostname). -* ``ansible_user``: Name of user within the jail to execute as. - - -Local -~~~~~ - -Behaves like `local -`_ except -connection delegation is supported. - -* ``ansible_python_interpreter`` - - -LXC -~~~ - -Behaves like `lxc -`_ and `lxd -`_ except -conncetion delegation is supported, and the ``lxc-attach`` tool is always used -rather than the LXC Python bindings, as is usual with the ``lxc`` method. - -The ``lxc-attach`` command must be available on the host machine. - -* ``ansible_python_interpreter`` -* ``ansible_host``: Name of LXC container (default: inventory hostname). - - Debugging ---------