From 97562fc4df0249cebb82fbe90cfd21afdcbdd69f Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Thu, 22 Jun 2017 15:26:31 -0400 Subject: [PATCH] block job template launches when an inventory is being deleted see: #4382 --- awx/api/serializers.py | 3 +++ .../tests/functional/api/test_inventory.py | 22 +++++++++++++++++++ .../tests/functional/api/test_job_template.py | 17 ++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 36e72e51ca..463e9c372a 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -3127,6 +3127,9 @@ class JobLaunchSerializer(BaseSerializer): if not (attrs.get(field, False) and obj._ask_for_vars_dict().get(field, False)): errors[field] = _("Job Template '%s' is missing or undefined.") % field + if obj.inventory and obj.inventory.pending_deletion is True: + errors['inventory'] = _("The inventory associated with this Job Template is being deleted.") + if (not obj.ask_credential_on_launch) or (not attrs.get('credential', None)): credential = obj.credential else: diff --git a/awx/main/tests/functional/api/test_inventory.py b/awx/main/tests/functional/api/test_inventory.py index 8f71544f98..3266c3f27c 100644 --- a/awx/main/tests/functional/api/test_inventory.py +++ b/awx/main/tests/functional/api/test_inventory.py @@ -40,6 +40,28 @@ def test_edit_inventory(put, inventory, alice, role_field, expected_status_code) put(reverse('api:inventory_detail', kwargs={'pk': inventory.id}), data, alice, expect=expected_status_code) +@pytest.mark.django_db +def test_async_inventory_deletion(delete, get, inventory, alice): + inventory.admin_role.members.add(alice) + resp = delete(reverse('api:inventory_detail', kwargs={'pk': inventory.id}), alice) + assert resp.status_code == 202 + + resp = get(reverse('api:inventory_detail', kwargs={'pk': inventory.id}), alice) + assert resp.status_code == 200 + assert resp.data.get('pending_deletion') is True + + +@pytest.mark.django_db +def test_async_inventory_duplicate_deletion_prevention(delete, get, inventory, alice): + inventory.admin_role.members.add(alice) + resp = delete(reverse('api:inventory_detail', kwargs={'pk': inventory.id}), alice) + assert resp.status_code == 202 + + resp = delete(reverse('api:inventory_detail', kwargs={'pk': inventory.id}), alice) + assert resp.status_code == 400 + assert resp.data['error'] == 'Inventory is already being deleted.' + + @pytest.mark.parametrize('order_by', ('script', '-script', 'script,pk', '-script,pk')) @pytest.mark.django_db def test_list_cannot_order_by_unsearchable_field(get, organization, alice, order_by): diff --git a/awx/main/tests/functional/api/test_job_template.py b/awx/main/tests/functional/api/test_job_template.py index f18354625a..61892ffa82 100644 --- a/awx/main/tests/functional/api/test_job_template.py +++ b/awx/main/tests/functional/api/test_job_template.py @@ -472,6 +472,23 @@ def test_scan_jt_surveys(inventory): assert "survey_enabled" in serializer.errors +@pytest.mark.django_db +def test_launch_with_pending_deletion_inventory(get, post, organization_factory, + job_template_factory, machine_credential, + credential, net_credential): + objs = organization_factory("org", superusers=['admin']) + jt = job_template_factory("jt", organization=objs.organization, credential='c', + inventory='test_inv', project='test_proj').job_template + jt.inventory.pending_deletion = True + jt.inventory.save() + + resp = post( + reverse('api:job_template_launch', kwargs={'pk': jt.pk}), + objs.superusers.admin, expect=400 + ) + assert resp.data['inventory'] == ['The inventory associated with this Job Template is being deleted.'] + + @pytest.mark.django_db def test_launch_with_extra_credentials(get, post, organization_factory, job_template_factory, machine_credential,