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
4 changes: 4 additions & 0 deletions src/machinelearningservices/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2026-09-10

### Azure Machine Learning CLI (v2) v 2.45.0

## 2026-07-16

### Azure Machine Learning CLI (v2) v 2.44.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ def cf_ml_cl(cli_ctx, *_):
from azext_mlv2.manual.custom.utils import _get_cloud_information_from_cli

# the client used here doesn't matter since it isn't used by any command
from azure.ai.ml._restclient.v2022_02_01_preview import AzureMachineLearningWorkspaces
from azure.ai.ml._restclient.arm_ml_service import MachineLearningServicesMgmtClient
from azure.cli.core.commands.client_factory import get_mgmt_service_client

kwargs = _get_cloud_information_from_cli(cli_ctx=cli_ctx)
return get_mgmt_service_client(cli_ctx, AzureMachineLearningWorkspaces, **kwargs)
return get_mgmt_service_client(cli_ctx, MachineLearningServicesMgmtClient, **kwargs)
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from azure.ai.ml.entities._deployment.batch_deployment import BatchDeployment
from azure.ai.ml.entities._deployment.model_batch_deployment import ModelBatchDeployment
from azure.ai.ml.entities._deployment.pipeline_component_batch_deployment import PipelineComponentBatchDeployment
from azure.ai.ml.entities._component.pipeline_component import PipelineComponent
from azure.ai.ml.entities._load_functions import (
load_batch_deployment, _try_load_yaml_dict, load_pipeline_component_batch_deployment,
load_model_batch_deployment
Expand Down Expand Up @@ -60,6 +61,12 @@ def ml_batch_deployment_create(
else:
deployment = load_batch_deployment(source=file, params_override=params_override)

if isinstance(deployment, PipelineComponentBatchDeployment) and isinstance(
deployment.component, PipelineComponent
):
registered_component = ml_client.components.create_or_update(deployment.component)
deployment.component = registered_component.id

deployment_result = ml_client.begin_create_or_update(
entity=deployment, skip_script_validation=skip_script_validation
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def ml_batch_endpoint_show(cmd, resource_group_name, workspace_name, name):

try:
endpoint = ml_client.batch_endpoints.get(name=name)
return endpoint.dump()
return _dump_entity_with_warnings(endpoint)
except Exception as err: # pylint: disable=broad-exception-caught
log_and_raise_error(err, debug)

Expand Down
13 changes: 12 additions & 1 deletion src/machinelearningservices/azext_mlv2/manual/custom/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,18 @@ def ml_compute_list_nodes(cmd, resource_group_name, workspace_name, name):

try:
nodes = ml_client.compute.list_nodes(name=name)
return [_dump_entity_with_warnings(x) for x in nodes]
results = []
for node in nodes:
for rest_name, entity_name in (
("nodeId", "node_id"),
("nodeState", "node_state"),
("privateIpAddress", "private_ip_address"),
("publicIpAddress", "public_ip_address"),
):
if getattr(node, entity_name, None) is None and hasattr(node, rest_name):
setattr(node, entity_name, getattr(node, rest_name))
results.append(_dump_entity_with_warnings(node))
return results
except Exception as err: # pylint: disable=broad-exception-caught
log_and_raise_error(err, debug)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .raise_error import log_and_raise_error
from .utils import (
_dump_entity_with_warnings,
_normalize_enum_values,
convert_str_to_dict,
get_ml_client,
is_not_found_error,
Expand All @@ -38,7 +39,7 @@ def ml_online_endpoint_show(cmd, resource_group_name, workspace_name, name, loca
endpoint = ml_client.online_endpoints.get(name=name, local=local)
if web:
open_online_endpoint_in_browser(endpoint)
return endpoint.dump()
return _normalize_enum_values(endpoint.dump())
except Exception as err: # pylint: disable=broad-exception-caught
log_and_raise_error(err, debug)

Expand Down Expand Up @@ -137,7 +138,7 @@ def ml_online_endpoint_create(
if isinstance(endpoint, OnlineEndpoint):
if web:
open_online_endpoint_in_browser(endpoint)
return endpoint.dump()
return _normalize_enum_values(endpoint.dump())
except Exception as err: # pylint: disable=broad-exception-caught
yaml_operation = bool(file)
log_and_raise_error(err, debug, yaml_operation=yaml_operation)
Expand Down Expand Up @@ -268,7 +269,7 @@ def ml_online_endpoint_update(
if isinstance(endpoint_return, OnlineEndpoint):
if web:
open_online_endpoint_in_browser(endpoint_return)
return endpoint_return.dump()
return _normalize_enum_values(endpoint_return.dump())
return endpoint_return

except Exception as err: # pylint: disable=broad-exception-caught
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from marshmallow import EXCLUDE

from azure.ai.ml._restclient.v2022_10_01_preview.models import ScheduleListViewType
from azure.ai.ml._restclient.arm_ml_service.models import ScheduleListViewType
from azure.ai.ml.entities import JobSchedule, Schedule
from azure.ai.ml.entities._load_functions import load_schedule
from azure.cli.core.commands import LongRunningOperation
Expand Down
33 changes: 25 additions & 8 deletions src/machinelearningservices/azext_mlv2/manual/custom/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import re
import sys
import traceback
from enum import Enum
from os import environ, getenv, pardir, path
from typing import Dict, Tuple, Union
from uuid import uuid4
Expand All @@ -20,8 +21,7 @@
from azext_mlv2.manual.user_agent import USER_AGENT
from azure.ai.ml import MLClient
from azure.ai.ml._azure_environments import _environments, _get_aml_resource_id_from_metadata, _get_default_cloud_name
from azure.ai.ml._restclient.v2020_09_01_dataplanepreview.models import BatchJobResource
from azure.ai.ml._restclient.v2022_02_01_preview.models import ListViewType
from azure.ai.ml._restclient.arm_ml_service.models import EndpointProvisioningState, ListViewType
from azure.ai.ml._utils._storage_utils import AzureMLDatastorePathUri
from azure.ai.ml.constants._common import (
ARM_ID_PREFIX,
Expand Down Expand Up @@ -56,6 +56,18 @@
module_logger = get_logger(__name__)


def _normalize_enum_values(value):
if isinstance(value, Enum):
return value.value
if isinstance(value, str) and value.startswith("EndpointProvisioningState."):
return EndpointProvisioningState[value.rsplit(".", 1)[1]].value
if isinstance(value, dict):
return {key: _normalize_enum_values(item) for key, item in value.items()}
if isinstance(value, list):
return [_normalize_enum_values(item) for item in value]
return value


def _dump_entity_with_warnings(entity) -> Dict:
if not entity:
return
Expand All @@ -65,10 +77,15 @@ def _dump_entity_with_warnings(entity) -> Dict:
return entity
try:
if entity.__class__.__name__ == "ComponentContainerData" or isinstance(
entity, (BatchJobResource, AzureOpenAIDeployment, ServerlessEndpoint, MarketplaceSubscription)
entity, (AzureOpenAIDeployment, ServerlessEndpoint, MarketplaceSubscription)
):
return entity.as_dict()
return entity._to_dict() # type: ignore # pylint: disable=protected-access
result = entity._to_dict() # type: ignore # pylint: disable=protected-access
for key in result:
source_value = getattr(entity, key, None)
if isinstance(source_value, Enum) and result[key] == str(source_value):
result[key] = source_value.value
return _normalize_enum_values(result)
except Exception as err: # pylint: disable=broad-exception-caught
module_logger.warning("Failed to deserialize response: %s", str(err))
module_logger.warning(str(entity))
Expand Down Expand Up @@ -286,14 +303,14 @@ def deep_get(d, keys, default=None):
return deep_get(d.get(keys[0]), keys[1:], default)


def get_list_view_type(include_archived: bool, archived_only: bool) -> ListViewType:
def get_list_view_type(include_archived: bool, archived_only: bool) -> str:
if include_archived and archived_only:
raise ValueError("Cannot provide both archived-only and include-archived.")
if include_archived:
return ListViewType.ALL
return ListViewType.ALL.value
if archived_only:
return ListViewType.ARCHIVED_ONLY
return ListViewType.ACTIVE_ONLY
return ListViewType.ARCHIVED_ONLY.value
return ListViewType.ACTIVE_ONLY.value


def is_env_var_enabled(env_var_name):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ cryptography
docker
azure-mgmt-resourcegraph<9.0.0,>=2.0.0
azure-identity==1.17.1
azure-ai-ml==1.34.1
azure-ai-ml==1.35.0
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,20 @@ interactions:
status:
code: 202
message: Accepted
- request:
body: null
headers:
Accept:
- '*/*'
method: GET
uri: https://eastus.api.azureml.ms/assetstore/v1.0/operations/plehAJZmdj8SBaSvvKkepBA_sjIcKOy85D5N0A1GDlQ
response:
body:
string: '{"assetId": "azureml://registries/dsvm-test/components/batchscore/versions/1.0.12"}'
headers:
content-type:
- application/json; charset=utf-8
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,20 @@ interactions:
status:
code: 202
message: Accepted
- request:
body: null
headers:
Accept:
- '*/*'
method: GET
uri: https://eastus.api.azureml.ms/assetstore/v1.0/operations/BeG3dl8uh0m7gRg3oZ0yotIxu7GLCAYN1xu7dClX8j4
response:
body:
string: '{"assetId": "azureml://registries/dsvm-test/components/batchscore/versions/1.0.12"}'
headers:
content-type:
- application/json; charset=utf-8
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,20 @@ interactions:
status:
code: 202
message: Accepted
- request:
body: null
headers:
Accept:
- '*/*'
method: GET
uri: https://eastus2.api.azureml.ms/environment/v1.0/operations/kchawla-reg_kchawla-env_1_2c1fde67-ab6a-442a-b634-0ab237a166c0
response:
body:
string: ''
headers:
content-length:
- '0'
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,20 @@ interactions:
status:
code: 202
message: Accepted
- request:
body: null
headers:
Accept:
- '*/*'
method: GET
uri: https://eastus.api.azureml.ms/assetstore/v1.0/operations/i3I_xeObAEBWXwGMxgflTJY0oxPP3TzNubj3LcUGvXk
response:
body:
string: '{"assetId": "azureml://registries/dsvm-test/models/model_version_e2e/versions/1"}'
headers:
content-type:
- application/json; charset=utf-8
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,20 @@ interactions:
status:
code: 202
message: Accepted
- request:
body: null
headers:
Accept:
- '*/*'
method: GET
uri: https://eastus.api.azureml.ms/assetstore/v1.0/operations/i3I_xeObAEBWXwGMxgflTJY0oxPP3TzNubj3LcUGvXk
response:
body:
string: '{"assetId": "azureml://registries/dsvm-test/models/model_version_e2e/versions/1"}'
headers:
content-type:
- application/json; charset=utf-8
status:
code: 200
message: OK
version: 1
Loading
Loading