From d5e918628985e497fcffec6568bb0a4a61582830 Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Fri, 7 Jul 2023 21:32:02 +0100 Subject: [PATCH 1/2] ansible_mitogen: Fix --ask-become-pass, add test coverage Previously f1503874de82353cbed8b51408d20fdfa899f8f7 fixed the priority of ansible_become_pass over ansible_become_password, but broke --ask-become-pass. Fixes #952. --- .ci/ansible_tests.py | 11 +++++++++- ansible_mitogen/transport_config.py | 16 ++++++++++---- docs/changelog.rst | 1 + tests/ansible/hosts/default.hosts | 2 ++ .../transport_config/become_pass.yml | 5 +++-- tests/ansible/regression/all.yml | 1 + tests/ansible/regression/become_test.yml | 9 ++++++++ .../regression/issue_952__ask_become_pass.yml | 21 +++++++++++++++++++ tests/requirements.txt | 2 ++ 9 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 tests/ansible/regression/become_test.yml create mode 100644 tests/ansible/regression/issue_952__ask_become_pass.yml diff --git a/.ci/ansible_tests.py b/.ci/ansible_tests.py index 43d4f4cb..0dd978c4 100755 --- a/.ci/ansible_tests.py +++ b/.ci/ansible_tests.py @@ -6,6 +6,7 @@ import glob import os import signal import sys +import textwrap import ci_lib @@ -74,7 +75,15 @@ with ci_lib.Fold('job_setup'): fp.write('\n[%s]\n' % family) fp.writelines('%s\n' % name for name in hostnames) - fp.write('\n[linux:children]\ntest-targets\n') + fp.write(textwrap.dedent( + ''' + [linux:children] + test-targets + + [linux_containers:children] + test-targets + ''' + )) ci_lib.dump_file(inventory_path) diff --git a/ansible_mitogen/transport_config.py b/ansible_mitogen/transport_config.py index 5fc78185..1fc1e80a 100644 --- a/ansible_mitogen/transport_config.py +++ b/ansible_mitogen/transport_config.py @@ -79,7 +79,6 @@ try: except ImportError: from ansible.vars.unsafe_proxy import AnsibleUnsafeText -import ansible_mitogen.loaders import mitogen.core @@ -436,9 +435,18 @@ class PlayContextSpec(Spec): return self._play_context.become_user def become_pass(self): - become_method = self.become_method() - become_plugin = ansible_mitogen.loaders.become_loader.get(become_method) - become_pass = become_plugin.get_option('become_pass', hostvars=self._task_vars) + # become_pass is owned/provided by the active become plugin. However + # PlayContext is intertwined with it. Known complications + # - ansible_become_password is higher priority than ansible_become_pass, + # `play_context.become_pass` doesn't obey this (atleast with Mitgeon). + # - `meta: reset_connection` runs `connection.reset()` but + # `ansible_mitogen.connection.Connection.reset()` recreates the + # connection object, setting `connection.become = None`. + become_plugin = self._connection.become + try: + become_pass = become_plugin.get_option('become_pass', playcontext=self._play_context) + except AttributeError: + become_pass = self._play_context.become_pass return optional_secret(become_pass) def password(self): diff --git a/docs/changelog.rst b/docs/changelog.rst index 0600ca3a..bcf6d01e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -21,6 +21,7 @@ To avail of fixes in an unreleased version, please download a ZIP file Unreleased ---------- +* :gh:issue:`952` Fix Ansible `--ask-become-pass`, add test coverage v0.3.7 (2024-04-08) diff --git a/tests/ansible/hosts/default.hosts b/tests/ansible/hosts/default.hosts index 1bec0014..4f5ea4c6 100644 --- a/tests/ansible/hosts/default.hosts +++ b/tests/ansible/hosts/default.hosts @@ -10,3 +10,5 @@ target ansible_host=localhost ansible_user="{{ lookup('pipe', 'whoami') }}" [test-targets] target + +[linux_containers] diff --git a/tests/ansible/integration/transport_config/become_pass.yml b/tests/ansible/integration/transport_config/become_pass.yml index 8fbe7251..b9bf1a8e 100644 --- a/tests/ansible/integration/transport_config/become_pass.yml +++ b/tests/ansible/integration/transport_config/become_pass.yml @@ -143,8 +143,9 @@ - out.result|length == 2 - out.result[0].method == "ssh" - out.result[1].method == "sudo" - # Ansible >= 2.10 builtin become plugins (e.g. sudo, su) give priority - # to ansible_become_pass over ansible_become_password. + # Ansible <= 2.9.1 prioritises ansible_become_password. + # Ansible >= 2.9.2 prioritises ansible_become_pass. + # https://github.com/ansible/ansible/commit/480b106d6535978ae6ecab68b40942ca4fa914a0 - out.result[1].kwargs.password == "bpass" fail_msg: out={{out}} tags: diff --git a/tests/ansible/regression/all.yml b/tests/ansible/regression/all.yml index 0e599476..477caccd 100644 --- a/tests/ansible/regression/all.yml +++ b/tests/ansible/regression/all.yml @@ -14,3 +14,4 @@ - import_playbook: issue_615__streaming_transfer.yml - import_playbook: issue_655__wait_for_connection_error.yml - import_playbook: issue_776__load_plugins_called_twice.yml +- import_playbook: issue_952__ask_become_pass.yml diff --git a/tests/ansible/regression/become_test.yml b/tests/ansible/regression/become_test.yml new file mode 100644 index 00000000..5af2e123 --- /dev/null +++ b/tests/ansible/regression/become_test.yml @@ -0,0 +1,9 @@ +- name: regression/become_test.yml + hosts: test-targets:&linux_containers + become: true + become_user: mitogen__pw_required + strategy: mitogen_linear + tasks: + - command: whoami + changed_when: false + check_mode: false diff --git a/tests/ansible/regression/issue_952__ask_become_pass.yml b/tests/ansible/regression/issue_952__ask_become_pass.yml new file mode 100644 index 00000000..da269e2d --- /dev/null +++ b/tests/ansible/regression/issue_952__ask_become_pass.yml @@ -0,0 +1,21 @@ +- name: regression/issue_952__ask_become_pass.yml + hosts: test-targets[0]:&linux_containers + gather_facts: false + tags: + - issue_952 + tasks: + - name: Test --ask-become-pass + delegate_to: localhost + expect: + command: > + ansible-playbook + {% for inv in ansible_inventory_sources %} + -i "{{ inv }}" + {% endfor %} + --ask-become-pass + regression/become_test.yml + chdir: ../ + responses: + 'BECOME password:': pw_required_password + changed_when: false + check_mode: false diff --git a/tests/requirements.txt b/tests/requirements.txt index 6d87d177..d64d8b87 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -12,6 +12,8 @@ Django==3.2.20; python_version >= '3.6' mock==3.0.5; python_version == '2.7' mock==5.1.0; python_version >= '3.6' +pexpect==4.8 + psutil==5.9.8 pytest==4.6.11; python_version == '2.7' From 8c93973f98698128c16f196a968211e86ff5a98b Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Fri, 12 Apr 2024 12:55:28 +0100 Subject: [PATCH 2/2] tests: Use Android portal to check get_url Should have higher uptime, and make us less of a burden. Refs #1058 --- .../interpreter_discovery/complex_args.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/ansible/integration/interpreter_discovery/complex_args.yml b/tests/ansible/integration/interpreter_discovery/complex_args.yml index 6ffff5f4..a3755ebf 100644 --- a/tests/ansible/integration/interpreter_discovery/complex_args.yml +++ b/tests/ansible/integration/interpreter_discovery/complex_args.yml @@ -29,20 +29,18 @@ special_python: "source /tmp/fake || true && python{{ ansible_facts.python.version.major }}" - name: run get_url with specially-sourced python - get_url: + uri: # Plain http for wider Ansible & Python version compatibility - url: http://httpbin.org/get - dest: "/tmp/" - mode: 0644 + url: http://www.gstatic.com/generate_204 + status_code: [204] vars: ansible_python_interpreter: "{{ special_python }}" - name: run get_url with specially-sourced python including jinja - get_url: + uri: # Plain http for wider Ansible & Python version compatibility - url: http://httpbin.org/get - dest: "/tmp/" - mode: 0644 + url: http://www.gstatic.com/generate_204 + status_code: [204] vars: ansible_python_interpreter: > {% if "1" == "1" %}