From a2a517d1934279917df78747395fa1909056fd22 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Jul 2026 06:15:01 +0000 Subject: [PATCH 1/9] Isolate online endpoint/deployment workspace scope for registry-backed clients Co-authored-by: Chakradhar886 <259224138+Chakradhar886@users.noreply.github.com> --- sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py | 33 ++++++- .../unittests/test_ml_client.py | 91 +++++++++++++++++++ 2 files changed, 119 insertions(+), 5 deletions(-) diff --git a/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py b/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py index e227029d10e5..8bd5824aaccc 100644 --- a/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py +++ b/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py @@ -223,6 +223,7 @@ def __init__( workspace_location = None workspace_id = None registry_reference = kwargs.pop("registry_reference", None) + workspace_reference = kwargs.pop("workspace_reference", None) if registry_name or registry_reference: # get the workspace location here if workspace_reference is provided self._ws_operation_scope = OperationScope( @@ -230,7 +231,6 @@ def __init__( str(resource_group_name), workspace_name, ) - workspace_reference = kwargs.pop("workspace_reference", None) if workspace_reference or registry_reference: ws_ops = WorkspaceOperations( OperationScope(str(subscription_id), str(resource_group_name), workspace_reference), @@ -273,6 +273,17 @@ def __init__( workspace_id, workspace_location, ) + self._online_operation_scope = ( + OperationScope( + self._ws_operation_scope.subscription_id, + self._ws_operation_scope.resource_group_name, + workspace_name, + workspace_id=workspace_id, + workspace_location=workspace_location, + ) + if workspace_reference or registry_reference + else self._operation_scope + ) # Cannot send multiple base_url as azure-cli sets the base_url automatically. kwargs.pop("base_url", None) @@ -319,6 +330,12 @@ def __init__( base_url=base_url, **kwargs, ) + self._service_client_02_2022_preview_online = ServiceClient022022Preview( + subscription_id=self._online_operation_scope._subscription_id, + credential=self._credential, + base_url=base_url, + **kwargs, + ) self._service_client_05_2022 = ServiceClient052022( credential=self._credential, @@ -420,6 +437,12 @@ def __init__( base_url=base_url, **kwargs, ) + self._service_client_04_2023_preview_online = ServiceClient042023Preview( + credential=self._credential, + subscription_id=self._online_operation_scope._subscription_id, + base_url=base_url, + **kwargs, + ) self._service_client_06_2023_preview = ServiceClient062023Preview( credential=self._credential, @@ -604,9 +627,9 @@ def __init__( self._local_endpoint_helper = _LocalEndpointHelper(requests_pipeline=self._requests_pipeline) self._local_deployment_helper = _LocalDeploymentHelper(self._operation_container) self._online_endpoints = OnlineEndpointOperations( - self._ws_operation_scope if registry_reference else self._operation_scope, + self._online_operation_scope, self._operation_config, - self._service_client_02_2022_preview, + self._service_client_02_2022_preview_online, self._operation_container, self._local_endpoint_helper, self._credential, @@ -625,9 +648,9 @@ def __init__( self._operation_container.add(AzureMLResourceType.BATCH_ENDPOINT, self._batch_endpoints) self._operation_container.add(AzureMLResourceType.ONLINE_ENDPOINT, self._online_endpoints) self._online_deployments = OnlineDeploymentOperations( - self._ws_operation_scope if registry_reference else self._operation_scope, + self._online_operation_scope, self._operation_config, - self._service_client_04_2023_preview, + self._service_client_04_2023_preview_online, self._operation_container, self._local_deployment_helper, self._credential, diff --git a/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py b/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py index aa7f3a55942f..181a09860a73 100644 --- a/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py +++ b/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py @@ -1,5 +1,6 @@ import logging import os +from contextlib import ExitStack from unittest import mock from unittest.mock import Mock, patch @@ -471,6 +472,96 @@ def test_ml_client_with_both_workspace_registry_names_throws( message = exception.value.args[0] assert message == "Both workspace_name and registry_name cannot be used together, for the ml_client." + def test_registry_backed_online_operations_keep_workspace_scope(self, mock_credential) -> None: + workspace_sub = "workspace-sub" + workspace_rg = "workspace-rg" + workspace_name = "workspace-name" + registry_sub = "registry-sub" + registry_rg = "registry-rg" + captured = {} + workspace_details = Mock(location="eastus", _workspace_id="workspace-id") + + def make_fake_operation(name): + class FakeOperation: + def __init__(self, *args, **kwargs): + captured[name] = { + "args": args, + "kwargs": kwargs, + "scope": args[0] if args else kwargs.get("operation_scope"), + } + + def get(self, *args, **kwargs): + return workspace_details + + return FakeOperation + + operation_names = [ + "WorkspaceOperations", + "WorkspaceOutboundRuleOperations", + "RegistryOperations", + "WorkspaceConnectionsOperations", + "CapabilityHostsOperations", + "ComputeOperations", + "DatastoreOperations", + "ModelOperations", + "EvaluatorOperations", + "CodeOperations", + "EnvironmentOperations", + "OnlineEndpointOperations", + "BatchEndpointOperations", + "OnlineDeploymentOperations", + "BatchDeploymentOperations", + "DeploymentTemplateOperations", + "DataOperations", + "ComponentOperations", + "JobOperations", + "ScheduleOperations", + "IndexOperations", + "FeatureStoreOperations", + "FeatureSetOperations", + "FeatureStoreEntityOperations", + "AzureOpenAIDeploymentOperations", + "ServerlessEndpointOperations", + "MarketplaceSubscriptionOperations", + ] + with ExitStack() as stack: + for operation_name in operation_names: + stack.enter_context(patch(f"azure.ai.ml._ml_client.{operation_name}", make_fake_operation(operation_name))) + + stack.enter_context(patch("azure.ai.ml._ml_client.get_deployments_operation", return_value=Mock())) + stack.enter_context( + patch( + "azure.ai.ml._ml_client.get_registry_client", + return_value=(Mock(), registry_rg, registry_sub, Mock(), Mock()), + ) + ) + + MLClient( + credential=mock_credential, + subscription_id=workspace_sub, + resource_group_name=workspace_rg, + registry_name="test-registry", + workspace_reference=workspace_name, + ) + + online_endpoint_scope = captured["OnlineEndpointOperations"]["scope"] + online_deployment_scope = captured["OnlineDeploymentOperations"]["scope"] + model_scope = captured["ModelOperations"]["scope"] + data_scope = captured["DataOperations"]["scope"] + + assert online_endpoint_scope.subscription_id == workspace_sub + assert online_endpoint_scope.resource_group_name == workspace_rg + assert online_endpoint_scope.workspace_name == workspace_name + assert online_deployment_scope.subscription_id == workspace_sub + assert online_deployment_scope.resource_group_name == workspace_rg + assert online_deployment_scope.workspace_name == workspace_name + assert model_scope.subscription_id == registry_sub + assert model_scope.resource_group_name == registry_rg + assert data_scope.subscription_id == registry_sub + assert data_scope.resource_group_name == registry_rg + assert online_endpoint_scope is not model_scope + assert online_deployment_scope is not data_scope + def test_ml_client_with_cli_config(self, mock_credential): # This cloud config should not work and it should NOT overwrite the hardcoded AzureCloud kwargs = { From d67cc1be09778dc695ed1bbc0f0a7f807640bc9d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Jul 2026 09:33:27 +0000 Subject: [PATCH 2/9] fix: apply black formatting to test_ml_client.py (wrap long line > 120 chars) Co-authored-by: Chakradhar886 <259224138+Chakradhar886@users.noreply.github.com> --- .../tests/internal_utils/unittests/test_ml_client.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py b/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py index 181a09860a73..16f7e2b33433 100644 --- a/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py +++ b/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py @@ -526,7 +526,9 @@ def get(self, *args, **kwargs): ] with ExitStack() as stack: for operation_name in operation_names: - stack.enter_context(patch(f"azure.ai.ml._ml_client.{operation_name}", make_fake_operation(operation_name))) + stack.enter_context( + patch(f"azure.ai.ml._ml_client.{operation_name}", make_fake_operation(operation_name)) + ) stack.enter_context(patch("azure.ai.ml._ml_client.get_deployments_operation", return_value=Mock())) stack.enter_context( From 15c70da2bce22e3607982f4da94c38ddf630a7e4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:16:30 +0000 Subject: [PATCH 3/9] address reviewer: fix guard, strengthen test, add CHANGELOG entry Co-authored-by: Chakradhar886 <259224138+Chakradhar886@users.noreply.github.com> --- sdk/ml/azure-ai-ml/CHANGELOG.md | 1 + sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py | 2 +- .../tests/internal_utils/unittests/test_ml_client.py | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/sdk/ml/azure-ai-ml/CHANGELOG.md b/sdk/ml/azure-ai-ml/CHANGELOG.md index 6a8f3dc71aaf..ad8544466221 100644 --- a/sdk/ml/azure-ai-ml/CHANGELOG.md +++ b/sdk/ml/azure-ai-ml/CHANGELOG.md @@ -5,6 +5,7 @@ ### Features Added ### Bugs Fixed +- Fixed registry-backed `MLClient` sending online endpoint/deployment calls to the registry's resource group instead of the workspace's, causing `ResourceNotFound` for cross-resource-group workspaces. - Fixed internal pipeline `Command` node dropping node-level interactive `services` (SSH, JupyterLab, TensorBoard, VS Code, etc.) during serialization, which prevented interactive endpoints from being created for Singularity jobs. The `services` are now serialized into the pipeline REST request and round-tripped on deserialization, matching the public `Command` node behavior. - Fixed `MLClient.jobs.create_or_update`, `archive`, and `restore` failing for previously-fetched jobs across all job types by routing metadata-only edits through the RunHistory PATCH endpoint. - Fixed `DeploymentTemplate.creation_context` always being `None` when retrieved via `get()` or `list()`. The created/modified timestamps and identity returned by the service (as `createdTime` / `modifiedTime` / `createdBy`) are now populated on `creation_context`, making `DeploymentTemplate` consistent with `Model` and `Environment`. diff --git a/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py b/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py index 8bd5824aaccc..9329b338e4ad 100644 --- a/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py +++ b/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py @@ -281,7 +281,7 @@ def __init__( workspace_id=workspace_id, workspace_location=workspace_location, ) - if workspace_reference or registry_reference + if registry_name or registry_reference else self._operation_scope ) diff --git a/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py b/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py index 16f7e2b33433..72e6cdef9844 100644 --- a/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py +++ b/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py @@ -548,9 +548,13 @@ def get(self, *args, **kwargs): online_endpoint_scope = captured["OnlineEndpointOperations"]["scope"] online_deployment_scope = captured["OnlineDeploymentOperations"]["scope"] + online_endpoint_client = captured["OnlineEndpointOperations"]["args"][2] + online_deployment_client = captured["OnlineDeploymentOperations"]["args"][2] model_scope = captured["ModelOperations"]["scope"] data_scope = captured["DataOperations"]["scope"] + assert online_endpoint_client._config.subscription_id == workspace_sub + assert online_deployment_client._config.subscription_id == workspace_sub assert online_endpoint_scope.subscription_id == workspace_sub assert online_endpoint_scope.resource_group_name == workspace_rg assert online_endpoint_scope.workspace_name == workspace_name From 64ac85e2383ad81449181d016e5dc3c38c5ac2fc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Aug 2026 12:08:31 +0000 Subject: [PATCH 4/9] Fix consistency check: update parserVersion in api.metadata.yml for azure-ai-ml Co-authored-by: Chakradhar886 <259224138+Chakradhar886@users.noreply.github.com> --- sdk/ml/azure-ai-ml/api.metadata.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/ml/azure-ai-ml/api.metadata.yml b/sdk/ml/azure-ai-ml/api.metadata.yml index 1ddd7ebc1983..ed2c4383a3f9 100644 --- a/sdk/ml/azure-ai-ml/api.metadata.yml +++ b/sdk/ml/azure-ai-ml/api.metadata.yml @@ -1,3 +1,3 @@ apiMdSha256: 4af4d65ad5c624b35aefa8442a07cb8cb147fe1dcbab6aa993625728a4a04de1 -parserVersion: 0.3.30 +parserVersion: 0.3.31 pythonVersion: 3.12.13 From b5877b4da01a07f25142a74007e5f99b92e05e71 Mon Sep 17 00:00:00 2001 From: chakradhar886 Date: Thu, 13 Aug 2026 22:25:27 +0530 Subject: [PATCH 5/9] Add cross-resource-group registry deployment coverage --- sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py | 2 +- sdk/ml/azure-ai-ml/tests/conftest.py | 14 +++++++++++ .../unittests/test_ml_client.py | 8 ++---- .../e2etests/test_online_deployment.py | 25 +++++++++++-------- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py b/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py index 9329b338e4ad..9a47bdfe16a7 100644 --- a/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py +++ b/sdk/ml/azure-ai-ml/azure/ai/ml/_ml_client.py @@ -223,7 +223,6 @@ def __init__( workspace_location = None workspace_id = None registry_reference = kwargs.pop("registry_reference", None) - workspace_reference = kwargs.pop("workspace_reference", None) if registry_name or registry_reference: # get the workspace location here if workspace_reference is provided self._ws_operation_scope = OperationScope( @@ -231,6 +230,7 @@ def __init__( str(resource_group_name), workspace_name, ) + workspace_reference = kwargs.pop("workspace_reference", None) if workspace_reference or registry_reference: ws_ops = WorkspaceOperations( OperationScope(str(subscription_id), str(resource_group_name), workspace_reference), diff --git a/sdk/ml/azure-ai-ml/tests/conftest.py b/sdk/ml/azure-ai-ml/tests/conftest.py index 1c6dd80d429e..1032f787b08a 100644 --- a/sdk/ml/azure-ai-ml/tests/conftest.py +++ b/sdk/ml/azure-ai-ml/tests/conftest.py @@ -485,6 +485,20 @@ def sdkv2_registry_client(e2e_ws_scope: OperationScope, auth: ClientSecretCreden ) +@pytest.fixture +def registry_backed_client(e2e_ws_scope: OperationScope, auth: ClientSecretCredential) -> MLClient: + """Return a registry-backed client whose online operations target the test workspace.""" + return MLClient( + credential=auth, + subscription_id=e2e_ws_scope.subscription_id, + resource_group_name=e2e_ws_scope.resource_group_name, + workspace_name=e2e_ws_scope.workspace_name, + registry_reference="sdkv2-testFeed", + logging_enable=getenv(E2E_TEST_LOGGING_ENABLED), + cloud="AzureCloud", + ) + + @pytest.fixture def only_registry_client(e2e_ws_scope: OperationScope, auth: ClientSecretCredential) -> MLClient: """return a machine learning client using default e2e testing workspace""" diff --git a/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py b/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py index 72e6cdef9844..371ee9ac895e 100644 --- a/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py +++ b/sdk/ml/azure-ai-ml/tests/internal_utils/unittests/test_ml_client.py @@ -542,8 +542,8 @@ def get(self, *args, **kwargs): credential=mock_credential, subscription_id=workspace_sub, resource_group_name=workspace_rg, - registry_name="test-registry", - workspace_reference=workspace_name, + workspace_name=workspace_name, + registry_reference="test-registry", ) online_endpoint_scope = captured["OnlineEndpointOperations"]["scope"] @@ -551,7 +551,6 @@ def get(self, *args, **kwargs): online_endpoint_client = captured["OnlineEndpointOperations"]["args"][2] online_deployment_client = captured["OnlineDeploymentOperations"]["args"][2] model_scope = captured["ModelOperations"]["scope"] - data_scope = captured["DataOperations"]["scope"] assert online_endpoint_client._config.subscription_id == workspace_sub assert online_deployment_client._config.subscription_id == workspace_sub @@ -563,10 +562,7 @@ def get(self, *args, **kwargs): assert online_deployment_scope.workspace_name == workspace_name assert model_scope.subscription_id == registry_sub assert model_scope.resource_group_name == registry_rg - assert data_scope.subscription_id == registry_sub - assert data_scope.resource_group_name == registry_rg assert online_endpoint_scope is not model_scope - assert online_deployment_scope is not data_scope def test_ml_client_with_cli_config(self, mock_credential): # This cloud config should not work and it should NOT overwrite the hardcoded AzureCloud diff --git a/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py b/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py index 6319cf7b92f3..b4aec10e006b 100644 --- a/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py +++ b/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py @@ -4,6 +4,7 @@ from devtools_testutils import AzureRecordedTestCase from pathlib import Path from azure.ai.ml import MLClient, load_online_deployment, load_online_endpoint, load_model +from azure.ai.ml._scope_dependent_operations import OperationScope from azure.ai.ml.entities import ManagedOnlineDeployment, ManagedOnlineEndpoint, Model, CodeConfiguration, Environment @@ -52,16 +53,18 @@ def test_online_deployment_create( def test_online_deployment_create_when_registry_assets( self, - sdkv2_registry_client: MLClient, - client: MLClient, + registry_backed_client: MLClient, + e2e_ws_scope: OperationScope, randstr: Callable[[], str], rand_online_name: Callable[[], str], rand_online_deployment_name: Callable[[], str], ) -> None: + assert registry_backed_client.resource_group_name != e2e_ws_scope.resource_group_name + # create a model in registry model_name = randstr("test-registry-model") model = Model(name=model_name, path="./tests/test_configs/deployments/model-1/model") - model = sdkv2_registry_client.models.create_or_update(model) + model = registry_backed_client.models.create_or_update(model) assert model.name == model_name # create a endpoint @@ -69,7 +72,7 @@ def test_online_deployment_create_when_registry_assets( endpoint = load_online_endpoint(endpoint_yaml) endpoint_name = rand_online_name("endpoint_name") endpoint.name = endpoint_name - endpoint = client.online_endpoints.begin_create_or_update(endpoint).result() + endpoint = registry_backed_client.online_endpoints.begin_create_or_update(endpoint).result() assert endpoint.name == endpoint_name # create a deployment @@ -80,23 +83,23 @@ def test_online_deployment_create_when_registry_assets( deployment.model = model try: - client.online_deployments.begin_create_or_update(deployment).result() - dep = client.online_deployments.get(name=deployment.name, endpoint_name=endpoint.name) + registry_backed_client.online_deployments.begin_create_or_update(deployment).result() + dep = registry_backed_client.online_deployments.get(name=deployment.name, endpoint_name=endpoint.name) assert dep.name == deployment.name - deps = client.online_deployments.list(endpoint_name=endpoint.name) + deps = registry_backed_client.online_deployments.list(endpoint_name=endpoint.name) assert len(list(deps)) > 0 endpoint.traffic = {deployment.name: 100} - client.online_endpoints.begin_create_or_update(endpoint).result() - endpoint_updated = client.online_endpoints.get(endpoint.name) + registry_backed_client.online_endpoints.begin_create_or_update(endpoint).result() + endpoint_updated = registry_backed_client.online_endpoints.get(endpoint.name) assert endpoint_updated.traffic[deployment.name] == 100 - client.online_endpoints.invoke( + registry_backed_client.online_endpoints.invoke( endpoint_name=endpoint.name, request_file="tests/test_configs/deployments/model-1/sample-request.json", ) finally: - client.online_endpoints.begin_delete(name=endpoint.name) + registry_backed_client.online_endpoints.begin_delete(name=endpoint.name) def test_online_deployment_update( self, client: MLClient, rand_online_name: Callable[[], str], rand_online_deployment_name: Callable[[], str] From 5ba9faaedf074cf1a11380d2a4cf00fb8ae1f4f2 Mon Sep 17 00:00:00 2001 From: chakradhar886 Date: Fri, 14 Aug 2026 11:46:16 +0530 Subject: [PATCH 6/9] Fix registry deployment CI checks --- sdk/ml/azure-ai-ml/api.metadata.yml | 2 +- .../tests/online_services/e2etests/test_online_deployment.py | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/sdk/ml/azure-ai-ml/api.metadata.yml b/sdk/ml/azure-ai-ml/api.metadata.yml index ed2c4383a3f9..8c1bb6e6d121 100644 --- a/sdk/ml/azure-ai-ml/api.metadata.yml +++ b/sdk/ml/azure-ai-ml/api.metadata.yml @@ -1,3 +1,3 @@ -apiMdSha256: 4af4d65ad5c624b35aefa8442a07cb8cb147fe1dcbab6aa993625728a4a04de1 +apiMdSha256: c39d5bf8320fae3388fc50ddcd9e5a7cbca070b46ffced33935ae06133a3364e parserVersion: 0.3.31 pythonVersion: 3.12.13 diff --git a/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py b/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py index b4aec10e006b..4e8cf05fc7bf 100644 --- a/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py +++ b/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py @@ -4,7 +4,6 @@ from devtools_testutils import AzureRecordedTestCase from pathlib import Path from azure.ai.ml import MLClient, load_online_deployment, load_online_endpoint, load_model -from azure.ai.ml._scope_dependent_operations import OperationScope from azure.ai.ml.entities import ManagedOnlineDeployment, ManagedOnlineEndpoint, Model, CodeConfiguration, Environment @@ -54,13 +53,10 @@ def test_online_deployment_create( def test_online_deployment_create_when_registry_assets( self, registry_backed_client: MLClient, - e2e_ws_scope: OperationScope, randstr: Callable[[], str], rand_online_name: Callable[[], str], rand_online_deployment_name: Callable[[], str], ) -> None: - assert registry_backed_client.resource_group_name != e2e_ws_scope.resource_group_name - # create a model in registry model_name = randstr("test-registry-model") model = Model(name=model_name, path="./tests/test_configs/deployments/model-1/model") From ee8919bdb86fba67d40f399da1d64e1ab7017a12 Mon Sep 17 00:00:00 2001 From: chakradhar886 Date: Fri, 14 Aug 2026 12:23:16 +0530 Subject: [PATCH 7/9] Fix registry deployment playback setup --- .../tests/online_services/e2etests/test_online_deployment.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py b/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py index 4e8cf05fc7bf..9aa2181c689a 100644 --- a/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py +++ b/sdk/ml/azure-ai-ml/tests/online_services/e2etests/test_online_deployment.py @@ -52,6 +52,7 @@ def test_online_deployment_create( def test_online_deployment_create_when_registry_assets( self, + sdkv2_registry_client: MLClient, registry_backed_client: MLClient, randstr: Callable[[], str], rand_online_name: Callable[[], str], @@ -60,7 +61,7 @@ def test_online_deployment_create_when_registry_assets( # create a model in registry model_name = randstr("test-registry-model") model = Model(name=model_name, path="./tests/test_configs/deployments/model-1/model") - model = registry_backed_client.models.create_or_update(model) + model = sdkv2_registry_client.models.create_or_update(model) assert model.name == model_name # create a endpoint From f2e645be331dc326dfdb75c4c8c4bed25e1e812c Mon Sep 17 00:00:00 2001 From: chakradhar886 Date: Fri, 14 Aug 2026 13:05:39 +0530 Subject: [PATCH 8/9] Reuse registry discovery in deployment playback --- sdk/ml/azure-ai-ml/tests/conftest.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/sdk/ml/azure-ai-ml/tests/conftest.py b/sdk/ml/azure-ai-ml/tests/conftest.py index 1032f787b08a..c9e6ba2471c7 100644 --- a/sdk/ml/azure-ai-ml/tests/conftest.py +++ b/sdk/ml/azure-ai-ml/tests/conftest.py @@ -486,17 +486,27 @@ def sdkv2_registry_client(e2e_ws_scope: OperationScope, auth: ClientSecretCreden @pytest.fixture -def registry_backed_client(e2e_ws_scope: OperationScope, auth: ClientSecretCredential) -> MLClient: +def registry_backed_client( + e2e_ws_scope: OperationScope, auth: ClientSecretCredential, sdkv2_registry_client: MLClient +) -> MLClient: """Return a registry-backed client whose online operations target the test workspace.""" - return MLClient( - credential=auth, - subscription_id=e2e_ws_scope.subscription_id, - resource_group_name=e2e_ws_scope.resource_group_name, - workspace_name=e2e_ws_scope.workspace_name, - registry_reference="sdkv2-testFeed", - logging_enable=getenv(E2E_TEST_LOGGING_ENABLED), - cloud="AzureCloud", + registry_clients = ( + sdkv2_registry_client._service_client_10_2021_dataplanepreview, + sdkv2_registry_client.resource_group_name, + sdkv2_registry_client.subscription_id, + sdkv2_registry_client._service_client_model_dataplane, + sdkv2_registry_client._service_client_registry_arm, ) + with patch("azure.ai.ml._ml_client.get_registry_client", return_value=registry_clients): + return MLClient( + credential=auth, + subscription_id=e2e_ws_scope.subscription_id, + resource_group_name=e2e_ws_scope.resource_group_name, + workspace_name=e2e_ws_scope.workspace_name, + registry_reference="sdkv2-testFeed", + logging_enable=getenv(E2E_TEST_LOGGING_ENABLED), + cloud="AzureCloud", + ) @pytest.fixture From 38c0e93e5e71dc5f59c0ec27777df38272de2d91 Mon Sep 17 00:00:00 2001 From: chakradhar886 Date: Fri, 14 Aug 2026 15:04:57 +0530 Subject: [PATCH 9/9] Use cached workspace location for online operations --- .../ai/ml/operations/_online_deployment_operations.py | 2 ++ .../ai/ml/operations/_online_endpoint_operations.py | 2 ++ .../unittests/test_online_deployments.py | 10 ++++++++++ .../online_services/unittests/test_online_endpoints.py | 10 ++++++++++ 4 files changed, 24 insertions(+) diff --git a/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_online_deployment_operations.py b/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_online_deployment_operations.py index 24510ea4ef25..f71204f05e32 100644 --- a/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_online_deployment_operations.py +++ b/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_online_deployment_operations.py @@ -373,6 +373,8 @@ def _get_workspace_location(self) -> str: :return: The workspace location :rtype: str """ + if self._operation_scope._workspace_location: + return self._operation_scope._workspace_location return str( self._all_operations.all_operations[AzureMLResourceType.WORKSPACE].get(self._workspace_name).location ) diff --git a/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_online_endpoint_operations.py b/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_online_endpoint_operations.py index 2b27e5774529..0e0761f7d051 100644 --- a/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_online_endpoint_operations.py +++ b/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_online_endpoint_operations.py @@ -367,6 +367,8 @@ def invoke( return str(response.text()) def _get_workspace_location(self) -> str: + if self._operation_scope._workspace_location: + return self._operation_scope._workspace_location return str( self._all_operations.all_operations[AzureMLResourceType.WORKSPACE].get(self._workspace_name).location ) diff --git a/sdk/ml/azure-ai-ml/tests/online_services/unittests/test_online_deployments.py b/sdk/ml/azure-ai-ml/tests/online_services/unittests/test_online_deployments.py index 36ad1c70cc3d..bae9b7d117f9 100644 --- a/sdk/ml/azure-ai-ml/tests/online_services/unittests/test_online_deployments.py +++ b/sdk/ml/azure-ai-ml/tests/online_services/unittests/test_online_deployments.py @@ -140,6 +140,16 @@ def mock_online_deployment_operations( @pytest.mark.unittest @pytest.mark.production_experiences_test class TestOnlineDeploymentOperations: + def test_get_workspace_location_uses_cached_scope( + self, + mock_online_deployment_operations: OnlineDeploymentOperations, + mock_workspace_operations: WorkspaceOperations, + ) -> None: + mock_online_deployment_operations._operation_scope._workspace_location = "eastus" + + assert mock_online_deployment_operations._get_workspace_location() == "eastus" + mock_workspace_operations._operation.get.assert_not_called() + def test_online_deployment_k8s_create( self, mock_online_deployment_operations: OnlineDeploymentOperations, diff --git a/sdk/ml/azure-ai-ml/tests/online_services/unittests/test_online_endpoints.py b/sdk/ml/azure-ai-ml/tests/online_services/unittests/test_online_endpoints.py index 0b111fd26f97..a425a32d7d2b 100644 --- a/sdk/ml/azure-ai-ml/tests/online_services/unittests/test_online_endpoints.py +++ b/sdk/ml/azure-ai-ml/tests/online_services/unittests/test_online_endpoints.py @@ -232,6 +232,16 @@ def mock_online_endpoint_operations( @pytest.mark.unittest @pytest.mark.production_experiences_test class TestOnlineEndpointsOperations: + def test_get_workspace_location_uses_cached_scope( + self, + mock_online_endpoint_operations: OnlineEndpointOperations, + mock_workspace_operations: WorkspaceOperations, + ) -> None: + mock_online_endpoint_operations._operation_scope._workspace_location = "eastus" + + assert mock_online_endpoint_operations._get_workspace_location() == "eastus" + mock_workspace_operations._operation.get.assert_not_called() + def test_online_list(self, mock_online_endpoint_operations: OnlineEndpointOperations) -> None: mock_online_endpoint_operations.list() mock_online_endpoint_operations._online_operation.list.assert_called_once()