[cognitiveservices] Unblock managed compute creation - fix misleading 202 / AuthorizationFailed errors #48096
Open
swarupecenits wants to merge 5 commits into
Open
Conversation
…lerate read-after-write 404 Override begin_create_or_update (sync + async) to accept the service's HTTP 202 and track the LRO by polling the compute resource (BodyContentPolling) instead of the computeOperations status endpoint that needs computeOperations/read many callers lack. Tolerates the ~15-20s read-after-write 404 window, blocks until terminal, and surfaces the compute's own provisioning error. Adds 14 unit tests; bumps to 15.0.0b4.
|
Azure Pipelines: Successfully started running 1 pipeline(s). 9 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
…, no computeOperations) Poll provisioningState from the list API instead of a resource GET: a GET on a just-created compute returns 404 'Cluster not found' for an extended period while it provisions, whereas list reflects state from the moment the create is accepted. Keeps the 202 accept, blocks until terminal via a custom _ComputeListPolling, surfaces the compute's real error on failure, and preserves the public overloads, api-version validation and continuation_token resume path. Updates 22 unit tests and the CHANGELOG.
|
Azure Pipelines: Successfully started running 1 pipeline(s). 9 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
…tched ComputesOperations
…idate continuation_token - Apply caller-supplied cls to the final resource in the list-based poller. - Preserve terminal Canceled status instead of collapsing it to Failed. - Encode/decode continuation_token so resume uses the token as source of truth and raises on a malformed token. - Add sync+async tests for all three (30 tests total).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes the misleading errors users hit when creating a Cognitive Services managed compute via
ComputesOperations.begin_create_or_update(surfaced throughaz cognitiveservices account compute create).The generated SDK failed asynchronous compute creation in two ways:
202 Accepted. The service returns HTTP202for the async create, but thegenerated
_create_or_update_initialonly accepts200/201, so it raisedOperation returned an invalid status 'Accepted'.Azure-AsyncOperationheaderto
.../locations/{location}/computeOperations/{operationId}, which requiresMicrosoft.CognitiveServices/locations/computeOperations/read. Callers allowed to create a computebut not granted that read permission saw a misleading
AuthorizationFailedeven though the createsucceeded.
What this change does
Overrides
ComputesOperations.begin_create_or_update(sync + async, in_patch.py) to:202in addition to200/201(in a minimal_create_or_update_initialoverride that isotherwise identical to the generated method).
provisioningStatefrom thelistAPI via a customblocking poller (
_ComputeListPolling/_AsyncComputeListPolling), matching the compute by name.This needs only
computes/read(which callers already have) and never touches thecomputeOperationsoperation-status endpoint.properties.errors(e.g. the quota message) instead of a genericOperation returned an invalid status 'OK'.@overloads, the@api_version_validationguard, the
polling=Falseescape hatch, and thecontinuation_tokenresume path (which does notre-issue the create PUT). Genuine non-2xx create failures still propagate.
Why
listand not a resourcegetThe compute create is asynchronous, and a
GETon the just-created compute returns404 "Cluster not found"for an extended, variable period while the cluster backend materializes — longenough that a
get-based poller wrongly fails a create that is actually succeeding. The compute does,however, appear in the
listresponse with itsprovisioningStatefrom the moment the create isaccepted. Polling
listtherefore reflects the true state throughout provisioning. This also matches thework item's guidance to "rely on the list API for status polling of compute creation."
Only private helpers were added (
_ComputeListPolling,_AsyncComputeListPolling,_provisioning_error,_state_of,_TERMINAL_FAILED_STATES,_TERMINAL_SUCCESS_STATES); the public API surface isunchanged (verified: the three public overloads are preserved and api-version validation still fires).
Notes
_patch.pyso the code generator does not overwrite it.
_patch.pyre-implements the initial request send only because the generated_create_or_update_initialrejects the
202; it is kept intentionally close to the generated code.poller.result()semantics) rather than returning early,and surfaces provisioning failures - so callers get correct results, not a premature "Accepted".
15.0.0b3→15.0.0b4; CHANGELOG updated.Testing
tests/test_computes_operations_patch.py+..._async.py, 11 sync + 11 async):accept 202 · reads status via
list, nevercomputeOperations· blocks until terminal · tolerates thecompute being briefly absent from
listthen appearing · gives up (bounded) if it never appears ·surfaces the real failure reason · propagates non-2xx ·
polling=False· public overloads preserved ·old api-version rejected ·
continuation_tokendoes not re-send the create. All pass;black+pyflakesclean.jayant-westcentralus,Standard_D64_v3):provisioningStatefromlist(never a404), and returned the compute withprovisioningState: Succeeded.real error (
ClusterCoreQuotaReachedquota message) instead of a generic status error.AuthorizationFailed/invalid status 'Accepted'occurs.All SDK Contribution checklist:
General Guidelines and Best Practices
Testing Guidelines
Verification
**Unit tests - all passing. **
test_computes_operations_patch.py(sync) andtest_computes_operations_patch_async.py(async) cover accepting the async202, polling the compute resource instead ofcomputeOperations, blocking until terminal state, tolerating the read-after-write404window, surfacing the real provisioning failure, propagating non-2xx errors, and thepolling=Falseescape hatch.Live end-to-end success.
begin_create_or_update(...).result()accepts the async 202, tracksstatus via the
listAPI (STEP 2: computeOperations never called), blocks through ~33 min ofprovisioning, and returns the created
Standard_D64_v3compute withprovisioningState: SucceededAuthorizationFailed, noinvalid status 'Accepted', and none of the404 "Cluster not found"that a
get-based poller hits during creation.