mirror of
https://github.com/ansible/awx.git
synced 2026-01-29 15:24:42 -03:30
Added /api/v1/groups/N/hosts and /api/v1/groups/N/all_hosts/
This commit is contained in:
parent
27ac9a206e
commit
5e6ad5a244
6
TODO.md
6
TODO.md
@ -78,3 +78,9 @@ QUESTIONS
|
||||
* if creating a project, do we want to have an appliance style path for them, like
|
||||
/storage/projects/GUID ??? may want to keep somewhere else ?
|
||||
|
||||
MISC
|
||||
----
|
||||
|
||||
when associating inventory objects, objects should share common inventory records (user_can_attach method should check)
|
||||
|
||||
|
||||
|
||||
@ -123,6 +123,11 @@ class BaseSubList(BaseList):
|
||||
|
||||
# now make sure we could have already attached the two together. If we could not have, raise an exception
|
||||
# such that the transaction does not commit.
|
||||
|
||||
if main == obj:
|
||||
# no attaching to yourself
|
||||
raise PermissionDenied()
|
||||
|
||||
if self.__class__.parent_model != User:
|
||||
if not self.__class__.parent_model.can_user_attach(request.user, main, obj, self.__class__.relationship):
|
||||
raise PermissionDenied()
|
||||
|
||||
@ -212,6 +212,7 @@ class InventoryTest(BaseTest):
|
||||
got = self.get(url5, expect=200, auth=self.get_other_credentials())
|
||||
self.assertEquals(got['count'], 3)
|
||||
|
||||
|
||||
##################################################
|
||||
# GROUPS->inventories POST via subcollection
|
||||
|
||||
@ -310,6 +311,38 @@ class InventoryTest(BaseTest):
|
||||
put = self.put(vdata1_url, data=vars_c, expect=200, auth=self.get_normal_credentials())
|
||||
self.assertEquals(put, vars_c)
|
||||
|
||||
|
||||
####################################################
|
||||
# ADDING HOSTS TO GROUPS
|
||||
|
||||
groups = Group.objects.all()
|
||||
hosts = Host.objects.all()
|
||||
groups[0].hosts.add(Host.objects.get(pk=1))
|
||||
groups[0].hosts.add(Host.objects.get(pk=3))
|
||||
groups[0].save()
|
||||
|
||||
# access
|
||||
url1 = '/api/v1/groups/1/hosts/'
|
||||
data = self.get(url1, expect=200, auth=self.get_normal_credentials())
|
||||
self.assertEquals(data['count'], 2)
|
||||
self.assertEquals(data['results'][0]['id'], 1)
|
||||
self.assertEquals(data['results'][1]['id'], 3)
|
||||
|
||||
# addition
|
||||
got = self.get('/api/v1/hosts/2/', expect=200, auth=self.get_normal_credentials())
|
||||
self.assertEquals(got['id'], 2)
|
||||
posted = self.post('/api/v1/groups/1/hosts/', data=got, expect=204, auth=self.get_normal_credentials())
|
||||
data = self.get(url1, expect=200, auth=self.get_normal_credentials())
|
||||
self.assertEquals(data['count'], 3)
|
||||
self.assertEquals(data['results'][1]['id'], 2)
|
||||
|
||||
# removal
|
||||
got['disassociate'] = 1
|
||||
posted = self.post('/api/v1/groups/1/hosts/', data=got, expect=204, auth=self.get_normal_credentials())
|
||||
data = self.get(url1, expect=200, auth=self.get_normal_credentials())
|
||||
self.assertEquals(data['count'], 2)
|
||||
self.assertEquals(data['results'][1]['id'], 3)
|
||||
|
||||
####################################################
|
||||
# SUBGROUPS
|
||||
|
||||
@ -329,6 +362,12 @@ class InventoryTest(BaseTest):
|
||||
permission_type = PERM_INVENTORY_WRITE
|
||||
)
|
||||
|
||||
# data used for testing listing all hosts that are transitive members of a group
|
||||
g2 = Group.objects.get(pk=2)
|
||||
nh = Host.objects.create(name='newhost.example.com', inventory=inv, created_by=User.objects.get(pk=1))
|
||||
g2.hosts.add(nh)
|
||||
g2.save()
|
||||
|
||||
# a super user can set subgroups
|
||||
subgroups_url = '/api/v1/groups/1/children/'
|
||||
child_url = '/api/v1/groups/2/'
|
||||
@ -355,6 +394,15 @@ class InventoryTest(BaseTest):
|
||||
self.post(subgroups_url3, data=got, expect=204, auth=self.get_other_credentials())
|
||||
checked = self.get(subgroups_url3, expect=200, auth=self.get_normal_credentials())
|
||||
self.assertEqual(checked['count'], 1)
|
||||
|
||||
# slight detour
|
||||
# can see all hosts under a group, even if it has subgroups
|
||||
# this URL is NOT postable
|
||||
all_hosts = '/api/v1/groups/1/all_hosts/'
|
||||
self.assertEqual(Group.objects.get(pk=1).hosts.count(), 2)
|
||||
data = self.get(all_hosts, expect=200, auth=self.get_normal_credentials())
|
||||
self.post(all_hosts, data=dict(id=123456, msg='spam'), expect=405, auth=self.get_normal_credentials())
|
||||
self.assertEquals(data['count'], 3)
|
||||
|
||||
# now post it back to remove it, by adding the disassociate bit
|
||||
result = checked['results'][0]
|
||||
|
||||
@ -578,6 +578,83 @@ class GroupsChildrenList(BaseSubList):
|
||||
).distinct()
|
||||
return admin_of | has_user_perms | has_team_perms
|
||||
|
||||
class GroupsHostsList(BaseSubList):
|
||||
''' the list of hosts directly below a group '''
|
||||
|
||||
model = Host
|
||||
serializer_class = HostSerializer
|
||||
permission_classes = (CustomRbac,)
|
||||
parent_model = Group
|
||||
relationship = 'hosts'
|
||||
postable = True
|
||||
inject_primary_key_on_post_as = 'group'
|
||||
|
||||
def _get_queryset(self):
|
||||
|
||||
parent = Group.objects.get(pk=self.kwargs['pk'])
|
||||
|
||||
# FIXME: verify read permissions on this object are still required at a higher level
|
||||
|
||||
base = parent.hosts
|
||||
if self.request.user.is_superuser:
|
||||
return base.all()
|
||||
admin_of = base.filter(inventory__organization__admins__in = [ self.request.user ]).distinct()
|
||||
has_user_perms = base.filter(
|
||||
inventory__permissions__user__in = [ self.request.user ],
|
||||
inventory__permissions__permission_type__in = PERMISSION_TYPES_ALLOWING_INVENTORY_READ,
|
||||
).distinct()
|
||||
has_team_perms = base.filter(
|
||||
inventory__permissions__team__in = self.request.user.teams.all(),
|
||||
inventory__permissions__permission_type__in = PERMISSION_TYPES_ALLOWING_INVENTORY_READ,
|
||||
).distinct()
|
||||
return admin_of | has_user_perms | has_team_perms
|
||||
|
||||
|
||||
class GroupsAllHostsList(BaseSubList):
|
||||
''' the list of all hosts below a group, even including subgroups '''
|
||||
|
||||
model = Host
|
||||
serializer_class = HostSerializer
|
||||
permission_classes = (CustomRbac,)
|
||||
parent_model = Group
|
||||
relationship = 'hosts'
|
||||
|
||||
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):
|
||||
|
||||
parent = Group.objects.get(pk=self.kwargs['pk'])
|
||||
|
||||
# FIXME: verify read permissions on this object are still required at a higher level
|
||||
|
||||
base = self._child_hosts(parent)
|
||||
|
||||
if self.request.user.is_superuser:
|
||||
return base.all()
|
||||
|
||||
admin_of = base.filter(inventory__organization__admins__in = [ self.request.user ]).distinct()
|
||||
has_user_perms = base.filter(
|
||||
inventory__permissions__user__in = [ self.request.user ],
|
||||
inventory__permissions__permission_type__in = PERMISSION_TYPES_ALLOWING_INVENTORY_READ,
|
||||
).distinct()
|
||||
has_team_perms = base.filter(
|
||||
inventory__permissions__team__in = self.request.user.teams.all(),
|
||||
inventory__permissions__permission_type__in = PERMISSION_TYPES_ALLOWING_INVENTORY_READ,
|
||||
).distinct()
|
||||
return admin_of | has_user_perms | has_team_perms
|
||||
|
||||
|
||||
class GroupsDetail(BaseDetail):
|
||||
|
||||
model = Group
|
||||
|
||||
@ -66,6 +66,8 @@ views_GroupsList = views.GroupsList.as_view()
|
||||
views_GroupsDetail = views.GroupsDetail.as_view()
|
||||
views_GroupsVariableDetail = views.GroupsVariableDetail.as_view()
|
||||
views_GroupsChildrenList = views.GroupsChildrenList.as_view()
|
||||
views_GroupsAllHostsList = views.GroupsAllHostsList.as_view()
|
||||
views_GroupsHostsList = views.GroupsHostsList.as_view()
|
||||
|
||||
# host service
|
||||
views_HostsList = views.HostsList.as_view()
|
||||
@ -147,6 +149,8 @@ urlpatterns = patterns('',
|
||||
url(r'^api/v1/groups/$', views_GroupsList),
|
||||
url(r'^api/v1/groups/(?P<pk>[0-9]+)/$', views_GroupsDetail),
|
||||
url(r'^api/v1/groups/(?P<pk>[0-9]+)/children/$', views_GroupsChildrenList),
|
||||
url(r'^api/v1/groups/(?P<pk>[0-9]+)/hosts/$', views_GroupsHostsList),
|
||||
url(r'^api/v1/groups/(?P<pk>[0-9]+)/all_hosts/$', views_GroupsAllHostsList),
|
||||
|
||||
# variable data
|
||||
url(r'^api/v1/hosts/(?P<pk>[0-9]+)/variable_data/$', views_HostsVariableDetail),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user