mirror of
https://github.com/GAM-team/GAM.git
synced 2026-07-06 13:51:36 +00:00
resources, buildings and features to resource.py
This commit is contained in:
450
src/gam.py
450
src/gam.py
@@ -75,6 +75,8 @@ import controlflow
|
|||||||
import display
|
import display
|
||||||
import fileutils
|
import fileutils
|
||||||
import gapi.calendar
|
import gapi.calendar
|
||||||
|
import gapi.directory
|
||||||
|
import gapi.directory.resource
|
||||||
import gapi.errors
|
import gapi.errors
|
||||||
import gapi.storage
|
import gapi.storage
|
||||||
import gapi.vault
|
import gapi.vault
|
||||||
@@ -268,8 +270,6 @@ def splitEmailAddress(emailAddress):
|
|||||||
return (emailAddress.lower(), GC_Values[GC_DOMAIN].lower())
|
return (emailAddress.lower(), GC_Values[GC_DOMAIN].lower())
|
||||||
return (emailAddress[:atLoc].lower(), emailAddress[atLoc+1:].lower())
|
return (emailAddress[:atLoc].lower(), emailAddress[atLoc+1:].lower())
|
||||||
|
|
||||||
UID_PATTERN = re.compile(r'u?id: ?(.+)', re.IGNORECASE)
|
|
||||||
|
|
||||||
# Normalize user/group email address/uid
|
# Normalize user/group email address/uid
|
||||||
# uid:12345abc -> 12345abc
|
# uid:12345abc -> 12345abc
|
||||||
# foo -> foo@domain
|
# foo -> foo@domain
|
||||||
@@ -6394,7 +6394,7 @@ def getUserAttributes(i, cd, updateCmd):
|
|||||||
location['area'] = sys.argv[i+1]
|
location['area'] = sys.argv[i+1]
|
||||||
i += 2
|
i += 2
|
||||||
elif myopt in ['building', 'buildingid']:
|
elif myopt in ['building', 'buildingid']:
|
||||||
location['buildingId'] = _getBuildingByNameOrId(cd, sys.argv[i+1])
|
location['buildingId'] = gapi.directory.resources.getBuildingByNameOrId(cd, sys.argv[i+1])
|
||||||
i += 2
|
i += 2
|
||||||
elif myopt in ['desk', 'deskcode']:
|
elif myopt in ['desk', 'deskcode']:
|
||||||
location['deskCode'] = sys.argv[i+1]
|
location['deskCode'] = sys.argv[i+1]
|
||||||
@@ -7601,231 +7601,6 @@ def doCreateOrg():
|
|||||||
parent = body['parentOrgUnitPath']
|
parent = body['parentOrgUnitPath']
|
||||||
gapi.call(cd.orgunits(), 'insert', customerId=GC_Values[GC_CUSTOMER_ID], body=body)
|
gapi.call(cd.orgunits(), 'insert', customerId=GC_Values[GC_CUSTOMER_ID], body=body)
|
||||||
|
|
||||||
def _getBuildingAttributes(args, body={}):
|
|
||||||
i = 0
|
|
||||||
while i < len(args):
|
|
||||||
myarg = args[i].lower().replace('_', '')
|
|
||||||
if myarg == 'id':
|
|
||||||
body['buildingId'] = args[i+1]
|
|
||||||
i += 2
|
|
||||||
elif myarg == 'name':
|
|
||||||
body['buildingName'] = args[i+1]
|
|
||||||
i += 2
|
|
||||||
elif myarg in ['lat', 'latitude']:
|
|
||||||
if 'coordinates' not in body:
|
|
||||||
body['coordinates'] = {}
|
|
||||||
body['coordinates']['latitude'] = args[i+1]
|
|
||||||
i += 2
|
|
||||||
elif myarg in ['long', 'lng', 'longitude']:
|
|
||||||
if 'coordinates' not in body:
|
|
||||||
body['coordinates'] = {}
|
|
||||||
body['coordinates']['longitude'] = args[i+1]
|
|
||||||
i += 2
|
|
||||||
elif myarg == 'description':
|
|
||||||
body['description'] = args[i+1]
|
|
||||||
i += 2
|
|
||||||
elif myarg == 'floors':
|
|
||||||
body['floorNames'] = args[i+1].split(',')
|
|
||||||
i += 2
|
|
||||||
else:
|
|
||||||
controlflow.invalid_argument_exit(myarg, "gam create|update building")
|
|
||||||
return body
|
|
||||||
|
|
||||||
def doCreateBuilding():
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
body = {'floorNames': ['1'],
|
|
||||||
'buildingId': str(uuid.uuid4()),
|
|
||||||
'buildingName': sys.argv[3]}
|
|
||||||
body = _getBuildingAttributes(sys.argv[4:], body)
|
|
||||||
print(f'Creating building {body["buildingId"]}...')
|
|
||||||
gapi.call(cd.resources().buildings(), 'insert',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], body=body)
|
|
||||||
|
|
||||||
def _makeBuildingIdNameMap(cd):
|
|
||||||
buildings = gapi.get_all_pages(cd.resources().buildings(), 'list', 'buildings',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID],
|
|
||||||
fields='nextPageToken,buildings(buildingId,buildingName)')
|
|
||||||
GM_Globals[GM_MAP_BUILDING_ID_TO_NAME] = {}
|
|
||||||
GM_Globals[GM_MAP_BUILDING_NAME_TO_ID] = {}
|
|
||||||
for building in buildings:
|
|
||||||
GM_Globals[GM_MAP_BUILDING_ID_TO_NAME][building['buildingId']] = building['buildingName']
|
|
||||||
GM_Globals[GM_MAP_BUILDING_NAME_TO_ID][building['buildingName']] = building['buildingId']
|
|
||||||
|
|
||||||
def _getBuildingByNameOrId(cd, which_building, minLen=1):
|
|
||||||
if not which_building or (minLen == 0 and which_building in ['id:', 'uid:']):
|
|
||||||
if minLen == 0:
|
|
||||||
return ''
|
|
||||||
controlflow.system_error_exit(3, 'Building id/name is empty')
|
|
||||||
cg = UID_PATTERN.match(which_building)
|
|
||||||
if cg:
|
|
||||||
return cg.group(1)
|
|
||||||
if GM_Globals[GM_MAP_BUILDING_NAME_TO_ID] is None:
|
|
||||||
_makeBuildingIdNameMap(cd)
|
|
||||||
# Exact name match, return ID
|
|
||||||
if which_building in GM_Globals[GM_MAP_BUILDING_NAME_TO_ID]:
|
|
||||||
return GM_Globals[GM_MAP_BUILDING_NAME_TO_ID][which_building]
|
|
||||||
# No exact name match, check for case insensitive name matches
|
|
||||||
which_building_lower = which_building.lower()
|
|
||||||
ci_matches = []
|
|
||||||
for buildingName, buildingId in GM_Globals[GM_MAP_BUILDING_NAME_TO_ID].items():
|
|
||||||
if buildingName.lower() == which_building_lower:
|
|
||||||
ci_matches.append({'buildingName': buildingName, 'buildingId': buildingId})
|
|
||||||
# One match, return ID
|
|
||||||
if len(ci_matches) == 1:
|
|
||||||
return ci_matches[0]['buildingId']
|
|
||||||
# No or multiple name matches, try ID
|
|
||||||
# Exact ID match, return ID
|
|
||||||
if which_building in GM_Globals[GM_MAP_BUILDING_ID_TO_NAME]:
|
|
||||||
return which_building
|
|
||||||
# No exact ID match, check for case insensitive id match
|
|
||||||
for buildingId in GM_Globals[GM_MAP_BUILDING_ID_TO_NAME]:
|
|
||||||
# Match, return ID
|
|
||||||
if buildingId.lower() == which_building_lower:
|
|
||||||
return buildingId
|
|
||||||
# Multiple name matches
|
|
||||||
if len(ci_matches) > 1:
|
|
||||||
message = 'Multiple buildings with same name:\n'
|
|
||||||
for building in ci_matches:
|
|
||||||
message += f' Name:{building["buildingName"]} id:{building["buildingId"]}\n'
|
|
||||||
message += '\nPlease specify building name by exact case or by id.'
|
|
||||||
controlflow.system_error_exit(3, message)
|
|
||||||
# No matches
|
|
||||||
else:
|
|
||||||
controlflow.system_error_exit(3, f'No such building {which_building}')
|
|
||||||
|
|
||||||
def _getBuildingNameById(cd, buildingId):
|
|
||||||
if GM_Globals[GM_MAP_BUILDING_ID_TO_NAME] is None:
|
|
||||||
_makeBuildingIdNameMap(cd)
|
|
||||||
return GM_Globals[GM_MAP_BUILDING_ID_TO_NAME].get(buildingId, 'UNKNOWN')
|
|
||||||
|
|
||||||
def doUpdateBuilding():
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
buildingId = _getBuildingByNameOrId(cd, sys.argv[3])
|
|
||||||
body = _getBuildingAttributes(sys.argv[4:])
|
|
||||||
print(f'Updating building {buildingId}...')
|
|
||||||
gapi.call(cd.resources().buildings(), 'patch',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], buildingId=buildingId, body=body)
|
|
||||||
|
|
||||||
def doGetBuildingInfo():
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
buildingId = _getBuildingByNameOrId(cd, sys.argv[3])
|
|
||||||
building = gapi.call(cd.resources().buildings(), 'get',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], buildingId=buildingId)
|
|
||||||
if 'buildingId' in building:
|
|
||||||
building['buildingId'] = f'id:{building["buildingId"]}'
|
|
||||||
if 'floorNames' in building:
|
|
||||||
building['floorNames'] = ','.join(building['floorNames'])
|
|
||||||
if 'buildingName' in building:
|
|
||||||
sys.stdout.write(building.pop('buildingName'))
|
|
||||||
display.print_json(building)
|
|
||||||
|
|
||||||
def doDeleteBuilding():
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
buildingId = _getBuildingByNameOrId(cd, sys.argv[3])
|
|
||||||
print(f'Deleting building {buildingId}...')
|
|
||||||
gapi.call(cd.resources().buildings(), 'delete',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], buildingId=buildingId)
|
|
||||||
|
|
||||||
def _getFeatureAttributes(args, body={}):
|
|
||||||
i = 0
|
|
||||||
while i < len(args):
|
|
||||||
myarg = args[i].lower().replace('_', '')
|
|
||||||
if myarg == 'name':
|
|
||||||
body['name'] = args[i+1]
|
|
||||||
i += 2
|
|
||||||
else:
|
|
||||||
controlflow.invalid_argument_exit(myarg, "gam create|update feature")
|
|
||||||
return body
|
|
||||||
|
|
||||||
def doCreateFeature():
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
body = _getFeatureAttributes(sys.argv[3:])
|
|
||||||
print(f'Creating feature {body["name"]}...')
|
|
||||||
gapi.call(cd.resources().features(), 'insert',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], body=body)
|
|
||||||
|
|
||||||
def doUpdateFeature():
|
|
||||||
# update does not work for name and name is only field to be updated
|
|
||||||
# if additional writable fields are added to feature in the future
|
|
||||||
# we'll add support for update as well as rename
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
oldName = sys.argv[3]
|
|
||||||
body = {'newName': sys.argv[5:]}
|
|
||||||
print(f'Updating feature {oldName}...')
|
|
||||||
gapi.call(cd.resources().features(), 'rename',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], oldName=oldName,
|
|
||||||
body=body)
|
|
||||||
|
|
||||||
def doDeleteFeature():
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
featureKey = sys.argv[3]
|
|
||||||
print(f'Deleting feature {featureKey}...')
|
|
||||||
gapi.call(cd.resources().features(), 'delete',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], featureKey=featureKey)
|
|
||||||
|
|
||||||
def _getResourceCalendarAttributes(cd, args, body={}):
|
|
||||||
i = 0
|
|
||||||
while i < len(args):
|
|
||||||
myarg = args[i].lower().replace('_', '')
|
|
||||||
if myarg == 'name':
|
|
||||||
body['resourceName'] = args[i+1]
|
|
||||||
i += 2
|
|
||||||
elif myarg == 'description':
|
|
||||||
body['resourceDescription'] = args[i+1].replace('\\n', '\n')
|
|
||||||
i += 2
|
|
||||||
elif myarg == 'type':
|
|
||||||
body['resourceType'] = args[i+1]
|
|
||||||
i += 2
|
|
||||||
elif myarg in ['building', 'buildingid']:
|
|
||||||
body['buildingId'] = _getBuildingByNameOrId(cd, args[i+1], minLen=0)
|
|
||||||
i += 2
|
|
||||||
elif myarg in ['capacity']:
|
|
||||||
body['capacity'] = getInteger(args[i+1], myarg, minVal=0)
|
|
||||||
i += 2
|
|
||||||
elif myarg in ['feature', 'features']:
|
|
||||||
features = args[i+1].split(',')
|
|
||||||
body['featureInstances'] = []
|
|
||||||
for feature in features:
|
|
||||||
body['featureInstances'].append({'feature': {'name': feature}})
|
|
||||||
i += 2
|
|
||||||
elif myarg in ['floor', 'floorname']:
|
|
||||||
body['floorName'] = args[i+1]
|
|
||||||
i += 2
|
|
||||||
elif myarg in ['floorsection']:
|
|
||||||
body['floorSection'] = args[i+1]
|
|
||||||
i += 2
|
|
||||||
elif myarg in ['category']:
|
|
||||||
body['resourceCategory'] = args[i+1].upper()
|
|
||||||
if body['resourceCategory'] == 'ROOM':
|
|
||||||
body['resourceCategory'] = 'CONFERENCE_ROOM'
|
|
||||||
i += 2
|
|
||||||
elif myarg in ['uservisibledescription', 'userdescription']:
|
|
||||||
body['userVisibleDescription'] = args[i+1]
|
|
||||||
i += 2
|
|
||||||
else:
|
|
||||||
controlflow.invalid_argument_exit(args[i], "gam create|update resource")
|
|
||||||
return body
|
|
||||||
|
|
||||||
def doCreateResourceCalendar():
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
body = {'resourceId': sys.argv[3],
|
|
||||||
'resourceName': sys.argv[4]}
|
|
||||||
body = _getResourceCalendarAttributes(cd, sys.argv[5:], body)
|
|
||||||
print(f'Creating resource {body["resourceId"]}...')
|
|
||||||
gapi.call(cd.resources().calendars(), 'insert',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], body=body)
|
|
||||||
|
|
||||||
def doUpdateResourceCalendar():
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
resId = sys.argv[3]
|
|
||||||
body = _getResourceCalendarAttributes(cd, sys.argv[4:])
|
|
||||||
# Use patch since it seems to work better.
|
|
||||||
# update requires name to be set.
|
|
||||||
gapi.call(cd.resources().calendars(), 'patch',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], calendarResourceId=resId, body=body,
|
|
||||||
fields='')
|
|
||||||
print(f'updated resource {resId}')
|
|
||||||
|
|
||||||
def doUpdateUser(users, i):
|
def doUpdateUser(users, i):
|
||||||
cd = buildGAPIObject('directory')
|
cd = buildGAPIObject('directory')
|
||||||
if users is None:
|
if users is None:
|
||||||
@@ -8950,18 +8725,6 @@ def doGetAliasInfo(alias_email=None):
|
|||||||
print(f' Group Email: {result["email"]}')
|
print(f' Group Email: {result["email"]}')
|
||||||
print(f' Unique ID: {result["id"]}')
|
print(f' Unique ID: {result["id"]}')
|
||||||
|
|
||||||
def doGetResourceCalendarInfo():
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
resId = sys.argv[3]
|
|
||||||
resource = gapi.call(cd.resources().calendars(), 'get',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], calendarResourceId=resId)
|
|
||||||
if 'featureInstances' in resource:
|
|
||||||
resource['features'] = ', '.join([a_feature['feature']['name'] for a_feature in resource.pop('featureInstances')])
|
|
||||||
if 'buildingId' in resource:
|
|
||||||
resource['buildingName'] = _getBuildingNameById(cd, resource['buildingId'])
|
|
||||||
resource['buildingId'] = f'id:{resource["buildingId"]}'
|
|
||||||
display.print_json(resource)
|
|
||||||
|
|
||||||
def _filterTimeRanges(activeTimeRanges, startDate, endDate):
|
def _filterTimeRanges(activeTimeRanges, startDate, endDate):
|
||||||
if startDate is None and endDate is None:
|
if startDate is None and endDate is None:
|
||||||
return activeTimeRanges
|
return activeTimeRanges
|
||||||
@@ -9692,13 +9455,6 @@ def doDeleteAlias(alias_email=None):
|
|||||||
if not is_user or (not is_user and not is_group):
|
if not is_user or (not is_user and not is_group):
|
||||||
gapi.call(cd.groups().aliases(), 'delete', groupKey=alias_email, alias=alias_email)
|
gapi.call(cd.groups().aliases(), 'delete', groupKey=alias_email, alias=alias_email)
|
||||||
|
|
||||||
def doDeleteResourceCalendar():
|
|
||||||
resId = sys.argv[3]
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
print(f'Deleting resource calendar {resId}')
|
|
||||||
gapi.call(cd.resources().calendars(), 'delete',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], calendarResourceId=resId)
|
|
||||||
|
|
||||||
def doDeleteOrg():
|
def doDeleteOrg():
|
||||||
cd = buildGAPIObject('directory')
|
cd = buildGAPIObject('directory')
|
||||||
name = getOrgUnitItem(sys.argv[3])
|
name = getOrgUnitItem(sys.argv[3])
|
||||||
@@ -11062,178 +10818,6 @@ def doShowLicenses():
|
|||||||
line += f'{u_license[i]}: {u_license[i+1]}, '
|
line += f'{u_license[i]}: {u_license[i+1]}, '
|
||||||
print(line[:-2])
|
print(line[:-2])
|
||||||
|
|
||||||
RESCAL_DFLTFIELDS = ['id', 'name', 'email',]
|
|
||||||
RESCAL_ALLFIELDS = ['id', 'name', 'email', 'description', 'type', 'buildingid', 'category', 'capacity',
|
|
||||||
'features', 'floor', 'floorsection', 'generatedresourcename', 'uservisibledescription',]
|
|
||||||
|
|
||||||
RESCAL_ARGUMENT_TO_PROPERTY_MAP = {
|
|
||||||
'description': ['resourceDescription'],
|
|
||||||
'building': ['buildingId',],
|
|
||||||
'buildingid': ['buildingId',],
|
|
||||||
'capacity': ['capacity',],
|
|
||||||
'category': ['resourceCategory',],
|
|
||||||
'email': ['resourceEmail'],
|
|
||||||
'feature': ['featureInstances',],
|
|
||||||
'features': ['featureInstances',],
|
|
||||||
'floor': ['floorName',],
|
|
||||||
'floorname': ['floorName',],
|
|
||||||
'floorsection': ['floorSection',],
|
|
||||||
'generatedresourcename': ['generatedResourceName',],
|
|
||||||
'id': ['resourceId'],
|
|
||||||
'name': ['resourceName'],
|
|
||||||
'type': ['resourceType'],
|
|
||||||
'userdescription': ['userVisibleDescription',],
|
|
||||||
'uservisibledescription': ['userVisibleDescription',],
|
|
||||||
}
|
|
||||||
|
|
||||||
def doPrintFeatures():
|
|
||||||
to_drive = False
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
titles = []
|
|
||||||
csvRows = []
|
|
||||||
fieldsList = ['name']
|
|
||||||
fields = 'nextPageToken,features(%s)'
|
|
||||||
possible_fields = {}
|
|
||||||
for pfield in cd._rootDesc['schemas']['Feature']['properties']:
|
|
||||||
possible_fields[pfield.lower()] = pfield
|
|
||||||
i = 3
|
|
||||||
while i < len(sys.argv):
|
|
||||||
myarg = sys.argv[i].lower()
|
|
||||||
if myarg == 'todrive':
|
|
||||||
to_drive = True
|
|
||||||
i += 1
|
|
||||||
elif myarg == 'allfields':
|
|
||||||
fields = None
|
|
||||||
i += 1
|
|
||||||
elif myarg in possible_fields:
|
|
||||||
fieldsList.append(possible_fields[myarg])
|
|
||||||
i += 1
|
|
||||||
elif 'feature'+myarg in possible_fields:
|
|
||||||
fieldsList.append(possible_fields['feature'+myarg])
|
|
||||||
i += 1
|
|
||||||
else:
|
|
||||||
controlflow.invalid_argument_exit(sys.argv[i], "gam print features")
|
|
||||||
if fields:
|
|
||||||
fields = fields % ','.join(fieldsList)
|
|
||||||
features = gapi.get_all_pages(cd.resources().features(), 'list', 'features',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], fields=fields)
|
|
||||||
for feature in features:
|
|
||||||
feature.pop('etags', None)
|
|
||||||
feature.pop('etag', None)
|
|
||||||
feature.pop('kind', None)
|
|
||||||
feature = utils.flatten_json(feature)
|
|
||||||
for item in feature:
|
|
||||||
if item not in titles:
|
|
||||||
titles.append(item)
|
|
||||||
csvRows.append(feature)
|
|
||||||
display.sort_csv_titles('name', titles)
|
|
||||||
display.write_csv_file(csvRows, titles, 'Features', to_drive)
|
|
||||||
|
|
||||||
def doPrintBuildings():
|
|
||||||
to_drive = False
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
titles = []
|
|
||||||
csvRows = []
|
|
||||||
fieldsList = ['buildingId']
|
|
||||||
# buildings.list() currently doesn't support paging
|
|
||||||
# but should soon, attempt to use it now so we
|
|
||||||
# won't break when it's turned on.
|
|
||||||
fields = 'nextPageToken,buildings(%s)'
|
|
||||||
possible_fields = {}
|
|
||||||
for pfield in cd._rootDesc['schemas']['Building']['properties']:
|
|
||||||
possible_fields[pfield.lower()] = pfield
|
|
||||||
i = 3
|
|
||||||
while i < len(sys.argv):
|
|
||||||
myarg = sys.argv[i].lower()
|
|
||||||
if myarg == 'todrive':
|
|
||||||
to_drive = True
|
|
||||||
i += 1
|
|
||||||
elif myarg == 'allfields':
|
|
||||||
fields = None
|
|
||||||
i += 1
|
|
||||||
elif myarg in possible_fields:
|
|
||||||
fieldsList.append(possible_fields[myarg])
|
|
||||||
i += 1
|
|
||||||
# Allows shorter arguments like "name" instead of "buildingname"
|
|
||||||
elif 'building'+myarg in possible_fields:
|
|
||||||
fieldsList.append(possible_fields['building'+myarg])
|
|
||||||
i += 1
|
|
||||||
else:
|
|
||||||
controlflow.invalid_argument_exit(sys.argv[i], "gam print buildings")
|
|
||||||
if fields:
|
|
||||||
fields = fields % ','.join(fieldsList)
|
|
||||||
buildings = gapi.get_all_pages(cd.resources().buildings(), 'list', 'buildings',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], fields=fields)
|
|
||||||
for building in buildings:
|
|
||||||
building.pop('etags', None)
|
|
||||||
building.pop('etag', None)
|
|
||||||
building.pop('kind', None)
|
|
||||||
if 'buildingId' in building:
|
|
||||||
building['buildingId'] = f'id:{building["buildingId"]}'
|
|
||||||
if 'floorNames' in building:
|
|
||||||
building['floorNames'] = ','.join(building['floorNames'])
|
|
||||||
building = utils.flatten_json(building)
|
|
||||||
for item in building:
|
|
||||||
if item not in titles:
|
|
||||||
titles.append(item)
|
|
||||||
csvRows.append(building)
|
|
||||||
display.sort_csv_titles('buildingId', titles)
|
|
||||||
display.write_csv_file(csvRows, titles, 'Buildings', to_drive)
|
|
||||||
|
|
||||||
def doPrintResourceCalendars():
|
|
||||||
cd = buildGAPIObject('directory')
|
|
||||||
todrive = False
|
|
||||||
fieldsList = []
|
|
||||||
fieldsTitles = {}
|
|
||||||
titles = []
|
|
||||||
csvRows = []
|
|
||||||
query = None
|
|
||||||
i = 3
|
|
||||||
while i < len(sys.argv):
|
|
||||||
myarg = sys.argv[i].lower()
|
|
||||||
if myarg == 'todrive':
|
|
||||||
todrive = True
|
|
||||||
i += 1
|
|
||||||
elif myarg == 'query':
|
|
||||||
query = sys.argv[i+1]
|
|
||||||
i += 2
|
|
||||||
elif myarg == 'allfields':
|
|
||||||
fieldsList = []
|
|
||||||
fieldsTitles = {}
|
|
||||||
titles = []
|
|
||||||
for field in RESCAL_ALLFIELDS:
|
|
||||||
display.add_field_to_csv_file(field, RESCAL_ARGUMENT_TO_PROPERTY_MAP, fieldsList, fieldsTitles, titles)
|
|
||||||
i += 1
|
|
||||||
elif myarg in RESCAL_ARGUMENT_TO_PROPERTY_MAP:
|
|
||||||
display.add_field_to_csv_file(myarg, RESCAL_ARGUMENT_TO_PROPERTY_MAP, fieldsList, fieldsTitles, titles)
|
|
||||||
i += 1
|
|
||||||
else:
|
|
||||||
controlflow.invalid_argument_exit(sys.argv[i], "gam print resources")
|
|
||||||
if not fieldsList:
|
|
||||||
for field in RESCAL_DFLTFIELDS:
|
|
||||||
display.add_field_to_csv_file(field, RESCAL_ARGUMENT_TO_PROPERTY_MAP, fieldsList, fieldsTitles, titles)
|
|
||||||
fields = f'nextPageToken,items({",".join(set(fieldsList))})'
|
|
||||||
if 'buildingId' in fieldsList:
|
|
||||||
display.add_field_to_csv_file('buildingName', {'buildingName': ['buildingName',]}, fieldsList, fieldsTitles, titles)
|
|
||||||
printGettingAllItems('Resource Calendars', None)
|
|
||||||
page_message = gapi.got_total_items_first_last_msg('Resource Calendars')
|
|
||||||
resources = gapi.get_all_pages(cd.resources().calendars(), 'list', 'items',
|
|
||||||
page_message=page_message, message_attribute='resourceId',
|
|
||||||
customer=GC_Values[GC_CUSTOMER_ID], query=query,
|
|
||||||
fields=fields)
|
|
||||||
for resource in resources:
|
|
||||||
if 'featureInstances' in resource:
|
|
||||||
resource['featureInstances'] = ','.join([a_feature['feature']['name'] for a_feature in resource.pop('featureInstances')])
|
|
||||||
if 'buildingId' in resource:
|
|
||||||
resource['buildingName'] = _getBuildingNameById(cd, resource['buildingId'])
|
|
||||||
resource['buildingId'] = f'id:{resource["buildingId"]}'
|
|
||||||
resUnit = {}
|
|
||||||
for field in fieldsList:
|
|
||||||
resUnit[fieldsTitles[field]] = resource.get(field, '')
|
|
||||||
csvRows.append(resUnit)
|
|
||||||
display.sort_csv_titles(['resourceId', 'resourceName', 'resourceEmail'], titles)
|
|
||||||
display.write_csv_file(csvRows, titles, 'Resources', todrive)
|
|
||||||
|
|
||||||
def shlexSplitList(entity, dataDelimiter=' ,'):
|
def shlexSplitList(entity, dataDelimiter=' ,'):
|
||||||
lexer = shlex.shlex(entity, posix=True)
|
lexer = shlex.shlex(entity, posix=True)
|
||||||
lexer.whitespace = dataDelimiter
|
lexer.whitespace = dataDelimiter
|
||||||
@@ -12340,7 +11924,7 @@ def ProcessGAMCommand(args):
|
|||||||
elif argument in ['org', 'ou']:
|
elif argument in ['org', 'ou']:
|
||||||
doCreateOrg()
|
doCreateOrg()
|
||||||
elif argument == 'resource':
|
elif argument == 'resource':
|
||||||
doCreateResourceCalendar()
|
gapi.directory.resource.createResourceCalendar()
|
||||||
elif argument in ['verify', 'verification']:
|
elif argument in ['verify', 'verification']:
|
||||||
doSiteVerifyShow()
|
doSiteVerifyShow()
|
||||||
elif argument == 'schema':
|
elif argument == 'schema':
|
||||||
@@ -12370,9 +11954,9 @@ def ProcessGAMCommand(args):
|
|||||||
elif argument in ['export', 'vaultexport']:
|
elif argument in ['export', 'vaultexport']:
|
||||||
gapi.vault.createExport()
|
gapi.vault.createExport()
|
||||||
elif argument in ['building']:
|
elif argument in ['building']:
|
||||||
doCreateBuilding()
|
gapi.directory.resource.createBuilding()
|
||||||
elif argument in ['feature']:
|
elif argument in ['feature']:
|
||||||
doCreateFeature()
|
gapi.directory.resource.createFeature()
|
||||||
elif argument in ['alertfeedback']:
|
elif argument in ['alertfeedback']:
|
||||||
doCreateAlertFeedback()
|
doCreateAlertFeedback()
|
||||||
elif argument in ['gcpfolder']:
|
elif argument in ['gcpfolder']:
|
||||||
@@ -12398,7 +11982,7 @@ def ProcessGAMCommand(args):
|
|||||||
elif argument in ['ou', 'org']:
|
elif argument in ['ou', 'org']:
|
||||||
doUpdateOrg()
|
doUpdateOrg()
|
||||||
elif argument == 'resource':
|
elif argument == 'resource':
|
||||||
doUpdateResourceCalendar()
|
gapi.directory.resource.updateResourceCalendar()
|
||||||
elif argument == 'cros':
|
elif argument == 'cros':
|
||||||
doUpdateCros()
|
doUpdateCros()
|
||||||
elif argument == 'mobile':
|
elif argument == 'mobile':
|
||||||
@@ -12426,9 +12010,9 @@ def ProcessGAMCommand(args):
|
|||||||
elif argument in ['project', 'projects', 'apiproject']:
|
elif argument in ['project', 'projects', 'apiproject']:
|
||||||
doUpdateProjects()
|
doUpdateProjects()
|
||||||
elif argument in ['building']:
|
elif argument in ['building']:
|
||||||
doUpdateBuilding()
|
gapi.directory.resource.updateBuilding()
|
||||||
elif argument in ['feature']:
|
elif argument in ['feature']:
|
||||||
doUpdateFeature()
|
gapi.directory.resource.updateFeature()
|
||||||
else:
|
else:
|
||||||
controlflow.invalid_argument_exit(argument, "gam update")
|
controlflow.invalid_argument_exit(argument, "gam update")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
@@ -12447,7 +12031,7 @@ def ProcessGAMCommand(args):
|
|||||||
elif argument in ['org', 'ou']:
|
elif argument in ['org', 'ou']:
|
||||||
doGetOrgInfo()
|
doGetOrgInfo()
|
||||||
elif argument == 'resource':
|
elif argument == 'resource':
|
||||||
doGetResourceCalendarInfo()
|
gapi.directory.resource.getResourceCalendarInfo()
|
||||||
elif argument == 'cros':
|
elif argument == 'cros':
|
||||||
doGetCrosInfo()
|
doGetCrosInfo()
|
||||||
elif argument == 'mobile':
|
elif argument == 'mobile':
|
||||||
@@ -12479,7 +12063,7 @@ def ProcessGAMCommand(args):
|
|||||||
elif argument in ['export', 'vaultexport']:
|
elif argument in ['export', 'vaultexport']:
|
||||||
gapi.vault.getExportInfo()
|
gapi.vault.getExportInfo()
|
||||||
elif argument in ['building']:
|
elif argument in ['building']:
|
||||||
doGetBuildingInfo()
|
gapi.directory.resource.getBuildingInfo()
|
||||||
else:
|
else:
|
||||||
controlflow.invalid_argument_exit(argument, "gam info")
|
controlflow.invalid_argument_exit(argument, "gam info")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
@@ -12501,7 +12085,7 @@ def ProcessGAMCommand(args):
|
|||||||
elif argument == 'org':
|
elif argument == 'org':
|
||||||
doDeleteOrg()
|
doDeleteOrg()
|
||||||
elif argument == 'resource':
|
elif argument == 'resource':
|
||||||
doDeleteResourceCalendar()
|
gapi.directory.resource.deleteResourceCalendar()
|
||||||
elif argument == 'mobile':
|
elif argument == 'mobile':
|
||||||
doDeleteMobile()
|
doDeleteMobile()
|
||||||
elif argument in ['schema', 'schemas']:
|
elif argument in ['schema', 'schemas']:
|
||||||
@@ -12529,9 +12113,9 @@ def ProcessGAMCommand(args):
|
|||||||
elif argument in ['export', 'vaultexport']:
|
elif argument in ['export', 'vaultexport']:
|
||||||
gapi.vault.deleteExport()
|
gapi.vault.deleteExport()
|
||||||
elif argument in ['building']:
|
elif argument in ['building']:
|
||||||
doDeleteBuilding()
|
gapi.directory.resource.deleteBuilding()
|
||||||
elif argument in ['feature']:
|
elif argument in ['feature']:
|
||||||
doDeleteFeature()
|
gapi.directory.resource.deleteFeature()
|
||||||
elif argument in ['alert']:
|
elif argument in ['alert']:
|
||||||
doDeleteOrUndeleteAlert('delete')
|
doDeleteOrUndeleteAlert('delete')
|
||||||
elif argument in ['sakey', 'sakeys']:
|
elif argument in ['sakey', 'sakeys']:
|
||||||
@@ -12571,7 +12155,7 @@ def ProcessGAMCommand(args):
|
|||||||
elif argument in ['orgs', 'ous']:
|
elif argument in ['orgs', 'ous']:
|
||||||
doPrintOrgs()
|
doPrintOrgs()
|
||||||
elif argument == 'resources':
|
elif argument == 'resources':
|
||||||
doPrintResourceCalendars()
|
gapi.directory.resource.printResourceCalendars()
|
||||||
elif argument == 'cros':
|
elif argument == 'cros':
|
||||||
doPrintCrosDevices()
|
doPrintCrosDevices()
|
||||||
elif argument == 'crosactivity':
|
elif argument == 'crosactivity':
|
||||||
@@ -12613,9 +12197,9 @@ def ProcessGAMCommand(args):
|
|||||||
elif argument in ['exports', 'vaultexports']:
|
elif argument in ['exports', 'vaultexports']:
|
||||||
gapi.vault.printExports()
|
gapi.vault.printExports()
|
||||||
elif argument in ['building', 'buildings']:
|
elif argument in ['building', 'buildings']:
|
||||||
doPrintBuildings()
|
gapi.directory.resource.printBuildings()
|
||||||
elif argument in ['feature', 'features']:
|
elif argument in ['feature', 'features']:
|
||||||
doPrintFeatures()
|
gapi.directory.resource.printFeatures()
|
||||||
elif argument in ['project', 'projects']:
|
elif argument in ['project', 'projects']:
|
||||||
doPrintShowProjects(True)
|
doPrintShowProjects(True)
|
||||||
elif argument in ['alert', 'alerts']:
|
elif argument in ['alert', 'alerts']:
|
||||||
|
|||||||
5
src/gapi/directory/__init__.py
Normal file
5
src/gapi/directory/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import __main__
|
||||||
|
|
||||||
|
|
||||||
|
def buildGAPIObject():
|
||||||
|
return __main__.buildGAPIObject('directory')
|
||||||
487
src/gapi/directory/resource.py
Normal file
487
src/gapi/directory/resource.py
Normal file
@@ -0,0 +1,487 @@
|
|||||||
|
import sys
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import __main__
|
||||||
|
from var import *
|
||||||
|
import controlflow
|
||||||
|
import display
|
||||||
|
import gapi.directory
|
||||||
|
import utils
|
||||||
|
|
||||||
|
|
||||||
|
def printBuildings():
|
||||||
|
to_drive = False
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
titles = []
|
||||||
|
csvRows = []
|
||||||
|
fieldsList = ['buildingId']
|
||||||
|
# buildings.list() currently doesn't support paging
|
||||||
|
# but should soon, attempt to use it now so we
|
||||||
|
# won't break when it's turned on.
|
||||||
|
fields = 'nextPageToken,buildings(%s)'
|
||||||
|
possible_fields = {}
|
||||||
|
for pfield in cd._rootDesc['schemas']['Building']['properties']:
|
||||||
|
possible_fields[pfield.lower()] = pfield
|
||||||
|
i = 3
|
||||||
|
while i < len(sys.argv):
|
||||||
|
myarg = sys.argv[i].lower()
|
||||||
|
if myarg == 'todrive':
|
||||||
|
to_drive = True
|
||||||
|
i += 1
|
||||||
|
elif myarg == 'allfields':
|
||||||
|
fields = None
|
||||||
|
i += 1
|
||||||
|
elif myarg in possible_fields:
|
||||||
|
fieldsList.append(possible_fields[myarg])
|
||||||
|
i += 1
|
||||||
|
# Allows shorter arguments like "name" instead of "buildingname"
|
||||||
|
elif 'building'+myarg in possible_fields:
|
||||||
|
fieldsList.append(possible_fields['building'+myarg])
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
controlflow.invalid_argument_exit(
|
||||||
|
sys.argv[i], "gam print buildings")
|
||||||
|
if fields:
|
||||||
|
fields = fields % ','.join(fieldsList)
|
||||||
|
buildings = gapi.get_all_pages(cd.resources().buildings(), 'list',
|
||||||
|
'buildings',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID],
|
||||||
|
fields=fields)
|
||||||
|
for building in buildings:
|
||||||
|
building.pop('etags', None)
|
||||||
|
building.pop('etag', None)
|
||||||
|
building.pop('kind', None)
|
||||||
|
if 'buildingId' in building:
|
||||||
|
building['buildingId'] = f'id:{building["buildingId"]}'
|
||||||
|
if 'floorNames' in building:
|
||||||
|
building['floorNames'] = ','.join(building['floorNames'])
|
||||||
|
building = utils.flatten_json(building)
|
||||||
|
for item in building:
|
||||||
|
if item not in titles:
|
||||||
|
titles.append(item)
|
||||||
|
csvRows.append(building)
|
||||||
|
display.sort_csv_titles('buildingId', titles)
|
||||||
|
display.write_csv_file(csvRows, titles, 'Buildings', to_drive)
|
||||||
|
|
||||||
|
|
||||||
|
def printResourceCalendars():
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
todrive = False
|
||||||
|
fieldsList = []
|
||||||
|
fieldsTitles = {}
|
||||||
|
titles = []
|
||||||
|
csvRows = []
|
||||||
|
query = None
|
||||||
|
i = 3
|
||||||
|
while i < len(sys.argv):
|
||||||
|
myarg = sys.argv[i].lower()
|
||||||
|
if myarg == 'todrive':
|
||||||
|
todrive = True
|
||||||
|
i += 1
|
||||||
|
elif myarg == 'query':
|
||||||
|
query = sys.argv[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg == 'allfields':
|
||||||
|
fieldsList = []
|
||||||
|
fieldsTitles = {}
|
||||||
|
titles = []
|
||||||
|
for field in RESCAL_ALLFIELDS:
|
||||||
|
display.add_field_to_csv_file(field,
|
||||||
|
RESCAL_ARGUMENT_TO_PROPERTY_MAP,
|
||||||
|
fieldsList, fieldsTitles,
|
||||||
|
titles)
|
||||||
|
i += 1
|
||||||
|
elif myarg in RESCAL_ARGUMENT_TO_PROPERTY_MAP:
|
||||||
|
display.add_field_to_csv_file(myarg,
|
||||||
|
RESCAL_ARGUMENT_TO_PROPERTY_MAP,
|
||||||
|
fieldsList, fieldsTitles, titles)
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
controlflow.invalid_argument_exit(
|
||||||
|
sys.argv[i], "gam print resources")
|
||||||
|
if not fieldsList:
|
||||||
|
for field in RESCAL_DFLTFIELDS:
|
||||||
|
display.add_field_to_csv_file(field,
|
||||||
|
RESCAL_ARGUMENT_TO_PROPERTY_MAP,
|
||||||
|
fieldsList, fieldsTitles, titles)
|
||||||
|
fields = f'nextPageToken,items({",".join(set(fieldsList))})'
|
||||||
|
if 'buildingId' in fieldsList:
|
||||||
|
display.add_field_to_csv_file('buildingName', {'buildingName': [
|
||||||
|
'buildingName', ]}, fieldsList, fieldsTitles, titles)
|
||||||
|
__main__.printGettingAllItems('Resource Calendars', None)
|
||||||
|
page_message = gapi.got_total_items_first_last_msg('Resource Calendars')
|
||||||
|
resources = gapi.get_all_pages(cd.resources().calendars(), 'list',
|
||||||
|
'items', page_message=page_message,
|
||||||
|
message_attribute='resourceId',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID],
|
||||||
|
query=query, fields=fields)
|
||||||
|
for resource in resources:
|
||||||
|
if 'featureInstances' in resource:
|
||||||
|
features = [a_feature['feature']['name'] for \
|
||||||
|
a_feature in resource['featureInstances']]
|
||||||
|
resource['featureInstances'] = ','.join(features)
|
||||||
|
if 'buildingId' in resource:
|
||||||
|
resource['buildingName'] = getBuildingNameById(
|
||||||
|
cd, resource['buildingId'])
|
||||||
|
resource['buildingId'] = f'id:{resource["buildingId"]}'
|
||||||
|
resUnit = {}
|
||||||
|
for field in fieldsList:
|
||||||
|
resUnit[fieldsTitles[field]] = resource.get(field, '')
|
||||||
|
csvRows.append(resUnit)
|
||||||
|
display.sort_csv_titles(
|
||||||
|
['resourceId', 'resourceName', 'resourceEmail'], titles)
|
||||||
|
display.write_csv_file(csvRows, titles, 'Resources', todrive)
|
||||||
|
|
||||||
|
|
||||||
|
RESCAL_DFLTFIELDS = ['id', 'name', 'email',]
|
||||||
|
RESCAL_ALLFIELDS = ['id', 'name', 'email', 'description', 'type',
|
||||||
|
'buildingid', 'category', 'capacity', 'features', 'floor',
|
||||||
|
'floorsection', 'generatedresourcename',
|
||||||
|
'uservisibledescription',]
|
||||||
|
|
||||||
|
RESCAL_ARGUMENT_TO_PROPERTY_MAP = {
|
||||||
|
'description': ['resourceDescription'],
|
||||||
|
'building': ['buildingId', ],
|
||||||
|
'buildingid': ['buildingId', ],
|
||||||
|
'capacity': ['capacity', ],
|
||||||
|
'category': ['resourceCategory', ],
|
||||||
|
'email': ['resourceEmail'],
|
||||||
|
'feature': ['featureInstances', ],
|
||||||
|
'features': ['featureInstances', ],
|
||||||
|
'floor': ['floorName', ],
|
||||||
|
'floorname': ['floorName', ],
|
||||||
|
'floorsection': ['floorSection', ],
|
||||||
|
'generatedresourcename': ['generatedResourceName', ],
|
||||||
|
'id': ['resourceId'],
|
||||||
|
'name': ['resourceName'],
|
||||||
|
'type': ['resourceType'],
|
||||||
|
'userdescription': ['userVisibleDescription', ],
|
||||||
|
'uservisibledescription': ['userVisibleDescription', ],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def printFeatures():
|
||||||
|
to_drive = False
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
titles = []
|
||||||
|
csvRows = []
|
||||||
|
fieldsList = ['name']
|
||||||
|
fields = 'nextPageToken,features(%s)'
|
||||||
|
possible_fields = {}
|
||||||
|
for pfield in cd._rootDesc['schemas']['Feature']['properties']:
|
||||||
|
possible_fields[pfield.lower()] = pfield
|
||||||
|
i = 3
|
||||||
|
while i < len(sys.argv):
|
||||||
|
myarg = sys.argv[i].lower()
|
||||||
|
if myarg == 'todrive':
|
||||||
|
to_drive = True
|
||||||
|
i += 1
|
||||||
|
elif myarg == 'allfields':
|
||||||
|
fields = None
|
||||||
|
i += 1
|
||||||
|
elif myarg in possible_fields:
|
||||||
|
fieldsList.append(possible_fields[myarg])
|
||||||
|
i += 1
|
||||||
|
elif 'feature'+myarg in possible_fields:
|
||||||
|
fieldsList.append(possible_fields['feature'+myarg])
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
controlflow.invalid_argument_exit(
|
||||||
|
sys.argv[i], "gam print features")
|
||||||
|
if fields:
|
||||||
|
fields = fields % ','.join(fieldsList)
|
||||||
|
features = gapi.get_all_pages(cd.resources().features(), 'list',
|
||||||
|
'features',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID],
|
||||||
|
fields=fields)
|
||||||
|
for feature in features:
|
||||||
|
feature.pop('etags', None)
|
||||||
|
feature.pop('etag', None)
|
||||||
|
feature.pop('kind', None)
|
||||||
|
feature = utils.flatten_json(feature)
|
||||||
|
for item in feature:
|
||||||
|
if item not in titles:
|
||||||
|
titles.append(item)
|
||||||
|
csvRows.append(feature)
|
||||||
|
display.sort_csv_titles('name', titles)
|
||||||
|
display.write_csv_file(csvRows, titles, 'Features', to_drive)
|
||||||
|
|
||||||
|
|
||||||
|
def _getBuildingAttributes(args, body={}):
|
||||||
|
i = 0
|
||||||
|
while i < len(args):
|
||||||
|
myarg = args[i].lower().replace('_', '')
|
||||||
|
if myarg == 'id':
|
||||||
|
body['buildingId'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg == 'name':
|
||||||
|
body['buildingName'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg in ['lat', 'latitude']:
|
||||||
|
if 'coordinates' not in body:
|
||||||
|
body['coordinates'] = {}
|
||||||
|
body['coordinates']['latitude'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg in ['long', 'lng', 'longitude']:
|
||||||
|
if 'coordinates' not in body:
|
||||||
|
body['coordinates'] = {}
|
||||||
|
body['coordinates']['longitude'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg == 'description':
|
||||||
|
body['description'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg == 'floors':
|
||||||
|
body['floorNames'] = args[i+1].split(',')
|
||||||
|
i += 2
|
||||||
|
else:
|
||||||
|
controlflow.invalid_argument_exit(
|
||||||
|
myarg, "gam create|update building")
|
||||||
|
return body
|
||||||
|
|
||||||
|
|
||||||
|
def createBuilding():
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
body = {'floorNames': ['1'],
|
||||||
|
'buildingId': str(uuid.uuid4()),
|
||||||
|
'buildingName': sys.argv[3]}
|
||||||
|
body = _getBuildingAttributes(sys.argv[4:], body)
|
||||||
|
print(f'Creating building {body["buildingId"]}...')
|
||||||
|
gapi.call(cd.resources().buildings(), 'insert',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID], body=body)
|
||||||
|
|
||||||
|
|
||||||
|
def _makeBuildingIdNameMap(cd):
|
||||||
|
fields = 'nextPageToken,buildings(buildingId,buildingName)'
|
||||||
|
buildings = gapi.get_all_pages(cd.resources().buildings(), 'list',
|
||||||
|
'buildings',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID],
|
||||||
|
fields=fields)
|
||||||
|
GM_Globals[GM_MAP_BUILDING_ID_TO_NAME] = {}
|
||||||
|
GM_Globals[GM_MAP_BUILDING_NAME_TO_ID] = {}
|
||||||
|
for building in buildings:
|
||||||
|
GM_Globals[GM_MAP_BUILDING_ID_TO_NAME][building['buildingId']
|
||||||
|
] = building['buildingName']
|
||||||
|
GM_Globals[GM_MAP_BUILDING_NAME_TO_ID][building['buildingName']
|
||||||
|
] = building['buildingId']
|
||||||
|
|
||||||
|
|
||||||
|
def getBuildingByNameOrId(cd, which_building, minLen=1):
|
||||||
|
if not which_building or \
|
||||||
|
(minLen == 0 and which_building in ['id:', 'uid:']):
|
||||||
|
if minLen == 0:
|
||||||
|
return ''
|
||||||
|
controlflow.system_error_exit(3, 'Building id/name is empty')
|
||||||
|
cg = UID_PATTERN.match(which_building)
|
||||||
|
if cg:
|
||||||
|
return cg.group(1)
|
||||||
|
if GM_Globals[GM_MAP_BUILDING_NAME_TO_ID] is None:
|
||||||
|
_makeBuildingIdNameMap(cd)
|
||||||
|
# Exact name match, return ID
|
||||||
|
if which_building in GM_Globals[GM_MAP_BUILDING_NAME_TO_ID]:
|
||||||
|
return GM_Globals[GM_MAP_BUILDING_NAME_TO_ID][which_building]
|
||||||
|
# No exact name match, check for case insensitive name matches
|
||||||
|
which_building_lower = which_building.lower()
|
||||||
|
ci_matches = []
|
||||||
|
for buildingName, buildingId in GM_Globals[GM_MAP_BUILDING_NAME_TO_ID].items():
|
||||||
|
if buildingName.lower() == which_building_lower:
|
||||||
|
ci_matches.append(
|
||||||
|
{'buildingName': buildingName, 'buildingId': buildingId})
|
||||||
|
# One match, return ID
|
||||||
|
if len(ci_matches) == 1:
|
||||||
|
return ci_matches[0]['buildingId']
|
||||||
|
# No or multiple name matches, try ID
|
||||||
|
# Exact ID match, return ID
|
||||||
|
if which_building in GM_Globals[GM_MAP_BUILDING_ID_TO_NAME]:
|
||||||
|
return which_building
|
||||||
|
# No exact ID match, check for case insensitive id match
|
||||||
|
for buildingId in GM_Globals[GM_MAP_BUILDING_ID_TO_NAME]:
|
||||||
|
# Match, return ID
|
||||||
|
if buildingId.lower() == which_building_lower:
|
||||||
|
return buildingId
|
||||||
|
# Multiple name matches
|
||||||
|
if len(ci_matches) > 1:
|
||||||
|
message = 'Multiple buildings with same name:\n'
|
||||||
|
for building in ci_matches:
|
||||||
|
message += f' Name:{building["buildingName"]} ' \
|
||||||
|
f'id:{building["buildingId"]}\n'
|
||||||
|
message += '\nPlease specify building name by exact case or by id.'
|
||||||
|
controlflow.system_error_exit(3, message)
|
||||||
|
# No matches
|
||||||
|
else:
|
||||||
|
controlflow.system_error_exit(3, f'No such building {which_building}')
|
||||||
|
|
||||||
|
|
||||||
|
def getBuildingNameById(cd, buildingId):
|
||||||
|
if GM_Globals[GM_MAP_BUILDING_ID_TO_NAME] is None:
|
||||||
|
_makeBuildingIdNameMap(cd)
|
||||||
|
return GM_Globals[GM_MAP_BUILDING_ID_TO_NAME].get(buildingId, 'UNKNOWN')
|
||||||
|
|
||||||
|
|
||||||
|
def updateBuilding():
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
buildingId = getBuildingByNameOrId(cd, sys.argv[3])
|
||||||
|
body = _getBuildingAttributes(sys.argv[4:])
|
||||||
|
print(f'Updating building {buildingId}...')
|
||||||
|
gapi.call(cd.resources().buildings(), 'patch',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID], buildingId=buildingId,
|
||||||
|
body=body)
|
||||||
|
|
||||||
|
|
||||||
|
def getBuildingInfo():
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
buildingId = getBuildingByNameOrId(cd, sys.argv[3])
|
||||||
|
building = gapi.call(cd.resources().buildings(), 'get',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID],
|
||||||
|
buildingId=buildingId)
|
||||||
|
if 'buildingId' in building:
|
||||||
|
building['buildingId'] = f'id:{building["buildingId"]}'
|
||||||
|
if 'floorNames' in building:
|
||||||
|
building['floorNames'] = ','.join(building['floorNames'])
|
||||||
|
if 'buildingName' in building:
|
||||||
|
sys.stdout.write(building.pop('buildingName'))
|
||||||
|
display.print_json(building)
|
||||||
|
|
||||||
|
|
||||||
|
def deleteBuilding():
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
buildingId = getBuildingByNameOrId(cd, sys.argv[3])
|
||||||
|
print(f'Deleting building {buildingId}...')
|
||||||
|
gapi.call(cd.resources().buildings(), 'delete',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID], buildingId=buildingId)
|
||||||
|
|
||||||
|
|
||||||
|
def _getFeatureAttributes(args, body={}):
|
||||||
|
i = 0
|
||||||
|
while i < len(args):
|
||||||
|
myarg = args[i].lower().replace('_', '')
|
||||||
|
if myarg == 'name':
|
||||||
|
body['name'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
else:
|
||||||
|
controlflow.invalid_argument_exit(
|
||||||
|
myarg, "gam create|update feature")
|
||||||
|
return body
|
||||||
|
|
||||||
|
|
||||||
|
def createFeature():
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
body = _getFeatureAttributes(sys.argv[3:])
|
||||||
|
print(f'Creating feature {body["name"]}...')
|
||||||
|
gapi.call(cd.resources().features(), 'insert',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID], body=body)
|
||||||
|
|
||||||
|
|
||||||
|
def updateFeature():
|
||||||
|
# update does not work for name and name is only field to be updated
|
||||||
|
# if additional writable fields are added to feature in the future
|
||||||
|
# we'll add support for update as well as rename
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
oldName = sys.argv[3]
|
||||||
|
body = {'newName': sys.argv[5:]}
|
||||||
|
print(f'Updating feature {oldName}...')
|
||||||
|
gapi.call(cd.resources().features(), 'rename',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID], oldName=oldName,
|
||||||
|
body=body)
|
||||||
|
|
||||||
|
|
||||||
|
def deleteFeature():
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
featureKey = sys.argv[3]
|
||||||
|
print(f'Deleting feature {featureKey}...')
|
||||||
|
gapi.call(cd.resources().features(), 'delete',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID], featureKey=featureKey)
|
||||||
|
|
||||||
|
|
||||||
|
def _getResourceCalendarAttributes(cd, args, body={}):
|
||||||
|
i = 0
|
||||||
|
while i < len(args):
|
||||||
|
myarg = args[i].lower().replace('_', '')
|
||||||
|
if myarg == 'name':
|
||||||
|
body['resourceName'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg == 'description':
|
||||||
|
body['resourceDescription'] = args[i+1].replace('\\n', '\n')
|
||||||
|
i += 2
|
||||||
|
elif myarg == 'type':
|
||||||
|
body['resourceType'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg in ['building', 'buildingid']:
|
||||||
|
body['buildingId'] = getBuildingByNameOrId(
|
||||||
|
cd, args[i+1], minLen=0)
|
||||||
|
i += 2
|
||||||
|
elif myarg in ['capacity']:
|
||||||
|
body['capacity'] = __main__.getInteger(args[i+1], myarg, minVal=0)
|
||||||
|
i += 2
|
||||||
|
elif myarg in ['feature', 'features']:
|
||||||
|
features = args[i+1].split(',')
|
||||||
|
body['featureInstances'] = []
|
||||||
|
for feature in features:
|
||||||
|
instance = {'feature': {'name': feature}}
|
||||||
|
body['featureInstances'].append(instance)
|
||||||
|
i += 2
|
||||||
|
elif myarg in ['floor', 'floorname']:
|
||||||
|
body['floorName'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg in ['floorsection']:
|
||||||
|
body['floorSection'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg in ['category']:
|
||||||
|
body['resourceCategory'] = args[i+1].upper()
|
||||||
|
if body['resourceCategory'] == 'ROOM':
|
||||||
|
body['resourceCategory'] = 'CONFERENCE_ROOM'
|
||||||
|
i += 2
|
||||||
|
elif myarg in ['uservisibledescription', 'userdescription']:
|
||||||
|
body['userVisibleDescription'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
else:
|
||||||
|
controlflow.invalid_argument_exit(
|
||||||
|
args[i], "gam create|update resource")
|
||||||
|
return body
|
||||||
|
|
||||||
|
|
||||||
|
def createResourceCalendar():
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
body = {'resourceId': sys.argv[3],
|
||||||
|
'resourceName': sys.argv[4]}
|
||||||
|
body = _getResourceCalendarAttributes(cd, sys.argv[5:], body)
|
||||||
|
print(f'Creating resource {body["resourceId"]}...')
|
||||||
|
gapi.call(cd.resources().calendars(), 'insert',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID], body=body)
|
||||||
|
|
||||||
|
|
||||||
|
def updateResourceCalendar():
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
resId = sys.argv[3]
|
||||||
|
body = _getResourceCalendarAttributes(cd, sys.argv[4:])
|
||||||
|
# Use patch since it seems to work better.
|
||||||
|
# update requires name to be set.
|
||||||
|
gapi.call(cd.resources().calendars(), 'patch',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID], calendarResourceId=resId,
|
||||||
|
body=body, fields='')
|
||||||
|
print(f'updated resource {resId}')
|
||||||
|
|
||||||
|
|
||||||
|
def getResourceCalendarInfo():
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
resId = sys.argv[3]
|
||||||
|
resource = gapi.call(cd.resources().calendars(), 'get',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID],
|
||||||
|
calendarResourceId=resId)
|
||||||
|
if 'featureInstances' in resource:
|
||||||
|
features = []
|
||||||
|
for a_feature in resource.pop('featureInstances'):
|
||||||
|
features.append(a_feature['feature']['name'])
|
||||||
|
resources['features'] = ', '.join(features)
|
||||||
|
if 'buildingId' in resource:
|
||||||
|
resource['buildingName'] = getBuildingNameById(
|
||||||
|
cd, resource['buildingId'])
|
||||||
|
resource['buildingId'] = f'id:{resource["buildingId"]}'
|
||||||
|
display.print_json(resource)
|
||||||
|
|
||||||
|
|
||||||
|
def doDeleteResourceCalendar():
|
||||||
|
resId = sys.argv[3]
|
||||||
|
cd = gapi.directory.buildGAPIObject()
|
||||||
|
print(f'Deleting resource calendar {resId}')
|
||||||
|
gapi.call(cd.resources().calendars(), 'delete',
|
||||||
|
customer=GC_Values[GC_CUSTOMER_ID], calendarResourceId=resId)
|
||||||
@@ -384,7 +384,7 @@ def getHoldInfo():
|
|||||||
|
|
||||||
def convertExportNameToID(v, nameOrID, matterId):
|
def convertExportNameToID(v, nameOrID, matterId):
|
||||||
nameOrID = nameOrID.lower()
|
nameOrID = nameOrID.lower()
|
||||||
cg = __main__.UID_PATTERN.match(nameOrID)
|
cg = UID_PATTERN.match(nameOrID)
|
||||||
if cg:
|
if cg:
|
||||||
return cg.group(1)
|
return cg.group(1)
|
||||||
fields = 'exports(id,name),nextPageToken'
|
fields = 'exports(id,name),nextPageToken'
|
||||||
@@ -399,7 +399,7 @@ def convertExportNameToID(v, nameOrID, matterId):
|
|||||||
|
|
||||||
def convertHoldNameToID(v, nameOrID, matterId):
|
def convertHoldNameToID(v, nameOrID, matterId):
|
||||||
nameOrID = nameOrID.lower()
|
nameOrID = nameOrID.lower()
|
||||||
cg = __main__.UID_PATTERN.match(nameOrID)
|
cg = UID_PATTERN.match(nameOrID)
|
||||||
if cg:
|
if cg:
|
||||||
return cg.group(1)
|
return cg.group(1)
|
||||||
fields = 'holds(holdId,name),nextPageToken'
|
fields = 'holds(holdId,name),nextPageToken'
|
||||||
@@ -414,7 +414,7 @@ def convertHoldNameToID(v, nameOrID, matterId):
|
|||||||
|
|
||||||
def convertMatterNameToID(v, nameOrID):
|
def convertMatterNameToID(v, nameOrID):
|
||||||
nameOrID = nameOrID.lower()
|
nameOrID = nameOrID.lower()
|
||||||
cg = __main__.UID_PATTERN.match(nameOrID)
|
cg = UID_PATTERN.match(nameOrID)
|
||||||
if cg:
|
if cg:
|
||||||
return cg.group(1)
|
return cg.group(1)
|
||||||
fields = 'matters(matterId,name),nextPageToken'
|
fields = 'matters(matterId,name),nextPageToken'
|
||||||
|
|||||||
Binary file not shown.
@@ -6,7 +6,7 @@ import platform
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
gam_author = 'Jay Lee <jay0lee@gmail.com>'
|
gam_author = 'Jay Lee <jay0lee@gmail.com>'
|
||||||
gam_version = '4.99'
|
gam_version = '5.00'
|
||||||
gam_license = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
gam_license = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||||
|
|
||||||
GAM_URL = 'https://git.io/gam'
|
GAM_URL = 'https://git.io/gam'
|
||||||
@@ -1197,3 +1197,5 @@ YYYYMMDD_FORMAT_REQUIRED = 'yyyy-mm-dd'
|
|||||||
YYYYMMDDTHHMMSS_FORMAT_REQUIRED = 'yyyy-mm-ddThh:mm:ss[.fff](Z|(+|-(hh:mm)))'
|
YYYYMMDDTHHMMSS_FORMAT_REQUIRED = 'yyyy-mm-ddThh:mm:ss[.fff](Z|(+|-(hh:mm)))'
|
||||||
|
|
||||||
YYYYMMDD_PATTERN = re.compile(r'^[0-9]{4}-[0-9]{2}-[0-9]{2}$')
|
YYYYMMDD_PATTERN = re.compile(r'^[0-9]{4}-[0-9]{2}-[0-9]{2}$')
|
||||||
|
|
||||||
|
UID_PATTERN = re.compile(r'u?id: ?(.+)', re.IGNORECASE)
|
||||||
Reference in New Issue
Block a user