ansible_mitogen: Support templated become_user

This reads the become username from the `become_user` attribute of the play
context, to the `"become_user"` option of the loaded become plugin. This has
been supported by vanilla Ansible since Ansible 2.10 (ansible-base 2.10).

To support this I've also switched from using the `play_context.become` (a
bool), to `connection.become` (an instance of the appropriate) become plugin.

New tests have been added, modelled on those for templated connection
parameters (see #1147, #1153, #1159).

See
- 480b106d65

refs #1083

Co-authored-by: mordek <m.pirog@bonasoft.pl>
pull/1148/head
Alex Willmer 1 month ago
parent 3b2b03bd97
commit bf6607e27e

@ -814,7 +814,7 @@ class Connection(ansible.plugins.connection.ConnectionBase):
self.context = dct['context'] self.context = dct['context']
self.chain = CallChain(self, self.context, pipelined=True) self.chain = CallChain(self, self.context, pipelined=True)
if self._play_context.become: if self.become:
self.login_context = dct['via'] self.login_context = dct['via']
else: else:
self.login_context = self.context self.login_context = self.context
@ -926,7 +926,7 @@ class Connection(ansible.plugins.connection.ConnectionBase):
self.close() self.close()
inventory_name, stack = self._build_stack() inventory_name, stack = self._build_stack()
if self._play_context.become: if self.become:
stack = stack[:-1] stack = stack[:-1]
worker_model = ansible_mitogen.process.get_worker_model() worker_model = ansible_mitogen.process.get_worker_model()

@ -294,7 +294,7 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase):
if not path.startswith('~'): if not path.startswith('~'):
# /home/foo -> /home/foo # /home/foo -> /home/foo
return path return path
if sudoable or not self._play_context.become: if sudoable or not self._connection.become:
if path == '~': if path == '~':
# ~ -> /home/dmw # ~ -> /home/dmw
return self._connection.homedir return self._connection.homedir

@ -417,6 +417,10 @@ class PlayContextSpec(Spec):
# used to run interpreter discovery # used to run interpreter discovery
self._action = connection._action self._action = connection._action
def _become_option(self, name):
plugin = self._connection.become
return plugin.get_option(name, self._task_vars, self._play_context)
def _connection_option(self, name): def _connection_option(self, name):
try: try:
return self._connection.get_option(name, hostvars=self._task_vars) return self._connection.get_option(name, hostvars=self._task_vars)
@ -437,13 +441,13 @@ class PlayContextSpec(Spec):
return self._connection_option('remote_user') return self._connection_option('remote_user')
def become(self): def become(self):
return self._play_context.become return self._connection.become
def become_method(self): def become_method(self):
return self._play_context.become_method return self._play_context.become_method
def become_user(self): def become_user(self):
return self._play_context.become_user return self._become_option('become_user')
def become_pass(self): def become_pass(self):
# become_pass is owned/provided by the active become plugin. However # become_pass is owned/provided by the active become plugin. However

@ -23,6 +23,7 @@ In progress (unreleased)
* :gh:issue:`1159` CI: Reduce number of Jobs by parameterizing Mitogen Docker * :gh:issue:`1159` CI: Reduce number of Jobs by parameterizing Mitogen Docker
SSH tests SSH tests
* :gh:issue:`1083` :mod:`ansible_mitogen`: Support templated become username.
v0.3.13 (2024-10-09) v0.3.13 (2024-10-09)

@ -134,6 +134,7 @@ sponsorship and outstanding future-thinking of its early adopters.
<li>luto</li> <li>luto</li>
<li><a href="https://mayeu.me/">Mayeu a.k.a Matthieu Maury</a></li> <li><a href="https://mayeu.me/">Mayeu a.k.a Matthieu Maury</a></li>
<li><a href="https://github.com/madsi1m">Michael D'Silva</a></li> <li><a href="https://github.com/madsi1m">Michael D'Silva</a></li>
<li><a href="https://github.com/mordekasg">mordek</a></li>
<li><a href="https://twitter.com/nathanhruby">@nathanhruby</a></li> <li><a href="https://twitter.com/nathanhruby">@nathanhruby</a></li>
<li><a href="https://github.com/opoplawski">Orion Poplawski</a></li> <li><a href="https://github.com/opoplawski">Orion Poplawski</a></li>
<li><a href="https://github.com/philfry">Philippe Kueck</a></li> <li><a href="https://github.com/philfry">Philippe Kueck</a></li>

@ -25,6 +25,20 @@ tt-bare
[tt_targets_bare:vars] [tt_targets_bare:vars]
ansible_host=localhost ansible_host=localhost
[tt_become_bare]
tt-become-bare
[tt_become_bare:vars]
ansible_host=localhost
ansible_user="{{ lookup('pipe', 'whoami') }}"
[tt_become_by_inv]
tt-become-user ansible_become=true ansible_become_user="{{ 'root' | trim }}"
[tt_become_by_inv:vars]
ansible_host=localhost
ansible_user="{{ lookup('pipe', 'whoami') }}"
[tt_targets_inventory] [tt_targets_inventory]
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

@ -5,3 +5,7 @@
- import_playbook: sudo_nopassword.yml - import_playbook: sudo_nopassword.yml
- import_playbook: sudo_password.yml - import_playbook: sudo_password.yml
- import_playbook: sudo_requiretty.yml - import_playbook: sudo_requiretty.yml
- import_playbook: templated_by_inv.yml
- import_playbook: templated_by_play_keywords.yml
- import_playbook: templated_by_play_vars.yml
- import_playbook: templated_by_task_keywords.yml

@ -0,0 +1,14 @@
- name: integration/become/templated_by_inv.yml
hosts: tt_become_by_inv
gather_facts: false
tasks:
- meta: reset_connection
- name: Templated become in inventory
command:
cmd: whoami
changed_when: false
check_mode: false
register: become_templated_by_inv_whoami
failed_when:
- become_templated_by_inv_whoami is failed
or become_templated_by_inv_whoami.stdout != 'root'

@ -0,0 +1,16 @@
- name: integration/become/templated_by_play_keywords.yml
hosts: tt_become_bare
gather_facts: false
become: true
become_user: "{{ 'root' | trim }}"
tasks:
- meta: reset_connection
- name: Templated become by play keywords
command:
cmd: whoami
changed_when: false
check_mode: false
register: become_templated_by_play_keywords_whoami
failed_when:
- become_templated_by_play_keywords_whoami is failed
or become_templated_by_play_keywords_whoami.stdout != 'root'

@ -0,0 +1,16 @@
- name: integration/become/templated_by_play_vars.yml
hosts: tt_become_bare
gather_facts: false
vars:
ansible_become: true
ansible_become_user: "{{ 'root' | trim }}"
tasks:
- name: Templated become by play vars
command:
cmd: whoami
changed_when: false
check_mode: false
register: become_templated_by_play_vars_whoami
failed_when:
- become_templated_by_play_vars_whoami is failed
or become_templated_by_play_vars_whoami.stdout != 'root'

@ -0,0 +1,27 @@
- name: integration/become/templated_by_task_keywords.yml
hosts: tt_become_bare
gather_facts: false
# FIXME Resetting the connection shouldn't require credentials
# https://github.com/mitogen-hq/mitogen/issues/1132
become: true
become_user: "{{ 'root' | trim }}"
tasks:
- name: Reset connection to target that will be delegate_to
meta: reset_connection
- name: Test connection template by task keywords, with delegate_to
hosts: test-targets[0]
gather_facts: false
tasks:
- name: Templated become by task keywords, with delegate_to
become: true
become_user: "{{ 'root' | trim }}"
delegate_to: "{{ groups.tt_become_bare[0] }}"
command:
cmd: whoami
changed_when: false
check_mode: false
register: become_templated_by_task_with_delegate_to_whoami
failed_when:
- become_templated_by_task_with_delegate_to_whoami is failed
or become_templated_by_task_with_delegate_to_whoami.stdout != 'root'

@ -48,6 +48,26 @@ ansible_host={{ tt.hostname }}
ansible_port={{ tt.port }} ansible_port={{ tt.port }}
ansible_python_interpreter={{ tt.python_path }} ansible_python_interpreter={{ tt.python_path }}
[tt_become_bare]
tt-become-bare
[tt_become_bare:vars]
ansible_host={{ tt.hostname }}
ansible_password=has_sudo_nopw_password
ansible_port={{ tt.port }}
ansible_python_interpreter={{ tt.python_path }}
ansible_user=mitogen__has_sudo_nopw
[tt_become_by_inv]
tt-become-user ansible_become=true ansible_become_user="{{ '{{' }} 'root' | trim {{ '}}' }}"
[tt_become_by_inv:vars]
ansible_host={{ tt.hostname }}
ansible_password=has_sudo_nopw_password
ansible_port={{ tt.port }}
ansible_python_interpreter={{ tt.python_path }}
ansible_user=mitogen__has_sudo_nopw
[tt_targets_inventory] [tt_targets_inventory]
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

Loading…
Cancel
Save