From 79ef9e5ed5d515709e0579195c4760f3fa9e7631 Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Thu, 8 May 2014 15:49:49 -0400 Subject: [PATCH] Implement smart recursive deleting on certain inventory resources --- awx/api/generics.py | 5 ++++- awx/api/urls.py | 2 ++ awx/api/views.py | 23 +++++++++++++++++++++++ awx/main/models/inventory.py | 27 +++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/awx/api/generics.py b/awx/api/generics.py index 5efd34e9f3..0735f768e9 100644 --- a/awx/api/generics.py +++ b/awx/api/generics.py @@ -30,7 +30,7 @@ from awx.main.utils import * __all__ = ['APIView', 'GenericAPIView', 'ListAPIView', 'SimpleListAPIView', 'ListCreateAPIView', 'SubListAPIView', 'SubListCreateAPIView', 'RetrieveAPIView', 'RetrieveUpdateAPIView', - 'RetrieveDestroyAPIView', 'RetrieveUpdateDestroyAPIView'] + 'RetrieveDestroyAPIView', 'RetrieveUpdateDestroyAPIView', 'DestroyAPIView'] logger = logging.getLogger('awx.api.generics') @@ -466,3 +466,6 @@ class RetrieveDestroyAPIView(RetrieveAPIView, generics.RetrieveDestroyAPIView): class RetrieveUpdateDestroyAPIView(RetrieveUpdateAPIView, RetrieveDestroyAPIView): pass + +class DestroyAPIView(GenericAPIView, generics.DestroyAPIView): + pass diff --git a/awx/api/urls.py b/awx/api/urls.py index dd83eb98d8..fe38d61019 100644 --- a/awx/api/urls.py +++ b/awx/api/urls.py @@ -65,6 +65,7 @@ inventory_urls = patterns('awx.api.views', url(r'^(?P[0-9]+)/$', 'inventory_detail'), url(r'^(?P[0-9]+)/hosts/$', 'inventory_hosts_list'), url(r'^(?P[0-9]+)/groups/$', 'inventory_groups_list'), + url(r'^(?P[0-9]+)/groups/(?P[0-9]+)/$', 'inventory_root_group_remove'), url(r'^(?P[0-9]+)/root_groups/$', 'inventory_root_groups_list'), url(r'^(?P[0-9]+)/variable_data/$', 'inventory_variable_data'), url(r'^(?P[0-9]+)/script/$', 'inventory_script_view'), @@ -89,6 +90,7 @@ group_urls = patterns('awx.api.views', url(r'^$', 'group_list'), url(r'^(?P[0-9]+)/$', 'group_detail'), url(r'^(?P[0-9]+)/children/$', 'group_children_list'), + url(r'^(?P[0-9]+)/children/(?P[0-9]+)/$', 'group_children_remove'), url(r'^(?P[0-9]+)/hosts/$', 'group_hosts_list'), url(r'^(?P[0-9]+)/all_hosts/$', 'group_all_hosts_list'), url(r'^(?P[0-9]+)/variable_data/$', 'group_variable_data'), diff --git a/awx/api/views.py b/awx/api/views.py index b8ec380884..a2a62b7cb9 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -788,6 +788,18 @@ class GroupChildrenList(SubListCreateAPIView): return Response(status=status.HTTP_204_NO_CONTENT) +class GroupChildrenRemove(DestroyAPIView): + + model = Group + serializer_class = GroupSerializer + view_name = 'Remove a subgroup recursively' + + def destroy(self, request, *args, **kwargs): + parent_group = self.get_object() + group = Group.objects.get(id=kwargs['subgroup_pk']) + group.mark_inactive_recursive(parent_group) + return Response() + class GroupPotentialChildrenList(SubListAPIView): model = Group @@ -863,6 +875,17 @@ class InventoryGroupsList(SubListCreateAPIView): relationship = 'groups' parent_key = 'inventory' +class InventoryRootGroupRemove(DestroyAPIView): + + model = Group + serializer_class = GroupSerializer + view_name = 'Inventory Group Subgroup' + + def destroy(self, request, *args, **kwargs): + group = Group.objects.get(id=kwargs['group_pk']) + group.mark_inactive_recursive() + return Response() + class InventoryRootGroupsList(SubListCreateAPIView): model = Group diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 0df74d9509..431d006dcf 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -361,6 +361,33 @@ class Group(CommonModelNameNotUnique): def get_absolute_url(self): return reverse('api:group_detail', args=(self.pk,)) + def mark_inactive_recursive(self, parent=None): + def mark_actual(parent=parent): + linked_children = [(parent, self)] + [(self, child) for child in self.children.all()] + marked_groups = [] + marked_hosts = [] + for subgroup in linked_children: + parent, group = subgroup + if parent is not None: + group.parents.remove(parent) + if group.parents.count() > 0: + continue + for host in group.hosts.all(): + host.groups.remove(group) + # Remove inventory source + if host.groups.count() < 1: + marked_hosts.append(host) + for childgroup in group.children.all(): + linked_children.append((group, childgroup)) + marked_groups.append(group) + for group in marked_groups: + group.mark_inactive() + for host in marked_hosts: + host.mark_inactive() + with ignore_inventory_computed_fields(): + mark_actual() + self.inventory.update_computed_fields() + def mark_inactive(self, save=True, recompute=True): ''' When marking groups inactive, remove all associations to related