about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry')
-rw-r--r--.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/__init__.py5
-rw-r--r--.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/registry.py231
-rw-r--r--.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/registry_support_classes.py273
-rw-r--r--.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/util.py17
4 files changed, 526 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/__init__.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/__init__.py
new file mode 100644
index 00000000..fdf8caba
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/__init__.py
@@ -0,0 +1,5 @@
+# ---------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# ---------------------------------------------------------
+
+__path__ = __import__("pkgutil").extend_path(__path__, __name__)
diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/registry.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/registry.py
new file mode 100644
index 00000000..a01e70d3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/registry.py
@@ -0,0 +1,231 @@
+# ---------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# ---------------------------------------------------------
+
+# pylint: disable=protected-access
+
+from os import PathLike
+from pathlib import Path
+from typing import IO, Any, AnyStr, Dict, List, Optional, Union
+
+from azure.ai.ml._restclient.v2022_10_01_preview.models import ManagedServiceIdentity as RestManagedServiceIdentity
+from azure.ai.ml._restclient.v2022_10_01_preview.models import (
+    ManagedServiceIdentityType as RestManagedServiceIdentityType,
+)
+from azure.ai.ml._restclient.v2022_10_01_preview.models import Registry as RestRegistry
+from azure.ai.ml._restclient.v2022_10_01_preview.models import RegistryProperties
+from azure.ai.ml._utils.utils import dump_yaml_to_file
+from azure.ai.ml.constants._common import BASE_PATH_CONTEXT_KEY, PARAMS_OVERRIDE_KEY
+from azure.ai.ml.entities._assets.intellectual_property import IntellectualProperty
+from azure.ai.ml.entities._credentials import IdentityConfiguration
+from azure.ai.ml.entities._resource import Resource
+from azure.ai.ml.entities._util import load_from_dict
+
+from .registry_support_classes import RegistryRegionDetails
+
+CONTAINER_REGISTRY = "container_registry"
+REPLICATION_LOCATIONS = "replication_locations"
+INTELLECTUAL_PROPERTY = "intellectual_property"
+
+
+class Registry(Resource):
+    def __init__(
+        self,
+        *,
+        name: str,
+        location: str,
+        identity: Optional[IdentityConfiguration] = None,
+        tags: Optional[Dict[str, str]] = None,
+        public_network_access: Optional[str] = None,
+        discovery_url: Optional[str] = None,
+        intellectual_property: Optional[IntellectualProperty] = None,
+        managed_resource_group: Optional[str] = None,
+        mlflow_registry_uri: Optional[str] = None,
+        replication_locations: Optional[List[RegistryRegionDetails]],
+        **kwargs: Any,
+    ):
+        """Azure ML registry.
+
+        :param name: Name of the registry. Must be globally unique and is immutable.
+        :type name: str
+        :param location: The location this registry resource is located in.
+        :type location: str
+        :param identity: registry's System Managed Identity
+        :type identity: ManagedServiceIdentity
+        :param tags: Tags of the registry.
+        :type tags: dict
+        :param public_network_access: Whether to allow public endpoint connectivity.
+        :type public_network_access: str
+        :param discovery_url: Backend service base url for the registry.
+        :type discovery_url: str
+        :param intellectual_property: **Experimental** Intellectual property publisher.
+        :type intellectual_property: ~azure.ai.ml.entities.IntellectualProperty
+        :param managed_resource_group: Managed resource group created for the registry.
+        :type managed_resource_group: str
+        :param mlflow_registry_uri: Ml flow tracking uri for the registry.
+        :type mlflow_registry_uri: str
+        :param region_details: Details of each region the registry is in.
+        :type region_details: List[RegistryRegionDetails]
+        :param kwargs: A dictionary of additional configuration parameters.
+        :type kwargs: dict
+        """
+
+        super().__init__(name=name, tags=tags, **kwargs)
+
+        # self.display_name = name # Do we need a top-level visible name value?
+        self.location = location
+        self.identity = identity
+        self.replication_locations = replication_locations
+        self.public_network_access = public_network_access
+        self.intellectual_property = intellectual_property
+        self.managed_resource_group = managed_resource_group
+        self.discovery_url = discovery_url
+        self.mlflow_registry_uri = mlflow_registry_uri
+        self.container_registry = None
+
+    def dump(
+        self,
+        dest: Union[str, PathLike, IO[AnyStr]],
+        **kwargs: Any,
+    ) -> None:
+        """Dump the registry spec into a file in yaml format.
+
+        :param dest: Path to a local file as the target, new file will be created, raises exception if the file exists.
+        :type dest: str
+        """
+        yaml_serialized = self._to_dict()
+        dump_yaml_to_file(dest, yaml_serialized, default_flow_style=False)
+
+    # The internal structure of the registry object is closer to how it's
+    # represented by the registry API, which differs from how registries
+    # are represented in YAML. This function converts those differences.
+    def _to_dict(self) -> Dict:
+        # JIT import to avoid experimental warnings on unrelated calls
+        from azure.ai.ml._schema.registry.registry import RegistrySchema
+
+        schema = RegistrySchema(context={BASE_PATH_CONTEXT_KEY: "./"})
+
+        # Grab the first acr account of the first region and set that
+        # as the system-wide container registry.
+        # Although support for multiple ACRs per region, as well as
+        # different ACRs per region technically exist according to the
+        # API schema, we do not want to surface that as an option,
+        # since the use cases for variable/multiple ACRs are extremely
+        # limited, and would probably just confuse most users.
+        if self.replication_locations and len(self.replication_locations) > 0:
+            if self.replication_locations[0].acr_config and len(self.replication_locations[0].acr_config) > 0:
+                self.container_registry = self.replication_locations[0].acr_config[0]  # type: ignore[assignment]
+
+        res: dict = schema.dump(self)
+        return res
+
+    @classmethod
+    def _load(
+        cls,
+        data: Optional[Dict] = None,
+        yaml_path: Optional[Union[PathLike, str]] = None,
+        params_override: Optional[list] = None,
+        **kwargs: Any,
+    ) -> "Registry":
+        data = data or {}
+        params_override = params_override or []
+        context = {
+            BASE_PATH_CONTEXT_KEY: Path(yaml_path).parent if yaml_path else Path("./"),
+            PARAMS_OVERRIDE_KEY: params_override,
+        }
+        # JIT import to avoid experimental warnings on unrelated calls
+        from azure.ai.ml._schema.registry.registry import RegistrySchema
+
+        loaded_schema = load_from_dict(RegistrySchema, data, context, **kwargs)
+        cls._convert_yaml_dict_to_entity_input(loaded_schema)
+        return Registry(**loaded_schema)
+
+    @classmethod
+    def _from_rest_object(cls, rest_obj: RestRegistry) -> Optional["Registry"]:
+        if not rest_obj:
+            return None
+        real_registry = rest_obj.properties
+
+        # Convert from api name region_details to user-shown name "replication locations"
+        replication_locations = []
+        if real_registry and real_registry.region_details:
+            replication_locations = [
+                RegistryRegionDetails._from_rest_object(details) for details in real_registry.region_details
+            ]
+        identity = None
+        if rest_obj.identity and isinstance(rest_obj.identity, RestManagedServiceIdentity):
+            identity = IdentityConfiguration._from_rest_object(rest_obj.identity)
+        return Registry(
+            name=rest_obj.name,
+            identity=identity,
+            id=rest_obj.id,
+            tags=rest_obj.tags,
+            location=rest_obj.location,
+            public_network_access=real_registry.public_network_access,
+            discovery_url=real_registry.discovery_url,
+            intellectual_property=(
+                IntellectualProperty(publisher=real_registry.intellectual_property_publisher)
+                if real_registry.intellectual_property_publisher
+                else None
+            ),
+            managed_resource_group=real_registry.managed_resource_group,
+            mlflow_registry_uri=real_registry.ml_flow_registry_uri,
+            replication_locations=replication_locations,  # type: ignore[arg-type]
+        )
+
+    # There are differences between what our registry validation schema
+    # accepts, and how we actually represent things internally.
+    # This is mostly due to the compromise required to balance
+    # the actual shape of registries as they're defined by
+    # autorest with how the spec wanted users to be able to
+    # configure them. This function should eventually be
+    @classmethod
+    def _convert_yaml_dict_to_entity_input(
+        cls,
+        input: Dict,  # pylint: disable=redefined-builtin
+    ) -> None:
+        # pop container_registry value.
+        global_acr_exists = False
+        if CONTAINER_REGISTRY in input:
+            acr_input = input.pop(CONTAINER_REGISTRY)
+            global_acr_exists = True
+        for region_detail in input[REPLICATION_LOCATIONS]:
+            # Apply container_registry as acr_config of each region detail
+            if global_acr_exists:
+                if not hasattr(region_detail, "acr_details") or len(region_detail.acr_details) == 0:
+                    region_detail.acr_config = [acr_input]  # pylint: disable=(possibly-used-before-assignment
+
+    def _to_rest_object(self) -> RestRegistry:
+        """Build current parameterized schedule instance to a registry object before submission.
+
+        :return: Rest registry.
+        :rtype: RestRegistry
+        """
+        identity = RestManagedServiceIdentity(type=RestManagedServiceIdentityType.SYSTEM_ASSIGNED)
+        replication_locations = []
+        if self.replication_locations:
+            replication_locations = [details._to_rest_object() for details in self.replication_locations]
+        # Notes about this construction.
+        # RestRegistry.properties.tags: this property exists due to swagger inheritance
+        # issues, don't actually use it, use top level RestRegistry.tags instead
+        # RestRegistry.properties.managed_resource_group_tags: Registries create a
+        # managed resource group to manage their internal sub-resources.
+        # We always want the tags on this MRG to match those of the registry itself
+        # to keep janitor policies aligned.
+        return RestRegistry(
+            name=self.name,
+            location=self.location,
+            identity=identity,
+            tags=self.tags,
+            properties=RegistryProperties(
+                public_network_access=self.public_network_access,
+                discovery_url=self.discovery_url,
+                intellectual_property_publisher=(
+                    (self.intellectual_property.publisher) if self.intellectual_property else None
+                ),
+                managed_resource_group=self.managed_resource_group,
+                ml_flow_registry_uri=self.mlflow_registry_uri,
+                region_details=replication_locations,
+                managed_resource_group_tags=self.tags,
+            ),
+        )
diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/registry_support_classes.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/registry_support_classes.py
new file mode 100644
index 00000000..810c5df5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/registry_support_classes.py
@@ -0,0 +1,273 @@
+# ---------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# ---------------------------------------------------------
+# pylint:disable=protected-access,no-else-return
+
+from copy import deepcopy
+from functools import reduce
+from typing import List, Optional, Union
+
+from azure.ai.ml._exception_helper import log_and_raise_error
+from azure.ai.ml._restclient.v2022_10_01_preview.models import AcrDetails as RestAcrDetails
+from azure.ai.ml._restclient.v2022_10_01_preview.models import ArmResourceId as RestArmResourceId
+from azure.ai.ml._restclient.v2022_10_01_preview.models import RegistryRegionArmDetails as RestRegistryRegionArmDetails
+from azure.ai.ml._restclient.v2022_10_01_preview.models import StorageAccountDetails as RestStorageAccountDetails
+from azure.ai.ml._restclient.v2022_10_01_preview.models import SystemCreatedAcrAccount as RestSystemCreatedAcrAccount
+from azure.ai.ml._restclient.v2022_10_01_preview.models import (
+    SystemCreatedStorageAccount as RestSystemCreatedStorageAccount,
+)
+from azure.ai.ml._restclient.v2022_10_01_preview.models import UserCreatedAcrAccount as RestUserCreatedAcrAccount
+from azure.ai.ml.constants._registry import StorageAccountType
+from azure.ai.ml.exceptions import ErrorCategory, ErrorTarget, ValidationErrorType, ValidationException
+
+from .util import _make_rest_user_storage_from_id
+
+
+# This exists despite not being used by the schema validator because this entire
+# class is an output only value from the API.
+class SystemCreatedAcrAccount:
+    def __init__(
+        self,
+        *,
+        acr_account_sku: str,
+        arm_resource_id: Optional[str] = None,
+    ):
+        """Azure ML ACR account.
+
+        :param acr_account_sku: The storage account service tier. Currently
+            only Premium is a valid option for registries.
+        :type acr_account_sku: str
+        :param arm_resource_id: Resource ID of the ACR account.
+        :type arm_resource_id: str. Default value is None.
+        """
+        self.acr_account_sku = acr_account_sku
+        self.arm_resource_id = arm_resource_id
+
+    # acr should technically be a union between str and SystemCreatedAcrAccount,
+    # but python doesn't accept self class references apparently.
+    # Class method instead of normal function to accept possible
+    # string input.
+    @classmethod
+    def _to_rest_object(cls, acr: Union[str, "SystemCreatedAcrAccount"]) -> RestAcrDetails:
+        if hasattr(acr, "acr_account_sku") and acr.acr_account_sku is not None:
+            # SKU enum requires input to be a capitalized word,
+            # so we format the input to be acceptable as long as spelling is
+            # correct.
+            acr_account_sku = acr.acr_account_sku.capitalize()
+            # We DO NOT want to set the arm_resource_id. The backend provides very
+            # unhelpful errors if you provide an empty/null/invalid resource ID,
+            # and ignores the value otherwise. It's better to avoid setting it in
+            # the conversion in this direction at all.
+            return RestAcrDetails(
+                system_created_acr_account=RestSystemCreatedAcrAccount(
+                    acr_account_sku=acr_account_sku,
+                )
+            )
+        else:
+            return RestAcrDetails(
+                user_created_acr_account=RestUserCreatedAcrAccount(arm_resource_id=RestArmResourceId(resource_id=acr))
+            )
+
+    @classmethod
+    def _from_rest_object(cls, rest_obj: RestAcrDetails) -> Optional["Union[str, SystemCreatedAcrAccount]"]:
+        if not rest_obj:
+            return None
+        if hasattr(rest_obj, "system_created_acr_account") and rest_obj.system_created_acr_account is not None:
+            resource_id = None
+            if rest_obj.system_created_acr_account.arm_resource_id:
+                resource_id = rest_obj.system_created_acr_account.arm_resource_id.resource_id
+            return SystemCreatedAcrAccount(
+                acr_account_sku=rest_obj.system_created_acr_account.acr_account_sku,
+                arm_resource_id=resource_id,
+            )
+        elif hasattr(rest_obj, "user_created_acr_account") and rest_obj.user_created_acr_account is not None:
+            res: Optional[str] = rest_obj.user_created_acr_account.arm_resource_id.resource_id
+            return res
+        else:
+            return None
+
+
+class SystemCreatedStorageAccount:
+    def __init__(
+        self,
+        *,
+        storage_account_hns: bool,
+        storage_account_type: Optional[StorageAccountType],
+        arm_resource_id: Optional[str] = None,
+        replicated_ids: Optional[List[str]] = None,
+        replication_count: int = 1,
+    ):
+        """
+        :param arm_resource_id: Resource ID of the storage account.
+        :type arm_resource_id: str
+        :param storage_account_hns: Whether or not this storage account
+            has hierarchical namespaces enabled.
+        :type storage_account_hns: bool
+        :param storage_account_type: Allowed values: "Standard_LRS",
+            "Standard_GRS, "Standard_RAGRS", "Standard_ZRS", "Standard_GZRS",
+            "Standard_RAGZRS", "Premium_LRS", "Premium_ZRS"
+        :type storage_account_type: StorageAccountType
+        :param replication_count: The number of replicas of this storage account
+            that should be created. Defaults to 1. Values less than 1 are invalid.
+        :type replication_count: int
+        :param replicated_ids: If this storage was replicated, then this is a
+            list of all storage IDs with these settings for this registry.
+            Defaults to none for un-replicated storage accounts.
+        :type replicated_ids: List[str]
+        """
+        self.arm_resource_id = arm_resource_id
+        self.storage_account_hns = storage_account_hns
+        self.storage_account_type = storage_account_type
+        self.replication_count = replication_count
+        self.replicated_ids = replicated_ids
+
+
+# Per-region information for registries.
+class RegistryRegionDetails:
+    def __init__(
+        self,
+        *,
+        acr_config: Optional[List[Union[str, SystemCreatedAcrAccount]]] = None,
+        location: Optional[str] = None,
+        storage_config: Optional[Union[List[str], SystemCreatedStorageAccount]] = None,
+    ):
+        """Details for each region a registry is in.
+
+        :param acr_details: List of ACR account details. Each value can either be a
+            single string representing the arm_resource_id of a user-created
+            acr_details object, or a entire SystemCreatedAcrAccount object.
+        :type acr_details: List[Union[str, SystemCreatedAcrAccount]]
+        :param location: The location where the registry exists.
+        :type location: str
+        :param storage_account_details: List of storage accounts. Each value
+            can either be a single string representing the arm_resource_id of
+            a user-created storage account, or an entire
+            SystemCreatedStorageAccount object.
+        :type storage_account_details: Union[List[str], SystemCreatedStorageAccount]
+        """
+        self.acr_config = acr_config
+        self.location = location
+        self.storage_config = storage_config
+
+    @classmethod
+    def _from_rest_object(cls, rest_obj: RestRegistryRegionArmDetails) -> Optional["RegistryRegionDetails"]:
+        if not rest_obj:
+            return None
+        converted_acr_details = []
+        if rest_obj.acr_details:
+            converted_acr_details = [SystemCreatedAcrAccount._from_rest_object(acr) for acr in rest_obj.acr_details]
+        storages: Optional[Union[List[str], SystemCreatedStorageAccount]] = []
+        if rest_obj.storage_account_details:
+            storages = cls._storage_config_from_rest_object(rest_obj.storage_account_details)
+
+        return RegistryRegionDetails(
+            acr_config=converted_acr_details,  # type: ignore[arg-type]
+            location=rest_obj.location,
+            storage_config=storages,
+        )
+
+    def _to_rest_object(self) -> RestRegistryRegionArmDetails:
+        converted_acr_details = []
+        if self.acr_config:
+            converted_acr_details = [SystemCreatedAcrAccount._to_rest_object(acr) for acr in self.acr_config]
+        storages = []
+        if self.storage_config:
+            storages = self._storage_config_to_rest_object()
+        return RestRegistryRegionArmDetails(
+            acr_details=converted_acr_details,
+            location=self.location,
+            storage_account_details=storages,
+        )
+
+    def _storage_config_to_rest_object(self) -> List[RestStorageAccountDetails]:
+        storage = self.storage_config
+        # storage_config can either be a single system-created storage account,
+        # or list of user-inputted id's.
+        if (
+            storage is not None
+            and not isinstance(storage, list)
+            and hasattr(storage, "storage_account_type")
+            and storage.storage_account_type is not None
+        ):
+            # We DO NOT want to set the arm_resource_id. The backend provides very
+            # unhelpful errors if you provide an empty/null/invalid resource ID,
+            # and ignores the value otherwise. It's better to avoid setting it in
+            # the conversion in this direction at all.
+            # We don't bother processing storage_account_type because the
+            # rest version is case insensitive.
+            account = RestStorageAccountDetails(
+                system_created_storage_account=RestSystemCreatedStorageAccount(
+                    storage_account_hns_enabled=storage.storage_account_hns,
+                    storage_account_type=storage.storage_account_type,
+                )
+            )
+            # duplicate this value based on the replication_count
+            count = storage.replication_count
+            if count < 1:
+                raise ValueError(f"Replication count cannot be less than 1. Value was: {count}.")
+            return [deepcopy(account) for _ in range(0, count)]
+        elif storage is not None and not isinstance(storage, SystemCreatedStorageAccount) and len(storage) > 0:
+            return [_make_rest_user_storage_from_id(user_id=user_id) for user_id in storage]
+        else:
+            return []
+
+    @classmethod
+    def _storage_config_from_rest_object(
+        cls, rest_configs: Optional[List]
+    ) -> Optional[Union[List[str], SystemCreatedStorageAccount]]:
+        if not rest_configs:
+            return None
+        num_configs = len(rest_configs)
+        if num_configs == 0:
+            return None
+        system_created_count = reduce(
+            # TODO: Bug Item number: 2883323
+            lambda x, y: int(x) + int(y),  # type: ignore
+            [
+                hasattr(config, "system_created_storage_account") and config.system_created_storage_account is not None
+                for config in rest_configs
+            ],
+        )
+        # configs should be mono-typed. Either they're all system created
+        # or all user created.
+        if system_created_count == num_configs:
+            # System created case - assume all elements are duplicates
+            # of a single storage configuration.
+            # Convert back into a single local representation by
+            # combining id's into a list, and using the first element's
+            # account type and hns.
+            first_config = rest_configs[0].system_created_storage_account
+            resource_id = None
+            if first_config.arm_resource_id:
+                resource_id = first_config.arm_resource_id.resource_id
+            # account for ids of duplicated if they exist
+            replicated_ids = None
+            if num_configs > 1:
+                replicated_ids = [
+                    config.system_created_storage_account.arm_resource_id.resource_id for config in rest_configs
+                ]
+            return SystemCreatedStorageAccount(
+                storage_account_hns=first_config.storage_account_hns_enabled,
+                storage_account_type=(
+                    (StorageAccountType(first_config.storage_account_type.lower()))
+                    if first_config.storage_account_type
+                    else None
+                ),
+                arm_resource_id=resource_id,
+                replication_count=num_configs,
+                replicated_ids=replicated_ids,
+            )
+        elif system_created_count == 0:
+            return [config.user_created_storage_account.arm_resource_id.resource_id for config in rest_configs]
+        else:
+            msg = f"""tried reading in a registry whose storage accounts were not
+                mono-managed or user-created. {system_created_count} out of {num_configs} were managed."""
+            err = ValidationException(
+                message=msg,
+                target=ErrorTarget.REGISTRY,
+                no_personal_data_message=msg,
+                error_category=ErrorCategory.USER_ERROR,
+                error_type=ValidationErrorType.INVALID_VALUE,
+            )
+            log_and_raise_error(err)
+            return None
diff --git a/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/util.py b/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/util.py
new file mode 100644
index 00000000..18f56169
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/ai/ml/entities/_registry/util.py
@@ -0,0 +1,17 @@
+# ---------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# ---------------------------------------------------------
+
+from azure.ai.ml._restclient.v2022_10_01_preview.models import ArmResourceId as RestArmResourceId
+from azure.ai.ml._restclient.v2022_10_01_preview.models import StorageAccountDetails as RestStorageAccountDetails
+from azure.ai.ml._restclient.v2022_10_01_preview.models import (
+    UserCreatedStorageAccount as RestUserCreatedStorageAccount,
+)
+
+
+def _make_rest_user_storage_from_id(*, user_id: str) -> RestStorageAccountDetails:
+    return RestStorageAccountDetails(
+        user_created_storage_account=RestUserCreatedStorageAccount(
+            arm_resource_id=RestArmResourceId(resource_id=user_id)
+        )
+    )