Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a8d9b69
[refractor] - Migrated 'az vm identity show' command
william051200 Dec 15, 2025
3656c4d
[Refractor] - Refractored show_vm_dentity function and migrated get_v…
william051200 Dec 16, 2025
f5713df
[Refractor] - Migrated assign_vm_identity function
william051200 Dec 16, 2025
8feec2f
[Refractor] - Preserve old function to avoid breaking change, updated…
william051200 Dec 16, 2025
c59e5b0
[Refractor] - Refractored assign_identity_helper function
william051200 Dec 16, 2025
98bbdc3
[Refractor] - Edit so the response is same as original when identity …
william051200 Dec 16, 2025
10a93e5
[refractor] - Added handling to assign_vm_identity function
william051200 Dec 18, 2025
f15d418
[Refractor] - Migrated remove_vm_identity function
william051200 Dec 19, 2025
7877ad2
[Refractor] - Edited function name
william051200 Dec 19, 2025
e27e2a8
[style] - Update code styling
william051200 Dec 19, 2025
4c4a933
[style] - Update code styling
william051200 Dec 21, 2025
e11748b
[test] - fixed test_vm_explicit_msi test case
william051200 Dec 23, 2025
d2810fb
[style] - Update code styling
william051200 Dec 23, 2025
8e30afc
[style] - Update code styling
william051200 Dec 23, 2025
68d9c93
[style] - Update code styling
william051200 Dec 23, 2025
f1f2b55
[test] - Added handling to vm create and vmss create command
william051200 Dec 23, 2025
886114c
[Refractor] - Resolve copilot suggestion
william051200 Dec 23, 2025
5b3b87a
Add recording for test_vm_msi
ReaNAiveD Dec 23, 2025
02fc214
[Fix] - Fixed import show function
william051200 Dec 23, 2025
fdd77aa
[Test] - Re-record test case
william051200 Dec 23, 2025
c00181d
[style] - Update code styling
william051200 Dec 23, 2025
1de58c9
[Fix] - Fixed import patch function
william051200 Dec 23, 2025
f247a1d
[Fix] - Added handling when assigning vm identities
william051200 Dec 23, 2025
3ca71b2
[Fix] - Fixed schema output issue
william051200 Dec 24, 2025
780e27d
[Test] - Fixed test case failure and re-record test case
william051200 Dec 24, 2025
7e32359
[Test] - Re-record test case
william051200 Dec 26, 2025
7534018
Removed unused parameter in commands.py
william051200 Dec 30, 2025
50d5c29
Refractor assign_vm_identity in custom.py
william051200 Dec 31, 2025
0d212dc
Refractor code
william051200 Dec 31, 2025
8afcf50
Fix refractored code bug
william051200 Dec 31, 2025
5f86537
Removed redundant lines
william051200 Dec 31, 2025
1e9141b
Removed redundant import
william051200 Dec 31, 2025
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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def __init__(self, name_prefix=sqlvm_name_prefix, location='westus',
def create_resource(self, name, **kwargs):
group = self._get_resource_group(**kwargs)
template = ('az vm create -l {} -g {} -n {} --admin-username {} --admin-password {} --image {}'
' --size Standard_DS2_v2 --nsg-rule NONE')
' --size Standard_B2ms --nsg-rule NONE')
execute(DummyCli(), template.format(self.location, group, name, self.vm_user, self.vm_password, self.image))
return {self.parameter_name: name}

Expand Down
91 changes: 84 additions & 7 deletions src/azure-cli/azure/cli/command_modules/vm/_vm_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
import os
import re
import importlib
from enum import Enum

from urllib.parse import urlparse

from azure.cli.core.commands.arm import ArmTemplateBuilder
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azure.cli.core.profiles import ResourceType, get_sdk

from knack.log import get_logger
from knack.util import CLIError
Expand All @@ -32,7 +35,7 @@ def get_target_network_api(cli_ctx):
if cli_ctx.cloud.profile == 'latest':
version = '2022-01-01'
else:
from azure.cli.core.profiles import get_api_version, ResourceType
from azure.cli.core.profiles import get_api_version
version = get_api_version(cli_ctx, ResourceType.MGMT_NETWORK)
return version

Expand All @@ -46,8 +49,6 @@ def read_content_if_is_file(string_or_file):


def _resolve_api_version(cli_ctx, provider_namespace, resource_type, parent_path):
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azure.cli.core.profiles import ResourceType
client = get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES)
provider = client.providers.get(provider_namespace)

Expand Down Expand Up @@ -75,10 +76,8 @@ def log_pprint_template(template):
def check_existence(cli_ctx, value, resource_group, provider_namespace, resource_type,
parent_name=None, parent_type=None, static_version=None):
# check for name or ID and set the type flags
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azure.core.exceptions import HttpResponseError
from azure.mgmt.core.tools import parse_resource_id
from azure.cli.core.profiles import ResourceType
id_parts = parse_resource_id(value)
resource_client = get_mgmt_service_client(cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES,
subscription_id=id_parts.get('subscription', None)).resources
Expand Down Expand Up @@ -414,8 +413,6 @@ def _update(model, lun, value):


def get_storage_blob_uri(cli_ctx, storage):
from azure.cli.core.profiles._shared import ResourceType
from azure.cli.core.commands.client_factory import get_mgmt_service_client
if urlparse(storage).scheme:
storage_uri = storage
else:
Expand Down Expand Up @@ -757,3 +754,83 @@ def _open(filename, mode):
f.write(public_bytes)

return public_bytes.decode()


def _gen_guid():
import uuid
return uuid.uuid4()


def assign_identity(cli_ctx, getter, setter, identity_role=None, identity_scope=None):
import time
from azure.core.exceptions import HttpResponseError

# get
resource = getter()
resource = setter(resource)

# create role assignment:
if identity_scope:
principal_id = resource.get('identity', {}).get('principalId') or resource.get('identity', {}).get('principal_id')

identity_role_id = resolve_role_id(cli_ctx, identity_role, identity_scope)
assignments_client = get_mgmt_service_client(cli_ctx, ResourceType.MGMT_AUTHORIZATION).role_assignments
RoleAssignmentCreateParameters = get_sdk(cli_ctx, ResourceType.MGMT_AUTHORIZATION,
'RoleAssignmentCreateParameters', mod='models',
operation_group='role_assignments')
parameters = RoleAssignmentCreateParameters(role_definition_id=identity_role_id, principal_id=principal_id,
principal_type=None)

logger.info("Creating an assignment with a role '%s' on the scope of '%s'", identity_role_id, identity_scope)
retry_times = 36
assignment_name = _gen_guid()
for retry_time in range(0, retry_times):
try:
assignments_client.create(scope=identity_scope, role_assignment_name=assignment_name,
parameters=parameters)
break
except HttpResponseError as ex:
if ex.error.code == 'RoleAssignmentExists':
logger.info('Role assignment already exists')
break
if retry_time < retry_times and ' does not exist in the directory ' in ex.message:
time.sleep(5)
logger.warning('Retrying role assignment creation: %s/%s', retry_time + 1,
retry_times)
continue
raise
return resource


def resolve_role_id(cli_ctx, role, scope):
import uuid
client = get_mgmt_service_client(cli_ctx, ResourceType.MGMT_AUTHORIZATION).role_definitions

role_id = None
if re.match(r'/subscriptions/[^/]+/providers/Microsoft.Authorization/roleDefinitions/',
role, re.I):
role_id = role
else:
try:
uuid.UUID(role)
role_id = '/subscriptions/{}/providers/Microsoft.Authorization/roleDefinitions/{}'.format(
client.config.subscription_id, role)
except ValueError:
pass
if not role_id: # retrieve role id
role_defs = list(client.list(scope, "roleName eq '{}'".format(role)))
if not role_defs:
raise CLIError("Role '{}' doesn't exist.".format(role))
if len(role_defs) > 1:
ids = [r.id for r in role_defs]
err = "More than one role matches the given name '{}'. Please pick an id from '{}'"
raise CLIError(err.format(role, ids))
role_id = role_defs[0].id
return role_id


class IdentityType(Enum):
SYSTEM_ASSIGNED = 'SystemAssigned'
USER_ASSIGNED = 'UserAssigned'
SYSTEM_ASSIGNED_USER_ASSIGNED = 'SystemAssigned, UserAssigned'
NONE = 'None'
9 changes: 5 additions & 4 deletions src/azure-cli/azure/cli/command_modules/vm/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,12 @@ def load_command_table(self, _):
from .operations.snapshot import SnapshotUpdate
self.command_table['snapshot update'] = SnapshotUpdate(loader=self)

with self.command_group('vm', compute_vm_sdk) as g:
g.custom_command('identity assign', 'assign_vm_identity', validator=process_assign_identity_namespace)
g.custom_command('identity remove', 'remove_vm_identity', validator=process_remove_identity_namespace, min_api='2017-12-01')
g.custom_show_command('identity show', 'show_vm_identity')
with self.command_group('vm identity') as g:
g.custom_command('assign', 'assign_vm_identity', validator=process_assign_identity_namespace)
g.custom_command('remove', 'remove_vm_identity', validator=process_remove_identity_namespace, min_api='2017-12-01')
g.custom_show_command('show', 'show_vm_identity')

with self.command_group('vm', compute_vm_sdk) as g:
g.custom_command('application set', 'set_vm_applications', validator=process_set_applications_namespace, min_api='2021-07-01')
g.custom_command('application list', 'list_vm_applications', min_api='2021-07-01')

Expand Down
Loading
Loading