Handle ERROR: 412: conditionNotMet - User creation is not complete.

This commit is contained in:
Ross Scroggs
2024-09-30 15:54:36 -07:00
parent 896f7f5d37
commit 7c88793e8f
8 changed files with 10175 additions and 59 deletions

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 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 ### 7.00.09
Added initial support for `Folders with limited access`; you must be enrolled in the Beta preview. 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$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version 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 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> GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.6 64-bit final Python 3.12.6 64-bit final
MacOS Sonoma 14.5 x86_64 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:\>del C:\GAMConfig\oauth2.txt
C:\>gam version C:\>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
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> GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.6 64-bit final Python 3.12.6 64-bit final
Windows-10-10.0.17134 AMD64 Windows-10-10.0.17134 AMD64

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
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> GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.5 64-bit final Python 3.12.5 64-bit final
MacOS Sonoma 14.5 x86_64 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 Print the current version of Gam with details and time offset information
``` ```
gam version timeoffset 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> GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.5 64-bit final Python 3.12.5 64-bit final
MacOS Sonoma 14.5 x86_64 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 Print the current version of Gam with extended details and SSL information
``` ```
gam version extended 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> GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.5 64-bit final Python 3.12.5 64-bit final
MacOS Sonoma 14.5 x86_64 MacOS Sonoma 14.5 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: 7.00.09 Latest: 7.00.10
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
7.00.09 7.00.10
``` ```
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 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> GAM Team <google-apps-manager@googlegroups.com>
Python 3.12.5 64-bit final Python 3.12.5 64-bit final
MacOS Sonoma 14.5 x86_64 MacOS Sonoma 14.5 x86_64

5045
src/drive-v3beta.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
""" """
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>' __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)' __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position #pylint: disable=wrong-import-position
@ -4669,10 +4669,10 @@ def getAPIService(api, httpObj):
discoveryServiceUrl=DISCOVERY_URIS[v2discovery], static_discovery=False) discoveryServiceUrl=DISCOVERY_URIS[v2discovery], static_discovery=False)
def getService(api, httpObj): def getService(api, httpObj):
hasLocalJSON = API.hasLocalJSON(api)
### Drive v3beta ### Drive v3beta
if api == API.DRIVE3 and GC.Values[GC.DRIVE_V3_BETA]: if api == API.DRIVE3 and GC.Values[GC.DRIVE_V3_BETA]:
api = API.DRIVE3B api = API.DRIVE3B
hasLocalJSON = API.hasLocalJSON(api)
api, version, v2discovery = API.getVersion(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]: 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) 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): def waitForCompletion(i):
sleep_time = i*5 sleep_time = i*5
if i > 3: 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) time.sleep(sleep_time)
local_key_size = 2048 local_key_size = 2048
@ -43152,8 +43152,14 @@ def verifyUserPrimaryEmail(cd, user, createIfNotFound, i, count):
# [notifyonupdate [<Boolean>]] # [notifyonupdate [<Boolean>]]
# [lograndompassword <FileName>] [ignorenullpassword] # [lograndompassword <FileName>] [ignorenullpassword]
def updateUsers(entityList): 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) cd = buildGAPIObject(API.DIRECTORY)
ci = None ci = None
errorRetries = 5
updateRetryDelay = 5
body, notify, tagReplacements, addGroups, addAliases, PwdOpts, \ body, notify, tagReplacements, addGroups, addAliases, PwdOpts, \
updatePrimaryEmail, notFoundBody, groupOrgUnitMap, \ updatePrimaryEmail, notFoundBody, groupOrgUnitMap, \
parameters, resolveConflictAccount = getUserAttributes(cd, parameters, resolveConflictAccount = getUserAttributes(cd,
@ -43228,9 +43234,12 @@ def updateUsers(entityList):
continue continue
if PwdOpts.makeUniqueRandomPassword: if PwdOpts.makeUniqueRandomPassword:
PwdOpts.AssignPassword(body, notify, notFoundBody, parameters['createIfNotFound']) PwdOpts.AssignPassword(body, notify, notFoundBody, parameters['createIfNotFound'])
retry = 0
while True:
try: try:
result = callGAPI(cd.users(), 'update', result = callGAPI(cd.users(), 'update',
throwReasons=[GAPI.USER_NOT_FOUND, GAPI.DOMAIN_NOT_FOUND, GAPI.FORBIDDEN, GAPI.BAD_REQUEST, 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, GAPI.INVALID_INPUT, GAPI.INVALID_PARAMETER,
GAPI.INVALID_ORGUNIT, GAPI.INVALID_SCHEMA_VALUE, GAPI.DUPLICATE, GAPI.INVALID_ORGUNIT, GAPI.INVALID_SCHEMA_VALUE, GAPI.DUPLICATE,
GAPI.INSUFFICIENT_ARCHIVED_USER_LICENSES, GAPI.CONFLICT], GAPI.INSUFFICIENT_ARCHIVED_USER_LICENSES, GAPI.CONFLICT],
@ -43240,6 +43249,14 @@ def updateUsers(entityList):
writeFile(PwdOpts.filename, f'{userKey},{PwdOpts.password}\n', mode='a', continueOnError=True) writeFile(PwdOpts.filename, f'{userKey},{PwdOpts.password}\n', mode='a', continueOnError=True)
if parameters['notifyOnUpdate'] and notify.get('recipients') and notify['password']: if parameters['notifyOnUpdate'] and notify.get('recipients') and notify['password']:
sendCreateUpdateUserNotification(result, notify, tagReplacements, i, count, createMessage=False) 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: except GAPI.userNotFound:
if parameters['createIfNotFound']: 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 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']):
@ -43273,6 +43290,7 @@ def updateUsers(entityList):
entityActionFailedWarning([Ent.USER, user], Msg.UNABLE_TO_CREATE_NOT_FOUND_USER, i, count) entityActionFailedWarning([Ent.USER, user], Msg.UNABLE_TO_CREATE_NOT_FOUND_USER, i, count)
else: else:
entityUnknownWarning(Ent.USER, user, i, count) entityUnknownWarning(Ent.USER, user, i, count)
break
else: else:
entityActionNotPerformedWarning([Ent.USER, user], Msg.NO_CHANGES, i, count) entityActionNotPerformedWarning([Ent.USER, user], Msg.NO_CHANGES, i, count)
except GAPI.userNotFound: except GAPI.userNotFound:
@ -64236,7 +64254,7 @@ def _moveSharedDriveToOU(orgUnit, orgUnitId, driveId, user, i, count, ci, return
# [(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly] # [(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
def createSharedDrive(users, useDomainAdminAccess=False): def createSharedDrive(users, useDomainAdminAccess=False):
def waitingForCreationToComplete(sleep_time): 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.SHARED_DRIVE), sleep_time))
time.sleep(sleep_time) time.sleep(sleep_time)
requestId = str(uuid.uuid4()) 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}, DOCS: {'name': 'Docs API', 'version': 'v1', 'v2discovery': True},
DRIVE2: {'name': 'Drive API v2', 'version': 'v2', 'v2discovery': False, 'mappedAPI': 'drive'}, DRIVE2: {'name': 'Drive API v2', 'version': 'v2', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVE3: {'name': 'Drive API v3', 'version': 'v3', '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'}, DRIVETD: {'name': 'Drive API v3 - todrive', 'version': 'v3', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVEACTIVITY: {'name': 'Drive Activity API v2', 'version': 'v2', 'v2discovery': True}, DRIVEACTIVITY: {'name': 'Drive Activity API v2', 'version': 'v2', 'v2discovery': True},
DRIVELABELS_ADMIN: {'name': 'Drive Labels API v2beta - Admin', 'version': 'v2beta', 'v2discovery': True, 'mappedAPI': DRIVELABELS}, 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' VALUES_ARE_NOT_CONSISTENT = 'Values are not consistent'
VERSION_UPDATE_AVAILABLE = 'Version update available' 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_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_ITEM_CREATION_TO_COMPLETE_SLEEPING = 'Waiting for {0} creation to complete. Sleeping {1} seconds\n'
WAITING_FOR_SHARED_DRIVE_CREATION_TO_COMPLETE_SLEEPING = 'Waiting for Shared Drive creation to complete. Sleeping {0} seconds\n'
WHAT_IS_YOUR_PROJECT_ID = '\nWhat is your project ID? ' 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' WILL_RERUN_WITH_NO_BROWSER_TRUE = 'Will re-run command with no_browser true\n'
WITH = 'with' WITH = 'with'