mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-28 09: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 fileutils
|
||||
import gapi.calendar
|
||||
import gapi.directory
|
||||
import gapi.directory.resource
|
||||
import gapi.errors
|
||||
import gapi.storage
|
||||
import gapi.vault
|
||||
@@ -268,8 +270,6 @@ def splitEmailAddress(emailAddress):
|
||||
return (emailAddress.lower(), GC_Values[GC_DOMAIN].lower())
|
||||
return (emailAddress[:atLoc].lower(), emailAddress[atLoc+1:].lower())
|
||||
|
||||
UID_PATTERN = re.compile(r'u?id: ?(.+)', re.IGNORECASE)
|
||||
|
||||
# Normalize user/group email address/uid
|
||||
# uid:12345abc -> 12345abc
|
||||
# foo -> foo@domain
|
||||
@@ -6394,7 +6394,7 @@ def getUserAttributes(i, cd, updateCmd):
|
||||
location['area'] = sys.argv[i+1]
|
||||
i += 2
|
||||
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
|
||||
elif myopt in ['desk', 'deskcode']:
|
||||
location['deskCode'] = sys.argv[i+1]
|
||||
@@ -7601,231 +7601,6 @@ def doCreateOrg():
|
||||
parent = body['parentOrgUnitPath']
|
||||
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):
|
||||
cd = buildGAPIObject('directory')
|
||||
if users is None:
|
||||
@@ -8950,18 +8725,6 @@ def doGetAliasInfo(alias_email=None):
|
||||
print(f' Group Email: {result["email"]}')
|
||||
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):
|
||||
if startDate is None and endDate is None:
|
||||
return activeTimeRanges
|
||||
@@ -9692,13 +9455,6 @@ def doDeleteAlias(alias_email=None):
|
||||
if not is_user or (not is_user and not is_group):
|
||||
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():
|
||||
cd = buildGAPIObject('directory')
|
||||
name = getOrgUnitItem(sys.argv[3])
|
||||
@@ -11062,178 +10818,6 @@ def doShowLicenses():
|
||||
line += f'{u_license[i]}: {u_license[i+1]}, '
|
||||
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=' ,'):
|
||||
lexer = shlex.shlex(entity, posix=True)
|
||||
lexer.whitespace = dataDelimiter
|
||||
@@ -12340,7 +11924,7 @@ def ProcessGAMCommand(args):
|
||||
elif argument in ['org', 'ou']:
|
||||
doCreateOrg()
|
||||
elif argument == 'resource':
|
||||
doCreateResourceCalendar()
|
||||
gapi.directory.resource.createResourceCalendar()
|
||||
elif argument in ['verify', 'verification']:
|
||||
doSiteVerifyShow()
|
||||
elif argument == 'schema':
|
||||
@@ -12370,9 +11954,9 @@ def ProcessGAMCommand(args):
|
||||
elif argument in ['export', 'vaultexport']:
|
||||
gapi.vault.createExport()
|
||||
elif argument in ['building']:
|
||||
doCreateBuilding()
|
||||
gapi.directory.resource.createBuilding()
|
||||
elif argument in ['feature']:
|
||||
doCreateFeature()
|
||||
gapi.directory.resource.createFeature()
|
||||
elif argument in ['alertfeedback']:
|
||||
doCreateAlertFeedback()
|
||||
elif argument in ['gcpfolder']:
|
||||
@@ -12398,7 +11982,7 @@ def ProcessGAMCommand(args):
|
||||
elif argument in ['ou', 'org']:
|
||||
doUpdateOrg()
|
||||
elif argument == 'resource':
|
||||
doUpdateResourceCalendar()
|
||||
gapi.directory.resource.updateResourceCalendar()
|
||||
elif argument == 'cros':
|
||||
doUpdateCros()
|
||||
elif argument == 'mobile':
|
||||
@@ -12426,9 +12010,9 @@ def ProcessGAMCommand(args):
|
||||
elif argument in ['project', 'projects', 'apiproject']:
|
||||
doUpdateProjects()
|
||||
elif argument in ['building']:
|
||||
doUpdateBuilding()
|
||||
gapi.directory.resource.updateBuilding()
|
||||
elif argument in ['feature']:
|
||||
doUpdateFeature()
|
||||
gapi.directory.resource.updateFeature()
|
||||
else:
|
||||
controlflow.invalid_argument_exit(argument, "gam update")
|
||||
sys.exit(0)
|
||||
@@ -12447,7 +12031,7 @@ def ProcessGAMCommand(args):
|
||||
elif argument in ['org', 'ou']:
|
||||
doGetOrgInfo()
|
||||
elif argument == 'resource':
|
||||
doGetResourceCalendarInfo()
|
||||
gapi.directory.resource.getResourceCalendarInfo()
|
||||
elif argument == 'cros':
|
||||
doGetCrosInfo()
|
||||
elif argument == 'mobile':
|
||||
@@ -12479,7 +12063,7 @@ def ProcessGAMCommand(args):
|
||||
elif argument in ['export', 'vaultexport']:
|
||||
gapi.vault.getExportInfo()
|
||||
elif argument in ['building']:
|
||||
doGetBuildingInfo()
|
||||
gapi.directory.resource.getBuildingInfo()
|
||||
else:
|
||||
controlflow.invalid_argument_exit(argument, "gam info")
|
||||
sys.exit(0)
|
||||
@@ -12501,7 +12085,7 @@ def ProcessGAMCommand(args):
|
||||
elif argument == 'org':
|
||||
doDeleteOrg()
|
||||
elif argument == 'resource':
|
||||
doDeleteResourceCalendar()
|
||||
gapi.directory.resource.deleteResourceCalendar()
|
||||
elif argument == 'mobile':
|
||||
doDeleteMobile()
|
||||
elif argument in ['schema', 'schemas']:
|
||||
@@ -12529,9 +12113,9 @@ def ProcessGAMCommand(args):
|
||||
elif argument in ['export', 'vaultexport']:
|
||||
gapi.vault.deleteExport()
|
||||
elif argument in ['building']:
|
||||
doDeleteBuilding()
|
||||
gapi.directory.resource.deleteBuilding()
|
||||
elif argument in ['feature']:
|
||||
doDeleteFeature()
|
||||
gapi.directory.resource.deleteFeature()
|
||||
elif argument in ['alert']:
|
||||
doDeleteOrUndeleteAlert('delete')
|
||||
elif argument in ['sakey', 'sakeys']:
|
||||
@@ -12571,7 +12155,7 @@ def ProcessGAMCommand(args):
|
||||
elif argument in ['orgs', 'ous']:
|
||||
doPrintOrgs()
|
||||
elif argument == 'resources':
|
||||
doPrintResourceCalendars()
|
||||
gapi.directory.resource.printResourceCalendars()
|
||||
elif argument == 'cros':
|
||||
doPrintCrosDevices()
|
||||
elif argument == 'crosactivity':
|
||||
@@ -12613,9 +12197,9 @@ def ProcessGAMCommand(args):
|
||||
elif argument in ['exports', 'vaultexports']:
|
||||
gapi.vault.printExports()
|
||||
elif argument in ['building', 'buildings']:
|
||||
doPrintBuildings()
|
||||
gapi.directory.resource.printBuildings()
|
||||
elif argument in ['feature', 'features']:
|
||||
doPrintFeatures()
|
||||
gapi.directory.resource.printFeatures()
|
||||
elif argument in ['project', 'projects']:
|
||||
doPrintShowProjects(True)
|
||||
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):
|
||||
nameOrID = nameOrID.lower()
|
||||
cg = __main__.UID_PATTERN.match(nameOrID)
|
||||
cg = UID_PATTERN.match(nameOrID)
|
||||
if cg:
|
||||
return cg.group(1)
|
||||
fields = 'exports(id,name),nextPageToken'
|
||||
@@ -399,7 +399,7 @@ def convertExportNameToID(v, nameOrID, matterId):
|
||||
|
||||
def convertHoldNameToID(v, nameOrID, matterId):
|
||||
nameOrID = nameOrID.lower()
|
||||
cg = __main__.UID_PATTERN.match(nameOrID)
|
||||
cg = UID_PATTERN.match(nameOrID)
|
||||
if cg:
|
||||
return cg.group(1)
|
||||
fields = 'holds(holdId,name),nextPageToken'
|
||||
@@ -414,7 +414,7 @@ def convertHoldNameToID(v, nameOrID, matterId):
|
||||
|
||||
def convertMatterNameToID(v, nameOrID):
|
||||
nameOrID = nameOrID.lower()
|
||||
cg = __main__.UID_PATTERN.match(nameOrID)
|
||||
cg = UID_PATTERN.match(nameOrID)
|
||||
if cg:
|
||||
return cg.group(1)
|
||||
fields = 'matters(matterId,name),nextPageToken'
|
||||
|
||||
Binary file not shown.
@@ -6,7 +6,7 @@ import platform
|
||||
import re
|
||||
|
||||
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_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)))'
|
||||
|
||||
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