Skip to content

[Cosmos DB] az cosmosdb restore: Fix cross-region restore by preserving source region in top-level location#33274

Open
dsapaliga wants to merge 2 commits intoAzure:devfrom
dsapaliga:dsapaliga/fix-crr-arm-location
Open

[Cosmos DB] az cosmosdb restore: Fix cross-region restore by preserving source region in top-level location#33274
dsapaliga wants to merge 2 commits intoAzure:devfrom
dsapaliga:dsapaliga/fix-crr-arm-location

Conversation

@dsapaliga
Copy link
Copy Markdown
Contributor

@dsapaliga dsapaliga commented Apr 28, 2026

Related command

az cosmosdb restore

Description

Fixes a regression in cross-region restore (CRR) introduced by commit 2cf7b76a (PR #32752).

That commit added an unconditional loop in _create_database_account that overwrites arm_location with the priority-0 entry of locations:

for loc in locations:
    if loc.failover_priority == 0:
        arm_location = loc.location_name
        break

For a regular create this is a defensive no-op. But cli_cosmosdb_restore deliberately passes:

  • arm_location = restorable account's region (source, e.g. eastus2)
  • locations = [Location(location_name=<--location>, failover_priority=0)] (target, e.g. westus2)
  • is_restore_request=True

After the loop, arm_location is clobbered with the target region, so the wire payload becomes:

location = westus2                                 (target)   <-- wrong
properties.restoreParameters.restoreSource = .../locations/eastus2/...
properties.locations[0].locationName = westus2     (target)

The backend's ParseAndValidateRestoreSourceUri enforces that the top-level location matches the source URI region and rejects the request:

(BadRequest) Location provided in 'restoreSource' ('eastus2') does not match the location of the request ('westus2')

This breaks every cross-region restore via CLI.

Fix

Gate the override on non-restore requests:

if not is_restore_request:
    for loc in locations:
        if loc.failover_priority == 0:
            arm_location = loc.location_name
            break

This preserves the Cosmos ARM contract for restore (top-level location = source, properties.locations[0] = target) and keeps the loop's existing behavior for regular create. The unrelated 403 retry-via-GET workaround from #32752 (the documented purpose of that PR) is untouched.

Testing

Added two unit tests to CosmosDBRestoreUnitTests:

  • test_restore_preserves_source_arm_location_for_cross_region — asserts location='eastus2' is forwarded when is_restore_request=True even with priority-0 location westus2. Would have caught 2cf7b76a.
  • test_normal_create_aligns_arm_location_with_priority_zero — counterpart asserting the override still happens for normal create.

Local results:

azdev style cosmosdb     -> PASSED
azdev linter cosmosdb    -> PASSED
pytest CosmosDBRestoreUnitTests -> 6 passed (4 existing + 2 new)

History notes

  • [Cosmos DB] az cosmosdb restore: Preserve source region in top-level location for cross-region restore
image

…ving source region in top-level location

The priority-0 location override added in 2cf7b76 clobbered the source region passed by `cli_cosmosdb_restore` with the target region, causing the backend to reject CRR with: "Location provided in 'restoreSource' does not match the location of the request". Gate the override behind `not is_restore_request` so the restore path preserves the source region per the Cosmos ARM contract (top-level location = source, properties.locations[0] = target). Regular create behavior is unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 28, 2026 04:18
@azure-client-tools-bot-prd
Copy link
Copy Markdown

azure-client-tools-bot-prd Bot commented Apr 28, 2026

️✔️AzureCLI-FullTest
️✔️acr
️✔️latest
️✔️3.12
️✔️3.13
️✔️acs
️✔️latest
️✔️3.12
️✔️3.13
️✔️advisor
️✔️latest
️✔️3.12
️✔️3.13
️✔️ams
️✔️latest
️✔️3.12
️✔️3.13
️✔️apim
️✔️latest
️✔️3.12
️✔️3.13
️✔️appconfig
️✔️latest
️✔️3.12
️✔️3.13
️✔️appservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️aro
️✔️latest
️✔️3.12
️✔️3.13
️✔️backup
️✔️latest
️✔️3.12
️✔️3.13
️✔️batch
️✔️latest
️✔️3.12
️✔️3.13
️✔️batchai
️✔️latest
️✔️3.12
️✔️3.13
️✔️billing
️✔️latest
️✔️3.12
️✔️3.13
️✔️botservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️cdn
️✔️latest
️✔️3.12
️✔️3.13
️✔️cloud
️✔️latest
️✔️3.12
️✔️3.13
️✔️cognitiveservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️compute_recommender
️✔️latest
️✔️3.12
️✔️3.13
️✔️computefleet
️✔️latest
️✔️3.12
️✔️3.13
️✔️config
️✔️latest
️✔️3.12
️✔️3.13
️✔️configure
️✔️latest
️✔️3.12
️✔️3.13
️✔️consumption
️✔️latest
️✔️3.12
️✔️3.13
️✔️container
️✔️latest
️✔️3.12
️✔️3.13
️✔️containerapp
️✔️latest
️✔️3.12
️✔️3.13
️✔️core
️✔️latest
️✔️3.12
️✔️3.13
️✔️cosmosdb
️✔️latest
️✔️3.12
️✔️3.13
️✔️databoxedge
️✔️latest
️✔️3.12
️✔️3.13
️✔️dls
️✔️latest
️✔️3.12
️✔️3.13
️✔️dms
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventgrid
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventhubs
️✔️latest
️✔️3.12
️✔️3.13
️✔️feedback
️✔️latest
️✔️3.12
️✔️3.13
️✔️find
️✔️latest
️✔️3.12
️✔️3.13
️✔️hdinsight
️✔️latest
️✔️3.12
️✔️3.13
️✔️identity
️✔️latest
️✔️3.12
️✔️3.13
️✔️iot
️✔️latest
️✔️3.12
️✔️3.13
️✔️keyvault
️✔️latest
️✔️3.12
️✔️3.13
️✔️lab
️✔️latest
️✔️3.12
️✔️3.13
️✔️managedservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️maps
️✔️latest
️✔️3.12
️✔️3.13
️✔️marketplaceordering
️✔️latest
️✔️3.12
️✔️3.13
️✔️monitor
️✔️latest
️✔️3.12
️✔️3.13
️✔️mysql
️✔️latest
️✔️3.12
️✔️3.13
️✔️netappfiles
️✔️latest
️✔️3.12
️✔️3.13
️✔️network
️✔️latest
️✔️3.12
️✔️3.13
️✔️policyinsights
️✔️latest
️✔️3.12
️✔️3.13
️✔️postgresql
️✔️latest
️✔️3.12
️✔️3.13
️✔️privatedns
️✔️latest
️✔️3.12
️✔️3.13
️✔️profile
️✔️latest
️✔️3.12
️✔️3.13
️✔️rdbms
️✔️latest
️✔️3.12
️✔️3.13
️✔️redis
️✔️latest
️✔️3.12
️✔️3.13
️✔️relay
️✔️latest
️✔️3.12
️✔️3.13
️✔️resource
️✔️latest
️✔️3.12
️✔️3.13
️✔️role
️✔️latest
️✔️3.12
️✔️3.13
️✔️search
️✔️latest
️✔️3.12
️✔️3.13
️✔️security
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicebus
️✔️latest
️✔️3.12
️✔️3.13
️✔️serviceconnector
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicefabric
️✔️latest
️✔️3.12
️✔️3.13
️✔️signalr
️✔️latest
️✔️3.12
️✔️3.13
️✔️sql
️✔️latest
️✔️3.12
️✔️3.13
️✔️sqlvm
️✔️latest
️✔️3.12
️✔️3.13
️✔️storage
️✔️latest
️✔️3.12
️✔️3.13
️✔️synapse
️✔️latest
️✔️3.12
️✔️3.13
️✔️telemetry
️✔️latest
️✔️3.12
️✔️3.13
️✔️util
️✔️latest
️✔️3.12
️✔️3.13
️✔️vm
️✔️latest
️✔️3.12
️✔️3.13

@azure-client-tools-bot-prd
Copy link
Copy Markdown

azure-client-tools-bot-prd Bot commented Apr 28, 2026

️✔️AzureCLI-BreakingChangeTest
️✔️Non Breaking Changes

@yonzhan
Copy link
Copy Markdown
Collaborator

yonzhan commented Apr 28, 2026

Thank you for your contribution! We will review the pull request and get back to you soon.

@github-actions
Copy link
Copy Markdown

The git hooks are available for azure-cli and azure-cli-extensions repos. They could help you run required checks before creating the PR.

Please sync the latest code with latest dev branch (for azure-cli) or main branch (for azure-cli-extensions).
After that please run the following commands to enable git hooks:

pip install azdev --upgrade
azdev setup -c <your azure-cli repo path> -r <your azure-cli-extensions repo path>

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a regression in az cosmosdb restore cross-region restore by preventing _create_database_account from overwriting the restore source region (arm_location) with the priority-0 target region.

Changes:

  • Skip arm_location normalization to priority-0 locations when is_restore_request=True.
  • Add unit tests covering cross-region restore location preservation and normal create behavior.
  • Add a release history entry for the restore fix.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/azure-cli/azure/cli/command_modules/cosmosdb/custom.py Gate the priority-0 location normalization so restore requests preserve the source region in the top-level ARM location.
src/azure-cli/azure/cli/command_modules/cosmosdb/tests/latest/test_cosmosdb_backuprestore_scenario.py Add regression/control unit tests validating location behavior for restore vs normal create.
src/azure-cli/HISTORY.rst Document the az cosmosdb restore cross-region restore fix in release notes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/azure-cli/HISTORY.rst Outdated
@yonzhan yonzhan assigned calvinhzy and unassigned evelyn-ys Apr 28, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants