From 0b7fd3f2904f3f9af0293deefad7e9ca361f226f Mon Sep 17 00:00:00 2001 From: David Wilson Date: Mon, 3 Jun 2019 02:31:43 +0100 Subject: [PATCH] issue #591: ansible: restore CWD prior to AnsibleModule initialization. --- ansible_mitogen/runner.py | 11 ++++++++++ docs/changelog.rst | 11 ++++++++++ .../lib/modules/custom_python_os_getcwd.py | 14 +++++++++++++ tests/ansible/regression/all.yml | 1 + .../issue_591__setuptools_cwd_crash.yml | 20 +++++++++++++++++++ 5 files changed, 57 insertions(+) create mode 100644 tests/ansible/lib/modules/custom_python_os_getcwd.py create mode 100644 tests/ansible/regression/issue_591__setuptools_cwd_crash.yml diff --git a/ansible_mitogen/runner.py b/ansible_mitogen/runner.py index 8dbddadd..05bc55c0 100644 --- a/ansible_mitogen/runner.py +++ b/ansible_mitogen/runner.py @@ -344,11 +344,22 @@ class Runner(object): env.update(self.env) self._env = TemporaryEnvironment(env) + def _revert_cwd(self): + """ + #591: make a best-effort attempt to return to :attr:`good_temp_dir`. + """ + try: + os.chdir(self.good_temp_dir) + except OSError: + LOG.debug('%r: could not restore CWD to %r', + self, self.good_temp_dir) + def revert(self): """ Revert any changes made to the process after running a module. The base implementation simply restores the original environment. """ + self._revert_cwd() self._env.revert() self.revert_temp_dir() diff --git a/docs/changelog.rst b/docs/changelog.rst index 4a3a5612..1e4c7e18 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -30,18 +30,29 @@ Enhancements `_ functionality, which will be addressed in a future release. + Fixes ^^^^^ * `#590 `_: the importer can handle modules that replace themselves in :mod:`sys.modules` during import. +* `#591 `_: the target's current + working directory is restored to a known-existent directory between tasks to + ensure :func:`os.getcwd` will not fail when called, in the same way that + :class:`AnsibleModule` restores it during initialization. However this + restore happens before the module ever executes, ensuring any code that calls + :func:`os.getcwd` prior to :class:`AnsibleModule` initialization, such as the + Ansible 2.7 ``pip`` module, cannot fail due to the behavior of a prior task. + Thanks! ~~~~~~~ Mitogen would not be possible without the support of users. A huge thanks for bug reports, testing, features and fixes in this release contributed by +`Anton Markelov `_, +`Nigel Metheringham `_, `Orion Poplawski `_, and `Ulrich Schreiner `_. diff --git a/tests/ansible/lib/modules/custom_python_os_getcwd.py b/tests/ansible/lib/modules/custom_python_os_getcwd.py new file mode 100644 index 00000000..7fe3fd1b --- /dev/null +++ b/tests/ansible/lib/modules/custom_python_os_getcwd.py @@ -0,0 +1,14 @@ +#!/usr/bin/python +# #591: call os.getcwd() before AnsibleModule ever gets a chance to fix up the +# process environment. + +import os + +try: + import json +except ImportError: + import simplejson as json + +print(json.dumps({ + 'cwd': os.getcwd() +})) diff --git a/tests/ansible/regression/all.yml b/tests/ansible/regression/all.yml index 62606b00..32852942 100644 --- a/tests/ansible/regression/all.yml +++ b/tests/ansible/regression/all.yml @@ -9,3 +9,4 @@ - include: issue_177__copy_module_failing.yml - include: issue_332_ansiblemoduleerror_first_occurrence.yml - include: issue_590__sys_modules_crap.yml +- include: issue_591__setuptools_cwd_crash.yml diff --git a/tests/ansible/regression/issue_591__setuptools_cwd_crash.yml b/tests/ansible/regression/issue_591__setuptools_cwd_crash.yml new file mode 100644 index 00000000..cbd65193 --- /dev/null +++ b/tests/ansible/regression/issue_591__setuptools_cwd_crash.yml @@ -0,0 +1,20 @@ +# #591: process CWD is not reset before start of module execution. This is +# usually fine, except for modules importing setuptools early, which attempts +# to call getcwd() before AnsibleModule has had a chance to clean up the +# process environment. + +- hosts: test-targets + tasks: + - meta: end_play + when: not is_mitogen + + - custom_python_run_script: + script: | + import os + os.chdir(module.tmpdir) + + # Will crash if process has a nonexistent CWD. + - custom_python_os_getcwd: + script: | + import os + self._connection.get_chain().call(os.getcwd)