Multiple updates

This commit is contained in:
Ross Scroggs
2023-09-15 19:44:26 -07:00
parent effa972a40
commit d16ce28ee5
25 changed files with 490 additions and 413 deletions

View File

@ -100,6 +100,7 @@ gam print aliases [todrive <ToDriveAttribute>*]
``` ```
By default, group and user aliases in all domains in the account are selected; these options allow selection of subsets of aliases: By default, group and user aliases in all domains in the account are selected; these options allow selection of subsets of aliases:
* `domain|domains <DomainNameEntity>` - Limit aliases to those in the domains specified by `<DomainNameEntity>` * `domain|domains <DomainNameEntity>` - Limit aliases to those in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `(query <QueryUser>)|(queries <QueryUserList>)` - Print aliases for users/groups that match a query; each query is run against each domain * `(query <QueryUser>)|(queries <QueryUserList>)` - Print aliases for users/groups that match a query; each query is run against each domain
* `limittoou <OrgUnitItem>` - Print aliases for users in the specified `<OrgUnitItem>` * `limittoou <OrgUnitItem>` - Print aliases for users in the specified `<OrgUnitItem>`
* `user|users <EmailAddressList>` - Print aliases for users in `<EmailAddressList` * `user|users <EmailAddressList>` - Print aliases for users in `<EmailAddressList`

View File

@ -371,12 +371,6 @@
<CourseWorkState> ::= draft|published|deleted <CourseWorkState> ::= draft|published|deleted
<CrOSID> ::= <String> <CrOSID> ::= <String>
<CustomerID> ::= <String> <CustomerID> ::= <String>
<DataStudioAssetID> ::= <String>
<DataStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<DeliverySetting> ::= <DeliverySetting> ::=
allmail| allmail|
abridged|daily| abridged|daily|
@ -452,6 +446,12 @@
<LabelID> ::= Label_<String> <LabelID> ::= Label_<String>
<LabelName> ::= <String> <LabelName> ::= <String>
<LabelReplacement> ::= <String> <LabelReplacement> ::= <String>
<LookerStudioAssetID> ::= <String>
<LookerStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<Marker> ::= <String> <Marker> ::= <String>
<MatterItem> ::= <UniqueID>|<String> <MatterItem> ::= <UniqueID>|<String>
<MatterState> ::= open|closed|deleted <MatterState> ::= open|closed|deleted

View File

@ -556,9 +556,13 @@ is also specified, the query applies to devices within the OUs.
- `(query <QueryCrOS>)|(queries <QueryCrOSList>)` - Select CrOS devices that match a query - `(query <QueryCrOS>)|(queries <QueryCrOSList>)` - Select CrOS devices that match a query
- `limittoou|cros_ou <OrgUnitItem>` - Select CrOS devices directly in the OU `<OrgUnitItem>` - `limittoou|cros_ou <OrgUnitItem>` - Select CrOS devices directly in the OU `<OrgUnitItem>`
- You can predefine this item with the `print_cros_ous` variable in `gam.cfg`.
- `cros_ou_and_children <OrgUnitItem>` - Select CrOS devices in the OU `<OrgUnitItem>` and its sub OUs - `cros_ou_and_children <OrgUnitItem>` - Select CrOS devices in the OU `<OrgUnitItem>` and its sub OUs
- You can predefine this item with the `print_cros_ous_and_children` variable in `gam.cfg`.
- `cros_ous <OrgUnitList>` - Select CrOS devices directly in the OUs `<OrgUnitList>` - `cros_ous <OrgUnitList>` - Select CrOS devices directly in the OUs `<OrgUnitList>`
- You can predefine this list with the `print_cros_ous` variable in `gam.cfg`.
- `cros_ous_and_children <OrgUnitList>` - Select CrOS devices in the OUs `<OrgUnitList>` and their sub OUs - `cros_ous_and_children <OrgUnitList>` - Select CrOS devices in the OUs `<OrgUnitList>` and their sub OUs
- You can predefine this list with the `print_cros_ous_and_children` variable in `gam.cfg`.
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryCrOS>` and `queries <QueryCrOSList>` options. Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryCrOS>` and `queries <QueryCrOSList>` options.
The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries. The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries.
@ -704,9 +708,13 @@ is also specified, the query applies to devices within the OUs.
- `(query <QueryCrOS>)|(queries <QueryCrOSList>)` - Select CrOS devices that match a query - `(query <QueryCrOS>)|(queries <QueryCrOSList>)` - Select CrOS devices that match a query
- `limittoou|cros_ou <OrgUnitItem>` - Select CrOS devices directly in the OU `<OrgUnitItem>` - `limittoou|cros_ou <OrgUnitItem>` - Select CrOS devices directly in the OU `<OrgUnitItem>`
- You can predefine this item with the `print_cros_ous` variable in `gam.cfg`.
- `cros_ou_and_children <OrgUnitItem>` - Select CrOS devices in the OU `<OrgUnitItem>` and its sub OUs - `cros_ou_and_children <OrgUnitItem>` - Select CrOS devices in the OU `<OrgUnitItem>` and its sub OUs
- You can predefine this item with the `print_cros_ous_and_children` variable in `gam.cfg`.
- `cros_ous <OrgUnitList>` - Select CrOS devices directly in the OUs `<OrgUnitList>` - `cros_ous <OrgUnitList>` - Select CrOS devices directly in the OUs `<OrgUnitList>`
- You can predefine this list with the `print_cros_ous` variable in `gam.cfg`.
- `cros_ous_and_children <OrgUnitList>` - Select CrOS devices in the OUs `<OrgUnitList>` and their sub OUs - `cros_ous_and_children <OrgUnitList>` - Select CrOS devices in the OUs `<OrgUnitList>` and their sub OUs
- You can predefine this list with the `print_cros_ous_and_children` variable in `gam.cfg`.
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryCrOS>` and `queries <QueryCrOSList>` options. Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryCrOS>` and `queries <QueryCrOSList>` options.
The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries. The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries.

View File

@ -165,10 +165,6 @@ Data fields identified in a `csvkmd` argument.
<CrOSEntity> ::= <CrOSEntity> ::=
<CrOSIDList> | (cros_sn <SerialNumberList>) | <CrOSIDList> | (cros_sn <SerialNumberList>) |
(query:<QueryCrOS>) | (query:orgunitpath:<OrgUnitPath>) | (query <QueryCrOS>) (query:<QueryCrOS>) | (query:orgunitpath:<OrgUnitPath>) | (query <QueryCrOS>)
<DataStudioAssetIDEntity> ::=
<DataStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DataStudioPermissionEntity> ::=
<DataStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DeviceIDEntity> ::= <DeviceIDEntity> ::=
<DeviceIDList> | (device_sn <SerialNumber>) <DeviceIDList> | (device_sn <SerialNumber>)
(query:<QueryDevice>) | (query <QueryDevice>) (query:<QueryDevice>) | (query <QueryDevice>)
@ -282,6 +278,10 @@ Data fields identified in a `csvkmd` argument.
<LabelIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector> <LabelIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LabelNameEntity> ::= <LabelNameEntity> ::=
<LabelNameList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector> <LabelNameList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LookerStudioAssetIDEntity> ::=
<LookerStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LookerStudioPermissionEntity> ::=
<LookerStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<MessageIDEntity> ::= <MessageIDEntity> ::=
<MessageIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector> <MessageIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<MobileEntity> ::= <MobileEntity> ::=

View File

@ -3,6 +3,7 @@
- [Windows Command Prompt](#windows-command-prompt) - [Windows Command Prompt](#windows-command-prompt)
- [Windows PowerShell](#windows-powershell) - [Windows PowerShell](#windows-powershell)
- [List quoting rules](#list-quoting-rules) - [List quoting rules](#list-quoting-rules)
- [Queries example](#queries-example)
## Linux and MacOS ## Linux and MacOS
@ -60,3 +61,19 @@ Typically, you will enclose the entire list in double quotes and quote each item
* ```"'it em' 'it,em' \"it'em\""``` * ```"'it em' 'it,em' \"it'em\""```
Typical places where these rules apply are lists of OUs and Contact Groups. Typical places where these rules apply are lists of OUs and Contact Groups.
## Queries example
### Linux and MacOS
```
gam print users queries "\"orgUnitPath='/Students/Lower School/2027'\",\"orgUnitPath='/Students/Lower School/2028'\""
```
### Windows Command Prompt
```
gam print users queries "\"orgUnitPath='/Students/Lower School/2027'\",\"orgUnitPath='/Students/Lower School/2028'\""
```
### Windows Power Shell
```
gam print users queries "`"orgUnitPath=\'/Students/Lower\ School/2027\'`",`"orgUnitPath=\'/Students/Lower\ School/2028\'`""
```

View File

@ -10,6 +10,27 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads) for Windows or other options, including manual installation. See [Downloads](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads) for Windows or other options, including manual installation.
### 6.63.15
Added `print_cros_ous` and `print_cros_ous_and_children` variables to `gam.cfg` that provide a default list of OUs for these commands:
```
gam print cros
gam print crosactivity
```
Updated `group` commands that manage members to handle the following error:
```
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
```
Updated Data Studio to Looker Studio; added the following command synonyms:
* `lookerstudioassets` for `datastudioassets`
* 'lookerstudiopermissions` for `datastudiopermissions`
Corrected error message in `gam add datastudiopermissions`:
* Old -`ERROR: Missing argument: Expected <DataStudioAssetMembersEntity>`
* New - `ERROR: Missing argument: Expected <LookerStudioPermissionEntity>
### 6.63.14 ### 6.63.14
Added option `verifyorganizer [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`. When a copy/move Added option `verifyorganizer [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`. When a copy/move

View File

@ -587,6 +587,7 @@ gam print group-members [todrive <ToDriveAttribute>*]
``` ```
By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups: By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups:
* `domain|domains <DomainNameEntity>` - Limit display to groups in the domains specified by `<DomainNameEntity>` * `domain|domains <DomainNameEntity>` - Limit display to groups in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>` * `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>`
* `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>` * `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>`
* `(query <QueryGroup>)|(queries <QueryGroupList>)` - Limit groups to those that match a query; each query is run against each domain * `(query <QueryGroup>)|(queries <QueryGroupList>)` - Limit groups to those that match a query; each query is run against each domain
@ -698,6 +699,7 @@ gam show group-members
``` ```
By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups: By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups:
* `domain|domains <DomainNameEntity>` - Limit display to groups in the domains specified by `<DomainNameEntity>` * `domain|domains <DomainNameEntity>` - Limit display to groups in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>` * `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>`
* `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>` * `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>`
* `(query <QueryGroup>)|(queries <QueryGroupList>)` - Limit groups to those that match a query; each query is run against each domain * `(query <QueryGroup>)|(queries <QueryGroupList>)` - Limit groups to those that match a query; each query is run against each domain

View File

@ -429,6 +429,7 @@ gam print groups [todrive <ToDriveAttribute>*]
``` ```
By default, all groups in the account are displayed, these options allow selection of subsets of groups: By default, all groups in the account are displayed, these options allow selection of subsets of groups:
* `domain|domains <DomainNameEntity>` - Limit display to groups in the domains specified by `<DomainNameEntity>` * `domain|domains <DomainNameEntity>` - Limit display to groups in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>` * `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>`
* `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>` * `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>`
* `(query <QueryGroup>)|(queries <QueryGroupList>)` - Limit groups to those that match a query; each query is run against each domain * `(query <QueryGroup>)|(queries <QueryGroupList>)` - Limit groups to those that match a query; each query is run against each domain

View File

@ -175,6 +175,8 @@ Section: DEFAULT
oauth2service_json = oauth2service.json ; /Users/admin/GAMConfig/oauth2service.json oauth2service_json = oauth2service.json ; /Users/admin/GAMConfig/oauth2service.json
people_max_results = 100 people_max_results = 100
print_agu_domains = '' print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0 process_wait_limit = 0
quick_cros_move = false quick_cros_move = false
quick_info_user = false quick_info_user = false
@ -331,7 +333,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin/bin/gamadv-xtd3$ rm -f /Users/admin/GAMConfig/oauth2.txt admin@server:/Users/admin/bin/gamadv-xtd3$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam version admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAMADV-XTD3 6.63.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.63.15 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.10.8 64-bit final Python 3.10.8 64-bit final
MacOS High Sierra 10.13.6 x86_64 MacOS High Sierra 10.13.6 x86_64
@ -598,6 +600,8 @@ Section: DEFAULT
oauth2service_json = oauth2service.json ; /Users/admin/GAMConfig/oauth2service.json oauth2service_json = oauth2service.json ; /Users/admin/GAMConfig/oauth2service.json
people_max_results = 100 people_max_results = 100
print_agu_domains = '' print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0 process_wait_limit = 0
quick_cros_move = false quick_cros_move = false
quick_info_user = False quick_info_user = False
@ -797,6 +801,8 @@ Section: DEFAULT
oauth2service_json = oauth2service.json ; C:\GAMConfig\oauth2service.json oauth2service_json = oauth2service.json ; C:\GAMConfig\oauth2service.json
people_max_results = 100 people_max_results = 100
print_agu_domains = '' print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0 process_wait_limit = 0
quick_cros_move = false quick_cros_move = false
quick_info_user = False quick_info_user = False
@ -975,7 +981,7 @@ writes the credentials into the file oauth2.txt.
C:\GAMADV-XTD3>del C:\GAMConfig\oauth2.txt C:\GAMADV-XTD3>del C:\GAMConfig\oauth2.txt
C:\GAMADV-XTD3>gam version C:\GAMADV-XTD3>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAMADV-XTD3 6.63.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.63.15 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.5 64-bit final Python 3.11.5 64-bit final
Windows-10-10.0.17134 AMD64 Windows-10-10.0.17134 AMD64
@ -1244,6 +1250,8 @@ Section: DEFAULT
output_timeformat = '' output_timeformat = ''
people_max_results = 100 people_max_results = 100
print_agu_domains = '' print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0 process_wait_limit = 0
quick_cros_move = false quick_cros_move = false
quick_info_user = False quick_info_user = False

View File

@ -30,8 +30,6 @@
<CourseWorkIDList> ::= "<CourseWorkID>(,<CourseWorkID>)*" <CourseWorkIDList> ::= "<CourseWorkID>(,<CourseWorkID>)*"
<CourseWorkStateList> ::= all|"<CourseWorkState>(,<CourseWorkState>)*" <CourseWorkStateList> ::= all|"<CourseWorkState>(,<CourseWorkState>)*"
<CrOSIDList> ::= "<CrOSID>(,<CrOSID>)*" <CrOSIDList> ::= "<CrOSID>(,<CrOSID>)*"
<DataStudioAssetIDList> ::= "<DataStudioAssetID>(,<DataStudioAssetID>)*"
<DataStudioPermissionList> ::= "<DataStudioPermission>(,<DataStudioPermission>)*"
<DeviceIDList> ::= "<DeviceID>(,<DeviceID>)*" <DeviceIDList> ::= "<DeviceID>(,<DeviceID>)*"
<DeviceUserList> ::= "<DeviceUserID>(,<DeviceUserID>)*" <DeviceUserList> ::= "<DeviceUserID>(,<DeviceUserID>)*"
<DomainNameList> ::= "<DomainName>(,<DomainName>)*" <DomainNameList> ::= "<DomainName>(,<DomainName>)*"
@ -63,6 +61,8 @@
<LabelIDList> ::= "<LabelID>(,<LabelID>)*" <LabelIDList> ::= "<LabelID>(,<LabelID>)*"
<LabelNameList> ::= "'<LabelName>'(,'<LabelName>')*" <LabelNameList> ::= "'<LabelName>'(,'<LabelName>')*"
<LanguageList> ::= "<Language>(,<Language>)*" <LanguageList> ::= "<Language>(,<Language>)*"
<LookerStudioAssetIDList> ::= "<LookerStudioAssetID>(,<LookerStudioAssetID>)*"
<LookerStudioPermissionList> ::= "<LookerStudioPermission>(,<LookerStudioPermission>)*"
<MatterItemList> ::= "<MatterItem>(,<MatterItem>)*" <MatterItemList> ::= "<MatterItem>(,<MatterItem>)*"
<MatterStateList> ::= "<MatterState>(,<MatterState>)*" <MatterStateList> ::= "<MatterState>(,<MatterState>)*"
<MessageIDList> ::= "<MessageID>(,<MessageID>)*" <MessageIDList> ::= "<MessageID>(,<MessageID>)*"

View File

@ -1,19 +1,19 @@
# Users - Data Studio # Users - Looker Studio
- [API documentation](#api-documentation) - [API documentation](#api-documentation)
- [Notes](#notes) - [Notes](#notes)
- [Definitions](#definitions) - [Definitions](#definitions)
- [Display Data Studio assets](#display-data-studio-assets) - [Display Looker Studio assets](#display-data-studio-assets)
- [Manage Data Studio permissions](#manage-data-studio-permissions) - [Manage Looker Studio permissions](#manage-data-studio-permissions)
- [Add Permissions](#add-permissions) - [Add Permissions](#add-permissions)
- [Delete Permissions](#delete-permissions) - [Delete Permissions](#delete-permissions)
- [Update Permissions](#update-permissions) - [Update Permissions](#update-permissions)
- [Display Data Studio permissions](#display-data-studio-permissions) - [Display Looker Studio permissions](#display-data-studio-permissions)
## API documentation ## API documentation
* https://developers.google.com/datastudio/api/reference * https://developers.google.com/looker-studio/integrate/api/reference
## Notes ## Notes
To use these commands you must add the 'Data Studio API' to your project and update your service account authorization. To use these commands you must add the 'Looker Studio API' to your project and update your service account authorization.
``` ```
gam update project gam update project
gam user user@domain.com check serviceaccount gam user user@domain.com check serviceaccount
@ -27,33 +27,33 @@ gam user user@domain.com check serviceaccount
<UniqueID> ::= id:<String> <UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String> <UserItem> ::= <EmailAddress>|<UniqueID>|<String>
<DataStudioAssetID> ::= <String> <LookerStudioAssetID> ::= <String>
<DataStudioAssetIDList> ::= "<DataStudioAssetID>(,<DataStudioAssetID>)*" <LookerStudioAssetIDList> ::= "<LookerStudioAssetID>(,<LookerStudioAssetID>)*"
<DataStudioAssetIDEntity> ::= <LookerStudioAssetIDEntity> ::=
<DataStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector> <LookerStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
See: https://github.com/taers232c/GAMADV-XTD3/wiki/Collections-of-Items See: https://github.com/taers232c/GAMADV-XTD3/wiki/Collections-of-Items
<DataStudioPermission> ::= <LookerStudioPermission> ::=
user:<EmailAddress>| user:<EmailAddress>|
group:<EmailAddress>| group:<EmailAddress>|
domain:<DomainName>| domain:<DomainName>|
serviceAccount:<EmailAddress> serviceAccount:<EmailAddress>
<DataStudioPermissionList> ::= "<DataStudioPermission>(,<DataStudioPermission>)*" <LookerStudioPermissionList> ::= "<LookerStudioPermission>(,<LookerStudioPermission>)*"
<DataStudioPermissionEntity> ::= <LookerStudioPermissionEntity> ::=
<DataStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector> <LookerStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
See: https://github.com/taers232c/GAMADV-XTD3/wiki/Collections-of-Items See: https://github.com/taers232c/GAMADV-XTD3/wiki/Collections-of-Items
``` ```
Data Studio assets have an ID that is referred to by Google as its `name`; this is the value Looker Studio assets have an ID that is referred to by Google as its `name`; this is the value
you will use wherever `<DataStudioAssetID>` is required. you will use wherever `<LookerStudioAssetID>` is required.
## Display Data Studio assets ## Display Looker Studio assets
``` ```
gam <UserTypeEntity> show datastudioassets gam <UserTypeEntity> show lookerstudioassets
[([assettype report|datasource|all] [title <String>] [([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed] [owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) | [orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)] (assetids <LookerStudioAssetIDEntity>)]
[stripcrsfromtitle] [stripcrsfromtitle]
[formatjson] [formatjson]
``` ```
@ -65,7 +65,7 @@ By default, all assets of type `report` not in the trash are displayed; use the
* `includetrashed` - Display assets in the trash * `includetrashed` - Display assets in the trash
* `orderby title [ascending|descending]` - Order of assets * `orderby title [ascending|descending]` - Order of assets
* Specific * Specific
* `assetids <DataStudioAssetIDEntity>` - Display a specific list of `assetids` * `assetids <LookerStudioAssetIDEntity>` - Display a specific list of `assetids`
The `stripcrsfromtitle` option strips nulls, carriage returns and linefeeds from asset titles. The `stripcrsfromtitle` option strips nulls, carriage returns and linefeeds from asset titles.
Use this option if you discover asset titles containing these special characters; it is not common. Use this option if you discover asset titles containing these special characters; it is not common.
@ -73,11 +73,11 @@ Use this option if you discover asset titles containing these special characters
By default, Gam displays the information as an indented list of keys and values. By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format. * `formatjson` - Display the fields in JSON format.
``` ```
gam <UserTypeEntity> print datastudioassets [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print lookerstudioassets [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>] [([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed] [owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) | [orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)] (assetids <LookerStudioAssetIDEntity>)]
[stripcrsfromtitle] [stripcrsfromtitle]
[formatjson [quotechar <Character>]] [formatjson [quotechar <Character>]]
``` ```
@ -89,7 +89,7 @@ By default, all assets of type `report` not in the trash are displayed; use the
* `includetrashed` - Display assets in the trash * `includetrashed` - Display assets in the trash
* `orderby title [ascending|descending]` - Order of assets * `orderby title [ascending|descending]` - Order of assets
* Specific * Specific
* `assetids <DataStudioAssetIDEntity>` - Display a specific list of `assetids` * `assetids <LookerStudioAssetIDEntity>` - Display a specific list of `assetids`
The `stripcrsfromtitle` option strips nulls, carriage returns and linefeeds from asset titles. The `stripcrsfromtitle` option strips nulls, carriage returns and linefeeds from asset titles.
Use this option if you discover asset titles containing these special characters; it is not common. Use this option if you discover asset titles containing these special characters; it is not common.
@ -100,22 +100,22 @@ When using the `formatjson` option, double quotes are used extensively in the da
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output. The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used. `quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
## Manage Data Studio permissions ## Manage Looker Studio permissions
* The owner of an asset can not have it's role changed. * The owner of an asset can not have it's role changed.
* The owner of an asset can not be deleted. * The owner of an asset can not be deleted.
* A new owner can not be added to an asset. * A new owner can not be added to an asset.
`<EmailAddress>` in `<DataStudioPermission>` must be complete, GAM will not add a domain name. `<EmailAddress>` in `<LookerStudioPermission>` must be complete, GAM will not add a domain name.
A viewer can not manage permissions. A viewer can not manage permissions.
### Add permissions ### Add permissions
``` ```
gam <UserTypeEntity> add datastudiopermissions gam <UserTypeEntity> add lookerstudiopermissions
[([assettype report|datasource|all] [title <String>] [([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed] [owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) | [orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity)] (assetids <LookerStudioAssetIDEntity)]
(role editor|viewer <DataStudioPermissionEntity>)+ (role editor|viewer <LookerStudioPermissionEntity>)+
[nodetails] [nodetails]
``` ```
By default, the permission is added to all assets of type `report` not in the trash; use the following options to select a subset of assets. By default, the permission is added to all assets of type `report` not in the trash; use the following options to select a subset of assets.
@ -126,19 +126,19 @@ By default, the permission is added to all assets of type `report` not in the tr
* `includetrashed` - Add permission to assets in the trash * `includetrashed` - Add permission to assets in the trash
* `orderby title [ascending|descending]` - Order of assets * `orderby title [ascending|descending]` - Order of assets
* Specific * Specific
* `assetids <DataStudioAssetIDEntity>` - Add permission to a specific list of `assetids` * `assetids <LookerStudioAssetIDEntity>` - Add permission to a specific list of `assetids`
By default, when a permission is added, GAM outputs details of the permission. The `nodetails` option By default, when a permission is added, GAM outputs details of the permission. The `nodetails` option
suppresses this output. suppresses this output.
### Delete permissions ### Delete permissions
``` ```
gam <UserTypeEntity> delete datastudiopermissions gam <UserTypeEntity> delete lookerstudiopermissions
[([assettype report|datasource|all] [title <String>] [([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed] [owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) | [orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity)] (assetids <LookerStudioAssetIDEntity)]
(role any <DataStudioPermissionEntity>)+ (role any <LookerStudioPermissionEntity>)+
[nodetails] [nodetails]
``` ```
By default, the permission is deleted from all assets of type `report` not in the trash; use the following options to select a subset of assets. By default, the permission is deleted from all assets of type `report` not in the trash; use the following options to select a subset of assets.
@ -149,7 +149,7 @@ By default, the permission is deleted from all assets of type `report` not in th
* `includetrashed` - Delete permission from assets in the trash * `includetrashed` - Delete permission from assets in the trash
* `orderby title [ascending|descending]` - Order of assets * `orderby title [ascending|descending]` - Order of assets
* Specific * Specific
* `assetids <DataStudioAssetIDEntity>` - Delete permission from a specific list of `assetids` * `assetids <LookerStudioAssetIDEntity>` - Delete permission from a specific list of `assetids`
By default, when a permission is deleted, GAM outputs details of the permission. The `nodetails` option By default, when a permission is deleted, GAM outputs details of the permission. The `nodetails` option
suppresses this output. suppresses this output.
@ -157,12 +157,12 @@ suppresses this output.
### Update permissions ### Update permissions
A permission is updated by deleting the existing permission and then adding the new permission. A permission is updated by deleting the existing permission and then adding the new permission.
``` ```
gam <UserTypeEntity> update datastudiopermissions gam <UserTypeEntity> update lookerstudiopermissions
[([assettype report|datasource|all] [title <String>] [([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed] [owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) | [orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity)] (assetids <LookerStudioAssetIDEntity)]
(role editor|viewer <DataStudioPermissionEntity>)+ (role editor|viewer <LookerStudioPermissionEntity>)+
[nodetails] [nodetails]
``` ```
By default, the permission is updated in all assets of type `report` not in the trash; use the following options to select a subset of assets. By default, the permission is updated in all assets of type `report` not in the trash; use the following options to select a subset of assets.
@ -173,20 +173,20 @@ By default, the permission is updated in all assets of type `report` not in the
* `includetrashed` - Update permission in assets in the trash * `includetrashed` - Update permission in assets in the trash
* `orderby title [ascending|descending]` - Order of assets * `orderby title [ascending|descending]` - Order of assets
* Specific * Specific
* `assetids <DataStudioAssetIDEntity>` - Update permission in a specific list of `assetids` * `assetids <LookerStudioAssetIDEntity>` - Update permission in a specific list of `assetids`
By default, when a permission is updated, GAM outputs details of the permission. The `nodetails` option By default, when a permission is updated, GAM outputs details of the permission. The `nodetails` option
suppresses this output. suppresses this output.
## Display Data Studio permissions ## Display Looker Studio permissions
A viewer can not display permissions. A viewer can not display permissions.
``` ```
gam <UserTypeEntity> show datastudiopermissions gam <UserTypeEntity> show lookerstudiopermissions
[([assettype report|datasource|all] [title <String>] [([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed] [owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) | [orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)] (assetids <LookerStudioAssetIDEntity>)]
[role editor|owner|viewer] [role editor|owner|viewer]
[formatjson] [formatjson]
``` ```
@ -198,19 +198,19 @@ By default, permissions for all assets of type `report` not in the trash are dis
* `includetrashed` - Display permissions for assets in the trash * `includetrashed` - Display permissions for assets in the trash
* `orderby title [ascending|descending]` - Order of assets * `orderby title [ascending|descending]` - Order of assets
* Specific * Specific
* `assetids <DataStudioAssetIDEntity>` - Display permissions for a specific list of `assetids` * `assetids <LookerStudioAssetIDEntity>` - Display permissions for a specific list of `assetids`
The Data Studio API defines this parameter `role editor|owner|viewer` but it doesn't seem to have any effect. The Looker Studio API defines this parameter `role editor|owner|viewer` but it doesn't seem to have any effect.
By default, Gam displays the information as an indented list of keys and values. By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format. * `formatjson` - Display the fields in JSON format.
``` ```
gam <UserTypeEntity> print datastudiopermissions [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print lookerstudiopermissions [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>] [([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed] [owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) | [orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)] (assetids <LookerStudioAssetIDEntity>)]
[role editor|owner|viewer] [role editor|owner|viewer]
[formatjson [quotechar <Character>]] [formatjson [quotechar <Character>]]
``` ```
@ -222,9 +222,9 @@ By default, permissions for all assets of type `report` not in the trash are dis
* `includetrashed` - Display permissions for assets in the trash * `includetrashed` - Display permissions for assets in the trash
* `orderby title [ascending|descending]` - Order of assets * `orderby title [ascending|descending]` - Order of assets
* Specific * Specific
* `assetids <DataStudioAssetIDEntity>` - Display permissions for a specific list of `assetids` * `assetids <LookerStudioAssetIDEntity>` - Display permissions for a specific list of `assetids`
The Data Studio API defines this parameter `role editor|owner|viewer` but it doesn't seem to have any effect. The Looker Studio API defines this parameter `role editor|owner|viewer` but it doesn't seem to have any effect.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled. the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.

View File

@ -64,9 +64,15 @@ Typically, you will enclose the entire list in double quotes and quote each item
* ```"'it em' 'it,em' \"it'em\""``` * ```"'it em' 'it,em' \"it'em\""```
For example, a list of queries for Org Units where the Org Unit names contain spaces: For example, a list of queries for Org Units where the Org Unit names contain spaces:
* Linux and MacOS and Windows Command Prompt
``` ```
queries "\"orgUnitPath='/Students/Middle School'\",\"orgUnitPath='/Students/Lower School'\"" queries "\"orgUnitPath='/Students/Middle School'\",\"orgUnitPath='/Students/Lower School'\""
``` ```
* Windows Power Shell
```
queries "`"orgUnitPath=\'/Students/Lower\ School/2027\'`",`"orgUnitPath=\'/Students/Lower\ School/2028\'`""
```
## Definitions ## Definitions
* [`<UserTypeEntity>`](Collections-of-Users) * [`<UserTypeEntity>`](Collections-of-Users)
@ -970,6 +976,7 @@ gam print users [todrive <ToDriveAttribute>*]
By default, users in all domains in the account are selected; these options allow selection of subsets of users: By default, users in all domains in the account are selected; these options allow selection of subsets of users:
* `domain|domains <DomainNameEntity>` - Limit users to those in the domains specified by `<DomainNameEntity>` * `domain|domains <DomainNameEntity>` - Limit users to those in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `(query <QueryUser>)|(queries <QueryUserList>)` - Limit users to those that match a query; each query is run against each domain * `(query <QueryUser>)|(queries <QueryUserList>)` - Limit users to those that match a query; each query is run against each domain
* `limittoou <OrgUnitPath>|<OrgUnitID>` - Limit users to those in the specified `<OrgUnitItem>>` * `limittoou <OrgUnitPath>|<OrgUnitID>` - Limit users to those in the specified `<OrgUnitItem>>`
* `deleted_only|only_deleted` - Only display deleted users * `deleted_only|only_deleted` - Only display deleted users
@ -1070,6 +1077,7 @@ gam print users [todrive <ToDriveAttribute>*]
``` ```
By default, users in all domains in the account are selected; these options allow selection of subsets of users: By default, users in all domains in the account are selected; these options allow selection of subsets of users:
* `domain|domains <DomainNameEntity>` - Limit users to those in the domains specified by `<DomainNameEntity>` * `domain|domains <DomainNameEntity>` - Limit users to those in the domains specified by `<DomainNameEntity>`
* You can predefine this list with the `print_agu_domains` variable in `gam.cfg`.
* `(query <QueryUser>)|(queries <QueryUserList>)` - Limit users to those that match a query; each query is run against each domain * `(query <QueryUser>)|(queries <QueryUserList>)` - Limit users to those that match a query; each query is run against each domain
* `limittoou <OrgUnitPath>|<OrgUnitID>` - Limit users to those in the specified `<OrgUnitItem>>` * `limittoou <OrgUnitPath>|<OrgUnitID>` - Limit users to those in the specified `<OrgUnitItem>>`
* `deleted_only|only_deleted` - Only display deleted users * `deleted_only|only_deleted` - Only display deleted users

View File

@ -3,7 +3,7 @@
Print the current version of Gam with details Print the current version of Gam with details
``` ```
gam version gam version
GAMADV-XTD3 6.63.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.63.15 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.5 64-bit final Python 3.11.5 64-bit final
MacOS Monterey 12.6.6 x86_64 MacOS Monterey 12.6.6 x86_64
@ -15,7 +15,7 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information Print the current version of Gam with details and time offset information
``` ```
gam version timeoffset gam version timeoffset
GAMADV-XTD3 6.63.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.63.15 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.5 64-bit final Python 3.11.5 64-bit final
MacOS Monterey 12.6.6 x86_64 MacOS Monterey 12.6.6 x86_64
@ -27,7 +27,7 @@ Your system time differs from www.googleapis.com by less than 1 second
Print the current version of Gam with extended details and SSL information Print the current version of Gam with extended details and SSL information
``` ```
gam version extended gam version extended
GAMADV-XTD3 6.63.14 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.63.15 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.5 64-bit final Python 3.11.5 64-bit final
MacOS Monterey 12.6.6 x86_64 MacOS Monterey 12.6.6 x86_64
@ -64,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3 Path: /Users/Admin/bin/gamadv-xtd3
Version Check: Version Check:
Current: 5.35.08 Current: 5.35.08
Latest: 6.63.14 Latest: 6.63.15
echo $? echo $?
1 1
``` ```
@ -72,7 +72,7 @@ echo $?
Print the current version number without details Print the current version number without details
``` ```
gam version simple gam version simple
6.63.14 6.63.15
``` ```
In Linux/MacOS you can do: In Linux/MacOS you can do:
``` ```
@ -82,7 +82,7 @@ echo $VER
Print the current version of Gam and address of this Wiki Print the current version of Gam and address of this Wiki
``` ```
gam help gam help
GAM 6.63.14 - https://github.com/taers232c/GAMADV-XTD3 GAM 6.63.15 - https://github.com/taers232c/GAMADV-XTD3
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.5 64-bit final Python 3.11.5 64-bit final
MacOS Monterey 12.6.6 x86_64 MacOS Monterey 12.6.6 x86_64

View File

@ -125,7 +125,6 @@ Service Account Access
* [Users - Deprovision](Users-Deprovision) * [Users - Deprovision](Users-Deprovision)
* [Users - Contacts](Users-People-Contacts-Profiles) * [Users - Contacts](Users-People-Contacts-Profiles)
* [Users - Contacts - Delegates](Users-Contacts-Delegates) * [Users - Contacts - Delegates](Users-Contacts-Delegates)
* [Users - Data Studio](Users-DataStudio)
* [Users - Drive - File Selection](Drive-File-Selection) * [Users - Drive - File Selection](Drive-File-Selection)
* [Users - Drive - Activity/Settings](Users-Drive-Activity-Settings) * [Users - Drive - Activity/Settings](Users-Drive-Activity-Settings)
* [Users - Drive - Cleanup](Users-Drive-Cleanup) * [Users - Drive - Cleanup](Users-Drive-Cleanup)
@ -152,6 +151,7 @@ Service Account Access
* [Users - Gmail - Settings](Users-Gmail-Settings) * [Users - Gmail - Settings](Users-Gmail-Settings)
* [Users - Group Membership](Users-Group-Membership) * [Users - Group Membership](Users-Group-Membership)
* [Users - Keep](Users-Keep) * [Users - Keep](Users-Keep)
* [Users - Looker Studio](Users-Looker-Studio)
* [Users - People - Contacts & Profiles](Users-People-Contacts-Profiles) * [Users - People - Contacts & Profiles](Users-People-Contacts-Profiles)
* [Users - Photo](Users-Photo) * [Users - Photo](Users-Photo)
* [Users - Profile Sharing](Users-Profile-Sharing) * [Users - Profile Sharing](Users-Profile-Sharing)

View File

@ -407,6 +407,19 @@ print_agu_domains
gam print groups gam print groups
gam print|show group-members gam print|show group-members
gam print users gam print users
This allows predefining the list of domains so they don't have to be specified in each command.
Default: Blank
print_cros_ous
A comma separated list of org unit that are used in these commands:
gam print cros
gam print crosactivity
This allows predefining the list of org units so they don't have to be specified in each command.
Default: Blank
print_cros_ous_and_children
A comma separated list of org unit names that are used in these commands:
gam print cros
gam print crosactivity
This allows predefining the list of org units so they don't have to be specified in each command.
Default: Blank Default: Blank
process_wait_limit process_wait_limit
When processing batch/CSV files, how long (in seconds) GAM should wait for all batch|csv processes to complete When processing batch/CSV files, how long (in seconds) GAM should wait for all batch|csv processes to complete
@ -641,6 +654,8 @@ Section: DEFAULT
output_timeformat = '' output_timeformat = ''
people_max_results = 100 people_max_results = 100
print_agu_domains = '' print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0 process_wait_limit = 0
quick_cros_move = false quick_cros_move = false
quick_info_user = false quick_info_user = false
@ -823,6 +838,8 @@ output_dateformat = ''
output_timeformat = '' output_timeformat = ''
people_max_results = 100 people_max_results = 100
print_agu_domains = '' print_agu_domains = ''
print_cros_ous = ''
print_cros_ous_and_children = ''
process_wait_limit = 0 process_wait_limit = 0
quick_cros_move = False quick_cros_move = False
quick_info_user = False quick_info_user = False

94
docs~
View File

@ -1,94 +0,0 @@
# Version and Help
Print the current version of Gam with details
```
gam version
GAMADV-XTD3 6.61.18 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain.com
Time: 2023-06-02T21:10:00-07:00
```
Print the current version of Gam with details and time offset information
```
gam version timeoffset
GAMADV-XTD3 6.61.18 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain.com
Your system time differs from www.googleapis.com by less than 1 second
```
Print the current version of Gam with extended details and SSL information
```
gam version extended
GAMADV-XTD3 6.61.18 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain.com
Time: 2023-06-02T21:10:00-07:00
Your system time differs from admin.googleapis.com by less than 1 second
OpenSSL 3.1.1 30 May 2023
cryptography 41.0.1
filelock 3.12.0
google-api-python-client 2.88.0
google-auth-httplib2 0.1.0
google-auth-oauthlib 1.0.0
google-auth 2.19.1
httplib2 0.22.0
passlib 1.7.4
python-dateutil 2.8.2
yubikey-manager 5.1.1
admin.googleapis.com connects using TLSv1.3 TLS_AES_256_GCM_SHA384
```
Print the current and latest versions of Gam and:
* set the return code to 0 if the current version is the latest version
* set the return code to 1 if the current version is not the latest
```
gam version checkrc
GAM 5.35.08 - https://github.com/taers232c/GAMADV-XTD3
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.8.1 64-bit final
google-api-python-client 2.77.0
httplib2 0.16.0
oauth2client 4.1.3
MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Version Check:
Current: 5.35.08
Latest: 6.61.18
echo $?
1
```
Print the current version number without details
```
gam version simple
6.61.18
```
In Linux/MacOS you can do:
```
VER=`gam version simple`
echo $VER
```
Print the current version of Gam and address of this Wiki
```
gam help
GAM 6.61.18 - https://github.com/taers232c/GAMADV-XTD3
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.11.4 64-bit final
MacOS Monterey 12.6.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain.com
Time: 2023-06-02T21:10:00-07:00
Help: Syntax in file /Users/Admin/bin/gamadv-xtd3/GamCommands.txt
Help: Documentation is at https://github.com/taers232c/GAMADV-XTD3/wiki
```

View File

@ -386,12 +386,6 @@ If an item contains spaces, it should be surrounded by ".
<CourseWorkState> ::= draft|published|deleted <CourseWorkState> ::= draft|published|deleted
<CrOSID> ::= <String> <CrOSID> ::= <String>
<CustomerID> ::= <String> <CustomerID> ::= <String>
<DataStudioAssetID> ::= <String>
<DataStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<DeliverySetting> ::= <DeliverySetting> ::=
allmail| allmail|
abridged|daily| abridged|daily|
@ -467,6 +461,12 @@ If an item contains spaces, it should be surrounded by ".
<LabelID> ::= Label_<String> <LabelID> ::= Label_<String>
<LabelName> ::= <String> <LabelName> ::= <String>
<LabelReplacement> ::= <String> <LabelReplacement> ::= <String>
<LookerStudioAssetID> ::= <String>
<LookerStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<Marker> ::= <String> <Marker> ::= <String>
<MatterItem> ::= <UniqueID>|<String> <MatterItem> ::= <UniqueID>|<String>
<MatterState> ::= open|closed|deleted <MatterState> ::= open|closed|deleted
@ -652,8 +652,6 @@ If an item contains spaces, it should be surrounded by ".
<CourseWorkIDList> ::= "<CourseWorkID>(,<CourseWorkID>)*" <CourseWorkIDList> ::= "<CourseWorkID>(,<CourseWorkID>)*"
<CourseWorkStateList> ::= all|"<CourseWorkState>(,<CourseWorkState>)*" <CourseWorkStateList> ::= all|"<CourseWorkState>(,<CourseWorkState>)*"
<CrOSIDList> ::= "<CrOSID>(,<CrOSID>)*" <CrOSIDList> ::= "<CrOSID>(,<CrOSID>)*"
<DataStudioAssetIDList> ::= "<DataStudioAssetID>(,<DataStudioAssetID>)*"
<DataStudioPermissionList> ::= "<DataStudioPermission>(,<DataStudioPermission>)*"
<DeviceIDList> ::= "<DeviceID>(,<DeviceID>)*" <DeviceIDList> ::= "<DeviceID>(,<DeviceID>)*"
<DeviceUserList> ::= "<DeviceUserID>(,<DeviceUserID>)*" <DeviceUserList> ::= "<DeviceUserID>(,<DeviceUserID>)*"
<DomainNameList> ::= "<DomainName>(,<DomainName>)*" <DomainNameList> ::= "<DomainName>(,<DomainName>)*"
@ -685,6 +683,8 @@ If an item contains spaces, it should be surrounded by ".
<LabelIDList> ::= "<LabelID>(,<LabelID>)*" <LabelIDList> ::= "<LabelID>(,<LabelID>)*"
<LabelNameList> ::= "'<LabelName>'(,'<LabelName>')*" <LabelNameList> ::= "'<LabelName>'(,'<LabelName>')*"
<LanguageList> ::= "<Language>(,<Language>)*" <LanguageList> ::= "<Language>(,<Language>)*"
<LookerStudioAssetIDList> ::= "<LookerStudioAssetID>(,<LookerStudioAssetID>)*"
<LookerStudioPermissionList> ::= "<LookerStudioPermission>(,<LookerStudioPermission>)*"
<MatterItemList> ::= "<MatterItem>(,<MatterItem>)*" <MatterItemList> ::= "<MatterItem>(,<MatterItem>)*"
<MatterStateList> ::= "<MatterState>(,<MatterState>)*" <MatterStateList> ::= "<MatterState>(,<MatterState>)*"
<MessageIDList> ::= "<MessageID>(,<MessageID>)*" <MessageIDList> ::= "<MessageID>(,<MessageID>)*"
@ -988,10 +988,6 @@ Specify a collection of items by directly specifying them; the item type is dete
<CrOSEntity> ::= <CrOSEntity> ::=
<CrOSIDList> | (cros_sn <SerialNumberList>) | <CrOSIDList> | (cros_sn <SerialNumberList>) |
(query:<QueryCrOS>) | (query:orgunitpath:<OrgUnitPath>) | (query <QueryCrOS>) (query:<QueryCrOS>) | (query:orgunitpath:<OrgUnitPath>) | (query <QueryCrOS>)
<DataStudioAssetIDEntity> ::=
<DataStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DataStudioPermissionEntity> ::=
<DataStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DeviceIDEntity> ::= <DeviceIDEntity> ::=
<DeviceIDList> | (device_sn <SerialNumber>) <DeviceIDList> | (device_sn <SerialNumber>)
(query:<QueryDevice>) | (query <QueryDevice>) (query:<QueryDevice>) | (query <QueryDevice>)
@ -1105,6 +1101,10 @@ Specify a collection of items by directly specifying them; the item type is dete
<LabelIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector> <LabelIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LabelNameEntity> ::= <LabelNameEntity> ::=
<LabelNameList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector> <LabelNameList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LookerStudioAssetIDEntity> ::=
<LookerStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LookerStudioPermissionEntity> ::=
<LookerStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<MessageIDEntity> ::= <MessageIDEntity> ::=
<MessageIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector> <MessageIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<MobileEntity> ::= <MobileEntity> ::=
@ -3084,7 +3084,7 @@ gam print|show transferapps
<DataTransferService> ::= <DataTransferService> ::=
calendar| calendar|
currents| currents|
datastudio|"google data studio"| datastudio|lookerstudio|"google data studio"|
googledrive|gdrive|drive|"drive and docs" googledrive|gdrive|drive|"drive and docs"
<DataTransferServiceList> ::= "<DataTransferService>(,<DataTransferService>)*" <DataTransferServiceList> ::= "<DataTransferService>(,<DataTransferService>)*"
@ -5788,68 +5788,6 @@ gam <UserTypeEntity> print chatmessages [todrive <ToDriveAttribute>*] <ChatSpace
[showdeleted [<Boolean>]] [filter <String>] [showdeleted [<Boolean>]] [filter <String>]
[formatjson [quotechar <Character>]] [formatjson [quotechar <Character>]]
# Users - Data Studuo
<DataStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<DataStudioPermissionList> ::= "<DataStudioPermission>(,<DataStudioPermission>)*"
<DataStudioPermissionEntity> ::=
<DataStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
stam <UserTypeEntity> print datastudioassets [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
[stripcrsfromtitle]
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> show datastudioassets
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
[stripcrsfromtitle]
[formatjson]
gam <UserTypeEntity> add datastudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
(role editor|viewer <DataStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> delete datastudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]) |
(assetids <DataStudioAssetIDEntity>)]
(role any <DataStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> update datastudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
(role editor|viewer <DataStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> print datastudiopermissions [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
[role editor|owner|viewer]
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> show datastudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <DataStudioAssetIDEntity>)]
[role editor|owner|viewer]
[formatjson]
# Users - Drive # Users - Drive
<DriveFileOrderByFieldName> ::= <DriveFileOrderByFieldName> ::=
@ -7142,6 +7080,68 @@ gam <UserTypeEntity> update license <SKUID> [product|productid <ProductID>] [fro
gam <UserTypeEntity> delete license <SKUIDList> [product|productid <ProductID>] [preview] [actioncsv] gam <UserTypeEntity> delete license <SKUIDList> [product|productid <ProductID>] [preview] [actioncsv]
gam <UserTypeEntity> sync license <SKUIDList> [product|productid <ProductID>] [addonly|removeonly] [allskus|onesku] [preview] [actioncsv] gam <UserTypeEntity> sync license <SKUIDList> [product|productid <ProductID>] [addonly|removeonly] [allskus|onesku] [preview] [actioncsv]
# Users - Looker Studuo
<LookerStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<LookerStudioPermissionList> ::= "<LookerStudioPermission>(,<LookerStudioPermission>)*"
<LookerStudioPermissionEntity> ::=
<LookerStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
stam <UserTypeEntity> print lookerstudioassets [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
[stripcrsfromtitle]
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> show lookerstudioassets
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
[stripcrsfromtitle]
[formatjson]
gam <UserTypeEntity> add lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
(role editor|viewer <LookerStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> delete lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]) |
(assetids <LookerStudioAssetIDEntity>)]
(role any <LookerStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> update lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
(role editor|viewer <LookerStudioPermissionEntity>)+
[nodetails]
gam <UserTypeEntity> print lookerstudiopermissions [todrive <ToDriveAttribute>*]
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
[role editor|owner|viewer]
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> show lookerstudiopermissions
[([assettype report|datasource|all] [title <String>]
[owner <Emailddress>] [includetrashed]
[orderby title [ascending|descending]]) |
(assetids <LookerStudioAssetIDEntity>)]
[role editor|owner|viewer]
[formatjson]
# Users - Contacts and Profiles # Users - Contacts and Profiles
<PeopleContactAttribute> ::= <PeopleContactAttribute> ::=

View File

@ -2,6 +2,27 @@
Merged GAM-Team version Merged GAM-Team version
6.63.15
Added `print_cros_ous` and `print_cros_ous_and_children` variables to `gam.cfg` that provide a default list of OUs for these commands:
```
gam print cros
gam print crosactivity
```
Updated `group` commands that manage members to handle the following error:
```
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
```
Updated Data Studio to Looker Studio; added the following command synonyms:
* `lookerstudioassets` for `datastudioassets`
* 'lookerstudiopermissions` for `datastudiopermissions`
Corrected error message in `gam add datastudiopermissions`:
* Old -`ERROR: Missing argument: Expected <DataStudioAssetMembersEntity>`
* New - `ERROR: Missing argument: Expected <LookerStudioPermissionEntity>
6.63.14 6.63.14
Added option `verifyorganizer [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`. When a copy/move Added option `verifyorganizer [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`. When a copy/move

View File

@ -4102,7 +4102,7 @@ def SetGlobalVariables():
elif (varType == GC.TYPE_INTEGER) and itemName in {GC.CSV_INPUT_ROW_LIMIT, GC.CSV_OUTPUT_ROW_LIMIT}: elif (varType == GC.TYPE_INTEGER) and itemName in {GC.CSV_INPUT_ROW_LIMIT, GC.CSV_OUTPUT_ROW_LIMIT}:
GM.Globals[GM.PARSER].set(sectionName, itemName, '0') GM.Globals[GM.PARSER].set(sectionName, itemName, '0')
# Child process # Child process
# Inherit main process output header/row filters/limit if not locally defined # Inherit main process output header/row filters/limit, print defaults if not locally defined
else: else:
if not GC.Values[GC.CSV_OUTPUT_HEADER_FILTER]: if not GC.Values[GC.CSV_OUTPUT_HEADER_FILTER]:
GC.Values[GC.CSV_OUTPUT_HEADER_FILTER] = GM.Globals[GM.CSV_OUTPUT_HEADER_FILTER][:] GC.Values[GC.CSV_OUTPUT_HEADER_FILTER] = GM.Globals[GM.CSV_OUTPUT_HEADER_FILTER][:]
@ -4120,6 +4120,10 @@ def SetGlobalVariables():
GC.Values[GC.CSV_OUTPUT_ROW_LIMIT] = GM.Globals[GM.CSV_OUTPUT_ROW_LIMIT] GC.Values[GC.CSV_OUTPUT_ROW_LIMIT] = GM.Globals[GM.CSV_OUTPUT_ROW_LIMIT]
if not GC.Values[GC.PRINT_AGU_DOMAINS]: if not GC.Values[GC.PRINT_AGU_DOMAINS]:
GC.Values[GC.PRINT_AGU_DOMAINS] = GM.Globals[GM.PRINT_AGU_DOMAINS] GC.Values[GC.PRINT_AGU_DOMAINS] = GM.Globals[GM.PRINT_AGU_DOMAINS]
if not GC.Values[GC.PRINT_CROS_OUS]:
GC.Values[GC.PRINT_CROS_OUS] = GM.Globals[GM.PRINT_CROS_OUS]
if not GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN]:
GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN] = GM.Globals[GM.PRINT_CROS_OUS_AND_CHILDREN]
# customer_id, domain and admin_email must be set when enable_dasa = true # customer_id, domain and admin_email must be set when enable_dasa = true
if GC.Values[GC.ENABLE_DASA]: if GC.Values[GC.ENABLE_DASA]:
errors = 0 errors = 0
@ -5954,7 +5958,7 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
throwReasons=GAPI.MEMBERS_THROW_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS, throwReasons=GAPI.MEMBERS_THROW_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS,
includeDerivedMembership=includeDerivedMembership, includeDerivedMembership=includeDerivedMembership,
groupKey=group, roles=listRoles, fields=listFields, maxResults=GC.Values[GC.MEMBER_MAX_RESULTS]) groupKey=group, roles=listRoles, fields=listFields, maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
entityUnknownWarning(Ent.GROUP, group) entityUnknownWarning(Ent.GROUP, group)
_incrEntityDoesNotExist(Ent.GROUP) _incrEntityDoesNotExist(Ent.GROUP)
return return
@ -6085,7 +6089,7 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
throwReasons=GAPI.MEMBERS_THROW_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS, throwReasons=GAPI.MEMBERS_THROW_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS,
includeDerivedMembership=includeDerivedMembership, includeDerivedMembership=includeDerivedMembership,
groupKey=group, roles=listRoles, fields=listFields, maxResults=GC.Values[GC.MEMBER_MAX_RESULTS]) groupKey=group, roles=listRoles, fields=listFields, maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
entityUnknownWarning(Ent.GROUP, group) entityUnknownWarning(Ent.GROUP, group)
_incrEntityDoesNotExist(Ent.GROUP) _incrEntityDoesNotExist(Ent.GROUP)
continue continue
@ -9300,6 +9304,7 @@ def terminateStdQueueHandler(mpQueue, mpQueueHandler):
def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout, mpQueueStderr, def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout, mpQueueStderr,
debugLevel, todrive, printAguDomains, debugLevel, todrive, printAguDomains,
printCrosOUs, printCrosOUsAndChildren,
output_dateformat, output_timeformat, output_dateformat, output_timeformat,
csvColumnDelimiter, csvQuoteChar, csvColumnDelimiter, csvQuoteChar,
csvTimestampColumn, csvTimestampColumn,
@ -9339,6 +9344,8 @@ def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout,
GM.Globals[GM.NUM_BATCH_ITEMS] = numItems GM.Globals[GM.NUM_BATCH_ITEMS] = numItems
GM.Globals[GM.PID] = pid GM.Globals[GM.PID] = pid
GM.Globals[GM.PRINT_AGU_DOMAINS] = printAguDomains GM.Globals[GM.PRINT_AGU_DOMAINS] = printAguDomains
GM.Globals[GM.PRINT_CROS_OUS] = printCrosOUs
GM.Globals[GM.PRINT_CROS_OUS_AND_CHILDREN] = printCrosOUsAndChildren
GM.Globals[GM.SAVED_STDOUT] = None GM.Globals[GM.SAVED_STDOUT] = None
GM.Globals[GM.SYSEXITRC] = 0 GM.Globals[GM.SYSEXITRC] = 0
if mpQueueCSVFile: if mpQueueCSVFile:
@ -9509,6 +9516,7 @@ def MultiprocessGAMCommands(items, showCmds):
[pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout, mpQueueStderr, [pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout, mpQueueStderr,
GC.Values[GC.DEBUG_LEVEL], GM.Globals[GM.CSV_TODRIVE], GC.Values[GC.DEBUG_LEVEL], GM.Globals[GM.CSV_TODRIVE],
GC.Values[GC.PRINT_AGU_DOMAINS], GC.Values[GC.PRINT_AGU_DOMAINS],
GC.Values[GC.PRINT_CROS_OUS], GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN],
GC.Values[GC.OUTPUT_DATEFORMAT], GC.Values[GC.OUTPUT_TIMEFORMAT], GC.Values[GC.OUTPUT_DATEFORMAT], GC.Values[GC.OUTPUT_TIMEFORMAT],
GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER], GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER],
GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR], GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR],
@ -12882,6 +12890,7 @@ REPORT_CHOICE_MAP = {
'keep': 'keep', 'keep': 'keep',
'login': 'login', 'login': 'login',
'logins': 'login', 'logins': 'login',
'lookerstudio': 'data_studio',
'meet': 'meet', 'meet': 'meet',
'mobile': 'mobile', 'mobile': 'mobile',
'oauthtoken': 'token', 'oauthtoken': 'token',
@ -16069,6 +16078,7 @@ SERVICE_NAME_CHOICE_MAP = {
'drive': DRIVE_AND_DOCS_APP_NAME, 'drive': DRIVE_AND_DOCS_APP_NAME,
'googledrive': DRIVE_AND_DOCS_APP_NAME, 'googledrive': DRIVE_AND_DOCS_APP_NAME,
'gdrive': DRIVE_AND_DOCS_APP_NAME, 'gdrive': DRIVE_AND_DOCS_APP_NAME,
'lookerstudio': GOOGLE_DATA_STUDIO_APP_NAME,
} }
def _validateTransferAppName(apps, appName): def _validateTransferAppName(apps, appName):
@ -23120,6 +23130,16 @@ def substituteQueryTimes(queries, queryTimes):
for queryTimeName, queryTimeValue in iter(queryTimes.items()): for queryTimeName, queryTimeValue in iter(queryTimes.items()):
queries[i] = query.replace(f'#{queryTimeName}#', queryTimeValue) queries[i] = query.replace(f'#{queryTimeName}#', queryTimeValue)
# Get CrOS devices from gam.cfg print_cros_ous and print_cros_ous_and_children
def getCfgCrOSEntities():
if GC.Values[GC.PRINT_CROS_OUS]:
entityList = getItemsToModify(Cmd.ENTITY_CROS_OUS, GC.Values[GC.PRINT_CROS_OUS])
else:
entityList = []
if GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN]:
entityList.extend(getItemsToModify(Cmd.ENTITY_CROS_OUS_AND_CHILDREN, GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN]))
return entityList
CROS_ORDERBY_CHOICE_MAP = { CROS_ORDERBY_CHOICE_MAP = {
'lastsync': 'lastSync', 'lastsync': 'lastSync',
'location': 'annotatedLocation', 'location': 'annotatedLocation',
@ -23287,6 +23307,9 @@ def doPrintCrOSDevices(entityList=None):
selectedLists = {} selectedLists = {}
queryTimes = {} queryTimes = {}
selectionAllowed = entityList is None selectionAllowed = entityList is None
if selectionAllowed and (GC.Values[GC.PRINT_CROS_OUS] or GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN]):
entityList = getCfgCrOSEntities()
selectionAllowed = False
allFields = noLists = oneRow = showDVRstorageFreePercentage = sortHeaders = False allFields = noLists = oneRow = showDVRstorageFreePercentage = sortHeaders = False
activeTimeRangesOrder = 'ASCENDING' activeTimeRangesOrder = 'ASCENDING'
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
@ -23545,6 +23568,9 @@ def doPrintCrOSActivity(entityList=None):
selectedLists = {} selectedLists = {}
queryTimes = {} queryTimes = {}
selectionAllowed = entityList is None selectionAllowed = entityList is None
if selectionAllowed and (GC.Values[GC.PRINT_CROS_OUS] or GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN]):
entityList = getCfgCrOSEntities()
selectionAllowed = False
oneUserPerRow = False oneUserPerRow = False
directlyInOU = True directlyInOU = True
activeTimeRangesOrder = 'ASCENDING' activeTimeRangesOrder = 'ASCENDING'
@ -29344,7 +29370,7 @@ def doUpdateGroups():
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(entityType, group, i, count) entityUnknownWarning(entityType, group, i, count)
except (GAPI.duplicate, GAPI.memberNotFound, GAPI.resourceNotFound, except (GAPI.duplicate, GAPI.memberNotFound, GAPI.resourceNotFound,
GAPI.invalidMember, GAPI.cyclicMembershipsNotAllowed, GAPI.conditionNotMet) as e: GAPI.invalidMember, GAPI.cyclicMembershipsNotAllowed, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
_showFailure(group, member, role, str(e), j, jcount) _showFailure(group, member, role, str(e), j, jcount)
except GAPI.conflict: except GAPI.conflict:
_showSuccess(group, member, role, delivery_settings, j, jcount, Msg.ACTION_MAY_BE_DELAYED) _showSuccess(group, member, role, delivery_settings, j, jcount, Msg.ACTION_MAY_BE_DELAYED)
@ -29381,7 +29407,7 @@ def doUpdateGroups():
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT])) _showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT]))
else: else:
http_status, reason, message = checkGAPIError(exception) http_status, reason, message = checkGAPIError(exception)
if reason in GAPI.MEMBERS_THROW_REASONS: if reason in GAPI.MEMBERS_THROW_REASONS and reason != GAPI.SERVICE_NOT_AVAILABLE:
entityUnknownWarning(entityType, ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT])) entityUnknownWarning(entityType, ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT]))
elif reason == GAPI.CONFLICT: elif reason == GAPI.CONFLICT:
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT]), Msg.ACTION_MAY_BE_DELAYED) _showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT]), Msg.ACTION_MAY_BE_DELAYED)
@ -29455,7 +29481,7 @@ def doUpdateGroups():
_showSuccess(group, member, role, DELIVERY_SETTINGS_UNDEFINED, j, jcount) _showSuccess(group, member, role, DELIVERY_SETTINGS_UNDEFINED, j, jcount)
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(entityType, group, i, count) entityUnknownWarning(entityType, group, i, count)
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.resourceNotFound, GAPI.conditionNotMet) as e: except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.resourceNotFound, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
_showFailure(group, member, role, str(e), j, jcount) _showFailure(group, member, role, str(e), j, jcount)
except GAPI.conflict: except GAPI.conflict:
_showSuccess(group, member, role, DELIVERY_SETTINGS_UNDEFINED, j, jcount, Msg.ACTION_MAY_BE_DELAYED) _showSuccess(group, member, role, DELIVERY_SETTINGS_UNDEFINED, j, jcount, Msg.ACTION_MAY_BE_DELAYED)
@ -29470,7 +29496,7 @@ def doUpdateGroups():
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], DELIVERY_SETTINGS_UNDEFINED, int(ri[RI_J]), int(ri[RI_JCOUNT])) _showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], DELIVERY_SETTINGS_UNDEFINED, int(ri[RI_J]), int(ri[RI_JCOUNT]))
else: else:
http_status, reason, message = checkGAPIError(exception) http_status, reason, message = checkGAPIError(exception)
if reason in GAPI.MEMBERS_THROW_REASONS: if reason in GAPI.MEMBERS_THROW_REASONS and reason != GAPI.SERVICE_NOT_AVAILABLE:
entityUnknownWarning(entityType, ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT])) entityUnknownWarning(entityType, ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT]))
elif reason == GAPI.CONFLICT: elif reason == GAPI.CONFLICT:
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], DELIVERY_SETTINGS_UNDEFINED, int(ri[RI_J]), int(ri[RI_JCOUNT]), Msg.ACTION_MAY_BE_DELAYED) _showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], DELIVERY_SETTINGS_UNDEFINED, int(ri[RI_J]), int(ri[RI_JCOUNT]), Msg.ACTION_MAY_BE_DELAYED)
@ -29560,7 +29586,7 @@ def doUpdateGroups():
Act.Set(Act.UPDATE) Act.Set(Act.UPDATE)
else: else:
_showFailure(group, member, role, str(e), j, jcount) _showFailure(group, member, role, str(e), j, jcount)
except (GAPI.invalidMember, GAPI.resourceNotFound) as e: except (GAPI.invalidMember, GAPI.resourceNotFound, GAPI.serviceNotAvailable) as e:
_showFailure(group, member, role, str(e), j, jcount) _showFailure(group, member, role, str(e), j, jcount)
def _callbackUpdateGroupMembers(request_id, response, exception): def _callbackUpdateGroupMembers(request_id, response, exception):
@ -29573,11 +29599,18 @@ def doUpdateGroups():
Act.Set(Act.ADD) Act.Set(Act.ADD)
_addMember(ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT]), ri[RI_ROLE], ri[RI_OPTION], ri[RI_ITEM], int(ri[RI_J]), int(ri[RI_JCOUNT])) _addMember(ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT]), ri[RI_ROLE], ri[RI_OPTION], ri[RI_ITEM], int(ri[RI_J]), int(ri[RI_JCOUNT]))
Act.Set(Act.UPDATE) Act.Set(Act.UPDATE)
elif reason in GAPI.MEMBERS_THROW_REASONS: elif reason in GAPI.MEMBERS_THROW_REASONS and reason != GAPI.SERVICE_NOT_AVAILABLE:
entityUnknownWarning(entityType, ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT])) entityUnknownWarning(entityType, ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT]))
else: elif reason not in GAPI.DEFAULT_RETRY_REASONS+GAPI.MEMBERS_RETRY_REASONS:
errMsg = getHTTPError(_UPDATE_MEMBER_REASON_TO_MESSAGE_MAP, http_status, reason, message) errMsg = getHTTPError(_UPDATE_MEMBER_REASON_TO_MESSAGE_MAP, http_status, reason, message)
_showFailure(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], errMsg, int(ri[RI_J]), int(ri[RI_JCOUNT])) _showFailure(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], errMsg, int(ri[RI_J]), int(ri[RI_JCOUNT]))
else:
if addBatchParms['adjust']:
addBatchParms['adjust'] = False
addBatchParms['wait'] += 0.25
writeStderr(f'{WARNING_PREFIX}{Msg.INTER_BATCH_WAIT_INCREASED.format(addBatchParms["wait"])}\n')
time.sleep(0.1)
_updateMember(ri[RI_ENTITY], int(ri[RI_I]), int(ri[RI_COUNT]), ri[RI_ROLE], ri[RI_OPTION], ri[RI_ITEM], int(ri[RI_J]), int(ri[RI_JCOUNT]))
def _batchUpdateGroupMembers(group, i, count, updateMembers, role, delivery_settings): def _batchUpdateGroupMembers(group, i, count, updateMembers, role, delivery_settings):
Act.Set([Act.UPDATE, Act.UPDATE_PREVIEW][preview]) Act.Set([Act.UPDATE, Act.UPDATE_PREVIEW][preview])
@ -29891,7 +29924,7 @@ def doUpdateGroups():
roles=None if Ent.ROLE_MEMBER in rolesSet or ignoreRole else memberRoles, roles=None if Ent.ROLE_MEMBER in rolesSet or ignoreRole else memberRoles,
fields='nextPageToken,members(email,id,type,status,role)', fields='nextPageToken,members(email,id,type,status,role)',
maxResults=GC.Values[GC.MEMBER_MAX_RESULTS]) maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
entityUnknownWarning(entityType, group, i, count) entityUnknownWarning(entityType, group, i, count)
continue continue
for role in rolesSet: for role in rolesSet:
@ -30016,7 +30049,7 @@ def doUpdateGroups():
groupKey=group, roles=None if Ent.ROLE_MEMBER in rolesSet else memberRoles, groupKey=group, roles=None if Ent.ROLE_MEMBER in rolesSet else memberRoles,
fields='nextPageToken,members(email,id,type,status,role)', fields='nextPageToken,members(email,id,type,status,role)',
maxResults=GC.Values[GC.MEMBER_MAX_RESULTS]) maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
entityUnknownWarning(entityType, group, i, count) entityUnknownWarning(entityType, group, i, count)
continue continue
removeMembers = {} removeMembers = {}
@ -30845,7 +30878,7 @@ def doPrintGroups():
includeDerivedMembership=memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP], includeDerivedMembership=memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP],
groupKey=ri[RI_ENTITY], roles=ri[RI_ROLE], fields='nextPageToken,members(email,id,role,type,status)', groupKey=ri[RI_ENTITY], roles=ri[RI_ROLE], fields='nextPageToken,members(email,id,role,type,status)',
maxResults=GC.Values[GC.MEMBER_MAX_RESULTS]) maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.invalid, GAPI.forbidden) as e: except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.GROUP, ri[RI_ENTITY], ri[RI_ROLE], None], str(e), i, int(ri[RI_COUNT])) entityActionFailedWarning([Ent.GROUP, ri[RI_ENTITY], ri[RI_ROLE], None], str(e), i, int(ri[RI_COUNT]))
groupData[i]['required'] -= 1 groupData[i]['required'] -= 1
return return
@ -30861,7 +30894,7 @@ def doPrintGroups():
includeDerivedMembership=memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP], includeDerivedMembership=memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP],
groupKey=ri[RI_ENTITY], roles=ri[RI_ROLE], fields='nextPageToken,members(email,id,role,type,status)', groupKey=ri[RI_ENTITY], roles=ri[RI_ROLE], fields='nextPageToken,members(email,id,role,type,status)',
maxResults=GC.Values[GC.MEMBER_MAX_RESULTS]) maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.invalid, GAPI.forbidden) as e: except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.GROUP, ri[RI_ENTITY], ri[RI_ROLE], None], str(e), i, int(ri[RI_COUNT])) entityActionFailedWarning([Ent.GROUP, ri[RI_ENTITY], ri[RI_ROLE], None], str(e), i, int(ri[RI_COUNT]))
break break
groupData[i]['required'] -= 1 groupData[i]['required'] -= 1
@ -31238,7 +31271,7 @@ def infoGroupMembers(entityList, ciGroupsAPI=False):
for field in INFO_GROUPMEMBERS_FIELDS: for field in INFO_GROUPMEMBERS_FIELDS:
printKeyValueList([field, result[field]]) printKeyValueList([field, result[field]])
Ind.Decrement() Ind.Decrement()
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden) as e: except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([entityType, group], str(e), j, jcount) entityActionFailedWarning([entityType, group], str(e), j, jcount)
except GAPI.memberNotFound: except GAPI.memberNotFound:
entityActionFailedWarning([entityType, group, Ent.MEMBER, memberKey], Msg.NOT_AN_ENTITY.format(Ent.Singular(Ent.MEMBER)), j, jcount) entityActionFailedWarning([entityType, group, Ent.MEMBER, memberKey], Msg.NOT_AN_ENTITY.format(Ent.Singular(Ent.MEMBER)), j, jcount)
@ -31307,7 +31340,7 @@ def getGroupMembers(cd, groupEmail, memberRoles, membersList, membersSet, i, cou
throwReasons=GAPI.MEMBERS_THROW_REASONS+[GAPI.MEMBER_NOT_FOUND], throwReasons=GAPI.MEMBERS_THROW_REASONS+[GAPI.MEMBER_NOT_FOUND],
retryReasons=GAPI.MEMBERS_RETRY_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS,
groupKey=groupEmail, memberKey=member['id'], fields='delivery_settings')['delivery_settings'] groupKey=groupEmail, memberKey=member['id'], fields='delivery_settings')['delivery_settings']
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
pass pass
except GAPI.memberNotFound: except GAPI.memberNotFound:
pass pass
@ -31322,7 +31355,7 @@ def getGroupMembers(cd, groupEmail, memberRoles, membersList, membersSet, i, cou
throwReasons=GAPI.MEMBERS_THROW_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS, throwReasons=GAPI.MEMBERS_THROW_REASONS, retryReasons=GAPI.MEMBERS_RETRY_REASONS,
includeDerivedMembership=memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP], includeDerivedMembership=memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP],
groupKey=groupEmail, roles=listRoles, fields=listFields, maxResults=GC.Values[GC.MEMBER_MAX_RESULTS]) groupKey=groupEmail, roles=listRoles, fields=listFields, maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
entityUnknownWarning(Ent.GROUP, groupEmail, i, count) entityUnknownWarning(Ent.GROUP, groupEmail, i, count)
return return
if not memberOptions[MEMBEROPTION_RECURSIVE]: if not memberOptions[MEMBEROPTION_RECURSIVE]:
@ -31679,7 +31712,7 @@ def doShowGroupMembers():
groupKey=groupEmail, fields='nextPageToken,members(email,id,role,status,type)', maxResults=GC.Values[GC.MEMBER_MAX_RESULTS]) groupKey=groupEmail, fields='nextPageToken,members(email,id,role,status,type)', maxResults=GC.Values[GC.MEMBER_MAX_RESULTS])
if showOwnedBy and not checkGroupShowOwnedBy(showOwnedBy, membersList): if showOwnedBy and not checkGroupShowOwnedBy(showOwnedBy, membersList):
return return
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden, GAPI.serviceNotAvailable):
if depth == 0: if depth == 0:
entityUnknownWarning(Ent.GROUP, groupEmail, i, count) entityUnknownWarning(Ent.GROUP, groupEmail, i, count)
return return
@ -32313,6 +32346,9 @@ def doUpdateCIGroups():
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, group) entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, group)
continue continue
except (GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.CLOUD_IDENTITY_GROUP, group], str(e))
continue
currentMembersNames = {} currentMembersNames = {}
for role in rolesSet: for role in rolesSet:
currentMembersSets[role] = set() currentMembersSets[role] = set()
@ -32484,6 +32520,9 @@ def doUpdateCIGroups():
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(entityType, group, i, count) entityUnknownWarning(entityType, group, i, count)
continue continue
except (GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([entityType, group], str(e), i, count)
continue
removeMembers = {} removeMembers = {}
for role in rolesSet: for role in rolesSet:
removeMembers[role] = [] removeMembers[role] = []
@ -32554,6 +32593,9 @@ def doInfoCIGroups():
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, group_id, i, count) entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, group_id, i, count)
return return
except (GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.CLOUD_IDENTITY_GROUP, group_id], str(e), i, count)
return
for member in cachedGroupMembers[group_id]: for member in cachedGroupMembers[group_id]:
member_id = member.get('name', '') member_id = member.get('name', '')
member_id = member_id.split('/')[-1] member_id = member_id.split('/')[-1]
@ -32943,6 +32985,8 @@ def doPrintCIGroups():
parent=groupEntity['name'], view='FULL', fields='*', pageSize=pageSize) parent=groupEntity['name'], view='FULL', fields='*', pageSize=pageSize)
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, groupEmail, i, count) entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, groupEmail, i, count)
except (GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.CLOUD_IDENTITY_GROUP, groupEmail], str(e), i, count)
if memberRestrictions: if memberRestrictions:
printGettingEntityItemForWhom(Ent.MEMBER_RESTRICTION, groupEmail, i, count) printGettingEntityItemForWhom(Ent.MEMBER_RESTRICTION, groupEmail, i, count)
try: try:
@ -56832,6 +56876,7 @@ TRANSFER_DRIVEFILE_ACL_ROLES_MAP = {
# [(targetfolderid <DriveFolderID>)|(targetfoldername <DriveFolderName>)] # [(targetfolderid <DriveFolderID>)|(targetfoldername <DriveFolderName>)]
# [targetuserfoldername <DriveFolderName>] [targetuserorphansfoldername <DriveFolderName>] # [targetuserfoldername <DriveFolderName>] [targetuserorphansfoldername <DriveFolderName>]
# [mergewithtarget [<Boolean>]] # [mergewithtarget [<Boolean>]]
# [createshortcutsfornonmovablefiles [<Boolean>]]
# [skipids <DriveFileEntity>] # [skipids <DriveFileEntity>]
# [keepuser | (retainrole reader|commenter|writer|editor|fileorganizer|none)] [noretentionmessages] # [keepuser | (retainrole reader|commenter|writer|editor|fileorganizer|none)] [noretentionmessages]
# [nonowner_retainrole reader|commenter|writer|editor|fileorganizer|current|none] # [nonowner_retainrole reader|commenter|writer|editor|fileorganizer|current|none]
@ -56905,37 +56950,36 @@ def transferDrive(users):
def _setUpdateRole(permission): def _setUpdateRole(permission):
return {'role': permission['role']} return {'role': permission['role']}
# def _makeXferShortcut(drive, user, j, jcount, entityType, childId, childName, newParentId, newParentName): def _makeXferShortcut(drive, user, j, jcount, entityType, childId, childName, newParentId):
# kvList = [Ent.USER, user, entityType, f'{childName}({childId})'] kvList = [Ent.USER, user, entityType, f'{childName}({childId})']
# targetEntityType = Ent.DRIVE_FILE_SHORTCUT if entityType == Ent.DRIVE_FILE else Ent.DRIVE_FOLDER_SHORTCUT targetEntityType = Ent.DRIVE_FILE_SHORTCUT if entityType == Ent.DRIVE_FILE else Ent.DRIVE_FOLDER_SHORTCUT
# newParentNameId = f'{newParentName}({newParentId})' action = Act.Get()
# action = Act.Get() existingShortcut = _checkForExistingShortcut(drive, childId, childName, newParentId)
# existingShortcut = _checkForExistingShortcut(drive, childId, childName, newParentId) if existingShortcut:
# if existingShortcut: Act.Set(Act.CREATE_SHORTCUT)
# Act.Set(Act.CREATE_SHORTCUT) entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_PREVIOUSLY_IN,
# entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_PREVIOUSLY_IN, [Ent.DRIVE_FOLDER, newParentId, targetEntityType, f"{childName}({existingShortcut})"],
# [Ent.DRIVE_FOLDER, newParentNameId, targetEntityType, f"{childName}({existingShortcut})"], j, jcount)
# j, jcount) Act.Set(action)
# Act.Set(action) return
# return body = {'name': childName, 'mimeType': MIMETYPE_GA_SHORTCUT,
# body = {'name': childName, 'mimeType': MIMETYPE_GA_SHORTCUT, 'parents': [newParentId], 'shortcutDetails': {'targetId': childId}}
# 'parents': [newParentId], 'shortcutDetails': {'targetId': childId}} try:
# try: result = callGAPI(drive.files(), 'create',
# result = callGAPI(drive.files(), 'create', throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.FORBIDDEN, GAPI.INSUFFICIENT_PERMISSIONS, GAPI.INSUFFICIENT_PARENT_PERMISSIONS,
# throwReasons=GAPI.DRIVE_USER_THROW_REASONS+[GAPI.FORBIDDEN, GAPI.INSUFFICIENT_PERMISSIONS, GAPI.INSUFFICIENT_PARENT_PERMISSIONS, GAPI.INVALID, GAPI.BAD_REQUEST, GAPI.FILE_NOT_FOUND, GAPI.UNKNOWN_ERROR,
# GAPI.INVALID, GAPI.BAD_REQUEST, GAPI.FILE_NOT_FOUND, GAPI.UNKNOWN_ERROR, GAPI.STORAGE_QUOTA_EXCEEDED, GAPI.TEAMDRIVES_SHARING_RESTRICTION_NOT_ALLOWED,
# GAPI.STORAGE_QUOTA_EXCEEDED, GAPI.TEAMDRIVES_SHARING_RESTRICTION_NOT_ALLOWED, GAPI.TEAMDRIVE_HIERARCHY_TOO_DEEP, GAPI.SHORTCUT_TARGET_INVALID],
# GAPI.TEAMDRIVE_HIERARCHY_TOO_DEEP, GAPI.SHORTCUT_TARGET_INVALID], body=body, fields='id', supportsAllDrives=True)
# body=body, fields='id', supportsAllDrives=True) Act.Set(Act.CREATE_SHORTCUT)
# Act.Set(Act.CREATE_SHORTCUT) entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_IN,
# entityModifierItemValueListActionPerformed(kvList, Act.MODIFIER_IN, [Ent.DRIVE_FOLDER, newParentId, targetEntityType, f"{childName}({result['id']})"],
# [Ent.DRIVE_FOLDER, newParentNameId, targetEntityType, f"{childName}({result['id']})"], j, jcount)
# j, jcount) Act.Set(action)
# Act.Set(action) except (GAPI.forbidden, GAPI.insufficientFilePermissions, GAPI.insufficientParentPermissions, GAPI.invalid, GAPI.badRequest,
# except (GAPI.forbidden, GAPI.insufficientFilePermissions, GAPI.insufficientParentPermissions, GAPI.invalid, GAPI.badRequest, GAPI.fileNotFound, GAPI.unknownError, GAPI.storageQuotaExceeded, GAPI.teamDrivesSharingRestrictionNotAllowed,
# GAPI.fileNotFound, GAPI.unknownError, GAPI.storageQuotaExceeded, GAPI.teamDrivesSharingRestrictionNotAllowed, GAPI.teamDriveHierarchyTooDeep, GAPI.shortcutTargetInvalid) as e:
# GAPI.teamDriveHierarchyTooDeep, GAPI.shortcutTargetInvalid) as e: entityActionFailedWarning(kvList+[Ent.DRIVE_FILE_SHORTCUT, childName], str(e), j, jcount)
# entityActionFailedWarning(kvList+[Ent.DRIVE_FILE_SHORTCUT, childName], str(e), j, jcount)
def _transferFile(childEntry, i, count, j, jcount, atSelectTop): def _transferFile(childEntry, i, count, j, jcount, atSelectTop):
childEntryInfo = childEntry['info'] childEntryInfo = childEntry['info']
@ -56956,14 +57000,14 @@ def transferDrive(users):
csvPF.WriteRow({'OldOwner': sourceUser, 'NewOwner': targetUser, 'type': Ent.Singular(childFileType), 'id': childFileId, 'name': childFileName, 'role': 'owner'}) csvPF.WriteRow({'OldOwner': sourceUser, 'NewOwner': targetUser, 'type': Ent.Singular(childFileType), 'id': childFileId, 'name': childFileName, 'role': 'owner'})
return return
Act.Set(Act.TRANSFER_OWNERSHIP) Act.Set(Act.TRANSFER_OWNERSHIP)
addTargetParents = set() addTargetParent = None
removeSourceParents = set() removeSourceParents = set()
removeTargetParents = set() removeTargetParents = set()
childParents = childEntryInfo.get('parents', []) childParents = childEntryInfo.get('parents', [])
if childParents: if childParents:
for parentId in childParents: for parentId in childParents:
if parentId in parentIdMap: if parentId in parentIdMap:
addTargetParents.add(parentIdMap[parentId]) addTargetParent = parentIdMap[parentId]
if parentId != sourceRootId: if parentId != sourceRootId:
removeSourceParents.add(parentId) removeSourceParents.add(parentId)
elif not mergeWithTarget and targetFolderId != targetRootId: elif not mergeWithTarget and targetFolderId != targetRootId:
@ -56971,7 +57015,7 @@ def transferDrive(users):
else: else:
if targetIds[TARGET_ORPHANS_PARENT_ID] is None: if targetIds[TARGET_ORPHANS_PARENT_ID] is None:
_buildTargetUserOrphansFolder() _buildTargetUserOrphansFolder()
addTargetParents.add(targetIds[TARGET_ORPHANS_PARENT_ID]) addTargetParent = targetIds[TARGET_ORPHANS_PARENT_ID]
removeTargetParents.add(targetRootId) removeTargetParents.add(targetRootId)
try: try:
actionUser = sourceUser actionUser = sourceUser
@ -56992,24 +57036,22 @@ def transferDrive(users):
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS, retryReasons=[GAPI.BAD_REQUEST, GAPI.FILE_NOT_FOUND], retries=3, throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS, retryReasons=[GAPI.BAD_REQUEST, GAPI.FILE_NOT_FOUND], retries=3,
fileId=childFileId, removeParents=','.join(removeSourceParents), fields='') fileId=childFileId, removeParents=','.join(removeSourceParents), fields='')
actionUser = targetUser actionUser = targetUser
if addTargetParents or removeTargetParents: if addTargetParent or removeTargetParents:
op = 'Add/Remove Target Parents' op = 'Add/Remove Target Parents'
callGAPI(targetDrive.files(), 'update', callGAPI(targetDrive.files(), 'update',
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.INSUFFICIENT_PARENT_PERMISSIONS], throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.INSUFFICIENT_PARENT_PERMISSIONS],
retryReasons=[GAPI.BAD_REQUEST, GAPI.FILE_NOT_FOUND], retries=3, retryReasons=[GAPI.BAD_REQUEST, GAPI.FILE_NOT_FOUND], retries=3,
fileId=childFileId, fileId=childFileId,
addParents=','.join(addTargetParents), removeParents=','.join(removeTargetParents), fields='') addParents=addTargetParent, removeParents=','.join(removeTargetParents), fields='')
entityModifierNewValueItemValueListActionPerformed([Ent.USER, sourceUser, childFileType, childFileName], Act.MODIFIER_TO, None, [Ent.USER, targetUser], j, jcount) entityModifierNewValueItemValueListActionPerformed([Ent.USER, sourceUser, childFileType, childFileName], Act.MODIFIER_TO, None, [Ent.USER, targetUser], j, jcount)
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.unknownError, except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.unknownError,
GAPI.badRequest, GAPI.sharingRateLimitExceeded, GAPI.badRequest, GAPI.sharingRateLimitExceeded, GAPI.insufficientParentPermissions) as e:
GAPI.insufficientFilePermissions, GAPI.insufficientParentPermissions,
GAPI.fileOwnerNotMemberOfWriterDomain, GAPI.crossDomainMoveRestriction) as e:
entityActionFailedWarning([Ent.USER, actionUser, childFileType, childFileName], f'{op}: {str(e)}', j, jcount) entityActionFailedWarning([Ent.USER, actionUser, childFileType, childFileName], f'{op}: {str(e)}', j, jcount)
# except (GAPI.insufficientFilePermissions, GAPI.fileOwnerNotMemberOfWriterDomain, GAPI.crossDomainMoveRestriction) as e: except (GAPI.insufficientFilePermissions, GAPI.fileOwnerNotMemberOfWriterDomain, GAPI.crossDomainMoveRestriction) as e:
# if not createShortcutsForNonmovableFiles: if not createShortcutsForNonmovableFiles:
# entityActionFailedWarning([Ent.USER, actionUser, childFileType, childFileName], f'{op}: {str(e)}', j, jcount) entityActionFailedWarning([Ent.USER, actionUser, childFileType, childFileName], f'{op}: {str(e)}', j, jcount)
# else: else:
# _makeXferShortcut(targetDrive, targetUser, j, jcount, childFileType, childFileId, childFileName, newParentId, newParentName) _makeXferShortcut(targetDrive, targetUser, j, jcount, childFileType, childFileId, childFileName, addTargetParent)
except GAPI.permissionNotFound: except GAPI.permissionNotFound:
entityDoesNotHaveItemWarning([Ent.USER, actionUser, childFileType, childFileName, Ent.PERMISSION_ID, targetPermissionId], j, jcount) entityDoesNotHaveItemWarning([Ent.USER, actionUser, childFileType, childFileName, Ent.PERMISSION_ID, targetPermissionId], j, jcount)
except GAPI.invalidSharingRequest as e: except GAPI.invalidSharingRequest as e:
@ -57373,7 +57415,7 @@ def transferDrive(users):
targetUserFolderPattern = '#user# old files' targetUserFolderPattern = '#user# old files'
targetUserOrphansFolderPattern = '#user# orphaned files' targetUserOrphansFolderPattern = '#user# orphaned files'
targetIds = [None, None] targetIds = [None, None]
# createShortcutsForNonmovableFiles = False createShortcutsForNonmovableFiles = False
mergeWithTarget = False mergeWithTarget = False
thirdPartyOwners = {} thirdPartyOwners = {}
skipFileIdEntity = initDriveFileEntity() skipFileIdEntity = initDriveFileEntity()
@ -57410,8 +57452,8 @@ def transferDrive(users):
buildTree = False buildTree = False
elif myarg == 'mergewithtarget': elif myarg == 'mergewithtarget':
mergeWithTarget = getBoolean() mergeWithTarget = getBoolean()
# elif myarg == 'createshortcutsfornonmovablefiles': elif myarg == 'createshortcutsfornonmovablefiles':
# createShortcutsForNonmovableFiles = getBoolean() createShortcutsForNonmovableFiles = getBoolean()
elif myarg == 'skipids': elif myarg == 'skipids':
skipFileIdEntity = getDriveFileEntity() skipFileIdEntity = getDriveFileEntity()
elif myarg == 'preview': elif myarg == 'preview':
@ -60840,18 +60882,18 @@ def printShowSharedDriveACLs(users, useDomainAdminAccess=False):
def doPrintShowSharedDriveACLs(): def doPrintShowSharedDriveACLs():
printShowSharedDriveACLs([_getAdminEmail()], True) printShowSharedDriveACLs([_getAdminEmail()], True)
DATASTUDIO_ASSETTYPE_CHOICE_MAP = { LOOKERSTUDIO_ASSETTYPE_CHOICE_MAP = {
'report': ['REPORT'], 'report': ['REPORT'],
'datasource': ['DATA_SOURCE'], 'datasource': ['DATA_SOURCE'],
'all': ['REPORT', 'DATA_SOURCE'], 'all': ['REPORT', 'DATA_SOURCE'],
} }
def initDataStudioAssetSelectionParameters(): def initLookerStudioAssetSelectionParameters():
return ({'owner': None, 'title': None, 'includeTrashed': False}, {'assetTypes': ['REPORT']}) return ({'owner': None, 'title': None, 'includeTrashed': False}, {'assetTypes': ['REPORT']})
def getDataStudioAssetSelectionParameters(myarg, parameters, assetTypes): def getLookerStudioAssetSelectionParameters(myarg, parameters, assetTypes):
if myarg in {'assettype', 'assettypes'}: if myarg in {'assettype', 'assettypes'}:
assetTypes['assetTypes'] = getChoice(DATASTUDIO_ASSETTYPE_CHOICE_MAP, mapChoice=True) assetTypes['assetTypes'] = getChoice(LOOKERSTUDIO_ASSETTYPE_CHOICE_MAP, mapChoice=True)
elif myarg == 'title': elif myarg == 'title':
parameters['title'] = getString(Cmd.OB_STRING) parameters['title'] = getString(Cmd.OB_STRING)
elif myarg == 'owner': elif myarg == 'owner':
@ -60862,7 +60904,7 @@ def getDataStudioAssetSelectionParameters(myarg, parameters, assetTypes):
return False return False
return True return True
def _validateUserGetDataStudioAssetIds(user, i, count, entity): def _validateUserGetLookerStudioAssetIds(user, i, count, entity):
if entity: if entity:
if entity['dict']: if entity['dict']:
entityList = [{'name': item, 'title': item} for item in entity['dict'][user]] entityList = [{'name': item, 'title': item} for item in entity['dict'][user]]
@ -60870,16 +60912,16 @@ def _validateUserGetDataStudioAssetIds(user, i, count, entity):
entityList = [{'name': item, 'title': item} for item in entity['list']] entityList = [{'name': item, 'title': item} for item in entity['list']]
else: else:
entityList = [] entityList = []
user, ds = buildGAPIServiceObject(API.DATASTUDIO, user, i, count) user, ds = buildGAPIServiceObject(API.LOOKERSTUDIO, user, i, count)
if not ds: if not ds:
return (user, None, None, 0) return (user, None, None, 0)
return (user, ds, entityList, len(entityList)) return (user, ds, entityList, len(entityList))
def _getDataStudioAssetByID(ds, user, i, count, assetId): def _getLookerStudioAssetByID(ds, user, i, count, assetId):
printGettingAllEntityItemsForWhom(Ent.DATASTUDIO_ASSET, user, i, count) printGettingAllEntityItemsForWhom(Ent.LOOKERSTUDIO_ASSET, user, i, count)
try: try:
return callGAPI(ds.assets(), 'get', return callGAPI(ds.assets(), 'get',
throwReasons=GAPI.DATASTUDIO_THROW_REASONS, throwReasons=GAPI.LOOKERSTUDIO_THROW_REASONS,
name=f'assets/{assetId}') name=f'assets/{assetId}')
except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e: except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e:
entityActionFailedWarning([Ent.USER, user], str(e), i, count) entityActionFailedWarning([Ent.USER, user], str(e), i, count)
@ -60887,16 +60929,16 @@ def _getDataStudioAssetByID(ds, user, i, count, assetId):
entityServiceNotApplicableWarning(Ent.USER, user, i, count) entityServiceNotApplicableWarning(Ent.USER, user, i, count)
return None return None
def _getDataStudioAssets(ds, user, i, count, parameters, assetTypes, fields, orderBy=None): def _getLookerStudioAssets(ds, user, i, count, parameters, assetTypes, fields, orderBy=None):
assets = [] assets = []
for assetType in assetTypes['assetTypes']: for assetType in assetTypes['assetTypes']:
entityType = Ent.DATASTUDIO_ASSET_REPORT if assetType == 'REPORT' else Ent.DATASTUDIO_ASSET_DATASOURCE entityType = Ent.LOOKERSTUDIO_ASSET_REPORT if assetType == 'REPORT' else Ent.LOOKERSTUDIO_ASSET_DATASOURCE
printGettingAllEntityItemsForWhom(entityType, user, i, count) printGettingAllEntityItemsForWhom(entityType, user, i, count)
parameters['assetTypes'] = assetType parameters['assetTypes'] = assetType
try: try:
assets.extend(callGAPIpages(ds.assets(), 'search', 'assets', assets.extend(callGAPIpages(ds.assets(), 'search', 'assets',
pageMessage=getPageMessage(), pageMessage=getPageMessage(),
throwReasons=GAPI.DATASTUDIO_THROW_REASONS, throwReasons=GAPI.LOOKERSTUDIO_THROW_REASONS,
**parameters, orderBy=orderBy, fields=fields)) **parameters, orderBy=orderBy, fields=fields))
except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e: except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e:
entityActionFailedWarning([Ent.USER, user], str(e), i, count) entityActionFailedWarning([Ent.USER, user], str(e), i, count)
@ -60906,26 +60948,26 @@ def _getDataStudioAssets(ds, user, i, count, parameters, assetTypes, fields, ord
return (None, 0) return (None, 0)
return (assets, len(assets)) return (assets, len(assets))
DATASTUDIO_ASSETS_ORDERBY_CHOICE_MAP = { LOOKERSTUDIO_ASSETS_ORDERBY_CHOICE_MAP = {
'title': 'title' 'title': 'title'
} }
DATASTUDIO_ASSETS_TIME_OBJECTS = {'updateTime', 'updateByMeTime', 'createTime', 'lastViewByMeTime'} LOOKERSTUDIO_ASSETS_TIME_OBJECTS = {'updateTime', 'updateByMeTime', 'createTime', 'lastViewByMeTime'}
# gam <UserTypeEntity> print datastudioassets [todrive <ToDriveAttribute>*] # gam <UserTypeEntity> print lookerstudioassets [todrive <ToDriveAttribute>*]
# [([assettype report|datasource|all] [title <String>] # [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed] # [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) | # [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)] # (assetids <LookerStudioAssetIDEntity>)]
# [stripcrsfromtitle] # [stripcrsfromtitle]
# [formatjson [quotechar <Character>]] # [formatjson [quotechar <Character>]]
# gam <UserTypeEntity> show datastudioassets # gam <UserTypeEntity> show lookerstudioassets
# [([assettype report|datasource|all] [title <String>] # [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed] # [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) | # [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)] # (assetids <LookerStudioAssetIDEntity>)]
# [stripcrsfromtitle] # [stripcrsfromtitle]
# [formatjson] # [formatjson]
def printShowDataStudioAssets(users): def printShowLookerStudioAssets(users):
def _printAsset(asset, user): def _printAsset(asset, user):
if stripCRsFromTitle: if stripCRsFromTitle:
asset['title'] = _stripControlCharsFromName(asset['title']) asset['title'] = _stripControlCharsFromName(asset['title'])
@ -60934,33 +60976,33 @@ def printShowDataStudioAssets(users):
csvPF.WriteRowTitles(row) csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row): elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'User': user, 'title': asset['title'], csvPF.WriteRowNoFilter({'User': user, 'title': asset['title'],
'JSON': json.dumps(cleanJSON(asset, timeObjects=DATASTUDIO_ASSETS_TIME_OBJECTS), ensure_ascii=False, sort_keys=True)}) 'JSON': json.dumps(cleanJSON(asset, timeObjects=LOOKERSTUDIO_ASSETS_TIME_OBJECTS), ensure_ascii=False, sort_keys=True)})
def _showAsset(asset): def _showAsset(asset):
if stripCRsFromTitle: if stripCRsFromTitle:
asset['title'] = _stripControlCharsFromName(asset['title']) asset['title'] = _stripControlCharsFromName(asset['title'])
if FJQC.formatJSON: if FJQC.formatJSON:
printLine(json.dumps(cleanJSON(asset, timeObjects=DATASTUDIO_ASSETS_TIME_OBJECTS), ensure_ascii=False, sort_keys=False)) printLine(json.dumps(cleanJSON(asset, timeObjects=LOOKERSTUDIO_ASSETS_TIME_OBJECTS), ensure_ascii=False, sort_keys=False))
return return
printEntity([Ent.DATASTUDIO_ASSET, asset['title']], j, jcount) printEntity([Ent.LOOKERSTUDIO_ASSET, asset['title']], j, jcount)
Ind.Increment() Ind.Increment()
showJSON(None, asset, timeObjects=DATASTUDIO_ASSETS_TIME_OBJECTS) showJSON(None, asset, timeObjects=LOOKERSTUDIO_ASSETS_TIME_OBJECTS)
Ind.Decrement() Ind.Decrement()
csvPF = CSVPrintFile(['User', 'title']) if Act.csvFormat() else None csvPF = CSVPrintFile(['User', 'title']) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
OBY = OrderBy(DATASTUDIO_ASSETS_ORDERBY_CHOICE_MAP, ascendingKeyword='ascending', descendingKeyword='') OBY = OrderBy(LOOKERSTUDIO_ASSETS_ORDERBY_CHOICE_MAP, ascendingKeyword='ascending', descendingKeyword='')
parameters, assetTypes = initDataStudioAssetSelectionParameters() parameters, assetTypes = initLookerStudioAssetSelectionParameters()
assetIdEntity = None assetIdEntity = None
stripCRsFromTitle = False stripCRsFromTitle = False
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if csvPF and myarg == 'todrive': if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters() csvPF.GetTodriveParameters()
elif getDataStudioAssetSelectionParameters(myarg, parameters, assetTypes): elif getLookerStudioAssetSelectionParameters(myarg, parameters, assetTypes):
pass pass
elif myarg in {'assetid', 'assetids'}: elif myarg in {'assetid', 'assetids'}:
assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.DATASTUDIO_ASSETID) assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.LOOKERSTUDIO_ASSETID)
elif myarg == 'stripcrsfromtitle': elif myarg == 'stripcrsfromtitle':
stripCRsFromTitle = True stripCRsFromTitle = True
elif myarg == 'orderby': elif myarg == 'orderby':
@ -60970,35 +61012,35 @@ def printShowDataStudioAssets(users):
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
for user in users: for user in users:
i += 1 i += 1
user, ds, assets, jcount = _validateUserGetDataStudioAssetIds(user, i, count, assetIdEntity) user, ds, assets, jcount = _validateUserGetLookerStudioAssetIds(user, i, count, assetIdEntity)
if not ds: if not ds:
continue continue
if assetIdEntity is None: if assetIdEntity is None:
assets, jcount = _getDataStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets', OBY.orderBy) assets, jcount = _getLookerStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets', OBY.orderBy)
if assets is None: if assets is None:
continue continue
if not csvPF: if not csvPF:
if not FJQC.formatJSON: if not FJQC.formatJSON:
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.DATASTUDIO_ASSET, i, count) entityPerformActionNumItems([Ent.USER, user], jcount, Ent.LOOKERSTUDIO_ASSET, i, count)
Ind.Increment() Ind.Increment()
j = 0 j = 0
for asset in assets: for asset in assets:
j += 1 j += 1
if assetIdEntity: if assetIdEntity:
asset = _getDataStudioAssetByID(ds, user, i, count, asset['name']) asset = _getLookerStudioAssetByID(ds, user, i, count, asset['name'])
if asset: if asset:
_showAsset(asset) _showAsset(asset)
Ind.Decrement() Ind.Decrement()
else: else:
for asset in assets: for asset in assets:
if assetIdEntity: if assetIdEntity:
asset = _getDataStudioAssetByID(ds, user, i, count, asset['name']) asset = _getLookerStudioAssetByID(ds, user, i, count, asset['name'])
if asset: if asset:
_printAsset(asset, user) _printAsset(asset, user)
if csvPF: if csvPF:
csvPF.writeCSVfile('Data Studio Assets') csvPF.writeCSVfile('Looker Studio Assets')
def _showDataStudioPermissions(user, asset, permissions, j, jcount, FJQC): def _showLookerStudioPermissions(user, asset, permissions, j, jcount, FJQC):
if FJQC is not None and FJQC.formatJSON: if FJQC is not None and FJQC.formatJSON:
permissions['User'] = user permissions['User'] = user
permissions['assetId'] = asset['name'] permissions['assetId'] = asset['name']
@ -61006,7 +61048,7 @@ def _showDataStudioPermissions(user, asset, permissions, j, jcount, FJQC):
return return
permissions = permissions['permissions'] permissions = permissions['permissions']
if permissions: if permissions:
printEntity([Ent.DATASTUDIO_ASSET, asset['title'], Ent.DATASTUDIO_PERMISSION, ''], j, jcount) printEntity([Ent.LOOKERSTUDIO_ASSET, asset['title'], Ent.LOOKERSTUDIO_PERMISSION, ''], j, jcount)
for role in ['OWNER', 'EDITOR', 'VIEWER']: for role in ['OWNER', 'EDITOR', 'VIEWER']:
members = permissions.get(role, {}).get('members', []) members = permissions.get(role, {}).get('members', [])
if members: if members:
@ -61016,25 +61058,25 @@ def _showDataStudioPermissions(user, asset, permissions, j, jcount, FJQC):
printKeyValueList([lrole, member]) printKeyValueList([lrole, member])
Ind.Decrement() Ind.Decrement()
DATASTUDIO_VIEW_PERMISSION_ROLE_CHOICE_MAP = { LOOKERSTUDIO_VIEW_PERMISSION_ROLE_CHOICE_MAP = {
'editor': 'EDITOR', 'editor': 'EDITOR',
'owner': 'OWNER', 'owner': 'OWNER',
'viewer': 'VIEWER', 'viewer': 'VIEWER',
} }
DATASTUDIO_ADD_UPDATE_PERMISSION_ROLE_CHOICE_MAP = { LOOKERSTUDIO_ADD_UPDATE_PERMISSION_ROLE_CHOICE_MAP = {
'editor': 'EDITOR', 'editor': 'EDITOR',
'viewer': 'VIEWER', 'viewer': 'VIEWER',
} }
DATASTUDIO_DELETE_PERMISSION_ROLE_CHOICE_MAP = { LOOKERSTUDIO_DELETE_PERMISSION_ROLE_CHOICE_MAP = {
'any': None, 'any': None,
'editor': None, 'editor': None,
'owner': None, 'owner': None,
'viewer': None, 'viewer': None,
} }
DATASTUDIO_PERMISSION_MODIFIER_MAP = { LOOKERSTUDIO_PERMISSION_MODIFIER_MAP = {
Act.ADD: Act.MODIFIER_TO, Act.ADD: Act.MODIFIER_TO,
Act.DELETE: Act.MODIFIER_FROM, Act.DELETE: Act.MODIFIER_FROM,
Act.UPDATE: Act.MODIFIER_FOR Act.UPDATE: Act.MODIFIER_FOR
@ -61044,46 +61086,46 @@ DATASTUDIO_PERMISSION_MODIFIER_MAP = {
# [([assettype report|datasource|all] [title <String>] # [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed] # [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) | # [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)] # (assetids <LookerStudioAssetIDEntity>)]
# (role editor|viewer <DataStudioPermissionEntity>)+ # (role editor|viewer <LookerStudioPermissionEntity>)+
# [nodetails] # [nodetails]
# gam <UserTypeEntity> delete datastudiopermissions # gam <UserTypeEntity> delete datastudiopermissions
# ([[assettype report|datasource|all] [title <String>] # ([[assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed] # [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) | # [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)] # (assetids <LookerStudioAssetIDEntity>)]
# (role any <DataStudioPermissionEntity>)+ # (role any <LookerStudioPermissionEntity>)+
# [nodetails] # [nodetails]
# gam <UserTypeEntity> update datastudiopermissions # gam <UserTypeEntity> update datastudiopermissions
# [([assettype report|datasource|all] [title <String>] # [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed] # [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) | # [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)] # (assetids <LookerStudioAssetIDEntity>)]
# (role editor|viewer <DataStudioPermissionEntity>)+ # (role editor|viewer <LookerStudioPermissionEntity>)+
# [nodetails] # [nodetails]
def processDataStudioPermissions(users): def processLookerStudioPermissions(users):
action = Act.Get() action = Act.Get()
if action == Act.CREATE: if action == Act.CREATE:
action = Act.ADD action = Act.ADD
modifier = DATASTUDIO_PERMISSION_MODIFIER_MAP[action] modifier = LOOKERSTUDIO_PERMISSION_MODIFIER_MAP[action]
parameters, assetTypes = initDataStudioAssetSelectionParameters() parameters, assetTypes = initLookerStudioAssetSelectionParameters()
permissions = {} permissions = {}
assetIdEntity = None assetIdEntity = None
showDetails = True showDetails = True
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if getDataStudioAssetSelectionParameters(myarg, parameters, assetTypes): if getLookerStudioAssetSelectionParameters(myarg, parameters, assetTypes):
pass pass
elif myarg in {'assetid', 'assetids'}: elif myarg in {'assetid', 'assetids'}:
assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.DATASTUDIO_ASSETID) assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.LOOKERSTUDIO_ASSETID)
elif myarg == 'role': elif myarg == 'role':
permissions.setdefault('permissions', {}) permissions.setdefault('permissions', {})
if action in {Act.ADD, Act.UPDATE}: if action in {Act.ADD, Act.UPDATE}:
role = getChoice(DATASTUDIO_ADD_UPDATE_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True) role = getChoice(LOOKERSTUDIO_ADD_UPDATE_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True)
else: else:
role = getChoice(DATASTUDIO_DELETE_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True) role = getChoice(LOOKERSTUDIO_DELETE_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True)
permissions['permissions'].setdefault(role, {'members': []}) permissions['permissions'].setdefault(role, {'members': []})
permissions['permissions'][role]['members'].extend(getEntityList(Cmd.OB_DATASTUDIO_ASSET_MEMBERS_ENTITY)) permissions['permissions'][role]['members'].extend(getEntityList(Cmd.OB_LOOKERSTUDIO_PERMISSION_ENTITY))
elif myarg == 'nodetails': elif myarg == 'nodetails':
showDetails = False showDetails = False
else: else:
@ -61096,14 +61138,14 @@ def processDataStudioPermissions(users):
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
for user in users: for user in users:
i += 1 i += 1
user, ds, assets, jcount = _validateUserGetDataStudioAssetIds(user, i, count, assetIdEntity) user, ds, assets, jcount = _validateUserGetLookerStudioAssetIds(user, i, count, assetIdEntity)
if not ds: if not ds:
continue continue
if assetIdEntity is None: if assetIdEntity is None:
assets, jcount = _getDataStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets(name,title)', None) assets, jcount = _getLookerStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets(name,title)', None)
if assets is None: if assets is None:
continue continue
entityPerformActionSubItemModifierNumItems([Ent.USER, user], Ent.DATASTUDIO_PERMISSION, modifier, jcount, Ent.DATASTUDIO_ASSET, i, count) entityPerformActionSubItemModifierNumItems([Ent.USER, user], Ent.LOOKERSTUDIO_PERMISSION, modifier, jcount, Ent.LOOKERSTUDIO_ASSET, i, count)
j = 0 j = 0
for asset in assets: for asset in assets:
j += 1 j += 1
@ -61112,18 +61154,18 @@ def processDataStudioPermissions(users):
body = {'name': asset['name'], 'members': permissions['permissions'][role]['members']} body = {'name': asset['name'], 'members': permissions['permissions'][role]['members']}
if action in {Act.DELETE, Act.UPDATE}: if action in {Act.DELETE, Act.UPDATE}:
results = callGAPI(ds.assets().permissions(), 'revokeAllPermissions', results = callGAPI(ds.assets().permissions(), 'revokeAllPermissions',
throwReasons=GAPI.DATASTUDIO_THROW_REASONS, throwReasons=GAPI.LOOKERSTUDIO_THROW_REASONS,
name=asset['name'], body=body) name=asset['name'], body=body)
if action in {Act.ADD, Act.UPDATE}: if action in {Act.ADD, Act.UPDATE}:
body['role'] = role body['role'] = role
results = callGAPI(ds.assets().permissions(), 'addMembers', results = callGAPI(ds.assets().permissions(), 'addMembers',
throwReasons=GAPI.DATASTUDIO_THROW_REASONS, throwReasons=GAPI.LOOKERSTUDIO_THROW_REASONS,
name=asset['name'], body=body) name=asset['name'], body=body)
entityActionPerformed([Ent.USER, user, Ent.DATASTUDIO_ASSET, asset['title'], Ent.DATASTUDIO_PERMISSION, ''], j, jcount) entityActionPerformed([Ent.USER, user, Ent.LOOKERSTUDIO_ASSET, asset['title'], Ent.LOOKERSTUDIO_PERMISSION, ''], j, jcount)
if showDetails: if showDetails:
_showDataStudioPermissions(user, asset, results, j, jcount, None) _showLookerStudioPermissions(user, asset, results, j, jcount, None)
except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e: except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e:
entityActionFailedWarning([Ent.USER, user, Ent.DATASTUDIO_ASSET, asset['title']], str(e), j, jcount) entityActionFailedWarning([Ent.USER, user, Ent.LOOKERSTUDIO_ASSET, asset['title']], str(e), j, jcount)
continue continue
except GAPI.serviceNotAvailable: except GAPI.serviceNotAvailable:
entityServiceNotApplicableWarning(Ent.USER, user, i, count) entityServiceNotApplicableWarning(Ent.USER, user, i, count)
@ -61133,18 +61175,18 @@ def processDataStudioPermissions(users):
# [([assettype report|datasource|all] [title <String>] # [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed] # [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) | # [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)] # (assetids <LookerStudioAssetIDEntity>)]
# [role editor|owner|viewer] # [role editor|owner|viewer]
# [formatjson [quotechar <Character>]] # [formatjson [quotechar <Character>]]
# gam <UserTypeEntity> show datastudiopermissions # gam <UserTypeEntity> show datastudiopermissions
# [([assettype report|datasource|all] [title <String>] # [([assettype report|datasource|all] [title <String>]
# [owner <Emailddress>] [includetrashed] # [owner <Emailddress>] [includetrashed]
# [orderby title [ascending|descending]]) | # [orderby title [ascending|descending]]) |
# (assetids <DataStudioAssetIDEntity>)[ # (assetids <LookerStudioAssetIDEntity>)[
# [role editor|owner|viewer] # [role editor|owner|viewer]
# [formatjson] # [formatjson]
def printShowDataStudioPermissions(users): def printShowLookerStudioPermissions(users):
def _printDataStudioPermissions(user, asset, permissions): def _printLookerStudioPermissions(user, asset, permissions):
row = flattenJSON(permissions, flattened={'User': user, 'assetId': asset['name']}, row = flattenJSON(permissions, flattened={'User': user, 'assetId': asset['name']},
simpleLists=['members'], delimiter=delimiter) simpleLists=['members'], delimiter=delimiter)
if not FJQC.formatJSON: if not FJQC.formatJSON:
@ -61156,19 +61198,19 @@ def printShowDataStudioPermissions(users):
csvPF = CSVPrintFile(['User', 'assetId']) if Act.csvFormat() else None csvPF = CSVPrintFile(['User', 'assetId']) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER] delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
parameters, assetTypes = initDataStudioAssetSelectionParameters() parameters, assetTypes = initLookerStudioAssetSelectionParameters()
assetIdEntity = None assetIdEntity = None
role = None role = None
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if csvPF and myarg == 'todrive': if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters() csvPF.GetTodriveParameters()
elif getDataStudioAssetSelectionParameters(myarg, parameters, assetTypes): elif getLookerStudioAssetSelectionParameters(myarg, parameters, assetTypes):
pass pass
elif myarg in {'assetid', 'assetids'}: elif myarg in {'assetid', 'assetids'}:
assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.DATASTUDIO_ASSETID) assetIdEntity = getUserObjectEntity(Cmd.OB_USER_ENTITY, Ent.LOOKERSTUDIO_ASSETID)
elif myarg == 'role': elif myarg == 'role':
role = getChoice(DATASTUDIO_VIEW_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True) role = getChoice(LOOKERSTUDIO_VIEW_PERMISSION_ROLE_CHOICE_MAP, mapChoice=True)
elif myarg == 'delimiter': elif myarg == 'delimiter':
delimiter = getCharacter() delimiter = getCharacter()
else: else:
@ -61176,36 +61218,36 @@ def printShowDataStudioPermissions(users):
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
for user in users: for user in users:
i += 1 i += 1
user, ds, assets, jcount = _validateUserGetDataStudioAssetIds(user, i, count, assetIdEntity) user, ds, assets, jcount = _validateUserGetLookerStudioAssetIds(user, i, count, assetIdEntity)
if not ds: if not ds:
continue continue
if assetIdEntity is None: if assetIdEntity is None:
assets, jcount = _getDataStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets(name,title)', None) assets, jcount = _getLookerStudioAssets(ds, user, i, count, parameters, assetTypes, 'nextPageToken,assets(name,title)', None)
if assets is None: if assets is None:
continue continue
if not csvPF and not FJQC.formatJSON: if not csvPF and not FJQC.formatJSON:
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.DATASTUDIO_ASSET, i, count) entityPerformActionNumItems([Ent.USER, user], jcount, Ent.LOOKERSTUDIO_ASSET, i, count)
j = 0 j = 0
for asset in assets: for asset in assets:
j += 1 j += 1
try: try:
permissions = callGAPI(ds.assets(), 'getPermissions', permissions = callGAPI(ds.assets(), 'getPermissions',
throwReasons=GAPI.DATASTUDIO_THROW_REASONS, throwReasons=GAPI.LOOKERSTUDIO_THROW_REASONS,
name=asset['name'], role=role) name=asset['name'], role=role)
except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e: except (GAPI.invalidArgument, GAPI.badRequest, GAPI.notFound, GAPI.permissionDenied) as e:
entityActionFailedWarning([Ent.USER, user, Ent.DATASTUDIO_ASSET, asset['title']], str(e), j, jcount) entityActionFailedWarning([Ent.USER, user, Ent.LOOKERSTUDIO_ASSET, asset['title']], str(e), j, jcount)
continue continue
except GAPI.serviceNotAvailable: except GAPI.serviceNotAvailable:
entityServiceNotApplicableWarning(Ent.USER, user, i, count) entityServiceNotApplicableWarning(Ent.USER, user, i, count)
break break
if not csvPF: if not csvPF:
Ind.Increment() Ind.Increment()
_showDataStudioPermissions(user, asset, permissions, j, jcount, FJQC) _showLookerStudioPermissions(user, asset, permissions, j, jcount, FJQC)
Ind.Decrement() Ind.Decrement()
else: else:
_printDataStudioPermissions(user, asset, permissions) _printLookerStudioPermissions(user, asset, permissions)
if csvPF: if csvPF:
csvPF.writeCSVfile('Data Studio Permissions') csvPF.writeCSVfile('Looker Studio Permissions')
def _validateSubkeyRoleGetGroups(user, role, origUser, userGroupLists, i, count): def _validateSubkeyRoleGetGroups(user, role, origUser, userGroupLists, i, count):
roleLower = role.lower() roleLower = role.lower()
@ -61235,7 +61277,7 @@ def _addUserToGroups(cd, user, addGroupsSet, addGroups, i, count):
entityActionPerformed([Ent.GROUP, group, role, user], j, jcount) entityActionPerformed([Ent.GROUP, group, role, user], j, jcount)
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, group, j, jcount) entityUnknownWarning(Ent.GROUP, group, j, jcount)
except (GAPI.duplicate, GAPI.cyclicMembershipsNotAllowed, GAPI.conditionNotMet) as e: except (GAPI.duplicate, GAPI.cyclicMembershipsNotAllowed, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.GROUP, group, role, user], str(e), j, jcount) entityActionFailedWarning([Ent.GROUP, group, role, user], str(e), j, jcount)
except GAPI.conflict: except GAPI.conflict:
entityActionPerformedMessage([Ent.GROUP, group, role, user], Msg.ACTION_MAY_BE_DELAYED, j, jcount) entityActionPerformedMessage([Ent.GROUP, group, role, user], Msg.ACTION_MAY_BE_DELAYED, j, jcount)
@ -61302,7 +61344,7 @@ def _deleteUserFromGroups(cd, user, deleteGroupsSet, deleteGroups, i, count):
entityActionPerformed([Ent.GROUP, group, role, user], j, jcount) entityActionPerformed([Ent.GROUP, group, role, user], j, jcount)
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, group, j, jcount) entityUnknownWarning(Ent.GROUP, group, j, jcount)
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet) as e: except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, group], str(e), j, jcount) entityActionFailedWarning([Ent.USER, user, Ent.GROUP, group], str(e), j, jcount)
except GAPI.conflict: except GAPI.conflict:
entityActionPerformedMessage([Ent.GROUP, group, role, user], Msg.ACTION_MAY_BE_DELAYED, j, jcount) entityActionPerformedMessage([Ent.GROUP, group, role, user], Msg.ACTION_MAY_BE_DELAYED, j, jcount)
@ -61402,7 +61444,7 @@ def _updateUserGroups(cd, user, updateGroupsSet, updateGroups, i, count):
entityActionPerformed([Ent.GROUP, group, role, user], j, jcount) entityActionPerformed([Ent.GROUP, group, role, user], j, jcount)
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, group, j, jcount) entityUnknownWarning(Ent.GROUP, group, j, jcount)
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet) as e: except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, group], str(e), j, jcount) entityActionFailedWarning([Ent.USER, user, Ent.GROUP, group], str(e), j, jcount)
Ind.Decrement() Ind.Decrement()
@ -61533,7 +61575,7 @@ def syncUserWithGroups(users):
'delivery_settings': result.get('delivery_settings', DELIVERY_SETTINGS_UNDEFINED)} 'delivery_settings': result.get('delivery_settings', DELIVERY_SETTINGS_UNDEFINED)}
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, groupEmail, i, count) entityUnknownWarning(Ent.GROUP, groupEmail, i, count)
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet) as e: except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), i, count) entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), i, count)
currGroupsSet = set(currGroups) currGroupsSet = set(currGroups)
syncGroupsSet = set(syncGroups) syncGroupsSet = set(syncGroups)
@ -61649,7 +61691,7 @@ def checkUserInGroups(users):
else: else:
csvPF.WriteRow({'user': user, 'group': groupEmail, 'role': notMemberOrRole}) csvPF.WriteRow({'user': user, 'group': groupEmail, 'role': notMemberOrRole})
_setCheckError() _setCheckError()
except (GAPI.invalidMember, GAPI.conditionNotMet) as e: except (GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), j, jcount) entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), j, jcount)
_setCheckError() _setCheckError()
else: else:
@ -61672,6 +61714,9 @@ def checkUserInGroups(users):
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, groupEmail, j, jcount) entityUnknownWarning(Ent.GROUP, groupEmail, j, jcount)
_setCheckError() _setCheckError()
except (GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), j, jcount)
_setCheckError()
Ind.Decrement() Ind.Decrement()
if csvPF: if csvPF:
csvPF.writeCSVfile('User Check Groups') csvPF.writeCSVfile('User Check Groups')
@ -61793,7 +61838,7 @@ def printShowUserGroups(users):
csvPF.WriteRow({'User': user, 'Group': groupEmail, 'Role': role, 'Status': status, 'Delivery': delivery_settings}) csvPF.WriteRow({'User': user, 'Group': groupEmail, 'Role': role, 'Status': status, 'Delivery': delivery_settings})
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, groupEmail, j, jcount) entityUnknownWarning(Ent.GROUP, groupEmail, j, jcount)
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet) as e: except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), j, jcount) entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), j, jcount)
if countsOnly: if countsOnly:
if not csvPF: if not csvPF:
@ -61930,7 +61975,7 @@ def printShowGroupTree(users):
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden): except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden):
entityUnknownWarning(Ent.GROUP, groupEmail, j, jcount) entityUnknownWarning(Ent.GROUP, groupEmail, j, jcount)
continue continue
except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet) as e: except (GAPI.memberNotFound, GAPI.invalidMember, GAPI.conditionNotMet, GAPI.serviceNotAvailable) as e:
entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), j, jcount) entityActionFailedWarning([Ent.USER, user, Ent.GROUP, groupEmail], str(e), j, jcount)
continue continue
else: else:
@ -70558,7 +70603,7 @@ USER_ADD_CREATE_FUNCTIONS = {
Cmd.ARG_CHATSPACE: createChatSpace, Cmd.ARG_CHATSPACE: createChatSpace,
Cmd.ARG_CLASSROOMINVITATION: createClassroomInvitations, Cmd.ARG_CLASSROOMINVITATION: createClassroomInvitations,
Cmd.ARG_CONTACTDELEGATE: processContactDelegates, Cmd.ARG_CONTACTDELEGATE: processContactDelegates,
Cmd.ARG_DATASTUDIOPERMISSION: processDataStudioPermissions, Cmd.ARG_LOOKERSTUDIOPERMISSION: processLookerStudioPermissions,
Cmd.ARG_DELEGATE: processDelegates, Cmd.ARG_DELEGATE: processDelegates,
Cmd.ARG_DRIVEFILE: createDriveFile, Cmd.ARG_DRIVEFILE: createDriveFile,
Cmd.ARG_DRIVEFILEACL: createDriveFileACL, Cmd.ARG_DRIVEFILEACL: createDriveFileACL,
@ -70668,7 +70713,7 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_CHATSPACE: deleteChatSpace, Cmd.ARG_CHATSPACE: deleteChatSpace,
Cmd.ARG_CLASSROOMINVITATION: deleteClassroomInvitations, Cmd.ARG_CLASSROOMINVITATION: deleteClassroomInvitations,
Cmd.ARG_CONTACTDELEGATE: processContactDelegates, Cmd.ARG_CONTACTDELEGATE: processContactDelegates,
Cmd.ARG_DATASTUDIOPERMISSION: processDataStudioPermissions, Cmd.ARG_LOOKERSTUDIOPERMISSION: processLookerStudioPermissions,
Cmd.ARG_DELEGATE: processDelegates, Cmd.ARG_DELEGATE: processDelegates,
Cmd.ARG_DRIVEFILE: deleteDriveFile, Cmd.ARG_DRIVEFILE: deleteDriveFile,
Cmd.ARG_DRIVEFILEACL: deleteDriveFileACLs, Cmd.ARG_DRIVEFILEACL: deleteDriveFileACLs,
@ -70817,8 +70862,8 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_CLASSROOMINVITATION: printShowClassroomInvitations, Cmd.ARG_CLASSROOMINVITATION: printShowClassroomInvitations,
Cmd.ARG_CLASSROOMPROFILE: printShowClassroomProfile, Cmd.ARG_CLASSROOMPROFILE: printShowClassroomProfile,
Cmd.ARG_CONTACTDELEGATE: printShowContactDelegates, Cmd.ARG_CONTACTDELEGATE: printShowContactDelegates,
Cmd.ARG_DATASTUDIOASSET: printShowDataStudioAssets, Cmd.ARG_LOOKERSTUDIOASSET: printShowLookerStudioAssets,
Cmd.ARG_DATASTUDIOPERMISSION: printShowDataStudioPermissions, Cmd.ARG_LOOKERSTUDIOPERMISSION: printShowLookerStudioPermissions,
Cmd.ARG_DELEGATE: printShowDelegates, Cmd.ARG_DELEGATE: printShowDelegates,
Cmd.ARG_DISKUSAGE: printDiskUsage, Cmd.ARG_DISKUSAGE: printDiskUsage,
Cmd.ARG_DRIVEACTIVITY: printDriveActivity, Cmd.ARG_DRIVEACTIVITY: printDriveActivity,
@ -70910,8 +70955,8 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_CLASSROOMPROFILE: printShowClassroomProfile, Cmd.ARG_CLASSROOMPROFILE: printShowClassroomProfile,
Cmd.ARG_CONTACTDELEGATE: printShowContactDelegates, Cmd.ARG_CONTACTDELEGATE: printShowContactDelegates,
Cmd.ARG_COUNT: showCountUser, Cmd.ARG_COUNT: showCountUser,
Cmd.ARG_DATASTUDIOASSET: printShowDataStudioAssets, Cmd.ARG_LOOKERSTUDIOASSET: printShowLookerStudioAssets,
Cmd.ARG_DATASTUDIOPERMISSION: printShowDataStudioPermissions, Cmd.ARG_LOOKERSTUDIOPERMISSION: printShowLookerStudioPermissions,
Cmd.ARG_DELEGATE: printShowDelegates, Cmd.ARG_DELEGATE: printShowDelegates,
Cmd.ARG_DISKUSAGE: printDiskUsage, Cmd.ARG_DISKUSAGE: printDiskUsage,
Cmd.ARG_DRIVEACTIVITY: printDriveActivity, Cmd.ARG_DRIVEACTIVITY: printDriveActivity,
@ -71029,7 +71074,7 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_CALENDARACL: updateCalendarACLs, Cmd.ARG_CALENDARACL: updateCalendarACLs,
Cmd.ARG_CHATMESSAGE: updateChatMessage, Cmd.ARG_CHATMESSAGE: updateChatMessage,
Cmd.ARG_CHATSPACE: updateChatSpace, Cmd.ARG_CHATSPACE: updateChatSpace,
Cmd.ARG_DATASTUDIOPERMISSION: processDataStudioPermissions, Cmd.ARG_LOOKERSTUDIOPERMISSION: processLookerStudioPermissions,
Cmd.ARG_DELEGATE: updateDelegates, Cmd.ARG_DELEGATE: updateDelegates,
Cmd.ARG_DRIVEFILE: updateDriveFile, Cmd.ARG_DRIVEFILE: updateDriveFile,
Cmd.ARG_DRIVEFILEACL: updateDriveFileACLs, Cmd.ARG_DRIVEFILEACL: updateDriveFileACLs,
@ -71110,8 +71155,12 @@ USER_COMMANDS_OBJ_ALIASES = {
Cmd.ARG_CONTACTPHOTO: Cmd.ARG_PEOPLECONTACTPHOTO, Cmd.ARG_CONTACTPHOTO: Cmd.ARG_PEOPLECONTACTPHOTO,
Cmd.ARG_CONTACTPHOTOS: Cmd.ARG_PEOPLECONTACTPHOTO, Cmd.ARG_CONTACTPHOTOS: Cmd.ARG_PEOPLECONTACTPHOTO,
Cmd.ARG_COUNTS: Cmd.ARG_COUNT, Cmd.ARG_COUNTS: Cmd.ARG_COUNT,
Cmd.ARG_DATASTUDIOASSETS: Cmd.ARG_DATASTUDIOASSET, Cmd.ARG_DATASTUDIOASSET: Cmd.ARG_LOOKERSTUDIOASSET,
Cmd.ARG_DATASTUDIOPERMISSIONS: Cmd.ARG_DATASTUDIOPERMISSION, Cmd.ARG_DATASTUDIOPERMISSION: Cmd.ARG_LOOKERSTUDIOPERMISSION,
Cmd.ARG_DATASTUDIOASSETS: Cmd.ARG_LOOKERSTUDIOASSET,
Cmd.ARG_DATASTUDIOPERMISSIONS: Cmd.ARG_LOOKERSTUDIOPERMISSION,
Cmd.ARG_LOOKERSTUDIOASSETS: Cmd.ARG_LOOKERSTUDIOASSET,
Cmd.ARG_LOOKERSTUDIOPERMISSIONS: Cmd.ARG_LOOKERSTUDIOPERMISSION,
Cmd.ARG_DELEGATES: Cmd.ARG_DELEGATE, Cmd.ARG_DELEGATES: Cmd.ARG_DELEGATE,
Cmd.ARG_DOMAINCONTACT: Cmd.ARG_PEOPLECONTACT, Cmd.ARG_DOMAINCONTACT: Cmd.ARG_PEOPLECONTACT,
Cmd.ARG_DOMAINCONTACTS: Cmd.ARG_PEOPLECONTACT, Cmd.ARG_DOMAINCONTACTS: Cmd.ARG_PEOPLECONTACT,

View File

@ -47,7 +47,6 @@ CLOUDRESOURCEMANAGER = 'cloudresourcemanager'
CLOUDRESOURCEMANAGER_V1 = 'cloudresourcemanager1' CLOUDRESOURCEMANAGER_V1 = 'cloudresourcemanager1'
CONTACTS = 'contacts' CONTACTS = 'contacts'
CONTACTDELEGATION = 'contactdelegation' CONTACTDELEGATION = 'contactdelegation'
DATASTUDIO = 'datastudio'
DATATRANSFER = 'datatransfer' DATATRANSFER = 'datatransfer'
DIRECTORY = 'directory' DIRECTORY = 'directory'
DIRECTORY_BETA = 'directory_beta' DIRECTORY_BETA = 'directory_beta'
@ -69,6 +68,7 @@ IAM_CREDENTIALS = 'iamcredentials'
IAP = 'iap' IAP = 'iap'
KEEP = 'keep' KEEP = 'keep'
LICENSING = 'licensing' LICENSING = 'licensing'
LOOKERSTUDIO = 'datastudio'
OAUTH2 = 'oauth2' OAUTH2 = 'oauth2'
PEOPLE = 'people' PEOPLE = 'people'
PEOPLE_DIRECTORY = 'peopledirectory' PEOPLE_DIRECTORY = 'peopledirectory'
@ -206,7 +206,6 @@ _INFO = {
CLOUDRESOURCEMANAGER: {'name': 'Cloud Resource Manager API v3', 'version': 'v3', 'v2discovery': True}, CLOUDRESOURCEMANAGER: {'name': 'Cloud Resource Manager API v3', 'version': 'v3', 'v2discovery': True},
CONTACTS: {'name': 'Contacts API', 'version': 'v3', 'v2discovery': False}, CONTACTS: {'name': 'Contacts API', 'version': 'v3', 'v2discovery': False},
CONTACTDELEGATION: {'name': 'Contact Delegation API', 'version': 'v1', 'v2discovery': True, 'localjson': True}, CONTACTDELEGATION: {'name': 'Contact Delegation API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
DATASTUDIO: {'name': 'Data Studio API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
DATATRANSFER: {'name': 'Data Transfer API', 'version': 'datatransfer_v1', 'v2discovery': True, 'mappedAPI': 'admin'}, DATATRANSFER: {'name': 'Data Transfer API', 'version': 'datatransfer_v1', 'v2discovery': True, 'mappedAPI': 'admin'},
DIRECTORY: {'name': 'Directory API', 'version': 'directory_v1', 'v2discovery': True, 'mappedAPI': 'admin'}, DIRECTORY: {'name': 'Directory API', 'version': 'directory_v1', 'v2discovery': True, 'mappedAPI': 'admin'},
DIRECTORY_BETA: {'name': 'Directory API', 'version': 'directory_v1.1beta1', 'v2discovery': True, 'mappedAPI': 'admin', 'localjson': True}, DIRECTORY_BETA: {'name': 'Directory API', 'version': 'directory_v1.1beta1', 'v2discovery': True, 'mappedAPI': 'admin', 'localjson': True},
@ -227,6 +226,7 @@ _INFO = {
IAP: {'name': 'Cloud Identity-Aware Proxy API', 'version': 'v1', 'v2discovery': True}, IAP: {'name': 'Cloud Identity-Aware Proxy API', 'version': 'v1', 'v2discovery': True},
KEEP: {'name': 'Keep API', 'version': 'v1', 'v2discovery': True}, KEEP: {'name': 'Keep API', 'version': 'v1', 'v2discovery': True},
LICENSING: {'name': 'License Manager API', 'version': 'v1', 'v2discovery': True}, LICENSING: {'name': 'License Manager API', 'version': 'v1', 'v2discovery': True},
LOOKERSTUDIO: {'name': 'Looker Studio API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
OAUTH2: {'name': 'OAuth2 API', 'version': 'v2', 'v2discovery': False}, OAUTH2: {'name': 'OAuth2 API', 'version': 'v2', 'v2discovery': False},
PEOPLE: {'name': 'People API', 'version': 'v1', 'v2discovery': True}, PEOPLE: {'name': 'People API', 'version': 'v1', 'v2discovery': True},
PEOPLE_DIRECTORY: {'name': 'People Directory API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': PEOPLE}, PEOPLE_DIRECTORY: {'name': 'People Directory API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': PEOPLE},
@ -546,10 +546,6 @@ _SVCACCT_SCOPES = [
# 'api': CONTACTS, # 'api': CONTACTS,
# 'subscopes': [], # 'subscopes': [],
# 'scope': 'https://www.google.com/m8/feeds'}, # 'scope': 'https://www.google.com/m8/feeds'},
{'name': 'Data Studio API',
'api': DATASTUDIO,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/datastudio'},
{'name': 'Drive API', {'name': 'Drive API',
'api': DRIVE3, 'api': DRIVE3,
'subscopes': READONLY, 'subscopes': READONLY,
@ -598,6 +594,10 @@ _SVCACCT_SCOPES = [
'api': KEEP, 'api': KEEP,
'subscopes': READONLY, 'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/keep'}, 'scope': 'https://www.googleapis.com/auth/keep'},
{'name': 'Looker Studio API',
'api': LOOKERSTUDIO,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/datastudio'},
{'name': 'OAuth2 API', {'name': 'OAuth2 API',
'api': OAUTH2, 'api': OAUTH2,
'subscopes': [], 'subscopes': [],

View File

@ -200,6 +200,10 @@ OUTPUT_TIMEFORMAT = 'output_timeformat'
PEOPLE_MAX_RESULTS = 'people_max_results' PEOPLE_MAX_RESULTS = 'people_max_results'
# Domains for print alises|groups|users # Domains for print alises|groups|users
PRINT_AGU_DOMAINS = 'print_agu_domains' PRINT_AGU_DOMAINS = 'print_agu_domains'
# OrgUnits for print cros
PRINT_CROS_OUS = 'print_cros_ous'
# OrgUnits and children for print cros
PRINT_CROS_OUS_AND_CHILDREN = 'print_cros_ous_and_children'
# Number of seconds to wait for batch/csv processes to complete # Number of seconds to wait for batch/csv processes to complete
PROCESS_WAIT_LIMIT = 'process_wait_limit' PROCESS_WAIT_LIMIT = 'process_wait_limit'
# Use quick method to move Chromebooks to OU # Use quick method to move Chromebooks to OU
@ -366,6 +370,8 @@ Defaults = {
OUTPUT_TIMEFORMAT: '', OUTPUT_TIMEFORMAT: '',
PEOPLE_MAX_RESULTS: '100', PEOPLE_MAX_RESULTS: '100',
PRINT_AGU_DOMAINS: '', PRINT_AGU_DOMAINS: '',
PRINT_CROS_OUS: '',
PRINT_CROS_OUS_AND_CHILDREN: '',
PROCESS_WAIT_LIMIT: '0', PROCESS_WAIT_LIMIT: '0',
QUICK_CROS_MOVE: FALSE, QUICK_CROS_MOVE: FALSE,
QUICK_INFO_USER: FALSE, QUICK_INFO_USER: FALSE,
@ -515,6 +521,8 @@ VAR_INFO = {
OUTPUT_TIMEFORMAT: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)}, OUTPUT_TIMEFORMAT: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PEOPLE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 1000)}, PEOPLE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 1000)},
PRINT_AGU_DOMAINS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)}, PRINT_AGU_DOMAINS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PRINT_CROS_OUS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PRINT_CROS_OUS_AND_CHILDREN: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
PROCESS_WAIT_LIMIT: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, None)}, PROCESS_WAIT_LIMIT: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, None)},
QUICK_CROS_MOVE: {VAR_TYPE: TYPE_BOOLEAN}, QUICK_CROS_MOVE: {VAR_TYPE: TYPE_BOOLEAN},
QUICK_INFO_USER: {VAR_TYPE: TYPE_BOOLEAN}, QUICK_INFO_USER: {VAR_TYPE: TYPE_BOOLEAN},

View File

@ -523,6 +523,10 @@ class GamCLArgs():
ARG_DATASTUDIOASSETS = 'datastudioassets' ARG_DATASTUDIOASSETS = 'datastudioassets'
ARG_DATASTUDIOPERMISSION = 'datastudiopermission' ARG_DATASTUDIOPERMISSION = 'datastudiopermission'
ARG_DATASTUDIOPERMISSIONS = 'datastudiopermissions' ARG_DATASTUDIOPERMISSIONS = 'datastudiopermissions'
ARG_LOOKERSTUDIOASSET = 'lookerstudioasset'
ARG_LOOKERSTUDIOASSETS = 'lookerstudioassets'
ARG_LOOKERSTUDIOPERMISSION = 'lookerstudiopermission'
ARG_LOOKERSTUDIOPERMISSIONS = 'lookerstudiopermissions'
ARG_DATATRANSFER = 'datatransfer' ARG_DATATRANSFER = 'datatransfer'
ARG_DATATRANSFERS = 'datatransfers' ARG_DATATRANSFERS = 'datatransfers'
ARG_DELEGATE = 'delegate' ARG_DELEGATE = 'delegate'
@ -834,7 +838,6 @@ class GamCLArgs():
OB_CROS_ENTITY = 'CrOSEntity' OB_CROS_ENTITY = 'CrOSEntity'
OB_CUSTOMER_ID = 'CustomerID' OB_CUSTOMER_ID = 'CustomerID'
OB_CUSTOMER_AUTH_TOKEN = 'CustomerAuthToken' OB_CUSTOMER_AUTH_TOKEN = 'CustomerAuthToken'
OB_DATASTUDIO_ASSET_MEMBERS_ENTITY = 'DataStudioAssetMembersEntity'
OB_DEVICE_FILE_ENTITY = 'DeviceFileEntity' OB_DEVICE_FILE_ENTITY = 'DeviceFileEntity'
OB_DEVICE_ENTITY = 'DeviceEntity' OB_DEVICE_ENTITY = 'DeviceEntity'
OB_DEVICE_ID = 'DeviceID' OB_DEVICE_ID = 'DeviceID'
@ -903,6 +906,7 @@ class GamCLArgs():
OB_LABEL_NAME_LIST = 'LabelNameList' OB_LABEL_NAME_LIST = 'LabelNameList'
OB_LABEL_REPLACEMENT = 'LabelReplacement' OB_LABEL_REPLACEMENT = 'LabelReplacement'
OB_LANGUAGE_LIST = 'LanguageList' OB_LANGUAGE_LIST = 'LanguageList'
OB_LOOKERSTUDIO_PERMISSION_ENTITY = 'LookerStudioPermissionEntity'
OB_MATTER_ITEM = 'MatterItem' OB_MATTER_ITEM = 'MatterItem'
OB_MATTER_ITEM_LIST = 'MatterItemList' OB_MATTER_ITEM_LIST = 'MatterItemList'
OB_MESSAGE_ID = 'MessageID' OB_MESSAGE_ID = 'MessageID'

View File

@ -149,11 +149,6 @@ class GamEntity():
CROS_SERIAL_NUMBER = 'crsn' CROS_SERIAL_NUMBER = 'crsn'
CUSTOMER_DOMAIN = 'cudo' CUSTOMER_DOMAIN = 'cudo'
CUSTOMER_ID = 'cuid' CUSTOMER_ID = 'cuid'
DATASTUDIO_ASSET = 'dsas'
DATASTUDIO_ASSET_DATASOURCE = 'dsad'
DATASTUDIO_ASSETID = 'dsai'
DATASTUDIO_ASSET_REPORT = 'dsar'
DATASTUDIO_PERMISSION = 'dspe'
DATE = 'date' DATE = 'date'
DEFAULT_LANGUAGE = 'dfla' DEFAULT_LANGUAGE = 'dfla'
DELEGATE = 'dele' DELEGATE = 'dele'
@ -241,6 +236,11 @@ class GamEntity():
LANGUAGE = 'lang' LANGUAGE = 'lang'
LICENSE = 'lice' LICENSE = 'lice'
LOCATION = 'loca' LOCATION = 'loca'
LOOKERSTUDIO_ASSET = 'lsas'
LOOKERSTUDIO_ASSET_DATASOURCE = 'lsad'
LOOKERSTUDIO_ASSETID = 'lsai'
LOOKERSTUDIO_ASSET_REPORT = 'lsar'
LOOKERSTUDIO_PERMISSION = 'lspe'
MD5HASH = 'md5h' MD5HASH = 'md5h'
MEMBER = 'memb' MEMBER = 'memb'
MEMBER_NOT_ARCHIVED = 'mena' MEMBER_NOT_ARCHIVED = 'mena'
@ -475,11 +475,6 @@ class GamEntity():
CROS_SERIAL_NUMBER: ['CrOS Serial Numbers', 'CrOS Serial Numbers'], CROS_SERIAL_NUMBER: ['CrOS Serial Numbers', 'CrOS Serial Numbers'],
CUSTOMER_DOMAIN: ['Customer Domains', 'Customer Domain'], CUSTOMER_DOMAIN: ['Customer Domains', 'Customer Domain'],
CUSTOMER_ID: ['Customer IDs', 'Customer ID'], CUSTOMER_ID: ['Customer IDs', 'Customer ID'],
DATASTUDIO_ASSET: ['Data Studio Assets', 'Data Studio Asset'],
DATASTUDIO_ASSET_DATASOURCE: ['Data Studio DATA_SOURCE Assets', 'Data Studio DATA_SOURCE Asset'],
DATASTUDIO_ASSETID: ['Data Studio Asset IDs', 'Data Studio Asset ID'],
DATASTUDIO_ASSET_REPORT: ['Data Studio REPORT Assets', 'Data Studio REPORT Asset'],
DATASTUDIO_PERMISSION: ['Data Studio Permissions', 'Data Studio Permission'],
DATE: ['Dates', 'Date'], DATE: ['Dates', 'Date'],
DEFAULT_LANGUAGE: ['Default Language', 'Default Language'], DEFAULT_LANGUAGE: ['Default Language', 'Default Language'],
DELEGATE: ['Delegates', 'Delegate'], DELEGATE: ['Delegates', 'Delegate'],
@ -567,6 +562,11 @@ class GamEntity():
LANGUAGE: ['Languages', 'Language'], LANGUAGE: ['Languages', 'Language'],
LICENSE: ['Licenses', 'License'], LICENSE: ['Licenses', 'License'],
LOCATION: ['Locations', 'Location'], LOCATION: ['Locations', 'Location'],
LOOKERSTUDIO_ASSET: ['Looker Studio Assets', 'Looker Studio Asset'],
LOOKERSTUDIO_ASSET_DATASOURCE: ['Looker Studio DATA_SOURCE Assets', 'Looker Studio DATA_SOURCE Asset'],
LOOKERSTUDIO_ASSETID: ['Looker Studio Asset IDs', 'Looker Studio Asset ID'],
LOOKERSTUDIO_ASSET_REPORT: ['Looker Studio REPORT Assets', 'Looker Studio REPORT Asset'],
LOOKERSTUDIO_PERMISSION: ['Looker Studio Permissions', 'Looker Studio Permission'],
MD5HASH: ['MD5 hash', 'MD5 Hash'], MD5HASH: ['MD5 hash', 'MD5 Hash'],
MEMBER: ['Members', 'Member'], MEMBER: ['Members', 'Member'],
MEMBER_NOT_ARCHIVED: ['Members (Not Archived)', 'Member (Not Archived)'], MEMBER_NOT_ARCHIVED: ['Members (Not Archived)', 'Member (Not Archived)'],

View File

@ -193,7 +193,6 @@ CISSO_UPDATE_THROW_REASONS = [SERVICE_NOT_AVAILABLE, NOT_FOUND, FAILED_PRECONDIT
SYSTEM_ERROR, PERMISSION_DENIED, INTERNAL_ERROR] SYSTEM_ERROR, PERMISSION_DENIED, INTERNAL_ERROR]
CONTACT_DELEGATE_THROW_REASONS = [SERVICE_NOT_AVAILABLE, BAD_REQUEST, FAILED_PRECONDITION, PERMISSION_DENIED, FORBIDDEN, INVALID_ARGUMENT] CONTACT_DELEGATE_THROW_REASONS = [SERVICE_NOT_AVAILABLE, BAD_REQUEST, FAILED_PRECONDITION, PERMISSION_DENIED, FORBIDDEN, INVALID_ARGUMENT]
COURSE_ACCESS_THROW_REASONS = [NOT_FOUND, INSUFFICIENT_PERMISSIONS, PERMISSION_DENIED, FORBIDDEN, INVALID_ARGUMENT] COURSE_ACCESS_THROW_REASONS = [NOT_FOUND, INSUFFICIENT_PERMISSIONS, PERMISSION_DENIED, FORBIDDEN, INVALID_ARGUMENT]
DATASTUDIO_THROW_REASONS = [INVALID_ARGUMENT, SERVICE_NOT_AVAILABLE, BAD_REQUEST, NOT_FOUND, PERMISSION_DENIED]
DRIVE_USER_THROW_REASONS = [SERVICE_NOT_AVAILABLE, AUTH_ERROR, DOMAIN_POLICY] DRIVE_USER_THROW_REASONS = [SERVICE_NOT_AVAILABLE, AUTH_ERROR, DOMAIN_POLICY]
DRIVE_ACCESS_THROW_REASONS = DRIVE_USER_THROW_REASONS+[FILE_NOT_FOUND, FORBIDDEN, INTERNAL_ERROR, INSUFFICIENT_FILE_PERMISSIONS, UNKNOWN_ERROR, INVALID] DRIVE_ACCESS_THROW_REASONS = DRIVE_USER_THROW_REASONS+[FILE_NOT_FOUND, FORBIDDEN, INTERNAL_ERROR, INSUFFICIENT_FILE_PERMISSIONS, UNKNOWN_ERROR, INVALID]
DRIVE_COPY_THROW_REASONS = DRIVE_ACCESS_THROW_REASONS+[CANNOT_COPY_FILE, BAD_REQUEST, RESPONSE_PREPARATION_FAILURE, TEAMDRIVES_SHARING_RESTRICTION_NOT_ALLOWED, DRIVE_COPY_THROW_REASONS = DRIVE_ACCESS_THROW_REASONS+[CANNOT_COPY_FILE, BAD_REQUEST, RESPONSE_PREPARATION_FAILURE, TEAMDRIVES_SHARING_RESTRICTION_NOT_ALLOWED,
@ -253,7 +252,8 @@ GROUP_SETTINGS_RETRY_REASONS = [INVALID, SERVICE_LIMIT, SERVICE_NOT_AVAILABLE]
GROUP_LIST_THROW_REASONS = [RESOURCE_NOT_FOUND, DOMAIN_NOT_FOUND, FORBIDDEN, BAD_REQUEST] GROUP_LIST_THROW_REASONS = [RESOURCE_NOT_FOUND, DOMAIN_NOT_FOUND, FORBIDDEN, BAD_REQUEST]
GROUP_LIST_USERKEY_THROW_REASONS = GROUP_LIST_THROW_REASONS+[INVALID_MEMBER, INVALID_INPUT] GROUP_LIST_USERKEY_THROW_REASONS = GROUP_LIST_THROW_REASONS+[INVALID_MEMBER, INVALID_INPUT]
KEEP_THROW_REASONS = [SERVICE_NOT_AVAILABLE, BAD_REQUEST, PERMISSION_DENIED, INVALID_ARGUMENT, NOT_FOUND] KEEP_THROW_REASONS = [SERVICE_NOT_AVAILABLE, BAD_REQUEST, PERMISSION_DENIED, INVALID_ARGUMENT, NOT_FOUND]
MEMBERS_THROW_REASONS = [GROUP_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, INVALID, FORBIDDEN] LOOKERSTUDIO_THROW_REASONS = [INVALID_ARGUMENT, SERVICE_NOT_AVAILABLE, BAD_REQUEST, NOT_FOUND, PERMISSION_DENIED]
MEMBERS_THROW_REASONS = [GROUP_NOT_FOUND, DOMAIN_NOT_FOUND, DOMAIN_CANNOT_USE_APIS, INVALID, FORBIDDEN, SERVICE_NOT_AVAILABLE]
MEMBERS_RETRY_REASONS = [SYSTEM_ERROR, SERVICE_NOT_AVAILABLE] MEMBERS_RETRY_REASONS = [SYSTEM_ERROR, SERVICE_NOT_AVAILABLE]
ORGUNIT_GET_THROW_REASONS = [INVALID_ORGUNIT, ORGUNIT_NOT_FOUND, BACKEND_ERROR, BAD_REQUEST, INVALID_CUSTOMER_ID, LOGIN_REQUIRED] ORGUNIT_GET_THROW_REASONS = [INVALID_ORGUNIT, ORGUNIT_NOT_FOUND, BACKEND_ERROR, BAD_REQUEST, INVALID_CUSTOMER_ID, LOGIN_REQUIRED]
PEOPLE_ACCESS_THROW_REASONS = [SERVICE_NOT_AVAILABLE, FORBIDDEN, PERMISSION_DENIED] PEOPLE_ACCESS_THROW_REASONS = [SERVICE_NOT_AVAILABLE, FORBIDDEN, PERMISSION_DENIED]

View File

@ -158,6 +158,10 @@ PARSER = 'pars'
PID = 'pid ' PID = 'pid '
# Domains for print alises|groups|users # Domains for print alises|groups|users
PRINT_AGU_DOMAINS = 'pagu' PRINT_AGU_DOMAINS = 'pagu'
# OrgUnits for print cros
PRINT_CROS_OUS = 'pcou'
# OrgUnits and children for print cros
PRINT_CROS_OUS_AND_CHILDREN = 'pcoc'
# Check API calls rate # Check API calls rate
RATE_CHECK_COUNT = 'rccn' RATE_CHECK_COUNT = 'rccn'
RATE_CHECK_START = 'rcst' RATE_CHECK_START = 'rcst'
@ -272,6 +276,8 @@ Globals = {
PARSER: None, PARSER: None,
PID: 0, PID: 0,
PRINT_AGU_DOMAINS: '', PRINT_AGU_DOMAINS: '',
PRINT_CROS_OUS: '',
PRINT_CROS_OUS_AND_CHILDREN: '',
RATE_CHECK_COUNT: 0, RATE_CHECK_COUNT: 0,
RATE_CHECK_START: 0, RATE_CHECK_START: 0,
SECTION: None, SECTION: None,