summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--awx/main/models/ha.py11
-rw-r--r--awx/main/tests/functional/test_instances.py20
-rw-r--r--awx/ui/src/screens/Job/JobOutput/HostEventModal.js14
-rw-r--r--awx/ui/src/screens/Job/JobOutput/HostEventModal.test.js48
4 files changed, 78 insertions, 15 deletions
diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py
index dbeb81dcac..f101a94d7a 100644
--- a/awx/main/models/ha.py
+++ b/awx/main/models/ha.py
@@ -233,11 +233,12 @@ class Instance(HasPolicyEditsMixin, BaseModel):
if not isinstance(vargs.get('grace_period'), int):
vargs['grace_period'] = 60 # grace period of 60 minutes, need to set because CLI default will not take effect
if 'exclude_strings' not in vargs and vargs.get('file_pattern'):
- active_pks = list(
- UnifiedJob.objects.filter(
- (models.Q(execution_node=self.hostname) | models.Q(controller_node=self.hostname)) & models.Q(status__in=('running', 'waiting'))
- ).values_list('pk', flat=True)
- )
+ active_job_qs = UnifiedJob.objects.filter(status__in=('running', 'waiting'))
+ if self.node_type == 'execution':
+ active_job_qs = active_job_qs.filter(execution_node=self.hostname)
+ else:
+ active_job_qs = active_job_qs.filter(controller_node=self.hostname)
+ active_pks = list(active_job_qs.values_list('pk', flat=True))
if active_pks:
vargs['exclude_strings'] = [JOB_FOLDER_PREFIX % job_id for job_id in active_pks]
if 'remove_images' in vargs or 'image_prune' in vargs:
diff --git a/awx/main/tests/functional/test_instances.py b/awx/main/tests/functional/test_instances.py
index 8ce6524d38..df6d177868 100644
--- a/awx/main/tests/functional/test_instances.py
+++ b/awx/main/tests/functional/test_instances.py
@@ -1,7 +1,7 @@
import pytest
from unittest import mock
-from awx.main.models import AdHocCommand, InventoryUpdate, JobTemplate
+from awx.main.models import AdHocCommand, InventoryUpdate, JobTemplate, Job
from awx.main.models.activity_stream import ActivityStream
from awx.main.models.ha import Instance, InstanceGroup
from awx.main.tasks.system import apply_cluster_membership_policies
@@ -16,6 +16,24 @@ def test_default_tower_instance_group(default_instance_group, job_factory):
@pytest.mark.django_db
+@pytest.mark.parametrize('node_type', ('execution', 'control'))
+@pytest.mark.parametrize('active', (True, False))
+def test_get_cleanup_task_kwargs_active_jobs(node_type, active):
+ instance = Instance.objects.create(hostname='foobar', node_type=node_type)
+ job_kwargs = dict()
+ job_kwargs['controller_node' if node_type == 'control' else 'execution_node'] = instance.hostname
+ job_kwargs['status'] = 'running' if active else 'successful'
+
+ job = Job.objects.create(**job_kwargs)
+ kwargs = instance.get_cleanup_task_kwargs()
+
+ if active:
+ assert kwargs['exclude_strings'] == [f'awx_{job.pk}_']
+ else:
+ assert 'exclude_strings' not in kwargs
+
+
+@pytest.mark.django_db
class TestPolicyTaskScheduling:
"""Tests make assertions about when the policy task gets scheduled"""
diff --git a/awx/ui/src/screens/Job/JobOutput/HostEventModal.js b/awx/ui/src/screens/Job/JobOutput/HostEventModal.js
index 57fe7ce05f..a7295c1692 100644
--- a/awx/ui/src/screens/Job/JobOutput/HostEventModal.js
+++ b/awx/ui/src/screens/Job/JobOutput/HostEventModal.js
@@ -70,7 +70,6 @@ const getStdOutValue = (hostEvent) => {
function HostEventModal({ onClose, hostEvent = {}, isOpen = false }) {
const [hostStatus, setHostStatus] = useState(null);
const [activeTabKey, setActiveTabKey] = useState(0);
-
useEffect(() => {
setHostStatus(processEventStatus(hostEvent));
}, [setHostStatus, hostEvent]);
@@ -108,11 +107,11 @@ function HostEventModal({ onClose, hostEvent = {}, isOpen = false }) {
style={{ alignItems: 'center', marginTop: '20px' }}
gutter="sm"
>
- <Detail label={t`Host`} value={hostEvent.host_name} />
- {hostEvent.summary_fields.host?.description ? (
+ <Detail label={t`Host`} value={hostEvent.event_data?.host} />
+ {hostEvent.summary_fields?.host?.description ? (
<Detail
label={t`Description`}
- value={hostEvent.summary_fields.host.description}
+ value={hostEvent.summary_fields?.host?.description}
/>
) : null}
{hostStatus ? (
@@ -125,12 +124,9 @@ function HostEventModal({ onClose, hostEvent = {}, isOpen = false }) {
<Detail label={t`Task`} value={hostEvent.task} />
<Detail
label={t`Module`}
- value={hostEvent.event_data.task_action || t`No result found`}
- />
- <Detail
- label={t`Command`}
- value={hostEvent?.event_data?.res?.cmd}
+ value={hostEvent.event_data?.task_action || t`No result found`}
/>
+ <Detail label={t`Command`} value={hostEvent.event_data?.res?.cmd} />
</DetailList>
</Tab>
<Tab
diff --git a/awx/ui/src/screens/Job/JobOutput/HostEventModal.test.js b/awx/ui/src/screens/Job/JobOutput/HostEventModal.test.js
index 96866c4b03..0b877b4e4c 100644
--- a/awx/ui/src/screens/Job/JobOutput/HostEventModal.test.js
+++ b/awx/ui/src/screens/Job/JobOutput/HostEventModal.test.js
@@ -52,6 +52,47 @@ const hostEvent = {
},
};
+const partialHostEvent = {
+ changed: true,
+ event: 'runner_on_ok',
+ event_data: {
+ host: 'foo',
+ play: 'all',
+ playbook: 'run_command.yml',
+ res: {
+ ansible_loop_var: 'item',
+ changed: true,
+ item: '1',
+ msg: 'This is a debug message: 1',
+ stdout:
+ ' total used free shared buff/cache available\nMem: 7973 3005 960 30 4007 4582\nSwap: 1023 0 1023',
+ stderr: 'problems',
+ cmd: ['free', '-m'],
+ stderr_lines: [],
+ stdout_lines: [
+ ' total used free shared buff/cache available',
+ 'Mem: 7973 3005 960 30 4007 4582',
+ 'Swap: 1023 0 1023',
+ ],
+ },
+ task: 'command',
+ task_action: 'command',
+ },
+ event_display: 'Host OK',
+ event_level: 3,
+ failed: false,
+ host: 1,
+ id: 123,
+ job: 4,
+ play: 'all',
+ playbook: 'run_command.yml',
+ stdout: `stdout: "changed: [localhost] => {"changed": true, "cmd": ["free", "-m"], "delta": "0:00:01.479609", "end": "2019-09-10 14:21:45.469533", "rc": 0, "start": "2019-09-10 14:21:43.989924", "stderr": "", "stderr_lines": [], "stdout": " total used free shared buff/cache available\nMem: 7973 3005 960 30 4007 4582\nSwap: 1023 0 1023", "stdout_lines": [" total used free shared buff/cache available", "Mem: 7973 3005 960 30 4007 4582", "Swap: 1023 0 1023"]}"
+ `,
+ task: 'command',
+ type: 'job_event',
+ url: '/api/v2/job_events/123/',
+};
+
/*
Some libraries return a list of string in stdout
Example: https://github.com/ansible-collections/cisco.ios/blob/main/plugins/modules/ios_command.py#L124-L128
@@ -134,6 +175,13 @@ describe('HostEventModal', () => {
expect(wrapper).toHaveLength(1);
});
+ test('renders successfully with partial data', () => {
+ const wrapper = shallow(
+ <HostEventModal hostEvent={partialHostEvent} onClose={() => {}} />
+ );
+ expect(wrapper).toHaveLength(1);
+ });
+
test('should render all tabs', () => {
const wrapper = shallow(
<HostEventModal hostEvent={hostEvent} onClose={() => {}} isOpen />