From 7183549289605695e8f205b81ed53c42513150c6 Mon Sep 17 00:00:00 2001 From: Chris Church Date: Tue, 14 May 2013 19:17:09 -0400 Subject: [PATCH] Moved queryset filtering/ordering out of BaseList into the CustomFilterBackend. Added job_host_summaries sublists for jobs and hosts, add detail view for job host summary, with tests. --- lib/main/base_views.py | 19 +----- lib/main/custom_filters.py | 14 +++- lib/main/models/__init__.py | 3 + lib/main/serializers.py | 20 +++--- lib/main/tests/jobs.py | 78 ++++++++++++++++++++-- lib/main/urls.py | 16 +++-- lib/main/views.py | 125 +++++++++++++++++++++--------------- 7 files changed, 187 insertions(+), 88 deletions(-) diff --git a/lib/main/base_views.py b/lib/main/base_views.py index 461f9d2585..19297d3196 100644 --- a/lib/main/base_views.py +++ b/lib/main/base_views.py @@ -31,28 +31,13 @@ class BaseList(generics.ListCreateAPIView): # serializer_class = SerializerClass def post(self, request, *args, **kwargs): + # FIXME: Should inherit from generics.ListAPIView if not postable. postable = getattr(self.__class__, 'postable', True) if not postable: return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) return super(BaseList, self).post(request, *args, **kwargs) - def get_queryset(self): - - base = self._get_queryset() - model = self.__class__.model - qs = None - if model == User: - qs = base.filter(is_active=True) - elif model in [ Tag, AuditTrail, JobEvent ]: - qs = base - else: - qs = self._get_queryset().filter(active=True) - - order = self.request.QUERY_PARAMS.get('order', None) - if order: - qs = qs.order_by(order) - - return qs + # NOTE: Moved filtering from get_queryset into custom filter backend. class BaseSubList(BaseList): diff --git a/lib/main/custom_filters.py b/lib/main/custom_filters.py index fe08c02846..7b7bc5a4f4 100644 --- a/lib/main/custom_filters.py +++ b/lib/main/custom_filters.py @@ -13,12 +13,20 @@ class CustomFilterBackend(object): terms = {} order_by = None - for key, value in request.GET.items(): + # Filtering by is_active/active that was previously in BaseList. + qs = queryset + for field in queryset.model._meta.fields: + if field.name == 'is_active': + qs = qs.filter(is_active=True) + elif field.name == 'active': + qs = qs.filter(active=True) + + for key, value in request.QUERY_PARAMS.items(): if key in [ 'page', 'page_size', 'format' ]: continue - if key == 'order_by': + if key in ('order', 'order_by'): order_by = value continue @@ -29,7 +37,7 @@ class CustomFilterBackend(object): terms[key2] = value - qs = queryset.filter(**terms) + qs = qs.filter(**terms) if order_by: qs = qs.order_by(order_by) diff --git a/lib/main/models/__init__.py b/lib/main/models/__init__.py index 124d112899..f3180b8a79 100644 --- a/lib/main/models/__init__.py +++ b/lib/main/models/__init__.py @@ -802,6 +802,9 @@ class JobHostSummary(models.Model): (self.host.name, self.changed, self.dark, self.failures, self.ok, self.processed, self.skipped) + def get_absolute_url(self): + return reverse('main:job_host_summary_detail', args=(self.pk,)) + def save(self, *args, **kwargs): super(JobHostSummary, self).save(*args, **kwargs) self.update_host_last_job_summary() diff --git a/lib/main/serializers.py b/lib/main/serializers.py index 9c8dd5703c..5ffdfeec4d 100644 --- a/lib/main/serializers.py +++ b/lib/main/serializers.py @@ -207,11 +207,12 @@ class HostSerializer(BaseSerializer): variable_data = reverse('main:hosts_variable_detail', args=(obj.pk,)), inventory = reverse('main:inventory_detail', args=(obj.inventory.pk,)), job_events = reverse('main:host_job_event_list', args=(obj.pk,)), + job_host_summaries = reverse('main:host_job_host_summary_list', args=(obj.pk,)), )) if obj.last_job: res['last_job'] = reverse('main:job_detail', args=(obj.last_job.pk,)) - #if obj.last_job_host_summary: - # res['last_job_host_summary'] = reverse('main:job_host_summary_detail', args=(obj.last_job_host_summary.pk,)) + if obj.last_job_host_summary: + res['last_job_host_summary'] = reverse('main:job_host_summary_detail', args=(obj.last_job_host_summary.pk,)) # NICE TO HAVE: possible reverse resource to show what groups the host is in return res @@ -391,7 +392,7 @@ class JobSerializer(BaseSerializer): project = reverse('main:projects_detail', args=(obj.project.pk,)), credential = reverse('main:credentials_detail', args=(obj.credential.pk,)), job_events = reverse('main:job_job_event_list', args=(obj.pk,)), - #hosts = reverse('main:job_???', args=(obj.pk,)), + job_host_summaries = reverse('main:job_job_host_summary_list', args=(obj.pk,)), )) if obj.job_template: res['job_template'] = reverse('main:job_template_detail', args=(obj.job_template.pk,)) @@ -427,14 +428,15 @@ class JobHostSummarySerializer(BaseSerializer): class Meta: model = JobHostSummary - fields = ('id', 'url', 'job', 'host', 'changed', 'dark', 'failures', - 'ok', 'processed', 'skipped', 'related') + fields = ('id', 'url', 'job', 'host', 'summary_fields', 'related', + 'changed', 'dark', 'failures', 'ok', 'processed', 'skipped') def get_related(self, obj): res = super(JobHostSummarySerializer, self).get_related(obj) - res['job'] = reverse('main:job_detail', args=(obj.job.pk,)) - if obj.host: - res['host'] = reverse('main:hosts_detail', args=(obj.host.pk,)) + res.update(dict( + job=reverse('main:job_detail', args=(obj.job.pk,)), + host=reverse('main:hosts_detail', args=(obj.host.pk,)) + )) return res class JobEventSerializer(BaseSerializer): @@ -442,7 +444,7 @@ class JobEventSerializer(BaseSerializer): class Meta: model = JobEvent fields = ('id', 'url', 'job', 'event', 'event_data', 'failed', 'host', - 'related') + 'related', 'summary_fields') def get_related(self, obj): res = super(JobEventSerializer, self).get_related(obj) diff --git a/lib/main/tests/jobs.py b/lib/main/tests/jobs.py index 591eb517d4..211ab3f8cb 100644 --- a/lib/main/tests/jobs.py +++ b/lib/main/tests/jobs.py @@ -868,11 +868,81 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.TransactionTestCase): # FIXME: Test with other users. - def test_get_job_host_list(self): - pass + def test_get_job_results(self): + # Start/run a job and then access its results via the API. + job = self.job_ops_east_run + job.start() - def test_get_job_job_event_list(self): - pass + # Check that the job detail has been updated. + url = reverse('main:job_detail', args=(job.pk,)) + with self.current_user(self.user_sue): + response = self.get(url) + self.assertEqual(response['status'], 'successful') + self.assertTrue(response['result_stdout']) + # Test job events for completed job. + url = reverse('main:job_job_event_list', args=(job.pk,)) + with self.current_user(self.user_sue): + response = self.get(url) + qs = job.job_events.all() + self.assertTrue(qs.count()) + self.check_pagination_and_size(response, qs.count()) + self.check_list_ids(response, qs) + # Test individual job event detail records. + host_ids = set() + for job_event in job.job_events.all(): + if job_event.host: + host_ids.add(job_event.host.pk) + url = reverse('main:job_event_detail', args=(job_event.pk,)) + with self.current_user(self.user_sue): + response = self.get(url) + # Also test job event list for each host. + for host in Host.objects.filter(pk__in=host_ids): + url = reverse('main:host_job_event_list', args=(host.pk,)) + with self.current_user(self.user_sue): + response = self.get(url) + qs = host.job_events.all() + self.assertTrue(qs.count()) + self.check_pagination_and_size(response, qs.count()) + self.check_list_ids(response, qs) + + # Test global job event list. + url = reverse('main:job_event_list') + with self.current_user(self.user_sue): + response = self.get(url) + qs = JobEvent.objects.all() + self.assertTrue(qs.count()) + self.check_pagination_and_size(response, qs.count()) + self.check_list_ids(response, qs) + + # Test job host summaries for completed job. + url = reverse('main:job_job_host_summary_list', args=(job.pk,)) + with self.current_user(self.user_sue): + response = self.get(url) + qs = job.job_host_summaries.all() + self.assertTrue(qs.count()) + self.check_pagination_and_size(response, qs.count()) + self.check_list_ids(response, qs) + # Every host referenced by a job_event should be present as a job + # host summary record. + self.assertEqual(host_ids, + set(qs.values_list('host__pk', flat=True))) + + # Test individual job host summary records. + for job_host_summary in job.job_host_summaries.all(): + url = reverse('main:job_host_summary_detail', + args=(job_host_summary.pk,)) + with self.current_user(self.user_sue): + response = self.get(url) + + # Test job host summaries for each host. + for host in Host.objects.filter(pk__in=host_ids): + url = reverse('main:host_job_host_summary_list', args=(host.pk,)) + with self.current_user(self.user_sue): + response = self.get(url) + qs = host.job_host_summaries.all() + self.assertTrue(qs.count()) + self.check_pagination_and_size(response, qs.count()) + self.check_list_ids(response, qs) diff --git a/lib/main/urls.py b/lib/main/urls.py index ff1f87fde1..a62c291a9a 100644 --- a/lib/main/urls.py +++ b/lib/main/urls.py @@ -68,6 +68,7 @@ hosts_urls = patterns('lib.main.views', url(r'^(?P[0-9]+)/$', 'hosts_detail'), url(r'^(?P[0-9]+)/variable_data/$', 'hosts_variable_detail'), url(r'^(?P[0-9]+)/job_events/', 'host_job_event_list'), + url(r'^(?P[0-9]+)/job_host_summaries/$', 'host_job_host_summary_list'), ) groups_urls = patterns('lib.main.views', @@ -105,14 +106,18 @@ jobs_urls = patterns('lib.main.views', url(r'^(?P[0-9]+)/$', 'job_detail'), url(r'^(?P[0-9]+)/start/$', 'job_start'), url(r'^(?P[0-9]+)/cancel/$', 'job_cancel'), - url(r'^(?P[0-9]+)/hosts/$', 'job_hosts_list'), - url(r'^(?P[0-9]+)/successful_hosts/$', 'jobs_successful_hosts_list'), - url(r'^(?P[0-9]+)/changed_hosts/$', 'jobs_changed_hosts_list'), - url(r'^(?P[0-9]+)/failed_hosts/$', 'jobs_failed_hosts_list'), - url(r'^(?P[0-9]+)/unreachable_hosts/$', 'jobs_unreachable_hosts_list'), + url(r'^(?P[0-9]+)/job_host_summaries/$', 'job_job_host_summary_list'), + #url(r'^(?P[0-9]+)/successful_hosts/$', 'jobs_successful_hosts_list'), + #url(r'^(?P[0-9]+)/changed_hosts/$', 'jobs_changed_hosts_list'), + #url(r'^(?P[0-9]+)/failed_hosts/$', 'jobs_failed_hosts_list'), + #url(r'^(?P[0-9]+)/unreachable_hosts/$', 'jobs_unreachable_hosts_list'), url(r'^(?P[0-9]+)/job_events/$', 'job_job_event_list'), ) +job_host_summary_urls = patterns('lib.main.views', + url(r'^(?P[0-9]+)/$', 'job_host_summary_detail'), +) + job_events_urls = patterns('lib.main.views', url(r'^$', 'job_event_list'), url(r'^(?P[0-9]+)/$', 'job_event_detail'), @@ -140,6 +145,7 @@ v1_urls = patterns('lib.main.views', url(r'^permissions/', include(permissions_urls)), url(r'^job_templates/', include(job_templates_urls)), url(r'^jobs/', include(jobs_urls)), + url(r'^job_host_summaries/', include(job_host_summary_urls)), url(r'^job_events/', include(job_events_urls)), url(r'^tags/', include(tags_urls)), ) diff --git a/lib/main/views.py b/lib/main/views.py index 46797a9be3..84fc00b98f 100644 --- a/lib/main/views.py +++ b/lib/main/views.py @@ -95,7 +95,7 @@ class OrganizationsList(BaseList): # I am an admin of the organization # I am a member of the organization - def _get_queryset(self): + def get_queryset(self): ''' I can see organizations when I am a superuser, or I am an admin or user in that organization ''' base = Organization.objects if self.request.user.is_superuser: @@ -121,7 +121,7 @@ class OrganizationsAuditTrailList(BaseSubList): relationship = 'audit_trail' postable = False - def _get_queryset(self): + def get_queryset(self): ''' to list tags in the organization, I must be a superuser or org admin ''' organization = Organization.objects.get(pk=self.kwargs['pk']) if not (self.request.user.is_superuser or self.request.user in organization.admins.all()): @@ -138,7 +138,7 @@ class OrganizationsInventoriesList(BaseSubList): relationship = 'inventories' postable = False - def _get_queryset(self): + def get_queryset(self): ''' to list inventories in the organization, I must be a superuser or org admin ''' organization = Organization.objects.get(pk=self.kwargs['pk']) if not (self.request.user.is_superuser or self.request.user in organization.admins.all()): @@ -157,7 +157,7 @@ class OrganizationsUsersList(BaseSubList): inject_primary_key_on_post_as = 'organization' filter_fields = ('username',) - def _get_queryset(self): + def get_queryset(self): ''' to list users in the organization, I must be a superuser or org admin ''' organization = Organization.objects.get(pk=self.kwargs['pk']) if not self.request.user.is_superuser and not self.request.user in organization.admins.all(): @@ -175,7 +175,7 @@ class OrganizationsAdminsList(BaseSubList): inject_primary_key_on_post_as = 'organization' filter_fields = ('username',) - def _get_queryset(self): + def get_queryset(self): ''' to list admins in the organization, I must be a superuser or org admin ''' organization = Organization.objects.get(pk=self.kwargs['pk']) if not self.request.user.is_superuser and not self.request.user in organization.admins.all(): @@ -193,7 +193,7 @@ class OrganizationsProjectsList(BaseSubList): inject_primary_key_on_post_as = 'organization' filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): ''' to list projects in the organization, I must be a superuser or org admin ''' organization = Organization.objects.get(pk=self.kwargs['pk']) if not (self.request.user.is_superuser or self.request.user in organization.admins.all()): @@ -211,7 +211,7 @@ class OrganizationsTagsList(BaseSubList): inject_primary_key_on_post_as = 'organization' filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): ''' to list tags in the organization, I must be a superuser or org admin ''' organization = Organization.objects.get(pk=self.kwargs['pk']) if not (self.request.user.is_superuser or self.request.user in organization.admins.all()): @@ -231,7 +231,7 @@ class OrganizationsTeamsList(BaseSubList): severable = False filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): ''' to list users in the organization, I must be a superuser or org admin ''' organization = Organization.objects.get(pk=self.kwargs['pk']) if not self.request.user.is_superuser and not self.request.user in organization.admins.all(): @@ -250,7 +250,7 @@ class TeamsList(BaseList): # I am an admin of the organization that the team is # I am on that team - def _get_queryset(self): + def get_queryset(self): ''' I can see organizations when I am a superuser, or I am an admin or user in that organization ''' base = Team.objects if self.request.user.is_superuser: @@ -279,7 +279,7 @@ class TeamsUsersList(BaseSubList): severable = True filter_fields = ('username',) - def _get_queryset(self): + def get_queryset(self): # FIXME: audit all BaseSubLists to check for permissions on the original object too 'team members can see the whole team, as can org admins or superusers' team = Team.objects.get(pk=self.kwargs['pk']) @@ -301,7 +301,7 @@ class TeamsPermissionsList(BaseSubList): filter_fields = ('name',) inject_primary_key_on_post_as = 'team' - def _get_queryset(self): + def get_queryset(self): team = Team.objects.get(pk=self.kwargs['pk']) base = Permission.objects.filter(team = team) #if Team.can_user_administrate(self.request.user, team, None): @@ -326,7 +326,7 @@ class TeamsProjectsList(BaseSubList): # FIXME: filter_fields is no longer used, think we can remove these references everywhere given new custom filtering -- MPD filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): team = Team.objects.get(pk=self.kwargs['pk']) base = team.projects.all() if self.request.user.is_superuser or self.request.user in team.organization.admins.all(): @@ -347,7 +347,7 @@ class TeamsCredentialsList(BaseSubList): inject_primary_key_on_post_as = 'team' filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): team = Team.objects.get(pk=self.kwargs['pk']) #if not Team.can_user_administrate(self.request.user, team, None): if not check_user_access(self.request.user, Team, 'change', team, None): @@ -371,7 +371,7 @@ class ProjectsList(BaseList): # I am an admin of the organization that contains the project # I am a member of a team that also contains the project - def _get_queryset(self): + def get_queryset(self): ''' I can see organizations when I am a superuser, or I am an admin or user in that organization ''' base = Project.objects if self.request.user.is_superuser: @@ -406,7 +406,7 @@ class ProjectsOrganizationsList(BaseSubList): postable = False filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): project = Project.objects.get(pk=self.kwargs['pk']) if not self.request.user.is_superuser: raise PermissionDenied() @@ -435,7 +435,7 @@ class UsersList(BaseList): user.save() return result - def _get_queryset(self): + def get_queryset(self): ''' I can see user records when I'm a superuser, I'm that user, I'm their org admin, or I'm on a team with that user ''' base = User.objects if self.request.user.is_superuser: @@ -458,7 +458,7 @@ class UsersMeList(BaseList): def post(self, request, *args, **kwargs): raise PermissionDenied() - def _get_queryset(self): + def get_queryset(self): ''' a quick way to find my user record ''' return User.objects.filter(pk=self.request.user.pk) @@ -472,7 +472,7 @@ class UsersTeamsList(BaseSubList): postable = False filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): user = User.objects.get(pk=self.kwargs['pk']) #if not UserHelper.can_user_administrate(self.request.user, user, None): if not check_user_access(self.request.user, User, 'change', user, None): @@ -490,7 +490,7 @@ class UsersPermissionsList(BaseSubList): filter_fields = ('name',) inject_primary_key_on_post_as = 'user' - def _get_queryset(self): + def get_queryset(self): user = User.objects.get(pk=self.kwargs['pk']) #if not UserHelper.can_user_administrate(self.request.user, user, None): if not check_user_access(self.request.user, User, 'change', user, None): @@ -507,7 +507,7 @@ class UsersProjectsList(BaseSubList): postable = False filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): user = User.objects.get(pk=self.kwargs['pk']) #if not UserHelper.can_user_administrate(self.request.user, user, None): if not check_user_access(self.request.user, User, 'change', user, None): @@ -526,7 +526,7 @@ class UsersCredentialsList(BaseSubList): inject_primary_key_on_post_as = 'user' filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): user = User.objects.get(pk=self.kwargs['pk']) #if not UserHelper.can_user_administrate(self.request.user, user, None): if not check_user_access(self.request.user, User, 'change', user, None): @@ -546,7 +546,7 @@ class UsersOrganizationsList(BaseSubList): postable = False filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): user = User.objects.get(pk=self.kwargs['pk']) #if not UserHelper.can_user_administrate(self.request.user, user, None): if not check_user_access(self.request.user, User, 'change', user, None): @@ -563,7 +563,7 @@ class UsersAdminOrganizationsList(BaseSubList): postable = False filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): user = User.objects.get(pk=self.kwargs['pk']) #if not UserHelper.can_user_administrate(self.request.user, user, None): if not check_user_access(self.request.user, User, 'change', user, None): @@ -593,7 +593,7 @@ class CredentialsList(BaseList): permission_classes = (CustomRbac,) postable = False - def _get_queryset(self): + def get_queryset(self): return get_user_queryset(self.request.user, self.model) class CredentialsDetail(BaseDetail): @@ -629,7 +629,7 @@ class InventoryList(BaseList): ).distinct() return admin_of | has_user_perms | has_team_perms - def _get_queryset(self): + def get_queryset(self): ''' I can see inventory when I'm a superuser, an org admin of the inventory, or I have permissions on it ''' base = Inventory.objects return self._filter_queryset(base) @@ -647,7 +647,7 @@ class HostsList(BaseList): permission_classes = (CustomRbac,) filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): ''' I can see hosts when: I'm a superuser, @@ -689,7 +689,7 @@ class InventoryHostsList(BaseSubList): severable = False filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): inventory = Inventory.objects.get(pk=self.kwargs['pk']) base = inventory.hosts # FIXME: verify that you can can_read permission on the inventory is required @@ -702,7 +702,7 @@ class GroupsList(BaseList): permission_classes = (CustomRbac,) filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): ''' I can see groups when: I'm a superuser, @@ -734,7 +734,7 @@ class GroupsChildrenList(BaseSubList): inject_primary_key_on_post_as = 'parent' filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): # FIXME: this is the mostly the same as GroupsList, share code similar to how done with Host and Group objects. @@ -768,7 +768,7 @@ class GroupsHostsList(BaseSubList): inject_primary_key_on_post_as = 'group' filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): parent = Group.objects.get(pk=self.kwargs['pk']) @@ -812,7 +812,7 @@ class GroupsAllHostsList(BaseSubList): result = result | self._child_hosts(child) return result - def _get_queryset(self): + def get_queryset(self): parent = Group.objects.get(pk=self.kwargs['pk']) @@ -856,7 +856,7 @@ class InventoryGroupsList(BaseSubList): severable = False filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): # FIXME: share code with inventory filter queryset methods (make that a classmethod) inventory = Inventory.objects.get(pk=self.kwargs['pk']) base = inventory.groups @@ -916,7 +916,7 @@ class JobTemplateList(BaseList): permission_classes = (CustomRbac,) filter_fields = ('name',) - def _get_queryset(self): + def get_queryset(self): return get_user_queryset(self.request.user, self.model) class JobTemplateDetail(BaseDetail): @@ -940,8 +940,8 @@ class JobTemplateJobList(BaseSubList): severable = False #filter_fields = ('name',) - def _get_queryset(self): - # FIxME: Verify read permission on the job template. + def get_queryset(self): + # FIXME: Verify read permission on the job template. job_template = get_object_or_404(JobTemplate, pk=self.kwargs['pk']) return job_template.jobs @@ -951,7 +951,7 @@ class JobList(BaseList): serializer_class = JobSerializer permission_classes = (CustomRbac,) - def _get_queryset(self): + def get_queryset(self): return self.model.objects.all() # FIXME class JobDetail(BaseDetail): @@ -1012,20 +1012,45 @@ class JobCancel(generics.RetrieveAPIView): else: return Response(status=405) -class JobHostsList(BaseSubList): - pass +class HostJobHostSummaryList(generics.ListAPIView): -class JobsSuccessfulHostsList(BaseSubList): - pass + model = JobHostSummary + serializer_class = JobHostSummarySerializer + permission_classes = (CustomRbac,) + parent_model = Host + relationship = 'job_host_summaries' -class JobsChangedHostsList(BaseSubList): - pass + def get_name(self): + return 'Job Host Summary List' -class JobsFailedHostsList(BaseSubList): - pass + def get_queryset(self): + # FIXME: Verify read permission on the host and job. + host = get_object_or_404(Host, pk=self.kwargs['pk']) + return host.job_host_summaries -class JobsUnreachableHostsList(BaseSubList): - pass +class JobJobHostSummaryList(generics.ListAPIView): + + model = JobHostSummary + serializer_class = JobHostSummarySerializer + permission_classes = (CustomRbac,) + parent_model = Job + relationship = 'job_host_summaries' + + def get_name(self): + return 'Job Host Summary List' + + def get_queryset(self): + # FIXME: Verify read permission on the host and job. + job = get_object_or_404(Job, pk=self.kwargs['pk']) + return job.job_host_summaries + +# FIXME: Subclasses of XJobHostSummaryList for failed/successful/etc. + +class JobHostSummaryDetail(generics.RetrieveAPIView): + + model = JobHostSummary + serializer_class = JobHostSummarySerializer + permission_classes = (CustomRbac,) class JobEventList(BaseList): @@ -1033,10 +1058,10 @@ class JobEventList(BaseList): serializer_class = JobEventSerializer permission_classes = (CustomRbac,) - def _get_queryset(self): + def get_queryset(self): return self.model.objects.all() # FIXME -class JobEventDetail(BaseDetail): +class JobEventDetail(generics.RetrieveAPIView): model = JobEvent serializer_class = JobEventSerializer @@ -1052,7 +1077,7 @@ class JobJobEventList(BaseSubList): postable = False severable = False - def _get_queryset(self): + def get_queryset(self): job = get_object_or_404(Job, pk=self.kwargs['pk']) # FIXME: Verify read permission on the job. return job.job_events @@ -1067,7 +1092,7 @@ class HostJobEventList(BaseSubList): postable = False severable = False - def _get_queryset(self): + def get_queryset(self): host = get_object_or_404(Host, pk=self.kwargs['pk']) # FIXME: Verify read permission on the host. return host.job_events