mirror of
https://github.com/ansible/awx.git
synced 2026-02-15 10:10:01 -03:30
Merge pull request #5705 from chrismeyersfsu/fix-5700
add job cancel dependency information
This commit is contained in:
@@ -1277,10 +1277,20 @@ class InventoryUpdate(UnifiedJob, InventorySourceOptions, JobNotificationMixin):
|
|||||||
def get_notification_friendly_name(self):
|
def get_notification_friendly_name(self):
|
||||||
return "Inventory Update"
|
return "Inventory Update"
|
||||||
|
|
||||||
def cancel(self):
|
def _build_job_explanation(self):
|
||||||
res = super(InventoryUpdate, self).cancel()
|
if not self.job_explanation:
|
||||||
|
return 'Previous Task Canceled: {"job_type": "%s", "job_name": "%s", "job_id": "%s"}' % \
|
||||||
|
(self.model_to_str(), self.name, self.id)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_dependent_jobs(self):
|
||||||
|
return Job.objects.filter(dependent_jobs__in=[self.id])
|
||||||
|
|
||||||
|
def cancel(self, job_explanation=None):
|
||||||
|
|
||||||
|
res = super(InventoryUpdate, self).cancel(job_explanation=job_explanation)
|
||||||
if res:
|
if res:
|
||||||
map(lambda x: x.cancel(), Job.objects.filter(dependent_jobs__in=[self.id]))
|
map(lambda x: x.cancel(job_explanation=self._build_job_explanation()), self.get_dependent_jobs())
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -633,10 +633,10 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin):
|
|||||||
Canceling a job also cancels the implicit project update with launch_type
|
Canceling a job also cancels the implicit project update with launch_type
|
||||||
run.
|
run.
|
||||||
'''
|
'''
|
||||||
def cancel(self):
|
def cancel(self, job_explanation=None):
|
||||||
res = super(Job, self).cancel()
|
res = super(Job, self).cancel(job_explanation=job_explanation)
|
||||||
if self.project_update:
|
if self.project_update:
|
||||||
self.project_update.cancel()
|
self.project_update.cancel(job_explanation=job_explanation)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1025,7 +1025,7 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
|
|||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self, job_explanation=None):
|
||||||
if self.can_cancel:
|
if self.can_cancel:
|
||||||
if not self.cancel_flag:
|
if not self.cancel_flag:
|
||||||
self.cancel_flag = True
|
self.cancel_flag = True
|
||||||
@@ -1033,6 +1033,9 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
|
|||||||
if self.status in ('pending', 'waiting', 'new'):
|
if self.status in ('pending', 'waiting', 'new'):
|
||||||
self.status = 'canceled'
|
self.status = 'canceled'
|
||||||
cancel_fields.append('status')
|
cancel_fields.append('status')
|
||||||
|
if job_explanation is not None:
|
||||||
|
self.job_explanation = job_explanation
|
||||||
|
cancel_fields.append('job_explanation')
|
||||||
self.save(update_fields=cancel_fields)
|
self.save(update_fields=cancel_fields)
|
||||||
self.websocket_emit_status("canceled")
|
self.websocket_emit_status("canceled")
|
||||||
if settings.BROKER_URL.startswith('amqp://'):
|
if settings.BROKER_URL.startswith('amqp://'):
|
||||||
|
|||||||
0
awx/main/tests/unit/models/__init__.py
Normal file
0
awx/main/tests/unit/models/__init__.py
Normal file
38
awx/main/tests/unit/models/test_inventory.py
Normal file
38
awx/main/tests/unit/models/test_inventory.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import pytest
|
||||||
|
import mock
|
||||||
|
from awx.main.models import (
|
||||||
|
UnifiedJob,
|
||||||
|
InventoryUpdate,
|
||||||
|
Job,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def dependent_job(mocker):
|
||||||
|
j = Job(id=3, name='I_am_a_job')
|
||||||
|
j.cancel = mocker.MagicMock(return_value=True)
|
||||||
|
return [j]
|
||||||
|
|
||||||
|
|
||||||
|
def test_cancel(mocker, dependent_job):
|
||||||
|
with mock.patch.object(UnifiedJob, 'cancel', return_value=True) as parent_cancel:
|
||||||
|
iu = InventoryUpdate()
|
||||||
|
|
||||||
|
iu.get_dependent_jobs = mocker.MagicMock(return_value=dependent_job)
|
||||||
|
iu.save = mocker.MagicMock()
|
||||||
|
build_job_explanation_mock = mocker.MagicMock()
|
||||||
|
iu._build_job_explanation = mocker.MagicMock(return_value=build_job_explanation_mock)
|
||||||
|
|
||||||
|
iu.cancel()
|
||||||
|
|
||||||
|
parent_cancel.assert_called_with(job_explanation=None)
|
||||||
|
dependent_job[0].cancel.assert_called_with(job_explanation=build_job_explanation_mock)
|
||||||
|
|
||||||
|
|
||||||
|
def test__build_job_explanation():
|
||||||
|
iu = InventoryUpdate(id=3, name='I_am_an_Inventory_Update')
|
||||||
|
|
||||||
|
job_explanation = iu._build_job_explanation()
|
||||||
|
|
||||||
|
assert job_explanation == 'Previous Task Canceled: {"job_type": "%s", "job_name": "%s", "job_id": "%s"}' % \
|
||||||
|
('inventory_update', 'I_am_an_Inventory_Update', 3)
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import pytest
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from awx.main.models import (
|
from awx.main.models import (
|
||||||
@@ -14,3 +15,38 @@ def test_unified_job_workflow_attributes():
|
|||||||
|
|
||||||
assert job.spawned_by_workflow is True
|
assert job.spawned_by_workflow is True
|
||||||
assert job.workflow_job_id == 1
|
assert job.workflow_job_id == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def unified_job(mocker):
|
||||||
|
mocker.patch.object(UnifiedJob, 'can_cancel', return_value=True)
|
||||||
|
j = UnifiedJob()
|
||||||
|
j.status = 'pending'
|
||||||
|
j.cancel_flag = None
|
||||||
|
j.save = mocker.MagicMock()
|
||||||
|
j.websocket_emit_status = mocker.MagicMock()
|
||||||
|
return j
|
||||||
|
|
||||||
|
|
||||||
|
def test_cancel(unified_job):
|
||||||
|
|
||||||
|
unified_job.cancel()
|
||||||
|
|
||||||
|
assert unified_job.cancel_flag is True
|
||||||
|
assert unified_job.status == 'canceled'
|
||||||
|
assert unified_job.job_explanation == ''
|
||||||
|
# Note: the websocket emit status check is just reflecting the state of the current code.
|
||||||
|
# Some more thought may want to go into only emitting canceled if/when the job record
|
||||||
|
# status is changed to canceled. Unlike, currently, where it's emitted unconditionally.
|
||||||
|
unified_job.websocket_emit_status.assert_called_with("canceled")
|
||||||
|
unified_job.save.assert_called_with(update_fields=['cancel_flag', 'status'])
|
||||||
|
|
||||||
|
|
||||||
|
def test_cancel_job_explanation(unified_job):
|
||||||
|
job_explanation = 'giggity giggity'
|
||||||
|
|
||||||
|
unified_job.cancel(job_explanation=job_explanation)
|
||||||
|
|
||||||
|
assert unified_job.job_explanation == job_explanation
|
||||||
|
unified_job.save.assert_called_with(update_fields=['cancel_flag', 'status', 'job_explanation'])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user