Compare commits

...

4 Commits

Author SHA1 Message Date
Ross Scroggs
2b6891c12d Handle ERROR: 412: conditionNotMet - User creation is not complete.
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-30 19:44:10 -07:00
Ross Scroggs
70fb68d81b Handle ERROR: 412: conditionNotMet - User creation is not complete.
Some checks are pending
Build and test GAM / build (Win64, build, 9, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 8, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
2024-09-30 16:28:56 -07:00
Ross Scroggs
6b15628d81 Handle ERROR: 412: conditionNotMet - User creation is not complete. 2024-09-30 16:00:15 -07:00
Ross Scroggs
7c88793e8f Handle ERROR: 412: conditionNotMet - User creation is not complete. 2024-09-30 15:54:36 -07:00
12 changed files with 10190 additions and 64 deletions

View File

@@ -115,7 +115,7 @@ jobs:
with:
path: |
cache.tar.xz
key: gam-${{ matrix.jid }}-20240918
key: gam-${{ matrix.jid }}-20240930
- name: Untar Cache archive
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'

View File

@@ -38,11 +38,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -53,7 +53,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -67,4 +67,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3

View File

@@ -10,6 +10,15 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads-Installs-GAM7](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads-Installs) for Windows or other options, including manual installation
### 7.00.10
Handled the following error that occurs when `gam create user` is immediateley followed by `gam update user`.
```
ERROR: 412: conditionNotMet - User creation is not complete.
```
Updated support for `Folders with limited access`; this is a work in progress.
### 7.00.09
Added initial support for `Folders with limited access`; you must be enrolled in the Beta preview.

View File

@@ -251,7 +251,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.00.09 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.10 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.6 64-bit final
MacOS Sonoma 14.5 x86_64
@@ -923,7 +923,7 @@ writes the credentials into the file oauth2.txt.
C:\>del C:\GAMConfig\oauth2.txt
C:\>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAM7 7.00.09 - https://github.com/taers232c/GAM7 - pythonsource
GAM7 7.00.10 - https://github.com/taers232c/GAM7 - pythonsource
GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.6 64-bit final
Windows-10-10.0.17134 AMD64

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details
```
gam version
GAM 7.00.09 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.10 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.5 64-bit final
MacOS Sonoma 14.5 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
```
gam version timeoffset
GAM 7.00.09 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.10 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.5 64-bit final
MacOS Sonoma 14.5 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
```
gam version extended
GAM 7.00.09 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.10 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.5 64-bit final
MacOS Sonoma 14.5 x86_64
@@ -64,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Version Check:
Current: 5.35.08
Latest: 7.00.09
Latest: 7.00.10
echo $?
1
```
@@ -72,7 +72,7 @@ echo $?
Print the current version number without details
```
gam version simple
7.00.09
7.00.10
```
In Linux/MacOS you can do:
```
@@ -82,7 +82,7 @@ echo $VER
Print the current version of Gam and address of this Wiki
```
gam help
GAM 7.00.09 - https://github.com/taers232c/GAMADV-XTD3
GAM 7.00.10 - https://github.com/taers232c/GAMADV-XTD3
GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.5 64-bit final
MacOS Sonoma 14.5 x86_64

View File

@@ -1,3 +1,12 @@
7.00.10
Handled the following error that occurs when `gam create user` is immediateley followed by `gam update user`.
```
ERROR: 412: conditionNotMet - User creation is not complete.
```
Updated support for `Folders with limited access`; this is a work in progress.
7.00.09
Added initial support for `Folders with limited access`; you must be enrolled in the Beta preview.

5045
src/drive-v3beta.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,7 @@ datas += [('admin-directory_v1.1beta1.json', '.')]
datas += [('cbcm-v1.1beta1.json', '.')]
datas += [('contactdelegation-v1.json', '.')]
datas += [('datastudio-v1.json', '.')]
datas += [('drive-v3beta.json', '.')]
datas += [('serviceaccountlookup-v1.json', '.')]
datas += [('cacerts.pem', '.')]
hiddenimports = [

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
"""
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.00.09'
__version__ = '7.00.10'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position
@@ -4669,10 +4669,10 @@ def getAPIService(api, httpObj):
discoveryServiceUrl=DISCOVERY_URIS[v2discovery], static_discovery=False)
def getService(api, httpObj):
hasLocalJSON = API.hasLocalJSON(api)
### Drive v3beta
if api == API.DRIVE3 and GC.Values[GC.DRIVE_V3_BETA]:
api = API.DRIVE3B
hasLocalJSON = API.hasLocalJSON(api)
api, version, v2discovery = API.getVersion(api)
if api in GM.Globals[GM.CURRENT_API_SERVICES] and version in GM.Globals[GM.CURRENT_API_SERVICES][api]:
service = googleapiclient.discovery.build_from_document(GM.Globals[GM.CURRENT_API_SERVICES][api][version], http=httpObj)
@@ -12445,7 +12445,7 @@ def doProcessSvcAcctKeys(mode=None, iam=None, projectId=None, clientEmail=None,
def waitForCompletion(i):
sleep_time = i*5
if i > 3:
sys.stdout.write(Msg.WAITING_FOR_SERVICE_ACCOUNT_CREATION_TO_COMPLETE_SLEEPING.format(sleep_time))
sys.stdout.write(Msg.WAITING_FOR_ITEM_CREATION_TO_COMPLETE_SLEEPING.format(Ent.Singular(Ent.SVCACCT), sleep_time))
time.sleep(sleep_time)
local_key_size = 2048
@@ -43152,8 +43152,14 @@ def verifyUserPrimaryEmail(cd, user, createIfNotFound, i, count):
# [notifyonupdate [<Boolean>]]
# [lograndompassword <FileName>] [ignorenullpassword]
def updateUsers(entityList):
def waitingForCreationToComplete(sleep_time):
writeStderr(Ind.Spaces()+Msg.WAITING_FOR_ITEM_CREATION_TO_COMPLETE_SLEEPING.format(Ent.Singular(Ent.USER), sleep_time))
time.sleep(sleep_time)
cd = buildGAPIObject(API.DIRECTORY)
ci = None
errorRetries = 5
updateRetryDelay = 5
body, notify, tagReplacements, addGroups, addAliases, PwdOpts, \
updatePrimaryEmail, notFoundBody, groupOrgUnitMap, \
parameters, resolveConflictAccount = getUserAttributes(cd,
@@ -43228,51 +43234,63 @@ def updateUsers(entityList):
continue
if PwdOpts.makeUniqueRandomPassword:
PwdOpts.AssignPassword(body, notify, notFoundBody, parameters['createIfNotFound'])
try:
result = callGAPI(cd.users(), 'update',
throwReasons=[GAPI.USER_NOT_FOUND, GAPI.DOMAIN_NOT_FOUND, GAPI.FORBIDDEN, GAPI.BAD_REQUEST,
GAPI.INVALID, GAPI.INVALID_INPUT, GAPI.INVALID_PARAMETER,
GAPI.INVALID_ORGUNIT, GAPI.INVALID_SCHEMA_VALUE, GAPI.DUPLICATE,
GAPI.INSUFFICIENT_ARCHIVED_USER_LICENSES, GAPI.CONFLICT],
userKey=userKey, body=body, fields=fields)
entityActionPerformed([Ent.USER, user], i, count)
if PwdOpts.filename and PwdOpts.password:
writeFile(PwdOpts.filename, f'{userKey},{PwdOpts.password}\n', mode='a', continueOnError=True)
if parameters['notifyOnUpdate'] and notify.get('recipients') and notify['password']:
sendCreateUpdateUserNotification(result, notify, tagReplacements, i, count, createMessage=False)
except GAPI.userNotFound:
if parameters['createIfNotFound']:
if notFoundBody and (count == 1) and not vfe and ('password' in notFoundBody) and ('name' in body) and ('givenName' in body['name']) and ('familyName' in body['name']):
if 'primaryEmail' not in body:
body['primaryEmail'] = user
body.update(notFoundBody)
if parameters['setChangePasswordOnCreate']:
body['changePasswordAtNextLogin'] = True
Act.Set(Act.CREATE)
try:
result = callGAPI(cd.users(), 'insert',
throwReasons=[GAPI.DUPLICATE, GAPI.DOMAIN_NOT_FOUND, GAPI.FORBIDDEN,
GAPI.INVALID, GAPI.INVALID_INPUT, GAPI.INVALID_PARAMETER,
GAPI.INVALID_ORGUNIT, GAPI.INVALID_SCHEMA_VALUE, GAPI.CONDITION_NOT_MET],
body=body,
fields=fields,
resolveConflictAccount=resolveConflictAccount)
entityActionPerformed([Ent.USER, body['primaryEmail']], i, count)
if PwdOpts.filename and PwdOpts.notFoundPassword:
writeFile(PwdOpts.filename, f'{user},{PwdOpts.notFoundPassword}\n', mode='a', continueOnError=True)
if addGroups:
createUserAddToGroups(cd, result['primaryEmail'], addGroups, i, count)
if addAliases:
createUserAddAliases(cd, result['primaryEmail'], addAliases, i, count)
if notify.get('recipients'):
notify['password'] = notify['notFoundPassword']
sendCreateUpdateUserNotification(result, notify, tagReplacements, i, count)
except GAPI.duplicate:
duplicateAliasGroupUserWarning(cd, [Ent.USER, body['primaryEmail']], i, count)
retry = 0
while True:
try:
result = callGAPI(cd.users(), 'update',
throwReasons=[GAPI.CONDITION_NOT_MET, GAPI.USER_NOT_FOUND, GAPI.DOMAIN_NOT_FOUND,
GAPI.FORBIDDEN, GAPI.BAD_REQUEST,
GAPI.INVALID, GAPI.INVALID_INPUT, GAPI.INVALID_PARAMETER,
GAPI.INVALID_ORGUNIT, GAPI.INVALID_SCHEMA_VALUE, GAPI.DUPLICATE,
GAPI.INSUFFICIENT_ARCHIVED_USER_LICENSES, GAPI.CONFLICT],
userKey=userKey, body=body, fields=fields)
entityActionPerformed([Ent.USER, user], i, count)
if PwdOpts.filename and PwdOpts.password:
writeFile(PwdOpts.filename, f'{userKey},{PwdOpts.password}\n', mode='a', continueOnError=True)
if parameters['notifyOnUpdate'] and notify.get('recipients') and notify['password']:
sendCreateUpdateUserNotification(result, notify, tagReplacements, i, count, createMessage=False)
break
except GAPI.conditionNotMet as e:
retry += 1
if ('User creation is not complete' not in str(e)) or retry > errorRetries:
entityActionFailedWarning([Ent.USER, user], str(e), i, count)
break
waitingForCreationToComplete(updateRetryDelay)
continue
except GAPI.userNotFound:
if parameters['createIfNotFound']:
if notFoundBody and (count == 1) and not vfe and ('password' in notFoundBody) and ('name' in body) and ('givenName' in body['name']) and ('familyName' in body['name']):
if 'primaryEmail' not in body:
body['primaryEmail'] = user
body.update(notFoundBody)
if parameters['setChangePasswordOnCreate']:
body['changePasswordAtNextLogin'] = True
Act.Set(Act.CREATE)
try:
result = callGAPI(cd.users(), 'insert',
throwReasons=[GAPI.DUPLICATE, GAPI.DOMAIN_NOT_FOUND, GAPI.FORBIDDEN,
GAPI.INVALID, GAPI.INVALID_INPUT, GAPI.INVALID_PARAMETER,
GAPI.INVALID_ORGUNIT, GAPI.INVALID_SCHEMA_VALUE, GAPI.CONDITION_NOT_MET],
body=body,
fields=fields,
resolveConflictAccount=resolveConflictAccount)
entityActionPerformed([Ent.USER, body['primaryEmail']], i, count)
if PwdOpts.filename and PwdOpts.notFoundPassword:
writeFile(PwdOpts.filename, f'{user},{PwdOpts.notFoundPassword}\n', mode='a', continueOnError=True)
if addGroups:
createUserAddToGroups(cd, result['primaryEmail'], addGroups, i, count)
if addAliases:
createUserAddAliases(cd, result['primaryEmail'], addAliases, i, count)
if notify.get('recipients'):
notify['password'] = notify['notFoundPassword']
sendCreateUpdateUserNotification(result, notify, tagReplacements, i, count)
except GAPI.duplicate:
duplicateAliasGroupUserWarning(cd, [Ent.USER, body['primaryEmail']], i, count)
else:
entityActionFailedWarning([Ent.USER, user], Msg.UNABLE_TO_CREATE_NOT_FOUND_USER, i, count)
else:
entityActionFailedWarning([Ent.USER, user], Msg.UNABLE_TO_CREATE_NOT_FOUND_USER, i, count)
else:
entityUnknownWarning(Ent.USER, user, i, count)
entityUnknownWarning(Ent.USER, user, i, count)
break
else:
entityActionNotPerformedWarning([Ent.USER, user], Msg.NO_CHANGES, i, count)
except GAPI.userNotFound:
@@ -64236,7 +64254,7 @@ def _moveSharedDriveToOU(orgUnit, orgUnitId, driveId, user, i, count, ci, return
# [(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
def createSharedDrive(users, useDomainAdminAccess=False):
def waitingForCreationToComplete(sleep_time):
writeStderr(Ind.Spaces()+Msg.WAITING_FOR_SHARED_DRIVE_CREATION_TO_COMPLETE_SLEEPING.format(sleep_time))
writeStderr(Ind.Spaces()+Msg.WAITING_FOR_ITEM_CREATION_TO_COMPLETE_SLEEPING.format(Ent.Singular(Ent.SHAREDDRIVE), sleep_time))
time.sleep(sleep_time)
requestId = str(uuid.uuid4())

5045
src/gam/drive-v3beta.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -238,7 +238,7 @@ _INFO = {
DOCS: {'name': 'Docs API', 'version': 'v1', 'v2discovery': True},
DRIVE2: {'name': 'Drive API v2', 'version': 'v2', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVE3: {'name': 'Drive API v3', 'version': 'v3', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVE3B: {'name': 'Drive API v3beta', 'version': 'v3beta', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVE3B: {'name': 'Drive API v3beta', 'version': 'v3beta', 'v2discovery': False, 'mappedAPI': 'drive', 'localjson': True},
DRIVETD: {'name': 'Drive API v3 - todrive', 'version': 'v3', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVEACTIVITY: {'name': 'Drive Activity API v2', 'version': 'v2', 'v2discovery': True},
DRIVELABELS_ADMIN: {'name': 'Drive Labels API v2beta - Admin', 'version': 'v2beta', 'v2discovery': True, 'mappedAPI': DRIVELABELS},

View File

@@ -510,8 +510,7 @@ USING_N_PROCESSES = '{0},0/{1},Using {2} {3}...\n'
VALUES_ARE_NOT_CONSISTENT = 'Values are not consistent'
VERSION_UPDATE_AVAILABLE = 'Version update available'
WAITING_FOR_DATA_TRANSFER_TO_COMPLETE_SLEEPING = 'Waiting for Data Transfer to complete. Sleeping {0} seconds\n'
WAITING_FOR_SERVICE_ACCOUNT_CREATION_TO_COMPLETE_SLEEPING = 'Waiting for Service Account creation to complete. Sleeping {0} seconds\n'
WAITING_FOR_SHARED_DRIVE_CREATION_TO_COMPLETE_SLEEPING = 'Waiting for Shared Drive creation to complete. Sleeping {0} seconds\n'
WAITING_FOR_ITEM_CREATION_TO_COMPLETE_SLEEPING = 'Waiting for {0} creation to complete. Sleeping {1} seconds\n'
WHAT_IS_YOUR_PROJECT_ID = '\nWhat is your project ID? '
WILL_RERUN_WITH_NO_BROWSER_TRUE = 'Will re-run command with no_browser true\n'
WITH = 'with'