mirror of
https://github.com/GAM-team/GAM.git
synced 2025-07-09 22:23:35 +00:00
'gam sync licenses' command, move licensing to separate file
This commit is contained in:
@ -63,6 +63,7 @@ from gam.gapi.directory import privileges as gapi_directory_privileges
|
||||
from gam.gapi.directory import resource as gapi_directory_resource
|
||||
from gam.gapi.directory import roles as gapi_directory_roles
|
||||
from gam.gapi.directory import users as gapi_directory_users
|
||||
from gam.gapi import licensing as gapi_licensing
|
||||
from gam.gapi import siteverification as gapi_siteverification
|
||||
from gam.gapi import errors as gapi_errors
|
||||
from gam.gapi import reports as gapi_reports
|
||||
@ -4305,73 +4306,6 @@ def getImap(users):
|
||||
)
|
||||
|
||||
|
||||
def getProductAndSKU(sku):
|
||||
l_sku = sku.lower().replace('-', '').replace(' ', '')
|
||||
for a_sku, sku_values in list(SKUS.items()):
|
||||
if l_sku == a_sku.lower().replace(
|
||||
'-',
|
||||
'') or l_sku in sku_values['aliases'] or l_sku == sku_values[
|
||||
'displayName'].lower().replace(' ', ''):
|
||||
return (sku_values['product'], a_sku)
|
||||
try:
|
||||
product = re.search('^([A-Z,a-z]*-[A-Z,a-z]*)', sku).group(1)
|
||||
except AttributeError:
|
||||
product = sku
|
||||
return (product, sku)
|
||||
|
||||
|
||||
def doLicense(users, operation):
|
||||
lic = buildGAPIObject('licensing')
|
||||
sku = sys.argv[5]
|
||||
productId, skuId = getProductAndSKU(sku)
|
||||
i = 6
|
||||
if len(sys.argv) > 6 and sys.argv[i].lower() in ['product', 'productid']:
|
||||
productId = sys.argv[i + 1]
|
||||
i += 2
|
||||
for user in users:
|
||||
if operation == 'delete':
|
||||
print(
|
||||
f'Removing license {_formatSKUIdDisplayName(skuId)} from user {user}'
|
||||
)
|
||||
gapi.call(lic.licenseAssignments(),
|
||||
operation,
|
||||
soft_errors=True,
|
||||
productId=productId,
|
||||
skuId=skuId,
|
||||
userId=user)
|
||||
elif operation == 'insert':
|
||||
print(
|
||||
f'Adding license {_formatSKUIdDisplayName(skuId)} to user {user}'
|
||||
)
|
||||
gapi.call(lic.licenseAssignments(),
|
||||
operation,
|
||||
soft_errors=True,
|
||||
productId=productId,
|
||||
skuId=skuId,
|
||||
body={'userId': user})
|
||||
elif operation == 'patch':
|
||||
try:
|
||||
old_sku = sys.argv[i]
|
||||
if old_sku.lower() == 'from':
|
||||
old_sku = sys.argv[i + 1]
|
||||
except KeyError:
|
||||
controlflow.system_error_exit(
|
||||
2,
|
||||
'You need to specify the user\'s old SKU as the last argument'
|
||||
)
|
||||
_, old_sku = getProductAndSKU(old_sku)
|
||||
print(
|
||||
f'Changing user {user} from license {_formatSKUIdDisplayName(old_sku)} to {_formatSKUIdDisplayName(skuId)}'
|
||||
)
|
||||
gapi.call(lic.licenseAssignments(),
|
||||
operation,
|
||||
soft_errors=True,
|
||||
productId=productId,
|
||||
skuId=old_sku,
|
||||
userId=user,
|
||||
body={'skuId': skuId})
|
||||
|
||||
|
||||
def doPop(users):
|
||||
enable = getBoolean(sys.argv[4], 'gam <users> pop')
|
||||
body = {
|
||||
@ -8434,7 +8368,7 @@ def _getResoldSubscriptionAttr(arg, customerId):
|
||||
arg[i + 2], 'maximumNumberOfSeats', minVal=0)
|
||||
i += 1
|
||||
elif myarg in ['sku', 'skuid']:
|
||||
_, body['skuId'] = getProductAndSKU(arg[i + 1])
|
||||
_, body['skuId'] = gapi_licensing.getProductAndSKU(arg[i + 1])
|
||||
elif myarg in ['customerauthtoken', 'transfertoken']:
|
||||
customerAuthToken = arg[i + 1]
|
||||
else:
|
||||
@ -8813,25 +8747,14 @@ def doGetUserInfo(user_email=None):
|
||||
lbatch = lic.new_batch_http_request(callback=user_lic_result)
|
||||
user_licenses = []
|
||||
for sku in skus:
|
||||
productId, skuId = getProductAndSKU(sku)
|
||||
productId, skuId = gapi_licensing.getProductAndSKU(sku)
|
||||
lbatch.add(lic.licenseAssignments().get(userId=user_email,
|
||||
productId=productId,
|
||||
skuId=skuId,
|
||||
fields='skuId'))
|
||||
lbatch.execute()
|
||||
for user_license in user_licenses:
|
||||
print(f' {_formatSKUIdDisplayName(user_license)}')
|
||||
|
||||
|
||||
def _skuIdToDisplayName(skuId):
|
||||
return SKUS[skuId]['displayName'] if skuId in SKUS else skuId
|
||||
|
||||
|
||||
def _formatSKUIdDisplayName(skuId):
|
||||
skuIdDisplay = _skuIdToDisplayName(skuId)
|
||||
if skuId == skuIdDisplay:
|
||||
return skuId
|
||||
return f'{skuId} ({skuIdDisplay})'
|
||||
print(f' {gapi_licensing._formatSKUIdDisplayName(user_license)}')
|
||||
|
||||
|
||||
def doGetAliasInfo(alias_email=None):
|
||||
@ -9521,13 +9444,13 @@ def doPrintUsers():
|
||||
[groupname['email'] for groupname in groups])
|
||||
if getLicenseFeed:
|
||||
titles.append('Licenses')
|
||||
licenses = doPrintLicenses(returnFields='userId,skuId')
|
||||
licenses = gapi_licensing.print_(returnFields='userId,skuId')
|
||||
if licenses:
|
||||
for user in csvRows:
|
||||
u_licenses = licenses.get(user['primaryEmail'].lower())
|
||||
if u_licenses:
|
||||
user['Licenses'] = licenseDelimiter.join(
|
||||
[_skuIdToDisplayName(skuId) for skuId in u_licenses])
|
||||
[gapi_licensing._skuIdToDisplayName(skuId) for skuId in u_licenses])
|
||||
display.write_csv_file(csvRows, titles, 'Users', todrive)
|
||||
|
||||
|
||||
@ -9664,172 +9587,6 @@ def doPrintAliases():
|
||||
display.write_csv_file(csvRows, titles, 'Aliases', todrive)
|
||||
|
||||
|
||||
def doPrintLicenses(returnFields=None,
|
||||
skus=None,
|
||||
countsOnly=False,
|
||||
returnCounts=False):
|
||||
lic = buildGAPIObject('licensing')
|
||||
products = []
|
||||
licenses = []
|
||||
licenseCounts = []
|
||||
if not returnFields:
|
||||
csvRows = []
|
||||
todrive = False
|
||||
i = 3
|
||||
while i < len(sys.argv):
|
||||
myarg = sys.argv[i].lower()
|
||||
if not returnCounts and myarg == 'todrive':
|
||||
todrive = True
|
||||
i += 1
|
||||
elif myarg in ['products', 'product']:
|
||||
products = sys.argv[i + 1].split(',')
|
||||
i += 2
|
||||
elif myarg in ['sku', 'skus']:
|
||||
skus = sys.argv[i + 1].split(',')
|
||||
i += 2
|
||||
elif myarg == 'allskus':
|
||||
skus = sorted(SKUS)
|
||||
products = []
|
||||
i += 1
|
||||
elif myarg == 'gsuite':
|
||||
skus = [
|
||||
skuId for skuId in SKUS
|
||||
if SKUS[skuId]['product'] in ['Google-Apps', '101031']
|
||||
]
|
||||
products = []
|
||||
i += 1
|
||||
elif myarg == 'countsonly':
|
||||
countsOnly = True
|
||||
i += 1
|
||||
else:
|
||||
controlflow.invalid_argument_exit(sys.argv[i],
|
||||
'gam print licenses')
|
||||
if not countsOnly:
|
||||
fields = 'nextPageToken,items(productId,skuId,userId)'
|
||||
titles = ['userId', 'productId', 'skuId']
|
||||
else:
|
||||
fields = 'nextPageToken,items(userId)'
|
||||
if not returnCounts:
|
||||
if skus:
|
||||
titles = ['productId', 'skuId', 'licenses']
|
||||
else:
|
||||
titles = ['productId', 'licenses']
|
||||
else:
|
||||
fields = f'nextPageToken,items({returnFields})'
|
||||
if skus:
|
||||
for sku in skus:
|
||||
if not products:
|
||||
product, sku = getProductAndSKU(sku)
|
||||
else:
|
||||
product = products[0]
|
||||
page_message = gapi.got_total_items_msg(
|
||||
f'Licenses for {SKUS.get(sku, {"displayName": sku})["displayName"]}',
|
||||
'...\n')
|
||||
try:
|
||||
licenses += gapi.get_all_pages(
|
||||
lic.licenseAssignments(),
|
||||
'listForProductAndSku',
|
||||
'items',
|
||||
throw_reasons=[
|
||||
gapi_errors.ErrorReason.INVALID,
|
||||
gapi_errors.ErrorReason.FORBIDDEN
|
||||
],
|
||||
page_message=page_message,
|
||||
customerId=GC_Values[GC_DOMAIN],
|
||||
productId=product,
|
||||
skuId=sku,
|
||||
fields=fields)
|
||||
if countsOnly:
|
||||
licenseCounts.append([
|
||||
'Product', product, 'SKU', sku, 'Licenses',
|
||||
len(licenses)
|
||||
])
|
||||
licenses = []
|
||||
except (gapi_errors.GapiInvalidError,
|
||||
gapi_errors.GapiForbiddenError):
|
||||
pass
|
||||
else:
|
||||
if not products:
|
||||
products = sorted(PRODUCTID_NAME_MAPPINGS)
|
||||
for productId in products:
|
||||
page_message = gapi.got_total_items_msg(
|
||||
f'Licenses for {PRODUCTID_NAME_MAPPINGS.get(productId, productId)}',
|
||||
'...\n')
|
||||
try:
|
||||
licenses += gapi.get_all_pages(
|
||||
lic.licenseAssignments(),
|
||||
'listForProduct',
|
||||
'items',
|
||||
throw_reasons=[
|
||||
gapi_errors.ErrorReason.INVALID,
|
||||
gapi_errors.ErrorReason.FORBIDDEN
|
||||
],
|
||||
page_message=page_message,
|
||||
customerId=GC_Values[GC_DOMAIN],
|
||||
productId=productId,
|
||||
fields=fields)
|
||||
if countsOnly:
|
||||
licenseCounts.append(
|
||||
['Product', productId, 'Licenses',
|
||||
len(licenses)])
|
||||
licenses = []
|
||||
except (gapi_errors.GapiInvalidError,
|
||||
gapi_errors.GapiForbiddenError):
|
||||
pass
|
||||
if countsOnly:
|
||||
if returnCounts:
|
||||
return licenseCounts
|
||||
if skus:
|
||||
for u_license in licenseCounts:
|
||||
csvRows.append({
|
||||
'productId': u_license[1],
|
||||
'skuId': u_license[3],
|
||||
'licenses': u_license[5]
|
||||
})
|
||||
else:
|
||||
for u_license in licenseCounts:
|
||||
csvRows.append({
|
||||
'productId': u_license[1],
|
||||
'licenses': u_license[3]
|
||||
})
|
||||
display.write_csv_file(csvRows, titles, 'Licenses', todrive)
|
||||
return
|
||||
if returnFields:
|
||||
if returnFields == 'userId':
|
||||
userIds = []
|
||||
for u_license in licenses:
|
||||
userId = u_license.get('userId', '').lower()
|
||||
if userId:
|
||||
userIds.append(userId)
|
||||
return userIds
|
||||
userSkuIds = {}
|
||||
for u_license in licenses:
|
||||
userId = u_license.get('userId', '').lower()
|
||||
skuId = u_license.get('skuId')
|
||||
if userId and skuId:
|
||||
userSkuIds.setdefault(userId, [])
|
||||
userSkuIds[userId].append(skuId)
|
||||
return userSkuIds
|
||||
for u_license in licenses:
|
||||
userId = u_license.get('userId', '').lower()
|
||||
skuId = u_license.get('skuId', '')
|
||||
csvRows.append({
|
||||
'userId': userId,
|
||||
'productId': u_license.get('productId', ''),
|
||||
'skuId': _skuIdToDisplayName(skuId)
|
||||
})
|
||||
display.write_csv_file(csvRows, titles, 'Licenses', todrive)
|
||||
|
||||
|
||||
def doShowLicenses():
|
||||
licenseCounts = doPrintLicenses(countsOnly=True, returnCounts=True)
|
||||
for u_license in licenseCounts:
|
||||
line = ''
|
||||
for i in range(0, len(u_license), 2):
|
||||
line += f'{u_license[i]}: {u_license[i+1]}, '
|
||||
print(line[:-2])
|
||||
|
||||
|
||||
def shlexSplitList(entity, dataDelimiter=' ,'):
|
||||
lexer = shlex.shlex(entity, posix=True)
|
||||
lexer.whitespace = dataDelimiter
|
||||
@ -10044,7 +9801,7 @@ def getUsersToModify(entity_type=None,
|
||||
if not silent:
|
||||
sys.stderr.write('done.\r\n')
|
||||
elif entity_type in ['license', 'licenses', 'licence', 'licences']:
|
||||
users = doPrintLicenses(returnFields='userId', skus=entity.split(','))
|
||||
users = gapi_licensing.print_(returnFields='userId', skus=entity.split(','))
|
||||
elif entity_type in ['file', 'crosfile']:
|
||||
users = []
|
||||
f = fileutils.open_file(entity, strip_utf_bom=True)
|
||||
@ -11456,7 +11213,7 @@ def ProcessGAMCommand(args):
|
||||
elif argument == 'mobile':
|
||||
gapi_directory_mobiledevices.print_()
|
||||
elif argument in ['license', 'licenses', 'licence', 'licences']:
|
||||
doPrintLicenses()
|
||||
gapi_licensing.print_()
|
||||
elif argument in ['token', 'tokens', 'oauth', '3lo']:
|
||||
printShowTokens(3, None, None, True)
|
||||
elif argument in ['schema', 'schemas']:
|
||||
@ -11505,7 +11262,7 @@ def ProcessGAMCommand(args):
|
||||
elif argument in ['guardian', 'guardians']:
|
||||
doPrintShowGuardians(False)
|
||||
elif argument in ['license', 'licenses', 'licence', 'licences']:
|
||||
doShowLicenses()
|
||||
gapi_licensing.show_()
|
||||
elif argument in ['project', 'projects']:
|
||||
doPrintShowProjects(False)
|
||||
elif argument in ['sakey', 'sakeys']:
|
||||
@ -11595,6 +11352,13 @@ def ProcessGAMCommand(args):
|
||||
else:
|
||||
controlflow.invalid_argument_exit(argument, 'gam rotate')
|
||||
sys.exit(0)
|
||||
elif command == 'sync':
|
||||
argument = sys.argv[2].lower()
|
||||
if argument in ['sku', 'skus', 'license', 'licenses']:
|
||||
gapi_licensing.sync()
|
||||
else:
|
||||
controlflow.invalid_argument_exit(argument, 'gam sync')
|
||||
sys.exit(0)
|
||||
elif command in ['cancelwipe', 'wipe', 'approve', 'block', 'sync']:
|
||||
target = sys.argv[2].lower().replace('_', '')
|
||||
if target in ['device', 'devices']:
|
||||
@ -11773,7 +11537,7 @@ def ProcessGAMCommand(args):
|
||||
elif delWhat == 'photo':
|
||||
deletePhoto(users)
|
||||
elif delWhat in ['license', 'licence']:
|
||||
doLicense(users, 'delete')
|
||||
gapi_licensing.delete(users)
|
||||
elif delWhat in ['backupcode', 'backupcodes', 'verificationcodes']:
|
||||
doDelBackupCodes(users)
|
||||
elif delWhat in ['asp', 'asps', 'applicationspecificpasswords']:
|
||||
@ -11815,7 +11579,7 @@ def ProcessGAMCommand(args):
|
||||
elif addWhat == 'drivefile':
|
||||
createDriveFile(users)
|
||||
elif addWhat in ['license', 'licence']:
|
||||
doLicense(users, 'insert')
|
||||
gapi_licensing.create(users)
|
||||
elif addWhat in ['drivefileacl', 'drivefileacls']:
|
||||
addDriveFileACL(users)
|
||||
elif addWhat in ['label', 'labels']:
|
||||
@ -11844,7 +11608,7 @@ def ProcessGAMCommand(args):
|
||||
elif updateWhat == 'photo':
|
||||
doPhoto(users)
|
||||
elif updateWhat in ['license', 'licence']:
|
||||
doLicense(users, 'patch')
|
||||
gapi_licensing.update(users)
|
||||
elif updateWhat == 'user':
|
||||
doUpdateUser(users, 5)
|
||||
elif updateWhat in [
|
||||
|
318
src/gam/gapi/licensing.py
Normal file
318
src/gam/gapi/licensing.py
Normal file
@ -0,0 +1,318 @@
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
import googleapiclient
|
||||
|
||||
import gam
|
||||
from gam.var import *
|
||||
from gam import display
|
||||
from gam import gapi
|
||||
from gam import fileutils
|
||||
from gam.gapi import errors as gapi_errors
|
||||
from gam.gapi.directory import groups as gapi_directory_groups
|
||||
from gam import utils
|
||||
|
||||
|
||||
def build():
|
||||
return gam.buildGAPIObject('licensing')
|
||||
|
||||
|
||||
def getProductAndSKU(sku):
|
||||
l_sku = sku.lower().replace('-', '').replace(' ', '')
|
||||
for a_sku, sku_values in list(SKUS.items()):
|
||||
if l_sku == a_sku.lower().replace(
|
||||
'-',
|
||||
'') or l_sku in sku_values['aliases'] or l_sku == sku_values[
|
||||
'displayName'].lower().replace(' ', ''):
|
||||
return (sku_values['product'], a_sku)
|
||||
try:
|
||||
product = re.search('^([A-Z,a-z]*-[A-Z,a-z]*)', sku).group(1)
|
||||
except AttributeError:
|
||||
product = sku
|
||||
return (product, sku)
|
||||
|
||||
|
||||
def user_lic_result(request_id, response, exception):
|
||||
if exception:
|
||||
http_status, reason, message = gapi_errors.get_gapi_error_detail(
|
||||
exception,
|
||||
soft_errors=True)
|
||||
print(f'ERROR: {request_id}: {http_status} - {reason} {message}')
|
||||
|
||||
def create(users, sku=None):
|
||||
lic = build()
|
||||
if not sku:
|
||||
sku = sys.argv[5]
|
||||
productId, skuId = getProductAndSKU(sku)
|
||||
sku_name = _formatSKUIdDisplayName(skuId)
|
||||
i = 6
|
||||
if len(sys.argv) > 6 and sys.argv[i].lower() in ['product', 'productid']:
|
||||
productId = sys.argv[i+1]
|
||||
i += 2
|
||||
lbatch = lic.new_batch_http_request(callback=user_lic_result)
|
||||
for user in users:
|
||||
print(f'Adding license {sku_name} from user {user}')
|
||||
body = {'userId': user}
|
||||
lbatch.add(lic.licenseAssignments().insert(
|
||||
productId=productId, skuId=skuId, body=body), request_id=user)
|
||||
if len(lbatch._order) == 1000:
|
||||
lbatch.execute()
|
||||
lbatch = lic.new_batch_http_request(callback=user_lic_result)
|
||||
if len(lbatch._order) > 0:
|
||||
lbatch.execute()
|
||||
|
||||
def delete(users, sku=None):
|
||||
lic = build()
|
||||
if not sku:
|
||||
sku = sys.argv[5]
|
||||
productId, skuId = getProductAndSKU(sku)
|
||||
sku_name = _formatSKUIdDisplayName(skuId)
|
||||
i = 6
|
||||
if len(sys.argv) > 6 and sys.argv[i].lower() in ['product', 'productid']:
|
||||
productId = sys.argv[i+1]
|
||||
i += 2
|
||||
lbatch = lic.new_batch_http_request(callback=user_lic_result)
|
||||
for user in users:
|
||||
print(f'Removing license {sku_name} from user {user}')
|
||||
lbatch.add(lic.licenseAssignments().delete(
|
||||
productId=productId, skuId=skuId, userId=user), request_id=user)
|
||||
if len(lbatch._order) == 1000:
|
||||
lbatch.execute()
|
||||
lbatch = lic.new_batch_http_request(callback=user_lic_result)
|
||||
if len(lbatch._order) > 0:
|
||||
lbatch.execute()
|
||||
|
||||
def sync():
|
||||
lic = build()
|
||||
sku = sys.argv[3]
|
||||
entity_type = sys.argv[4].lower()
|
||||
entity = sys.argv[5].lower()
|
||||
current_users = gam.getUsersToModify(entity_type, entity)
|
||||
current_licenses = gam.getUsersToModify(entity_type='license',
|
||||
entity=sku)
|
||||
users_to_license = [user for user in current_users if user not in current_licenses]
|
||||
users_to_unlicense = [user for user in current_licenses if user not in current_users]
|
||||
print(f'Need to remove license from {len(users_to_unlicense)} and add to ' \
|
||||
f'{len(users_to_license)} users...')
|
||||
# do the remove first to free up seats
|
||||
delete(users_to_unlicense, sku)
|
||||
create(users_to_license, sku)
|
||||
|
||||
|
||||
def update(users, sku=None, old_sku=None):
|
||||
lic = build()
|
||||
if not sku:
|
||||
sku = sys.argv[5]
|
||||
productId, skuId = getProductAndSKU(sku)
|
||||
sku_name = _formatSKUIdDisplayName(skuId)
|
||||
i = 6
|
||||
if len(sys.argv) > 6 and sys.argv[i].lower() in ['product', 'productid']:
|
||||
productId = sys.argv[i+1]
|
||||
i += 2
|
||||
if not old_sku:
|
||||
try:
|
||||
old_sku = sys.argv[i]
|
||||
if old_sku.lower() == 'from':
|
||||
old_sku = sys.argv[i + 1]
|
||||
except KeyError:
|
||||
controlflow.system_error_exit(
|
||||
2,
|
||||
'You need to specify the user\'s old SKU as the last argument'
|
||||
)
|
||||
_, old_sku = getProductAndSKU(old_sku)
|
||||
old_sku_name = _formatSKUIdDisplayName(old_sku)
|
||||
lbatch = lic.new_batch_http_request(callback=user_lic_result)
|
||||
for user in users:
|
||||
print(f'Changing user {user} from license {old_sku_name} to {sku_name}')
|
||||
body = {'skuId': skuId}
|
||||
lbatch.add(lic.licenseAssignments().patch(
|
||||
productId=productId, skuId=old_sku, userId=user, body=body),
|
||||
request_id=user)
|
||||
if len(lbatch._order) == 1000:
|
||||
lbatch.execute()
|
||||
lbatch = lic.new_batch_http_request(callback=user_lic_result)
|
||||
if len(lbatch._order) > 0:
|
||||
lbatch.execute()
|
||||
|
||||
|
||||
def print_(returnFields=None,
|
||||
skus=None,
|
||||
countsOnly=False,
|
||||
returnCounts=False):
|
||||
lic = build()
|
||||
products = []
|
||||
licenses = []
|
||||
licenseCounts = []
|
||||
if not returnFields:
|
||||
csvRows = []
|
||||
todrive = False
|
||||
i = 3
|
||||
while i < len(sys.argv):
|
||||
myarg = sys.argv[i].lower()
|
||||
if not returnCounts and myarg == 'todrive':
|
||||
todrive = True
|
||||
i += 1
|
||||
elif myarg in ['products', 'product']:
|
||||
products = sys.argv[i + 1].split(',')
|
||||
i += 2
|
||||
elif myarg in ['sku', 'skus']:
|
||||
skus = sys.argv[i + 1].split(',')
|
||||
i += 2
|
||||
elif myarg == 'allskus':
|
||||
skus = sorted(SKUS)
|
||||
products = []
|
||||
i += 1
|
||||
elif myarg == 'gsuite':
|
||||
skus = [
|
||||
skuId for skuId in SKUS
|
||||
if SKUS[skuId]['product'] in ['Google-Apps', '101031']
|
||||
]
|
||||
products = []
|
||||
i += 1
|
||||
elif myarg == 'countsonly':
|
||||
countsOnly = True
|
||||
i += 1
|
||||
else:
|
||||
controlflow.invalid_argument_exit(sys.argv[i],
|
||||
'gam print licenses')
|
||||
if not countsOnly:
|
||||
fields = 'nextPageToken,items(productId,skuId,userId)'
|
||||
titles = ['userId', 'productId', 'skuId']
|
||||
else:
|
||||
fields = 'nextPageToken,items(userId)'
|
||||
if not returnCounts:
|
||||
if skus:
|
||||
titles = ['productId', 'skuId', 'licenses']
|
||||
else:
|
||||
titles = ['productId', 'licenses']
|
||||
else:
|
||||
fields = f'nextPageToken,items({returnFields})'
|
||||
if skus:
|
||||
for sku in skus:
|
||||
if not products:
|
||||
product, sku = getProductAndSKU(sku)
|
||||
else:
|
||||
product = products[0]
|
||||
page_message = gapi.got_total_items_msg(
|
||||
f'Licenses for {SKUS.get(sku, {"displayName": sku})["displayName"]}',
|
||||
'...\n')
|
||||
try:
|
||||
licenses += gapi.get_all_pages(
|
||||
lic.licenseAssignments(),
|
||||
'listForProductAndSku',
|
||||
'items',
|
||||
throw_reasons=[
|
||||
gapi_errors.ErrorReason.INVALID,
|
||||
gapi_errors.ErrorReason.FORBIDDEN
|
||||
],
|
||||
page_message=page_message,
|
||||
customerId=GC_Values[GC_DOMAIN],
|
||||
productId=product,
|
||||
skuId=sku,
|
||||
fields=fields)
|
||||
if countsOnly:
|
||||
licenseCounts.append([
|
||||
'Product', product, 'SKU', sku, 'Licenses',
|
||||
len(licenses)
|
||||
])
|
||||
licenses = []
|
||||
except (gapi_errors.GapiInvalidError,
|
||||
gapi_errors.GapiForbiddenError):
|
||||
pass
|
||||
else:
|
||||
if not products:
|
||||
products = sorted(PRODUCTID_NAME_MAPPINGS)
|
||||
for productId in products:
|
||||
page_message = gapi.got_total_items_msg(
|
||||
f'Licenses for {PRODUCTID_NAME_MAPPINGS.get(productId, productId)}',
|
||||
'...\n')
|
||||
try:
|
||||
licenses += gapi.get_all_pages(
|
||||
lic.licenseAssignments(),
|
||||
'listForProduct',
|
||||
'items',
|
||||
throw_reasons=[
|
||||
gapi_errors.ErrorReason.INVALID,
|
||||
gapi_errors.ErrorReason.FORBIDDEN
|
||||
],
|
||||
page_message=page_message,
|
||||
customerId=GC_Values[GC_DOMAIN],
|
||||
productId=productId,
|
||||
fields=fields)
|
||||
if countsOnly:
|
||||
licenseCounts.append(
|
||||
['Product', productId, 'Licenses',
|
||||
len(licenses)])
|
||||
licenses = []
|
||||
except (gapi_errors.GapiInvalidError,
|
||||
gapi_errors.GapiForbiddenError):
|
||||
pass
|
||||
if countsOnly:
|
||||
if returnCounts:
|
||||
return licenseCounts
|
||||
if skus:
|
||||
for u_license in licenseCounts:
|
||||
csvRows.append({
|
||||
'productId': u_license[1],
|
||||
'skuId': u_license[3],
|
||||
'licenses': u_license[5]
|
||||
})
|
||||
else:
|
||||
for u_license in licenseCounts:
|
||||
csvRows.append({
|
||||
'productId': u_license[1],
|
||||
'licenses': u_license[3]
|
||||
})
|
||||
display.write_csv_file(csvRows, titles, 'Licenses', todrive)
|
||||
return
|
||||
if returnFields:
|
||||
if returnFields == 'userId':
|
||||
userIds = []
|
||||
for u_license in licenses:
|
||||
userId = u_license.get('userId', '').lower()
|
||||
if userId:
|
||||
userIds.append(userId)
|
||||
return userIds
|
||||
userSkuIds = {}
|
||||
for u_license in licenses:
|
||||
userId = u_license.get('userId', '').lower()
|
||||
skuId = u_license.get('skuId')
|
||||
if userId and skuId:
|
||||
userSkuIds.setdefault(userId, [])
|
||||
userSkuIds[userId].append(skuId)
|
||||
return userSkuIds
|
||||
for u_license in licenses:
|
||||
userId = u_license.get('userId', '').lower()
|
||||
skuId = u_license.get('skuId', '')
|
||||
csvRows.append({
|
||||
'userId': userId,
|
||||
'productId': u_license.get('productId', ''),
|
||||
'skuId': _skuIdToDisplayName(skuId)
|
||||
})
|
||||
display.write_csv_file(csvRows, titles, 'Licenses', todrive)
|
||||
|
||||
|
||||
def show():
|
||||
licenseCounts = doPrintLicenses(countsOnly=True, returnCounts=True)
|
||||
for u_license in licenseCounts:
|
||||
line = ''
|
||||
for i in range(0, len(u_license), 2):
|
||||
line += f'{u_license[i]}: {u_license[i+1]}, '
|
||||
print(line[:-2])
|
||||
|
||||
|
||||
def _skuIdToDisplayName(skuId):
|
||||
return SKUS[skuId]['displayName'] if skuId in SKUS else skuId
|
||||
|
||||
|
||||
def _formatSKUIdDisplayName(skuId):
|
||||
skuIdDisplay = _skuIdToDisplayName(skuId)
|
||||
if skuId == skuIdDisplay:
|
||||
return skuId
|
||||
return f'{skuId} ({skuIdDisplay})'
|
||||
|
||||
|
||||
|
@ -8,7 +8,7 @@ import platform
|
||||
import re
|
||||
|
||||
GAM_AUTHOR = 'Jay Lee <jay0lee@gmail.com>'
|
||||
GAM_VERSION = '5.20'
|
||||
GAM_VERSION = '5.21'
|
||||
GAM_LICENSE = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||
|
||||
GAM_URL = 'https://git.io/gam'
|
||||
|
Reference in New Issue
Block a user