Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/azure-cli-core/azure/cli/core/cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ class CloudNameEnum: # pylint: disable=too-few-public-methods
active_directory_graph_resource_id='https://graph.windows.net/',
microsoft_graph_resource_id='https://graph.microsoft.com/',
active_directory_data_lake_resource_id='https://datalake.azure.net/',
vm_image_alias_doc='https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/arm-compute/quickstart-templates/aliases.json',
vm_image_alias_doc='https://azcliprod.blob.core.windows.net/cli/vm/aliases.json',
media_resource_id='https://rest.media.azure.net',
ossrdbms_resource_id='https://ossrdbms-aad.database.windows.net',
app_insights_resource_id='https://api.applicationinsights.io',
Expand Down Expand Up @@ -410,7 +410,7 @@ class CloudNameEnum: # pylint: disable=too-few-public-methods
active_directory_resource_id='https://management.core.chinacloudapi.cn/',
active_directory_graph_resource_id='https://graph.chinacloudapi.cn/',
microsoft_graph_resource_id='https://microsoftgraph.chinacloudapi.cn',
vm_image_alias_doc='https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/arm-compute/quickstart-templates/aliases.json',
vm_image_alias_doc='https://azcliprod.blob.core.windows.net/cli/vm/aliases.json',
media_resource_id='https://rest.media.chinacloudapi.cn',
ossrdbms_resource_id='https://ossrdbms-aad.database.chinacloudapi.cn',
app_insights_resource_id='https://api.applicationinsights.azure.cn',
Expand Down Expand Up @@ -444,7 +444,7 @@ class CloudNameEnum: # pylint: disable=too-few-public-methods
active_directory_resource_id='https://management.core.usgovcloudapi.net/',
active_directory_graph_resource_id='https://graph.microsoftazure.us/',
microsoft_graph_resource_id='https://graph.microsoft.us/',
vm_image_alias_doc='https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/arm-compute/quickstart-templates/aliases.json',
vm_image_alias_doc='https://azcliprod.blob.core.windows.net/cli/vm/aliases.json',
media_resource_id='https://rest.media.usgovcloudapi.net',
ossrdbms_resource_id='https://ossrdbms-aad.database.usgovcloudapi.net',
app_insights_resource_id='https://api.applicationinsights.us',
Expand Down Expand Up @@ -479,7 +479,7 @@ class CloudNameEnum: # pylint: disable=too-few-public-methods
active_directory_resource_id='https://management.core.cloudapi.de/',
active_directory_graph_resource_id='https://graph.cloudapi.de/',
microsoft_graph_resource_id='https://graph.microsoft.de',
vm_image_alias_doc='https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/arm-compute/quickstart-templates/aliases.json',
vm_image_alias_doc='https://azcliprod.blob.core.windows.net/cli/vm/aliases.json',
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

All four Azure cloud configurations (AZURE_PUBLIC_CLOUD, AZURE_CHINA_CLOUD, AZURE_US_GOV_CLOUD, AZURE_GERMAN_CLOUD) are configured to use the same blob storage URL (azcliprod.blob.core.windows.net). This could be problematic for sovereign clouds like Azure China and Azure US Government, which typically have network isolation from public Azure. Consider verifying whether sovereign clouds need to use region-specific blob storage URLs (e.g., azcliprod.blob.core.chinacloudapi.cn for China, azcliprod.blob.core.usgovcloudapi.net for US Gov) to maintain their network isolation requirements.

Suggested change
vm_image_alias_doc='https://azcliprod.blob.core.windows.net/cli/vm/aliases.json',
vm_image_alias_doc='https://azcliprod.blob.core.cloudapi.de/cli/vm/aliases.json',

Copilot uses AI. Check for mistakes.
media_resource_id='https://rest.media.cloudapi.de',
ossrdbms_resource_id='https://ossrdbms-aad.database.cloudapi.de',
portal='https://portal.microsoftazure.de'),
Expand Down
55 changes: 45 additions & 10 deletions src/azure-cli-core/azure/cli/core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@
"sys", "test2", "test3", "user4", "user5"
]

# AME Storage Account URL for version checking and VM image aliases (Network Isolation)
# Files are stored as:
# - https://azcliprod.blob.core.windows.net/cli/{package}/setup.py (CLI versions)
# - https://azcliprod.blob.core.windows.net/cli/vm/aliases.json (VM image aliases)
AME_STORAGE_BASE_URL = "https://azcliprod.blob.core.windows.net/cli"
Comment on lines +55 to +59
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

The acronym "AME" is not defined in the comment. This makes the code less maintainable and could confuse developers who are not familiar with this internal Azure term. Consider either spelling out the full name (e.g., "Azure Managed Environment" or the actual service name) or adding a brief explanation of what AME stands for in the comment.

Copilot uses AI. Check for mistakes.


def handle_exception(ex): # pylint: disable=too-many-locals, too-many-statements, too-many-branches
# For error code, follow guidelines at https://docs.python.org/2/library/sys.html#sys.exit,
Expand Down Expand Up @@ -291,14 +297,23 @@ def __init__(self, key, version):
]


def get_latest_from_github(package_path='azure-cli'):
def get_latest_version_from_ame_storage(package_path='azure-cli'):
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

The naming convention is inconsistent with the existing codebase. The function is named "get_latest_version_from_ame_storage" but the constant is "AME_STORAGE_BASE_URL". For clarity and maintainability, consider using a more descriptive name like "get_latest_version_from_azure_storage" or "get_latest_version_from_blob_storage" that doesn't rely on the internal acronym "AME".

Copilot uses AI. Check for mistakes.
"""Get the latest version from AME Storage Account.

This replaces get_latest_from_github() due to network isolation requirements.
The setup.py files are uploaded to AME Storage Account during release pipeline.

Args:
package_path: Package name, e.g., 'azure-cli', 'azure-cli-core', 'azure-cli-telemetry', 'azure-cli-testsdk'
"""
try:
import requests
git_url = "https://raw.githubusercontent.com/Azure/azure-cli/main/src/{}/setup.py".format(package_path)
response = requests.get(git_url, timeout=10)
storage_url = "{}/{}/setup.py".format(AME_STORAGE_BASE_URL, package_path)

response = requests.get(storage_url, timeout=10)
if response.status_code != 200:
logger.info("Failed to fetch the latest version from '%s' with status code '%s' and reason '%s'",
git_url, response.status_code, response.reason)
storage_url, response.status_code, response.reason)
return None
for line in response.iter_lines():
txt = line.decode('utf-8', errors='ignore')
Expand All @@ -307,16 +322,28 @@ def get_latest_from_github(package_path='azure-cli'):
if match:
return match.group(1)
except Exception as ex: # pylint: disable=broad-except
logger.info("Failed to get the latest version from '%s'. %s", git_url, str(ex))
logger.info("Failed to get the latest version from '%s'. %s", storage_url, str(ex))
return None


def _update_latest_from_github(versions):
if not check_connectivity(url='https://raw.githubusercontent.com', max_retries=0):
def get_latest_from_github(package_path='azure-cli'):
"""Deprecated: Use get_latest_version_from_ame_storage() instead.

This function is kept for backward compatibility but now reads from AME Storage Account.
"""
return get_latest_version_from_ame_storage(package_path)


def _update_latest_from_ame_storage(versions):
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

The naming convention is inconsistent with the existing codebase. The function is named "_update_latest_from_ame_storage" but uses an internal acronym "AME". For clarity and maintainability, consider using a more descriptive name like "_update_latest_from_azure_storage" or "_update_latest_from_blob_storage" that doesn't rely on the internal acronym "AME".

Copilot uses AI. Check for mistakes.
"""Update versions from AME Storage Account.

This replaces _update_latest_from_github() due to network isolation requirements.
"""
if not check_connectivity(url=AME_STORAGE_BASE_URL, max_retries=0):
return versions, False
success = True
for pkg in ['azure-cli-core', 'azure-cli-telemetry']:
version = get_latest_from_github(pkg)
version = get_latest_version_from_ame_storage(pkg)
if not version:
success = False
else:
Expand All @@ -328,6 +355,14 @@ def _update_latest_from_github(versions):
return versions, success


def _update_latest_from_github(versions):
"""Deprecated: Use _update_latest_from_ame_storage() instead.

This function is kept for backward compatibility but now reads from AME Storage Account.
"""
return _update_latest_from_ame_storage(versions)


def get_cached_latest_versions(versions=None):
""" Get the latest versions from a cached file"""
import datetime
Expand All @@ -343,7 +378,7 @@ def get_cached_latest_versions(versions=None):
if cache_versions and cache_versions['azure-cli']['local'] == versions['azure-cli']['local']:
return cache_versions.copy(), True

versions, success = _update_latest_from_github(versions)
versions, success = _update_latest_from_ame_storage(versions)
VERSIONS['versions'] = versions
VERSIONS[_VERSION_UPDATE_TIME] = str(datetime.datetime.now())
return versions.copy(), success
Expand All @@ -369,7 +404,7 @@ def get_az_version_string(use_cache=False): # pylint: disable=too-many-statemen
versions = _get_local_versions()

# get the versions from pypi
versions, success = get_cached_latest_versions(versions) if use_cache else _update_latest_from_github(versions)
versions, success = get_cached_latest_versions(versions) if use_cache else _update_latest_from_ame_storage(versions)
updates_available_components = []

def _print(val=''):
Expand Down
4 changes: 2 additions & 2 deletions src/azure-cli/azure/cli/command_modules/util/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ def upgrade_version(cmd, update_all=None, yes=None, allow_preview=None): # pyli
from packaging.version import parse

update_cli = True
from azure.cli.core.util import get_latest_from_github
latest_version = get_latest_from_github()
from azure.cli.core.util import get_latest_version_from_ame_storage
latest_version = get_latest_version_from_ame_storage()
if not latest_version:
logger.warning("Failed to get the latest azure-cli version.")
update_cli = False
Expand Down
Loading