Merge remote-tracking branch 'origin/dmw'

* origin/dmw:
  docs: update Changelog.
  issue #536: rework how 2.3-compatible simplejson is served
  .github: add some more questions to issue template
  docs: duplicate word
  docs: update Changelog.
  tests/ansible: Spec.become_method() test & mitogen_via= fix.
  setup.py: include LICENSE; closes #538.
  tests/ansible: Spec.become() test
  tests/ansible: Spec.password() test, document interactive pw limitation.
  tests/ansible: Spec.remote_user() test & mitogen_via= fix.
  tests/ansible: Spec.remote_addr() test & mitogen_via= fix.
  tests/ansible: Spec.transport() test.
  docs: lighter pink
  docs: add 'Fixes' heading
  docs: more margin tweaks for changelog
  docs: tighter <p> margins, even less shouting, red headings
  docs: tidy up footer and GitHub link
  docs: enable fixed_sidebar
  docs: sans-serif fonts, reduce shouty headings
  issue #536: add mitogen_via= tests too.
  ansible: fix a crash on 2.3 when mitogen_via= host is missing.
  tests: for 2.3 compatibility, disable gcloud.py for now
pull/564/head
David Wilson 6 years ago
commit 2fe8332983

@ -4,6 +4,10 @@ Please drag-drop large logs as text file attachments.
Feel free to write an issue in your preferred format, however if in doubt, use Feel free to write an issue in your preferred format, however if in doubt, use
the following checklist as a guide for what to include. the following checklist as a guide for what to include.
* Which version of Ansible are you running?
* Is your version of Ansible patched in any way?
* Are you running with any custom modules, or `module_utils` loaded?
* 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.rtfd.io/en/stable/ansible.html#common-problems has

@ -0,0 +1 @@
include LICENSE

@ -547,7 +547,7 @@ class Connection(ansible.plugins.connection.ConnectionBase):
def connected(self): def connected(self):
return self.context is not None return self.context is not None
def _spec_from_via(self, via_spec): def _spec_from_via(self, proxied_inventory_name, via_spec):
""" """
Produce a dict connection specifiction given a string `via_spec`, of Produce a dict connection specifiction given a string `via_spec`, of
the form `[[become_method:]become_user@]inventory_hostname`. the form `[[become_method:]become_user@]inventory_hostname`.
@ -555,17 +555,20 @@ class Connection(ansible.plugins.connection.ConnectionBase):
become_user, _, inventory_name = via_spec.rpartition('@') become_user, _, inventory_name = via_spec.rpartition('@')
become_method, _, become_user = become_user.rpartition(':') become_method, _, become_user = become_user.rpartition(':')
via_vars = self.host_vars[inventory_name] # must use __contains__ to avoid a TypeError for a missing host on
if isinstance(via_vars, jinja2.runtime.Undefined): # Ansible 2.3.
if self.host_vars is None or inventory_name not in self.host_vars:
raise ansible.errors.AnsibleConnectionFailure( raise ansible.errors.AnsibleConnectionFailure(
self.unknown_via_msg % ( self.unknown_via_msg % (
via_spec, via_spec,
inventory_name, proxied_inventory_name,
) )
) )
via_vars = self.host_vars[inventory_name]
return ansible_mitogen.transport_config.MitogenViaSpec( return ansible_mitogen.transport_config.MitogenViaSpec(
inventory_name=inventory_name, inventory_name=inventory_name,
play_context=self._play_context,
host_vars=dict(via_vars), # TODO: make it lazy host_vars=dict(via_vars), # TODO: make it lazy
become_method=become_method or None, become_method=become_method or None,
become_user=become_user or None, become_user=become_user or None,
@ -615,7 +618,7 @@ class Connection(ansible.plugins.connection.ConnectionBase):
if spec.mitogen_via(): if spec.mitogen_via():
stack = self._stack_from_spec( stack = self._stack_from_spec(
self._spec_from_via(spec.mitogen_via()), self._spec_from_via(spec.inventory_name(), spec.mitogen_via()),
stack=stack, stack=stack,
seen_names=seen_names + (spec.inventory_name(),), seen_names=seen_names + (spec.inventory_name(),),
) )

@ -236,6 +236,41 @@ class MuxProcess(object):
if secs: if secs:
mitogen.debug.dump_to_logger(secs=secs) mitogen.debug.dump_to_logger(secs=secs)
def _setup_simplejson(self, responder):
"""
We support serving simplejson for Python 2.4 targets on Ansible 2.3, at
least so the package's own CI Docker scripts can run without external
help, however newer versions of simplejson no longer support Python
2.4. Therefore override any installed/loaded version with a
2.4-compatible version we ship in the compat/ directory.
"""
responder.whitelist_prefix('simplejson')
# issue #536: must be at end of sys.path, in case existing newer
# version is already loaded.
compat_path = os.path.join(os.path.dirname(__file__), 'compat')
sys.path.append(compat_path)
for fullname, is_pkg, suffix in (
(u'simplejson', True, '__init__.py'),
(u'simplejson.decoder', False, 'decoder.py'),
(u'simplejson.encoder', False, 'encoder.py'),
(u'simplejson.scanner', False, 'scanner.py'),
):
path = os.path.join(compat_path, 'simplejson', suffix)
fp = open(path, 'rb')
try:
source = fp.read()
finally:
fp.close()
responder.add_source_override(
fullname=fullname,
path=path,
source=source,
is_pkg=is_pkg,
)
def _setup_responder(self, responder): def _setup_responder(self, responder):
""" """
Configure :class:`mitogen.master.ModuleResponder` to only permit Configure :class:`mitogen.master.ModuleResponder` to only permit
@ -243,9 +278,7 @@ class MuxProcess(object):
""" """
responder.whitelist_prefix('ansible') responder.whitelist_prefix('ansible')
responder.whitelist_prefix('ansible_mitogen') responder.whitelist_prefix('ansible_mitogen')
responder.whitelist_prefix('simplejson') self._setup_simplejson(responder)
simplejson_path = os.path.join(os.path.dirname(__file__), 'compat')
sys.path.insert(0, simplejson_path)
# Ansible 2.3 is compatible with Python 2.4 targets, however # Ansible 2.3 is compatible with Python 2.4 targets, however
# ansible/__init__.py is not. Instead, executor/module_common.py writes # ansible/__init__.py is not. Instead, executor/module_common.py writes

@ -377,6 +377,11 @@ def init_child(econtext, log_level, candidate_temp_dirs):
LOG.setLevel(log_level) LOG.setLevel(log_level)
logging.getLogger('ansible_mitogen').setLevel(log_level) logging.getLogger('ansible_mitogen').setLevel(log_level)
# issue #536: if the json module is available, remove simplejson from the
# importer whitelist to avoid confusing certain Ansible modules.
if json.__name__ == 'json':
econtext.importer.whitelist.remove('simplejson')
global _fork_parent global _fork_parent
if FORK_SUPPORTED: if FORK_SUPPORTED:
mitogen.parent.upgrade_router(econtext) mitogen.parent.upgrade_router(econtext)

@ -430,12 +430,33 @@ class MitogenViaSpec(Spec):
having a configruation problem with connection delegation, the answer to having a configruation problem with connection delegation, the answer to
your problem lies in the method implementations below! your problem lies in the method implementations below!
""" """
def __init__(self, inventory_name, host_vars, def __init__(self, inventory_name, host_vars, become_method, become_user,
become_method, become_user): play_context):
"""
:param str inventory_name:
The inventory name of the intermediary machine, i.e. not the target
machine.
:param dict host_vars:
The HostVars magic dictionary provided by Ansible in task_vars.
:param str become_method:
If the mitogen_via= spec included a become method, the method it
specifies.
:param str become_user:
If the mitogen_via= spec included a become user, the user it
specifies.
:param PlayContext play_context:
For some global values **only**, the PlayContext used to describe
the real target machine. Values from this object are **strictly
restricted** to values that are Ansible-global, e.g. the passwords
specified interactively.
"""
self._inventory_name = inventory_name self._inventory_name = inventory_name
self._host_vars = host_vars self._host_vars = host_vars
self._become_method = become_method self._become_method = become_method
self._become_user = become_user self._become_user = become_user
# Dangerous! You may find a variable you want in this object, but it's
# almost certainly for the wrong machine!
self._dangerous_play_context = play_context
def transport(self): def transport(self):
return ( return (
@ -447,15 +468,17 @@ class MitogenViaSpec(Spec):
return self._inventory_name return self._inventory_name
def remote_addr(self): def remote_addr(self):
# play_context.py::MAGIC_VARIABLE_MAPPING
return ( return (
self._host_vars.get('ansible_ssh_host') or
self._host_vars.get('ansible_host') or self._host_vars.get('ansible_host') or
self._inventory_name self._inventory_name
) )
def remote_user(self): def remote_user(self):
return ( return (
self._host_vars.get('ansible_user') or
self._host_vars.get('ansible_ssh_user') or self._host_vars.get('ansible_ssh_user') or
self._host_vars.get('ansible_user') or
C.DEFAULT_REMOTE_USER C.DEFAULT_REMOTE_USER
) )
@ -463,7 +486,11 @@ class MitogenViaSpec(Spec):
return bool(self._become_user) return bool(self._become_user)
def become_method(self): def become_method(self):
return self._become_method or C.DEFAULT_BECOME_METHOD return (
self._become_method or
self._host_vars.get('ansible_become_method') or
C.DEFAULT_BECOME_METHOD
)
def become_user(self): def become_user(self):
return self._become_user return self._become_user
@ -477,7 +504,6 @@ class MitogenViaSpec(Spec):
def password(self): def password(self):
return optional_secret( return optional_secret(
# TODO: Might have to come from PlayContext.
self._host_vars.get('ansible_ssh_pass') or self._host_vars.get('ansible_ssh_pass') or
self._host_vars.get('ansible_password') self._host_vars.get('ansible_password')
) )
@ -495,7 +521,6 @@ class MitogenViaSpec(Spec):
# interpreter is specified. # interpreter is specified.
return parse_python_path(s or '/usr/bin/python') return parse_python_path(s or '/usr/bin/python')
def private_key_file(self): def private_key_file(self):
# TODO: must come from PlayContext too. # TODO: must come from PlayContext too.
return ( return (

@ -1,4 +1,66 @@
body {
font-size: 100%;
}
.sphinxsidebar {
font-size: 80% !important;
}
.sphinxsidebar h3 {
font-size: 130% !important;
}
img + p,
h1 + p,
h2 + p,
h3 + p,
h4 + p,
h5 + p
{
margin-top: 0;
}
.section > h3:first-child {
margin-top: 15px !important;
}
.body h1 { font-size: 200% !important; }
.body h2 { font-size: 165% !important; }
.body h3 { font-size: 125% !important; }
.body h4 { font-size: 110% !important; font-weight: bold; }
.body h5 { font-size: 100% !important; font-weight: bold; }
.body h1,
.body h2,
.body h3,
.body h4,
.body h5 {
margin-top: 30px !important;
color: #7f0000;
}
.body h1 {
margin-top: 0 !important;
}
body,
.sphinxsidebar,
.sphinxsidebar h1,
.sphinxsidebar h2,
.sphinxsidebar h3,
.sphinxsidebar h4,
.sphinxsidebar h5,
.body h1,
.body h2,
.body h3,
.body h4,
.body h5 {
/*font-family: sans-serif !important;*/
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol !important;
}
.document { .document {
width: 1000px !important; width: 1000px !important;
} }
@ -38,10 +100,10 @@ div.body p, div.body dd, div.body li, div.body blockquote {
width: 150px; width: 150px;
} }
.mitogen-right-200 { .mitogen-right-180 {
float: right; float: right;
padding-left: 8px; padding-left: 8px;
width: 200px; width: 180px;
} }
.mitogen-right-225 { .mitogen-right-225 {

@ -1,8 +1,4 @@
<p> <p>
<br> <br>
<a class="github-button" href="https://github.com/dw/mitogen" data-size="large" data-show-count="true" aria-label="Star dw/mitogen on GitHub">Star</a> <a class="github-button" href="https://github.com/dw/mitogen/" data-size="large" data-show-count="true" aria-label="Star dw/mitogen on GitHub">Star</a>
</p>
<p>
<a href="https://github.com/dw/mitogen/">GitHub Repository</a>
</p> </p>

@ -3,7 +3,7 @@ Mitogen for Ansible
=================== ===================
.. image:: images/ansible/ansible_mitogen.svg .. image:: images/ansible/ansible_mitogen.svg
:class: mitogen-right-200 mitogen-logo-wrap :class: mitogen-right-180 mitogen-logo-wrap
An extension to `Ansible`_ is included that implements connections over An extension to `Ansible`_ is included that implements connections over
Mitogen, replacing embedded shell invocations with pure-Python equivalents Mitogen, replacing embedded shell invocations with pure-Python equivalents
@ -246,6 +246,11 @@ container.
as duplicate connections between hops, due to not perfectly replicating as duplicate connections between hops, due to not perfectly replicating
the configuration Ansible would normally use for the intermediary. the configuration Ansible would normally use for the intermediary.
* Intermediary machines cannot use login and become passwords that were
supplied to Ansible interactively. If an intermediary requires a
password, it must be supplied via ``ansible_ssh_pass``,
``ansible_password``, or ``ansible_become_pass`` inventory variables.
* Automatic tunnelling of SSH-dependent actions, such as the * Automatic tunnelling of SSH-dependent actions, such as the
``synchronize`` module, is not yet supported. This will be added in the ``synchronize`` module, is not yet supported. This will be added in the
0.3 series. 0.3 series.

@ -10,7 +10,7 @@ Release Notes
<style> <style>
div#release-notes h2 { div#release-notes h2 {
border-bottom: 1px dotted #c0c0c0; border-bottom: 1px dotted #c0c0c0;
margin-top: 40px; margin-top: 50px !important;
} }
</style> </style>
@ -128,16 +128,40 @@ Core Library
v0.2.5 (2019-02-1?) v0.2.5 (2019-02-1?)
------------------- -------------------
Fixes
~~~~~
* `#511 <https://github.com/dw/mitogen/issues/511>`_, * `#511 <https://github.com/dw/mitogen/issues/511>`_,
`#536 <https://github.com/dw/mitogen/issues/536>`_: changes in 0.2.4 to `#536 <https://github.com/dw/mitogen/issues/536>`_: changes in 0.2.4 to
repair ``delegate_to`` handling broke default ``ansible_python_interpreter`` repair ``delegate_to`` handling broke default ``ansible_python_interpreter``
handling. Test coverage was added. handling. Test coverage was added.
* `#536 <https://github.com/dw/mitogen/issues/536>`_: changes in 0.2.4 to
support Python 2.4 interacted poorly with modules that imported
``simplejson`` from a controller that also loaded an incompatible newer
version of ``simplejson``.
* `#538 <https://github.com/dw/mitogen/issues/538>`_: the Mitogen source
distribution includes a requisite ``LICENSE`` file.
* `748f5f67 <https://github.com/dw/mitogen/commit/748f5f67>`_: the
``ansible_ssh_host`` variable is respected when ``mitogen_via=`` is active.
* `21ad299d <https://github.com/dw/mitogen/commit/21ad299d>`_: the
precedence of ``ansible_ssh_user`` and ``ansible_user`` variables were
corrected when ``mitogen_via=`` is active.
* `8ae6ca1d <https://github.com/dw/mitogen/commit/8ae6ca1d>`_: the
``ansible_become_method`` variable is respected when ``mitogen_via=`` is
active.
Thanks! Thanks!
~~~~~~~ ~~~~~~~
Mitogen would not be possible without the support of users. A huge thanks for 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 bug reports, testing, features and fixes in this release contributed by
`Carl George <https://github.com/carlwgeorge>`_,
`Guy Knights <https://github.com/knightsg>`_, and `Guy Knights <https://github.com/knightsg>`_, and
`Josh Smift <https://github.com/jbscare>`_, `Josh Smift <https://github.com/jbscare>`_,

@ -17,6 +17,10 @@ html_theme = 'alabaster'
html_theme_options = { html_theme_options = {
'font_family': "Georgia, serif", 'font_family': "Georgia, serif",
'head_font_family': "Georgia, serif", 'head_font_family': "Georgia, serif",
'fixed_sidebar': True,
'show_powered_by': False,
'pink_2': 'fffafaf',
'pink_1': '#fff0f0',
} }
htmlhelp_basename = 'mitogendoc' htmlhelp_basename = 'mitogendoc'
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)} intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}

@ -11,7 +11,7 @@ Mitogen
</style> </style>
.. image:: images/mitogen.svg .. image:: images/mitogen.svg
:class: mitogen-right-200 mitogen-logo-wrap :class: mitogen-right-180 mitogen-logo-wrap
Mitogen is a Python library for writing distributed self-replicating programs. Mitogen is a Python library for writing distributed self-replicating programs.

@ -1125,6 +1125,11 @@ class Importer(object):
self.whitelist = list(whitelist) or [''] self.whitelist = list(whitelist) or ['']
self.blacklist = list(blacklist) + self.ALWAYS_BLACKLIST self.blacklist = list(blacklist) + self.ALWAYS_BLACKLIST
# Preserve copies of the original server-supplied whitelist/blacklist
# for later use by children.
self.master_whitelist = self.whitelist[:]
self.master_blacklist = self.blacklist[:]
# Presence of an entry in this map indicates in-flight GET_MODULE. # Presence of an entry in this map indicates in-flight GET_MODULE.
self._callbacks = {} self._callbacks = {}
self._cache = {} self._cache = {}

@ -485,8 +485,10 @@ class ModuleFinder(object):
return path, source, is_pkg return path, source, is_pkg
def _get_module_via_sys_modules(self, fullname): def _get_module_via_sys_modules(self, fullname):
"""Attempt to fetch source code via sys.modules. This is specifically """
to support __main__, but it may catch a few more cases.""" Attempt to fetch source code via sys.modules. This is specifically to
support __main__, but it may catch a few more cases.
"""
module = sys.modules.get(fullname) module = sys.modules.get(fullname)
LOG.debug('_get_module_via_sys_modules(%r) -> %r', fullname, module) LOG.debug('_get_module_via_sys_modules(%r) -> %r', fullname, module)
if not isinstance(module, types.ModuleType): if not isinstance(module, types.ModuleType):
@ -883,10 +885,13 @@ class ModuleResponder(object):
if msg.is_dead: if msg.is_dead:
return return
LOG.debug('%r._on_get_module(%r)', self, msg.data)
self.get_module_count += 1
stream = self._router.stream_by_id(msg.src_id) stream = self._router.stream_by_id(msg.src_id)
if stream is None:
return
fullname = msg.data.decode() fullname = msg.data.decode()
LOG.debug('%s requested module %s', stream.name, fullname)
self.get_module_count += 1
if fullname in stream.sent_modules: if fullname in stream.sent_modules:
LOG.warning('_on_get_module(): dup request for %r from %r', LOG.warning('_on_get_module(): dup request for %r from %r',
fullname, stream) fullname, stream)

@ -2054,12 +2054,12 @@ class Router(mitogen.core.Router):
def get_module_blacklist(self): def get_module_blacklist(self):
if mitogen.context_id == 0: if mitogen.context_id == 0:
return self.responder.blacklist return self.responder.blacklist
return self.importer.blacklist return self.importer.master_blacklist
def get_module_whitelist(self): def get_module_whitelist(self):
if mitogen.context_id == 0: if mitogen.context_id == 0:
return self.responder.whitelist return self.responder.whitelist
return self.importer.whitelist return self.importer.master_whitelist
def allocate_id(self): def allocate_id(self):
return self.id_allocator.allocate() return self.id_allocator.allocate()

@ -1,5 +1,5 @@
[defaults] [defaults]
inventory = hosts,lib/inventory inventory = hosts
gathering = explicit gathering = explicit
strategy_plugins = ../../ansible_mitogen/plugins/strategy strategy_plugins = ../../ansible_mitogen/plugins/strategy
action_plugins = lib/action action_plugins = lib/action

@ -1,10 +1,33 @@
# integration/transport_config # integration/transport_config
# Hosts with twiddled configs that need to be checked somehow. # Hosts with twiddled configs that need to be checked somehow.
# tansport()
tc-transport-unset
tc-transport-local ansible_connection=local
# python_path()
tc-python-path-unset tc-python-path-unset
tc-python-path-hostvar ansible_python_interpreter=/hostvar/path/to/python tc-python-path-hostvar ansible_python_interpreter=/hostvar/path/to/python
# local connections get virtualenv python path
tc-python-path-local-unset ansible_connection=local tc-python-path-local-unset ansible_connection=local
tc-python-path-local-explicit ansible_connection=local ansible_python_interpreter=/a/b/c tc-python-path-local-explicit ansible_connection=local ansible_python_interpreter=/a/b/c
# remote_addr()
tc-remote-addr-unset # defaults to inventory_hostname
tc-remote-addr-explicit-ssh ansible_ssh_host=ansi.ssh.host
tc-remote-addr-explicit-host ansible_host=ansi.host
tc-remote-addr-explicit-both ansible_ssh_host=a.b.c ansible_host=b.c.d
# password()
tc-password-unset
tc-password-explicit-ssh ansible_ssh_pass=ansi-ssh-pass
tc-password-explicit-user ansible_password=ansi-pass
tc-password-explicit-both ansible_password=a.b.c ansible_ssh_pass=c.b.a
# become()
tc-become-unset
tc-become-set
# become_method()
tc-become-method-unset
tc-become-method-su ansible_become_method=su

@ -0,0 +1,4 @@
# Include me for plays that can't run on vanilla.
#
- meta: end_play
when: not is_mitogen

@ -1,2 +1,7 @@
- include: become.yml
- include: become_method.yml
- include: password.yml
- include: python_path.yml - include: python_path.yml
- include: remote_addr.yml
- include: remote_user.yml
- include: transport.yml

@ -0,0 +1,68 @@
# Each case is followed by mitogen_via= case to test hostvars method.
# No become set.
- name: integration/transport_config/become.yml
hosts: tc-become-unset
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert:
that:
- out.result|length == 1
- out.result[0].method == "ssh"
- out.result[0].kwargs.username == "ansible-cfg-remote-user"
- hosts: tc-become-unset
vars: {mitogen_via: becomeuser@tc-become-set}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert:
that:
- out.result|length == 3
- out.result[0].method == "ssh"
- out.result[0].kwargs.username == "ansible-cfg-remote-user"
- out.result[1].method == "sudo"
- out.result[1].kwargs.username == "becomeuser"
- out.result[2].method == "ssh"
- out.result[2].kwargs.hostname == "tc-become-unset"
# Become set.
- name: integration/transport_config/become.yml
hosts: tc-become-set
become: true
become_user: becomeuser
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert:
that:
- out.result|length == 2
- out.result[0].method == "ssh"
- out.result[0].kwargs.username == "ansible-cfg-remote-user"
- out.result[1].method == "sudo"
- out.result[1].kwargs.username == "becomeuser"
- hosts: tc-become-set
vars: {mitogen_via: tc-become-unset}
become: true
become_user: becomeuser
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert:
that:
- out.result|length == 3
- out.result[0].method == "ssh"
- out.result[0].kwargs.hostname == "tc-become-unset"
- out.result[0].kwargs.username == "ansible-cfg-remote-user"
- out.result[1].method == "ssh"
- out.result[1].kwargs.hostname == "tc-become-set"
- out.result[2].method == "sudo"
- out.result[2].kwargs.username == "becomeuser"

@ -0,0 +1,83 @@
# Each case is followed by mitogen_via= case to test hostvars method.
# No become-method set.
- name: integration/transport_config/become-method.yml
hosts: tc-become-method-unset
become: true
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert:
that:
- out.result|length == 2
- out.result[0].method == "ssh"
- out.result[1].method == "sudo"
- hosts: tc-become-method-unset
vars: {mitogen_via: becomeuser@tc-become-method-su}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert:
that:
- out.result|length == 3
- out.result[0].method == "ssh"
- out.result[1].method == "su"
- out.result[1].kwargs.username == "becomeuser"
- out.result[2].method == "ssh"
- out.result[2].kwargs.hostname == "tc-become-method-unset"
# ansible_become_method=su
- hosts: tc-become-method-su
become: true
become_user: becomeuser
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert:
that:
- out.result|length == 2
- out.result[0].method == "ssh"
- out.result[1].method == "su"
- out.result[1].kwargs.username == "becomeuser"
- hosts: tc-become-method-su
vars: {mitogen_via: tc-become-method-unset}
become: true
become_user: becomeuser
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert:
that:
- out.result|length == 3
- out.result[0].method == "ssh"
- out.result[0].kwargs.hostname == "tc-become-method-unset"
- out.result[1].method == "ssh"
- out.result[1].kwargs.hostname == "tc-become-method-su"
- out.result[2].method == "su"
- out.result[2].kwargs.username == "becomeuser"
# mitogen_via used to specify explicit become method
- hosts: tc-become-method-unset
vars: {mitogen_via: "doas:doasuser@tc-become-method-su"}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert:
that:
- out.result|length == 3
- out.result[0].method == "ssh"
- out.result[0].kwargs.hostname == "tc-become-method-su"
- out.result[1].method == "doas"
- out.result[1].kwargs.username == "doasuser"
- out.result[2].method == "ssh"
- out.result[2].kwargs.hostname == "tc-become-method-unset"

@ -0,0 +1,94 @@
# Each case is followed by mitogen_via= case to test hostvars method.
# When no ansible_ssh_pass/ansible_password= is set, password comes via
# interactive input.
- name: integration/transport_config/password.yml
hosts: tc-password-unset
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.password
right: "" # actually null, but assert_equal limitation
- hosts: tc-password-unset
vars: {mitogen_via: tc-password-explicit-ssh}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.password
right: "ansi-ssh-pass"
- assert_equal:
left: out.result[1].kwargs.password
right: ""
# ansible_ssh_user=
- hosts: tc-password-explicit-ssh
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.password
right: "ansi-ssh-pass"
- hosts: tc-password-explicit-ssh
vars: {mitogen_via: tc-password-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.password
right: ""
- assert_equal:
left: out.result[1].kwargs.password
right: "ansi-ssh-pass"
# ansible_user=
- hosts: tc-password-explicit-pass
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.password
right: "ansi-pass"
- hosts: tc-password-explicit-pass
vars: {mitogen_via: tc-password-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.password
right: ""
- assert_equal:
left: out.result[1].kwargs.password
right: "ansi-pass"
# both; ansible_ssh_user= takes precedence according to play_context.py.
- hosts: tc-password-explicit-both
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.password
right: "c.b.a"
- hosts: tc-password-explicit-both
vars: {mitogen_via: tc-password-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.password
right: ""
- assert_equal:
left: out.result[1].kwargs.password
right: "c.b.a"

@ -1,4 +1,5 @@
# related: issue #511, #536 # related: issue #511, #536
# Each case is followed by mitogen_via= case to test hostvars method.
# When no ansible_python_interpreter is set, executor/module_common.py chooses # When no ansible_python_interpreter is set, executor/module_common.py chooses
@ -6,57 +7,108 @@
- name: integration/transport_config/python_path.yml - name: integration/transport_config/python_path.yml
hosts: tc-python-path-unset hosts: tc-python-path-unset
tasks: tasks:
- meta: end_play - include: ../_mitogen_only.yml
when: not is_mitogen - {mitogen_get_stack: {}, register: out}
- mitogen_get_stack:
register: out
- assert_equal: - assert_equal:
left: out.result[0].kwargs.python_path left: out.result[0].kwargs.python_path
right: ["/usr/bin/python"] right: ["/usr/bin/python"]
- hosts: tc-python-path-hostvar
vars: {mitogen_via: tc-python-path-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.python_path
right: ["/usr/bin/python"]
- assert_equal:
left: out.result[1].kwargs.python_path
right: ["/hostvar/path/to/python"]
# Non-localhost with explicit ansible_python_interpreter # Non-localhost with explicit ansible_python_interpreter
- hosts: tc-python-path-hostvar - hosts: tc-python-path-hostvar
tasks: tasks:
- meta: end_play - include: ../_mitogen_only.yml
when: not is_mitogen - {mitogen_get_stack: {}, register: out}
- mitogen_get_stack:
register: out
- assert_equal: - assert_equal:
left: out.result[0].kwargs.python_path left: out.result[0].kwargs.python_path
right: [/hostvar/path/to/python] right: [/hostvar/path/to/python]
- hosts: tc-python-path-unset
vars: {mitogen_via: tc-python-path-hostvar}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.python_path
right: ["/hostvar/path/to/python"]
- assert_equal:
left: out.result[1].kwargs.python_path
right: ["/usr/bin/python"]
# Implicit localhost gets ansible_python_interpreter=virtualenv interpreter # Implicit localhost gets ansible_python_interpreter=virtualenv interpreter
- hosts: localhost - hosts: localhost
tasks: tasks:
- meta: end_play - include: ../_mitogen_only.yml
when: not is_mitogen - {mitogen_get_stack: {}, register: out}
- mitogen_get_stack: - assert_equal:
register: out left: out.result[0].kwargs.python_path
right: ["{{ansible_playbook_python}}"]
- hosts: tc-python-path-unset
vars: {mitogen_via: localhost}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal: - assert_equal:
left: out.result[0].kwargs.python_path left: out.result[0].kwargs.python_path
right: ["{{ansible_playbook_python}}"] right: ["{{ansible_playbook_python}}"]
- assert_equal:
left: out.result[1].kwargs.python_path
right: ["/usr/bin/python"]
# explicit local connections get the same treatment as everything else. # explicit local connections get the same treatment as everything else.
- hosts: tc-python-path-local-unset - hosts: tc-python-path-local-unset
tasks: tasks:
- meta: end_play - include: ../_mitogen_only.yml
when: not is_mitogen - {mitogen_get_stack: {}, register: out}
- mitogen_get_stack:
register: out
- assert_equal: - assert_equal:
left: out.result[0].kwargs.python_path left: out.result[0].kwargs.python_path
right: ["/usr/bin/python"] right: ["/usr/bin/python"]
- hosts: localhost
vars: {mitogen_via: tc-python-path-local-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.python_path
right: ["/usr/bin/python"]
- assert_equal:
left: out.result[1].kwargs.python_path
right: ["{{ansible_playbook_python}}"]
# explicit local connection with explicit interpreter
- hosts: tc-python-path-local-explicit - hosts: tc-python-path-local-explicit
tasks: tasks:
- meta: end_play - include: ../_mitogen_only.yml
when: not is_mitogen - {mitogen_get_stack: {}, register: out}
- mitogen_get_stack:
register: out
- assert_equal: - assert_equal:
left: out.result[0].kwargs.python_path left: out.result[0].kwargs.python_path
right: ["/a/b/c"] right: ["/a/b/c"]
- hosts: localhost
vars: {mitogen_via: tc-python-path-local-explicit}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.python_path
right: ["/a/b/c"]
- assert_equal:
left: out.result[1].kwargs.python_path
right: ["{{ansible_playbook_python}}"]

@ -0,0 +1,95 @@
# Each case is followed by mitogen_via= case to test hostvars method.
# When no ansible_host/ansible_ssh_host= is set, hostname is same as inventory
# name.
- name: integration/transport_config/remote_addr.yml
hosts: tc-remote-addr-unset
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.hostname
right: "tc-remote-addr-unset"
- hosts: tc-remote-addr-unset
vars: {mitogen_via: tc-remote-addr-explicit-ssh}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.hostname
right: "ansi.ssh.host"
- assert_equal:
left: out.result[1].kwargs.hostname
right: "tc-remote-addr-unset"
# ansible_ssh_host=
- hosts: tc-remote-addr-explicit-ssh
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.hostname
right: "ansi.ssh.host"
- hosts: tc-remote-addr-explicit-ssh
vars: {mitogen_via: tc-remote-addr-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.hostname
right: "tc-remote-addr-unset"
- assert_equal:
left: out.result[1].kwargs.hostname
right: "ansi.ssh.host"
# ansible_host=
- hosts: tc-remote-addr-explicit-host
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.hostname
right: "ansi.host"
- hosts: tc-remote-addr-explicit-host
vars: {mitogen_via: tc-remote-addr-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.hostname
right: "tc-remote-addr-unset"
- assert_equal:
left: out.result[1].kwargs.hostname
right: "ansi.host"
# both; ansible_ssh_host= takes precedence according to play_context.py.
- hosts: tc-remote-addr-explicit-both
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.hostname
right: "a.b.c"
- hosts: tc-remote-addr-explicit-both
vars: {mitogen_via: tc-remote-addr-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.hostname
right: "tc-remote-addr-unset"
- assert_equal:
left: out.result[1].kwargs.hostname
right: "a.b.c"

@ -0,0 +1,96 @@
# Each case is followed by mitogen_via= case to test hostvars method.
# When no ansible_user/ansible_ssh_user= is set, username is
# C.DEFAULT_REMOTE_USER.
- name: integration/transport_config/remote_user.yml
hosts: tc-remote-user-unset
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.username
# We set DEFAULT_REMOTE_USER in our ansible.cfg
right: "ansible-cfg-remote-user"
- hosts: tc-remote-user-unset
vars: {mitogen_via: tc-remote-user-explicit-ssh}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.username
right: "ansi-ssh-user"
- assert_equal:
left: out.result[1].kwargs.username
right: "ansible-cfg-remote-user"
# ansible_ssh_user=
- hosts: tc-remote-user-explicit-ssh
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.username
right: "ansi-ssh-user"
- hosts: tc-remote-user-explicit-ssh
vars: {mitogen_via: tc-remote-user-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.username
right: "ansible-cfg-remote-user"
- assert_equal:
left: out.result[1].kwargs.username
right: "ansi-ssh-user"
# ansible_user=
- hosts: tc-remote-user-explicit-user
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.username
right: "ansi-user"
- hosts: tc-remote-user-explicit-host
vars: {mitogen_via: tc-remote-user-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.username
right: "ansible-cfg-remote-user"
- assert_equal:
left: out.result[1].kwargs.username
right: "ansi-user"
# both; ansible_ssh_user= takes precedence according to play_context.py.
- hosts: tc-remote-user-explicit-both
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.username
right: "c.b.a"
- hosts: tc-remote-user-explicit-both
vars: {mitogen_via: tc-remote-user-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.username
right: "ansible-cfg-remote-user"
- assert_equal:
left: out.result[1].kwargs.username
right: "c.b.a"

@ -0,0 +1,48 @@
# Each case is followed by mitogen_via= case to test hostvars method.
# When no ansible_connection= is set, transport comes via ansible.cfg ("smart"
# is parsed away to either paramiko or ssh).
- name: integration/transport_config/transport.yml
hosts: tc-transport-unset
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].method
right: "ssh"
- hosts: tc-transport-local
vars: {mitogen_via: tc-transport-unset}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].method
right: "ssh"
- assert_equal:
left: out.result[1].method
right: "local"
# ansible_connection=local
- hosts: tc-transport-local
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].method
right: "local"
- hosts: tc-transport-unset
vars: {mitogen_via: tc-transport-local}
tasks:
- include: ../_mitogen_only.yml
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].method
right: "local"
- assert_equal:
left: out.result[1].method
right: "ssh"
Loading…
Cancel
Save