Merge remote-tracking branch 'origin/v027' into stable

* origin/v027:
  docs: update Changelog for release.
  Bump version for release.
  issue #587: update Changelog
  issue #587: ansible: descriptive version check during startup.
  ansible: descriptive version check during startup.
  issue #581: expose mitogen_mask_remote_name variable.
  issue #576: fix Kwargs minor version check.
  issue #574: fix ISSUE_TEMPLATE link
  issue #575: fix exception text rendering
  docs: remove infringing mark
  docs: fix config var scope
  docs: faster stats-preserving redirect
  docs: update ansible page
  issue #570: add firewalld to always-fork list for now.
  docs: removed excess word
  docs: fixed message routing example description
  docs: removed repeated word
  docs: update Changelog; closes #557.
  issue #557: support correct cpu_set_t size
pull/862/head v0.2.7
David Wilson 6 years ago
commit 251642943d

@ -10,7 +10,7 @@ the following checklist as a guide for what to include.
* Have you tried the latest master version from Git? * Have you tried the latest master version from Git?
* Do you have some idea of what the underlying problem may be? * Do you have some idea of what the underlying problem may be?
https://mitogen.rtfd.io/en/stable/ansible.html#common-problems has https://mitogen.networkgenomics.com/ansible_detailed.html#common-problems has
instructions to help figure out the likely cause and how to gather relevant instructions to help figure out the likely cause and how to gather relevant
logs. logs.
* Mention your host and target OS and versions * Mention your host and target OS and versions

@ -79,6 +79,7 @@ import multiprocessing
import os import os
import struct import struct
import mitogen.core
import mitogen.parent import mitogen.parent
@ -246,8 +247,19 @@ class FixedPolicy(Policy):
class LinuxPolicy(FixedPolicy): class LinuxPolicy(FixedPolicy):
def _mask_to_bytes(self, mask):
"""
Convert the (type long) mask to a cpu_set_t.
"""
chunks = []
shiftmask = (2 ** 64) - 1
for x in range(16):
chunks.append(struct.pack('<Q', mask & shiftmask))
mask >>= 64
return mitogen.core.b('').join(chunks)
def _set_cpu_mask(self, mask): def _set_cpu_mask(self, mask):
s = struct.pack('L', mask) s = self._mask_to_bytes(mask)
_sched_setaffinity(os.getpid(), len(s), s) _sched_setaffinity(os.getpid(), len(s), s)

@ -58,6 +58,15 @@ import ansible_mitogen.transport_config
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
def get_remote_name(spec):
"""
Return the value to use for the "remote_name" parameter.
"""
if spec.mitogen_mask_remote_name():
return 'ansible'
return None
def optional_int(value): def optional_int(value):
""" """
Convert `value` to an integer if it is not :data:`None`, otherwise return Convert `value` to an integer if it is not :data:`None`, otherwise return
@ -135,6 +144,7 @@ def _connect_ssh(spec):
'connect_timeout': spec.ansible_ssh_timeout(), 'connect_timeout': spec.ansible_ssh_timeout(),
'ssh_args': spec.ssh_args(), 'ssh_args': spec.ssh_args(),
'ssh_debug_level': spec.mitogen_ssh_debug_level(), 'ssh_debug_level': spec.mitogen_ssh_debug_level(),
'remote_name': get_remote_name(spec),
} }
} }
@ -150,6 +160,7 @@ def _connect_docker(spec):
'container': spec.remote_addr(), 'container': spec.remote_addr(),
'python_path': spec.python_path(), 'python_path': spec.python_path(),
'connect_timeout': spec.ansible_ssh_timeout() or spec.timeout(), 'connect_timeout': spec.ansible_ssh_timeout() or spec.timeout(),
'remote_name': get_remote_name(spec),
} }
} }
@ -166,6 +177,7 @@ def _connect_kubectl(spec):
'connect_timeout': spec.ansible_ssh_timeout() or spec.timeout(), 'connect_timeout': spec.ansible_ssh_timeout() or spec.timeout(),
'kubectl_path': spec.mitogen_kubectl_path(), 'kubectl_path': spec.mitogen_kubectl_path(),
'kubectl_args': spec.extra_args(), 'kubectl_args': spec.extra_args(),
'remote_name': get_remote_name(spec),
} }
} }
@ -181,6 +193,7 @@ def _connect_jail(spec):
'container': spec.remote_addr(), 'container': spec.remote_addr(),
'python_path': spec.python_path(), 'python_path': spec.python_path(),
'connect_timeout': spec.ansible_ssh_timeout() or spec.timeout(), 'connect_timeout': spec.ansible_ssh_timeout() or spec.timeout(),
'remote_name': get_remote_name(spec),
} }
} }
@ -196,6 +209,7 @@ def _connect_lxc(spec):
'python_path': spec.python_path(), 'python_path': spec.python_path(),
'lxc_attach_path': spec.mitogen_lxc_attach_path(), 'lxc_attach_path': spec.mitogen_lxc_attach_path(),
'connect_timeout': spec.ansible_ssh_timeout() or spec.timeout(), 'connect_timeout': spec.ansible_ssh_timeout() or spec.timeout(),
'remote_name': get_remote_name(spec),
} }
} }
@ -211,6 +225,7 @@ def _connect_lxd(spec):
'python_path': spec.python_path(), 'python_path': spec.python_path(),
'lxc_path': spec.mitogen_lxc_path(), 'lxc_path': spec.mitogen_lxc_path(),
'connect_timeout': spec.ansible_ssh_timeout() or spec.timeout(), 'connect_timeout': spec.ansible_ssh_timeout() or spec.timeout(),
'remote_name': get_remote_name(spec),
} }
} }
@ -254,6 +269,7 @@ def _connect_su(spec):
'python_path': spec.python_path(), 'python_path': spec.python_path(),
'su_path': spec.become_exe(), 'su_path': spec.become_exe(),
'connect_timeout': spec.timeout(), 'connect_timeout': spec.timeout(),
'remote_name': get_remote_name(spec),
} }
} }
@ -272,6 +288,7 @@ def _connect_sudo(spec):
'sudo_path': spec.become_exe(), 'sudo_path': spec.become_exe(),
'connect_timeout': spec.timeout(), 'connect_timeout': spec.timeout(),
'sudo_args': spec.sudo_args(), 'sudo_args': spec.sudo_args(),
'remote_name': get_remote_name(spec),
} }
} }
@ -289,6 +306,7 @@ def _connect_doas(spec):
'python_path': spec.python_path(), 'python_path': spec.python_path(),
'doas_path': spec.become_exe(), 'doas_path': spec.become_exe(),
'connect_timeout': spec.timeout(), 'connect_timeout': spec.timeout(),
'remote_name': get_remote_name(spec),
} }
} }
@ -305,6 +323,7 @@ def _connect_mitogen_su(spec):
'python_path': spec.python_path(), 'python_path': spec.python_path(),
'su_path': spec.become_exe(), 'su_path': spec.become_exe(),
'connect_timeout': spec.timeout(), 'connect_timeout': spec.timeout(),
'remote_name': get_remote_name(spec),
} }
} }
@ -322,6 +341,7 @@ def _connect_mitogen_sudo(spec):
'sudo_path': spec.become_exe(), 'sudo_path': spec.become_exe(),
'connect_timeout': spec.timeout(), 'connect_timeout': spec.timeout(),
'sudo_args': spec.sudo_args(), 'sudo_args': spec.sudo_args(),
'remote_name': get_remote_name(spec),
} }
} }
@ -338,6 +358,7 @@ def _connect_mitogen_doas(spec):
'python_path': spec.python_path(), 'python_path': spec.python_path(),
'doas_path': spec.become_exe(), 'doas_path': spec.become_exe(),
'connect_timeout': spec.timeout(), 'connect_timeout': spec.timeout(),
'remote_name': get_remote_name(spec),
} }
} }

@ -296,6 +296,7 @@ class NewStylePlanner(ScriptPlanner):
#: manner. #: manner.
ALWAYS_FORK_MODULES = frozenset([ ALWAYS_FORK_MODULES = frozenset([
'dnf', # issue #280; py-dnf/hawkey need therapy 'dnf', # issue #280; py-dnf/hawkey need therapy
'firewalld', # issue #570: ansible module_utils caches dbus conn
]) ])
def should_fork(self): def should_fork(self):

@ -37,9 +37,46 @@ import ansible_mitogen.loaders
import ansible_mitogen.mixins import ansible_mitogen.mixins
import ansible_mitogen.process import ansible_mitogen.process
import ansible
import ansible.executor.process.worker import ansible.executor.process.worker
ANSIBLE_VERSION_MIN = '2.3'
ANSIBLE_VERSION_MAX = '2.7'
NEW_VERSION_MSG = (
"Your Ansible version (%s) is too recent. The most recent version\n"
"supported by Mitogen for Ansible is %s.x. Please check the Mitogen\n"
"release notes to see if a new version is available, otherwise\n"
"subscribe to the corresponding GitHub issue to be notified when\n"
"support becomes available.\n"
"\n"
" https://mitogen.rtfd.io/en/latest/changelog.html\n"
" https://github.com/dw/mitogen/issues/\n"
)
OLD_VERSION_MSG = (
"Your version of Ansible (%s) is too old. The oldest version supported by "
"Mitogen for Ansible is %s."
)
def _assert_supported_release():
"""
Throw AnsibleError with a descriptive message in case of being loaded into
an unsupported Ansible release.
"""
v = ansible.__version__
if v[:len(ANSIBLE_VERSION_MIN)] < ANSIBLE_VERSION_MIN:
raise ansible.errors.AnsibleError(
OLD_VERSION_MSG % (v, ANSIBLE_VERSION_MIN)
)
if v[:len(ANSIBLE_VERSION_MAX)] > ANSIBLE_VERSION_MAX:
raise ansible.errors.AnsibleError(
NEW_VERSION_MSG % (ansible.__version__, ANSIBLE_VERSION_MAX)
)
def _patch_awx_callback(): def _patch_awx_callback():
""" """
issue #400: AWX loads a display callback that suffers from thread-safety issue #400: AWX loads a display callback that suffers from thread-safety
@ -245,6 +282,8 @@ class StrategyMixin(object):
Arrange for a mitogen.master.Router to be available for the duration of Arrange for a mitogen.master.Router to be available for the duration of
the strategy's real run() method. the strategy's real run() method.
""" """
_assert_supported_release()
ansible_mitogen.process.MuxProcess.start() ansible_mitogen.process.MuxProcess.start()
run = super(StrategyMixin, self).run run = super(StrategyMixin, self).run
self._add_plugin_paths() self._add_plugin_paths()

@ -93,7 +93,7 @@ MAKE_TEMP_FAILED_MSG = (
u"were mounted on 'noexec' filesystems.\n" u"were mounted on 'noexec' filesystems.\n"
u"\n" u"\n"
u"The following paths were tried:\n" u"The following paths were tried:\n"
u" %(namelist)s\n" u" %(paths)s\n"
u"\n" u"\n"
u"Please check '-vvv' output for a log of individual path errors." u"Please check '-vvv' output for a log of individual path errors."
) )

@ -231,6 +231,15 @@ class Spec(with_metaclass(abc.ABCMeta, object)):
The type of container to use with the "setns" transport. The type of container to use with the "setns" transport.
""" """
@abc.abstractmethod
def mitogen_mask_remote_name(self):
"""
Specifies whether to set a fixed "remote_name" field. The remote_name
is the suffix of `argv[0]` for remote interpreters. By default it
includes identifying information from the local process, which may be
undesirable in some circumstances.
"""
@abc.abstractmethod @abc.abstractmethod
def mitogen_docker_path(self): def mitogen_docker_path(self):
""" """
@ -385,6 +394,9 @@ class PlayContextSpec(Spec):
def mitogen_kind(self): def mitogen_kind(self):
return self._connection.get_task_var('mitogen_kind') return self._connection.get_task_var('mitogen_kind')
def mitogen_mask_remote_name(self):
return self._connection.get_task_var('mitogen_mask_remote_name')
def mitogen_docker_path(self): def mitogen_docker_path(self):
return self._connection.get_task_var('mitogen_docker_path') return self._connection.get_task_var('mitogen_docker_path')
@ -593,6 +605,9 @@ class MitogenViaSpec(Spec):
def mitogen_kind(self): def mitogen_kind(self):
return self._host_vars.get('mitogen_kind') return self._host_vars.get('mitogen_kind')
def mitogen_mask_remote_name(self):
return self._host_vars.get('mitogen_mask_remote_name')
def mitogen_docker_path(self): def mitogen_docker_path(self):
return self._host_vars.get('mitogen_docker_path') return self._host_vars.get('mitogen_docker_path')

@ -0,0 +1,14 @@
<!doctype html>
<title>Mitogen for Ansible (Redirect)</title>
<script>
{% include "piwik-config.js" %}
var u="https://networkgenomics.com/p/tr/";
_paq.push(['setTrackerUrl', u+'ep']);
</script>
<script src="https://networkgenomics.com/p/tr/js"></script>
<script>
setTimeout(function() {
window.location = 'https://networkgenomics.com/ansible/';
}, 0);
</script>
<meta http-equiv="Refresh" content="0; url=https://networkgenomics.com/ansible/">

@ -5,14 +5,10 @@
{{ super() }} {{ super() }}
<script> <script>
var _paq = _paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() { (function() {
{% include "piwik-config.js" %}
var u="https://k1.botanicus.net/tr/"; var u="https://k1.botanicus.net/tr/";
_paq.push(['enableHeartBeatTimer', 30]);
_paq.push(['setTrackerUrl', u+'ep']); _paq.push(['setTrackerUrl', u+'ep']);
_paq.push(['setSiteId', 6]);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript';
g.defer=true; g.async=true; g.src=u+'js'; s.parentNode.insertBefore(g,s); g.defer=true; g.async=true; g.src=u+'js'; s.parentNode.insertBefore(g,s);
})(); })();

@ -0,0 +1,5 @@
window._paq = [];
window._paq.push(['trackPageView']);
window._paq.push(['enableLinkTracking']);
window._paq.push(['enableHeartBeatTimer', 30]);
window._paq.push(['setSiteId', 6]);

@ -1,8 +1,10 @@
.. _ansible_detailed:
Mitogen for Ansible Mitogen for Ansible
=================== ===================
.. image:: images/ansible/ansible_mitogen.svg .. image:: images/mitogen.svg
:class: mitogen-right-180 mitogen-logo-wrap :class: mitogen-right-180 mitogen-logo-wrap
**Mitogen for Ansible** is a completely redesigned UNIX connection layer and **Mitogen for Ansible** is a completely redesigned UNIX connection layer and
@ -569,7 +571,7 @@ in regular Ansible:
* During task shutdown, it is not necessary to wait to learn if the target has * During task shutdown, it is not necessary to wait to learn if the target has
succeeded in deleting a temporary directory, since any error that may occur succeeded in deleting a temporary directory, since any error that may occur
can is logged asynchronously via the logging framework, and the persistent is logged asynchronously via the logging framework, and the persistent
remote interpreter arranges for all subdirectories to be destroyed during remote interpreter arranges for all subdirectories to be destroyed during
interpreter shutdown. interpreter shutdown.
@ -731,6 +733,11 @@ When used as a become method:
* ``ansible_become_exe``: path to ``doas`` binary. * ``ansible_become_exe``: path to ``doas`` binary.
* ``ansible_become_user`` (default: ``root``) * ``ansible_become_user`` (default: ``root``)
* ``ansible_become_pass`` (default: assume passwordless) * ``ansible_become_pass`` (default: assume passwordless)
* ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the
Ansible controller process on remote machines. To simplify diagnostics,
Mitogen produces remote processes named like
`"mitogen:user@controller.name:1234"`, however this may be a privacy issue in
some circumstances.
* ansible.cfg: ``timeout`` * ansible.cfg: ``timeout``
When used as the ``mitogen_doas`` connection method: When used as the ``mitogen_doas`` connection method:
@ -752,6 +759,11 @@ connection delegation is supported.
* ``ansible_host``: Name of Docker container (default: inventory hostname). * ``ansible_host``: Name of Docker container (default: inventory hostname).
* ``ansible_user``: Name of user within the container to execute as. * ``ansible_user``: Name of user within the container to execute as.
* ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the
Ansible controller process on remote machines. To simplify diagnostics,
Mitogen produces remote processes named like
`"mitogen:user@controller.name:1234"`, however this may be a privacy issue in
some circumstances.
.. _method-jail: .. _method-jail:
@ -765,6 +777,11 @@ connection delegation is supported.
* ``ansible_host``: Name of jail (default: inventory hostname). * ``ansible_host``: Name of jail (default: inventory hostname).
* ``ansible_user``: Name of user within the jail to execute as. * ``ansible_user``: Name of user within the jail to execute as.
* ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the
Ansible controller process on remote machines. To simplify diagnostics,
Mitogen produces remote processes named like
`"mitogen:user@controller.name:1234"`, however this may be a privacy issue in
some circumstances.
.. _method-kubectl: .. _method-kubectl:
@ -778,6 +795,11 @@ connection delegation is supported.
* ``ansible_host``: Name of pod (default: inventory hostname). * ``ansible_host``: Name of pod (default: inventory hostname).
* ``ansible_user``: Name of user to authenticate to API as. * ``ansible_user``: Name of user to authenticate to API as.
* ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the
Ansible controller process on remote machines. To simplify diagnostics,
Mitogen produces remote processes named like
`"mitogen:user@controller.name:1234"`, however this may be a privacy issue in
some circumstances.
Local Local
@ -821,6 +843,11 @@ than the LXC Python bindings, as is usual with ``lxc``.
* ``ansible_host``: Name of LXC container (default: inventory hostname). * ``ansible_host``: Name of LXC container (default: inventory hostname).
* ``mitogen_lxc_attach_path``: path to ``lxc-attach`` command if not available * ``mitogen_lxc_attach_path``: path to ``lxc-attach`` command if not available
on the system path. on the system path.
* ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the
Ansible controller process on remote machines. To simplify diagnostics,
Mitogen produces remote processes named like
`"mitogen:user@controller.name:1234"`, however this may be a privacy issue in
some circumstances.
.. _method-lxd: .. _method-lxd:
@ -837,6 +864,11 @@ the host machine.
* ``ansible_host``: Name of LXC container (default: inventory hostname). * ``ansible_host``: Name of LXC container (default: inventory hostname).
* ``mitogen_lxc_path``: path to ``lxc`` command if not available on the system * ``mitogen_lxc_path``: path to ``lxc`` command if not available on the system
path. path.
* ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the
Ansible controller process on remote machines. To simplify diagnostics,
Mitogen produces remote processes named like
`"mitogen:user@controller.name:1234"`, however this may be a privacy issue in
some circumstances.
.. _machinectl: .. _machinectl:
@ -853,6 +885,11 @@ connection delegation is supported. This is a light wrapper around the
* ``ansible_user``: Name of user within the container to execute as. * ``ansible_user``: Name of user within the container to execute as.
* ``mitogen_machinectl_path``: path to ``machinectl`` command if not available * ``mitogen_machinectl_path``: path to ``machinectl`` command if not available
as ``/bin/machinectl``. as ``/bin/machinectl``.
* ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the
Ansible controller process on remote machines. To simplify diagnostics,
Mitogen produces remote processes named like
`"mitogen:user@controller.name:1234"`, however this may be a privacy issue in
some circumstances.
.. _setns: .. _setns:
@ -897,6 +934,11 @@ When used as a become method:
* ``ansible_su_user``, ``ansible_become_user`` (default: ``root``) * ``ansible_su_user``, ``ansible_become_user`` (default: ``root``)
* ``ansible_su_pass``, ``ansible_become_pass`` (default: assume passwordless) * ``ansible_su_pass``, ``ansible_become_pass`` (default: assume passwordless)
* ``su_flags``, ``become_flags`` * ``su_flags``, ``become_flags``
* ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the
Ansible controller process on remote machines. To simplify diagnostics,
Mitogen produces remote processes named like
`"mitogen:user@controller.name:1234"`, however this may be a privacy issue in
some circumstances.
* ansible.cfg: ``timeout`` * ansible.cfg: ``timeout``
When used as the ``mitogen_su`` connection method: When used as the ``mitogen_su`` connection method:
@ -922,6 +964,11 @@ When used as a become method:
* ``ansible_sudo_user``, ``ansible_become_user`` (default: ``root``) * ``ansible_sudo_user``, ``ansible_become_user`` (default: ``root``)
* ``ansible_sudo_pass``, ``ansible_become_pass`` (default: assume passwordless) * ``ansible_sudo_pass``, ``ansible_become_pass`` (default: assume passwordless)
* ``sudo_flags``, ``become_flags`` * ``sudo_flags``, ``become_flags``
* ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the
Ansible controller process on remote machines. To simplify diagnostics,
Mitogen produces remote processes named like
`"mitogen:user@controller.name:1234"`, however this may be a privacy issue in
some circumstances.
* ansible.cfg: ``timeout`` * ansible.cfg: ``timeout``
When used as the ``mitogen_sudo`` connection method: When used as the ``mitogen_sudo`` connection method:
@ -947,6 +994,11 @@ except connection delegation is supported.
* ``ansible_ssh_private_key_file`` * ``ansible_ssh_private_key_file``
* ``ansible_ssh_pass``, ``ansible_password`` (default: assume passwordless) * ``ansible_ssh_pass``, ``ansible_password`` (default: assume passwordless)
* ``ssh_args``, ``ssh_common_args``, ``ssh_extra_args`` * ``ssh_args``, ``ssh_common_args``, ``ssh_extra_args``
* ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the
Ansible controller process on remote machines. To simplify diagnostics,
Mitogen produces remote processes named like
`"mitogen:user@controller.name:1234"`, however this may be a privacy issue in
some circumstances.
* ``mitogen_ssh_debug_level``: integer between `0..3` indicating the SSH client * ``mitogen_ssh_debug_level``: integer between `0..3` indicating the SSH client
debug level. Ansible must also be run with '-vvv' to view the output. debug level. Ansible must also be run with '-vvv' to view the output.
* ``mitogen_ssh_compression``: :data:`True` to enable SSH compression, * ``mitogen_ssh_compression``: :data:`True` to enable SSH compression,

@ -15,16 +15,56 @@ Release Notes
</style> </style>
v0.2.7 (unreleased) v0.2.8 (unreleased)
------------------- -------------------
To avail of fixes in an unreleased version, please download a ZIP file To avail of fixes in an unreleased version, please download a ZIP file
`directly from GitHub <https://github.com/dw/mitogen/>`_. `directly from GitHub <https://github.com/dw/mitogen/>`_.
v0.2.7 (2019-05-19)
-------------------
This release primarily exists to add a descriptive error message when running
on Ansible 2.8, which is not yet supported.
Fixes Fixes
~~~~~ ~~~~~
*(none yet)* * `#557 <https://github.com/dw/mitogen/issues/557>`_: fix a crash when running
on machines with high CPU counts.
* `#570 <https://github.com/dw/mitogen/issues/570>`_: the ``firewalld`` module
internally caches a dbus name that changes across ``firewalld`` restarts,
causing a failure if the service is restarted between ``firewalld`` module invocations.
* `#575 <https://github.com/dw/mitogen/issues/575>`_: fix a crash when
rendering an error message to indicate no usable temporary directories could
be found.
* `#576 <https://github.com/dw/mitogen/issues/576>`_: fix a crash during
startup on SuSE Linux 11, due to an incorrect version compatibility check in
the Mitogen code.
* `#581 <https://github.com/dw/mitogen/issues/58>`_: a
``mitogen_mask_remote_name`` Ansible variable is exposed, to allow masking
the username, hostname and process ID of ``ansible-playbook`` running on the
controller machine.
* `#587 <https://github.com/dw/mitogen/issues/587>`_: display a friendly
message when running on an unsupported version of Ansible, to cope with
potential influx of 2.8-related bug reports.
Thanks!
~~~~~~~
Mitogen would not be possible without the support of users. A huge thanks for
bug reports, testing, features and fixes in this release contributed by
`Orion Poplawski <https://github.com/opoplawski>`_,
`Thibaut Barrère <https://github.com/thbar>`_,
`@Moumoutaru <https://github.com/Moumoutaru>`_, and
`@polski-g <https://github.com/polski-g>`_.
v0.2.6 (2019-03-06) v0.2.6 (2019-03-06)

@ -12,6 +12,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinxcontrib.pro
html_show_sourcelink = False html_show_sourcelink = False
html_show_sphinx = False html_show_sphinx = False
html_sidebars = {'**': ['globaltoc.html', 'github.html']} html_sidebars = {'**': ['globaltoc.html', 'github.html']}
html_additional_pages = {'ansible': 'ansible.html'}
html_static_path = ['_static'] html_static_path = ['_static']
html_theme = 'alabaster' html_theme = 'alabaster'
html_theme_options = { html_theme_options = {

@ -57,7 +57,7 @@ writing the decompressed result to the write-end of the UNIX pipe.
To allow recovery of ``stdin`` for reuse by the bootstrapped process for To allow recovery of ``stdin`` for reuse by the bootstrapped process for
parent<->child communication, it is necessary for the first stage to avoid parent<->child communication, it is necessary for the first stage to avoid
closing ``stdin`` or reading from it until until EOF. Therefore, the master closing ``stdin`` or reading from it until EOF. Therefore, the master
sends the :py:mod:`zlib`-compressed payload prefixed with an integer size, sends the :py:mod:`zlib`-compressed payload prefixed with an integer size,
allowing reading by the first stage of exactly the required bytes. allowing reading by the first stage of exactly the required bytes.
@ -572,10 +572,10 @@ to receive a message from a newly constructed child before receiving a
corresponding ``ADD_ROUTE`` sent by the child's parent, describing how to reply corresponding ``ADD_ROUTE`` sent by the child's parent, describing how to reply
to it. to it.
When ``sudo:node22a:webapp`` wants to send a message to When ``sudo:node12b:webapp`` wants to send a message to
``sudo:node12b:webapp``, the message will be routed as follows: ``sudo:node22a:webapp``, the message will be routed as follows:
``sudo:node22a:webapp -> node22a -> rack22 -> dc2 -> bastion -> dc1 -> rack12 -> node12b -> sudo:node12b:webapp`` ``sudo:node12b:webapp -> node12b -> rack12 -> dc1 -> bastion -> dc2 -> rack22 -> node22a -> sudo:node22a:webapp``
.. image:: images/route.svg .. image:: images/route.svg
:class: mitogen-full-width :class: mitogen-full-width

@ -6,7 +6,7 @@ Table Of Contents
:maxdepth: 2 :maxdepth: 2
index index
ansible Mitogen for Ansible <ansible_detailed>
contributors contributors
changelog changelog
howitworks howitworks

@ -35,7 +35,7 @@ be expected. On the slave, it is built dynamically during startup.
#: Library version as a tuple. #: Library version as a tuple.
__version__ = (0, 2, 6) __version__ = (0, 2, 7)
#: This is :data:`False` in slave contexts. Previously it was used to prevent #: This is :data:`False` in slave contexts. Previously it was used to prevent

@ -277,7 +277,7 @@ class Kwargs(dict):
self[k.decode()] = v self[k.decode()] = v
else: else:
self[k] = v self[k] = v
elif sys.version_info < (2, 6): elif sys.version_info < (2, 6, 5):
def __init__(self, dct): def __init__(self, dct):
for k, v in dct.iteritems(): for k, v in dct.iteritems():
if type(k) is unicode: if type(k) is unicode:

@ -40,6 +40,7 @@
'password': null, 'password': null,
'port': null, 'port': null,
'python_path': ["/usr/bin/python"], 'python_path': ["/usr/bin/python"],
'remote_name': null,
'ssh_args': [ 'ssh_args': [
'-o', '-o',
'UserKnownHostsFile=/dev/null', 'UserKnownHostsFile=/dev/null',
@ -67,6 +68,7 @@
'password': null, 'password': null,
'port': null, 'port': null,
'python_path': ["/usr/bin/python"], 'python_path': ["/usr/bin/python"],
'remote_name': null,
'ssh_args': [ 'ssh_args': [
'-o', '-o',
'UserKnownHostsFile=/dev/null', 'UserKnownHostsFile=/dev/null',

@ -24,6 +24,7 @@
'kwargs': { 'kwargs': {
'connect_timeout': 10, 'connect_timeout': 10,
'python_path': ["{{ansible_playbook_python}}"], 'python_path': ["{{ansible_playbook_python}}"],
'remote_name': null,
'password': null, 'password': null,
'username': 'root', 'username': 'root',
'sudo_path': null, 'sudo_path': null,

@ -21,6 +21,7 @@
'lxc_info_path': null, 'lxc_info_path': null,
'machinectl_path': null, 'machinectl_path': null,
'python_path': ['/usr/bin/python'], 'python_path': ['/usr/bin/python'],
'remote_name': null,
'username': null, 'username': null,
}, },
'method': 'setns', 'method': 'setns',

@ -44,6 +44,7 @@
"doas_path": null, "doas_path": null,
"password": null, "password": null,
"python_path": ["/usr/bin/python"], "python_path": ["/usr/bin/python"],
'remote_name': null,
"username": "normal-user", "username": "normal-user",
}, },
"method": "doas", "method": "doas",
@ -73,6 +74,7 @@
'password': null, 'password': null,
'port': null, 'port': null,
"python_path": ["/usr/bin/python"], "python_path": ["/usr/bin/python"],
'remote_name': null,
'ssh_args': [ 'ssh_args': [
'-o', '-o',
'UserKnownHostsFile=/dev/null', 'UserKnownHostsFile=/dev/null',
@ -113,6 +115,7 @@
'password': null, 'password': null,
'port': null, 'port': null,
"python_path": ["/usr/bin/python"], "python_path": ["/usr/bin/python"],
'remote_name': null,
'ssh_args': [ 'ssh_args': [
'-o', '-o',
'UserKnownHostsFile=/dev/null', 'UserKnownHostsFile=/dev/null',
@ -148,6 +151,7 @@
'doas_path': null, 'doas_path': null,
'password': null, 'password': null,
"python_path": ["/usr/bin/python"], "python_path": ["/usr/bin/python"],
'remote_name': null,
'username': 'normal-user', 'username': 'normal-user',
}, },
'method': 'doas', 'method': 'doas',
@ -163,6 +167,7 @@
'password': null, 'password': null,
'port': null, 'port': null,
"python_path": ["/usr/bin/python"], "python_path": ["/usr/bin/python"],
'remote_name': null,
'ssh_args': [ 'ssh_args': [
'-o', '-o',
'UserKnownHostsFile=/dev/null', 'UserKnownHostsFile=/dev/null',
@ -203,6 +208,7 @@
'password': null, 'password': null,
'port': null, 'port': null,
"python_path": ["/usr/bin/python"], "python_path": ["/usr/bin/python"],
'remote_name': null,
'ssh_args': [ 'ssh_args': [
'-o', '-o',
'UserKnownHostsFile=/dev/null', 'UserKnownHostsFile=/dev/null',
@ -230,6 +236,7 @@
'password': null, 'password': null,
'port': null, 'port': null,
"python_path": ["/usr/bin/python"], "python_path": ["/usr/bin/python"],
'remote_name': null,
'ssh_args': [ 'ssh_args': [
'-o', '-o',
'UserKnownHostsFile=/dev/null', 'UserKnownHostsFile=/dev/null',
@ -265,6 +272,7 @@
'doas_path': null, 'doas_path': null,
'password': null, 'password': null,
"python_path": ["/usr/bin/python"], "python_path": ["/usr/bin/python"],
'remote_name': null,
'username': 'normal-user', 'username': 'normal-user',
}, },
'method': 'doas', 'method': 'doas',
@ -280,6 +288,7 @@
'password': null, 'password': null,
'port': null, 'port': null,
"python_path": ["/usr/bin/python"], "python_path": ["/usr/bin/python"],
'remote_name': null,
'ssh_args': [ 'ssh_args': [
'-o', '-o',
'UserKnownHostsFile=/dev/null', 'UserKnownHostsFile=/dev/null',
@ -321,6 +330,7 @@
'password': null, 'password': null,
'port': null, 'port': null,
"python_path": ["/usr/bin/python"], "python_path": ["/usr/bin/python"],
'remote_name': null,
'ssh_args': [ 'ssh_args': [
'-o', '-o',
'UserKnownHostsFile=/dev/null', 'UserKnownHostsFile=/dev/null',
@ -375,6 +385,7 @@
'doas_path': null, 'doas_path': null,
'password': null, 'password': null,
'python_path': ["/usr/bin/python"], 'python_path': ["/usr/bin/python"],
'remote_name': null,
'username': 'normal-user', 'username': 'normal-user',
}, },
'method': 'doas', 'method': 'doas',
@ -385,6 +396,7 @@
'doas_path': null, 'doas_path': null,
'password': null, 'password': null,
'python_path': ["/usr/bin/python"], 'python_path': ["/usr/bin/python"],
'remote_name': null,
'username': 'newuser-doas-normal-user', 'username': 'newuser-doas-normal-user',
}, },
'method': 'doas', 'method': 'doas',

@ -1,3 +1,4 @@
- include: disconnect_cleanup.yml - include: disconnect_cleanup.yml
- include: lru_one_target.yml - include: lru_one_target.yml
- include: reconnection.yml - include: reconnection.yml
- include: remote_name.yml

@ -0,0 +1,27 @@
# issue #581: ensure mitogen_mask_remote_name is respected.
- name: integration/context_service/remote_name.yml
hosts: test-targets[0]
any_errors_fatal: true
tasks:
- meta: end_play
when: not is_mitogen
- shell: 'cat /proc/$PPID/cmdline | tr \\0 \\n'
register: out
- debug: var=out
- assert:
that:
- out.stdout is match('.*python([0-9.]+)?\(mitogen:[a-z]+@[^:]+:[0-9]+\)')
- shell: 'cat /proc/$PPID/cmdline | tr \\0 \\n'
register: out
vars:
mitogen_mask_remote_name: true
- debug: var=out
- assert:
that:
- out.stdout is match('.*python([0-9.]+)?\(mitogen:ansible\)')

@ -211,5 +211,16 @@ class LinuxPolicyTest(testlib.TestCase):
tf.close() tf.close()
class MockLinuxPolicyTest(testlib.TestCase):
klass = ansible_mitogen.affinity.LinuxPolicy
# Test struct.pack() in _set_cpu_mask().
def test_high_cpus(self):
policy = self.klass(cpu_count=4096)
for x in range(1, 4096, 32):
policy.assign_subprocess()
if __name__ == '__main__': if __name__ == '__main__':
unittest2.main() unittest2.main()

@ -15,14 +15,47 @@ LOGGER_NAME = ansible_mitogen.target.LOG.name
class NamedTemporaryDirectory(object): class NamedTemporaryDirectory(object):
def __init__(self, **kwargs):
self.kwargs = kwargs
def __enter__(self): def __enter__(self):
self.path = tempfile.mkdtemp() self.path = tempfile.mkdtemp(**self.kwargs)
return self.path return self.path
def __exit__(self, _1, _2, _3): def __exit__(self, _1, _2, _3):
subprocess.check_call(['rm', '-rf', self.path]) subprocess.check_call(['rm', '-rf', self.path])
class FindGoodTempDirTest(testlib.TestCase):
func = staticmethod(ansible_mitogen.target.find_good_temp_dir)
def test_expands_usernames(self):
with NamedTemporaryDirectory(
prefix='.ansible_mitogen_test',
dir=os.environ['HOME']
) as tmpdir:
path = self.func(['~'])
self.assertTrue(path.startswith(os.environ['HOME']))
def test_expands_vars(self):
with NamedTemporaryDirectory(
prefix='.ansible_mitogen_test',
dir=os.environ['HOME']
) as tmpdir:
os.environ['somevar'] = 'xyz'
path = self.func([tmpdir + '/$somevar'])
self.assertTrue(path.startswith('%s/%s' % (tmpdir, 'xyz')))
@mock.patch('ansible_mitogen.target.is_good_temp_dir')
def test_no_good_candidate(self, is_good_temp_dir):
is_good_temp_dir.return_value = False
e = self.assertRaises(IOError,
lambda: self.func([])
)
self.assertTrue(str(e).startswith('Unable to find a useable'))
class ApplyModeSpecTest(unittest2.TestCase): class ApplyModeSpecTest(unittest2.TestCase):
func = staticmethod(ansible_mitogen.target.apply_mode_spec) func = staticmethod(ansible_mitogen.target.apply_mode_spec)

Loading…
Cancel
Save