mirror of
https://github.com/ansible/awx.git
synced 2026-05-23 08:37:48 -02:30
Added job_events and job_host_summaries for groups.
This commit is contained in:
@@ -255,6 +255,21 @@ class Group(CommonModelNameNotUnique):
|
|||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('main:groups_detail', args=(self.pk,))
|
return reverse('main:groups_detail', args=(self.pk,))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def all_hosts(self):
|
||||||
|
qs = self.hosts.distinct()
|
||||||
|
for group in self.children.exclude(pk=self.pk):
|
||||||
|
qs = qs | group.all_hosts
|
||||||
|
return qs
|
||||||
|
|
||||||
|
@property
|
||||||
|
def job_host_summaries(self):
|
||||||
|
return JobHostSummary.objects.filter(host__in=self.all_hosts)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def job_events(self):
|
||||||
|
return JobEvent.objects.filter(host__in=self.all_hosts)
|
||||||
|
|
||||||
# FIXME: audit nullables
|
# FIXME: audit nullables
|
||||||
# FIXME: audit cascades
|
# FIXME: audit cascades
|
||||||
|
|
||||||
|
|||||||
@@ -230,6 +230,8 @@ class GroupSerializer(BaseSerializer):
|
|||||||
children = reverse('main:groups_children_list', args=(obj.pk,)),
|
children = reverse('main:groups_children_list', args=(obj.pk,)),
|
||||||
all_hosts = reverse('main:groups_all_hosts_list', args=(obj.pk,)),
|
all_hosts = reverse('main:groups_all_hosts_list', 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:group_job_event_list', args=(obj.pk,)),
|
||||||
|
job_host_summaries = reverse('main:group_job_host_summary_list', args=(obj.pk,)),
|
||||||
))
|
))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@@ -443,8 +445,8 @@ class JobEventSerializer(BaseSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = JobEvent
|
model = JobEvent
|
||||||
fields = ('id', 'url', 'job', 'event', 'event_data', 'failed', 'host',
|
fields = ('id', 'url', 'created', 'job', 'event', 'event_data',
|
||||||
'related', 'summary_fields')
|
'failed', 'host', '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)
|
||||||
|
|||||||
@@ -908,6 +908,16 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.TransactionTestCase):
|
|||||||
self.check_pagination_and_size(response, qs.count())
|
self.check_pagination_and_size(response, qs.count())
|
||||||
self.check_list_ids(response, qs)
|
self.check_list_ids(response, qs)
|
||||||
|
|
||||||
|
# Test job event list for groups.
|
||||||
|
for group in self.inv_ops_east.groups.all():
|
||||||
|
url = reverse('main:group_job_event_list', args=(group.pk,))
|
||||||
|
with self.current_user(self.user_sue):
|
||||||
|
response = self.get(url)
|
||||||
|
qs = group.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.
|
# Test global job event list.
|
||||||
url = reverse('main:job_event_list')
|
url = reverse('main:job_event_list')
|
||||||
with self.current_user(self.user_sue):
|
with self.current_user(self.user_sue):
|
||||||
@@ -946,3 +956,13 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.TransactionTestCase):
|
|||||||
self.assertTrue(qs.count())
|
self.assertTrue(qs.count())
|
||||||
self.check_pagination_and_size(response, qs.count())
|
self.check_pagination_and_size(response, qs.count())
|
||||||
self.check_list_ids(response, qs)
|
self.check_list_ids(response, qs)
|
||||||
|
|
||||||
|
# Test job host summaries for groups.
|
||||||
|
for group in self.inv_ops_east.groups.all():
|
||||||
|
url = reverse('main:group_job_host_summary_list', args=(group.pk,))
|
||||||
|
with self.current_user(self.user_sue):
|
||||||
|
response = self.get(url)
|
||||||
|
qs = group.job_host_summaries.all()
|
||||||
|
self.assertTrue(qs.count())
|
||||||
|
self.check_pagination_and_size(response, qs.count())
|
||||||
|
self.check_list_ids(response, qs)
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ groups_urls = patterns('lib.main.views',
|
|||||||
url(r'^(?P<pk>[0-9]+)/hosts/$', 'groups_hosts_list'),
|
url(r'^(?P<pk>[0-9]+)/hosts/$', 'groups_hosts_list'),
|
||||||
url(r'^(?P<pk>[0-9]+)/all_hosts/$', 'groups_all_hosts_list'),
|
url(r'^(?P<pk>[0-9]+)/all_hosts/$', 'groups_all_hosts_list'),
|
||||||
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'groups_variable_detail'),
|
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'groups_variable_detail'),
|
||||||
|
url(r'^(?P<pk>[0-9]+)/job_events/$', 'group_job_event_list'),
|
||||||
|
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'group_job_host_summary_list'),
|
||||||
)
|
)
|
||||||
|
|
||||||
variable_data_urls = patterns('lib.main.views',
|
variable_data_urls = patterns('lib.main.views',
|
||||||
|
|||||||
@@ -799,26 +799,13 @@ class GroupsAllHostsList(BaseSubList):
|
|||||||
relationship = 'hosts'
|
relationship = 'hosts'
|
||||||
filter_fields = ('name',)
|
filter_fields = ('name',)
|
||||||
|
|
||||||
def _child_hosts(self, parent):
|
|
||||||
# TODO: should probably be a method on the model
|
|
||||||
result = parent.hosts.distinct()
|
|
||||||
if parent.children.count() == 0:
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
for child in parent.children.all():
|
|
||||||
if child == parent:
|
|
||||||
# shouldn't happen, but be prepared in case DB is weird
|
|
||||||
continue
|
|
||||||
result = result | self._child_hosts(child)
|
|
||||||
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'])
|
||||||
|
|
||||||
# FIXME: verify read permissions on this object are still required at a higher level
|
# FIXME: verify read permissions on this object are still required at a higher level
|
||||||
|
|
||||||
base = self._child_hosts(parent)
|
base = parent.all_hosts
|
||||||
|
|
||||||
if self.request.user.is_superuser:
|
if self.request.user.is_superuser:
|
||||||
return base.all()
|
return base.all()
|
||||||
@@ -1012,37 +999,33 @@ class JobCancel(generics.RetrieveAPIView):
|
|||||||
else:
|
else:
|
||||||
return Response(status=405)
|
return Response(status=405)
|
||||||
|
|
||||||
class HostJobHostSummaryList(generics.ListAPIView):
|
class BaseJobHostSummaryList(generics.ListAPIView):
|
||||||
|
|
||||||
model = JobHostSummary
|
model = JobHostSummary
|
||||||
serializer_class = JobHostSummarySerializer
|
serializer_class = JobHostSummarySerializer
|
||||||
permission_classes = (CustomRbac,)
|
permission_classes = (CustomRbac,)
|
||||||
|
parent_model = None # Subclasses must define this attribute.
|
||||||
|
relationship = 'job_host_summaries'
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
return 'Job Host Summary List'
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
# FIXME: Verify read permission on the parent object and job.
|
||||||
|
parent_obj = get_object_or_404(self.parent_model, pk=self.kwargs['pk'])
|
||||||
|
return getattr(parent_obj, self.relationship)
|
||||||
|
|
||||||
|
class HostJobHostSummaryList(BaseJobHostSummaryList):
|
||||||
|
|
||||||
parent_model = Host
|
parent_model = Host
|
||||||
relationship = 'job_host_summaries'
|
|
||||||
|
|
||||||
def get_name(self):
|
class GroupJobHostSummaryList(BaseJobHostSummaryList):
|
||||||
return 'Job Host Summary List'
|
|
||||||
|
|
||||||
def get_queryset(self):
|
parent_model = Group
|
||||||
# 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 JobJobHostSummaryList(generics.ListAPIView):
|
class JobJobHostSummaryList(BaseJobHostSummaryList):
|
||||||
|
|
||||||
model = JobHostSummary
|
|
||||||
serializer_class = JobHostSummarySerializer
|
|
||||||
permission_classes = (CustomRbac,)
|
|
||||||
parent_model = Job
|
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.
|
# FIXME: Subclasses of XJobHostSummaryList for failed/successful/etc.
|
||||||
|
|
||||||
@@ -1067,36 +1050,30 @@ class JobEventDetail(generics.RetrieveAPIView):
|
|||||||
serializer_class = JobEventSerializer
|
serializer_class = JobEventSerializer
|
||||||
permission_classes = (CustomRbac,)
|
permission_classes = (CustomRbac,)
|
||||||
|
|
||||||
class JobJobEventList(BaseSubList):
|
class BaseJobEventList(generics.ListAPIView):
|
||||||
|
|
||||||
model = JobEvent
|
model = JobEvent
|
||||||
serializer_class = JobEventSerializer
|
serializer_class = JobEventSerializer
|
||||||
permission_classes = (CustomRbac,)
|
permission_classes = (CustomRbac,)
|
||||||
parent_model = Job
|
parent_model = None # Subclasses must define this attribute.
|
||||||
relationship = 'job_events'
|
relationship = 'job_events'
|
||||||
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 parent object and job.
|
||||||
# FIXME: Verify read permission on the job.
|
parent_obj = get_object_or_404(self.parent_model, pk=self.kwargs['pk'])
|
||||||
return job.job_events
|
return getattr(parent_obj, self.relationship)
|
||||||
|
|
||||||
class HostJobEventList(BaseSubList):
|
class HostJobEventList(BaseJobEventList):
|
||||||
|
|
||||||
model = JobEvent
|
|
||||||
serializer_class = JobEventSerializer
|
|
||||||
permission_classes = (CustomRbac,)
|
|
||||||
parent_model = Host
|
parent_model = Host
|
||||||
relationship = 'job_events'
|
|
||||||
postable = False
|
|
||||||
severable = False
|
|
||||||
|
|
||||||
def get_queryset(self):
|
class GroupJobEventList(BaseJobEventList):
|
||||||
host = get_object_or_404(Host, pk=self.kwargs['pk'])
|
|
||||||
# FIXME: Verify read permission on the host.
|
|
||||||
return host.job_events
|
|
||||||
|
|
||||||
|
parent_model = Group
|
||||||
|
|
||||||
|
class JobJobEventList(BaseJobEventList):
|
||||||
|
|
||||||
|
parent_model = Job
|
||||||
|
|
||||||
# Create view functions for all of the class-based views to simplify inclusion
|
# Create view functions for all of the class-based views to simplify inclusion
|
||||||
# in URL patterns and reverse URL lookups, converting CamelCase names to
|
# in URL patterns and reverse URL lookups, converting CamelCase names to
|
||||||
|
|||||||
Reference in New Issue
Block a user