Skip to content

Commit

Permalink
Additional /access-active-resource/ endpoints for all or selected groups
Browse files Browse the repository at this point in the history
jpnavarro committed Nov 6, 2024
1 parent 2ba0244 commit 2a7bd1b
Showing 4 changed files with 85 additions and 42 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
v3.41.0 2024-11-06 JP
- Additional /access-active-resource/ endpoints for all or selected groups

v3.40.0 2024-11-05 JP
- Change CiderGroups pk to new group_id field, info_groupid becomes a normal index field
- Recreate CiderGroups and CiderFeatures models, requires out of band table drops and django_migrations cleanup
2 changes: 1 addition & 1 deletion Operations_Warehouse_Django/cider/serializers.py
Original file line number Diff line number Diff line change
@@ -559,7 +559,7 @@ class Meta:
model = CiderGroups
fields = ('__all__')

class CiderCatalog_v1_ACCESSActiveGroups_Serializer(serializers.ModelSerializer):
class CiderACCESSActiveGroups_v1_List_Serializer(serializers.ModelSerializer):
rollup_info_resourceids = serializers.SerializerMethodField()
rollup_feature_ids = serializers.SerializerMethodField()
rollup_organization_ids = serializers.SerializerMethodField()
6 changes: 4 additions & 2 deletions Operations_Warehouse_Django/cider/urls.py
Original file line number Diff line number Diff line change
@@ -20,6 +20,8 @@
path(r'v1/groups/info_groupid/<str:info_groupid>/', CiderGroups_v1_Detail.as_view(), name='cider-group-info-groupid-v1'),
path(r'v1/groups/group_type/<str:group_type>/', CiderGroups_v1_List.as_view(), name='cider-group-type-v1'),
path(r'v1/groups/info_resourceid/<str:info_resourceid>/', CiderGroups_v1_List.as_view(), name='cider-group-infoid-v1'),
path(r'v1/access-active-groups/type/<str:group_type>/', CiderCatalog_v1_ACCESSActiveGroups.as_view(), name='cider-accessactivegroups-bytype-v1'),
# path(r'v1/access-active-group/id/<str:info_groupid>/', CiderCatalog_v1_ACCESSActiveGroups.as_view(), name='cider-accessactivegroups-byid-v1'),
path(r'v1/access-active-groups/', CiderACCESSActiveGroups_v1_List.as_view(), name='cider-accessactivegroups-v1'),
path(r'v1/access-active-groups/type/<str:group_type>/', CiderACCESSActiveGroups_v1_List.as_view(), name='cider-accessactivegroups-bytype-v1'),
path(r'v1/access-active-groups/group_id/<str:group_id>/', CiderACCESSActiveGroups_v1_List.as_view(), name='cider-accessactivegroups-byid-v1'),
path(r'v1/access-active-groups/info_groupid/<str:info_groupid>/', CiderACCESSActiveGroups_v1_List.as_view(), name='cider-accessactivegroups-byinfoid-v1'),
]
116 changes: 77 additions & 39 deletions Operations_Warehouse_Django/cider/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
from django.db.models import Q
from django.shortcuts import render
from drf_spectacular.utils import OpenApiParameter, extend_schema
from itertools import chain
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from rest_framework.renderers import JSONRenderer, TemplateHTMLRenderer
from rest_framework.response import Response
from rest_framework import status
from rest_framework.generics import GenericAPIView

@@ -281,86 +278,127 @@ def get(self, request, format=None, **kwargs):
serializer = CiderGroups_Serializer(items, context={'request': request}, many=True)
return MyAPIResponse({'results': serializer.data})

class CiderCatalog_v1_ACCESSActiveGroups(GenericAPIView):
# Design:
# 1st get all features
# 2nd get all ACCESS active resources
# 3rd get all or select groups
# counting which resources are referenced in selected groups
# 4th count referenced orgs, features, and feature groups for referenced resources
class CiderACCESSActiveGroups_v1_List(GenericAPIView):
'''
Catalog summary of ACCESS Active Compute and Storage resource groups of a group type
ACCESS Active Compute and Storage Resource Groups
'''
permission_classes = (IsAuthenticatedOrReadOnly,)
renderer_classes = (JSONRenderer,)
serializer_class = CiderCatalog_v1_ACCESSActiveGroups_Serializer
serializer_class = CiderACCESSActiveGroups_v1_List_Serializer
def get(self, request, format=None, **kwargs):
if not self.kwargs.get('group_type') and not self.kwargs.get('info_groupid'):
raise MyAPIException(code=status.HTTP_400_BAD_REQUEST, detail='Missing query parameter')
# Default to all groups
# if not self.kwargs.get('group_type') and not self.kwargs.get('group_id') and not self.kwargs.get('info_groupid'):
# raise MyAPIException(code=status.HTTP_400_BAD_REQUEST, detail='Missing selection parameter')

all_feature_categories = {}
all_features = {}
# The CiderFeatures model contains Feature Categories, and associated features in the features json field
for feature_category in CiderFeatures.objects.all():
# Key by feature_category_name which are unique and are what resources reference
all_feature_categories[feature_category.feature_category_name] = {
'counter': 0, # For counting references
# Key by id which are unique
all_feature_categories[feature_category.feature_category_id] = {
'counter': 0, # For counting references
'feature_category_id': feature_category.feature_category_id,
'feature_category_name': feature_category.feature_category_name,
'feature_category_description': feature_category.feature_category_description
}
for feature in feature_category.features:
# Key by id which are unique and are what resources reference
all_features[feature['id']] = {
'counter': 0, # For counting references
'counter': 0, # For counting references
'id': feature['id'],
'name': feature['name'],
'description': feature['description'],
'feature_category_id': feature_category.feature_category_id
}

active_resinfo = {}
active_orginfo = {}
active_resources = {}
active_orgs = {}
resources = CiderInfrastructure_ActiveAllocated_Filter(affiliation='ACCESS', result='OBJECTS')
for item in resources:
iid = item.info_resourceid
active_resinfo[iid] = {'org_ids': [], 'feature_ids': []} # Initialize
if isinstance(item.other_attributes.get('organizations'), list):
for o in item.other_attributes['organizations']:
active_resinfo[iid]['org_ids'].append(o['organization_id'])
if o['organization_id'] not in active_orginfo:
active_orginfo[o['organization_id']] = o
if isinstance(item.other_attributes.get('features'), list):
for f in item.other_attributes['features']:
active_resinfo[iid]['feature_ids'].append(f['id'])
if f['feature_category'] in all_feature_categories:
all_feature_categories[f['feature_category']]['counter'] += 1 # Increment feature category used
if f['id'] in all_features:
all_features[f['id']]['counter'] += 1 # Increment feature used
for resource in resources:
rid = resource.info_resourceid
active_resources[rid] = {
'counter': 0, # For counting references in selected groups
'info_resourceid': rid,
'org_ids': [],
'feature_ids': []
}
if isinstance(resource.other_attributes.get('organizations'), list):
for o in resource.other_attributes['organizations']:
oid = o.get('organization_id')
if not oid:
continue
active_resources[rid]['org_ids'].append(oid)
if oid not in active_orgs:
active_orgs[oid] = o
active_orgs[oid]['counter'] = 0 # For counting references in select group active resources
if isinstance(resource.other_attributes.get('features'), list):
for f in resource.other_attributes['features']:
fid = f.get('id')
if not fid:
continue
if fid not in all_features:
continue
active_resources[rid]['feature_ids'].append(fid) # All resource feature ids

groups = []
groups_extra = {}
if self.kwargs.get('group_type'):
if self.kwargs.get('group_id'):
query = CiderGroups.objects.filter(group_id=self.kwargs['group_id'])
elif self.kwargs.get('info_groupid'):
query = CiderGroups.objects.filter(info_groupid=self.kwargs['info_groupid'])
elif self.kwargs.get('group_type'):
query = CiderGroups.objects.filter(group_types__has_key=self.kwargs['group_type'])
else:
query = CiderGroups.objects.filter(info_groupid=self.kwargs['info_groupid'])
query = CiderGroups.objects.all()
for group in query:
if type(group.info_resourceids) is not list or group.info_resourceids is None:
continue # Ignore group with no resources
active_resources = [grid for grid in group.info_resourceids if grid in active_resinfo]
if not active_resources:
group_active_resources = [grid for grid in group.info_resourceids if grid in active_resources]
if not group_active_resources:
continue # Ignore group with no active resources
og = { # Extra group information to pass and use in the serializer
'rollup_feature_ids': [], # Feature id rollup for active resources in a group
'rollup_org_ids': [], # Organization id rollup for active resources in a group
'rollup_active_info_resourceids': active_resources
'rollup_active_info_resourceids': group_active_resources
}
for ogrid in active_resources:
og['rollup_org_ids'].extend(active_resinfo[ogrid]['org_ids'])
og['rollup_feature_ids'].extend(active_resinfo[ogrid]['feature_ids'])
for grid in group_active_resources:
active_resources[grid]['counter'] += 1 # A reference resource
og['rollup_feature_ids'].extend(active_resources[grid]['feature_ids'])
og['rollup_org_ids'].extend(active_resources[grid]['org_ids'])
og['rollup_feature_ids'] = list(set(chain(og['rollup_feature_ids']))) # Make unique
og['rollup_org_ids'] = list(set(chain(og['rollup_org_ids']))) # Make unique
groups_extra[group.info_groupid] = og
groups.append(group)

serializer = CiderCatalog_v1_ACCESSActiveGroups_Serializer(groups, context={'request': request, 'groups_extra': groups_extra}, many=True)
for ares in active_resources.values():
if ares['counter'] == 0: # Not a referenced resource
continue
rorgs = ares.get('org_ids')
if rorgs:
for oid in rorgs:
active_orgs[oid]['counter'] += 1
rfeatures = ares.get('feature_ids')
if rfeatures:
for fid in rfeatures:
all_features[fid]['counter'] += 1 # Increment feature used
fcid = all_features[fid].get('feature_category_id') # Lookup the feature category id
if not fcid:
continue
if fcid not in all_feature_categories:
continue
all_feature_categories[fcid]['counter'] += 1 # Increment feature category used

serializer = CiderACCESSActiveGroups_v1_List_Serializer(groups, context={'request': request, 'groups_extra': groups_extra}, many=True)
active_orgdata = [ {'organization_id': a['organization_id'],
'organization_name': a['organization_name'],
'organization_logo_url': a['organization_logo_url']}
for a in active_orginfo.values()]
for a in active_orgs.values() if a['counter'] > 0]
active_categories = [ { 'feature_category_id': f['feature_category_id'],
'feature_category_name': f['feature_category_name'],
'feature_category_description': f['feature_category_description']}

0 comments on commit 2a7bd1b

Please sign in to comment.