Skip to content

Commit 9a5ed20

Browse files
authored
AAP-37989 Tests for exclude list with multiple jobs (ansible#15722)
* Tests for exclude list with multiple jobs
1 parent 2657ea8 commit 9a5ed20

File tree

3 files changed

+89
-19
lines changed

3 files changed

+89
-19
lines changed

awx/main/tests/conftest.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,16 @@ def event_qs(self):
216216

217217
@pytest.fixture
218218
def mock_me():
219+
"Allows Instance.objects.me() to work without touching the database"
219220
me_mock = mock.MagicMock(return_value=Instance(id=1, hostname=settings.CLUSTER_HOST_ID, uuid='00000000-0000-0000-0000-000000000000'))
220221
with mock.patch.object(Instance.objects, 'me', me_mock):
221222
yield
223+
224+
225+
@pytest.fixture
226+
def me_inst():
227+
"Inserts an instance to the database for Instance.objects.me(), and goes ahead and mocks it in"
228+
inst = Instance.objects.create(hostname='local_node', uuid='00000000-0000-0000-0000-000000000000')
229+
me_mock = mock.MagicMock(return_value=inst)
230+
with mock.patch.object(Instance.objects, 'me', me_mock):
231+
yield inst

awx/main/tests/functional/test_tasks.py

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import pytest
2-
from unittest import mock
32
import os
43
import tempfile
54
import shutil
@@ -27,16 +26,24 @@ def test_no_worker_info_on_AWX_nodes(node_type):
2726

2827

2928
@pytest.fixture
30-
def mock_job_folder(request):
31-
pdd_path = tempfile.mkdtemp(prefix='awx_123_')
29+
def job_folder_factory(request):
30+
def _rf(job_id='1234'):
31+
pdd_path = tempfile.mkdtemp(prefix=f'awx_{job_id}_')
3232

33-
def test_folder_cleanup():
34-
if os.path.exists(pdd_path):
35-
shutil.rmtree(pdd_path)
33+
def test_folder_cleanup():
34+
if os.path.exists(pdd_path):
35+
shutil.rmtree(pdd_path)
3636

37-
request.addfinalizer(test_folder_cleanup)
37+
request.addfinalizer(test_folder_cleanup)
3838

39-
return pdd_path
39+
return pdd_path
40+
41+
return _rf
42+
43+
44+
@pytest.fixture
45+
def mock_job_folder(job_folder_factory):
46+
return job_folder_factory()
4047

4148

4249
@pytest.mark.django_db
@@ -49,17 +56,31 @@ def test_folder_cleanup_stale_file(mock_job_folder, mock_me):
4956

5057

5158
@pytest.mark.django_db
52-
def test_folder_cleanup_running_job(mock_job_folder, mock_me):
53-
me_inst = Instance.objects.create(hostname='local_node', uuid='00000000-0000-0000-0000-000000000000')
54-
with mock.patch.object(Instance.objects, 'me', return_value=me_inst):
55-
job = Job.objects.create(id=123, controller_node=me_inst.hostname, status='running')
56-
_cleanup_images_and_files(grace_period=0)
57-
assert os.path.exists(mock_job_folder) # running job should prevent folder from getting deleted
58-
59-
job.status = 'failed'
60-
job.save(update_fields=['status'])
61-
_cleanup_images_and_files(grace_period=0)
62-
assert not os.path.exists(mock_job_folder) # job is finished and no grace period, should delete
59+
def test_folder_cleanup_running_job(mock_job_folder, me_inst):
60+
job = Job.objects.create(id=1234, controller_node=me_inst.hostname, status='running')
61+
_cleanup_images_and_files(grace_period=0)
62+
assert os.path.exists(mock_job_folder) # running job should prevent folder from getting deleted
63+
64+
job.status = 'failed'
65+
job.save(update_fields=['status'])
66+
_cleanup_images_and_files(grace_period=0)
67+
assert not os.path.exists(mock_job_folder) # job is finished and no grace period, should delete
68+
69+
70+
@pytest.mark.django_db
71+
def test_folder_cleanup_multiple_running_jobs(job_folder_factory, me_inst):
72+
jobs = []
73+
dirs = []
74+
num_jobs = 3
75+
76+
for i in range(num_jobs):
77+
job = Job.objects.create(controller_node=me_inst.hostname, status='running')
78+
dirs.append(job_folder_factory(job.id))
79+
jobs.append(job)
80+
81+
_cleanup_images_and_files(grace_period=0)
82+
83+
assert [os.path.exists(d) for d in dirs] == [True for i in range(num_jobs)]
6384

6485

6586
@pytest.mark.django_db
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import os
2+
import tempfile
3+
import subprocess
4+
5+
from awx.main.tasks.receptor import _convert_args_to_cli
6+
from awx.main.models import Instance, JobTemplate
7+
8+
9+
def test_folder_cleanup_multiple_running_jobs_execution_node(request):
10+
demo_jt = JobTemplate.objects.get(name='Demo Job Template')
11+
12+
jobs = [demo_jt.create_unified_job(_eager_fields={'status': 'running'}) for i in range(3)]
13+
14+
def delete_jobs():
15+
for job in jobs:
16+
job.delete()
17+
18+
request.addfinalizer(delete_jobs)
19+
20+
job_dirs = []
21+
job_patterns = []
22+
for job in jobs:
23+
job_pattern = f'awx_{job.id}_1234'
24+
job_dir = os.path.join(tempfile.gettempdir(), job_pattern)
25+
job_patterns.append(job_pattern)
26+
job_dirs.append(job_dir)
27+
os.mkdir(job_dir)
28+
29+
inst = Instance.objects.me()
30+
runner_cleanup_kwargs = inst.get_cleanup_task_kwargs(exclude_strings=job_patterns, grace_period=0)
31+
32+
# We can not call worker_cleanup directly because execution and control nodes are not fungible
33+
args = _convert_args_to_cli(runner_cleanup_kwargs)
34+
remote_command = ' '.join(args)
35+
36+
subprocess.call('ansible-runner worker ' + remote_command, shell=True)
37+
print('ansible-runner worker ' + remote_command)
38+
39+
assert [os.path.exists(job_dir) for job_dir in job_dirs] == [True for i in range(3)]

0 commit comments

Comments
 (0)