-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[ARM] az deployment group/sub/mg/tenant validate/create/what-if: Support deployment with Bicep files #16857
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
zhoxing-ms
merged 20 commits into
Azure:dev
from
shenglol:shenglol/arm-deployment-with-bicep
Feb 24, 2021
Merged
[ARM] az deployment group/sub/mg/tenant validate/create/what-if: Support deployment with Bicep files #16857
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
4b2ff90
Add support to Bicep
shenglol e89fc1e
Add deployment with Bicep integration tests
shenglol 1d436dd
Add a unit test
shenglol 4538abc
Add more tests
shenglol 266f5ec
Add help docs; some refacoring
shenglol 4c1c67e
Remove deployment with Bicep scenario tests
shenglol 69d68a9
Remove unused import
shenglol 52b4de9
Fix style and linter issues
shenglol 38f85cb
Add license header
shenglol decec74
Try add semver to setup.py
shenglol 95c039b
Fix a module name
shenglol cff5e93
Fix Python 3.6 compatability issue
shenglol a66c212
Implement bicep decompile command
shenglol 895b289
Update Bicep CLI installation location
shenglol 277a4f8
Update src/azure-cli/azure/cli/command_modules/resource/_bicep.py
shenglol 3208ddd
Update src/azure-cli/azure/cli/command_modules/resource/_help.py
shenglol 1e6d746
Use more specific error types
shenglol bb0e6c9
Add live tests
shenglol 19b6806
Make sample files consistent in help docs
shenglol e579a7c
Update src/azure-cli/azure/cli/command_modules/resource/_help.py
shenglol File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
148 changes: 148 additions & 0 deletions
148
src/azure-cli/azure/cli/command_modules/resource/_bicep.py
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| # -------------------------------------------------------------------------------------------- | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT License. See License.txt in the project root for license information. | ||
| # -------------------------------------------------------------------------------------------- | ||
|
|
||
| import os | ||
| import re | ||
| import stat | ||
| import platform | ||
| import subprocess | ||
|
|
||
| from pathlib import Path | ||
| from contextlib import suppress | ||
|
|
||
| import requests | ||
| import semver | ||
|
|
||
| from six.moves.urllib.request import urlopen | ||
| from knack.log import get_logger | ||
| from azure.cli.core.azclierror import FileOperationError, ValidationError, UnclassifiedUserFault, ClientRequestError | ||
|
|
||
| # See: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string | ||
| _semver_pattern = r"(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?" # pylint: disable=line-too-long | ||
| _logger = get_logger(__name__) | ||
|
|
||
|
|
||
| def run_bicep_command(args, auto_install=True, check_upgrade=True): | ||
| installation_path = _get_bicep_installation_path(platform.system()) | ||
| installed = os.path.isfile(installation_path) | ||
|
|
||
| if not installed: | ||
| if auto_install: | ||
| ensure_bicep_installation() | ||
| else: | ||
| raise FileOperationError('Bicep CLI not found. Install it now by running "az bicep install".') | ||
| elif check_upgrade: | ||
| with suppress(ClientRequestError): | ||
| # Checking upgrade should ignore connection issues. | ||
| # Users may continue using the current installed version. | ||
| installed_version = _get_bicep_installed_version(installation_path) | ||
| latest_release_tag = get_bicep_latest_release_tag() | ||
| latest_version = _extract_semver(latest_release_tag) | ||
| if installed_version and latest_version and semver.compare(installed_version, latest_version) < 0: | ||
| _logger.warning( | ||
| 'A new Bicep release is available: %s. Upgrade now by running "az bicep upgrade".', | ||
| latest_release_tag, | ||
| ) | ||
|
|
||
| return _run_command(installation_path, args) | ||
|
|
||
|
|
||
| def ensure_bicep_installation(release_tag=None): | ||
| system = platform.system() | ||
| installation_path = _get_bicep_installation_path(system) | ||
|
|
||
| if os.path.isfile(installation_path): | ||
| if not release_tag: | ||
| return | ||
|
|
||
| installed_version = _get_bicep_installed_version(installation_path) | ||
| target_version = _extract_semver(release_tag) | ||
| if installed_version and target_version and semver.compare(installed_version, target_version) == 0: | ||
| return | ||
|
|
||
| installation_dir = os.path.dirname(installation_path) | ||
| if not os.path.exists(installation_dir): | ||
| os.makedirs(installation_dir) | ||
|
|
||
| try: | ||
| release_tag = release_tag if release_tag else get_bicep_latest_release_tag() | ||
| if release_tag: | ||
| print(f"Installing Bicep CLI {release_tag}...") | ||
| else: | ||
| print("Installing Bicep CLI...") | ||
|
|
||
| request = urlopen(_get_bicep_download_url(system, release_tag)) | ||
| with open(installation_path, "wb") as f: | ||
| f.write(request.read()) | ||
|
|
||
| os.chmod(installation_path, os.stat(installation_path).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) | ||
|
|
||
| print(f'Successfully installed Bicep CLI to "{installation_path}".') | ||
| except IOError as err: | ||
| raise ClientRequestError(f"Error while attempting to download Bicep CLI: {err}") | ||
|
|
||
|
|
||
| def is_bicep_file(file_path): | ||
| return file_path.lower().endswith(".bicep") | ||
|
|
||
|
|
||
| def get_bicep_available_release_tags(): | ||
| try: | ||
| response = requests.get("https://api.github.com/repos/Azure/bicep/releases") | ||
| return [release["tag_name"] for release in response.json()] | ||
| except IOError as err: | ||
| raise ClientRequestError(f"Error while attempting to retrieve available Bicep versions: {err}.") | ||
|
|
||
|
|
||
| def get_bicep_latest_release_tag(): | ||
| try: | ||
| response = requests.get("https://api.github.com/repos/Azure/bicep/releases/latest") | ||
| return response.json()["tag_name"] | ||
| except IOError as err: | ||
| raise ClientRequestError(f"Error while attempting to retrieve the latest Bicep version: {err}.") | ||
|
|
||
|
|
||
| def _get_bicep_installed_version(bicep_executable_path): | ||
| installed_version_output = _run_command(bicep_executable_path, ["--version"]) | ||
| return _extract_semver(installed_version_output) | ||
|
|
||
|
|
||
| def _get_bicep_download_url(system, release_tag): | ||
| download_url = f"https://github.com/Azure/bicep/releases/download/{release_tag}/{{}}" | ||
|
|
||
| if system == "Windows": | ||
| return download_url.format("bicep-win-x64.exe") | ||
| if system == "Linux": | ||
| return download_url.format("bicep-linux-x64") | ||
| if system == "Darwin": | ||
| return download_url.format("bicep-osx-x64") | ||
|
|
||
| raise ValidationError(f'The platform "{format(system)}" is not supported.') | ||
|
|
||
|
|
||
| def _get_bicep_installation_path(system): | ||
| installation_folder = os.path.join(str(Path.home()), ".azure", "bin") | ||
|
|
||
| if system == "Windows": | ||
| return os.path.join(installation_folder, "bicep.exe") | ||
| if system in ("Linux", "Darwin"): | ||
| return os.path.join(installation_folder, "bicep") | ||
|
|
||
| raise ValidationError(f'The platform "{format(system)}" is not supported.') | ||
|
|
||
|
|
||
| def _extract_semver(text): | ||
| semver_match = re.search(_semver_pattern, text) | ||
| return semver_match.group(0) if semver_match else None | ||
|
|
||
|
|
||
| def _run_command(bicep_installation_path, args): | ||
| process = subprocess.run([rf"{bicep_installation_path}"] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
|
|
||
| try: | ||
| process.check_returncode() | ||
| return process.stdout.decode("utf-8") | ||
| except subprocess.CalledProcessError: | ||
| raise UnclassifiedUserFault(process.stderr.decode("utf-8")) | ||
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
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
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
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shenglol, if
bicephas no fancy versioning schema and complies with PEP 440, cansemverbe replaced bypackaging.version?packaging.versionis used byaz extension(#17667):azure-cli/src/azure-cli-core/azure/cli/core/extension/__init__.py
Lines 287 to 298 in 22725b3
This will help us reduce Azure CLI’s packaging maintenance cost (#26523).