[Resource] az bicep: Add snapshot and run subcommands#33398
Conversation
- `az bicep snapshot`: Wraps the Bicep CLI `snapshot` command (introduced in Bicep CLI 0.41.2) to capture or validate deployment snapshots from a .bicepparam file. Supports `--mode`, `--tenant-id`, `--subscription-id`, `--management-group-id`, `--location`, `--resource-group`, and `--deployment-name`. - `az bicep run`: Generic passthrough that forwards a quoted command string to the installed Bicep CLI, allowing use of CLI features that don't yet have a dedicated `az bicep` wrapper. - Uses `shlex.split(..., posix=False)` plus quote stripping so Windows paths with backslashes are preserved. - Adds unit tests (TestBicepSnapshot, TestBicepRun) and LiveScenarioTests (BicepSnapshotTest, BicepRunTest).
️✔️AzureCLI-FullTest
|
|
Hi @shenglol, |
|
| rule | cmd_name | rule_message | suggest_message |
|---|---|---|---|
| bicep run | cmd bicep run added |
||
| bicep snapshot | cmd bicep snapshot added |
|
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). pip install azdev --upgrade
azdev setup -c <your azure-cli repo path> -r <your azure-cli-extensions repo path>
|
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds two new Bicep subcommands to the resource module: az bicep snapshot (wraps Bicep CLI's snapshot command, requires Bicep CLI v0.41.2+) and az bicep run (generic passthrough that forwards a quoted command string to the Bicep CLI, preserving Windows-style backslashes via shlex non-POSIX mode).
Changes:
- Implements
snapshot_bicep_fileandrun_bicep_cli_passthroughincustom.py, wired up viacommands.py,_params.py, and_help.py. - Adds unit tests covering argument forwarding, version-gating, quote handling, and empty-command validation.
- Adds
LiveScenarioTestclasses exercising the new commands end-to-end against the installed Bicep CLI.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/azure-cli/azure/cli/command_modules/resource/custom.py | Adds snapshot_bicep_file and run_bicep_cli_passthrough implementations. |
| src/azure-cli/azure/cli/command_modules/resource/commands.py | Registers the new snapshot and run commands under the bicep group. |
| src/azure-cli/azure/cli/command_modules/resource/_params.py | Declares arguments for the new commands. |
| src/azure-cli/azure/cli/command_modules/resource/_help.py | Adds help text and examples for bicep snapshot and bicep run. |
| src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource_bicep.py | Adds unit tests for the new custom functions. |
| src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource.py | Adds live scenario tests for bicep snapshot and bicep run. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| class BicepSnapshotTest(LiveScenarioTest): | ||
| def setup(self): | ||
| super().setup() | ||
| self.cmd('az bicep uninstall') |
There was a problem hiding this comment.
Fixed in d88079b — renamed both the method and the super() call to setUp in BicepSnapshotTest.
| class BicepRunTest(LiveScenarioTest): | ||
| def setup(self): | ||
| super().setup() | ||
| self.cmd('az bicep uninstall') |
There was a problem hiding this comment.
Fixed in d88079b — same correction applied to BicepRunTest.
| curr_dir = os.path.dirname(os.path.realpath(__file__)) | ||
| params_file = os.path.join(curr_dir, 'sample_params.bicepparam').replace('\\', '\\\\') | ||
| snapshot_path = os.path.join(curr_dir, 'sample_params.snapshot.json') |
There was a problem hiding this comment.
The fixtures already exist in this directory and are reused by other Bicep tests (e.g. BicepBuildParamsTest). They were originally added in #26781. No new files are required for this PR.
| def run_bicep_cli_passthrough(cmd, command_string): | ||
| import shlex | ||
|
|
||
| # Use non-POSIX mode so that backslashes in Windows paths are preserved. | ||
| # In non-POSIX mode, shlex retains the surrounding quotes on quoted tokens, | ||
| # so strip them so the values are passed through cleanly to the Bicep CLI. | ||
| args = [] | ||
| for token in shlex.split(command_string, posix=False): |
There was a problem hiding this comment.
Fixed in d88079b — run_bicep_cli_passthrough now calls ensure_bicep_installation(cmd.cli_ctx, stdout=False) at the start, matching the other az bicep wrappers, and the unit tests assert this. A fresh environment will now auto-install the Bicep CLI rather than failing with a confusing error.
| else: | ||
| logger.error("az bicep snapshot could not be executed with the current version of Bicep CLI. Please upgrade Bicep CLI to v%s or later.", minimum_supported_version) |
There was a problem hiding this comment.
Fixed in d88079b — snapshot_bicep_file now raises ValidationError (from azure.cli.core.azclierror) when the installed Bicep CLI is older than the minimum supported version, so the command exits with a non-zero code and CI/scripts can detect the failure. test_snapshot_bicep_file_errors_when_bicep_too_old was updated to assert the raise.
| c.argument('mode', arg_type=get_enum_type(['Overwrite', 'Validate']), | ||
| help="The snapshot mode. 'Overwrite' (default) writes the snapshot file. 'Validate' compares the existing snapshot against the current template and fails if differences are detected.") | ||
| c.argument('tenant_id', options_list=['--tenant-id'], help="The Azure tenant ID to use when capturing the snapshot.") | ||
| c.argument('subscription_id', options_list=['--subscription-id'], help="The Azure subscription ID to use when capturing the snapshot.") |
There was a problem hiding this comment.
Clarified in d88079b by expanding the --help text for --tenant-id, --subscription-id, --management-group-id, --location, --resource-group, and --deployment-name to call out that they are forwarded to the Bicep CLI as the deployment context used to resolve existing references in the snapshot, and are unrelated to Azure CLI authentication. The help for --subscription-id also explicitly points users to the global --subscription argument for switching the active subscription.
We intentionally kept the names aligned with bicep snapshot's native flags so that users coming from the Bicep CLI don't have to learn a new vocabulary. Happy to revisit (e.g. --snapshot-subscription-id) if you'd prefer the rename.
| c.argument('location', options_list=['--location'], help="The Azure location to use when capturing the snapshot.") | ||
| c.argument('resource_group', options_list=['--resource-group'], help="The Azure resource group name to use when capturing the snapshot.") |
There was a problem hiding this comment.
Fixed in d88079b — switched --resource-group to resource_group_name_type and --location to get_location_type(self.cli_ctx), so users now get the standard -g / -l short flags, completion, and az configure --defaults integration consistent with the rest of the module.
| def run_bicep_cli_passthrough(cmd, command_string): | ||
| import shlex |
There was a problem hiding this comment.
az bicep run is intentionally a thin escape hatch for users to consume new Bicep CLI features (or one-off subcommands) without waiting for an az bicep wrapper to ship in azure-cli — so an allowlist of subcommands would defeat its purpose. The command runs the Bicep CLI as the same user, so it can't grant elevated privileges that the user wouldn't already have by invoking bicep directly, but the untrusted-input concern is fair: in d88079b the long-summary in --help now warns "Because the value is forwarded to the Bicep CLI without validation, do not pass strings derived from untrusted input." Wrappers for the most useful Bicep CLI subcommands continue to be added over time, and az bicep run is meant to bridge the gap in the meantime.
|
Thank you for your contribution! We will review the pull request and get back to you soon. |
az bicep: Add snapshot and run subcommands
- Fix setup -> setUp typo in BicepSnapshotTest and BicepRunTest so the pre-test az bicep uninstall actually runs. - Call ensure_bicep_installation at the start of run_bicep_cli_passthrough so a fresh environment auto-installs the Bicep CLI (matching the other az bicep wrappers). - Raise ValidationError (instead of only logging) in snapshot_bicep_file when the installed Bicep CLI is older than the minimum supported version, so failures surface with a non-zero exit code. - Use shared resource_group_name_type and get_location_type for az bicep snapshot's --resource-group/--location so users get the standard -g/-l short flags. - Clarify in --help that --tenant-id/--subscription-id/--management-group-id/--location/--resource-group/--deployment-name on az bicep snapshot are forwarded to the Bicep CLI as deployment context (used to resolve existing references) and are unrelated to Azure CLI authentication. - Add a security note to az bicep run --help warning against passing untrusted input.
Related command
az bicep snapshotaz bicep runDescription
az bicep snapshot: Wraps the Bicep CLIsnapshotcommand (introduced in Bicep CLI 0.41.2) to capture or validate deployment snapshots from a .bicepparam file. Supports--mode,--tenant-id,--subscription-id,--management-group-id,--location,--resource-group, and--deployment-name.az bicep run: Generic passthrough that forwards a quoted command string to the installed Bicep CLI, allowing use of CLI features that don't yet have a dedicatedaz bicepwrapper.shlex.split(..., posix=False)plus quote stripping so Windows paths with backslashes are preserved.Closes Azure/bicep#19502.
Testing Guide
History Notes
az bicep snapshot: New command to wrap the Bicep CLIsnapshotcommand to capture or validate deployment snapshots from a .bicepparam file.az bicep run: New command that forwards a quoted command string to the Bicep CLI, allowing use of CLI features that don't yet have a dedicatedaz bicepwrapper.This checklist is used to make sure that common guidelines for a pull request are followed.
The PR title and description has followed the guideline in Submitting Pull Requests.
I adhere to the Command Guidelines.
I adhere to the Error Handling Guidelines.