From cdfaf31ebca69330eeb0941458345598c120add4 Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Thu, 24 Oct 2024 12:09:40 +0100 Subject: [PATCH] ansible_mitogen: Template ssh_*_args connection options This expands support to setting them in Play scoped variables. Task scoped variables are also very likely to work, but untested for now. refs #905 --- ansible_mitogen/transport_config.py | 7 ++- docs/changelog.rst | 2 + tests/ansible/hosts/default.hosts | 2 +- tests/ansible/integration/ssh/all.yml | 3 +- .../ssh/{args.yml => args_by_inv.yml} | 5 +- .../integration/ssh/args_by_play_taskvar.yml | 52 +++++++++++++++++++ tests/ansible/templates/test-targets.j2 | 2 +- 7 files changed, 62 insertions(+), 11 deletions(-) rename tests/ansible/integration/ssh/{args.yml => args_by_inv.yml} (85%) create mode 100644 tests/ansible/integration/ssh/args_by_play_taskvar.yml diff --git a/ansible_mitogen/transport_config.py b/ansible_mitogen/transport_config.py index 708c2897..770c1997 100644 --- a/ansible_mitogen/transport_config.py +++ b/ansible_mitogen/transport_config.py @@ -506,13 +506,12 @@ class PlayContextSpec(Spec): ) def ssh_args(self): - local_vars = self._task_vars.get("hostvars", {}).get(self._inventory_name, {}) return [ mitogen.core.to_text(term) for s in ( - C.config.get_config_value("ssh_args", plugin_type="connection", plugin_name="ssh", variables=local_vars), - C.config.get_config_value("ssh_common_args", plugin_type="connection", plugin_name="ssh", variables=local_vars), - C.config.get_config_value("ssh_extra_args", plugin_type="connection", plugin_name="ssh", variables=local_vars) + self._connection_option('ssh_args'), + self._connection_option('ssh_common_args'), + self._connection_option('ssh_extra_args'), ) for term in ansible.utils.shlex.shlex_split(s or '') ] diff --git a/docs/changelog.rst b/docs/changelog.rst index 3a1d6ff2..0655e970 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:`905` :mod:`ansible_mitogen`: Support templated SSH command + arguments (e.g. ``ansible_ssh_args``, ``ansible_ssh_extra_args``). v0.3.14 (2024-10-16) diff --git a/tests/ansible/hosts/default.hosts b/tests/ansible/hosts/default.hosts index ef05803e..2edb9d0e 100644 --- a/tests/ansible/hosts/default.hosts +++ b/tests/ansible/hosts/default.hosts @@ -17,7 +17,7 @@ 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 }} +ssh_args_canary_file=/tmp/ssh_args_by_inv_{{ inventory_hostname }} [tt_targets_bare] tt-bare diff --git a/tests/ansible/integration/ssh/all.yml b/tests/ansible/integration/ssh/all.yml index eada992a..20031704 100644 --- a/tests/ansible/integration/ssh/all.yml +++ b/tests/ansible/integration/ssh/all.yml @@ -1,4 +1,5 @@ -- import_playbook: args.yml +- import_playbook: args_by_inv.yml +- import_playbook: args_by_play_taskvar.yml - import_playbook: config.yml - import_playbook: password.yml - import_playbook: timeouts.yml diff --git a/tests/ansible/integration/ssh/args.yml b/tests/ansible/integration/ssh/args_by_inv.yml similarity index 85% rename from tests/ansible/integration/ssh/args.yml rename to tests/ansible/integration/ssh/args_by_inv.yml index 5892b5fe..58fd1e28 100644 --- a/tests/ansible/integration/ssh/args.yml +++ b/tests/ansible/integration/ssh/args_by_inv.yml @@ -1,12 +1,9 @@ -- name: integration/ssh/args.yml +- name: integration/ssh/args_by_inv.yml hosts: issue905 gather_facts: false tasks: # Test that ansible_ssh_common_args are templated; ansible_ssh_args & # ansible_ssh_extra_args aren't directly tested, we assume they're similar. - # FIXME This test currently relies on variables set in the host group. - # Ideally they'd be set here, and the host group eliminated, but - # Mitogen currently fails to template when defined in the play. # TODO Replace LocalCommand canary with SetEnv canary, to simplify test. # Requires modification of sshd_config files to add AcceptEnv ... - name: Test templating of ansible_ssh_common_args et al diff --git a/tests/ansible/integration/ssh/args_by_play_taskvar.yml b/tests/ansible/integration/ssh/args_by_play_taskvar.yml new file mode 100644 index 00000000..5ae83f2a --- /dev/null +++ b/tests/ansible/integration/ssh/args_by_play_taskvar.yml @@ -0,0 +1,52 @@ +- name: integration/ssh/args_by_play_taskvar.yml + hosts: tt_targets_bare + gather_facts: false + vars: + ansible_password: "{{ 'has_sudo_nopw_password' | trim }}" + ansible_port: "{{ hostvars[groups['test-targets'][0]].ansible_port | default(22) }}" + ansible_ssh_common_args: >- + -o PermitLocalCommand=yes + -o LocalCommand="touch {{ ssh_args_canary_file }}" + ansible_user: "{{ 'mitogen__has_sudo_nopw' | trim }}" + ssh_args_canary_file: "/tmp/ssh_args_by_play_taskvar_{{ inventory_hostname }}" + tasks: + # Test that ansible_ssh_common_args are templated; ansible_ssh_args & + # ansible_ssh_extra_args aren't directly tested, we assume they're similar. + # TODO Replace LocalCommand canary with SetEnv canary, to simplify test. + # Requires modification of sshd_config files to add AcceptEnv ... + - name: Test templating of ansible_ssh_common_args et al, by play taskvars + block: + - name: Ensure no lingering canary files + file: + path: "{{ ssh_args_canary_file }}" + state: absent + delegate_to: localhost + + - name: Reset connections to force new ssh execution + meta: reset_connection + + - name: Perform SSH connection, to trigger side effect + ping: + + - name: Stat for canary file created by side effect + stat: + path: "{{ ssh_args_canary_file }}" + delegate_to: localhost + register: ssh_args_by_play_taskvar_canary_stat + + - assert: + that: + - ssh_args_by_play_taskvar_canary_stat.stat.exists == true + quiet: true + success_msg: "Canary found: {{ ssh_args_canary_file }}" + fail_msg: | + ssh_args_canary_file={{ ssh_args_canary_file }} + ssh_args_by_play_taskvar_canary_stat={{ ssh_args_by_play_taskvar_canary_stat }} + always: + - name: Cleanup canary files + file: + path: "{{ ssh_args_canary_file }}" + state: absent + delegate_to: localhost + tags: + - issue_905 diff --git a/tests/ansible/templates/test-targets.j2 b/tests/ansible/templates/test-targets.j2 index 47f2ccd4..c0bd9cef 100644 --- a/tests/ansible/templates/test-targets.j2 +++ b/tests/ansible/templates/test-targets.j2 @@ -36,7 +36,7 @@ ssh-common-args ansible_host={{ c.hostname }} ansible_port={{ c.port }} ansible_ 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 {{ '}}' }} +ssh_args_canary_file=/tmp/ssh_args_by_inv_{{ '{{' }} inventory_hostname {{ '}}' }} {% set tt = containers[0] %}