mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-21 06:31:37 +00:00
310 lines
10 KiB
Python
310 lines
10 KiB
Python
import re
|
|
import sys
|
|
|
|
import gam
|
|
from gam.var import *
|
|
from gam import controlflow
|
|
from gam import display
|
|
from gam import gapi
|
|
from gam.gapi import errors as gapi_errors
|
|
from gam.gapi.directory import customer as gapi_directory_customer
|
|
|
|
|
|
def _get_customerid():
|
|
''' returns customerId with format C{customer_id}'''
|
|
gapi_directory_customer.setTrueCustomerId()
|
|
customer_id = GC_Values[GC_CUSTOMER_ID]
|
|
if customer_id[0] != 'C':
|
|
customer_id = 'C' + customer_id
|
|
return customer_id
|
|
|
|
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
|
|
for user in users:
|
|
print(f'Adding license {sku_name} to {user}')
|
|
gapi.call(lic.licenseAssignments(),
|
|
'insert',
|
|
soft_errors=True,
|
|
productId=productId,
|
|
skuId=skuId,
|
|
body={'userId': user})
|
|
|
|
|
|
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
|
|
for user in users:
|
|
print(f'Removing license {sku_name} from user {user}')
|
|
gapi.call(lic.licenseAssignments(),
|
|
'delete',
|
|
soft_errors=True,
|
|
productId=productId,
|
|
skuId=skuId,
|
|
userId=user)
|
|
|
|
|
|
def sync(users):
|
|
sku = sys.argv[5]
|
|
current_licenses = gam.getUsersToModify(entity_type='license',
|
|
entity=sku)
|
|
users_to_license = [user for user in users if user not in current_licenses]
|
|
users_to_unlicense = [user for user in current_licenses if user not in 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)
|
|
for user in users:
|
|
print(f'Changing user {user} from license {old_sku_name} to {sku_name}')
|
|
gapi.call(lic.licenseAssignments(),
|
|
'patch',
|
|
soft_errors=True,
|
|
productId=productId,
|
|
skuId=old_sku,
|
|
userId=user,
|
|
body={'skuId': skuId})
|
|
|
|
|
|
def print_(returnFields=None,
|
|
skus=None,
|
|
countsOnly=False,
|
|
returnCounts=False):
|
|
lic = build()
|
|
customer_id = _get_customerid()
|
|
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=customer_id,
|
|
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=customer_id,
|
|
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 = print_(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})'
|