semantic-link-labs 0.8.11__py3-none-any.whl → 0.9.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of semantic-link-labs might be problematic. Click here for more details.
- {semantic_link_labs-0.8.11.dist-info → semantic_link_labs-0.9.1.dist-info}/METADATA +9 -6
- {semantic_link_labs-0.8.11.dist-info → semantic_link_labs-0.9.1.dist-info}/RECORD +40 -40
- {semantic_link_labs-0.8.11.dist-info → semantic_link_labs-0.9.1.dist-info}/WHEEL +1 -1
- sempy_labs/__init__.py +29 -2
- sempy_labs/_authentication.py +78 -4
- sempy_labs/_capacities.py +770 -200
- sempy_labs/_capacity_migration.py +7 -37
- sempy_labs/_clear_cache.py +8 -8
- sempy_labs/_deployment_pipelines.py +1 -1
- sempy_labs/_gateways.py +2 -0
- sempy_labs/_generate_semantic_model.py +8 -0
- sempy_labs/_helper_functions.py +119 -79
- sempy_labs/_job_scheduler.py +138 -3
- sempy_labs/_list_functions.py +40 -31
- sempy_labs/_model_bpa.py +207 -204
- sempy_labs/_model_bpa_bulk.py +2 -2
- sempy_labs/_model_bpa_rules.py +3 -3
- sempy_labs/_notebooks.py +2 -0
- sempy_labs/_query_scale_out.py +8 -0
- sempy_labs/_sql.py +11 -7
- sempy_labs/_vertipaq.py +4 -2
- sempy_labs/_warehouses.py +6 -6
- sempy_labs/admin/_basic_functions.py +156 -103
- sempy_labs/admin/_domains.py +7 -2
- sempy_labs/admin/_git.py +4 -1
- sempy_labs/admin/_items.py +7 -2
- sempy_labs/admin/_scanner.py +7 -4
- sempy_labs/directlake/_directlake_schema_compare.py +7 -2
- sempy_labs/directlake/_directlake_schema_sync.py +6 -0
- sempy_labs/directlake/_dl_helper.py +51 -31
- sempy_labs/directlake/_get_directlake_lakehouse.py +20 -27
- sempy_labs/directlake/_update_directlake_partition_entity.py +5 -0
- sempy_labs/lakehouse/_get_lakehouse_columns.py +17 -22
- sempy_labs/lakehouse/_get_lakehouse_tables.py +20 -32
- sempy_labs/lakehouse/_lakehouse.py +2 -19
- sempy_labs/report/_generate_report.py +45 -0
- sempy_labs/report/_report_bpa.py +2 -2
- sempy_labs/tom/_model.py +97 -16
- {semantic_link_labs-0.8.11.dist-info → semantic_link_labs-0.9.1.dist-info}/LICENSE +0 -0
- {semantic_link_labs-0.8.11.dist-info → semantic_link_labs-0.9.1.dist-info}/top_level.txt +0 -0
sempy_labs/_capacities.py
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import sempy.fabric as fabric
|
|
2
|
-
from typing import Optional, List
|
|
2
|
+
from typing import Optional, List, Tuple
|
|
3
3
|
from sempy._utils._log import log
|
|
4
4
|
import sempy_labs._icons as icons
|
|
5
5
|
from sempy.fabric.exceptions import FabricHTTPException
|
|
6
6
|
import requests
|
|
7
|
-
from sempy_labs._helper_functions import _get_azure_token_credentials
|
|
8
7
|
import pandas as pd
|
|
8
|
+
from sempy_labs._authentication import _get_headers, ServicePrincipalTokenProvider
|
|
9
|
+
from uuid import UUID
|
|
10
|
+
from sempy_labs._helper_functions import _is_valid_uuid
|
|
11
|
+
import sempy_labs._authentication as auth
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
def _add_sll_tag(payload, tags):
|
|
@@ -24,20 +27,19 @@ def _add_sll_tag(payload, tags):
|
|
|
24
27
|
def create_fabric_capacity(
|
|
25
28
|
capacity_name: str,
|
|
26
29
|
azure_subscription_id: str,
|
|
27
|
-
key_vault_uri: str,
|
|
28
|
-
key_vault_tenant_id: str,
|
|
29
|
-
key_vault_client_id: str,
|
|
30
|
-
key_vault_client_secret: str,
|
|
31
30
|
resource_group: str,
|
|
32
31
|
region: str,
|
|
33
32
|
sku: str,
|
|
34
33
|
admin_members: str | List[str],
|
|
35
34
|
tags: Optional[dict] = None,
|
|
35
|
+
**kwargs,
|
|
36
36
|
):
|
|
37
37
|
"""
|
|
38
38
|
This function creates a new Fabric capacity within an Azure subscription.
|
|
39
39
|
|
|
40
|
-
This is a wrapper function for the following API: `Fabric Capacities - Create Or Update <https://learn.microsoft.com/rest/api/microsoftfabric/fabric-capacities/create-or-update
|
|
40
|
+
This is a wrapper function for the following API: `Fabric Capacities - Create Or Update <https://learn.microsoft.com/rest/api/microsoftfabric/fabric-capacities/create-or-update>`_.
|
|
41
|
+
|
|
42
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
41
43
|
|
|
42
44
|
Parameters
|
|
43
45
|
----------
|
|
@@ -45,14 +47,6 @@ def create_fabric_capacity(
|
|
|
45
47
|
Name of the Fabric capacity.
|
|
46
48
|
azure_subscription_id : str
|
|
47
49
|
The Azure subscription ID.
|
|
48
|
-
key_vault_uri : str
|
|
49
|
-
The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
|
|
50
|
-
key_vault_tenant_id : str
|
|
51
|
-
The name of the Azure key vault secret storing the Tenant ID.
|
|
52
|
-
key_vault_client_id : str
|
|
53
|
-
The name of the Azure key vault secret storing the Client ID.
|
|
54
|
-
key_vault_client_secret : str
|
|
55
|
-
The name of the Azure key vault secret storing the Client Secret.
|
|
56
50
|
resource_group : str
|
|
57
51
|
The name of the Azure resource group.
|
|
58
52
|
region : str
|
|
@@ -65,8 +59,6 @@ def create_fabric_capacity(
|
|
|
65
59
|
Tag(s) to add to the capacity. Example: {'tagName': 'tagValue'}.
|
|
66
60
|
"""
|
|
67
61
|
|
|
68
|
-
from azure.mgmt.resource import ResourceManagementClient
|
|
69
|
-
|
|
70
62
|
if isinstance(admin_members, str):
|
|
71
63
|
admin_members = [admin_members]
|
|
72
64
|
|
|
@@ -143,29 +135,41 @@ def create_fabric_capacity(
|
|
|
143
135
|
f"{icons.red_dot} Invalid region. Valid options: {valid_regions}."
|
|
144
136
|
)
|
|
145
137
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
138
|
+
token_provider = auth.token_provider.get()
|
|
139
|
+
if token_provider is None:
|
|
140
|
+
token_provider = ServicePrincipalTokenProvider.from_azure_key_vault(
|
|
141
|
+
key_vault_uri=kwargs["key_vault_uri"],
|
|
142
|
+
key_vault_tenant_id=kwargs["key_vault_tenant_id"],
|
|
143
|
+
key_vault_client_id=kwargs["key_vault_client_id"],
|
|
144
|
+
key_vault_client_secret=kwargs["key_vault_client_secret"],
|
|
145
|
+
)
|
|
146
|
+
print(
|
|
147
|
+
f"{icons.info} Please use the 'token_provider' parameter instead of the key vault parameters within this function as the key vault parameters have been deprecated."
|
|
148
|
+
)
|
|
149
|
+
headers = _get_headers(token_provider, audience="azure")
|
|
154
150
|
|
|
155
151
|
if resource_group is None:
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
152
|
+
dfRG = list_resource_groups(
|
|
153
|
+
azure_subscription_id=azure_subscription_id,
|
|
154
|
+
filter="resourceType eq 'Microsoft.PowerBIDedicated/capacities'",
|
|
155
|
+
)
|
|
156
|
+
dfRG_filt = dfRG[
|
|
157
|
+
dfRG["Resource Group Name"]
|
|
158
|
+
== capacity_name.removesuffix(icons.migrate_capacity_suffix)
|
|
159
|
+
]
|
|
160
|
+
if not dfRG_filt.empty:
|
|
161
|
+
resource_group = dfRG_filt["Resource Group Name"].iloc[0]
|
|
162
|
+
print(
|
|
163
|
+
f"{icons.yellow_dot} Override resource group flag detected for A SKUs - using the existing resource group '{resource_group}' for the '{capacity_name}' capacity."
|
|
164
|
+
)
|
|
164
165
|
else:
|
|
165
166
|
# Attempt to get the resource group
|
|
166
167
|
try:
|
|
167
|
-
|
|
168
|
-
|
|
168
|
+
dfRG = get_resource_group(
|
|
169
|
+
azure_subscription_id=azure_subscription_id,
|
|
170
|
+
resource_group=resource_group,
|
|
171
|
+
)
|
|
172
|
+
if dfRG["Location"].iloc[0] != region:
|
|
169
173
|
print(
|
|
170
174
|
f"{icons.yellow_dot} The '{resource_group}' resource group exists, but in a different region."
|
|
171
175
|
)
|
|
@@ -177,11 +181,10 @@ def create_fabric_capacity(
|
|
|
177
181
|
print(
|
|
178
182
|
f"{icons.in_progress} Creating the '{resource_group}' resource group in the '{region}' region"
|
|
179
183
|
)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
f"{icons.green_dot} Provisioned resource group with ID: {rg_result.id}"
|
|
184
|
+
create_or_update_resource_group(
|
|
185
|
+
azure_subscription_id=azure_subscription_id,
|
|
186
|
+
resource_group=resource_group,
|
|
187
|
+
region=region,
|
|
185
188
|
)
|
|
186
189
|
|
|
187
190
|
payload = {
|
|
@@ -243,20 +246,20 @@ def get_capacity_resource_governance(capacity_name: str):
|
|
|
243
246
|
return response.json()["workloadSettings"]
|
|
244
247
|
|
|
245
248
|
|
|
249
|
+
@log
|
|
246
250
|
def suspend_fabric_capacity(
|
|
247
251
|
capacity_name: str,
|
|
248
252
|
azure_subscription_id: str,
|
|
249
253
|
resource_group: str,
|
|
250
|
-
|
|
251
|
-
key_vault_tenant_id: str,
|
|
252
|
-
key_vault_client_id: str,
|
|
253
|
-
key_vault_client_secret: str,
|
|
254
|
+
**kwargs,
|
|
254
255
|
):
|
|
255
256
|
"""
|
|
256
257
|
This function suspends a Fabric capacity.
|
|
257
258
|
|
|
258
259
|
This is a wrapper function for the following API: `Fabric Capacities - Suspend <https://learn.microsoft.com/rest/api/microsoftfabric/fabric-capacities/suspend?view=rest-microsoftfabric-2023-11-01>`_.
|
|
259
260
|
|
|
261
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
262
|
+
|
|
260
263
|
Parameters
|
|
261
264
|
----------
|
|
262
265
|
capacity_name : str
|
|
@@ -265,23 +268,21 @@ def suspend_fabric_capacity(
|
|
|
265
268
|
The Azure subscription ID.
|
|
266
269
|
resource_group : str
|
|
267
270
|
The name of the Azure resource group.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
key_vault_client_secret=key_vault_client_secret,
|
|
284
|
-
)
|
|
271
|
+
"""
|
|
272
|
+
|
|
273
|
+
token_provider = auth.token_provider.get()
|
|
274
|
+
if token_provider is None:
|
|
275
|
+
token_provider = ServicePrincipalTokenProvider.from_azure_key_vault(
|
|
276
|
+
key_vault_uri=kwargs["key_vault_uri"],
|
|
277
|
+
key_vault_tenant_id=kwargs["key_vault_tenant_id"],
|
|
278
|
+
key_vault_client_id=kwargs["key_vault_client_id"],
|
|
279
|
+
key_vault_client_secret=kwargs["key_vault_client_secret"],
|
|
280
|
+
)
|
|
281
|
+
print(
|
|
282
|
+
f"{icons.info} Please use the 'token_provider' parameter instead of the key vault parameters within this function as the key vault parameters have been deprecated."
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
headers = _get_headers(token_provider, audience="azure")
|
|
285
286
|
|
|
286
287
|
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Fabric/capacities/{capacity_name}/suspend?api-version={icons.azure_api_version}"
|
|
287
288
|
|
|
@@ -293,20 +294,20 @@ def suspend_fabric_capacity(
|
|
|
293
294
|
print(f"{icons.green_dot} The '{capacity_name}' capacity has been suspended.")
|
|
294
295
|
|
|
295
296
|
|
|
297
|
+
@log
|
|
296
298
|
def resume_fabric_capacity(
|
|
297
299
|
capacity_name: str,
|
|
298
300
|
azure_subscription_id: str,
|
|
299
301
|
resource_group: str,
|
|
300
|
-
|
|
301
|
-
key_vault_tenant_id: str,
|
|
302
|
-
key_vault_client_id: str,
|
|
303
|
-
key_vault_client_secret: str,
|
|
302
|
+
**kwargs,
|
|
304
303
|
):
|
|
305
304
|
"""
|
|
306
305
|
This function resumes a Fabric capacity.
|
|
307
306
|
|
|
308
307
|
This is a wrapper function for the following API: `Fabric Capacities - Resume <https://learn.microsoft.com/rest/api/microsoftfabric/fabric-capacities/resume?view=rest-microsoftfabric-2023-11-01>`_.
|
|
309
308
|
|
|
309
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
310
|
+
|
|
310
311
|
Parameters
|
|
311
312
|
----------
|
|
312
313
|
capacity_name : str
|
|
@@ -315,24 +316,21 @@ def resume_fabric_capacity(
|
|
|
315
316
|
The Azure subscription ID.
|
|
316
317
|
resource_group : str
|
|
317
318
|
The name of the Azure resource group.
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
key_vault_client_id=key_vault_client_id,
|
|
334
|
-
key_vault_client_secret=key_vault_client_secret,
|
|
335
|
-
)
|
|
319
|
+
"""
|
|
320
|
+
|
|
321
|
+
token_provider = auth.token_provider.get()
|
|
322
|
+
if token_provider is None:
|
|
323
|
+
token_provider = ServicePrincipalTokenProvider.from_azure_key_vault(
|
|
324
|
+
key_vault_uri=kwargs["key_vault_uri"],
|
|
325
|
+
key_vault_tenant_id=kwargs["key_vault_tenant_id"],
|
|
326
|
+
key_vault_client_id=kwargs["key_vault_client_id"],
|
|
327
|
+
key_vault_client_secret=kwargs["key_vault_client_secret"],
|
|
328
|
+
)
|
|
329
|
+
print(
|
|
330
|
+
f"{icons.info} Please use the 'token_provider' parameter instead of the key vault parameters within this function as the key vault parameters have been deprecated."
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
headers = _get_headers(token_provider, audience="azure")
|
|
336
334
|
|
|
337
335
|
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Fabric/capacities/{capacity_name}/resume?api-version={icons.azure_api_version}"
|
|
338
336
|
|
|
@@ -344,18 +342,18 @@ def resume_fabric_capacity(
|
|
|
344
342
|
print(f"{icons.green_dot} The '{capacity_name}' capacity has been resumed.")
|
|
345
343
|
|
|
346
344
|
|
|
345
|
+
@log
|
|
347
346
|
def delete_embedded_capacity(
|
|
348
347
|
capacity_name: str,
|
|
349
348
|
azure_subscription_id: str,
|
|
350
349
|
resource_group: str,
|
|
351
|
-
|
|
352
|
-
key_vault_tenant_id: str,
|
|
353
|
-
key_vault_client_id: str,
|
|
354
|
-
key_vault_client_secret: str,
|
|
350
|
+
**kwargs,
|
|
355
351
|
):
|
|
356
352
|
"""
|
|
357
353
|
This function deletes a Power BI Embedded capacity.
|
|
358
354
|
|
|
355
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
356
|
+
|
|
359
357
|
Parameters
|
|
360
358
|
----------
|
|
361
359
|
capacity_name : str
|
|
@@ -364,24 +362,21 @@ def delete_embedded_capacity(
|
|
|
364
362
|
The Azure subscription ID.
|
|
365
363
|
resource_group : str
|
|
366
364
|
The name of the Azure resource group.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
key_vault_client_id=key_vault_client_id,
|
|
383
|
-
key_vault_client_secret=key_vault_client_secret,
|
|
384
|
-
)
|
|
365
|
+
"""
|
|
366
|
+
|
|
367
|
+
token_provider = auth.token_provider.get()
|
|
368
|
+
if token_provider is None:
|
|
369
|
+
token_provider = ServicePrincipalTokenProvider.from_azure_key_vault(
|
|
370
|
+
key_vault_uri=kwargs["key_vault_uri"],
|
|
371
|
+
key_vault_tenant_id=kwargs["key_vault_tenant_id"],
|
|
372
|
+
key_vault_client_id=kwargs["key_vault_client_id"],
|
|
373
|
+
key_vault_client_secret=kwargs["key_vault_client_secret"],
|
|
374
|
+
)
|
|
375
|
+
print(
|
|
376
|
+
f"{icons.info} Please use the 'token_provider' parameter instead of the key vault parameters within this function as the key vault parameters have been deprecated."
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
headers = _get_headers(token_provider, audience="azure")
|
|
385
380
|
|
|
386
381
|
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.PowerBIDedicated/capacities/{capacity_name}?api-version={icons.azure_api_version}"
|
|
387
382
|
|
|
@@ -393,6 +388,7 @@ def delete_embedded_capacity(
|
|
|
393
388
|
print(f"{icons.green_dot} The '{capacity_name}' capacity has been deleted.")
|
|
394
389
|
|
|
395
390
|
|
|
391
|
+
@log
|
|
396
392
|
def delete_premium_capacity(capacity_name: str):
|
|
397
393
|
"""
|
|
398
394
|
This function deletes a Power BI Premium capacity.
|
|
@@ -421,20 +417,20 @@ def delete_premium_capacity(capacity_name: str):
|
|
|
421
417
|
print(f"{icons.green_dot} The '{capacity_name}' capacity has been deleted.")
|
|
422
418
|
|
|
423
419
|
|
|
420
|
+
@log
|
|
424
421
|
def delete_fabric_capacity(
|
|
425
422
|
capacity_name: str,
|
|
426
423
|
azure_subscription_id: str,
|
|
427
424
|
resource_group: str,
|
|
428
|
-
|
|
429
|
-
key_vault_tenant_id: str,
|
|
430
|
-
key_vault_client_id: str,
|
|
431
|
-
key_vault_client_secret: str,
|
|
425
|
+
**kwargs,
|
|
432
426
|
):
|
|
433
427
|
"""
|
|
434
428
|
This function deletes a Fabric capacity.
|
|
435
429
|
|
|
436
430
|
This is a wrapper function for the following API: `Fabric Capacities - Delete <https://learn.microsoft.com/rest/api/microsoftfabric/fabric-capacities/delete?view=rest-microsoftfabric-2023-11-01>`_.
|
|
437
431
|
|
|
432
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
433
|
+
|
|
438
434
|
Parameters
|
|
439
435
|
----------
|
|
440
436
|
capacity_name : str
|
|
@@ -443,24 +439,21 @@ def delete_fabric_capacity(
|
|
|
443
439
|
The Azure subscription ID.
|
|
444
440
|
resource_group : str
|
|
445
441
|
The name of the Azure resource group.
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
key_vault_client_id=key_vault_client_id,
|
|
462
|
-
key_vault_client_secret=key_vault_client_secret,
|
|
463
|
-
)
|
|
442
|
+
"""
|
|
443
|
+
|
|
444
|
+
token_provider = auth.token_provider.get()
|
|
445
|
+
if token_provider is None:
|
|
446
|
+
token_provider = ServicePrincipalTokenProvider.from_azure_key_vault(
|
|
447
|
+
key_vault_uri=kwargs["key_vault_uri"],
|
|
448
|
+
key_vault_tenant_id=kwargs["key_vault_tenant_id"],
|
|
449
|
+
key_vault_client_id=kwargs["key_vault_client_id"],
|
|
450
|
+
key_vault_client_secret=kwargs["key_vault_client_secret"],
|
|
451
|
+
)
|
|
452
|
+
print(
|
|
453
|
+
f"{icons.info} Please use the 'token_provider' parameter instead of the key vault parameters within this function as the key vault parameters have been deprecated."
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
headers = _get_headers(token_provider, audience="azure")
|
|
464
457
|
|
|
465
458
|
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Fabric/capacities/{capacity_name}?api-version={icons.azure_api_version}"
|
|
466
459
|
|
|
@@ -472,23 +465,23 @@ def delete_fabric_capacity(
|
|
|
472
465
|
print(f"{icons.green_dot} The '{capacity_name}' capacity has been deleted.")
|
|
473
466
|
|
|
474
467
|
|
|
468
|
+
@log
|
|
475
469
|
def update_fabric_capacity(
|
|
476
470
|
capacity_name: str,
|
|
477
471
|
azure_subscription_id: str,
|
|
478
472
|
resource_group: str,
|
|
479
|
-
key_vault_uri: str,
|
|
480
|
-
key_vault_tenant_id: str,
|
|
481
|
-
key_vault_client_id: str,
|
|
482
|
-
key_vault_client_secret: str,
|
|
483
473
|
sku: Optional[str] = None,
|
|
484
474
|
admin_members: Optional[str | List[str]] = None,
|
|
485
475
|
tags: Optional[dict] = None,
|
|
476
|
+
**kwargs,
|
|
486
477
|
):
|
|
487
478
|
"""
|
|
488
479
|
This function updates a Fabric capacity's properties.
|
|
489
480
|
|
|
490
481
|
This is a wrapper function for the following API: `Fabric Capacities - Update <https://learn.microsoft.com/rest/api/microsoftfabric/fabric-capacities/update?view=rest-microsoftfabric-2023-11-01>`_.
|
|
491
482
|
|
|
483
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
484
|
+
|
|
492
485
|
Parameters
|
|
493
486
|
----------
|
|
494
487
|
capacity_name : str
|
|
@@ -497,14 +490,6 @@ def update_fabric_capacity(
|
|
|
497
490
|
The Azure subscription ID.
|
|
498
491
|
resource_group : str
|
|
499
492
|
The name of the Azure resource group.
|
|
500
|
-
key_vault_uri : str
|
|
501
|
-
The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
|
|
502
|
-
key_vault_tenant_id : str
|
|
503
|
-
The name of the Azure key vault secret storing the Tenant ID.
|
|
504
|
-
key_vault_client_id : str
|
|
505
|
-
The name of the Azure key vault secret storing the Client ID.
|
|
506
|
-
key_vault_client_secret : str
|
|
507
|
-
The name of the Azure key vault secret storing the Client Secret.
|
|
508
493
|
sku : str, default=None
|
|
509
494
|
The `sku size <https://azure.microsoft.com/pricing/details/microsoft-fabric/>`_ of the Fabric capacity.
|
|
510
495
|
admin_members : str | List[str], default=None
|
|
@@ -513,21 +498,19 @@ def update_fabric_capacity(
|
|
|
513
498
|
Tag(s) to add to the capacity. Example: {'tagName': 'tagValue'}.
|
|
514
499
|
"""
|
|
515
500
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
501
|
+
token_provider = auth.token_provider.get()
|
|
502
|
+
if token_provider is None:
|
|
503
|
+
token_provider = ServicePrincipalTokenProvider.from_azure_key_vault(
|
|
504
|
+
key_vault_uri=kwargs["key_vault_uri"],
|
|
505
|
+
key_vault_tenant_id=kwargs["key_vault_tenant_id"],
|
|
506
|
+
key_vault_client_id=kwargs["key_vault_client_id"],
|
|
507
|
+
key_vault_client_secret=kwargs["key_vault_client_secret"],
|
|
508
|
+
)
|
|
509
|
+
print(
|
|
510
|
+
f"{icons.info} Please use the 'token_provider' parameter instead of the key vault parameters within this function as the key vault parameters have been deprecated."
|
|
523
511
|
)
|
|
524
512
|
|
|
525
|
-
|
|
526
|
-
key_vault_uri=key_vault_uri,
|
|
527
|
-
key_vault_tenant_id=key_vault_tenant_id,
|
|
528
|
-
key_vault_client_id=key_vault_client_id,
|
|
529
|
-
key_vault_client_secret=key_vault_client_secret,
|
|
530
|
-
)
|
|
513
|
+
headers = _get_headers(token_provider, audience="azure")
|
|
531
514
|
|
|
532
515
|
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Fabric/capacities/{capacity_name}?api-version={icons.azure_api_version}"
|
|
533
516
|
|
|
@@ -575,20 +558,20 @@ def update_fabric_capacity(
|
|
|
575
558
|
)
|
|
576
559
|
|
|
577
560
|
|
|
561
|
+
@log
|
|
578
562
|
def check_fabric_capacity_name_availablility(
|
|
579
563
|
capacity_name: str,
|
|
580
564
|
azure_subscription_id: str,
|
|
581
565
|
region: str,
|
|
582
|
-
|
|
583
|
-
key_vault_tenant_id: str,
|
|
584
|
-
key_vault_client_id: str,
|
|
585
|
-
key_vault_client_secret: str,
|
|
566
|
+
**kwargs,
|
|
586
567
|
) -> bool:
|
|
587
568
|
"""
|
|
588
569
|
This function updates a Fabric capacity's properties.
|
|
589
570
|
|
|
590
571
|
This is a wrapper function for the following API: `Fabric Capacities - Check Name Availability <https://learn.microsoft.com/rest/api/microsoftfabric/fabric-capacities/check-name-availability?view=rest-microsoftfabric-2023-11-01>`_.
|
|
591
572
|
|
|
573
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
574
|
+
|
|
592
575
|
Parameters
|
|
593
576
|
----------
|
|
594
577
|
capacity_name : str
|
|
@@ -597,34 +580,32 @@ def check_fabric_capacity_name_availablility(
|
|
|
597
580
|
The Azure subscription ID.
|
|
598
581
|
region : str
|
|
599
582
|
The region name.
|
|
600
|
-
key_vault_uri : str
|
|
601
|
-
The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
|
|
602
|
-
key_vault_tenant_id : str
|
|
603
|
-
The name of the Azure key vault secret storing the Tenant ID.
|
|
604
|
-
key_vault_client_id : str
|
|
605
|
-
The name of the Azure key vault secret storing the Client ID.
|
|
606
|
-
key_vault_client_secret : str
|
|
607
|
-
The name of the Azure key vault secret storing the Client Secret.
|
|
608
583
|
|
|
609
584
|
Returns
|
|
610
585
|
-------
|
|
611
586
|
bool
|
|
612
587
|
An indication as to whether the Fabric capacity name is available or not.
|
|
613
588
|
"""
|
|
614
|
-
# https://learn.microsoft.com/en-us/rest/api/microsoftfabric/fabric-capacities/check-name-availability?view=rest-microsoftfabric-2023-11-01&tabs=HTTP
|
|
615
589
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
590
|
+
token_provider = auth.token_provider.get()
|
|
591
|
+
if token_provider is None:
|
|
592
|
+
token_provider = ServicePrincipalTokenProvider.from_azure_key_vault(
|
|
593
|
+
key_vault_uri=kwargs["key_vault_uri"],
|
|
594
|
+
key_vault_tenant_id=kwargs["key_vault_tenant_id"],
|
|
595
|
+
key_vault_client_id=kwargs["key_vault_client_id"],
|
|
596
|
+
key_vault_client_secret=kwargs["key_vault_client_secret"],
|
|
597
|
+
)
|
|
598
|
+
print(
|
|
599
|
+
f"{icons.info} Please use the 'token_provider' parameter instead of the key vault parameters within this function as the key vault parameters have been deprecated."
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
headers = _get_headers(token_provider, audience="azure")
|
|
622
603
|
|
|
623
604
|
payload = {"name": capacity_name, "type": "Microsoft.Fabric/capacities"}
|
|
624
605
|
|
|
625
606
|
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/providers/Microsoft.Fabric/locations/{region}/checkNameAvailability?api-version={icons.azure_api_version}"
|
|
626
607
|
|
|
627
|
-
response = requests.post(url, headers=headers,
|
|
608
|
+
response = requests.post(url, headers=headers, json=payload)
|
|
628
609
|
|
|
629
610
|
if response.status_code != 202:
|
|
630
611
|
raise FabricHTTPException(response)
|
|
@@ -632,59 +613,648 @@ def check_fabric_capacity_name_availablility(
|
|
|
632
613
|
return bool(response.json().get("nameAvailable"))
|
|
633
614
|
|
|
634
615
|
|
|
616
|
+
@log
|
|
635
617
|
def create_resource_group(
|
|
636
618
|
azure_subscription_id: str,
|
|
637
|
-
key_vault_uri: str,
|
|
638
|
-
key_vault_tenant_id: str,
|
|
639
|
-
key_vault_client_id: str,
|
|
640
|
-
key_vault_client_secret: str,
|
|
641
619
|
resource_group: str,
|
|
642
620
|
region: str,
|
|
621
|
+
**kwargs,
|
|
643
622
|
):
|
|
644
623
|
"""
|
|
645
624
|
This function creates a resource group in a region within an Azure subscription.
|
|
646
625
|
|
|
647
|
-
This is a wrapper function for the following API: `
|
|
626
|
+
This is a wrapper function for the following API: `Resource Groups - Create Or Update <https://learn.microsoft.com/rest/api/resources/resource-groups/create-or-update>`_.
|
|
627
|
+
|
|
628
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
648
629
|
|
|
649
630
|
Parameters
|
|
650
631
|
----------
|
|
651
632
|
azure_subscription_id : str
|
|
652
633
|
The Azure subscription ID.
|
|
653
|
-
key_vault_uri : str
|
|
654
|
-
The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
|
|
655
|
-
key_vault_tenant_id : str
|
|
656
|
-
The name of the Azure key vault secret storing the Tenant ID.
|
|
657
|
-
key_vault_client_id : str
|
|
658
|
-
The name of the Azure key vault secret storing the Client ID.
|
|
659
|
-
key_vault_client_secret : str
|
|
660
|
-
The name of the Azure key vault secret storing the Client Secret.
|
|
661
634
|
resource_group : str
|
|
662
635
|
The name of the Azure resource group to be created.
|
|
663
636
|
region : str
|
|
664
637
|
The name of the region in which the resource group will be created.
|
|
665
638
|
"""
|
|
666
639
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
key_vault_tenant_id=key_vault_tenant_id,
|
|
672
|
-
key_vault_client_id=key_vault_client_id,
|
|
673
|
-
key_vault_client_secret=key_vault_client_secret,
|
|
674
|
-
)
|
|
675
|
-
|
|
676
|
-
resource_client = ResourceManagementClient(credential, azure_subscription_id)
|
|
677
|
-
|
|
678
|
-
if resource_client.resource_groups.check_existence(resource_group):
|
|
640
|
+
if check_resource_group_existence(
|
|
641
|
+
azure_subscription_id=azure_subscription_id,
|
|
642
|
+
resource_group=resource_group,
|
|
643
|
+
):
|
|
679
644
|
print(
|
|
680
645
|
f"{icons.info} The '{resource_group}' resource group already exists in the '{region}' region within the '{azure_subscription_id}' Azure subscription."
|
|
681
646
|
)
|
|
682
647
|
return
|
|
683
648
|
|
|
684
|
-
|
|
685
|
-
|
|
649
|
+
create_or_update_resource_group(
|
|
650
|
+
azure_subscription_id=azure_subscription_id,
|
|
651
|
+
resource_group=resource_group,
|
|
652
|
+
region=region,
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
@log
|
|
657
|
+
def list_skus_for_capacity(
|
|
658
|
+
capacity: str,
|
|
659
|
+
azure_subscription_id: str,
|
|
660
|
+
resource_group: str,
|
|
661
|
+
) -> pd.DataFrame:
|
|
662
|
+
"""
|
|
663
|
+
Lists eligible SKUs for a Microsoft Fabric resource.
|
|
664
|
+
|
|
665
|
+
This is a wrapper function for the following API: `Fabric Capacities - List Skus For Capacity <https://learn.microsoft.com/rest/api/microsoftfabric/fabric-capacities/list-skus-for-capacity?view=rest-microsoftfabric-2023-11-01>`_.
|
|
666
|
+
|
|
667
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
668
|
+
|
|
669
|
+
Parameters
|
|
670
|
+
----------
|
|
671
|
+
capacity : str
|
|
672
|
+
The capacity name.
|
|
673
|
+
azure_subscription_id : str
|
|
674
|
+
The Azure subscription ID.
|
|
675
|
+
resource_group : str
|
|
676
|
+
The name of the resource group.
|
|
677
|
+
|
|
678
|
+
Returns
|
|
679
|
+
-------
|
|
680
|
+
pandas.DataFrame
|
|
681
|
+
A pandas dataframe showing a list of eligible SKUs for a Microsoft Fabric resource.
|
|
682
|
+
"""
|
|
683
|
+
|
|
684
|
+
df = pd.DataFrame(columns=["Resource Type", "Sku", "Sku Tier"])
|
|
685
|
+
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Fabric/capacities/{capacity}/skus?api-version=2023-11-01"
|
|
686
|
+
headers = _get_headers(token_provider=auth.token_provider.get(), audience="azure")
|
|
687
|
+
|
|
688
|
+
response = requests.get(url, headers=headers)
|
|
689
|
+
if response.status_code != 200:
|
|
690
|
+
raise FabricHTTPException(response)
|
|
691
|
+
|
|
692
|
+
for v in response.json().get("value", []):
|
|
693
|
+
sku = v.get("sku", {})
|
|
694
|
+
new_data = {
|
|
695
|
+
"Resource Type": v.get("resourceType"),
|
|
696
|
+
"Sku": sku.get("name"),
|
|
697
|
+
"Sku Tier": sku.get("tier"),
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
701
|
+
|
|
702
|
+
return df
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
@log
|
|
706
|
+
def list_skus(
|
|
707
|
+
azure_subscription_id: str,
|
|
708
|
+
) -> pd.DataFrame:
|
|
709
|
+
"""
|
|
710
|
+
Lists eligible SKUs for Microsoft Fabric resource provider.
|
|
711
|
+
|
|
712
|
+
This is a wrapper function for the following API: `Fabric Capacities - List Skus For Capacity <https://learn.microsoft.com/rest/api/microsoftfabric/fabric-capacities/list-skus?view=rest-microsoftfabric-2023-11-01>`_.
|
|
713
|
+
|
|
714
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
715
|
+
|
|
716
|
+
Parameters
|
|
717
|
+
----------
|
|
718
|
+
azure_subscription_id : str
|
|
719
|
+
The Azure subscription ID.
|
|
720
|
+
|
|
721
|
+
Returns
|
|
722
|
+
-------
|
|
723
|
+
pandas.DataFrame
|
|
724
|
+
A pandas dataframe showing a list of eligible SKUs for Microsoft Fabric resource provider.
|
|
725
|
+
"""
|
|
726
|
+
|
|
727
|
+
df = pd.DataFrame(columns=["Sku", "Locations"])
|
|
728
|
+
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/providers/Microsoft.Fabric/skus?api-version=2023-11-01"
|
|
729
|
+
headers = _get_headers(token_provider=auth.token_provider.get(), audience="azure")
|
|
730
|
+
|
|
731
|
+
response = requests.get(url, headers=headers)
|
|
732
|
+
if response.status_code != 200:
|
|
733
|
+
raise FabricHTTPException(response)
|
|
734
|
+
|
|
735
|
+
for v in response.json().get("value", []):
|
|
736
|
+
new_data = {
|
|
737
|
+
"Sku": v.get("name"),
|
|
738
|
+
"Locations": v.get("locations", []),
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
742
|
+
|
|
743
|
+
return df
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
@log
|
|
747
|
+
def list_subscriptions() -> pd.DataFrame:
|
|
748
|
+
"""
|
|
749
|
+
Gets all subscriptions for a tenant.
|
|
750
|
+
|
|
751
|
+
This is a wrapper function for the following API: `Subscriptions - List <https://learn.microsoft.com/rest/api/resources/subscriptions/list?view=rest-resources-2022-12-01>`_.
|
|
752
|
+
|
|
753
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
754
|
+
|
|
755
|
+
Returns
|
|
756
|
+
-------
|
|
757
|
+
pandas.DataFrame
|
|
758
|
+
A pandas dataframe showing a list of all subscriptions for a tenant.
|
|
759
|
+
"""
|
|
760
|
+
|
|
761
|
+
df = pd.DataFrame(
|
|
762
|
+
columns=[
|
|
763
|
+
"Subscription Id",
|
|
764
|
+
"Subscription Name",
|
|
765
|
+
"Tenant Id",
|
|
766
|
+
"State",
|
|
767
|
+
"Location Placement Id",
|
|
768
|
+
"Quota Id",
|
|
769
|
+
"Spending Limit",
|
|
770
|
+
"Authorization Source",
|
|
771
|
+
"Managed By Tenants",
|
|
772
|
+
"Tags",
|
|
773
|
+
]
|
|
686
774
|
)
|
|
775
|
+
url = "https://management.azure.com/subscriptions?api-version=2022-12-01"
|
|
776
|
+
headers = _get_headers(token_provider=auth.token_provider.get(), audience="azure")
|
|
777
|
+
|
|
778
|
+
response = requests.get(url, headers=headers)
|
|
779
|
+
if response.status_code != 200:
|
|
780
|
+
raise FabricHTTPException(response)
|
|
781
|
+
|
|
782
|
+
for v in response.json().get("value", []):
|
|
783
|
+
policy = v.get("subscriptionPolicies", {})
|
|
784
|
+
tenants = v.get("managedByTenants")
|
|
785
|
+
new_data = {
|
|
786
|
+
"Subscription Id": v.get("subscriptionId"),
|
|
787
|
+
"Subscription Name": v.get("displayName"),
|
|
788
|
+
"Tenant Id": v.get("tenantId"),
|
|
789
|
+
"State": v.get("state"),
|
|
790
|
+
"Location Placement Id": policy.get("locationPlacementId"),
|
|
791
|
+
"Quota Id": policy.get("quotaId"),
|
|
792
|
+
"Spending Limit": policy.get("spendingLimit"),
|
|
793
|
+
"Authorization Source": v.get("authorizationSource"),
|
|
794
|
+
"Managed by Tenants": tenants if tenants is not None else [],
|
|
795
|
+
"Tags": v.get("tags", {}),
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
799
|
+
|
|
800
|
+
return df
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
@log
|
|
804
|
+
def get_subscription(azure_subscription_id: str) -> pd.DataFrame:
|
|
805
|
+
"""
|
|
806
|
+
Gets details about a specified subscription.
|
|
807
|
+
|
|
808
|
+
This is a wrapper function for the following API: `Subscriptions - Get <https://learn.microsoft.com/rest/api/resources/subscriptions/get?view=rest-resources-2022-12-01>`_.
|
|
809
|
+
|
|
810
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
811
|
+
|
|
812
|
+
Parameters
|
|
813
|
+
----------
|
|
814
|
+
azure_subscription_id : str
|
|
815
|
+
The Azure subscription ID.
|
|
816
|
+
|
|
817
|
+
Returns
|
|
818
|
+
-------
|
|
819
|
+
pandas.DataFrame
|
|
820
|
+
A pandas dataframe showing details of a specific subscription.
|
|
821
|
+
"""
|
|
822
|
+
|
|
823
|
+
df = pd.DataFrame(
|
|
824
|
+
columns=[
|
|
825
|
+
"Subscription Id",
|
|
826
|
+
"Subscription Name",
|
|
827
|
+
"Tenant Id",
|
|
828
|
+
"State",
|
|
829
|
+
"Location Placement Id",
|
|
830
|
+
"Quota Id",
|
|
831
|
+
"Spending Limit",
|
|
832
|
+
"Authorization Source",
|
|
833
|
+
"Managed By Tenants",
|
|
834
|
+
"Tags",
|
|
835
|
+
]
|
|
836
|
+
)
|
|
837
|
+
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}?api-version=2022-12-01"
|
|
838
|
+
headers = _get_headers(token_provider=auth.token_provider.get(), audience="azure")
|
|
839
|
+
|
|
840
|
+
response = requests.get(url, headers=headers)
|
|
841
|
+
if response.status_code != 200:
|
|
842
|
+
raise FabricHTTPException(response)
|
|
843
|
+
|
|
844
|
+
v = response.json()
|
|
845
|
+
policy = v.get("subscriptionPolicies", {})
|
|
846
|
+
tenants = v.get("managedByTenants")
|
|
847
|
+
new_data = {
|
|
848
|
+
"Subscription Id": v.get("subscriptionId"),
|
|
849
|
+
"Subscription Name": v.get("displayName"),
|
|
850
|
+
"Tenant Id": v.get("tenantId"),
|
|
851
|
+
"State": v.get("state"),
|
|
852
|
+
"Location Placement Id": policy.get("locationPlacementId"),
|
|
853
|
+
"Quota Id": policy.get("quotaId"),
|
|
854
|
+
"Spending Limit": policy.get("spendingLimit"),
|
|
855
|
+
"Authorization Source": v.get("authorizationSource"),
|
|
856
|
+
"Managed by Tenants": tenants if tenants is not None else [],
|
|
857
|
+
"Tags": v.get("tags", {}),
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
861
|
+
|
|
862
|
+
return df
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
def _resolve_subscription_name_and_id(
|
|
866
|
+
azure_subscription: str | UUID,
|
|
867
|
+
) -> Tuple[str, UUID]:
|
|
868
|
+
|
|
869
|
+
if _is_valid_uuid(azure_subscription):
|
|
870
|
+
subscription_id = azure_subscription
|
|
871
|
+
df = get_subscription(azure_subscription_id=subscription_id)
|
|
872
|
+
if df.empty:
|
|
873
|
+
raise ValueError(f"{icons.red_dot} The subscription ID does not exist.")
|
|
874
|
+
subscription_name = df["Subscription Name"].iloc[0]
|
|
875
|
+
else:
|
|
876
|
+
subscription_name = azure_subscription
|
|
877
|
+
df = list_subscriptions()
|
|
878
|
+
df_filt = df[df["Subscription Name"] == subscription_name]
|
|
879
|
+
if df_filt.empty:
|
|
880
|
+
raise ValueError(f"{icons.red_dot} The subscription name does not exist.")
|
|
881
|
+
subscription_id = df_filt["Subscription Id"].iloc[0]
|
|
882
|
+
|
|
883
|
+
return subscription_name, subscription_id
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
@log
|
|
887
|
+
def list_tenants() -> pd.DataFrame:
|
|
888
|
+
"""
|
|
889
|
+
Gets the tenants for your account.
|
|
890
|
+
|
|
891
|
+
This is a wrapper function for the following API: `Tenants - List <https://learn.microsoft.com/rest/api/resources/tenants/list?view=rest-resources-2022-12-01>`_.
|
|
892
|
+
|
|
893
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
894
|
+
|
|
895
|
+
Returns
|
|
896
|
+
-------
|
|
897
|
+
pandas.DataFrame
|
|
898
|
+
A pandas dataframe showing a list of all tenants for your account.
|
|
899
|
+
"""
|
|
900
|
+
|
|
901
|
+
df = pd.DataFrame(
|
|
902
|
+
columns=[
|
|
903
|
+
"Tenant Id",
|
|
904
|
+
"Tenant Name",
|
|
905
|
+
"Country Code",
|
|
906
|
+
"Domains",
|
|
907
|
+
"Tenant Category",
|
|
908
|
+
"Default Domain",
|
|
909
|
+
"Tenant Type",
|
|
910
|
+
"Tenant Branding Logo Url",
|
|
911
|
+
]
|
|
912
|
+
)
|
|
913
|
+
url = "https://management.azure.com/tenants?api-version=2022-12-01"
|
|
914
|
+
headers = _get_headers(token_provider=auth.token_provider.get(), audience="azure")
|
|
915
|
+
|
|
916
|
+
response = requests.get(url, headers=headers)
|
|
917
|
+
if response.status_code != 200:
|
|
918
|
+
raise FabricHTTPException(response)
|
|
919
|
+
|
|
920
|
+
for v in response.json().get("value", []):
|
|
921
|
+
d = v.get("domains")
|
|
922
|
+
new_data = {
|
|
923
|
+
"Tenant Id": v.get("tenantId"),
|
|
924
|
+
"Tenant Name": v.get("displayName"),
|
|
925
|
+
"Country Code": v.get("countryCode"),
|
|
926
|
+
"Domains": d if d is not None else "",
|
|
927
|
+
"Tenant Category": v.get("tenantCategory"),
|
|
928
|
+
"Default Domain": v.get("defaultDomain"),
|
|
929
|
+
"Tenant Type": v.get("tenantType"),
|
|
930
|
+
"Tenant Branding Logo Url": v.get("tenantBrandingLogoUrl"),
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
934
|
+
|
|
935
|
+
return df
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
@log
|
|
939
|
+
def create_or_update_resource_group(
|
|
940
|
+
azure_subscription_id: str,
|
|
941
|
+
resource_group: str,
|
|
942
|
+
region: str,
|
|
943
|
+
):
|
|
944
|
+
"""
|
|
945
|
+
Creates or updates a resource group.
|
|
946
|
+
|
|
947
|
+
This is a wrapper function for the following API: `Resource Groups - Create Or Update <https://learn.microsoft.com/rest/api/resources/resource-groups/create-or-update>`_.
|
|
948
|
+
|
|
949
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
950
|
+
|
|
951
|
+
Parameters
|
|
952
|
+
----------
|
|
953
|
+
azure_subscription_id : str
|
|
954
|
+
The Azure subscription Id.
|
|
955
|
+
resource_group : str
|
|
956
|
+
The name of the resource group.
|
|
957
|
+
region : str
|
|
958
|
+
The name of the region.
|
|
959
|
+
"""
|
|
960
|
+
|
|
961
|
+
headers = _get_headers(auth.token_provider.get(), audience="azure")
|
|
962
|
+
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourcegroups/{resource_group}?api-version=2021-04-01"
|
|
963
|
+
|
|
964
|
+
payload = {
|
|
965
|
+
"location": region,
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
response = requests.put(url, headers=headers, json=payload)
|
|
969
|
+
if response.status_code not in [200, 201]:
|
|
970
|
+
raise FabricHTTPException(response)
|
|
687
971
|
|
|
688
972
|
print(
|
|
689
|
-
f"{icons.green_dot} The '{resource_group}' resource group has been created
|
|
973
|
+
f"{icons.green_dot} The '{resource_group}' resource group has been created/updated."
|
|
690
974
|
)
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
@log
|
|
978
|
+
def create_storage_account(
|
|
979
|
+
azure_subscription_id: str,
|
|
980
|
+
resource_group: str,
|
|
981
|
+
storage_account: str,
|
|
982
|
+
region: str,
|
|
983
|
+
):
|
|
984
|
+
"""
|
|
985
|
+
Asynchronously creates a new storage account with the specified parameters. If an account is already created and a subsequent create request is issued with different properties, the account properties will be updated. If an account is already created and a subsequent create or update request is issued with the exact same set of properties, the request will succeed.
|
|
986
|
+
|
|
987
|
+
This is a wrapper function for the following API: `Storage Accounts - Create <https://learn.microsoft.com/rest/api/storagerp/storage-accounts/create`_.
|
|
988
|
+
|
|
989
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
990
|
+
|
|
991
|
+
Parameters
|
|
992
|
+
----------
|
|
993
|
+
azure_subscription_id : str
|
|
994
|
+
The Azure subscription Id.
|
|
995
|
+
resource_group : str
|
|
996
|
+
The name of the resource group.
|
|
997
|
+
storage_account : str
|
|
998
|
+
The name of the storage account to be created.
|
|
999
|
+
region : str
|
|
1000
|
+
The name of the region.
|
|
1001
|
+
"""
|
|
1002
|
+
|
|
1003
|
+
headers = _get_headers(auth.token_provider.get(), audience="azure")
|
|
1004
|
+
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Storage/storageAccounts/{storage_account}?api-version=2018-02-01"
|
|
1005
|
+
|
|
1006
|
+
payload = {
|
|
1007
|
+
"sku": {"name": "Standard_GRS"},
|
|
1008
|
+
"kind": "StorageV2",
|
|
1009
|
+
"location": region,
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
response = requests.put(url, headers=headers, json=payload)
|
|
1013
|
+
|
|
1014
|
+
if response.status_code != 200:
|
|
1015
|
+
raise FabricHTTPException(response)
|
|
1016
|
+
|
|
1017
|
+
print(
|
|
1018
|
+
f"{icons.green_dot} The '{storage_account}' storage account has been created."
|
|
1019
|
+
)
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
@log
|
|
1023
|
+
def list_storage_accounts(
|
|
1024
|
+
azure_subscription_id: str,
|
|
1025
|
+
resource_group: Optional[str] = None,
|
|
1026
|
+
) -> pd.DataFrame:
|
|
1027
|
+
"""
|
|
1028
|
+
Lists all the storage accounts available under the subscription (or resource group). Note that storage keys are not returned; use the ListKeys operation for this.
|
|
1029
|
+
|
|
1030
|
+
This is a wrapper function for the following APIs: `Storage Accounts - List <https://learn.microsoft.com/rest/api/storagerp/storage-accounts/list>`_, `Storage Accounts - List By Resource Group <https://learn.microsoft.com/rest/api/storagerp/storage-accounts/list-by-resource-group>`_.
|
|
1031
|
+
|
|
1032
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
1033
|
+
|
|
1034
|
+
Parameters
|
|
1035
|
+
----------
|
|
1036
|
+
azure_subscription_id : str
|
|
1037
|
+
The Azure subscription Id.
|
|
1038
|
+
resource_group : str, default=None
|
|
1039
|
+
If set to None, retrieves all storage accounts for the subscription. If not None, shows the storage accounts within that resource group.
|
|
1040
|
+
|
|
1041
|
+
Returns
|
|
1042
|
+
-------
|
|
1043
|
+
pandas.DataFrame
|
|
1044
|
+
A pandas dataframe showing a list of all storage accounts within the subscription (or resource group).
|
|
1045
|
+
"""
|
|
1046
|
+
|
|
1047
|
+
headers = _get_headers(auth.token_provider.get(), audience="azure")
|
|
1048
|
+
|
|
1049
|
+
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}"
|
|
1050
|
+
|
|
1051
|
+
if resource_group is not None:
|
|
1052
|
+
url += f"/resourceGroups/{resource_group}"
|
|
1053
|
+
|
|
1054
|
+
url += "/providers/Microsoft.Storage/storageAccounts?api-version=2023-05-01"
|
|
1055
|
+
|
|
1056
|
+
df = pd.DataFrame(
|
|
1057
|
+
columns=[
|
|
1058
|
+
"Storage Account Id",
|
|
1059
|
+
"Storage Account Name",
|
|
1060
|
+
"Kind",
|
|
1061
|
+
"Location",
|
|
1062
|
+
"Sku Name",
|
|
1063
|
+
"Sku Tier",
|
|
1064
|
+
"Is HNS Enabled",
|
|
1065
|
+
"Creation Time",
|
|
1066
|
+
"Web Endpoint",
|
|
1067
|
+
"DFS Endpoint",
|
|
1068
|
+
"Blob Endpoint",
|
|
1069
|
+
"File Endpoint",
|
|
1070
|
+
"Queue Endpoint",
|
|
1071
|
+
"Table Endpoint",
|
|
1072
|
+
"Primary Location",
|
|
1073
|
+
"Provisioning State",
|
|
1074
|
+
"Secondary Location",
|
|
1075
|
+
"Status of Primary",
|
|
1076
|
+
"Status of Secondary",
|
|
1077
|
+
"Supports HTTPS Traffic Only",
|
|
1078
|
+
"Tags",
|
|
1079
|
+
]
|
|
1080
|
+
)
|
|
1081
|
+
response = requests.get(url, headers=headers)
|
|
1082
|
+
|
|
1083
|
+
if response.status_code != 200:
|
|
1084
|
+
raise FabricHTTPException(response)
|
|
1085
|
+
|
|
1086
|
+
for v in response.json().get("value", []):
|
|
1087
|
+
p = v.get("properties", {})
|
|
1088
|
+
new_data = {
|
|
1089
|
+
"Storage Account Id": v.get("id"),
|
|
1090
|
+
"Storage Account Name": v.get("name"),
|
|
1091
|
+
"Kind": v.get("kind"),
|
|
1092
|
+
"Location": v.get("location"),
|
|
1093
|
+
"Sku Name": v.get("sku", {}).get("name"),
|
|
1094
|
+
"Sku Tier": v.get("sku", {}).get("tier"),
|
|
1095
|
+
"Is HNS Enabled": p.get("isHnsEnabled"),
|
|
1096
|
+
"Creation Time": p.get("creationTime"),
|
|
1097
|
+
"Web Endpoint": p.get("primaryEndpoints", {}).get("web"),
|
|
1098
|
+
"DFS Endpoint": p.get("primaryEndpoints", {}).get("dfs"),
|
|
1099
|
+
"Blob Endpoint": p.get("primaryEndpoints", {}).get("blob"),
|
|
1100
|
+
"File Endpoint": p.get("primaryEndpoints", {}).get("file"),
|
|
1101
|
+
"Queue Endpoint": p.get("primaryEndpoints", {}).get("queue"),
|
|
1102
|
+
"Table Endpoint": p.get("primaryEndpoints", {}).get("table"),
|
|
1103
|
+
"Primary Location": p.get("primaryLocation"),
|
|
1104
|
+
"Provisioning State": p.get("provisioningState"),
|
|
1105
|
+
"Secondary Location": p.get("secondaryLocation"),
|
|
1106
|
+
"Status of Primary": p.get("statusOfPrimary"),
|
|
1107
|
+
"Status of Secondary": p.get("statusOfSecondary"),
|
|
1108
|
+
"Supports HTTPS Traffic Only": p.get("supportsHttpsTrafficOnly"),
|
|
1109
|
+
"Tags": v.get("tags"),
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
1113
|
+
|
|
1114
|
+
bool_cols = ["Is HNS Enabled", "Supports HTTPS Traffic Only"]
|
|
1115
|
+
df[bool_cols] = df[bool_cols].astype(bool)
|
|
1116
|
+
df["Creation Time"] = pd.to_datetime(df["Creation Time"])
|
|
1117
|
+
|
|
1118
|
+
return df
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
@log
|
|
1122
|
+
def check_resource_group_existence(
|
|
1123
|
+
azure_subscription_id: str, resource_group: str
|
|
1124
|
+
) -> bool:
|
|
1125
|
+
"""
|
|
1126
|
+
Checks whether a resource group exists.
|
|
1127
|
+
|
|
1128
|
+
This is a wrapper function for the following API: `Resource Groups - Check Existence <https://learn.microsoft.com/rest/api/resources/resource-groups/check-existence>`_.
|
|
1129
|
+
|
|
1130
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
1131
|
+
|
|
1132
|
+
Parameters
|
|
1133
|
+
----------
|
|
1134
|
+
azure_subscription_id : str
|
|
1135
|
+
The Azure subscription Id.
|
|
1136
|
+
resource_group : str
|
|
1137
|
+
The name of the resource group.
|
|
1138
|
+
|
|
1139
|
+
Returns
|
|
1140
|
+
-------
|
|
1141
|
+
bool
|
|
1142
|
+
True/False indicating if the resource group exists or not.
|
|
1143
|
+
"""
|
|
1144
|
+
|
|
1145
|
+
headers = _get_headers(auth.token_provider.get(), audience="azure")
|
|
1146
|
+
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}?api-version=2021-04-01"
|
|
1147
|
+
|
|
1148
|
+
response = requests.get(url, headers=headers)
|
|
1149
|
+
|
|
1150
|
+
if response.status_code not in [200, 204, 404]:
|
|
1151
|
+
raise FabricHTTPException(response)
|
|
1152
|
+
|
|
1153
|
+
if response.status_code == 200:
|
|
1154
|
+
return True
|
|
1155
|
+
elif response.status_code in [204, 404]:
|
|
1156
|
+
return False
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
@log
|
|
1160
|
+
def list_resource_groups(
|
|
1161
|
+
azure_subscription_id: str,
|
|
1162
|
+
filter: Optional[str] = None,
|
|
1163
|
+
top: Optional[int] = None,
|
|
1164
|
+
) -> pd.DataFrame:
|
|
1165
|
+
"""
|
|
1166
|
+
Lists all resource groups within a subscription.
|
|
1167
|
+
|
|
1168
|
+
This is a wrapper function for the following API: `Resource Groups - List <https://learn.microsoft.com/rest/api/resources/resource-groups/list>`_.
|
|
1169
|
+
|
|
1170
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
1171
|
+
|
|
1172
|
+
Parameters
|
|
1173
|
+
----------
|
|
1174
|
+
azure_subscription_id : str
|
|
1175
|
+
The Azure subscription Id.
|
|
1176
|
+
filter : str, default=None
|
|
1177
|
+
The filter to apply to the operation. Example: filter="tagname eq 'tagvalue'".
|
|
1178
|
+
top : int, default=None
|
|
1179
|
+
The number of results to return. If not specified, returns all results.
|
|
1180
|
+
|
|
1181
|
+
Returns
|
|
1182
|
+
-------
|
|
1183
|
+
pandas.DataFrame
|
|
1184
|
+
A pandas dataframe showing a list of all resource groups within the subscription.
|
|
1185
|
+
"""
|
|
1186
|
+
|
|
1187
|
+
headers = _get_headers(auth.token_provider.get(), audience="azure")
|
|
1188
|
+
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups?"
|
|
1189
|
+
|
|
1190
|
+
if filter is not None:
|
|
1191
|
+
url += f"$filter={filter}&"
|
|
1192
|
+
if top is not None:
|
|
1193
|
+
url += f"$top={top}&"
|
|
1194
|
+
|
|
1195
|
+
url += "api-version=2021-04-01"
|
|
1196
|
+
|
|
1197
|
+
df = pd.DataFrame(columns=["Resource Group Name", "Location", "Tags"])
|
|
1198
|
+
response = requests.get(url, headers=headers)
|
|
1199
|
+
|
|
1200
|
+
if response.status_code != 200:
|
|
1201
|
+
raise FabricHTTPException(response)
|
|
1202
|
+
|
|
1203
|
+
for v in response.json().get("value", []):
|
|
1204
|
+
new_data = {
|
|
1205
|
+
"Resource Group Id": v.get("id"),
|
|
1206
|
+
"Resource Group Name": v.get("name"),
|
|
1207
|
+
"Location": v.get("location"),
|
|
1208
|
+
"Managed By": v.get("managedBy"),
|
|
1209
|
+
"Tags": v.get("tags"),
|
|
1210
|
+
"Type": v.get("type"),
|
|
1211
|
+
"Provisioning State": v.get("properties", {}).get("provisioningState"),
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
|
|
1215
|
+
|
|
1216
|
+
return df
|
|
1217
|
+
|
|
1218
|
+
|
|
1219
|
+
@log
|
|
1220
|
+
def get_resource_group(azure_subscription_id: str, resource_group: str) -> pd.DataFrame:
|
|
1221
|
+
"""
|
|
1222
|
+
Gets details about a specified resource group.
|
|
1223
|
+
|
|
1224
|
+
This is a wrapper function for the following API: `Resource Groups - Get <https://learn.microsoft.com/rest/api/resources/resource-groups/get>`_.
|
|
1225
|
+
|
|
1226
|
+
Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
|
|
1227
|
+
|
|
1228
|
+
Parameters
|
|
1229
|
+
----------
|
|
1230
|
+
azure_subscription_id : str
|
|
1231
|
+
The Azure subscription Id.
|
|
1232
|
+
resource_group : str
|
|
1233
|
+
The name of the resource group.
|
|
1234
|
+
|
|
1235
|
+
Returns
|
|
1236
|
+
-------
|
|
1237
|
+
pandas.DataFrame
|
|
1238
|
+
A pandas dataframe showing details of a specific resource group.
|
|
1239
|
+
"""
|
|
1240
|
+
|
|
1241
|
+
headers = _get_headers(auth.token_provider.get(), audience="azure")
|
|
1242
|
+
url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}?api-version=2021-04-01"
|
|
1243
|
+
|
|
1244
|
+
response = requests.get(url, headers=headers)
|
|
1245
|
+
|
|
1246
|
+
if response.status_code != 200:
|
|
1247
|
+
raise FabricHTTPException(response)
|
|
1248
|
+
|
|
1249
|
+
v = response.json()
|
|
1250
|
+
new_data = {
|
|
1251
|
+
"Resource Group Id": v.get("id"),
|
|
1252
|
+
"Resource Group Name": v.get("name"),
|
|
1253
|
+
"Location": v.get("location"),
|
|
1254
|
+
"Managed By": v.get("managedBy"),
|
|
1255
|
+
"Tags": v.get("tags"),
|
|
1256
|
+
"Type": v.get("type"),
|
|
1257
|
+
"Provisioning State": v.get("properties", {}).get("provisioningState"),
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
return pd.DataFrame(new_data, index=[0])
|