From f594f62dfcb8c1fb5c59b9577a820b509041f511 Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Fri, 16 Mar 2018 08:27:01 -0400 Subject: [PATCH 1/4] Project needs to expose all of its ProjectUpdate jobs in an active state --- awx/main/models/projects.py | 14 +++++++++++--- awx/main/tests/functional/test_projects.py | 7 +++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py index 8c7ee0db35..32796df32a 100644 --- a/awx/main/models/projects.py +++ b/awx/main/models/projects.py @@ -447,6 +447,14 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn def get_absolute_url(self, request=None): return reverse('api:project_detail', kwargs={'pk': self.pk}, request=request) + def get_active_jobs(self): + for project_update in self.project_updates.all(): + active_jobs = project_update.get_active_jobs() + if active_jobs is None: + continue + return active_jobs + return [] + class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManagerProjectUpdateMixin, RelatedJobsMixin): ''' @@ -568,10 +576,10 @@ class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManage ''' def _get_active_jobs(self): return UnifiedJob.objects.non_polymorphic().filter( - Q(status__in=ACTIVE_STATES) & + models.Q(status__in=ACTIVE_STATES) & ( - Q(Job___project=self) | - Q(ProjectUpdate___project=self) + models.Q(Job___project=self) | + models.Q(ProjectUpdate___project=self) ) ) diff --git a/awx/main/tests/functional/test_projects.py b/awx/main/tests/functional/test_projects.py index 31792683d9..a6cef20f6f 100644 --- a/awx/main/tests/functional/test_projects.py +++ b/awx/main/tests/functional/test_projects.py @@ -251,3 +251,10 @@ def test_project_unique_together_with_org(organization): proj2.validate_unique() proj2 = Project(name='foo', organization=None) proj2.validate_unique() + + +@pytest.mark.django_db +def test_project_delete(delete, organization, admin): + proj = Project(name='foo', organization=organization) + proj.save() + delete(reverse('api:project_detail', kwargs={'pk':proj.id,}), admin) From c54d9a9445f0984fe456d69a589ad62120923832 Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Fri, 16 Mar 2018 09:24:46 -0400 Subject: [PATCH 2/4] Fix query using self -> self.project and fix imports --- awx/main/models/projects.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py index 32796df32a..1d51c53641 100644 --- a/awx/main/models/projects.py +++ b/awx/main/models/projects.py @@ -25,7 +25,11 @@ from awx.main.models.notifications import ( NotificationTemplate, JobNotificationMixin, ) -from awx.main.models.unified_jobs import * # noqa +from awx.main.models.unified_jobs import ( + UnifiedJob, + UnifiedJobTemplate, + ACTIVE_STATES, +) from awx.main.models.mixins import ( ResourceMixin, TaskManagerProjectUpdateMixin, @@ -578,8 +582,8 @@ class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManage return UnifiedJob.objects.non_polymorphic().filter( models.Q(status__in=ACTIVE_STATES) & ( - models.Q(Job___project=self) | - models.Q(ProjectUpdate___project=self) + models.Q(Job___project=self.project) | + models.Q(ProjectUpdate___project=self.project) ) ) From c628e9de0a79a7cc15e1bba874b3366fed73e01a Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Fri, 16 Mar 2018 09:32:42 -0400 Subject: [PATCH 3/4] Filter active jobs by WFT/JT --- awx/main/models/jobs.py | 2 +- awx/main/models/workflow.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index 6bae4b6a78..f1f7f9e28d 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -456,7 +456,7 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, Resour RelatedJobsMixin ''' def _get_active_jobs(self): - return Job.objects.filter(status__in=ACTIVE_STATES) + return Job.objects.filter(status__in=ACTIVE_STATES, job_template=self) class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskManagerJobMixin): diff --git a/awx/main/models/workflow.py b/awx/main/models/workflow.py index 73a56a2dea..59f3bccb74 100644 --- a/awx/main/models/workflow.py +++ b/awx/main/models/workflow.py @@ -415,7 +415,7 @@ class WorkflowJobTemplate(UnifiedJobTemplate, WorkflowJobOptions, SurveyJobTempl RelatedJobsMixin ''' def _get_active_jobs(self): - return WorkflowJob.objects.filter(status__in=ACTIVE_STATES) + return WorkflowJob.objects.filter(status__in=ACTIVE_STATES, workflow_job_template=self) class WorkflowJob(UnifiedJob, WorkflowJobOptions, SurveyJobMixin, JobNotificationMixin): From 6231742f718bb8a63d29ec162a435d990d38ba12 Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Fri, 16 Mar 2018 09:36:15 -0400 Subject: [PATCH 4/4] Move RelatedJob mixin to Project --- awx/main/models/projects.py | 34 +++++++++------------- awx/main/tests/functional/test_projects.py | 4 +-- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py index 1d51c53641..667efedfba 100644 --- a/awx/main/models/projects.py +++ b/awx/main/models/projects.py @@ -234,7 +234,7 @@ class ProjectOptions(models.Model): return proj_path + '.lock' -class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEnvMixin): +class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEnvMixin, RelatedJobsMixin): ''' A project represents a playbook git repo that can access a set of inventories ''' @@ -451,16 +451,21 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn def get_absolute_url(self, request=None): return reverse('api:project_detail', kwargs={'pk': self.pk}, request=request) - def get_active_jobs(self): - for project_update in self.project_updates.all(): - active_jobs = project_update.get_active_jobs() - if active_jobs is None: - continue - return active_jobs - return [] + ''' + RelatedJobsMixin + ''' + def _get_active_jobs(self): + return UnifiedJob.objects.non_polymorphic().filter( + models.Q(status__in=ACTIVE_STATES) & + ( + models.Q(Job___project=self) | + models.Q(ProjectUpdate___project=self) + ) + ) -class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManagerProjectUpdateMixin, RelatedJobsMixin): + +class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManagerProjectUpdateMixin): ''' Internal job for tracking project updates from SCM. ''' @@ -575,15 +580,4 @@ class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManage return self.global_instance_groups return selected_groups - ''' - RelatedJobsMixin - ''' - def _get_active_jobs(self): - return UnifiedJob.objects.non_polymorphic().filter( - models.Q(status__in=ACTIVE_STATES) & - ( - models.Q(Job___project=self.project) | - models.Q(ProjectUpdate___project=self.project) - ) - ) diff --git a/awx/main/tests/functional/test_projects.py b/awx/main/tests/functional/test_projects.py index a6cef20f6f..55cc484006 100644 --- a/awx/main/tests/functional/test_projects.py +++ b/awx/main/tests/functional/test_projects.py @@ -254,7 +254,7 @@ def test_project_unique_together_with_org(organization): @pytest.mark.django_db -def test_project_delete(delete, organization, admin): +def test_project_delete(delete, organization, admin_user): proj = Project(name='foo', organization=organization) proj.save() - delete(reverse('api:project_detail', kwargs={'pk':proj.id,}), admin) + delete(reverse('api:project_detail', kwargs={'pk':proj.id,}), admin_user)