Merge branches (#1377)

* Fix tests with apiclient >= 2.1

* disable MacOS 11 job

* info user grouptree and info cigroup membertree

* build updates
This commit is contained in:
Jay Lee
2021-05-04 08:12:35 -04:00
committed by GitHub
parent 784399f345
commit 72a683f2b1
3 changed files with 155 additions and 45 deletions

View File

@@ -12,10 +12,10 @@ defaults:
working-directory: src
env:
BUILD_PYTHON_VERSION: "3.9.4"
MIN_PYTHON_VERSION: "3.9.4"
BUILD_PYTHON_VERSION: "3.9.5"
MIN_PYTHON_VERSION: "3.9.5"
BUILD_OPENSSL_VERSION: "1.1.1k"
MIN_OPENSSL_VERSION: "1.1.1i"
MIN_OPENSSL_VERSION: "1.1.1k"
PATCHELF_VERSION: "0.12"
# PYINSTALLER_VERSION can be full commit hash or version like v4.20
PYINSTALLER_VERSION: "e20e74c03768d432d48665b8ef1e02511b16e4be"
@@ -65,7 +65,7 @@ jobs:
jid: 5
goal: "build"
gamos: "windows"
python: 3.9.4
python: 3.9 5
pyarch: "x64"
platform: "x86_64"
- os: windows-2019
@@ -73,7 +73,7 @@ jobs:
goal: "build"
gamos: "windows"
platform: "x86"
python: 3.9.4
python: 3.9.5
pyarch: "x86"
- os: ubuntu-20.04
goal: "test"
@@ -108,7 +108,7 @@ jobs:
path: |
~/python
~/ssl
key: ${{ matrix.os }}-${{ matrix.jid }}-20210407
key: ${{ matrix.os }}-${{ matrix.jid }}-20210504
- name: Set env variables
env:

View File

@@ -8731,7 +8731,11 @@ def doGetUserInfo(user_email=None):
i = 4
else:
user_email = _get_admin_email()
getSchemas = getAliases = getGroups = getLicenses = True
getSchemas = True
getAliases = True
getGroups = True
getCIGroups = False
getLicenses = True
projection = 'full'
customFieldMask = viewType = None
skus = sorted(SKUS)
@@ -8743,6 +8747,10 @@ def doGetUserInfo(user_email=None):
elif myarg == 'nogroups':
getGroups = False
i += 1
elif myarg == 'grouptree':
getCIGroups = True
getGroups = False
i += 1
elif myarg in ['nolicenses', 'nolicences']:
getLicenses = False
i += 1
@@ -9008,6 +9016,34 @@ def doGetUserInfo(user_email=None):
print(f' {group["name"]} <{group["email"]}>')
except gapi.errors.GapiForbiddenError:
print('No access to show user groups.')
elif getCIGroups:
memberships = gapi_cloudidentity_groups.get_membership_graph(user_email)
print('\nGroup Mmebership Tree:')
group_name_mapping = {}
group_displayname_mapping = {}
groups = memberships.get('groups', [])
for group in groups:
group_name = group.get('name')
group_key = group.get('groupKey', {})
group_email = group_key.get('id', '')
group_display_name = group.get('displayName', '')
group_name_mapping[group_name] = group_email
group_displayname_mapping[group_email] = group_display_name
edges = []
seen_group_count = {}
groups_with_multi_memberships = []
for adj in memberships.get('adjacencyList', []):
group_name = adj.get('group', '')
group_email = group_name_mapping[group_name]
for edge in adj.get('edges', []):
seen_group_count[group_email] = seen_group_count.get(group_email, 0) + 1
member_email = edge.get('preferredMemberKey', {}).get('id')
edges.append((member_email, group_email))
print_group_map(user_email, group_displayname_mapping, seen_group_count, edges, spaces=3, direct=True)
if max(seen_group_count.values()) > 1:
print()
print(' * user has multiple direct or inherited memberships in group')
print()
if getLicenses:
print('Licenses:')
lic = buildGAPIObject('licensing')
@@ -9023,6 +9059,19 @@ def doGetUserInfo(user_email=None):
for user_license in user_licenses:
print(f' {gapi_licensing._formatSKUIdDisplayName(user_license)}')
def print_group_map(parent, group_name_mappings, seen_group_count, edges, spaces=3, direct=False):
for a_parent, a_child in edges:
if a_parent == parent:
group_display_name = group_name_mappings[a_child]
if direct:
direction = 'direct'
else:
direction = 'inherited'
output = f'{" " * spaces}{group_display_name} <{a_child}> ({direction})'
if seen_group_count[a_child] > 1:
output += ' *'
print(output)
print_group_map(a_child, group_name_mappings, seen_group_count, edges, spaces+2)
def doGetAliasInfo(alias_email=None):
cd = buildGAPIObject('directory')

View File

@@ -13,8 +13,12 @@ from gam.gapi import cloudidentity as gapi_cloudidentity
from gam.gapi.directory import customer as gapi_directory_customer
def build():
return gapi_cloudidentity.build('cloudidentity')
def create():
ci = gapi_cloudidentity.build('cloudidentity_beta')
ci = build()
initialGroupConfig = 'EMPTY'
gapi_directory_customer.setTrueCustomerId()
parent = f'customers/{GC_Values[GC_CUSTOMER_ID]}'
@@ -66,7 +70,7 @@ def create():
def delete():
ci = gapi_cloudidentity.build('cloudidentity_beta')
ci = build()
group = sys.argv[3]
name = group_email_to_id(ci, group)
print(f'Deleting group {group}')
@@ -74,11 +78,12 @@ def delete():
def info():
ci = gapi_cloudidentity.build('cloudidentity_beta')
ci = build()
group = gam.normalizeEmailAddressOrUID(sys.argv[3])
getUsers = True
showJoinDate = True
showUpdateDate = False
showMemberTree = False
i = 4
while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '')
@@ -91,12 +96,15 @@ def info():
elif myarg == 'showupdatedate':
showUpdateDate = True
i += 1
elif myarg == 'membertree':
showMemberTree = True
i += 1
else:
controlflow.invalid_argument_exit(myarg, 'gam info cigroup')
name = group_email_to_id(ci, group)
basic_info = gapi.call(ci.groups(), 'get', name=name)
display.print_json(basic_info)
if getUsers:
if getUsers and not showMemberTree:
if not showJoinDate and not showUpdateDate:
view = 'BASIC'
pageSize = 1000
@@ -126,10 +134,42 @@ def info():
# f' {member.get("role", ROLE_MEMBER).lower()}: {member.get("email", member["id"])} ({member["type"].lower()})'
)
print(f'Total {len(members)} users in group')
elif showMemberTree:
print(' Member tree:')
global cached_group_members
cached_group_members = {}
print_member_tree(ci, name)
def print_member_tree(ci, group_id, spaces=2):
if not group_id in cached_group_members:
cached_group_members[group_id] = gapi.get_all_pages(ci.groups().memberships(),
'list',
'memberships',
parent=group_id,
fields='*',
pageSize=1000)
for member in cached_group_members[group_id]:
member_id = member.get('name', '')
member_id = member_id.split('/')[-1]
if member_id.isdigit():
member_type = 'user'
else:
member_type = 'group'
member_email = member.get('preferredMemberKey', {}).get('id')
relation_type = member.get('relationType', '').lower()
if member_type == 'user':
print(f'{" " * spaces}{member_email} - user')
elif member_type == 'group':
print(f'{" " * spaces}{member_email} - group')
group_id = group_email_to_id(ci, member_email)
print_member_tree(ci, group_id, spaces + 2)
else:
print(f'unknown member type: {member_type} for {member_email}')
def info_member():
ci = gapi_cloudidentity.build('cloudidentity_beta')
ci = build()
member = gam.normalizeEmailAddressOrUID(sys.argv[3])
group = gam.normalizeEmailAddressOrUID(sys.argv[4])
group_name = gapi.call(ci.groups(),
@@ -159,7 +199,7 @@ GROUP_ROLES_MAP = {
def print_():
ci = gapi_cloudidentity.build('cloudidentity_beta')
ci = build()
i = 3
members = membersCountOnly = managers = managersCountOnly = owners = ownersCountOnly = False
gapi_directory_customer.setTrueCustomerId()
@@ -343,8 +383,58 @@ def print_():
display.write_csv_file(csvRows, titles, 'Groups', todrive)
def _get_groups_list(ci=None, member=None, parent=None):
if not ci:
ci = build()
if not parent:
gapi_directory_customer.setTrueCustomerId()
parent = f'customers/{GC_Values[GC_CUSTOMER_ID]}'
gam.printGettingAllItems('Groups', member)
page_message = gapi.got_total_items_first_last_msg('Groups')
if member:
fields = 'nextPageToken,memberships(groupKey(id),relationType)'
try:
groups_to_get = gapi.get_all_pages(ci.groups().memberships(),
'searchTransitiveGroups',
'memberships',
throw_reasons=[gapi_errors.ErrorReason.FOUR_O_O],
message_attribute=['groupKey', 'id'],
page_message=page_message,
parent='groups/-',
query=member,
pageSize=1000,
fields=fields)
except googleapiclient.errors.HttpError:
controlflow.system_error_exit(
2,
f'enterprisemember requires Enterprise license')
return [group['groupKey']['id'] for group in groups_to_get if group['relationType'] == 'DIRECT']
else:
groups_to_get = gapi.get_all_pages(
ci.groups(),
'list',
'groups',
message_attribute=['groupKey', 'id'],
page_message=page_message,
parent=parent,
view='BASIC',
pageSize=1000,
fields='nextPageToken,groups(groupKey(id))')
return [group['groupKey']['id'] for group in groups_to_get]
def get_membership_graph(member):
ci = build()
query = f"member_key_id == '{member}' && 'cloudidentity.googleapis.com/groups.discussion_forum' in labels"
result = gapi.call(ci.groups().memberships(),
'getMembershipGraph',
parent='groups/-',
query=query)
return result.get('response')
def print_members():
ci = gapi_cloudidentity.build('cloudidentity_beta')
ci = build()
todrive = False
gapi_directory_customer.setTrueCustomerId()
parent = f'customers/{GC_Values[GC_CUSTOMER_ID]}'
@@ -381,36 +471,7 @@ def print_members():
controlflow.invalid_argument_exit(sys.argv[i],
'gam print cigroup-members')
if not groups_to_get:
gam.printGettingAllItems('Groups', usemember)
page_message = gapi.got_total_items_first_last_msg('Groups')
if usemember:
try:
groups_to_get = gapi.get_all_pages(ci.groups().memberships(),
'searchTransitiveGroups',
'memberships',
throw_reasons=[gapi_errors.ErrorReason.FOUR_O_O],
message_attribute=['groupKey', 'id'],
page_message=page_message,
parent='groups/-', query=usemember,
pageSize=1000,
fields='nextPageToken,memberships(groupKey(id),relationType)')
except googleapiclient.errors.HttpError:
controlflow.system_error_exit(
2,
f'enterprisemember requires Enterprise license')
groups_to_get = [group['groupKey']['id'] for group in groups_to_get if group['relationType'] == 'DIRECT']
else:
groups_to_get = gapi.get_all_pages(
ci.groups(),
'list',
'groups',
message_attribute=['groupKey', 'id'],
page_message=page_message,
parent=parent,
view='BASIC',
pageSize=1000,
fields='nextPageToken,groups(groupKey(id))')
groups_to_get = [group['groupKey']['id'] for group in groups_to_get]
groups_to_get = _get_groups_list(ci, usemember, parent)
i = 0
count = len(groups_to_get)
for group_email in groups_to_get:
@@ -489,7 +550,7 @@ def update():
]
return (role, expireTime, users_email)
ci = gapi_cloudidentity.build('cloudidentity_beta')
ci = build()
group = sys.argv[3]
myarg = sys.argv[4].lower()
items = []