fix: awxkit controller_dir support for containerized installs (#16647)

The controller_dir property hardcoded /tmp/awx_{id} as the expected
volume mount prefix. On containerized installs the job execution
directory is at /home/ansible/aap/controller/data/job_execution/awx_{id},
causing a RuntimeError when the prefix didn't match.

Changed to exact path component matching on the awx_{id} segment,
which works for both traditional and containerized path layouts
while preventing false matches (e.g. awx_1 matching awx_10).

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adrià Sala
2026-09-09 14:48:00 +00:00
committed by GitHub
co-authored by Claude Opus 4.6
parent 06c07edc6f
commit 94333d005e
2 changed files with 77 additions and 3 deletions
+6 -3
View File
@@ -139,15 +139,18 @@ class UnifiedJob(HasStatus, base.Base):
"""
self.get()
job_args = self.job_args
expected_prefix = '/tmp/awx_{}'.format(self.id)
expected_segment = 'awx_{}'.format(self.id)
for arg1, arg2 in zip(job_args[:-1], job_args[1:]):
if arg1 == '-v':
if ':' in arg2:
host_loc = arg2.split(':')[0]
if host_loc.startswith(expected_prefix):
parts = host_loc.rstrip('/').split('/')
if any(p == expected_segment or p.startswith(expected_segment + '_') for p in parts):
return host_loc
raise RuntimeError(
'Could not find a controller private_data_dir for this job. Searched for volume mount to {} inside of args {}'.format(expected_prefix, job_args)
'Could not find a controller private_data_dir for this job. Searched for volume mount matching {} inside of args {}'.format(
expected_segment, job_args
)
)
+71
View File
@@ -0,0 +1,71 @@
from unittest import mock
import pytest
from awxkit.api.pages.unified_jobs import UnifiedJob
def _make_job(job_id, job_args):
"""Create a minimal UnifiedJob mock with the given id and job_args."""
job = mock.MagicMock(spec=UnifiedJob)
job.id = job_id
job.get = mock.MagicMock()
type(job).job_args = mock.PropertyMock(return_value=job_args)
type(job).controller_dir = UnifiedJob.controller_dir
return job
class TestControllerDir:
def test_traditional_path(self):
job = _make_job(4387, ['podman', 'run', '-v', '/tmp/awx_4387_qv4aqn_8/:/runner/:Z', '--name', 'test'])
assert job.controller_dir == '/tmp/awx_4387_qv4aqn_8/'
def test_containerized_path(self):
job = _make_job(
4387,
[
'podman',
'run',
'-v',
'/home/ansible/aap/controller/data/job_execution/awx_4387_qv4aqn_8/:/runner/:Z',
'--name',
'test',
],
)
assert job.controller_dir == '/home/ansible/aap/controller/data/job_execution/awx_4387_qv4aqn_8/'
def test_no_false_match_on_similar_id(self):
job = _make_job(1, ['podman', 'run', '-v', '/tmp/awx_10_abc/:/runner/:Z', '--name', 'test'])
with pytest.raises(RuntimeError, match='Could not find a controller private_data_dir'):
_ = job.controller_dir
def test_exact_segment_match(self):
job = _make_job(1, ['podman', 'run', '-v', '/tmp/awx_1/:/runner/:Z', '--name', 'test'])
assert job.controller_dir == '/tmp/awx_1/'
def test_segment_with_suffix(self):
job = _make_job(1, ['podman', 'run', '-v', '/tmp/awx_1_abc/:/runner/:Z', '--name', 'test'])
assert job.controller_dir == '/tmp/awx_1_abc/'
def test_no_volume_mounts_raises(self):
job = _make_job(99, ['podman', 'run', '--name', 'test'])
with pytest.raises(RuntimeError, match='Could not find a controller private_data_dir'):
_ = job.controller_dir
def test_multiple_volumes_picks_correct(self):
job = _make_job(
42,
[
'podman',
'run',
'-v',
'/etc/pki:/etc/pki:O',
'-v',
'/home/ansible/aap/controller/data/job_execution/awx_42_xyz/:/runner/:Z',
'-v',
'/usr/share/pki:/usr/share/pki:O',
'--name',
'test',
],
)
assert job.controller_dir == '/home/ansible/aap/controller/data/job_execution/awx_42_xyz/'