From 364021d9e28e5a55e3df1802934a1500af6cc151 Mon Sep 17 00:00:00 2001 From: MilesHolland <108901744+MilesHolland@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:23:06 -0400 Subject: [PATCH] Fix workspace update tagging (#36131) * update cl * run black * testing * run-black * run pylint --- sdk/ml/azure-ai-ml/CHANGELOG.md | 6 +++++- .../azure-ai-ml/azure/ai/ml/constants/_common.py | 6 ++++++ .../ml/operations/_workspace_operations_base.py | 15 +++++++++++++-- .../tests/workspace/e2etests/test_workspace.py | 11 +++++++++-- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/sdk/ml/azure-ai-ml/CHANGELOG.md b/sdk/ml/azure-ai-ml/CHANGELOG.md index 25b7e117ed8..43621659269 100644 --- a/sdk/ml/azure-ai-ml/CHANGELOG.md +++ b/sdk/ml/azure-ai-ml/CHANGELOG.md @@ -2,16 +2,20 @@ ## 1.19.0 (unreleased) +### Bugs Fixed +- Workspace update no longer broken for older workspaces due to deprecated tags. + ## 1.18.0 (2024-07-09) ### Features Added -Expose `public_ip_address` in `AmlComputeNodeInfo`, to get the public ip address with the ssh port when calling `ml_client.compute.list_nodes` +- Expose `public_ip_address` in `AmlComputeNodeInfo`, to get the public ip address with the ssh port when calling `ml_client.compute.list_nodes` ### Bugs Fixed - InputTypes exported in constants module - WorkspaceConnection tags are now listed as deprecated, and the erroneously-deprecated metadata field has been un-deprecated and added as a initialization field. These two fields still point to the same underlying object property, and actual API usage of this value is unchanged. + ### Other Changes - WorkspaceConnections are officially GA'd and no longer experimental. But its much newer subclasses remain experimental. diff --git a/sdk/ml/azure-ai-ml/azure/ai/ml/constants/_common.py b/sdk/ml/azure-ai-ml/azure/ai/ml/constants/_common.py index 13e382b8e70..a1d01c0a279 100644 --- a/sdk/ml/azure-ai-ml/azure/ai/ml/constants/_common.py +++ b/sdk/ml/azure-ai-ml/azure/ai/ml/constants/_common.py @@ -194,6 +194,12 @@ CONNECTION_CONTAINER_NAME_KEY = "ContainerName" CONNECTION_ACCOUNT_NAME_KEY = "AccountName" CONNECTION_RESOURCE_ID_KEY = "ResourceId" +# Deprecated tag keys that cause workspace patch operations to fail +# Patch operations are used by the workspace begin_upcate operation, +# but not begin_create_or_update. Once the former is replaced with the +# latter, we can remove this list. +WORKSPACE_PATCH_REJECTED_KEYS = ["AttachKeyVaultToWorkspace", "AttachAppInsightsToWorkspace"] + class WorkspaceDiscoveryUrlKey(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Enum that captures keys URL types returned from querying a workspace's discovery url.""" diff --git a/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_workspace_operations_base.py b/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_workspace_operations_base.py index 89ccc98ad78..c39934f81d4 100644 --- a/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_workspace_operations_base.py +++ b/sdk/ml/azure-ai-ml/azure/ai/ml/operations/_workspace_operations_base.py @@ -33,7 +33,13 @@ from azure.ai.ml._utils._workspace_utils import ( from azure.ai.ml._utils.utils import camel_to_snake, from_iso_duration_format_min_sec from azure.ai.ml._version import VERSION from azure.ai.ml.constants import ManagedServiceIdentityType -from azure.ai.ml.constants._common import ArmConstants, LROConfigurations, WorkspaceKind, WorkspaceResourceConstants +from azure.ai.ml.constants._common import ( + ArmConstants, + LROConfigurations, + WorkspaceKind, + WorkspaceResourceConstants, + WORKSPACE_PATCH_REJECTED_KEYS, +) from azure.ai.ml.constants._workspace import IsolationMode, OutboundRuleCategory from azure.ai.ml.entities import Hub, Project, Workspace from azure.ai.ml.entities._credentials import IdentityConfiguration @@ -223,7 +229,7 @@ class WorkspaceOperationsBase(ABC): CustomArmTemplateDeploymentPollingMethod(poller, arm_submit, real_callback), ) - # pylint: disable=too-many-statements + # pylint: disable=too-many-statements,too-many-locals def begin_update( self, workspace: Workspace, @@ -370,6 +376,11 @@ class WorkspaceOperationsBase(ABC): ) grant_materialization_permissions = kwargs.get("grant_materialization_permissions", None) + # Remove deprecated keys from older workspaces that might still have them before we try to update. + if workspace.tags is not None: + for bad_key in WORKSPACE_PATCH_REJECTED_KEYS: + _ = workspace.tags.pop(bad_key, None) + # pylint: disable=unused-argument, docstring-missing-param def callback(_: Any, deserialized: Any, args: Any) -> Workspace: """Callback to be called after completion diff --git a/sdk/ml/azure-ai-ml/tests/workspace/e2etests/test_workspace.py b/sdk/ml/azure-ai-ml/tests/workspace/e2etests/test_workspace.py index 196b59b6e4b..0f2bc6e794e 100644 --- a/sdk/ml/azure-ai-ml/tests/workspace/e2etests/test_workspace.py +++ b/sdk/ml/azure-ai-ml/tests/workspace/e2etests/test_workspace.py @@ -9,7 +9,7 @@ from test_utilities.utils import verify_entity_load_and_dump from azure.ai.ml import MLClient, load_workspace from azure.ai.ml._utils.utils import camel_to_snake -from azure.ai.ml.constants._common import PublicNetworkAccess +from azure.ai.ml.constants._common import PublicNetworkAccess, WORKSPACE_PATCH_REJECTED_KEYS from azure.ai.ml.constants._workspace import ManagedServiceIdentityType from azure.ai.ml.entities._credentials import IdentityConfiguration, ManagedIdentityConfiguration from azure.ai.ml.entities import Hub @@ -126,10 +126,17 @@ class TestWorkspace(AzureRecordedTestCase): assert isinstance(workspace, Workspace) assert workspace.name == wps_name + workspace.tags = { + WORKSPACE_PATCH_REJECTED_KEYS[0]: "should be removed", + WORKSPACE_PATCH_REJECTED_KEYS[1]: "should be removed", + } param_image_build_compute = "compute" param_display_name = "Test display name" param_description = "Test description" - param_tags = {"k1": "v1", "k2": "v2"} + param_tags = { + "k1": "v1", + "k2": "v2", + } workspace.enable_data_isolation = False workspace_poller = client.workspaces.begin_update( workspace,