From 4371e52933907f86dd2a033d6d24654a9c7f0abe Mon Sep 17 00:00:00 2001 From: Jimmy Conner Date: Mon, 15 Jun 2026 13:00:11 -0500 Subject: [PATCH 1/2] Fix relaunching a sliced job at the Workflow level This was working before, but recent changes seemed to have broken it --- awx/api/views/__init__.py | 4 ++- .../tests/functional/api/test_workflow_job.py | 29 ++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index 846e7a11b..05515af58 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -3223,7 +3223,9 @@ def post(self, request, *args, **kwargs): jt = obj.job_template if not jt: raise ParseError(_('Cannot relaunch slice workflow job orphaned from job template.')) - elif not obj.inventory or min(obj.inventory.hosts.count(), jt.job_slice_count) != obj.workflow_nodes.count(): + elif getattr(obj.inventory, 'kind', None) != 'federated' and ( + not obj.inventory or min(obj.inventory.hosts.count(), jt.job_slice_count) != obj.workflow_nodes.count() + ): raise ParseError(_('Cannot relaunch sliced workflow job after slice count has changed.')) if from_failed: if not obj.workflow_nodes.filter(job__status__in=['failed', 'error', 'canceled']).exists(): diff --git a/awx/main/tests/functional/api/test_workflow_job.py b/awx/main/tests/functional/api/test_workflow_job.py index 0a88582b4..be1ceeb02 100644 --- a/awx/main/tests/functional/api/test_workflow_job.py +++ b/awx/main/tests/functional/api/test_workflow_job.py @@ -1,6 +1,6 @@ import pytest - +from awx.main.models import Inventory, WorkflowJobNode from awx.api.versioning import reverse @@ -38,6 +38,33 @@ def test_workflow_job_relaunch_not_inventory_failure(workflow_job, post, admin_u post(url, user=admin_user, expect=400) +@pytest.mark.django_db +def test_workflow_job_relaunch_federated_inventory(organization, job_template, post, admin_user): + """Relaunching a sliced workflow spawned from a federated inventory must not + be blocked by the stale-slice-count check (federated inventories have no + direct hosts, so hosts.count() is always 0).""" + fed_inv = Inventory.objects.create(name='fed-inv', kind='federated', organization=organization) + inv_a = Inventory.objects.create(name='inv-a', organization=organization) + inv_b = Inventory.objects.create(name='inv-b', organization=organization) + inv_a.hosts.create(name='host-a') + inv_b.hosts.create(name='host-b') + fed_inv.input_inventories.add(inv_a) + fed_inv.input_inventories.add(inv_b) + + job_template.inventory = fed_inv + job_template.organization = organization + job_template.save() + + wfj = job_template.create_unified_job() + wfj.status = 'successful' + wfj.save() + assert wfj.is_sliced_job + assert wfj.workflow_nodes.count() == 2 + + url = reverse("api:workflow_job_relaunch", kwargs={'pk': wfj.pk}) + post(url, user=admin_user, expect=201) + + @pytest.mark.django_db @pytest.mark.parametrize( "is_admin, status", From cd452ab2f548f47ea9b7fb63bd964e5849c8cd36 Mon Sep 17 00:00:00 2001 From: Jimmy Conner Date: Mon, 15 Jun 2026 13:10:44 -0500 Subject: [PATCH 2/2] Remove unused import --- awx/main/tests/functional/api/test_workflow_job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/main/tests/functional/api/test_workflow_job.py b/awx/main/tests/functional/api/test_workflow_job.py index be1ceeb02..6080cb359 100644 --- a/awx/main/tests/functional/api/test_workflow_job.py +++ b/awx/main/tests/functional/api/test_workflow_job.py @@ -1,6 +1,6 @@ import pytest -from awx.main.models import Inventory, WorkflowJobNode +from awx.main.models import Inventory from awx.api.versioning import reverse