1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-31 15:21:13 +03:00

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.

This commit is contained in:
Chris Church 2013-05-14 19:17:09 -04:00
parent 5c6895e606
commit 7183549289
7 changed files with 187 additions and 88 deletions

View File

@ -31,28 +31,13 @@ class BaseList(generics.ListCreateAPIView):
# serializer_class = SerializerClass # serializer_class = SerializerClass
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
# FIXME: Should inherit from generics.ListAPIView if not postable.
postable = getattr(self.__class__, 'postable', True) postable = getattr(self.__class__, 'postable', True)
if not postable: if not postable:
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
return super(BaseList, self).post(request, *args, **kwargs) return super(BaseList, self).post(request, *args, **kwargs)
def get_queryset(self): # NOTE: Moved filtering from get_queryset into custom filter backend.
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
class BaseSubList(BaseList): class BaseSubList(BaseList):

View File

@ -13,12 +13,20 @@ class CustomFilterBackend(object):
terms = {} terms = {}
order_by = None 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' ]: if key in [ 'page', 'page_size', 'format' ]:
continue continue
if key == 'order_by': if key in ('order', 'order_by'):
order_by = value order_by = value
continue continue
@ -29,7 +37,7 @@ class CustomFilterBackend(object):
terms[key2] = value terms[key2] = value
qs = queryset.filter(**terms) qs = qs.filter(**terms)
if order_by: if order_by:
qs = qs.order_by(order_by) qs = qs.order_by(order_by)

View File

@ -802,6 +802,9 @@ class JobHostSummary(models.Model):
(self.host.name, self.changed, self.dark, self.failures, self.ok, (self.host.name, self.changed, self.dark, self.failures, self.ok,
self.processed, self.skipped) self.processed, self.skipped)
def get_absolute_url(self):
return reverse('main:job_host_summary_detail', args=(self.pk,))
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
super(JobHostSummary, self).save(*args, **kwargs) super(JobHostSummary, self).save(*args, **kwargs)
self.update_host_last_job_summary() self.update_host_last_job_summary()

View File

@ -207,11 +207,12 @@ class HostSerializer(BaseSerializer):
variable_data = reverse('main:hosts_variable_detail', args=(obj.pk,)), variable_data = reverse('main:hosts_variable_detail', args=(obj.pk,)),
inventory = reverse('main:inventory_detail', args=(obj.inventory.pk,)), inventory = reverse('main:inventory_detail', args=(obj.inventory.pk,)),
job_events = reverse('main:host_job_event_list', args=(obj.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: if obj.last_job:
res['last_job'] = reverse('main:job_detail', args=(obj.last_job.pk,)) res['last_job'] = reverse('main:job_detail', args=(obj.last_job.pk,))
#if obj.last_job_host_summary: if obj.last_job_host_summary:
# res['last_job_host_summary'] = reverse('main:job_host_summary_detail', args=(obj.last_job_host_summary.pk,)) 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 # NICE TO HAVE: possible reverse resource to show what groups the host is in
return res return res
@ -391,7 +392,7 @@ class JobSerializer(BaseSerializer):
project = reverse('main:projects_detail', args=(obj.project.pk,)), project = reverse('main:projects_detail', args=(obj.project.pk,)),
credential = reverse('main:credentials_detail', args=(obj.credential.pk,)), credential = reverse('main:credentials_detail', args=(obj.credential.pk,)),
job_events = reverse('main:job_job_event_list', args=(obj.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: if obj.job_template:
res['job_template'] = reverse('main:job_template_detail', args=(obj.job_template.pk,)) res['job_template'] = reverse('main:job_template_detail', args=(obj.job_template.pk,))
@ -427,14 +428,15 @@ class JobHostSummarySerializer(BaseSerializer):
class Meta: class Meta:
model = JobHostSummary model = JobHostSummary
fields = ('id', 'url', 'job', 'host', 'changed', 'dark', 'failures', fields = ('id', 'url', 'job', 'host', 'summary_fields', 'related',
'ok', 'processed', 'skipped', 'related') 'changed', 'dark', 'failures', 'ok', 'processed', 'skipped')
def get_related(self, obj): def get_related(self, obj):
res = super(JobHostSummarySerializer, self).get_related(obj) res = super(JobHostSummarySerializer, self).get_related(obj)
res['job'] = reverse('main:job_detail', args=(obj.job.pk,)) res.update(dict(
if obj.host: job=reverse('main:job_detail', args=(obj.job.pk,)),
res['host'] = reverse('main:hosts_detail', args=(obj.host.pk,)) host=reverse('main:hosts_detail', args=(obj.host.pk,))
))
return res return res
class JobEventSerializer(BaseSerializer): class JobEventSerializer(BaseSerializer):
@ -442,7 +444,7 @@ class JobEventSerializer(BaseSerializer):
class Meta: class Meta:
model = JobEvent model = JobEvent
fields = ('id', 'url', 'job', 'event', 'event_data', 'failed', 'host', fields = ('id', 'url', 'job', 'event', 'event_data', 'failed', 'host',
'related') 'related', 'summary_fields')
def get_related(self, obj): def get_related(self, obj):
res = super(JobEventSerializer, self).get_related(obj) res = super(JobEventSerializer, self).get_related(obj)

View File

@ -868,11 +868,81 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.TransactionTestCase):
# FIXME: Test with other users. # FIXME: Test with other users.
def test_get_job_host_list(self): def test_get_job_results(self):
pass # 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): # Check that the job detail has been updated.
pass 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)

View File

@ -68,6 +68,7 @@ hosts_urls = patterns('lib.main.views',
url(r'^(?P<pk>[0-9]+)/$', 'hosts_detail'), url(r'^(?P<pk>[0-9]+)/$', 'hosts_detail'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'hosts_variable_detail'), url(r'^(?P<pk>[0-9]+)/variable_data/$', 'hosts_variable_detail'),
url(r'^(?P<pk>[0-9]+)/job_events/', 'host_job_event_list'), url(r'^(?P<pk>[0-9]+)/job_events/', 'host_job_event_list'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'host_job_host_summary_list'),
) )
groups_urls = patterns('lib.main.views', groups_urls = patterns('lib.main.views',
@ -105,14 +106,18 @@ jobs_urls = patterns('lib.main.views',
url(r'^(?P<pk>[0-9]+)/$', 'job_detail'), url(r'^(?P<pk>[0-9]+)/$', 'job_detail'),
url(r'^(?P<pk>[0-9]+)/start/$', 'job_start'), url(r'^(?P<pk>[0-9]+)/start/$', 'job_start'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'job_cancel'), url(r'^(?P<pk>[0-9]+)/cancel/$', 'job_cancel'),
url(r'^(?P<pk>[0-9]+)/hosts/$', 'job_hosts_list'), url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'job_job_host_summary_list'),
url(r'^(?P<pk>[0-9]+)/successful_hosts/$', 'jobs_successful_hosts_list'), #url(r'^(?P<pk>[0-9]+)/successful_hosts/$', 'jobs_successful_hosts_list'),
url(r'^(?P<pk>[0-9]+)/changed_hosts/$', 'jobs_changed_hosts_list'), #url(r'^(?P<pk>[0-9]+)/changed_hosts/$', 'jobs_changed_hosts_list'),
url(r'^(?P<pk>[0-9]+)/failed_hosts/$', 'jobs_failed_hosts_list'), #url(r'^(?P<pk>[0-9]+)/failed_hosts/$', 'jobs_failed_hosts_list'),
url(r'^(?P<pk>[0-9]+)/unreachable_hosts/$', 'jobs_unreachable_hosts_list'), #url(r'^(?P<pk>[0-9]+)/unreachable_hosts/$', 'jobs_unreachable_hosts_list'),
url(r'^(?P<pk>[0-9]+)/job_events/$', 'job_job_event_list'), url(r'^(?P<pk>[0-9]+)/job_events/$', 'job_job_event_list'),
) )
job_host_summary_urls = patterns('lib.main.views',
url(r'^(?P<pk>[0-9]+)/$', 'job_host_summary_detail'),
)
job_events_urls = patterns('lib.main.views', job_events_urls = patterns('lib.main.views',
url(r'^$', 'job_event_list'), url(r'^$', 'job_event_list'),
url(r'^(?P<pk>[0-9]+)/$', 'job_event_detail'), url(r'^(?P<pk>[0-9]+)/$', 'job_event_detail'),
@ -140,6 +145,7 @@ v1_urls = patterns('lib.main.views',
url(r'^permissions/', include(permissions_urls)), url(r'^permissions/', include(permissions_urls)),
url(r'^job_templates/', include(job_templates_urls)), url(r'^job_templates/', include(job_templates_urls)),
url(r'^jobs/', include(jobs_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'^job_events/', include(job_events_urls)),
url(r'^tags/', include(tags_urls)), url(r'^tags/', include(tags_urls)),
) )

View File

@ -95,7 +95,7 @@ class OrganizationsList(BaseList):
# I am an admin of the organization # I am an admin of the organization
# I am a member 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 ''' ''' I can see organizations when I am a superuser, or I am an admin or user in that organization '''
base = Organization.objects base = Organization.objects
if self.request.user.is_superuser: if self.request.user.is_superuser:
@ -121,7 +121,7 @@ class OrganizationsAuditTrailList(BaseSubList):
relationship = 'audit_trail' relationship = 'audit_trail'
postable = False postable = False
def _get_queryset(self): def get_queryset(self):
''' to list tags in the organization, I must be a superuser or org admin ''' ''' to list tags in the organization, I must be a superuser or org admin '''
organization = Organization.objects.get(pk=self.kwargs['pk']) organization = Organization.objects.get(pk=self.kwargs['pk'])
if not (self.request.user.is_superuser or self.request.user in organization.admins.all()): if not (self.request.user.is_superuser or self.request.user in organization.admins.all()):
@ -138,7 +138,7 @@ class OrganizationsInventoriesList(BaseSubList):
relationship = 'inventories' relationship = 'inventories'
postable = False postable = False
def _get_queryset(self): def get_queryset(self):
''' to list inventories in the organization, I must be a superuser or org admin ''' ''' to list inventories in the organization, I must be a superuser or org admin '''
organization = Organization.objects.get(pk=self.kwargs['pk']) organization = Organization.objects.get(pk=self.kwargs['pk'])
if not (self.request.user.is_superuser or self.request.user in organization.admins.all()): 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' inject_primary_key_on_post_as = 'organization'
filter_fields = ('username',) 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 ''' ''' to list users in the organization, I must be a superuser or org admin '''
organization = Organization.objects.get(pk=self.kwargs['pk']) organization = Organization.objects.get(pk=self.kwargs['pk'])
if not self.request.user.is_superuser and not self.request.user in organization.admins.all(): 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' inject_primary_key_on_post_as = 'organization'
filter_fields = ('username',) 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 ''' ''' to list admins in the organization, I must be a superuser or org admin '''
organization = Organization.objects.get(pk=self.kwargs['pk']) organization = Organization.objects.get(pk=self.kwargs['pk'])
if not self.request.user.is_superuser and not self.request.user in organization.admins.all(): 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' inject_primary_key_on_post_as = 'organization'
filter_fields = ('name',) 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 ''' ''' to list projects in the organization, I must be a superuser or org admin '''
organization = Organization.objects.get(pk=self.kwargs['pk']) organization = Organization.objects.get(pk=self.kwargs['pk'])
if not (self.request.user.is_superuser or self.request.user in organization.admins.all()): 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' inject_primary_key_on_post_as = 'organization'
filter_fields = ('name',) 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 ''' ''' to list tags in the organization, I must be a superuser or org admin '''
organization = Organization.objects.get(pk=self.kwargs['pk']) organization = Organization.objects.get(pk=self.kwargs['pk'])
if not (self.request.user.is_superuser or self.request.user in organization.admins.all()): if not (self.request.user.is_superuser or self.request.user in organization.admins.all()):
@ -231,7 +231,7 @@ class OrganizationsTeamsList(BaseSubList):
severable = False severable = False
filter_fields = ('name',) 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 ''' ''' to list users in the organization, I must be a superuser or org admin '''
organization = Organization.objects.get(pk=self.kwargs['pk']) organization = Organization.objects.get(pk=self.kwargs['pk'])
if not self.request.user.is_superuser and not self.request.user in organization.admins.all(): 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 an admin of the organization that the team is
# I am on that team # 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 ''' ''' I can see organizations when I am a superuser, or I am an admin or user in that organization '''
base = Team.objects base = Team.objects
if self.request.user.is_superuser: if self.request.user.is_superuser:
@ -279,7 +279,7 @@ class TeamsUsersList(BaseSubList):
severable = True severable = True
filter_fields = ('username',) filter_fields = ('username',)
def _get_queryset(self): def get_queryset(self):
# FIXME: audit all BaseSubLists to check for permissions on the original object too # 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 members can see the whole team, as can org admins or superusers'
team = Team.objects.get(pk=self.kwargs['pk']) team = Team.objects.get(pk=self.kwargs['pk'])
@ -301,7 +301,7 @@ class TeamsPermissionsList(BaseSubList):
filter_fields = ('name',) filter_fields = ('name',)
inject_primary_key_on_post_as = 'team' inject_primary_key_on_post_as = 'team'
def _get_queryset(self): def get_queryset(self):
team = Team.objects.get(pk=self.kwargs['pk']) team = Team.objects.get(pk=self.kwargs['pk'])
base = Permission.objects.filter(team = team) base = Permission.objects.filter(team = team)
#if Team.can_user_administrate(self.request.user, team, None): #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 # FIXME: filter_fields is no longer used, think we can remove these references everywhere given new custom filtering -- MPD
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
team = Team.objects.get(pk=self.kwargs['pk']) team = Team.objects.get(pk=self.kwargs['pk'])
base = team.projects.all() base = team.projects.all()
if self.request.user.is_superuser or self.request.user in team.organization.admins.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' inject_primary_key_on_post_as = 'team'
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
team = Team.objects.get(pk=self.kwargs['pk']) team = Team.objects.get(pk=self.kwargs['pk'])
#if not Team.can_user_administrate(self.request.user, team, None): #if not Team.can_user_administrate(self.request.user, team, None):
if not check_user_access(self.request.user, Team, 'change', 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 an admin of the organization that contains the project
# I am a member of a team that also 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 ''' ''' I can see organizations when I am a superuser, or I am an admin or user in that organization '''
base = Project.objects base = Project.objects
if self.request.user.is_superuser: if self.request.user.is_superuser:
@ -406,7 +406,7 @@ class ProjectsOrganizationsList(BaseSubList):
postable = False postable = False
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
project = Project.objects.get(pk=self.kwargs['pk']) project = Project.objects.get(pk=self.kwargs['pk'])
if not self.request.user.is_superuser: if not self.request.user.is_superuser:
raise PermissionDenied() raise PermissionDenied()
@ -435,7 +435,7 @@ class UsersList(BaseList):
user.save() user.save()
return result 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 ''' ''' 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 base = User.objects
if self.request.user.is_superuser: if self.request.user.is_superuser:
@ -458,7 +458,7 @@ class UsersMeList(BaseList):
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
raise PermissionDenied() raise PermissionDenied()
def _get_queryset(self): def get_queryset(self):
''' a quick way to find my user record ''' ''' a quick way to find my user record '''
return User.objects.filter(pk=self.request.user.pk) return User.objects.filter(pk=self.request.user.pk)
@ -472,7 +472,7 @@ class UsersTeamsList(BaseSubList):
postable = False postable = False
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
user = User.objects.get(pk=self.kwargs['pk']) user = User.objects.get(pk=self.kwargs['pk'])
#if not UserHelper.can_user_administrate(self.request.user, user, None): #if not UserHelper.can_user_administrate(self.request.user, user, None):
if not check_user_access(self.request.user, User, 'change', user, None): if not check_user_access(self.request.user, User, 'change', user, None):
@ -490,7 +490,7 @@ class UsersPermissionsList(BaseSubList):
filter_fields = ('name',) filter_fields = ('name',)
inject_primary_key_on_post_as = 'user' inject_primary_key_on_post_as = 'user'
def _get_queryset(self): def get_queryset(self):
user = User.objects.get(pk=self.kwargs['pk']) user = User.objects.get(pk=self.kwargs['pk'])
#if not UserHelper.can_user_administrate(self.request.user, user, None): #if not UserHelper.can_user_administrate(self.request.user, user, None):
if not check_user_access(self.request.user, User, 'change', user, None): if not check_user_access(self.request.user, User, 'change', user, None):
@ -507,7 +507,7 @@ class UsersProjectsList(BaseSubList):
postable = False postable = False
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
user = User.objects.get(pk=self.kwargs['pk']) user = User.objects.get(pk=self.kwargs['pk'])
#if not UserHelper.can_user_administrate(self.request.user, user, None): #if not UserHelper.can_user_administrate(self.request.user, user, None):
if not check_user_access(self.request.user, User, 'change', 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' inject_primary_key_on_post_as = 'user'
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
user = User.objects.get(pk=self.kwargs['pk']) user = User.objects.get(pk=self.kwargs['pk'])
#if not UserHelper.can_user_administrate(self.request.user, user, None): #if not UserHelper.can_user_administrate(self.request.user, user, None):
if not check_user_access(self.request.user, User, 'change', user, None): if not check_user_access(self.request.user, User, 'change', user, None):
@ -546,7 +546,7 @@ class UsersOrganizationsList(BaseSubList):
postable = False postable = False
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
user = User.objects.get(pk=self.kwargs['pk']) user = User.objects.get(pk=self.kwargs['pk'])
#if not UserHelper.can_user_administrate(self.request.user, user, None): #if not UserHelper.can_user_administrate(self.request.user, user, None):
if not check_user_access(self.request.user, User, 'change', user, None): if not check_user_access(self.request.user, User, 'change', user, None):
@ -563,7 +563,7 @@ class UsersAdminOrganizationsList(BaseSubList):
postable = False postable = False
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
user = User.objects.get(pk=self.kwargs['pk']) user = User.objects.get(pk=self.kwargs['pk'])
#if not UserHelper.can_user_administrate(self.request.user, user, None): #if not UserHelper.can_user_administrate(self.request.user, user, None):
if not check_user_access(self.request.user, User, 'change', user, None): if not check_user_access(self.request.user, User, 'change', user, None):
@ -593,7 +593,7 @@ class CredentialsList(BaseList):
permission_classes = (CustomRbac,) permission_classes = (CustomRbac,)
postable = False postable = False
def _get_queryset(self): def get_queryset(self):
return get_user_queryset(self.request.user, self.model) return get_user_queryset(self.request.user, self.model)
class CredentialsDetail(BaseDetail): class CredentialsDetail(BaseDetail):
@ -629,7 +629,7 @@ class InventoryList(BaseList):
).distinct() ).distinct()
return admin_of | has_user_perms | has_team_perms 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 ''' ''' I can see inventory when I'm a superuser, an org admin of the inventory, or I have permissions on it '''
base = Inventory.objects base = Inventory.objects
return self._filter_queryset(base) return self._filter_queryset(base)
@ -647,7 +647,7 @@ class HostsList(BaseList):
permission_classes = (CustomRbac,) permission_classes = (CustomRbac,)
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
''' '''
I can see hosts when: I can see hosts when:
I'm a superuser, I'm a superuser,
@ -689,7 +689,7 @@ class InventoryHostsList(BaseSubList):
severable = False severable = False
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
inventory = Inventory.objects.get(pk=self.kwargs['pk']) inventory = Inventory.objects.get(pk=self.kwargs['pk'])
base = inventory.hosts base = inventory.hosts
# FIXME: verify that you can can_read permission on the inventory is required # FIXME: verify that you can can_read permission on the inventory is required
@ -702,7 +702,7 @@ class GroupsList(BaseList):
permission_classes = (CustomRbac,) permission_classes = (CustomRbac,)
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
''' '''
I can see groups when: I can see groups when:
I'm a superuser, I'm a superuser,
@ -734,7 +734,7 @@ class GroupsChildrenList(BaseSubList):
inject_primary_key_on_post_as = 'parent' inject_primary_key_on_post_as = 'parent'
filter_fields = ('name',) 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. # 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' inject_primary_key_on_post_as = 'group'
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
parent = Group.objects.get(pk=self.kwargs['pk']) parent = Group.objects.get(pk=self.kwargs['pk'])
@ -812,7 +812,7 @@ class GroupsAllHostsList(BaseSubList):
result = result | self._child_hosts(child) result = result | self._child_hosts(child)
return result return result
def _get_queryset(self): def get_queryset(self):
parent = Group.objects.get(pk=self.kwargs['pk']) parent = Group.objects.get(pk=self.kwargs['pk'])
@ -856,7 +856,7 @@ class InventoryGroupsList(BaseSubList):
severable = False severable = False
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
# FIXME: share code with inventory filter queryset methods (make that a classmethod) # FIXME: share code with inventory filter queryset methods (make that a classmethod)
inventory = Inventory.objects.get(pk=self.kwargs['pk']) inventory = Inventory.objects.get(pk=self.kwargs['pk'])
base = inventory.groups base = inventory.groups
@ -916,7 +916,7 @@ class JobTemplateList(BaseList):
permission_classes = (CustomRbac,) permission_classes = (CustomRbac,)
filter_fields = ('name',) filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
return get_user_queryset(self.request.user, self.model) return get_user_queryset(self.request.user, self.model)
class JobTemplateDetail(BaseDetail): class JobTemplateDetail(BaseDetail):
@ -940,8 +940,8 @@ class JobTemplateJobList(BaseSubList):
severable = False severable = False
#filter_fields = ('name',) #filter_fields = ('name',)
def _get_queryset(self): def get_queryset(self):
# FIxME: Verify read permission on the job template. # FIXME: Verify read permission on the job template.
job_template = get_object_or_404(JobTemplate, pk=self.kwargs['pk']) job_template = get_object_or_404(JobTemplate, pk=self.kwargs['pk'])
return job_template.jobs return job_template.jobs
@ -951,7 +951,7 @@ class JobList(BaseList):
serializer_class = JobSerializer serializer_class = JobSerializer
permission_classes = (CustomRbac,) permission_classes = (CustomRbac,)
def _get_queryset(self): def get_queryset(self):
return self.model.objects.all() # FIXME return self.model.objects.all() # FIXME
class JobDetail(BaseDetail): class JobDetail(BaseDetail):
@ -1012,20 +1012,45 @@ class JobCancel(generics.RetrieveAPIView):
else: else:
return Response(status=405) return Response(status=405)
class JobHostsList(BaseSubList): class HostJobHostSummaryList(generics.ListAPIView):
pass
class JobsSuccessfulHostsList(BaseSubList): model = JobHostSummary
pass serializer_class = JobHostSummarySerializer
permission_classes = (CustomRbac,)
parent_model = Host
relationship = 'job_host_summaries'
class JobsChangedHostsList(BaseSubList): def get_name(self):
pass return 'Job Host Summary List'
class JobsFailedHostsList(BaseSubList): def get_queryset(self):
pass # 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): class JobJobHostSummaryList(generics.ListAPIView):
pass
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): class JobEventList(BaseList):
@ -1033,10 +1058,10 @@ class JobEventList(BaseList):
serializer_class = JobEventSerializer serializer_class = JobEventSerializer
permission_classes = (CustomRbac,) permission_classes = (CustomRbac,)
def _get_queryset(self): def get_queryset(self):
return self.model.objects.all() # FIXME return self.model.objects.all() # FIXME
class JobEventDetail(BaseDetail): class JobEventDetail(generics.RetrieveAPIView):
model = JobEvent model = JobEvent
serializer_class = JobEventSerializer serializer_class = JobEventSerializer
@ -1052,7 +1077,7 @@ class JobJobEventList(BaseSubList):
postable = False postable = False
severable = False severable = False
def _get_queryset(self): def get_queryset(self):
job = get_object_or_404(Job, pk=self.kwargs['pk']) job = get_object_or_404(Job, pk=self.kwargs['pk'])
# FIXME: Verify read permission on the job. # FIXME: Verify read permission on the job.
return job.job_events return job.job_events
@ -1067,7 +1092,7 @@ class HostJobEventList(BaseSubList):
postable = False postable = False
severable = False severable = False
def _get_queryset(self): def get_queryset(self):
host = get_object_or_404(Host, pk=self.kwargs['pk']) host = get_object_or_404(Host, pk=self.kwargs['pk'])
# FIXME: Verify read permission on the host. # FIXME: Verify read permission on the host.
return host.job_events return host.job_events