1111from azure .identity import DefaultAzureCredential
1212from azure .storage .blob import BlobServiceClient
1313from azure .storage .blob .aio import BlobServiceClient as BlobServiceClientAsync
14- from environs import Env
1514
1615ENDPOINT_ERROR_MSG = "Could not find connection string in environment variables"
1716
1817
19- class CosmosClientSingleton :
18+ class _CosmosClientSingleton :
2019 """
2120 Singleton class for a CosmosClient instance.
2221
@@ -29,19 +28,19 @@ class CosmosClientSingleton:
2928 @classmethod
3029 def get_instance (cls ):
3130 if not cls ._instance :
32- endpoint = os .getenv ("COSMOS_URI_ENDPOINT" )
3331 conn_string = os .getenv ("COSMOS_CONNECTION_STRING" )
3432 if conn_string :
3533 cls ._instance = CosmosClient .from_connection_string (conn_string )
3634 else :
35+ endpoint = os .getenv ("COSMOS_URI_ENDPOINT" )
3736 credential = DefaultAzureCredential ()
3837 cls ._instance = CosmosClient (endpoint , credential )
3938 return cls ._instance
4039
4140
42- class BlobServiceClientSingleton :
41+ class _BlobServiceClientSingleton :
4342 """
44- Singleton class for BlobServiceClient.
43+ Singleton class for a BlobServiceClient instance .
4544
4645 If a connection string is available, it will be used to create the BlobServiceClient instance.
4746 Otherwise assume managed identity is used.
@@ -61,28 +60,16 @@ def get_instance(cls) -> BlobServiceClient:
6160 cls ._instance = BlobServiceClient (account_url , credential = credential )
6261 return cls ._instance
6362
64- @classmethod
65- def get_storage_account_name (cls ) -> str :
66- conn_string = os .getenv ("STORAGE_CONNECTION_STRING" )
67- if conn_string :
68- # parse account name from the connection string
69- meta_info = {}
70- for meta_data in conn_string .split (";" ):
71- if not meta_data :
72- continue
73- m = meta_data .split ("=" , 1 )
74- if len (m ) != 2 :
75- continue
76- meta_info [m [0 ]] = m [1 ]
77- return meta_info ["AccountName" ]
78- else :
79- account_url = os .getenv ("STORAGE_ACCOUNT_BLOB_URL" )
80- return account_url .split ("//" )[1 ].split ("." )[0 ]
8163
64+ class _BlobServiceClientSingletonAsync :
65+ """
66+ Singleton class for a BlobServiceClientAsync instance.
67+
68+ If a connection string is available, it will be used to create the BlobServiceClientAsync instance.
69+ Otherwise assume managed identity is used.
70+ """
8271
83- class BlobServiceClientSingletonAsync :
8472 _instance = None
85- _env = Env ()
8673
8774 @classmethod
8875 def get_instance (cls ) -> BlobServiceClientAsync :
@@ -100,43 +87,15 @@ def get_instance(cls) -> BlobServiceClientAsync:
10087 )
10188 return cls ._instance
10289
103- @classmethod
104- def get_storage_account_name (cls ) -> str :
105- conn_string = os .getenv ("STORAGE_CONNECTION_STRING" )
106- if conn_string :
107- # parse account name from the connection string
108- meta_info = {}
109- for meta_data in conn_string .split (";" ):
110- if not meta_data :
111- continue
112- m = meta_data .split ("=" , 1 )
113- if len (m ) != 2 :
114- continue
115- meta_info [m [0 ]] = m [1 ]
116- return meta_info ["AccountName" ]
117- else :
118- account_url = os .environ ["STORAGE_ACCOUNT_BLOB_URL" ]
119- return account_url .split ("//" )[1 ].split ("." )[0 ]
120-
121-
122- def get_database_client (database_name : str ) -> DatabaseProxy :
123- client = CosmosClientSingleton .get_instance ()
124- return client .get_database_client (database_name )
125-
126-
127- def get_database_container_client (
128- database_name : str , container_name : str
129- ) -> ContainerProxy :
130- db_client = get_database_client (database_name )
131- return db_client .get_container_client (container_name )
132-
13390
13491class AzureClientManager :
13592 """
13693 Manages the clients for Azure blob storage and Cosmos DB.
13794
13895 Attributes:
139- azure_storage_blob_url (str): The blob endpoint for azure storage.
96+ storage_blob_url (str): The blob endpoint for azure storage.
97+ storage_account_name (str): The name of the azure storage account.
98+ storage_account_hostname (str): The hostname of the azure blob storage account.
14099 cosmos_uri_endpoint (str): The uri endpoint for the Cosmos DB.
141100 _blob_service_client (BlobServiceClient): The blob service client.
142101 _blob_service_client_async (BlobServiceClientAsync): The asynchronous blob service client.
@@ -146,37 +105,34 @@ class AzureClientManager:
146105 """
147106
148107 def __init__ (self ) -> None :
149- self .azure_storage_blob_url = os .getenv ("STORAGE_ACCOUNT_BLOB_URL" )
150- self .azure_storage_connection_string = os .getenv ("STORAGE_CONNECTION_STRING" )
108+ self .storage_blob_url = os .getenv ("STORAGE_ACCOUNT_BLOB_URL" )
109+ self .storage_connection_string = os .getenv ("STORAGE_CONNECTION_STRING" )
151110 self .cosmos_uri_endpoint = os .getenv ("COSMOS_URI_ENDPOINT" )
152111 self .cosmos_connection_string = os .getenv ("COSMOS_CONNECTION_STRING" )
153-
154- if self .cosmos_connection_string :
155- self ._cosmos_client = CosmosClient .from_connection_string (
156- self .cosmos_connection_string
157- )
158- else :
159- self ._cosmos_client = CosmosClient (
160- self .cosmos_uri_endpoint , credential = DefaultAzureCredential ()
161- )
162- if self .azure_storage_connection_string :
163- self ._blob_service_client = BlobServiceClient .from_connection_string (
164- self .azure_storage_connection_string
165- )
166- self ._blob_service_client_async = (
167- BlobServiceClientAsync .from_connection_string (
168- self .azure_storage_connection_string
169- )
170- )
112+ self ._cosmos_client = _CosmosClientSingleton .get_instance ()
113+ self ._blob_service_client = _BlobServiceClientSingleton .get_instance ()
114+ self ._blob_service_client_async = (
115+ _BlobServiceClientSingletonAsync .get_instance ()
116+ )
117+
118+ # parse account name from the azure storage connection string or blob url
119+ if self .storage_connection_string :
120+ meta_info = {}
121+ for meta_data in self .storage_connection_string .split (";" ):
122+ if not meta_data :
123+ continue
124+ m = meta_data .split ("=" , 1 )
125+ if len (m ) != 2 :
126+ continue
127+ meta_info [m [0 ]] = m [1 ]
128+ self .storage_account_name = meta_info ["AccountName" ]
171129 else :
172- self ._blob_service_client = BlobServiceClient (
173- account_url = self .azure_storage_blob_url ,
174- credential = DefaultAzureCredential (),
175- )
176- self ._blob_service_client_async = BlobServiceClientAsync (
177- account_url = self .azure_storage_blob_url ,
178- credential = DefaultAzureCredential (),
179- )
130+ self .storage_account_name = self .storage_blob_url .split ("//" )[1 ].split ("." )[
131+ 0
132+ ]
133+
134+ # parse account hostname from the azure storage connection string or blob url
135+ self .storage_account_hostname = self ._blob_service_client .url .split ("//" )[1 ]
180136
181137 def get_blob_service_client (self ) -> BlobServiceClient :
182138 """
@@ -215,11 +171,7 @@ def get_cosmos_database_client(self, database_name: str) -> DatabaseProxy:
215171 Returns:
216172 DatabaseProxy: The Cosmos database client.
217173 """
218- if not hasattr (self , "_cosmos_database_client" ):
219- self ._cosmos_database_client = self ._cosmos_client .get_database_client (
220- database = database_name
221- )
222- return self ._cosmos_database_client
174+ return self ._cosmos_client .get_database_client (database = database_name )
223175
224176 def get_cosmos_container_client (
225177 self , database_name : str , container_name : str
@@ -234,8 +186,6 @@ def get_cosmos_container_client(
234186 Returns:
235187 ContainerProxy: The Cosmos DB container client.
236188 """
237- if not hasattr (self , "_cosmos_container_client" ):
238- self ._cosmos_container_client = self .get_cosmos_database_client (
239- database_name = database_name
240- ).get_container_client (container = container_name )
241- return self ._cosmos_container_client
189+ return self ._cosmos_client .get_database_client (
190+ database = database_name
191+ ).get_container_client (container = container_name )
0 commit comments