From 551690ee1dd47aee18a448202f8ae8b9c6f016c1 Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Mon, 16 Sep 2024 00:32:29 +0100 Subject: [PATCH] ansible_mitogen: Handle templated connection passwords and ansible_ssh_password This switches `ansible_mitogen.transport_config.PlayContextSpec.password()` to Ansible's plugin option framework. As a result - The relatively recent `ansible_ssh_password` variable is now respected. - The SSH connection password can be templated and specified as a play variable. Task variables will probably also work, but testing was blocked by #1132. There is a chance this change will cause a regression in another connection plugin (e.g. mitogen_docker), but nothing turned up in the test suite. I intend ot migrate other connection configuration to `ansible_mitogen.transport_config.PlayContextSpec._connect_option()`, the next candidate is the remote port. fixes #1106 --- .../plugins/connection/mitogen_ssh.py | 27 +++++-------------- ansible_mitogen/transport_config.py | 13 ++++++++- docs/changelog.rst | 2 ++ tests/ansible/hosts/default.hosts | 14 ++++++++++ tests/ansible/integration/ssh/all.yml | 2 ++ .../integration/ssh/templated_by_inv.yml | 7 +++++ .../ssh/templated_by_play_taskvar.yml | 10 +++++++ tests/ansible/templates/test-targets.j2 | 19 +++++++++++++ 8 files changed, 72 insertions(+), 22 deletions(-) create mode 100644 tests/ansible/integration/ssh/templated_by_inv.yml create mode 100644 tests/ansible/integration/ssh/templated_by_play_taskvar.yml diff --git a/ansible_mitogen/plugins/connection/mitogen_ssh.py b/ansible_mitogen/plugins/connection/mitogen_ssh.py index 75f2d42f..f6a27a6e 100644 --- a/ansible_mitogen/plugins/connection/mitogen_ssh.py +++ b/ansible_mitogen/plugins/connection/mitogen_ssh.py @@ -32,35 +32,20 @@ __metaclass__ = type import os.path import sys +from ansible.plugins.connection.ssh import ( + DOCUMENTATION as _ansible_ssh_DOCUMENTATION, +) + DOCUMENTATION = """ + name: mitogen_ssh author: David Wilson - connection: mitogen_ssh short_description: Connect over SSH via Mitogen description: - This connects using an OpenSSH client controlled by the Mitogen for Ansible extension. It accepts every option the vanilla ssh plugin accepts. - version_added: "2.5" options: - ssh_args: - type: str - vars: - - name: ssh_args - - name: ansible_ssh_args - - name: ansible_mitogen_ssh_args - ssh_common_args: - type: str - vars: - - name: ssh_args - - name: ansible_ssh_common_args - - name: ansible_mitogen_ssh_common_args - ssh_extra_args: - type: str - vars: - - name: ssh_args - - name: ansible_ssh_extra_args - - name: ansible_mitogen_ssh_extra_args -""" +""" + _ansible_ssh_DOCUMENTATION.partition('options:\n')[2] try: import ansible_mitogen diff --git a/ansible_mitogen/transport_config.py b/ansible_mitogen/transport_config.py index 39df3f6a..a3336365 100644 --- a/ansible_mitogen/transport_config.py +++ b/ansible_mitogen/transport_config.py @@ -62,6 +62,7 @@ from __future__ import unicode_literals __metaclass__ = type import abc +import logging import os import ansible.utils.shlex import ansible.constants as C @@ -74,6 +75,9 @@ from ansible.module_utils.parsing.convert_bool import boolean import mitogen.core +LOG = logging.getLogger(__name__) + + def run_interpreter_discovery_if_necessary(s, task_vars, action, rediscover_python): """ Triggers ansible python interpreter discovery if requested. @@ -412,6 +416,13 @@ class PlayContextSpec(Spec): # used to run interpreter discovery self._action = connection._action + def _connection_option(self, name): + try: + return self._connection.get_option(name, hostvars=self._task_vars) + except KeyError: + LOG.debug('Used PlayContext fallback for option=%r', name) + return getattr(self._play_context, name) + def transport(self): return self._transport @@ -449,7 +460,7 @@ class PlayContextSpec(Spec): return optional_secret(become_pass) def password(self): - return optional_secret(self._play_context.password) + return optional_secret(self._connection_option('password')) def port(self): return self._play_context.port diff --git a/docs/changelog.rst b/docs/changelog.rst index 0b2875fa..25e3820c 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 Unreleased ---------- +* :gh:issue:`1106` :mod:`ansible_mitogen`: Support for `ansible_ssh_password` + connection variable, and templated SSH connection password. v0.3.11 (2024-10-30) diff --git a/tests/ansible/hosts/default.hosts b/tests/ansible/hosts/default.hosts index adc271e2..8ed80787 100644 --- a/tests/ansible/hosts/default.hosts +++ b/tests/ansible/hosts/default.hosts @@ -19,3 +19,17 @@ ssh-common-args ansible_host=localhost ansible_user="{{ lookup('pipe', 'whoami') [issue905:vars] ansible_ssh_common_args=-o PermitLocalCommand=yes -o LocalCommand="touch {{ ssh_args_canary_file }}" ssh_args_canary_file=/tmp/ssh_args_{{ inventory_hostname }} + +[tt_targets_bare] +tt-bare + +[tt_targets_bare:vars] +ansible_host=localhost +ansible_user=mitogen__has_sudo_nopw + +[tt_targets_inventory] +tt-password ansible_password="{{ 'has_sudo_nopw_password' | trim }}" + +[tt_targets_inventory:vars] +ansible_host=localhost +ansible_user=mitogen__has_sudo_nopw diff --git a/tests/ansible/integration/ssh/all.yml b/tests/ansible/integration/ssh/all.yml index 5c16f187..ab400051 100644 --- a/tests/ansible/integration/ssh/all.yml +++ b/tests/ansible/integration/ssh/all.yml @@ -2,4 +2,6 @@ - import_playbook: config.yml - import_playbook: password.yml - import_playbook: timeouts.yml +- import_playbook: templated_by_inv.yml +- import_playbook: templated_by_play_taskvar.yml - import_playbook: variables.yml diff --git a/tests/ansible/integration/ssh/templated_by_inv.yml b/tests/ansible/integration/ssh/templated_by_inv.yml new file mode 100644 index 00000000..686518fd --- /dev/null +++ b/tests/ansible/integration/ssh/templated_by_inv.yml @@ -0,0 +1,7 @@ +- name: integration/ssh/templated_by_inv.yml + hosts: tt_targets_inventory + gather_facts: false + tasks: + - meta: reset_connection + - name: Templated variables in inventory + ping: diff --git a/tests/ansible/integration/ssh/templated_by_play_taskvar.yml b/tests/ansible/integration/ssh/templated_by_play_taskvar.yml new file mode 100644 index 00000000..bc4ef1d8 --- /dev/null +++ b/tests/ansible/integration/ssh/templated_by_play_taskvar.yml @@ -0,0 +1,10 @@ +- name: integration/ssh/templated_by_play_taskvar.yml + hosts: tt_targets_bare + gather_facts: false + vars: + ansible_password: "{{ 'has_sudo_nopw_password' | trim }}" + + tasks: + - meta: reset_connection + - name: Templated variables in play + ping: diff --git a/tests/ansible/templates/test-targets.j2 b/tests/ansible/templates/test-targets.j2 index e2708192..37a0725a 100644 --- a/tests/ansible/templates/test-targets.j2 +++ b/tests/ansible/templates/test-targets.j2 @@ -37,3 +37,22 @@ ansible_user=mitogen__has_sudo_nopw ansible_password=has_sudo_nopw_password ansible_ssh_common_args=-o PermitLocalCommand=yes -o LocalCommand="touch {{ '{{' }} ssh_args_canary_file {{ '}}' }}" ssh_args_canary_file=/tmp/ssh_args_{{ '{{' }} inventory_hostname {{ '}}' }} + +{% set tt = containers[0] %} + +[tt_targets_bare] +tt-bare + +[tt_targets_bare:vars] +ansible_host={{ tt.hostname }} +ansible_port={{ tt.port }} +ansible_python_interpreter={{ tt.python_path }} +ansible_user=mitogen__has_sudo_nopw + +[tt_targets_inventory] +tt-password ansible_password="{{ '{{' }} 'has_sudo_nopw_password' | trim {{ '}}' }}" ansible_port={{ tt.port }} + +[tt_targets_inventory:vars] +ansible_host={{ tt.hostname }} +ansible_python_interpreter={{ tt.python_path }} +ansible_user=mitogen__has_sudo_nopw