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 39a4b604..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 @@ -678,6 +689,7 @@ class MitogenViaSpec(Spec): def password(self): return optional_secret( + self._host_vars.get('ansible_ssh_password') or self._host_vars.get('ansible_ssh_pass') or self._host_vars.get('ansible_password') ) diff --git a/docs/ansible_detailed.rst b/docs/ansible_detailed.rst index fed347c8..d818edd7 100644 --- a/docs/ansible_detailed.rst +++ b/docs/ansible_detailed.rst @@ -306,7 +306,8 @@ container. * 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. + ``ansible_ssh_password``, ``ansible_password``, or + ``ansible_become_pass`` inventory variables. * Automatic tunnelling of SSH-dependent actions, such as the ``synchronize`` module, is not yet supported. This will be addressed in a @@ -1011,7 +1012,8 @@ Like the :ans:conn:`ssh` except connection delegation is supported. * ``ansible_port``, ``ssh_port`` * ``ansible_ssh_executable``, ``ssh_executable`` * ``ansible_ssh_private_key_file`` -* ``ansible_ssh_pass``, ``ansible_password`` (default: assume passwordless) +* ``ansible_ssh_pass``, ``ansible_ssh_password``, ``ansible_password`` + (default: assume passwordless) * ``ssh_args``, ``ssh_common_args``, ``ssh_extra_args`` * ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the Ansible controller process on remote machines. To simplify diagnostics, 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/docs/contributors.rst b/docs/contributors.rst index e40607a0..4e9e58bd 100644 --- a/docs/contributors.rst +++ b/docs/contributors.rst @@ -132,6 +132,7 @@ sponsorship and outstanding future-thinking of its early adopters.
  • Lewis Bellwood — Happy to be apart of a great project.
  • luto
  • Mayeu a.k.a Matthieu Maury
  • +
  • Michael D'Silva
  • @nathanhruby
  • Orion Poplawski
  • Philippe Kueck
  • 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/password.yml b/tests/ansible/integration/ssh/password.yml index cf9396e0..9b7dcf8a 100644 --- a/tests/ansible/integration/ssh/password.yml +++ b/tests/ansible/integration/ssh/password.yml @@ -16,6 +16,12 @@ ansible_ssh_pass: user1_password ping: + - meta: reset_connection + - name: ansible_ssh_password + vars: + ansible_ssh_password: user1_password + ping: + - meta: reset_connection - name: absent password should fail ping: @@ -34,13 +40,22 @@ ansible_password: wrong ansible_ssh_pass: user1_password - # Tests that ansible_ssh_pass has priority over ansible_password + - meta: reset_connection + - name: Highest priority password variable should override all others + vars: + ansible_password: wrong + ansible_ssh_pass: wrong + ansible_ssh_password: user1_password + ping: + + # Tests that ansible_ssh_password has priority over others # and that a wrong password causes a target to be marked unreachable. - meta: reset_connection - - name: ansible_password should not override + - name: Lower priority password variables should not override vars: ansible_password: user1_password - ansible_ssh_pass: wrong + ansible_ssh_pass: user1_password + ansible_ssh_password: wrong ping: ignore_errors: true ignore_unreachable: true 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