Compare commits

..

7 Commits
v5.21 ... v5.22

Author SHA1 Message Date
Jay Lee
dd3e6420b6 Upgrade PyInstaller and hopefully fix Linux binary sizes 2020-10-01 09:30:29 -04:00
Jay Lee
d6a65861e0 GAM 5.22 2020-10-01 09:08:46 -04:00
Jay Lee
fe77ff3f60 stop pypy and nightly source tests that have been failing for awhile anyway 2020-10-01 08:36:00 -04:00
Jay Lee
326cccd525 Stop using batch for licensing
Licensing API seems to throw lots of errors on large batch and we weren't retrying temp errors. For now just stick with serial methods.
2020-10-01 07:36:23 -04:00
Ross Scroggs
b41ca0f0be More bug/pylint cleanup (#1258)
* More bug/pylint cleanup

* pylint cleanup groups.py

* Update GamCommands.txt
2020-09-30 16:56:42 -04:00
Jay Lee
02fa092775 fix reporting orgunit scoping 2020-09-30 16:44:48 -04:00
Ross Scroggs
57860dc5a6 Fix issue #1256 (#1257) 2020-09-30 09:43:42 -04:00
12 changed files with 62 additions and 75 deletions

View File

@@ -10,7 +10,7 @@ env:
- BUILD_OPENSSL_VERSION=1.1.1h - BUILD_OPENSSL_VERSION=1.1.1h
- MIN_OPENSSL_VERSION=1.1.1h - MIN_OPENSSL_VERSION=1.1.1h
- PATCHELF_VERSION=0.11 - PATCHELF_VERSION=0.11
- PYINSTALLER_COMMIT=ad39eb8df209d02636399ffdc44521a97886cf8c - PYINSTALLER_COMMIT=7aa19839c171d898b5cf957739083c4bb901607e
cache: cache:
directories: directories:
- $HOME/.cache/pip - $HOME/.cache/pip
@@ -64,14 +64,14 @@ jobs:
name: "Python 3.9 dev Source Testing" name: "Python 3.9 dev Source Testing"
language: python language: python
python: 3.9-dev python: 3.9-dev
- os: linux # - os: linux
name: "Python trunk nightly Source Testing" # name: "Python trunk nightly Source Testing"
language: python # language: python
python: nightly # python: nightly
- os: linux # - os: linux
name: "Python PyPi Source Testing" # name: "Python PyPi Source Testing"
language: python # language: python
python: pypy3 # python: pypy3
- os: osx - os: osx
name: "MacOS 10.13" name: "MacOS 10.13"
language: generic language: generic

View File

@@ -1027,7 +1027,10 @@ The following attributes are equivalent:
(colorindex|colorid <EventColorIndex>) (colorindex|colorid <EventColorIndex>)
(description <String>)| (description <String>)|
(end (allday <Date>)|<Time>)| (end (allday <Date>)|<Time>)|
(guestscaninviteothers <Boolean>)|
guestscantinviteothers| guestscantinviteothers|
(guestscanmodify <Boolean>)|
(guestscanseeothers <Boolean>)|
guestscantseeothers| guestscantseeothers|
hangoutsmeet| hangoutsmeet|
(location <String>)| (location <String>)|

View File

@@ -1,5 +1,3 @@
import csv
import gam import gam
from gam.var import * from gam.var import *
from gam import controlflow from gam import controlflow
@@ -9,7 +7,6 @@ from gam import utils
from gam.gapi import errors as gapi_errors from gam.gapi import errors as gapi_errors
from gam.gapi import cloudidentity as gapi_cloudidentity from gam.gapi import cloudidentity as gapi_cloudidentity
from gam.gapi.directory import customer as gapi_directory_customer from gam.gapi.directory import customer as gapi_directory_customer
from gam.gapi.directory import groups as gapi_directory_groups
def create(): def create():
@@ -583,14 +580,13 @@ def update():
name = membership_email_to_id(ci, parent, users_email[0]) name = membership_email_to_id(ci, parent, users_email[0])
addRoles = [] addRoles = []
removeRoles = [] removeRoles = []
new_role = {'role': role}
current_roles = gapi.call(ci.groups().memberships(), current_roles = gapi.call(ci.groups().memberships(),
'get', 'get',
name=name, name=name,
fields='roles').get('roles', []) fields='roles').get('roles', [])
current_roles = [role['name'] for role in current_roles] current_roles = [role['name'] for role in current_roles]
for crole in current_roles: for crole in current_roles:
if crole != ROLE_MEMBER and crole != role: if crole not in {ROLE_MEMBER, role}:
removeRoles.append(crole) removeRoles.append(crole)
if role not in current_roles: if role not in current_roles:
addRoles.append({'name': role}) addRoles.append({'name': role})

View File

@@ -1,7 +1,6 @@
import sys import sys
from gam.var import * from gam.var import *
from gam import controlflow
from gam import gapi from gam import gapi
from gam.gapi import directory as gapi_directory from gam.gapi import directory as gapi_directory
from gam import utils from gam import utils

View File

@@ -221,11 +221,11 @@ def info_member():
cd = gapi_directory.build() cd = gapi_directory.build()
memberKey = gam.normalizeEmailAddressOrUID(sys.argv[3]) memberKey = gam.normalizeEmailAddressOrUID(sys.argv[3])
groupKey = gam.normalizeEmailAddressOrUID(sys.argv[4]) groupKey = gam.normalizeEmailAddressOrUID(sys.argv[4])
info = gapi.call(cd.members(), member_info = gapi.call(cd.members(),
'get', 'get',
memberKey=memberKey, memberKey=memberKey,
groupKey=groupKey) groupKey=groupKey)
display.print_json(info) display.print_json(member_info)
GROUP_ARGUMENT_TO_PROPERTY_TITLE_MAP = { GROUP_ARGUMENT_TO_PROPERTY_TITLE_MAP = {
@@ -1146,7 +1146,7 @@ def update():
i += 2 i += 2
elif myarg == 'admincreated': elif myarg == 'admincreated':
use_cd_api = True use_cd_api = True
cd_body['adminCreated'] = getBoolean(sys.argv[i + 1], myarg) cd_body['adminCreated'] = gam.getBoolean(sys.argv[i + 1], myarg)
i += 2 i += 2
elif myarg == 'getbeforeupdate': elif myarg == 'getbeforeupdate':
gs_get_before_update = True gs_get_before_update = True
@@ -1242,5 +1242,3 @@ def getGroupAttrValue(myarg, value, gs_object, gs_body, function):
gs_body[attrib] = value gs_body[attrib] = value
return return
controlflow.invalid_argument_exit(myarg, f'gam {function} group') controlflow.invalid_argument_exit(myarg, f'gam {function} group')

View File

@@ -23,16 +23,16 @@ def delete():
def info(): def info():
cd = gapi_directory.build() cd = gapi_directory.build()
resourceId = sys.argv[3] resourceId = sys.argv[3]
info = gapi.call(cd.mobiledevices(), device_info = gapi.call(cd.mobiledevices(),
'get', 'get',
customerId=GC_Values[GC_CUSTOMER_ID], customerId=GC_Values[GC_CUSTOMER_ID],
resourceId=resourceId) resourceId=resourceId)
if 'deviceId' in info: if 'deviceId' in info:
info['deviceId'] = info['deviceId'].encode('unicode-escape').decode( device_info['deviceId'] = device_info['deviceId'].encode('unicode-escape').decode(
UTF8) UTF8)
attrib = 'securityPatchLevel' attrib = 'securityPatchLevel'
if attrib in info and int(info[attrib]): if attrib in info and int(device_info[attrib]):
info[attrib] = utils.formatTimestampYMDHMS(info[attrib]) device_info[attrib] = utils.formatTimestampYMDHMS(device_info[attrib])
display.print_json(info) display.print_json(info)
@@ -161,7 +161,7 @@ def print_():
def update(): def update():
cd = gapi_directory.build cd = gapi_directory.build()
resourceIds = sys.argv[3] resourceIds = sys.argv[3]
match_users = None match_users = None
doit = False doit = False
@@ -235,5 +235,3 @@ def update():
resourceId=device['resourceId'], resourceId=device['resourceId'],
body=body, body=body,
customerId=GC_Values[GC_CUSTOMER_ID]) customerId=GC_Values[GC_CUSTOMER_ID])

View File

@@ -7,7 +7,6 @@ from gam import display
from gam import gapi from gam import gapi
from gam.gapi import directory as gapi_directory from gam.gapi import directory as gapi_directory
from gam.gapi import errors as gapi_errors from gam.gapi import errors as gapi_errors
from gam import utils
def create(): def create():
@@ -229,12 +228,12 @@ def update():
if sys.argv[4].lower() in ['move', 'add']: if sys.argv[4].lower() in ['move', 'add']:
entity_type = sys.argv[5].lower() entity_type = sys.argv[5].lower()
if entity_type in usergroup_types: if entity_type in usergroup_types:
users = getUsersToModify(entity_type=entity_type, users = gam.getUsersToModify(entity_type=entity_type,
entity=sys.argv[6]) entity=sys.argv[6])
else: else:
entity_type = 'users' entity_type = 'users'
users = getUsersToModify(entity_type=entity_type, users = gam.getUsersToModify(entity_type=entity_type,
entity=sys.argv[5]) entity=sys.argv[5])
if (entity_type.startswith('cros')) or ( if (entity_type.startswith('cros')) or (
(entity_type == 'all') and (sys.argv[6].lower() == 'cros')): (entity_type == 'all') and (sys.argv[6].lower() == 'cros')):
for l in range(0, len(users), 50): for l in range(0, len(users), 50):
@@ -253,7 +252,7 @@ def update():
for user in users: for user in users:
i += 1 i += 1
sys.stderr.write( sys.stderr.write(
f' moving {user} to {orgUnitPath}{currentCountNL(i, count)}' f' moving {user} to {orgUnitPath}{gam.currentCountNL(i, count)}'
) )
try: try:
gapi.call(cd.users(), gapi.call(cd.users(),
@@ -377,7 +376,7 @@ def getTopLevelOrgId(cd, orgUnitPath):
def getOrgUnitId(orgUnit, cd=None): def getOrgUnitId(orgUnit, cd=None):
if cd is None: if cd is None:
cd = buildGAPIObject('directory') cd = gapi_directory.build()
orgUnit = getOrgUnitItem(orgUnit) orgUnit = getOrgUnitItem(orgUnit)
if orgUnit[:3] == 'id:': if orgUnit[:3] == 'id:':
return (orgUnit, orgUnit) return (orgUnit, orgUnit)

View File

@@ -15,7 +15,7 @@ def flatten_privilege_list(privs, parent=None):
parent=priv['privilegeName']) parent=priv['privilegeName'])
priv['children'] = ' '.join( priv['children'] = ' '.join(
[child['privilegeName'] for child in children]) [child['privilegeName'] for child in children])
del (priv['childPrivileges']) del priv['childPrivileges']
flat_privs = flat_privs + children flat_privs = flat_privs + children
flat_privs.append(priv) flat_privs.append(priv)
return flat_privs return flat_privs

View File

@@ -28,5 +28,3 @@ def turn_off_2sv(users):
'turnOff', 'turnOff',
soft_errors=True, soft_errors=True,
userKey=user) userKey=user)

View File

@@ -35,6 +35,7 @@ def user_lic_result(request_id, response, exception):
soft_errors=True) soft_errors=True)
print(f'ERROR: {request_id}: {http_status} - {reason} {message}') print(f'ERROR: {request_id}: {http_status} - {reason} {message}')
def create(users, sku=None): def create(users, sku=None):
lic = build() lic = build()
if not sku: if not sku:
@@ -45,17 +46,15 @@ def create(users, sku=None):
if len(sys.argv) > 6 and sys.argv[i].lower() in ['product', 'productid']: if len(sys.argv) > 6 and sys.argv[i].lower() in ['product', 'productid']:
productId = sys.argv[i+1] productId = sys.argv[i+1]
i += 2 i += 2
lbatch = lic.new_batch_http_request(callback=user_lic_result)
for user in users: for user in users:
print(f'Adding license {sku_name} from user {user}') print(f'Adding license {sku_name} from to {user}')
body = {'userId': user} gapi.call(lic.licenseAssignments(),
lbatch.add(lic.licenseAssignments().insert( 'insert',
productId=productId, skuId=skuId, body=body), request_id=user) soft_errors=True,
if len(lbatch._order) == 1000: productId=productId,
lbatch.execute() skuId=skuId,
lbatch = lic.new_batch_http_request(callback=user_lic_result) body={'userId': user})
if len(lbatch._order) > 0:
lbatch.execute()
def delete(users, sku=None): def delete(users, sku=None):
lic = build() lic = build()
@@ -67,16 +66,15 @@ def delete(users, sku=None):
if len(sys.argv) > 6 and sys.argv[i].lower() in ['product', 'productid']: if len(sys.argv) > 6 and sys.argv[i].lower() in ['product', 'productid']:
productId = sys.argv[i+1] productId = sys.argv[i+1]
i += 2 i += 2
lbatch = lic.new_batch_http_request(callback=user_lic_result)
for user in users: for user in users:
print(f'Removing license {sku_name} from user {user}') print(f'Removing license {sku_name} from user {user}')
lbatch.add(lic.licenseAssignments().delete( gapi.call(lic.licenseAssignments(),
productId=productId, skuId=skuId, userId=user), request_id=user) 'delete',
if len(lbatch._order) == 1000: soft_errors=True,
lbatch.execute() productId=productId,
lbatch = lic.new_batch_http_request(callback=user_lic_result) skuId=skuId,
if len(lbatch._order) > 0: userId=user)
lbatch.execute()
def sync(users): def sync(users):
sku = sys.argv[5] sku = sys.argv[5]
@@ -113,18 +111,15 @@ def update(users, sku=None, old_sku=None):
) )
_, old_sku = getProductAndSKU(old_sku) _, old_sku = getProductAndSKU(old_sku)
old_sku_name = _formatSKUIdDisplayName(old_sku) old_sku_name = _formatSKUIdDisplayName(old_sku)
lbatch = lic.new_batch_http_request(callback=user_lic_result)
for user in users: for user in users:
print(f'Changing user {user} from license {old_sku_name} to {sku_name}') print(f'Changing user {user} from license {old_sku_name} to {sku_name}')
body = {'skuId': skuId} gapi.call(lic.licenseAssignments(),
lbatch.add(lic.licenseAssignments().patch( 'patch',
productId=productId, skuId=old_sku, userId=user, body=body), soft_errors=True,
request_id=user) productId=productId,
if len(lbatch._order) == 1000: skuId=old_sku,
lbatch.execute() userId=user,
lbatch = lic.new_batch_http_request(callback=user_lic_result) body={'skuId': skuId})
if len(lbatch._order) > 0:
lbatch.execute()
def print_(returnFields=None, def print_(returnFields=None,

View File

@@ -11,6 +11,7 @@ from gam import controlflow
from gam import display from gam import display
from gam import gapi from gam import gapi
from gam import utils from gam import utils
from gam.gapi.directory import orgunits as gapi_directory_orgunits
def build(): def build():
@@ -178,7 +179,7 @@ def showUsage():
skip_day_numbers = [dow.index(d) for d in skipdaynames if d in dow] skip_day_numbers = [dow.index(d) for d in skipdaynames if d in dow]
i += 2 i += 2
elif report == 'user' and myarg in ['orgunit', 'org', 'ou']: elif report == 'user' and myarg in ['orgunit', 'org', 'ou']:
_, orgUnitId = gam.getOrgUnitId(sys.argv[i + 1]) _, orgUnitId = gapi_directory_orgunits.getOrgUnitId(sys.argv[i + 1])
i += 2 i += 2
elif report == 'user' and myarg in usergroup_types: elif report == 'user' and myarg in usergroup_types:
users = gam.getUsersToModify(myarg, sys.argv[i + 1]) users = gam.getUsersToModify(myarg, sys.argv[i + 1])
@@ -296,7 +297,7 @@ def showReport():
tryDate = utils.get_yyyymmdd(sys.argv[i + 1]) tryDate = utils.get_yyyymmdd(sys.argv[i + 1])
i += 2 i += 2
elif myarg in ['orgunit', 'org', 'ou']: elif myarg in ['orgunit', 'org', 'ou']:
_, orgUnitId = gam.getOrgUnitId(sys.argv[i + 1]) _, orgUnitId = gapi_directory_orgunits.getOrgUnitId(sys.argv[i + 1])
i += 2 i += 2
elif myarg == 'fulldatarequired': elif myarg == 'fulldatarequired':
fullDataRequired = [] fullDataRequired = []

View File

@@ -8,7 +8,7 @@ import platform
import re import re
GAM_AUTHOR = 'Jay Lee <jay0lee@gmail.com>' GAM_AUTHOR = 'Jay Lee <jay0lee@gmail.com>'
GAM_VERSION = '5.21' GAM_VERSION = '5.22'
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'