diff --git a/src/ansible_runner/config/runner.py b/src/ansible_runner/config/runner.py index 70379ef3..26be235e 100644 --- a/src/ansible_runner/config/runner.py +++ b/src/ansible_runner/config/runner.py @@ -158,14 +158,20 @@ def prepare(self): def prepare_inventory(self): """ Prepares the inventory default under ``private_data_dir`` if it's not overridden by the constructor. + + We make sure that if inventory is a path, that it is an absolute path. """ if self.containerized: self.inventory = '/runner/inventory' return if self.inventory is None: + # At this point we expect self.private_data_dir to be an absolute path + # since that is expanded in the base class. if os.path.exists(os.path.join(self.private_data_dir, "inventory")): self.inventory = os.path.join(self.private_data_dir, "inventory") + elif isinstance(self.inventory, str) and os.path.exists(self.inventory): + self.inventory = os.path.abspath(self.inventory) def prepare_env(self): """ diff --git a/test/integration/test_interface.py b/test/integration/test_interface.py index 4e17503e..457ea719 100644 --- a/test/integration/test_interface.py +++ b/test/integration/test_interface.py @@ -559,3 +559,51 @@ def test_get_role_argspec_within_container(project_fixtures, runtime, skipif_pre assert isinstance(resp, dict) assert 'Into_The_Mystic' in resp assert resp['Into_The_Mystic']['entry_points'] == expected_epoint + + +class TestRelativePvtDataDirPaths: + """ + Class to handle test setup/teardown of tests that need to change working + directory to test relative paths. + """ + + def setup_method(self): + self._old_workdir = os.getcwd() # pylint: disable=W0201 + + def teardown_method(self): + os.chdir(self._old_workdir) + + def test_inventory_as_string(self, project_fixtures): + """ + Test of bug fix for GH issue #1216: https://github.com/ansible/ansible-runner/issues/1216 + + A relative private data directory combined with an inventory specified as a string + would produce an invalid inventory path being passed along to ansible. + """ + os.chdir(str(project_fixtures)) + + inventory = 'hostA ansible_connection=local ansible_python_interpreter="{{ ansible_playbook_python }}"' + + r = run(private_data_dir='debug', + inventory=inventory, + playbook='debug.yml') + + with r.stdout as output: + text = output.read() + + assert r.status == 'successful' + assert "No inventory was parsed" not in text + + def test_default_inventory(self, project_fixtures): + """ + Test relative pvt data dir with the default inventory. + """ + os.chdir(str(project_fixtures)) + + r = run(private_data_dir='debug', playbook='debug.yml') + + with r.stdout as output: + text = output.read() + + assert r.status == 'successful' + assert "No inventory was parsed" not in text diff --git a/test/unit/config/test_runner.py b/test/unit/config/test_runner.py index 397fd9a5..8929139e 100644 --- a/test/unit/config/test_runner.py +++ b/test/unit/config/test_runner.py @@ -249,13 +249,16 @@ def test_prepare_inventory(mocker): rc = RunnerConfig(private_data_dir='/') rc.prepare_inventory() assert rc.inventory == '/inventory' + rc.inventory = '/tmp/inventory' rc.prepare_inventory() assert rc.inventory == '/tmp/inventory' + + path_exists.return_value = False rc.inventory = 'localhost,anotherhost,' rc.prepare_inventory() assert rc.inventory == 'localhost,anotherhost,' - path_exists.return_value = False + rc.inventory = None rc.prepare_inventory() assert rc.inventory is None