From c0391d33f7403282b120825cf6f3a5874c26cc8c Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Mon, 28 Oct 2024 20:57:46 +0000 Subject: [PATCH] ansible_mitogen: Support templated become_exe option Some ansible_mitogen connection plugins look more like become plugins (e.g. mitogen_sudo) & use become plugin options. For now there's special handling in PlayContextSpec._become_option(). Further design/discussion can go in #1173. Refs #1087. --- ansible_mitogen/transport_config.py | 33 +++++++++++++------ docs/changelog.rst | 2 ++ tests/ansible/hosts/default.hosts | 1 + .../integration/become/templated_by_inv.yml | 1 + .../become/templated_by_play_keywords.yml | 2 ++ .../become/templated_by_play_vars.yml | 2 ++ .../become/templated_by_task_keywords.yml | 4 +++ tests/ansible/templates/test-targets.j2 | 1 + 8 files changed, 36 insertions(+), 10 deletions(-) diff --git a/ansible_mitogen/transport_config.py b/ansible_mitogen/transport_config.py index c2976365c..759b8f51a 100644 --- a/ansible_mitogen/transport_config.py +++ b/ansible_mitogen/transport_config.py @@ -419,7 +419,28 @@ def __init__(self, connection, play_context, transport, inventory_name): def _become_option(self, name): plugin = self._connection.become - return plugin.get_option(name, self._task_vars, self._play_context) + try: + 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', + } + 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): try: @@ -505,15 +526,7 @@ def ssh_args(self): ] def become_exe(self): - # In Ansible 2.8, PlayContext.become_exe always has a default value due - # 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 + return self._become_option('become_exe') def sudo_args(self): return [ diff --git a/docs/changelog.rst b/docs/changelog.rst index b20c2c9c6..34d8a576e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -21,6 +21,8 @@ To avail of fixes in an unreleased version, please download a ZIP file In progress (unreleased) ------------------------ +* :gh:issue:`1083` :mod:`ansible_mitogen`: Templated become executable + (e.g. ``become_exe``). v0.3.15 (2024-10-28) diff --git a/tests/ansible/hosts/default.hosts b/tests/ansible/hosts/default.hosts index 58e003b04..8dc275c64 100644 --- a/tests/ansible/hosts/default.hosts +++ b/tests/ansible/hosts/default.hosts @@ -33,6 +33,7 @@ ansible_host=localhost ansible_user="{{ lookup('pipe', 'whoami') }}" [tt_become_by_inv] +tt-become-exe ansible_become=true ansible_become_exe="{{ 'sudo' | 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-user ansible_become=true ansible_become_user="{{ 'root' | trim }}" diff --git a/tests/ansible/integration/become/templated_by_inv.yml b/tests/ansible/integration/become/templated_by_inv.yml index 3409708b8..47825595b 100644 --- a/tests/ansible/integration/become/templated_by_inv.yml +++ b/tests/ansible/integration/become/templated_by_inv.yml @@ -12,6 +12,7 @@ - name: Templated become in inventory vars: expected_become_users: + tt-become-exe: root tt-become-pass: mitogen__pw_required tt-become-user: root command: diff --git a/tests/ansible/integration/become/templated_by_play_keywords.yml b/tests/ansible/integration/become/templated_by_play_keywords.yml index 94d527264..29c548a37 100644 --- a/tests/ansible/integration/become/templated_by_play_keywords.yml +++ b/tests/ansible/integration/become/templated_by_play_keywords.yml @@ -2,6 +2,7 @@ hosts: tt_become_bare gather_facts: false become: true + become_exe: "{{ 'sudo' | trim }}" become_user: "{{ 'root' | trim }}" tasks: - meta: reset_connection @@ -20,6 +21,7 @@ hosts: tt_become_bare gather_facts: false become: true + become_exe: "{{ 'sudo' | trim }}" become_user: "{{ 'mitogen__pw_required' | trim }}" vars: ansible_become_pass: "{{ 'pw_required_password' | trim }}" diff --git a/tests/ansible/integration/become/templated_by_play_vars.yml b/tests/ansible/integration/become/templated_by_play_vars.yml index c46ca1440..cae0e60e7 100644 --- a/tests/ansible/integration/become/templated_by_play_vars.yml +++ b/tests/ansible/integration/become/templated_by_play_vars.yml @@ -3,6 +3,7 @@ gather_facts: false vars: ansible_become: true + ansible_become_exe: "{{ 'sudo' | trim }}" ansible_become_user: "{{ 'root' | trim }}" tasks: - name: Templated become by play vars, no password @@ -20,6 +21,7 @@ gather_facts: false vars: ansible_become: true + ansible_become_exe: "{{ 'sudo' | trim }}" ansible_become_pass: "{{ 'pw_required_password' | trim }}" ansible_become_user: "{{ 'mitogen__pw_required' | trim }}" tasks: diff --git a/tests/ansible/integration/become/templated_by_task_keywords.yml b/tests/ansible/integration/become/templated_by_task_keywords.yml index 9c75cbd70..bc81c33d6 100644 --- a/tests/ansible/integration/become/templated_by_task_keywords.yml +++ b/tests/ansible/integration/become/templated_by_task_keywords.yml @@ -4,6 +4,7 @@ # FIXME Resetting the connection shouldn't require credentials # https://github.com/mitogen-hq/mitogen/issues/1132 become: true + become_exe: "{{ 'sudo' | trim }}" become_user: "{{ 'root' | trim }}" tasks: - name: Reset connection to target that will be delegate_to @@ -15,6 +16,7 @@ tasks: - name: Templated become by task keywords, with delegate_to become: true + become_exe: "{{ 'sudo' | trim }}" become_user: "{{ 'root' | trim }}" delegate_to: "{{ groups.tt_become_bare[0] }}" command: @@ -33,6 +35,7 @@ # FIXME Resetting the connection shouldn't require credentials # https://github.com/mitogen-hq/mitogen/issues/1132 become: true + become_exe: "{{ 'sudo' | trim }}" become_user: "{{ 'mitogen__pw_required' | trim }}" vars: ansible_become_pass: "{{ 'pw_required_password' | trim }}" @@ -52,6 +55,7 @@ - name: Templated become by task keywords, with delegate_to become: true + become_exe: "{{ 'sudo' | trim }}" become_user: "{{ 'mitogen__pw_required' | trim }}" delegate_to: "{{ groups.tt_become_bare[0] }}" vars: diff --git a/tests/ansible/templates/test-targets.j2 b/tests/ansible/templates/test-targets.j2 index 2eeebef7c..7c061be23 100644 --- a/tests/ansible/templates/test-targets.j2 +++ b/tests/ansible/templates/test-targets.j2 @@ -58,6 +58,7 @@ ansible_python_interpreter={{ tt.python_path }} ansible_user=mitogen__has_sudo_nopw [tt_become_by_inv] +tt-become-exe ansible_become=true ansible_become_exe="{{ '{{' }} 'sudo' | 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-user ansible_become=true ansible_become_user="{{ '{{' }} 'root' | trim {{ '}}' }}"