From 0de369b42f6e5a1d47f64dd442cd9cb1969af884 Mon Sep 17 00:00:00 2001 From: Yunfan Zhang Date: Fri, 8 Jun 2018 09:31:38 -0400 Subject: [PATCH] Fix job id incorrectly cast to string in ActiveJobConflict. --- awx/api/exceptions.py | 8 ++++++-- awx/main/models/mixins.py | 4 ++-- awx/main/tests/functional/api/test_instance_group.py | 4 ++-- awx/main/tests/functional/api/test_organizations.py | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/awx/api/exceptions.py b/awx/api/exceptions.py index 0c67be279b..7c7a182d06 100644 --- a/awx/api/exceptions.py +++ b/awx/api/exceptions.py @@ -12,7 +12,11 @@ class ActiveJobConflict(ValidationError): status_code = 409 def __init__(self, active_jobs): - super(ActiveJobConflict, self).__init__({ + # During APIException.__init__(), Django Rest Framework + # turn everything in self.detail into string by using force_text. + # Declare detail afterwards circumvent this behavior. + super(ActiveJobConflict, self).__init__() + self.detail = { "error": _("Resource is being used by running jobs."), "active_jobs": active_jobs - }) + } diff --git a/awx/main/models/mixins.py b/awx/main/models/mixins.py index 2314b295ae..7dcb560aa2 100644 --- a/awx/main/models/mixins.py +++ b/awx/main/models/mixins.py @@ -466,7 +466,7 @@ class RelatedJobsMixin(object): return self._get_related_jobs().filter(status__in=ACTIVE_STATES) ''' - Returns [{'id': '1', 'type': 'job'}, {'id': 2, 'type': 'project_update'}, ...] + Returns [{'id': 1, 'type': 'job'}, {'id': 2, 'type': 'project_update'}, ...] ''' def get_active_jobs(self): UnifiedJob = apps.get_model('main', 'UnifiedJob') @@ -475,5 +475,5 @@ class RelatedJobsMixin(object): if not isinstance(jobs, QuerySet): raise RuntimeError("Programmer error. Expected _get_active_jobs() to return a QuerySet.") - return [dict(id=str(t[0]), type=mapping[t[1]]) for t in jobs.values_list('id', 'polymorphic_ctype_id')] + return [dict(id=t[0], type=mapping[t[1]]) for t in jobs.values_list('id', 'polymorphic_ctype_id')] diff --git a/awx/main/tests/functional/api/test_instance_group.py b/awx/main/tests/functional/api/test_instance_group.py index cd78d0de33..bac1c9a806 100644 --- a/awx/main/tests/functional/api/test_instance_group.py +++ b/awx/main/tests/functional/api/test_instance_group.py @@ -73,12 +73,12 @@ def test_delete_instance_group_jobs(delete, instance_group_jobs_successful, inst @pytest.mark.django_db def test_delete_instance_group_jobs_running(delete, instance_group_jobs_running, instance_group_jobs_successful, instance_group, admin): def sort_keys(x): - return (x['type'], x['id']) + return (x['type'], str(x['id'])) url = reverse("api:instance_group_detail", kwargs={'pk': instance_group.pk}) response = delete(url, None, admin, expect=409) - expect_transformed = [dict(id=str(j.id), type=j.model_to_str()) for j in instance_group_jobs_running] + expect_transformed = [dict(id=j.id, type=j.model_to_str()) for j in instance_group_jobs_running] response_sorted = sorted(response.data['active_jobs'], key=sort_keys) expect_sorted = sorted(expect_transformed, key=sort_keys) diff --git a/awx/main/tests/functional/api/test_organizations.py b/awx/main/tests/functional/api/test_organizations.py index 43a9ffb1e5..5e4793b6a5 100644 --- a/awx/main/tests/functional/api/test_organizations.py +++ b/awx/main/tests/functional/api/test_organizations.py @@ -260,12 +260,12 @@ def test_organization_delete(delete, admin, organization, organization_jobs_succ @pytest.mark.django_db def test_organization_delete_with_active_jobs(delete, admin, organization, organization_jobs_running): def sort_keys(x): - return (x['type'], x['id']) + return (x['type'], str(x['id'])) url = reverse('api:organization_detail', kwargs={'pk': organization.id}) resp = delete(url, None, user=admin, expect=409) - expect_transformed = [dict(id=str(j.id), type=j.model_to_str()) for j in organization_jobs_running] + expect_transformed = [dict(id=j.id, type=j.model_to_str()) for j in organization_jobs_running] resp_sorted = sorted(resp.data['active_jobs'], key=sort_keys) expect_sorted = sorted(expect_transformed, key=sort_keys)