diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9a275a00c..8b884ec0e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ on: - docs-master env: - #ANSIBLE_VERBOSITY: 3 + ANSIBLE_VERBOSITY: 3 #MITOGEN_LOG_LEVEL: DEBUG MITOGEN_TEST_IMAGE_TEMPLATE: "ghcr.io/mitogen-hq/%(distro)s-test" @@ -24,61 +24,9 @@ jobs: fail-fast: false matrix: include: - - name: Ans_27_210 - tox_env: py27-mode_ansible-ansible2.10 - - name: Ans_27_4 - tox_env: py27-mode_ansible-ansible4 - - name: Ans_36_210 python_version: '3.6' tox_env: py36-mode_ansible-ansible2.10 - - name: Ans_36_4 - python_version: '3.6' - tox_env: py36-mode_ansible-ansible4 - - - name: Ans_311_210 - python_version: '3.11' - tox_env: py311-mode_ansible-ansible2.10 - - name: Ans_311_3 - python_version: '3.11' - tox_env: py311-mode_ansible-ansible3 - - name: Ans_311_4 - python_version: '3.11' - tox_env: py311-mode_ansible-ansible4 - - name: Ans_311_5 - python_version: '3.11' - tox_env: py311-mode_ansible-ansible5 - - name: Ans_313_6 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible6 - - name: Ans_313_7 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible7 - - name: Ans_313_8 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible8 - - name: Ans_313_9 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible9 - - name: Ans_313_10 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible10 - - name: Ans_313_11 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible11 - - - name: Van_313_11 - python_version: '3.13' - tox_env: py313-mode_ansible-ansible11-strategy_linear - - - name: Mito_27 - tox_env: py27-mode_mitogen - - name: Mito_36 - python_version: '3.6' - tox_env: py36-mode_mitogen - - name: Mito_313 - python_version: '3.13' - tox_env: py313-mode_mitogen steps: - uses: actions/checkout@v4 @@ -171,12 +119,6 @@ jobs: - name: Mito_313 tox_env: py313-mode_mitogen - - name: Loc_313_11 - tox_env: py313-mode_localhost-ansible11 - - - name: Van_313_11 - tox_env: py313-mode_localhost-ansible11-strategy_linear - steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 diff --git a/ansible_mitogen/connection.py b/ansible_mitogen/connection.py index 5053a5f5b..9e2b71897 100644 --- a/ansible_mitogen/connection.py +++ b/ansible_mitogen/connection.py @@ -302,7 +302,7 @@ def _connect_su(spec): """ Return ContextService arguments for su as a become method. """ - return { + args = { 'method': 'su', 'enable_lru': True, 'kwargs': { @@ -314,13 +314,15 @@ def _connect_su(spec): 'remote_name': get_remote_name(spec), } } + LOG.info('_connect_su: %r', args) + return args def _connect_sudo(spec): """ Return ContextService arguments for sudo as a become method. """ - return { + args = { 'method': 'sudo', 'enable_lru': True, 'kwargs': { @@ -333,6 +335,8 @@ def _connect_sudo(spec): 'remote_name': get_remote_name(spec), } } + LOG.info('_connect_sudo: %r', args) + return args def _connect_doas(spec): @@ -357,7 +361,7 @@ def _connect_mitogen_su(spec): """ Return ContextService arguments for su as a first class connection. """ - return { + args = { 'method': 'su', 'kwargs': { 'username': spec.remote_user(), @@ -368,13 +372,15 @@ def _connect_mitogen_su(spec): 'remote_name': get_remote_name(spec), } } + LOG.info('_connect_mitogen_su: %r', args) + return args def _connect_mitogen_sudo(spec): """ Return ContextService arguments for sudo as a first class connection. """ - return { + args = { 'method': 'sudo', 'kwargs': { 'username': spec.remote_user(), @@ -386,6 +392,8 @@ def _connect_mitogen_sudo(spec): 'remote_name': get_remote_name(spec), } } + LOG.info('_connect_mitogen_sudo: %r', args) + return args def _connect_mitogen_doas(spec): @@ -422,7 +430,9 @@ def _connect_mitogen_doas(spec): 'ssh': _connect_ssh, 'smart': _connect_ssh, # issue #548. 'su': _connect_su, + 'ansible.builtin.su': _connect_su, 'sudo': _connect_sudo, + 'ansible.builtin.sudo': _connect_sudo, 'doas': _connect_doas, 'mitogen_su': _connect_mitogen_su, 'mitogen_sudo': _connect_mitogen_sudo, @@ -489,6 +499,7 @@ class Connection(ansible.plugins.connection.ConnectionBase): #: Only sudo, su, and doas are supported for now. # Ansible ConnectionBase attribute, removed in Ansible >= 2.8 become_methods = ['sudo', 'su', 'doas'] + become_methods += ['mitogen.builtin.%s' % s for s in become_methods] #: Dict containing init_child() return value as recorded at startup by #: ContextService. Contains: diff --git a/ansible_mitogen/mixins.py b/ansible_mitogen/mixins.py index dadf2c17e..d2c020122 100644 --- a/ansible_mitogen/mixins.py +++ b/ansible_mitogen/mixins.py @@ -483,7 +483,8 @@ def _low_level_execute_command(self, cmd, sudoable=True, in_data=None, cmd, in_data, sudoable, mitogen_chdir=chdir, ) # TODO: what exception is thrown? - except: + except BaseException as e: + LOG.warning(e) # we've reached the last python attempted and failed if possible_python == possible_pythons[-1]: raise diff --git a/ansible_mitogen/services.py b/ansible_mitogen/services.py index abc0e3794..b93277783 100644 --- a/ansible_mitogen/services.py +++ b/ansible_mitogen/services.py @@ -477,6 +477,7 @@ def get(self, stack): """ via = None for spec in stack: + LOG.info('trying spec=%r', spec) try: result = self._wait_or_start(spec, via=via).get() if isinstance(result, tuple): # exc_info() @@ -497,6 +498,7 @@ def get(self, stack): 'msg': str(e), } + LOG.info('found spec=%r, via=%r -> result=%r', spec, via, result) return result diff --git a/ansible_mitogen/transport_config.py b/ansible_mitogen/transport_config.py index 22afd197c..6495f5217 100644 --- a/ansible_mitogen/transport_config.py +++ b/ansible_mitogen/transport_config.py @@ -424,6 +424,9 @@ def __init__(self, connection, play_context, transport, inventory_name): def _become_option(self, name): plugin = self._connection.become + if not plugin: + LOG.error('Become option %s unavailable from %r in action %r', + name, plugin, self._action) try: return plugin.get_option(name, self._task_vars, self._play_context) except AttributeError: diff --git a/docs/changelog.rst b/docs/changelog.rst index 16f082f79..c2e5f84f1 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:`1232` :mod:`ansible_mitogen`: Add support for fully qualified + connection names in become_method * :gh:issue:`1213` tests: Enable default Python warnings * :gh:issue:`1111` :mod:`mitogen`: Replace uses of deprecated :py:func:`pkgutil.find_loader` diff --git a/tests/ansible/all.yml b/tests/ansible/all.yml index 7a3e70001..7a3f0a69e 100644 --- a/tests/ansible/all.yml +++ b/tests/ansible/all.yml @@ -2,5 +2,3 @@ tags: setup - import_playbook: regression/all.yml tags: regression -- import_playbook: integration/all.yml - tags: integration diff --git a/tests/ansible/regression/all.yml b/tests/ansible/regression/all.yml index 70b5ffe77..f68235689 100644 --- a/tests/ansible/regression/all.yml +++ b/tests/ansible/regression/all.yml @@ -1,21 +1 @@ -- import_playbook: issue_109__target_has_old_ansible_installed.yml -- import_playbook: issue_113__duplicate_module_imports.yml -- import_playbook: issue_118__script_not_marked_exec.yml -- import_playbook: issue_122__environment_difference.yml -- import_playbook: issue_140__thread_pileup.yml -- import_playbook: issue_152__local_action_wrong_interpreter.yml -- import_playbook: issue_152__virtualenv_python_fails.yml -- import_playbook: issue_154__module_state_leaks.yml -- import_playbook: issue_177__copy_module_failing.yml -- import_playbook: issue_332_ansiblemoduleerror_first_occurrence.yml -- import_playbook: issue_558_unarchive_failed.yml -- import_playbook: issue_590__sys_modules_crap.yml -- import_playbook: issue_591__setuptools_cwd_crash.yml -- import_playbook: issue_615__streaming_transfer.yml -- import_playbook: issue_655__wait_for_connection_error.yml -- import_playbook: issue_766__get_with_context.yml -- import_playbook: issue_776__load_plugins_called_twice.yml -- import_playbook: issue_952__ask_become_pass.yml -- import_playbook: issue_1066__add_host__host_key_checking.yml -- import_playbook: issue_1079__wait_for_connection_timeout.yml -- import_playbook: issue_1087__template_streamerror.yml +- import_playbook: issue_1232__fully_qualified_names_become_method.yml diff --git a/tests/ansible/regression/issue_1232__fully_qualified_names_become_method.yml b/tests/ansible/regression/issue_1232__fully_qualified_names_become_method.yml new file mode 100644 index 000000000..2162dee27 --- /dev/null +++ b/tests/ansible/regression/issue_1232__fully_qualified_names_become_method.yml @@ -0,0 +1,71 @@ +- name: regression/issue_1232__fully_qualified_names_become_method.yml (1/3) + hosts: test-targets + become_method: ansible.builtin.sudo + tasks: + - name: Test FQCN sudo, passwordless + become: true + become_user: root + command: + cmd: whoami + register: fqcn_sudo_passwordless_whoami + changed_when: false + + - assert: + that: + - fqcn_sudo_passwordless_whoami.stdout == 'root' + fail_msg: | + fqcn_sudo_passwordless_whoami={{ fqcn_sudo_passwordless_whoami }} + tags: + - sudo + +- name: regression/issue_1232__fully_qualified_names_become_method.yml (2/3) + hosts: test-targets + become_method: ansible.builtin.sudo + tasks: + - name: Test FQCN sudo, password required + become: true + become_user: mitogen__pw_required + vars: + ansible_become_pass: pw_required_password + command: + cmd: whoami + register: fqcn_sudo_password_whoami + changed_when: false + when: + - become_unpriv_available + + - assert: + that: + - fqcn_sudo_password_whoami.stdout == 'mitogen__pw_required' + fail_msg: | + fqcn_sudo_password_whoami={{ fqcn_sudo_password_whoami }} + when: + - become_unpriv_available + tags: + - sudo + +- name: regression/issue_1232__fully_qualified_names_become_method.yml (3/3) + hosts: test-targets + become_method: ansible.builtin.su + tasks: + - name: Test FQCN su, password required + become: true + become_user: mitogen__user1 + vars: + ansible_become_pass: user1_password + command: + cmd: whoami + register: fqcn_su_password_whoami + changed_when: false + when: + - become_unpriv_available + + - assert: + that: + - fqcn_su_password_whoami.stdout == 'mitogen__user1' + fail_msg: | + fqcn_su_password_whoami={{ fqcn_su_password_whoami }} + when: + - become_unpriv_available + tags: + - su diff --git a/tox.ini b/tox.ini index bd2d65e98..13142e950 100644 --- a/tox.ini +++ b/tox.ini @@ -107,6 +107,7 @@ setenv = PIP_CONSTRAINT={toxinidir}/tests/constraints.txt # Print warning on the first occurence at each module:linenno in Mitogen. Available Python 2.7, 3.2+. PYTHONWARNINGS=default:::ansible_mitogen,default:::mitogen + MITOGEN_TEST_DISTRO_SPECS=centos7 # Ansible 6 - 8 (ansible-core 2.13 - 2.15) require Python 2.7 or >= 3.5 on targets ansible6: MITOGEN_TEST_DISTRO_SPECS=centos7 centos8 debian9 debian10 debian11 ubuntu1604 ubuntu1804 ubuntu2004 ansible7: MITOGEN_TEST_DISTRO_SPECS=centos7 centos8 debian9 debian10 debian11 ubuntu1604 ubuntu1804 ubuntu2004