diff options
| author | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
|---|---|---|
| committer | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
| commit | 4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch) | |
| tree | ee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace | |
| parent | cc961e04ba734dd72309fb548a2f97d67d578813 (diff) | |
| download | gn-ai-master.tar.gz | |
Diffstat (limited to '.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace')
18 files changed, 1156 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/__init__.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/__init__.py new file mode 100644 index 00000000..dc8b82e2 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/__init__.py @@ -0,0 +1,11 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore + +from .workspace import WorkspaceSchema +from .ai_workspaces.project import ProjectSchema +from .ai_workspaces.hub import HubSchema + +__all__ = ["WorkspaceSchema", "ProjectSchema", "HubSchema"] diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/__init__.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/__init__.py new file mode 100644 index 00000000..29a4fcd3 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/__init__.py @@ -0,0 +1,5 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/capability_host.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/capability_host.py new file mode 100644 index 00000000..cdccb24c --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/capability_host.py @@ -0,0 +1,18 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +from marshmallow import fields + +from azure.ai.ml._schema.core.schema import PathAwareSchema +from azure.ai.ml._utils._experimental import experimental + + +@experimental +class CapabilityHostSchema(PathAwareSchema): + name = fields.Str() + description = fields.Str() + capability_host_kind = fields.Str() + vector_store_connections = fields.List(fields.Str(), required=False) + ai_services_connections = fields.List(fields.Str(), required=False) + storage_connections = fields.List(fields.Str(), required=False) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/hub.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/hub.py new file mode 100644 index 00000000..94a7c380 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/hub.py @@ -0,0 +1,18 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +from marshmallow import fields + +from azure.ai.ml._schema import StringTransformedEnum +from azure.ai.ml._schema.workspace import WorkspaceSchema +from azure.ai.ml._utils._experimental import experimental +from azure.ai.ml.constants import WorkspaceKind + + +@experimental +class HubSchema(WorkspaceSchema): + # additional_workspace_storage_accounts This field exists in the API, but is unused, and thus not surfaced yet. + kind = StringTransformedEnum(required=True, allowed_values=WorkspaceKind.HUB) + default_resource_group = fields.Str(required=False) + associated_workspaces = fields.List(fields.Str(), required=False, dump_only=True) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/project.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/project.py new file mode 100644 index 00000000..86daa735 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/ai_workspaces/project.py @@ -0,0 +1,16 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +from marshmallow import fields + +from azure.ai.ml._schema import StringTransformedEnum +from azure.ai.ml._utils._experimental import experimental +from azure.ai.ml._schema.workspace import WorkspaceSchema +from azure.ai.ml.constants import WorkspaceKind + + +@experimental +class ProjectSchema(WorkspaceSchema): + kind = StringTransformedEnum(required=True, allowed_values=WorkspaceKind.PROJECT) + hub_id = fields.Str(required=True) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/__init__.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/__init__.py new file mode 100644 index 00000000..fa462cfb --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/__init__.py @@ -0,0 +1,37 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore + +from .workspace_connection import WorkspaceConnectionSchema +from .connection_subtypes import ( + AzureBlobStoreConnectionSchema, + MicrosoftOneLakeConnectionSchema, + AzureOpenAIConnectionSchema, + AzureAIServicesConnectionSchema, + AzureAISearchConnectionSchema, + AzureContentSafetyConnectionSchema, + AzureSpeechServicesConnectionSchema, + APIKeyConnectionSchema, + OpenAIConnectionSchema, + SerpConnectionSchema, + ServerlessConnectionSchema, + OneLakeArtifactSchema, +) + +__all__ = [ + "WorkspaceConnectionSchema", + "AzureBlobStoreConnectionSchema", + "MicrosoftOneLakeConnectionSchema", + "AzureOpenAIConnectionSchema", + "AzureAIServicesConnectionSchema", + "AzureAISearchConnectionSchema", + "AzureContentSafetyConnectionSchema", + "AzureSpeechServicesConnectionSchema", + "APIKeyConnectionSchema", + "OpenAIConnectionSchema", + "SerpConnectionSchema", + "ServerlessConnectionSchema", + "OneLakeArtifactSchema", +] diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/connection_subtypes.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/connection_subtypes.py new file mode 100644 index 00000000..d04b3e76 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/connection_subtypes.py @@ -0,0 +1,225 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=unused-argument + +from marshmallow import fields, post_load +from marshmallow.exceptions import ValidationError +from marshmallow.decorators import pre_load + +from azure.ai.ml._restclient.v2024_04_01_preview.models import ConnectionCategory +from azure.ai.ml._schema.core.fields import NestedField, StringTransformedEnum, UnionField +from azure.ai.ml._utils.utils import camel_to_snake +from azure.ai.ml.constants._common import ConnectionTypes +from azure.ai.ml._schema.workspace.connections.one_lake_artifacts import OneLakeArtifactSchema +from azure.ai.ml._schema.workspace.connections.credentials import ( + SasTokenConfigurationSchema, + ServicePrincipalConfigurationSchema, + AccountKeyConfigurationSchema, + AadCredentialConfigurationSchema, +) +from azure.ai.ml.entities import AadCredentialConfiguration +from .workspace_connection import WorkspaceConnectionSchema + + +class AzureBlobStoreConnectionSchema(WorkspaceConnectionSchema): + # type and credentials limited + type = StringTransformedEnum( + allowed_values=ConnectionCategory.AZURE_BLOB, casing_transform=camel_to_snake, required=True + ) + credentials = UnionField( + [ + NestedField(SasTokenConfigurationSchema), + NestedField(AccountKeyConfigurationSchema), + NestedField(AadCredentialConfigurationSchema), + ], + required=False, + load_default=AadCredentialConfiguration(), + ) + + url = fields.Str() + + account_name = fields.Str(required=True, allow_none=False) + container_name = fields.Str(required=True, allow_none=False) + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import AzureBlobStoreConnection + + return AzureBlobStoreConnection(**data) + + +class MicrosoftOneLakeConnectionSchema(WorkspaceConnectionSchema): + type = StringTransformedEnum( + allowed_values=ConnectionCategory.AZURE_ONE_LAKE, casing_transform=camel_to_snake, required=True + ) + credentials = UnionField( + [NestedField(ServicePrincipalConfigurationSchema), NestedField(AadCredentialConfigurationSchema)], + required=False, + load_default=AadCredentialConfiguration(), + ) + artifact = NestedField(OneLakeArtifactSchema, required=False, allow_none=True) + + endpoint = fields.Str(required=False) + one_lake_workspace_name = fields.Str(required=False) + + @pre_load + def check_for_target(self, data, **kwargs): + target = data.get("target", None) + artifact = data.get("artifact", None) + endpoint = data.get("endpoint", None) + one_lake_workspace_name = data.get("one_lake_workspace_name", None) + # If the user is using a target, then they don't need the artifact and one lake workspace name. + # This is distinct from when the user set's the 'endpoint' value, which is also used to construct + # the target. If the target is already present, then the loaded connection YAML was probably produced + # by dumping an extant connection. + if target is None: + if artifact is None: + raise ValidationError("If target is unset, then artifact must be set") + if endpoint is None: + raise ValidationError("If target is unset, then endpoint must be set") + if one_lake_workspace_name is None: + raise ValidationError("If target is unset, then one_lake_workspace_name must be set") + return data + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import MicrosoftOneLakeConnection + + return MicrosoftOneLakeConnection(**data) + + +class AzureOpenAIConnectionSchema(WorkspaceConnectionSchema): + # type and credentials limited + type = StringTransformedEnum( + allowed_values=ConnectionCategory.AZURE_OPEN_AI, casing_transform=camel_to_snake, required=True + ) + api_key = fields.Str(required=False, allow_none=True) + api_version = fields.Str(required=False, allow_none=True) + + azure_endpoint = fields.Str() + open_ai_resource_id = fields.Str(required=False, allow_none=True) + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import AzureOpenAIConnection + + return AzureOpenAIConnection(**data) + + +class AzureAIServicesConnectionSchema(WorkspaceConnectionSchema): + # type and credentials limited + type = StringTransformedEnum( + allowed_values=ConnectionTypes.AZURE_AI_SERVICES, casing_transform=camel_to_snake, required=True + ) + api_key = fields.Str(required=False, allow_none=True) + endpoint = fields.Str() + ai_services_resource_id = fields.Str() + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import AzureAIServicesConnection + + return AzureAIServicesConnection(**data) + + +class AzureAISearchConnectionSchema(WorkspaceConnectionSchema): + # type and credentials limited + type = StringTransformedEnum( + allowed_values=ConnectionTypes.AZURE_SEARCH, casing_transform=camel_to_snake, required=True + ) + api_key = fields.Str(required=False, allow_none=True) + endpoint = fields.Str() + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import AzureAISearchConnection + + return AzureAISearchConnection(**data) + + +class AzureContentSafetyConnectionSchema(WorkspaceConnectionSchema): + # type and credentials limited + type = StringTransformedEnum( + allowed_values=ConnectionTypes.AZURE_CONTENT_SAFETY, casing_transform=camel_to_snake, required=True + ) + api_key = fields.Str(required=False, allow_none=True) + endpoint = fields.Str() + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import AzureContentSafetyConnection + + return AzureContentSafetyConnection(**data) + + +class AzureSpeechServicesConnectionSchema(WorkspaceConnectionSchema): + # type and credentials limited + type = StringTransformedEnum( + allowed_values=ConnectionTypes.AZURE_SPEECH_SERVICES, casing_transform=camel_to_snake, required=True + ) + api_key = fields.Str(required=False, allow_none=True) + endpoint = fields.Str() + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import AzureSpeechServicesConnection + + return AzureSpeechServicesConnection(**data) + + +class APIKeyConnectionSchema(WorkspaceConnectionSchema): + # type and credentials limited + type = StringTransformedEnum( + allowed_values=ConnectionCategory.API_KEY, casing_transform=camel_to_snake, required=True + ) + api_key = fields.Str(required=True) + api_base = fields.Str(required=True) + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import APIKeyConnection + + return APIKeyConnection(**data) + + +class OpenAIConnectionSchema(WorkspaceConnectionSchema): + # type and credentials limited + type = StringTransformedEnum( + allowed_values=ConnectionCategory.OPEN_AI, casing_transform=camel_to_snake, required=True + ) + api_key = fields.Str(required=True) + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import OpenAIConnection + + return OpenAIConnection(**data) + + +class SerpConnectionSchema(WorkspaceConnectionSchema): + # type and credentials limited + type = StringTransformedEnum(allowed_values=ConnectionCategory.SERP, casing_transform=camel_to_snake, required=True) + api_key = fields.Str(required=True) + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import SerpConnection + + return SerpConnection(**data) + + +class ServerlessConnectionSchema(WorkspaceConnectionSchema): + # type and credentials limited + type = StringTransformedEnum( + allowed_values=ConnectionCategory.SERVERLESS, casing_transform=camel_to_snake, required=True + ) + api_key = fields.Str(required=True) + endpoint = fields.Str() + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import ServerlessConnection + + return ServerlessConnection(**data) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/credentials.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/credentials.py new file mode 100644 index 00000000..52213c08 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/credentials.py @@ -0,0 +1,178 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=unused-argument + +##### DEV NOTE: For some reason, these schemas correlate to the classes defined in ~azure.ai.ml.entities._credentials. +# There used to be a credentials.py file in ~azure.ai.ml.entities.workspace.connections, +# but it was, as far as I could tell, never used. So I removed it and added this comment. + +from typing import Dict + +from marshmallow import fields, post_load + +from azure.ai.ml._restclient.v2024_04_01_preview.models import ConnectionAuthType +from azure.ai.ml._schema.core.fields import StringTransformedEnum +from azure.ai.ml._schema.core.schema import PatchedSchemaMeta +from azure.ai.ml._utils.utils import camel_to_snake +from azure.ai.ml.entities._credentials import ( + ManagedIdentityConfiguration, + PatTokenConfiguration, + SasTokenConfiguration, + ServicePrincipalConfiguration, + UsernamePasswordConfiguration, + AccessKeyConfiguration, + ApiKeyConfiguration, + AccountKeyConfiguration, + AadCredentialConfiguration, + NoneCredentialConfiguration, +) + + +class WorkspaceCredentialsSchema(metaclass=PatchedSchemaMeta): + type = fields.Str() + + +class PatTokenConfigurationSchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=ConnectionAuthType.PAT, + casing_transform=camel_to_snake, + required=True, + ) + pat = fields.Str() + + @post_load + def make(self, data: Dict[str, str], **kwargs) -> PatTokenConfiguration: + data.pop("type") + return PatTokenConfiguration(**data) + + +class SasTokenConfigurationSchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=ConnectionAuthType.SAS, + casing_transform=camel_to_snake, + required=True, + ) + sas_token = fields.Str() + + @post_load + def make(self, data: Dict[str, str], **kwargs) -> SasTokenConfiguration: + data.pop("type") + return SasTokenConfiguration(**data) + + +class UsernamePasswordConfigurationSchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=ConnectionAuthType.USERNAME_PASSWORD, + casing_transform=camel_to_snake, + required=True, + ) + username = fields.Str() + password = fields.Str() + + @post_load + def make(self, data: Dict[str, str], **kwargs) -> UsernamePasswordConfiguration: + data.pop("type") + return UsernamePasswordConfiguration(**data) + + +class ManagedIdentityConfigurationSchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=ConnectionAuthType.MANAGED_IDENTITY, + casing_transform=camel_to_snake, + required=True, + ) + client_id = fields.Str() + resource_id = fields.Str() + + @post_load + def make(self, data: Dict[str, str], **kwargs) -> ManagedIdentityConfiguration: + data.pop("type") + return ManagedIdentityConfiguration(**data) + + +class ServicePrincipalConfigurationSchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=ConnectionAuthType.SERVICE_PRINCIPAL, + casing_transform=camel_to_snake, + required=True, + ) + + client_id = fields.Str() + client_secret = fields.Str() + tenant_id = fields.Str() + + @post_load + def make(self, data: Dict[str, str], **kwargs) -> ServicePrincipalConfiguration: + data.pop("type") + return ServicePrincipalConfiguration(**data) + + +class AccessKeyConfigurationSchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=ConnectionAuthType.ACCESS_KEY, + casing_transform=camel_to_snake, + required=True, + ) + access_key_id = fields.Str() + secret_access_key = fields.Str() + + @post_load + def make(self, data: Dict[str, str], **kwargs) -> AccessKeyConfiguration: + data.pop("type") + return AccessKeyConfiguration(**data) + + +class ApiKeyConfigurationSchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=ConnectionAuthType.API_KEY, + casing_transform=camel_to_snake, + required=True, + ) + key = fields.Str() + + @post_load + def make(self, data: Dict[str, str], **kwargs) -> ApiKeyConfiguration: + data.pop("type") + return ApiKeyConfiguration(**data) + + +class AccountKeyConfigurationSchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=ConnectionAuthType.ACCOUNT_KEY, + casing_transform=camel_to_snake, + required=True, + ) + account_key = fields.Str() + + @post_load + def make(self, data: Dict[str, str], **kwargs) -> AccountKeyConfiguration: + data.pop("type") + return AccountKeyConfiguration(**data) + + +class AadCredentialConfigurationSchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=ConnectionAuthType.AAD, + casing_transform=camel_to_snake, + required=True, + ) + + @post_load + def make(self, data: Dict[str, str], **kwargs) -> AadCredentialConfiguration: + data.pop("type") + return AadCredentialConfiguration(**data) + + +class NoneCredentialConfigurationSchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=ConnectionAuthType.NONE, + casing_transform=camel_to_snake, + required=True, + ) + + @post_load + def make(self, data: Dict[str, str], **kwargs) -> NoneCredentialConfiguration: + data.pop("type") + return NoneCredentialConfiguration(**data) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/one_lake_artifacts.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/one_lake_artifacts.py new file mode 100644 index 00000000..563a9359 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/one_lake_artifacts.py @@ -0,0 +1,26 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=unused-argument + +from marshmallow import fields, post_load + +from azure.ai.ml._schema.core.fields import StringTransformedEnum +from azure.ai.ml._utils.utils import camel_to_snake +from azure.ai.ml.constants._common import OneLakeArtifactTypes + +from azure.ai.ml._schema.core.schema import PatchedSchemaMeta + + +class OneLakeArtifactSchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=OneLakeArtifactTypes.ONE_LAKE, casing_transform=camel_to_snake, required=True + ) + name = fields.Str(required=True) + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import OneLakeConnectionArtifact + + return OneLakeConnectionArtifact(**data) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/workspace_connection.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/workspace_connection.py new file mode 100644 index 00000000..20863a5a --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/connections/workspace_connection.py @@ -0,0 +1,86 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=unused-argument + +from marshmallow import fields, post_load + +from azure.ai.ml._restclient.v2024_04_01_preview.models import ConnectionCategory +from azure.ai.ml._schema.core.fields import NestedField, StringTransformedEnum, UnionField +from azure.ai.ml._schema.core.resource import ResourceSchema +from azure.ai.ml._schema.job import CreationContextSchema +from azure.ai.ml._schema.workspace.connections.credentials import ( + AccountKeyConfigurationSchema, + ManagedIdentityConfigurationSchema, + PatTokenConfigurationSchema, + SasTokenConfigurationSchema, + ServicePrincipalConfigurationSchema, + UsernamePasswordConfigurationSchema, + AccessKeyConfigurationSchema, + ApiKeyConfigurationSchema, + AadCredentialConfigurationSchema, + NoneCredentialConfigurationSchema, +) +from azure.ai.ml._utils.utils import camel_to_snake +from azure.ai.ml.constants._common import ConnectionTypes +from azure.ai.ml.entities import NoneCredentialConfiguration, AadCredentialConfiguration + + +class WorkspaceConnectionSchema(ResourceSchema): + # Inherits name, id, tags, and description fields from ResourceSchema + creation_context = NestedField(CreationContextSchema, dump_only=True) + type = StringTransformedEnum( + allowed_values=[ + ConnectionCategory.GIT, + ConnectionCategory.CONTAINER_REGISTRY, + ConnectionCategory.PYTHON_FEED, + ConnectionCategory.S3, + ConnectionCategory.SNOWFLAKE, + ConnectionCategory.AZURE_SQL_DB, + ConnectionCategory.AZURE_SYNAPSE_ANALYTICS, + ConnectionCategory.AZURE_MY_SQL_DB, + ConnectionCategory.AZURE_POSTGRES_DB, + ConnectionTypes.CUSTOM, + ConnectionTypes.AZURE_DATA_LAKE_GEN_2, + ], + casing_transform=camel_to_snake, + required=True, + ) + + # Sorta false, some connection types require this field, some don't. + # And some rename it... for client familiarity reasons. + target = fields.Str(required=False) + + credentials = UnionField( + [ + NestedField(PatTokenConfigurationSchema), + NestedField(SasTokenConfigurationSchema), + NestedField(UsernamePasswordConfigurationSchema), + NestedField(ManagedIdentityConfigurationSchema), + NestedField(ServicePrincipalConfigurationSchema), + NestedField(AccessKeyConfigurationSchema), + NestedField(ApiKeyConfigurationSchema), + NestedField(AccountKeyConfigurationSchema), + NestedField(AadCredentialConfigurationSchema), + NestedField(NoneCredentialConfigurationSchema), + ], + required=False, + load_default=NoneCredentialConfiguration(), + ) + + is_shared = fields.Bool(load_default=True) + metadata = fields.Dict(required=False) + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import WorkspaceConnection + + # Most non-subclassed connections default to a none credential if none + # is provided. ALDS Gen 2 connections default to AAD with this code. + if ( + data.get("type", None) == ConnectionTypes.AZURE_DATA_LAKE_GEN_2 + and data.get("credentials", None) == NoneCredentialConfiguration() + ): + data["credentials"] = AadCredentialConfiguration() + return WorkspaceConnection(**data) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/customer_managed_key.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/customer_managed_key.py new file mode 100644 index 00000000..459507fc --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/customer_managed_key.py @@ -0,0 +1,23 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=unused-argument + +from marshmallow import fields, post_load + +from azure.ai.ml._schema.core.schema import PatchedSchemaMeta + + +class CustomerManagedKeySchema(metaclass=PatchedSchemaMeta): + key_vault = fields.Str() + key_uri = fields.Url() + cosmosdb_id = fields.Str() + storage_id = fields.Str() + search_id = fields.Str() + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import CustomerManagedKey + + return CustomerManagedKey(**data) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/endpoint_connection.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/endpoint_connection.py new file mode 100644 index 00000000..ba926d9e --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/endpoint_connection.py @@ -0,0 +1,23 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=unused-argument + +from marshmallow import fields, post_load + +from azure.ai.ml._schema.core.schema import PatchedSchemaMeta + + +class EndpointConnectionSchema(metaclass=PatchedSchemaMeta): + subscription_id = fields.UUID() + resource_group = fields.Str() + location = fields.Str() + vnet_name = fields.Str() + subnet_name = fields.Str() + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import EndpointConnection + + return EndpointConnection(**data) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/identity.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/identity.py new file mode 100644 index 00000000..d0348c3b --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/identity.py @@ -0,0 +1,79 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=unused-argument + +from marshmallow import fields +from marshmallow.decorators import post_load, pre_dump + +from azure.ai.ml._schema.core.fields import NestedField, StringTransformedEnum +from azure.ai.ml._schema.core.schema_meta import PatchedSchemaMeta +from azure.ai.ml._utils.utils import camel_to_snake, snake_to_camel +from azure.ai.ml.constants._workspace import ManagedServiceIdentityType +from azure.ai.ml.entities._credentials import IdentityConfiguration, ManagedIdentityConfiguration + + +class UserAssignedIdentitySchema(metaclass=PatchedSchemaMeta): + principal_id = fields.Str(required=False) + client_id = fields.Str(required=False) + resource_id = fields.Str(required=False) + + @post_load + def make(self, data, **kwargs): + return ManagedIdentityConfiguration(**data) + + +class IdentitySchema(metaclass=PatchedSchemaMeta): + type = StringTransformedEnum( + allowed_values=[ + ManagedServiceIdentityType.SYSTEM_ASSIGNED, + ManagedServiceIdentityType.USER_ASSIGNED, + ManagedServiceIdentityType.NONE, + ManagedServiceIdentityType.SYSTEM_ASSIGNED_USER_ASSIGNED, + ], + casing_transform=camel_to_snake, + metadata={"description": "resource identity type."}, + ) + principal_id = fields.Str(required=False) + tenant_id = fields.Str(required=False) + user_assigned_identities = fields.Dict( + keys=fields.Str(required=True), values=NestedField(UserAssignedIdentitySchema, allow_none=True), allow_none=True + ) + + @pre_dump + def predump(self, data, **kwargs): + if data and isinstance(data, IdentityConfiguration): + data.user_assigned_identities = self.uai_list2dict(data.user_assigned_identities) + return data + + @post_load + def make(self, data, **kwargs): + if data.get("user_assigned_identities", False): + data["user_assigned_identities"] = self.uai_dict2list(data.pop("user_assigned_identities")) + data["type"] = snake_to_camel(data.pop("type")) + return IdentityConfiguration(**data) + + def uai_dict2list(self, uai_dict): + res = [] + for resource_id, meta in uai_dict.items(): + if not isinstance(meta, ManagedIdentityConfiguration): + continue + c_id = meta.client_id + p_id = meta.principal_id + res.append(ManagedIdentityConfiguration(resource_id=resource_id, client_id=c_id, principal_id=p_id)) + return res + + def uai_list2dict(self, uai_list): + res = {} + if uai_list and isinstance(uai_list, list): + for uai in uai_list: + if not isinstance(uai, ManagedIdentityConfiguration): + continue + meta = {} + if uai.client_id: + meta["client_id"] = uai.client_id + if uai.principal_id: + meta["principal_id"] = uai.principal_id + res[uai.resource_id] = meta + return res if res else None diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/network_acls.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/network_acls.py new file mode 100644 index 00000000..e9e5e8ec --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/network_acls.py @@ -0,0 +1,63 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +from marshmallow import ValidationError, fields, post_load, validates_schema + +from azure.ai.ml._schema.core.schema import PathAwareSchema +from azure.ai.ml.entities._workspace.network_acls import DefaultActionType, IPRule, NetworkAcls + + +class IPRuleSchema(PathAwareSchema): + """Schema for IPRule.""" + + value = fields.Str(required=True) + + @post_load + def make(self, data, **kwargs): # pylint: disable=unused-argument + """Create an IPRule object from the marshmallow schema. + + :param data: The data from which the IPRule is being loaded. + :type data: OrderedDict[str, Any] + :returns: An IPRule object. + :rtype: azure.ai.ml.entities._workspace.network_acls.NetworkAcls.IPRule + """ + return IPRule(**data) + + +class NetworkAclsSchema(PathAwareSchema): + """Schema for NetworkAcls. + + :param default_action: Specifies the default action when no IP rules are matched. + :type default_action: str + :param ip_rules: Rules governing the accessibility of a resource from a specific IP address or IP range. + :type ip_rules: Optional[List[IPRule]] + """ + + default_action = fields.Str(required=True) + ip_rules = fields.List(fields.Nested(IPRuleSchema), allow_none=True) + + @post_load + def make(self, data, **kwargs): # pylint: disable=unused-argument + """Create a NetworkAcls object from the marshmallow schema. + + :param data: The data from which the NetworkAcls is being loaded. + :type data: OrderedDict[str, Any] + :returns: A NetworkAcls object. + :rtype: azure.ai.ml.entities._workspace.network_acls.NetworkAcls + """ + return NetworkAcls(**data) + + @validates_schema + def validate_schema(self, data, **kwargs): # pylint: disable=unused-argument + """Validate the NetworkAcls schema. + + :param data: The data to validate. + :type data: OrderedDict[str, Any] + :raises ValidationError: If the schema is invalid. + """ + if data["default_action"] not in set([DefaultActionType.DENY, DefaultActionType.ALLOW]): + raise ValidationError("Invalid value for default_action. Must be 'Deny' or 'Allow'.") + + if data["default_action"] == DefaultActionType.DENY and not data.get("ip_rules"): + raise ValidationError("ip_rules must be provided when default_action is 'Deny'.") diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/networking.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/networking.py new file mode 100644 index 00000000..f228ee3e --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/networking.py @@ -0,0 +1,224 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=unused-argument,no-else-return + +from marshmallow import EXCLUDE, fields +from marshmallow.decorators import post_load, pre_dump + +from azure.ai.ml._schema import ExperimentalField +from azure.ai.ml._schema.core.fields import NestedField, StringTransformedEnum, UnionField +from azure.ai.ml._schema.core.schema_meta import PatchedSchemaMeta +from azure.ai.ml._utils.utils import _snake_to_camel, camel_to_snake +from azure.ai.ml.constants._workspace import FirewallSku, IsolationMode, OutboundRuleCategory +from azure.ai.ml.entities._workspace.networking import ( + FqdnDestination, + ManagedNetwork, + PrivateEndpointDestination, + ServiceTagDestination, +) + + +class ManagedNetworkStatusSchema(metaclass=PatchedSchemaMeta): + spark_ready = fields.Bool(dump_only=True) + status = fields.Str(dump_only=True) + + +class FqdnOutboundRuleSchema(metaclass=PatchedSchemaMeta): + name = fields.Str(required=True) + parent_rule_names = fields.List(fields.Str(), dump_only=True) + type = fields.Constant("fqdn") + destination = fields.Str(required=True) + category = StringTransformedEnum( + allowed_values=[ + OutboundRuleCategory.REQUIRED, + OutboundRuleCategory.RECOMMENDED, + OutboundRuleCategory.USER_DEFINED, + ], + casing_transform=camel_to_snake, + metadata={"description": "outbound rule category."}, + dump_only=True, + ) + status = fields.Str(dump_only=True) + + @post_load + def createdestobject(self, data, **kwargs): + dest = data.get("destination") + category = data.get("category", OutboundRuleCategory.USER_DEFINED) + name = data.get("name") + status = data.get("status", None) + return FqdnDestination( + name=name, + destination=dest, + category=_snake_to_camel(category), + status=status, + ) + + +class ServiceTagDestinationSchema(metaclass=PatchedSchemaMeta): + service_tag = fields.Str(required=True) + protocol = fields.Str(required=True) + port_ranges = fields.Str(required=True) + address_prefixes = fields.List(fields.Str()) + + +class ServiceTagOutboundRuleSchema(metaclass=PatchedSchemaMeta): + name = fields.Str(required=True) + parent_rule_names = fields.List(fields.Str(), dump_only=True) + type = fields.Constant("service_tag") + destination = NestedField(ServiceTagDestinationSchema, required=True) + category = StringTransformedEnum( + allowed_values=[ + OutboundRuleCategory.REQUIRED, + OutboundRuleCategory.RECOMMENDED, + OutboundRuleCategory.USER_DEFINED, + ], + casing_transform=camel_to_snake, + metadata={"description": "outbound rule category."}, + dump_only=True, + ) + status = fields.Str(dump_only=True) + + @pre_dump + def predump(self, data, **kwargs): + data.destination = self.service_tag_dest2dict( + data.service_tag, data.protocol, data.port_ranges, data.address_prefixes + ) + return data + + @post_load + def createdestobject(self, data, **kwargs): + dest = data.get("destination") + category = data.get("category", OutboundRuleCategory.USER_DEFINED) + name = data.get("name") + status = data.get("status", None) + return ServiceTagDestination( + name=name, + service_tag=dest["service_tag"], + protocol=dest["protocol"], + port_ranges=dest["port_ranges"], + address_prefixes=dest.get("address_prefixes", None), + category=_snake_to_camel(category), + status=status, + ) + + def service_tag_dest2dict(self, service_tag, protocol, port_ranges, address_prefixes): + service_tag_dest = {} + service_tag_dest["service_tag"] = service_tag + service_tag_dest["protocol"] = protocol + service_tag_dest["port_ranges"] = port_ranges + service_tag_dest["address_prefixes"] = address_prefixes + return service_tag_dest + + +class PrivateEndpointDestinationSchema(metaclass=PatchedSchemaMeta): + service_resource_id = fields.Str(required=True) + subresource_target = fields.Str(required=True) + spark_enabled = fields.Bool(required=True) + + +class PrivateEndpointOutboundRuleSchema(metaclass=PatchedSchemaMeta): + name = fields.Str(required=True) + parent_rule_names = fields.List(fields.Str(), dump_only=True) + type = fields.Constant("private_endpoint") + destination = NestedField(PrivateEndpointDestinationSchema, required=True) + fqdns = fields.List(fields.Str()) + category = StringTransformedEnum( + allowed_values=[ + OutboundRuleCategory.REQUIRED, + OutboundRuleCategory.RECOMMENDED, + OutboundRuleCategory.USER_DEFINED, + OutboundRuleCategory.DEPENDENCY, + ], + casing_transform=camel_to_snake, + metadata={"description": "outbound rule category."}, + dump_only=True, + ) + status = fields.Str(dump_only=True) + + @pre_dump + def predump(self, data, **kwargs): + data.destination = self.pe_dest2dict(data.service_resource_id, data.subresource_target, data.spark_enabled) + return data + + @post_load + def createdestobject(self, data, **kwargs): + dest = data.get("destination") + category = data.get("category", OutboundRuleCategory.USER_DEFINED) + name = data.get("name") + status = data.get("status", None) + fqdns = data.get("fqdns", None) + return PrivateEndpointDestination( + name=name, + service_resource_id=dest["service_resource_id"], + subresource_target=dest["subresource_target"], + spark_enabled=dest["spark_enabled"], + category=_snake_to_camel(category), + status=status, + fqdns=fqdns, + ) + + def pe_dest2dict(self, service_resource_id, subresource_target, spark_enabled): + pedest = {} + pedest["service_resource_id"] = service_resource_id + pedest["subresource_target"] = subresource_target + pedest["spark_enabled"] = spark_enabled + return pedest + + +class ManagedNetworkSchema(metaclass=PatchedSchemaMeta): + isolation_mode = StringTransformedEnum( + allowed_values=[ + IsolationMode.DISABLED, + IsolationMode.ALLOW_INTERNET_OUTBOUND, + IsolationMode.ALLOW_ONLY_APPROVED_OUTBOUND, + ], + casing_transform=camel_to_snake, + metadata={"description": "isolation mode for the workspace managed network."}, + ) + outbound_rules = fields.List( + UnionField( + [ + NestedField(PrivateEndpointOutboundRuleSchema, allow_none=False, unknown=EXCLUDE), + NestedField(ServiceTagOutboundRuleSchema, allow_none=False, unknown=EXCLUDE), + NestedField( + FqdnOutboundRuleSchema, allow_none=False, unknown=EXCLUDE + ), # this needs to be last since otherwise union field with match destination as a string + ], + allow_none=False, + is_strict=True, + ), + allow_none=True, + ) + firewall_sku = ExperimentalField( + StringTransformedEnum( + allowed_values=[ + FirewallSku.STANDARD, + FirewallSku.BASIC, + ], + casing_transform=camel_to_snake, + metadata={"description": "Firewall sku for FQDN rules in AllowOnlyApprovedOutbound mode"}, + ) + ) + network_id = fields.Str(required=False, dump_only=True) + status = NestedField(ManagedNetworkStatusSchema, allow_none=False, unknown=EXCLUDE) + + @post_load + def make(self, data, **kwargs): + outbound_rules = data.get("outbound_rules", False) + + firewall_sku = data.get("firewall_sku", False) + firewall_sku_value = _snake_to_camel(data["firewall_sku"]) if firewall_sku else FirewallSku.STANDARD + + if outbound_rules: + return ManagedNetwork( + isolation_mode=_snake_to_camel(data["isolation_mode"]), + outbound_rules=outbound_rules, + firewall_sku=firewall_sku_value, + ) + else: + return ManagedNetwork( + isolation_mode=_snake_to_camel(data["isolation_mode"]), + firewall_sku=firewall_sku_value, + ) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/private_endpoint.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/private_endpoint.py new file mode 100644 index 00000000..0235a4a0 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/private_endpoint.py @@ -0,0 +1,23 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +# pylint: disable=unused-argument + +from marshmallow import fields, post_load + +from azure.ai.ml._schema.core.fields import NestedField +from azure.ai.ml._schema.core.schema import PatchedSchemaMeta + +from .endpoint_connection import EndpointConnectionSchema + + +class PrivateEndpointSchema(metaclass=PatchedSchemaMeta): + approval_type = fields.Str() + connections = fields.Dict(keys=fields.Str(), values=NestedField(EndpointConnectionSchema)) + + @post_load + def make(self, data, **kwargs): + from azure.ai.ml.entities import PrivateEndpoint + + return PrivateEndpoint(**data) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/serverless_compute.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/serverless_compute.py new file mode 100644 index 00000000..5137e57f --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/serverless_compute.py @@ -0,0 +1,52 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- +from marshmallow import fields +from marshmallow.decorators import post_load, validates + +from azure.ai.ml._schema._utils.utils import ArmId +from azure.ai.ml._schema.core.schema import PathAwareSchema +from azure.ai.ml.entities._workspace.serverless_compute import ServerlessComputeSettings + + +class ServerlessComputeSettingsSchema(PathAwareSchema): + """Schema for ServerlessComputeSettings. + + :param custom_subnet: The custom subnet to use for serverless computes created in the workspace. + :type custom_subnet: Optional[ArmId] + :param no_public_ip: Whether to disable public ip for the compute. Only valid if custom_subnet is defined. + :type no_public_ip: bool + """ + + custom_subnet = fields.Str(allow_none=True) + no_public_ip = fields.Bool(load_default=False) + + @post_load + def make(self, data, **_kwargs) -> ServerlessComputeSettings: + """Create a ServerlessComputeSettings object from the marshmallow schema. + + :param data: The data from which the ServerlessComputeSettings are being loaded. + :type data: OrderedDict[str, Any] + :returns: A ServerlessComputeSettings object. + :rtype: azure.ai.ml.entities._workspace.serverless_compute.ServerlessComputeSettings + """ + custom_subnet = data.pop("custom_subnet", None) + if custom_subnet == "None": + custom_subnet = None # For loading from YAML when the user wants to trigger a removal + no_public_ip = data.pop("no_public_ip", False) + return ServerlessComputeSettings(custom_subnet=custom_subnet, no_public_ip=no_public_ip) + + @validates("custom_subnet") + def validate_custom_subnet(self, data: str, **_kwargs): + """Validates the custom_subnet field matches the ARM ID format or is a None-recognizable value. + + :param data: The candidate custom_subnet to validate. + :type data: str + :raises ValidationError: If the custom_subnet is not formatted as an ARM ID. + """ + if data == "None" or data is None: + # If the string is literally "None", then it should be deserialized to None + pass + else: + # Verify that we can transform it to an ArmId if it is not None. + ArmId(data) diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/workspace.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/workspace.py new file mode 100644 index 00000000..1df06f97 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/_schema/workspace/workspace.py @@ -0,0 +1,49 @@ +# --------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# --------------------------------------------------------- + +from marshmallow import EXCLUDE, fields + +from azure.ai.ml._schema._utils.utils import validate_arm_str +from azure.ai.ml._schema.core.fields import NestedField, StringTransformedEnum +from azure.ai.ml._schema.core.schema import PathAwareSchema +from azure.ai.ml._schema.workspace.customer_managed_key import CustomerManagedKeySchema +from azure.ai.ml._schema.workspace.identity import IdentitySchema +from azure.ai.ml._schema.workspace.network_acls import NetworkAclsSchema +from azure.ai.ml._schema.workspace.networking import ManagedNetworkSchema +from azure.ai.ml._schema.workspace.serverless_compute import ServerlessComputeSettingsSchema +from azure.ai.ml._utils.utils import snake_to_pascal +from azure.ai.ml.constants._common import PublicNetworkAccess + + +class WorkspaceSchema(PathAwareSchema): + name = fields.Str(required=True) + location = fields.Str() + id = fields.Str(dump_only=True) + resource_group = fields.Str() + description = fields.Str() + discovery_url = fields.Str() + display_name = fields.Str() + hbi_workspace = fields.Bool() + storage_account = fields.Str(validate=validate_arm_str) + container_registry = fields.Str(validate=validate_arm_str) + key_vault = fields.Str(validate=validate_arm_str) + application_insights = fields.Str(validate=validate_arm_str) + customer_managed_key = NestedField(CustomerManagedKeySchema) + tags = fields.Dict(keys=fields.Str(), values=fields.Str()) + mlflow_tracking_uri = fields.Str(dump_only=True) + image_build_compute = fields.Str() + public_network_access = StringTransformedEnum( + allowed_values=[PublicNetworkAccess.DISABLED, PublicNetworkAccess.ENABLED], + casing_transform=snake_to_pascal, + ) + network_acls = NestedField(NetworkAclsSchema) + system_datastores_auth_mode = fields.Str() + identity = NestedField(IdentitySchema) + primary_user_assigned_identity = fields.Str() + workspace_hub = fields.Str(validate=validate_arm_str) + managed_network = NestedField(ManagedNetworkSchema, unknown=EXCLUDE) + provision_network_now = fields.Bool() + enable_data_isolation = fields.Bool() + allow_roleassignment_on_rg = fields.Bool() + serverless_compute = NestedField(ServerlessComputeSettingsSchema) |
