Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion awx/api/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down
29 changes: 28 additions & 1 deletion awx/main/tests/functional/api/test_workflow_job.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest


from awx.main.models import Inventory
from awx.api.versioning import reverse


Expand Down Expand Up @@ -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",
Expand Down