Merge branch 'master' into docs-master

docs-master
Alex Willmer 2 weeks ago
commit 9a147296d2

@ -156,30 +156,21 @@ jobs:
"$PYTHON" -m tox -e "${{ matrix.tox_env }}" "$PYTHON" -m tox -e "${{ matrix.tox_env }}"
macos: macos:
# https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md # https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md
runs-on: macos-12 runs-on: macos-13
timeout-minutes: 120 timeout-minutes: 120
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- name: Mito_27
tox_env: py27-mode_mitogen
- name: Mito_313 - name: Mito_313
python_version: '3.13'
tox_env: py313-mode_mitogen tox_env: py313-mode_mitogen
- name: Loc_27_210
tox_env: py27-mode_localhost-ansible2.10
- name: Loc_313_10 - name: Loc_313_10
python_version: '3.13'
tox_env: py313-mode_localhost-ansible10 tox_env: py313-mode_localhost-ansible10
- name: Van_27_210
tox_env: py27-mode_localhost-ansible2.10-strategy_linear
- name: Van_313_10 - name: Van_313_10
python_version: '3.13'
tox_env: py313-mode_localhost-ansible10-strategy_linear tox_env: py313-mode_localhost-ansible10-strategy_linear
steps: steps:

@ -890,6 +890,29 @@ class Connection(ansible.plugins.connection.ConnectionBase):
self.binding.close() self.binding.close()
self.binding = None self.binding = None
def _mitogen_var_options(self, templar):
# Workaround for https://github.com/ansible/ansible/issues/84238
var_names = C.config.get_plugin_vars('connection', self._load_name)
variables = templar.available_variables
var_options = {
var_name: templar.template(variables[var_name])
for var_name in var_names
if var_name in variables
}
if self.allow_extras:
extras_var_prefix = 'ansible_%s_' % self.extras_prefix
var_options['_extras'] = {
var_name: templar.template(variables[var_name])
for var_name in variables
if var_name not in var_options
and var_name.startswith(extras_var_prefix)
}
else:
var_options['_extras'] = {}
return var_options
reset_compat_msg = ( reset_compat_msg = (
'Mitogen only supports "reset_connection" on Ansible 2.5.6 or later' 'Mitogen only supports "reset_connection" on Ansible 2.5.6 or later'
) )
@ -922,6 +945,19 @@ class Connection(ansible.plugins.connection.ConnectionBase):
shared_loader_obj=0 shared_loader_obj=0
) )
# Workaround for https://github.com/ansible/ansible/issues/84238
try:
task, templar = self._play_context.vars.pop(
'_mitogen.smuggled.reset_connection',
)
except KeyError:
pass
else:
self.set_options(
task_keys=task.dump_attrs(),
var_options=self._mitogen_var_options(templar),
)
# Clear out state in case we were ever connected. # Clear out state in case we were ever connected.
self.close() self.close()

@ -45,6 +45,7 @@ import ansible_mitogen.mixins
import ansible_mitogen.process import ansible_mitogen.process
import ansible.executor.process.worker import ansible.executor.process.worker
import ansible.template
import ansible.utils.sentinel import ansible.utils.sentinel
@ -326,3 +327,24 @@ class StrategyMixin(object):
self._worker_model.on_strategy_complete() self._worker_model.on_strategy_complete()
finally: finally:
ansible_mitogen.process.set_worker_model(None) ansible_mitogen.process.set_worker_model(None)
def _smuggle_to_connction_reset(self, task, play_context, iterator, target_host):
# Workaround for https://github.com/ansible/ansible/issues/84238
variables = self._variable_manager.get_vars(
play=iterator._play, host=target_host, task=task,
_hosts=self._hosts_cache, _hosts_all=self._hosts_cache_all,
)
templar = ansible.template.Templar(
loader=self._loader, variables=variables,
)
play_context.vars.update({
'_mitogen.smuggled.reset_connection': (task, templar),
})
def _execute_meta(self, task, play_context, iterator, target_host):
if task.args['_raw_params'] == 'reset_connection':
self._smuggle_to_connction_reset(task, play_context, iterator, target_host)
return super(StrategyMixin, self)._execute_meta(
task, play_context, iterator, target_host,
)

@ -213,6 +213,12 @@ class Spec(with_metaclass(abc.ABCMeta, object)):
:data:`True` if privilege escalation should be active. :data:`True` if privilege escalation should be active.
""" """
@abc.abstractmethod
def become_flags(self):
"""
The command line arguments passed to the become executable.
"""
@abc.abstractmethod @abc.abstractmethod
def become_method(self): def become_method(self):
""" """
@ -290,10 +296,9 @@ class Spec(with_metaclass(abc.ABCMeta, object)):
@abc.abstractmethod @abc.abstractmethod
def sudo_args(self): def sudo_args(self):
""" """
The list of additional arguments that should be included in a become The list of additional arguments that should be included in a sudo
invocation. invocation.
""" """
# TODO: split out into sudo_args/become_args.
@abc.abstractmethod @abc.abstractmethod
def mitogen_via(self): def mitogen_via(self):
@ -419,7 +424,29 @@ class PlayContextSpec(Spec):
def _become_option(self, name): def _become_option(self, name):
plugin = self._connection.become plugin = self._connection.become
try:
return plugin.get_option(name, self._task_vars, self._play_context) return plugin.get_option(name, self._task_vars, self._play_context)
except AttributeError:
# A few ansible_mitogen connection plugins look more like become
# plugins. They don't quite fit Ansible's plugin.get_option() API.
# https://github.com/mitogen-hq/mitogen/issues/1173
fallback_plugins = {'mitogen_doas', 'mitogen_sudo', 'mitogen_su'}
if self._connection.transport not in fallback_plugins:
raise
fallback_options = {
'become_exe',
'become_flags',
}
if name not in fallback_options:
raise
LOG.info(
'Used PlayContext fallback for plugin=%r, option=%r',
self._connection, name,
)
return getattr(self._play_context, name)
def _connection_option(self, name): def _connection_option(self, name):
try: try:
@ -443,6 +470,9 @@ class PlayContextSpec(Spec):
def become(self): def become(self):
return self._connection.become return self._connection.become
def become_flags(self):
return self._become_option('become_flags')
def become_method(self): def become_method(self):
return self._play_context.become_method return self._play_context.become_method
@ -481,7 +511,7 @@ class PlayContextSpec(Spec):
return self._play_context.private_key_file return self._play_context.private_key_file
def ssh_executable(self): def ssh_executable(self):
return C.config.get_config_value("ssh_executable", plugin_type="connection", plugin_name="ssh", variables=self._task_vars.get("vars", {})) return self._connection_option('ssh_executable')
def timeout(self): def timeout(self):
return self._play_context.timeout return self._play_context.timeout
@ -505,30 +535,10 @@ class PlayContextSpec(Spec):
] ]
def become_exe(self): def become_exe(self):
# In Ansible 2.8, PlayContext.become_exe always has a default value due return self._become_option('become_exe')
# to the new options mechanism. Previously it was only set if a value
# ("somewhere") had been specified for the task.
# For consistency in the tests, here we make older Ansibles behave like
# newer Ansibles.
exe = self._play_context.become_exe
if exe is None and self._play_context.become_method == 'sudo':
exe = 'sudo'
return exe
def sudo_args(self): def sudo_args(self):
return [ return ansible.utils.shlex.shlex_split(self.become_flags() or '')
mitogen.core.to_text(term)
for term in ansible.utils.shlex.shlex_split(
first_true((
self._play_context.become_flags,
# Ansible <=2.7.
getattr(self._play_context, 'sudo_flags', ''),
# Ansible <=2.3.
getattr(C, 'DEFAULT_BECOME_FLAGS', ''),
getattr(C, 'DEFAULT_SUDO_FLAGS', '')
), default='')
)
]
def mitogen_via(self): def mitogen_via(self):
return self._connection.get_task_var('mitogen_via') return self._connection.get_task_var('mitogen_via')
@ -663,6 +673,9 @@ class MitogenViaSpec(Spec):
def become(self): def become(self):
return bool(self._become_user) return bool(self._become_user)
def become_flags(self):
return self._host_vars.get('ansible_become_flags')
def become_method(self): def become_method(self):
return ( return (
self._become_method or self._become_method or
@ -758,7 +771,7 @@ class MitogenViaSpec(Spec):
mitogen.core.to_text(term) mitogen.core.to_text(term)
for s in ( for s in (
self._host_vars.get('ansible_sudo_flags') or '', self._host_vars.get('ansible_sudo_flags') or '',
self._host_vars.get('ansible_become_flags') or '', self.become_flags() or '',
) )
for term in ansible.utils.shlex.shlex_split(s) for term in ansible.utils.shlex.shlex_split(s)
] ]

@ -23,6 +23,20 @@ In progress (unreleased)
v0.3.16 (2024-11-05)
--------------------
* :gh:issue:`1083` :mod:`ansible_mitogen`: Templated become executable
(e.g. ``become_exe``).
* :gh:issue:`1083` :mod:`ansible_mitogen`: Templated become executable
arguments (e.g. ``become_flags``).
* :gh:issue:`1083` :mod:`ansible_mitogen`: Templated ssh executable
(``ansible_ssh_executable``).
* :gh:issue:`1083` :mod:`ansible_mitogen`: Fixed templated connection options
during a ``meta: reset_connection`` task.
* :gh:issue:`1129` CI: Migrated macOS 12 runners to macOS 13, due to EOL.
v0.3.15 (2024-10-28) v0.3.15 (2024-10-28)
-------------------- --------------------

@ -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, 3, 16, 'dev') __version__ = (0, 3, 17, 'dev')
#: 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

@ -33,6 +33,8 @@ ansible_host=localhost
ansible_user="{{ lookup('pipe', 'whoami') }}" ansible_user="{{ lookup('pipe', 'whoami') }}"
[tt_become_by_inv] [tt_become_by_inv]
tt-become-exe ansible_become=true ansible_become_exe="{{ 'sudo' | trim }}" ansible_become_user=root
tt-become-flags ansible_become=true ansible_become_flags="{{ '--set-home --stdin --non-interactive' | trim }}" ansible_become_user=root
tt-become-pass ansible_become=true ansible_become_pass="{{ 'pw_required_password' | trim }}" ansible_become_user=mitogen__pw_required tt-become-pass ansible_become=true ansible_become_pass="{{ 'pw_required_password' | trim }}" ansible_become_user=mitogen__pw_required
tt-become-user ansible_become=true ansible_become_user="{{ 'root' | trim }}" tt-become-user ansible_become=true ansible_become_user="{{ 'root' | trim }}"
@ -44,6 +46,7 @@ ansible_user="{{ lookup('pipe', 'whoami') }}"
tt-password ansible_password="{{ 'has_sudo_nopw_password' | trim }}" ansible_user=mitogen__has_sudo_nopw tt-password ansible_password="{{ 'has_sudo_nopw_password' | trim }}" ansible_user=mitogen__has_sudo_nopw
tt-port ansible_password=has_sudo_nopw_password ansible_port="{{ 22 | int }}" ansible_user=mitogen__has_sudo_nopw tt-port ansible_password=has_sudo_nopw_password ansible_port="{{ 22 | int }}" ansible_user=mitogen__has_sudo_nopw
tt-remote-user ansible_password=has_sudo_nopw_password ansible_user="{{ 'mitogen__has_sudo_nopw' | trim }}" tt-remote-user ansible_password=has_sudo_nopw_password ansible_user="{{ 'mitogen__has_sudo_nopw' | trim }}"
tt-ssh-executable ansible_password=has_sudo_nopw_password ansible_ssh_executable="{{ 'ssh' | trim }}" ansible_user=mitogen__has_sudo_nopw
[tt_targets_inventory:vars] [tt_targets_inventory:vars]
ansible_host=localhost ansible_host=localhost

@ -12,6 +12,8 @@
- name: Templated become in inventory - name: Templated become in inventory
vars: vars:
expected_become_users: expected_become_users:
tt-become-exe: root
tt-become-flags: root
tt-become-pass: mitogen__pw_required tt-become-pass: mitogen__pw_required
tt-become-user: root tt-become-user: root
command: command:

@ -2,6 +2,8 @@
hosts: tt_become_bare hosts: tt_become_bare
gather_facts: false gather_facts: false
become: true become: true
become_exe: "{{ 'sudo' | trim }}"
become_flags: "{{ '--set-home --stdin --non-interactive' | trim }}"
become_user: "{{ 'root' | trim }}" become_user: "{{ 'root' | trim }}"
tasks: tasks:
- meta: reset_connection - meta: reset_connection
@ -20,6 +22,8 @@
hosts: tt_become_bare hosts: tt_become_bare
gather_facts: false gather_facts: false
become: true become: true
become_exe: "{{ 'sudo' | trim }}"
become_flags: "{{ '--set-home --stdin --non-interactive' | trim }}"
become_user: "{{ 'mitogen__pw_required' | trim }}" become_user: "{{ 'mitogen__pw_required' | trim }}"
vars: vars:
ansible_become_pass: "{{ 'pw_required_password' | trim }}" ansible_become_pass: "{{ 'pw_required_password' | trim }}"

@ -3,6 +3,8 @@
gather_facts: false gather_facts: false
vars: vars:
ansible_become: true ansible_become: true
ansible_become_exe: "{{ 'sudo' | trim }}"
ansible_become_flags: "{{ '--set-home --stdin --non-interactive' | trim }}"
ansible_become_user: "{{ 'root' | trim }}" ansible_become_user: "{{ 'root' | trim }}"
tasks: tasks:
- name: Templated become by play vars, no password - name: Templated become by play vars, no password
@ -20,6 +22,8 @@
gather_facts: false gather_facts: false
vars: vars:
ansible_become: true ansible_become: true
ansible_become_exe: "{{ 'sudo' | trim }}"
ansible_become_flags: "{{ '--set-home --stdin --non-interactive' | trim }}"
ansible_become_pass: "{{ 'pw_required_password' | trim }}" ansible_become_pass: "{{ 'pw_required_password' | trim }}"
ansible_become_user: "{{ 'mitogen__pw_required' | trim }}" ansible_become_user: "{{ 'mitogen__pw_required' | trim }}"
tasks: tasks:

@ -4,6 +4,8 @@
# FIXME Resetting the connection shouldn't require credentials # FIXME Resetting the connection shouldn't require credentials
# https://github.com/mitogen-hq/mitogen/issues/1132 # https://github.com/mitogen-hq/mitogen/issues/1132
become: true become: true
become_exe: "{{ 'sudo' | trim }}"
become_flags: "{{ '--set-home --stdin --non-interactive' | trim }}"
become_user: "{{ 'root' | trim }}" become_user: "{{ 'root' | trim }}"
tasks: tasks:
- name: Reset connection to target that will be delegate_to - name: Reset connection to target that will be delegate_to
@ -15,6 +17,8 @@
tasks: tasks:
- name: Templated become by task keywords, with delegate_to - name: Templated become by task keywords, with delegate_to
become: true become: true
become_exe: "{{ 'sudo' | trim }}"
become_flags: "{{ '--set-home --stdin --non-interactive' | trim }}"
become_user: "{{ 'root' | trim }}" become_user: "{{ 'root' | trim }}"
delegate_to: "{{ groups.tt_become_bare[0] }}" delegate_to: "{{ groups.tt_become_bare[0] }}"
command: command:
@ -33,6 +37,8 @@
# FIXME Resetting the connection shouldn't require credentials # FIXME Resetting the connection shouldn't require credentials
# https://github.com/mitogen-hq/mitogen/issues/1132 # https://github.com/mitogen-hq/mitogen/issues/1132
become: true become: true
become_exe: "{{ 'sudo' | trim }}"
become_flags: "{{ '--set-home --stdin --non-interactive' | trim }}"
become_user: "{{ 'mitogen__pw_required' | trim }}" become_user: "{{ 'mitogen__pw_required' | trim }}"
vars: vars:
ansible_become_pass: "{{ 'pw_required_password' | trim }}" ansible_become_pass: "{{ 'pw_required_password' | trim }}"
@ -52,6 +58,8 @@
- name: Templated become by task keywords, with delegate_to - name: Templated become by task keywords, with delegate_to
become: true become: true
become_exe: "{{ 'sudo' | trim }}"
become_flags: "{{ '--set-home --stdin --non-interactive' | trim }}"
become_user: "{{ 'mitogen__pw_required' | trim }}" become_user: "{{ 'mitogen__pw_required' | trim }}"
delegate_to: "{{ groups.tt_become_bare[0] }}" delegate_to: "{{ groups.tt_become_bare[0] }}"
vars: vars:

@ -4,6 +4,7 @@
vars: vars:
ansible_password: "{{ 'has_sudo_nopw_password' | trim }}" ansible_password: "{{ 'has_sudo_nopw_password' | trim }}"
ansible_port: "{{ hostvars[groups['test-targets'][0]].ansible_port | default(22) }}" ansible_port: "{{ hostvars[groups['test-targets'][0]].ansible_port | default(22) }}"
ansible_ssh_executable: "{{ 'ssh' | trim }}"
ansible_user: "{{ 'mitogen__has_sudo_nopw' | trim }}" ansible_user: "{{ 'mitogen__has_sudo_nopw' | trim }}"
tasks: tasks:

@ -11,11 +11,16 @@
tasks: tasks:
- meta: end_play - meta: end_play
when: when:
# TODO CI currently runs on macOS 12 & which isn't supported by Podman # Podman versions available in Homebrew have dropped macOS 12 support.
# version available in Homebrew.
- ansible_facts.system == 'Darwin' - ansible_facts.system == 'Darwin'
- ansible_facts.distribution_version is version('13.0', '<', strict=True) - ansible_facts.distribution_version is version('13.0', '<', strict=True)
- meta: end_play
when:
# Ansible 10 (ansible-core 2.17+) require Python 3.7+ on targets.
# On CentOS 8 /usr/libexec/platform-python is Python 3.6
- ansible_version.full is version('2.17', '>=', strict=True)
- name: set up test container and run tests inside it - name: set up test container and run tests inside it
block: block:
- name: install deps - name: install deps
@ -33,6 +38,7 @@
- cmd: podman info - cmd: podman info
timeout: 300 timeout: 300
register: podman_machine register: podman_machine
changed_when: true
- debug: - debug:
var: podman_machine var: podman_machine
@ -41,11 +47,13 @@
- name: create container - name: create container
command: command:
cmd: podman run --name testMitogen -d --rm centos:8 bash -c "sleep infinity & wait" cmd: podman run --name testMitogen -d --rm centos:8 bash -c "sleep infinity & wait"
changed_when: true
- name: add container to inventory - name: add container to inventory
add_host: add_host:
name: testMitogen name: testMitogen
ansible_connection: podman ansible_connection: podman
ansible_python_interpreter: /usr/libexec/platform-python # Python 3.6
ansible_user: root ansible_user: root
changed_when: false changed_when: false
environment: environment:
@ -57,6 +65,7 @@
- name: create test file - name: create test file
file: file:
path: /var/run/reboot-required path: /var/run/reboot-required
mode: u=rw,go=r
state: touch state: touch
- name: Check if reboot is required - name: Check if reboot is required
@ -68,13 +77,16 @@
shell: sleep 2 && shutdown -r now "Ansible updates triggered" shell: sleep 2 && shutdown -r now "Ansible updates triggered"
async: 1 async: 1
poll: 0 poll: 0
when: reboot_required.stat.exists == True changed_when: true
when:
- reboot_required.stat.exists
- name: Wait 300 seconds for server to become available - name: Wait 300 seconds for server to become available
wait_for_connection: wait_for_connection:
delay: 30 delay: 30
timeout: 300 timeout: 300
when: reboot_required.stat.exists == True when:
- reboot_required.stat.exists
- name: cleanup test file - name: cleanup test file
file: file:
@ -90,6 +102,7 @@
loop: loop:
- cmd: podman stop testMitogen - cmd: podman stop testMitogen
- cmd: podman machine stop - cmd: podman machine stop
changed_when: true
when: when:
- ansible_facts.pkg_mgr in ['homebrew'] - ansible_facts.pkg_mgr in ['homebrew']
tags: tags:

@ -58,6 +58,8 @@ ansible_python_interpreter={{ tt.python_path }}
ansible_user=mitogen__has_sudo_nopw ansible_user=mitogen__has_sudo_nopw
[tt_become_by_inv] [tt_become_by_inv]
tt-become-exe ansible_become=true ansible_become_exe="{{ '{{' }} 'sudo' | trim {{ '}}' }}" ansible_become_user=root
tt-become-flags ansible_become=true ansible_become_flags="{{ '{{' }} '--set-home --stdin --non-interactive' | trim {{ '}}' }}" ansible_become_user=root
tt-become-pass ansible_become=true ansible_become_pass="{{ '{{' }} 'pw_required_password' | trim {{ '}}' }}" ansible_become_user=mitogen__pw_required tt-become-pass ansible_become=true ansible_become_pass="{{ '{{' }} 'pw_required_password' | trim {{ '}}' }}" ansible_become_user=mitogen__pw_required
tt-become-user ansible_become=true ansible_become_user="{{ '{{' }} 'root' | trim {{ '}}' }}" tt-become-user ansible_become=true ansible_become_user="{{ '{{' }} 'root' | trim {{ '}}' }}"
@ -72,6 +74,7 @@ ansible_user=mitogen__has_sudo_nopw
tt-password ansible_password="{{ '{{' }} 'has_sudo_nopw_password' | trim {{ '}}' }}" ansible_port={{ tt.port }} ansible_user=mitogen__has_sudo_nopw tt-password ansible_password="{{ '{{' }} 'has_sudo_nopw_password' | trim {{ '}}' }}" ansible_port={{ tt.port }} ansible_user=mitogen__has_sudo_nopw
tt-port ansible_password=has_sudo_nopw_password ansible_port="{{ '{{' }} {{ tt.port }} | int {{ '}}' }}" ansible_user=mitogen__has_sudo_nopw tt-port ansible_password=has_sudo_nopw_password ansible_port="{{ '{{' }} {{ tt.port }} | int {{ '}}' }}" ansible_user=mitogen__has_sudo_nopw
tt-remote-user ansible_password=has_sudo_nopw_password ansible_port={{ tt.port }} ansible_user="{{ '{{' }} 'mitogen__has_sudo_nopw' | trim {{ '}}' }}" tt-remote-user ansible_password=has_sudo_nopw_password ansible_port={{ tt.port }} ansible_user="{{ '{{' }} 'mitogen__has_sudo_nopw' | trim {{ '}}' }}"
tt-ssh-executable ansible_password=has_sudo_nopw_password ansible_port={{ tt.port }} ansible_ssh_executable="{{ '{{' }} 'ssh' | trim {{ '}}' }}" ansible_user=mitogen__has_sudo_nopw
[tt_targets_inventory:vars] [tt_targets_inventory:vars]
ansible_host={{ tt.hostname }} ansible_host={{ tt.hostname }}

Loading…
Cancel
Save