Skip to content

[App Service] Add Active Backup silo management preview - #34239

Open
JarodAertsMsft wants to merge 6 commits into
Azure:devfrom
JarodAertsMsft:active-backup-preview
Open

JarodAertsMsft wants to merge 6 commits into
Azure:devfrom
JarodAertsMsft:active-backup-preview

Conversation

@JarodAertsMsft

@JarodAertsMsft JarodAertsMsft commented Oct 19, 2026 •

Copy link
Copy Markdown

🤖 PR Validation — ⚠️ Review suggested

Breaking Changes Tests
⚠️ None ️✔️ 130/130
⚠️AzureCLI-BreakingChangeTest
⚠️appservice
rule cmd_name rule_message suggest_message
⚠️ 1011 - SubgroupAdd appservice plan silo sub group appservice plan silo added
⚠️ 1011 - SubgroupAdd webapp last-known-good sub group webapp last-known-good added
⚠️ 1011 - SubgroupAdd webapp managed-traffic sub group webapp managed-traffic added
⚠️ 1011 - SubgroupAdd webapp silo sub group webapp silo added

Related command

az appservice plan silo, az webapp silo, az webapp managed-traffic, az webapp last-known-good

Description

Add public-preview Active Backup silo management for App Service plans and web apps using AAZ-generated commands, replacing the original handwritten client and command-dispatch implementation.

Swagger/TypeSpec source: Azure/azure-rest-api-specs PR #44330. Generation uses the App Service 2026-08-01 contract at pinned revision 33ee07b2b3d377b58c4d1a1c5be7e2339f43b879. That specification PR is still open; known contract corrections and companion Azure/aaz command-model publication remain outstanding.

Current scope

The implementation exposes 24 preview commands, including two resource-wait commands, covering the draft specification's 20 HTTP operations:

Command group Commands
appservice plan silo create, update, show, list, delete, wait
appservice plan silo vnet-integration list
webapp silo create, update, show, list, delete, wait, refresh
webapp silo vnet-integration show, add, update, remove
webapp managed-traffic list, show, update
webapp last-known-good list, show, mark

AAZ supplies HTTP transport, authentication, serialization, pagination and standard long-running-operation handling. The 38 generated Python files are generated from command models, not hand-edited. Handwritten compatibility subclasses live under appservice/operations; explicit command bindings and an original-resource-ID guard follow the existing module loader.

  • Existing ordinary webapp/plan commands, their API versions and SDK pins are unchanged.
  • --no-wait uses standard AAZ behavior: submit without subsequent polling and return no custom operation receipt. Explicit wait commands poll resource conditions, not saved operation IDs.
  • Generic updates preserve modeled writable fields and support standard --set, --add and --remove behavior. Existing silo location is preserved rather than guessed from defaults.
  • Refresh returns on HTTP 204 acceptance; it does not wait for revision propagation or implement a synthetic failover workflow.
  • Silo pass-through APIs, standalone operation inspection, managed-traffic metrics, publishing-profile access and the broader original 104-command surface are deferred.
  • The bespoke PowerShell validation harness is not part of this PR's net diff. Developer-local reports, credentials, fixtures, cloned specs and tool environments are not committed.

Narrow compatibility overrides

The generated request/response and command implementations remain the base. Temporary overrides address observed service/specification differences:

Difference Compatibility handling
Draft silo models omit the top-level ARM location required by the deployed service Supply it on create and preserve actual location metadata on reads/updates.
Pending Azure-AsyncOperation reads can return empty 202 responses Prefer the existing Location monitor through a response hook, retaining the SDK's standard polling.
Origin point GET can return 404 while the collection contains the origin Reuse generated list/pagination; require a unique matching valid ARM resource and warn about potentially absent stamp-derived IP fields.
Plan-silo VNet listing returns an ARM envelope containing a properties array rather than the declared bare array Map validated subnet entries into the generated response model; reject unexpected shapes.
Core's standard 409 mapping loses legacy App Service Code/Message detail Use AAZ's existing case-insensitive formatter for plan-silo delete conflicts, retaining the exception type, status and failure exit code.

No substitute resource identities or dependency-error messages are fabricated. See the preview usage and compatibility guide.

Testing Guide

With an eligible existing primary plan/app, a feature-enabled subscription and supported regions, create the plan silo before the site silo:

az appservice plan silo create --resource-group MyGroup --name MyPlan --silo WestPlan --location westus2 --primary-location eastus --number-of-workers 2
az webapp silo create --resource-group MyGroup --name MyApp --silo WestApp --location westus2 --primary-location eastus --traffic-mode Active
az webapp silo show --resource-group MyGroup --name MyApp --silo WestApp
az webapp managed-traffic update --resource-group MyGroup --name MyApp --traffic-mode Passive
az webapp silo refresh --resource-group MyGroup --name MyApp

Delete site silos before their backing plan silo. Live execution allocates billable resources and requires explicit authorization and service-side enablement.

Local offline validation

For head 8995e9cf3c, the following focused regression command passed: 71 tests run, 69 passed and 2 opt-in live scenarios skipped. It exercises actual CLI parsing, the 24-command inventory and help, the 20 modeled HTTP operations, 48 executable examples, compatibility/error/wait behavior, resource-ID guards and adjacent App Service regressions. The committed tests use mocked transport for offline validation; they require no enabled Azure subscription.

Run from a prepared repository development environment with an isolated local CLI configuration/cache:

$repo = (Get-Location).Path
$env:PYTHONPATH = "$repo\src\azure-cli;$repo\src\azure-cli-core;$repo\src\azure-cli-testsdk"
$env:AZURE_ACTIVE_BACKUP_LIVE = '0'
$env:AZURE_TEST_RUN_LIVE = 'false'
& .\env\Scripts\python.exe -m unittest `
    azure.cli.command_modules.appservice.tests.latest.test_active_backup_aaz `
    azure.cli.command_modules.appservice.tests.latest.test_active_backup_commands `
    azure.cli.command_modules.appservice.tests.latest.test_webapp_commands_thru_mock.TestWebappOutputTransformers `
    azure.cli.command_modules.appservice.tests.latest.test_webapp_commands_thru_mock.TestCreateAppServicePlanDefaults `
    azure.cli.command_modules.appservice.tests.latest.test_webapp_commands_thru_mock.TestUpdateWebapp `
    azure.cli.command_modules.appservice.tests.latest.test_webapp_commands_thru_mock.TestOneDeployTag -q

Focused style and committed-diff whitespace checks also passed:

& .\env\Scripts\python.exe -m flake8 `
    src\azure-cli\azure\cli\command_modules\appservice\operations `
    src\azure-cli\azure\cli\command_modules\appservice\commands.py `
    src\azure-cli\azure\cli\command_modules\appservice\_validators.py `
    src\azure-cli\azure\cli\command_modules\appservice\tests\latest\test_active_backup_aaz.py `
    src\azure-cli\azure\cli\command_modules\appservice\tests\latest\test_active_backup_commands.py `
    --max-line-length=119
git diff HEAD^ HEAD --check

Authorized live evidence

A developer-local Windows Core run on October 22 exercised the API implementation now in this PR: all 25 required checks passed, with automatic owned cleanup and independent confirmation that the test resource group was absent. Coverage included provisioning, reads, content replication, refresh acceptance, worker overrides, traffic, origin control, VNet add/show/update/list/remove, LKG baseline/pin/advance and negative cases. The previously failing dependency-delete check passed with the real service-provided error detail; the strict assertion was not weakened.

This was Windows P1V3 only, East US 2 EUAP to Central US EUAP, with at most two workers per plan. It provided successful evidence for 23 command paths and negative-only evidence for plan-silo deletion; positive live plan-silo deletion, Linux, additional SKUs and zone scenarios are not established by this run. The local driver and its reports are not committed replay recordings or hosted CI results.

Remaining review-readiness work

  • Publish/cross-link the companion Azure/aaz command-model PR and coordinate the source Swagger/TypeSpec contract corrections.
  • Add sanitized replay recordings and verify playback. The committed native scenarios are currently explicitly gated, live-only tests; their source is included, but they do not provide normal CI playback coverage yet.
  • Run the full azdev style/linter, playback and command/argument coverage gates. The local environment currently has no azdev executable; focused checks above are not substitutes for those gates.
  • Add positive live plan-silo deletion evidence and agree any additional platform/SKU verification required for preview.

The preserved bot-managed validation block above records an earlier head (c8c9e8b...); its 130/130 badge is not validation evidence for this AAZ rewrite. New-head hosted CI is separate from the local results above.

History Notes

[App Service] az appservice plan silo, az webapp silo: Add preview spec-generated Active Backup silo lifecycle, refresh and networking commands.
[App Service] az webapp managed-traffic, az webapp last-known-good: Add preview regional traffic and Last Known Good management.


This checklist is used to make sure that common guidelines for a pull request are followed.

Add dedicated plan/site silo lifecycle, managed regional traffic, Last Known Good, accepted refresh, networking, and operational pass-through commands. Preserve service eligibility and API operation semantics. Include isolated ARM transport, offline coverage, opt-in live scenarios, and usage documentation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 224abf0a-0923-4347-a5ea-5c4a1b4e4824
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@microsoft-github-policy-service microsoft-github-policy-service Bot added the customer-reported Issues that are reported by GitHub users external to the Azure organization. label Oct 19, 2026
@microsoft-github-policy-service

Copy link
Copy Markdown
Contributor

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

@x-engineering-agent

Copy link
Copy Markdown
Contributor

Hi JarodAertsMsft,
Since the current milestone time is less than 7 days, this pr will be reviewed in the next milestone.

@yonzhan

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).

Your Name and others added 4 commits October 20, 2026 09:49
Preserve no-wait receipts, return canonical resources after asynchronous writes, add the approved origin-only collection compatibility, and use async-status mode for standalone CRUD operation inspection and waits. Keep service errors visible and do not infer deletion success from polling 404.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 224abf0a-0923-4347-a5ea-5c4a1b4e4824
Add checkout-bound PowerShell Plan, Preflight, Run, Resume and Cleanup modes with explicit subscription/resource authorization, protected evidence, ownership-checked cleanup and offline safety tests. Cover Windows Core workflows while preserving known service polling failures in report history.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 224abf0a-0923-4347-a5ea-5c4a1b4e4824
Preserve silo regions despite configured location defaults, paginate actual ARM collections without flattening property bags, and clear completed mutation journal state regardless of validated output shape. Add parser/output/pagination and safe-resume regressions; keep backend errors and delete-404 policy unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 224abf0a-0923-4347-a5ea-5c4a1b4e4824
Normalize identity conflicts without private argparse APIs, preserve core HTTP error categories and retry behavior, expose named diagnostic inputs, and author complete help/examples. Protect recovery manifests with initialization/lock guards, ownership reconciliation and snapshot handoff validation. Keep strict delete polling errors; add regression coverage validated by 119 Python tests and 57 offline harness checks.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 224abf0a-0923-4347-a5ea-5c4a1b4e4824
@JarodAertsMsft

Copy link
Copy Markdown
Author

Hey Yong Zhang (@yonzhan), we need this payload for a feature we are announcing at ignite. Is it possible to get this reviewed before the cutoff?

@JarodAertsMsft

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree company="Microsoft"


def load_arguments(self, _):
from ._active_backup_commands import load_arguments as load_active_backup_arguments
load_active_backup_arguments(self, _)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ensure commands and params are registered according to pre-existing conventions. Refer to https://github.com/Azure/azure-cli/blob/dev/doc/authoring_command_modules/authoring_commands.md for guidance or how existing commands and params are registered

from azure.cli.core.util import get_az_user_agent, get_error_type_by_status_code, should_disable_connection_verify


API_VERSION = '2026-08-01'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks like a hand rolled client. Is there an sdk for this? Or a rest spec that we can code gen from? Refer to https://azure.github.io/aaz-dev-tools/pages/usage/cli-generator/

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

There is not yet an SDK and the swagger has not yet been published as the API has not yet been 100% deployed. But we have our PR into the swagger repo. I will look to use that to generate CLI and update PR with that. There might be some parts that will still require some somewhat special handling, but will see once I get things into a better state.

Azure/azure-rest-api-specs#44330

Thank you for the direction.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I have scoped this PR down to the base commands that can be automatically generated from the Swagger with the cli generator along with some required custom handling for async and some mismatches in our swagger we need to fix.

Some of the content I had previously related to our passthrough APIs (which is where Silo resources can use same endpoints as normal web app resources but with their path), I have omitted for now.

I will continue to test and address comments on the PR, please let me know if the direction here is incorrect. This is my first time doing CLI work and really appreciate the help.

@JarodAertsMsft
JarodAertsMsft marked this pull request as ready for review October 21, 2026 03:28
Copilot AI balanced review requested due to automatic review settings October 21, 2026 03:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

File-backed live capture and binary request-file handling have unresolved data-integrity defects.

2 open issues
What changed in this PR

Adds preview Active Backup management to the App Service CLI without changing existing app/plan API versions.

Changes:

  • Adds silo lifecycle, traffic, networking, diagnostics, and operational commands.
  • Implements authenticated transport, operation polling, pagination, and file streaming.
  • Adds mock/live tests, usage documentation, and an opt-in validation harness.
File Description
src/​azure-cli/​azure/​cli/​command_modules/​appservice/​tests/​latest/​test_active_backup_commands.py Opt-in Windows/Linux lifecycle tests.
src/​azure-cli/​azure/​cli/​command_modules/​appservice/​tests/​latest/​test_active_backup_commands_thru_mock.py Command routing, help, and CLI regression tests.
src/​azure-cli/​azure/​cli/​command_modules/​appservice/​tests/​latest/​test_active_backup_client.py Transport, polling, and file-handling tests.
src/​azure-cli/​azure/​cli/​command_modules/​appservice/​commands.py Registers preview commands.
src/​azure-cli/​azure/​cli/​command_modules/​appservice/​active_backup.py Implements Active Backup handlers.
src/​azure-cli/​azure/​cli/​command_modules/​appservice/​_params.py Loads new arguments.
src/​azure-cli/​azure/​cli/​command_modules/​appservice/​_help.py Loads preview help.
src/​azure-cli/​azure/​cli/​command_modules/​appservice/​_active_backup_commands.py Defines commands, arguments, and examples.
src/​azure-cli/​azure/​cli/​command_modules/​appservice/​_active_backup_client.py Provides ARM transport and operation handling.
scripts/​appservice/​test_active_backup.ps1 Adds authorized validation and recovery entrypoint.
scripts/​appservice/​README.md Documents harness operation and safeguards.
doc/​active_backup_preview.md Documents preview usage and limitations.
.gitignore Excludes local validation artifacts.

Review effort: Balanced

Comment on lines +352 to +361
descriptor, temporary = tempfile.mkstemp(dir=os.path.dirname(destination))
with os.fdopen(descriptor, 'wb') as handle:
for chunk in response.iter_content(chunk_size=65536):
handle.write(chunk)
if overwrite:
os.replace(temporary, destination)
temporary = None
else:
os.link(temporary, destination)
return {'file': destination}
Comment on lines +489 to +492
elif isinstance(body, str) and body.startswith('@'):
try:
with open(body[1:], 'rb') as handle:
body = handle.read()
Replace the handwritten transport and signature-driven command dispatch with the spec-limited 24-command AAZ preview. Retain narrow generated-command subclasses for observed resource-envelope, polling, origin-read, VNet-response and conflict-format compatibility. Keep portable offline and gated scenario tests, and remove developer-only PowerShell validation tooling from the feature PR while preserving it locally. Companion model publication, replay recordings and full azdev gates remain review-readiness work.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 224abf0a-0923-4347-a5ea-5c4a1b4e4824

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

act-observability-squad Auto-Assign Auto assign by bot Backup customer-reported Issues that are reported by GitHub users external to the Azure organization.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants