semantic-link-labs 0.7.3__py3-none-any.whl → 0.8.0__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.

Files changed (75) hide show
  1. {semantic_link_labs-0.7.3.dist-info → semantic_link_labs-0.8.0.dist-info}/METADATA +19 -4
  2. {semantic_link_labs-0.7.3.dist-info → semantic_link_labs-0.8.0.dist-info}/RECORD +75 -50
  3. {semantic_link_labs-0.7.3.dist-info → semantic_link_labs-0.8.0.dist-info}/WHEEL +1 -1
  4. sempy_labs/__init__.py +109 -31
  5. sempy_labs/_bpa_translation/{_translations_am-ET.po → _model/_translations_am-ET.po} +22 -0
  6. sempy_labs/_bpa_translation/{_translations_ar-AE.po → _model/_translations_ar-AE.po} +24 -0
  7. sempy_labs/_bpa_translation/_model/_translations_bg-BG.po +938 -0
  8. sempy_labs/_bpa_translation/_model/_translations_ca-ES.po +934 -0
  9. sempy_labs/_bpa_translation/{_translations_cs-CZ.po → _model/_translations_cs-CZ.po} +179 -157
  10. sempy_labs/_bpa_translation/{_translations_da-DK.po → _model/_translations_da-DK.po} +24 -0
  11. sempy_labs/_bpa_translation/{_translations_de-DE.po → _model/_translations_de-DE.po} +77 -52
  12. sempy_labs/_bpa_translation/{_translations_el-GR.po → _model/_translations_el-GR.po} +25 -0
  13. sempy_labs/_bpa_translation/{_translations_es-ES.po → _model/_translations_es-ES.po} +67 -43
  14. sempy_labs/_bpa_translation/{_translations_fa-IR.po → _model/_translations_fa-IR.po} +24 -0
  15. sempy_labs/_bpa_translation/_model/_translations_fi-FI.po +915 -0
  16. sempy_labs/_bpa_translation/{_translations_fr-FR.po → _model/_translations_fr-FR.po} +83 -57
  17. sempy_labs/_bpa_translation/{_translations_ga-IE.po → _model/_translations_ga-IE.po} +25 -0
  18. sempy_labs/_bpa_translation/{_translations_he-IL.po → _model/_translations_he-IL.po} +23 -0
  19. sempy_labs/_bpa_translation/{_translations_hi-IN.po → _model/_translations_hi-IN.po} +24 -0
  20. sempy_labs/_bpa_translation/{_translations_hu-HU.po → _model/_translations_hu-HU.po} +25 -0
  21. sempy_labs/_bpa_translation/_model/_translations_id-ID.po +918 -0
  22. sempy_labs/_bpa_translation/{_translations_is-IS.po → _model/_translations_is-IS.po} +25 -0
  23. sempy_labs/_bpa_translation/{_translations_it-IT.po → _model/_translations_it-IT.po} +25 -0
  24. sempy_labs/_bpa_translation/{_translations_ja-JP.po → _model/_translations_ja-JP.po} +21 -0
  25. sempy_labs/_bpa_translation/_model/_translations_ko-KR.po +823 -0
  26. sempy_labs/_bpa_translation/_model/_translations_mt-MT.po +937 -0
  27. sempy_labs/_bpa_translation/{_translations_nl-NL.po → _model/_translations_nl-NL.po} +80 -56
  28. sempy_labs/_bpa_translation/{_translations_pl-PL.po → _model/_translations_pl-PL.po} +101 -76
  29. sempy_labs/_bpa_translation/{_translations_pt-BR.po → _model/_translations_pt-BR.po} +25 -0
  30. sempy_labs/_bpa_translation/{_translations_pt-PT.po → _model/_translations_pt-PT.po} +25 -0
  31. sempy_labs/_bpa_translation/_model/_translations_ro-RO.po +939 -0
  32. sempy_labs/_bpa_translation/{_translations_ru-RU.po → _model/_translations_ru-RU.po} +25 -0
  33. sempy_labs/_bpa_translation/_model/_translations_sk-SK.po +925 -0
  34. sempy_labs/_bpa_translation/_model/_translations_sl-SL.po +922 -0
  35. sempy_labs/_bpa_translation/{_translations_ta-IN.po → _model/_translations_ta-IN.po} +26 -0
  36. sempy_labs/_bpa_translation/{_translations_te-IN.po → _model/_translations_te-IN.po} +24 -0
  37. sempy_labs/_bpa_translation/{_translations_th-TH.po → _model/_translations_th-TH.po} +24 -0
  38. sempy_labs/_bpa_translation/_model/_translations_tr-TR.po +925 -0
  39. sempy_labs/_bpa_translation/_model/_translations_uk-UA.po +933 -0
  40. sempy_labs/_bpa_translation/{_translations_zh-CN.po → _model/_translations_zh-CN.po} +116 -97
  41. sempy_labs/_bpa_translation/{_translations_zu-ZA.po → _model/_translations_zu-ZA.po} +25 -0
  42. sempy_labs/_capacities.py +577 -0
  43. sempy_labs/_capacity_migration.py +624 -0
  44. sempy_labs/_clear_cache.py +8 -8
  45. sempy_labs/_connections.py +140 -0
  46. sempy_labs/_environments.py +156 -0
  47. sempy_labs/_git.py +20 -21
  48. sempy_labs/_helper_functions.py +151 -10
  49. sempy_labs/_icons.py +62 -0
  50. sempy_labs/_list_functions.py +232 -887
  51. sempy_labs/_model_bpa.py +8 -32
  52. sempy_labs/_notebooks.py +143 -0
  53. sempy_labs/_query_scale_out.py +30 -8
  54. sempy_labs/_spark.py +460 -0
  55. sempy_labs/_sql.py +88 -19
  56. sempy_labs/_translations.py +3 -0
  57. sempy_labs/_vertipaq.py +162 -99
  58. sempy_labs/_workspaces.py +294 -0
  59. sempy_labs/admin/__init__.py +53 -0
  60. sempy_labs/admin/_basic_functions.py +806 -0
  61. sempy_labs/admin/_domains.py +411 -0
  62. sempy_labs/directlake/_directlake_schema_sync.py +1 -2
  63. sempy_labs/directlake/_generate_shared_expression.py +11 -14
  64. sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +14 -24
  65. sempy_labs/report/__init__.py +9 -6
  66. sempy_labs/report/_report_bpa.py +359 -0
  67. sempy_labs/report/_report_bpa_rules.py +113 -0
  68. sempy_labs/report/_report_helper.py +254 -0
  69. sempy_labs/report/_report_list_functions.py +95 -0
  70. sempy_labs/report/_report_rebind.py +0 -4
  71. sempy_labs/report/_reportwrapper.py +2039 -0
  72. sempy_labs/tom/_model.py +83 -5
  73. {semantic_link_labs-0.7.3.dist-info → semantic_link_labs-0.8.0.dist-info}/LICENSE +0 -0
  74. {semantic_link_labs-0.7.3.dist-info → semantic_link_labs-0.8.0.dist-info}/top_level.txt +0 -0
  75. /sempy_labs/_bpa_translation/{_translations_sv-SE.po → _model/_translations_sv-SE.po} +0 -0
@@ -0,0 +1,577 @@
1
+ import sempy.fabric as fabric
2
+ from typing import Optional, List
3
+ from sempy._utils._log import log
4
+ import sempy_labs._icons as icons
5
+ from sempy.fabric.exceptions import FabricHTTPException
6
+ import requests
7
+ from sempy_labs._helper_functions import get_azure_token_credentials
8
+ import pandas as pd
9
+
10
+
11
+ def _add_sll_tag(payload, tags):
12
+
13
+ if tags is None:
14
+ payload["tags"] = {"SLL": 1}
15
+ else:
16
+ if "tags" not in payload:
17
+ payload["tags"] = tags
18
+ payload["tags"]["SLL"] = 1
19
+
20
+ return payload
21
+
22
+
23
+ @log
24
+ def create_fabric_capacity(
25
+ capacity_name: str,
26
+ 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
+ resource_group: str,
32
+ region: str,
33
+ sku: str,
34
+ admin_members: str | List[str],
35
+ tags: Optional[dict] = None,
36
+ ):
37
+ """
38
+ This function creates a new Fabric capacity within an Azure subscription.
39
+
40
+ Parameters
41
+ ----------
42
+ capacity_name : str
43
+ Name of the Fabric capacity.
44
+ azure_subscription_id : str
45
+ The Azure subscription ID.
46
+ key_vault_uri : str
47
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
48
+ key_vault_tenant_id : str
49
+ The name of the Azure key vault secret storing the Tenant ID.
50
+ key_vault_client_id : str
51
+ The name of the Azure key vault secret storing the Client ID.
52
+ key_vault_client_secret : str
53
+ The name of the Azure key vault secret storing the Client Secret.
54
+ resource_group : str
55
+ The name of the Azure resource group.
56
+ region : str
57
+ The name of the region in which the capacity will be created.
58
+ sku : str
59
+ The `sku size <https://azure.microsoft.com/pricing/details/microsoft-fabric/>`_ of the Fabric capacity.
60
+ admin_members : str | List[str]
61
+ The email address(es) of the admin(s) of the Fabric capacity.
62
+ tags: dict, default=None
63
+ Tag(s) to add to the capacity. Example: {'tagName': 'tagValue'}.
64
+ """
65
+
66
+ from azure.mgmt.resource import ResourceManagementClient
67
+
68
+ capacity_suffix = "fsku"
69
+
70
+ if isinstance(admin_members, str):
71
+ admin_members = [admin_members]
72
+
73
+ # list source: https://learn.microsoft.com/fabric/admin/region-availability
74
+ region_list = [
75
+ "Brazil South",
76
+ "North Europe",
77
+ "UAE North",
78
+ "South Africa North",
79
+ "Australia East",
80
+ "Canada Central",
81
+ "West Europe",
82
+ "Australia Southeast",
83
+ "Canada East",
84
+ "France Central",
85
+ "Central India",
86
+ "East US",
87
+ "Germany West Central",
88
+ "East Asia",
89
+ "East US 2",
90
+ "Norway East",
91
+ "Japan East",
92
+ "North Central US",
93
+ "Sweden Central",
94
+ "Korea Central",
95
+ "South Central US",
96
+ "Switzerland North",
97
+ "Southeast Asia",
98
+ "West US",
99
+ "Switzerland West",
100
+ "South India",
101
+ "West US 2",
102
+ "UK South",
103
+ "West US 3",
104
+ "UK West",
105
+ "brazilsouth",
106
+ "northeurope",
107
+ "uaenorth",
108
+ "southafricanorth",
109
+ "australiaeast",
110
+ "canadacentral",
111
+ "westeurope",
112
+ "australiasoutheast",
113
+ "canadaeast",
114
+ "francecentral",
115
+ "centralindia",
116
+ "eastus",
117
+ "germanywestcentral",
118
+ "eastasia",
119
+ "eastus2",
120
+ "norwayeast",
121
+ "japaneast",
122
+ "northcentralus",
123
+ "swedencentral",
124
+ "koreacentral",
125
+ "southcentralus",
126
+ "switzerlandnorth",
127
+ "southeastasia",
128
+ "westus",
129
+ "switzerlandwest",
130
+ "southindia",
131
+ "westus2",
132
+ "uksouth",
133
+ "westus3",
134
+ "ukwest",
135
+ ]
136
+
137
+ valid_regions = [
138
+ region for region in region_list if any(char.isupper() for char in region)
139
+ ]
140
+
141
+ if region not in region_list:
142
+ raise ValueError(
143
+ f"{icons.red_dot} Invalid region. Valid options: {valid_regions}."
144
+ )
145
+
146
+ azure_token, credential, headers = get_azure_token_credentials(
147
+ key_vault_uri=key_vault_uri,
148
+ key_vault_tenant_id=key_vault_tenant_id,
149
+ key_vault_client_id=key_vault_client_id,
150
+ key_vault_client_secret=key_vault_client_secret,
151
+ )
152
+
153
+ resource_client = ResourceManagementClient(credential, azure_subscription_id)
154
+
155
+ if resource_group is None:
156
+ for i in resource_client.resources.list(
157
+ "resourceType eq 'Microsoft.PowerBIDedicated/capacities'"
158
+ ):
159
+ if i.name == capacity_name.removesuffix(icons.migrate_capacity_suffix):
160
+ resource_group = i.id.split("/")[4]
161
+ print(
162
+ f"{icons.yellow_dot} Override resource group flag detected for A SKUs - using the existing resource group '{resource_group}' for the '{capacity_name}' capacity."
163
+ )
164
+ else:
165
+ # Attempt to get the resource group
166
+ try:
167
+ rg = resource_client.resource_groups.get(resource_group)
168
+ if rg.location != region:
169
+ print(
170
+ f"{icons.yellow_dot} The '{resource_group}' resource group exists, but in a different region."
171
+ )
172
+ except Exception:
173
+ # If the resource group does not exist, create it
174
+ print(
175
+ f"{icons.yellow_dot} The '{resource_group}' resource group does not exist."
176
+ )
177
+ print(
178
+ f"{icons.in_progress} Creating the '{resource_group}' resource group in the '{region}' region"
179
+ )
180
+ rg_result = resource_client.resource_groups.create_or_update(
181
+ resource_group, {"location": region}
182
+ )
183
+ print(
184
+ f"{icons.green_dot} Provisioned resource group with ID: {rg_result.id}"
185
+ )
186
+
187
+ payload = {
188
+ "properties": {"administration": {"members": admin_members}},
189
+ "sku": {"name": sku, "tier": "Fabric"},
190
+ "location": region,
191
+ }
192
+
193
+ payload = _add_sll_tag(payload, tags)
194
+
195
+ print(
196
+ f"{icons.in_progress} Creating the '{capacity_name}' capacity as an '{sku}' SKU within the '{region}' region..."
197
+ )
198
+
199
+ 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}"
200
+
201
+ response = requests.put(url, headers=headers, json=payload)
202
+
203
+ if response.status_code not in [200, 201]:
204
+ raise FabricHTTPException(response)
205
+
206
+ print(
207
+ f"{icons.green_dot} Successfully created the '{capacity_name}' capacity within the '{region}' region."
208
+ )
209
+
210
+
211
+ def list_vcores() -> pd.DataFrame:
212
+
213
+ df = pd.DataFrame(columns=["Total Purchased Cores", "Available Cores"])
214
+
215
+ client = fabric.PowerBIRestClient()
216
+ response = client.get("capacities/vcores")
217
+ if response.status_code != 200:
218
+ FabricHTTPException(response)
219
+ response_json = response.json()
220
+ new_data = {
221
+ "Total Purchased Cores": response_json.get("totalPurchasedCores"),
222
+ "Available Cores": response_json.get("availableCores"),
223
+ }
224
+ df = pd.concat([df, pd.DataFrame(new_data, index=[0])], ignore_index=True)
225
+
226
+ int_cols = ["Total Purchased Cores", "Available Cores"]
227
+ df[int_cols] = df[int_cols].astype(int)
228
+
229
+ return df
230
+
231
+
232
+ def get_capacity_resource_governance(capacity_name: str):
233
+
234
+ dfC = fabric.list_capacities()
235
+ dfC_filt = dfC[dfC["Display Name"] == capacity_name]
236
+ capacity_id = dfC_filt["Id"].iloc[0].upper()
237
+ client = fabric.PowerBIRestClient()
238
+ response = client.get(f"capacities/{capacity_id}/resourceGovernance")
239
+
240
+ if response.status_code != 200:
241
+ FabricHTTPException(response)
242
+
243
+ return response.json()["workloadSettings"]
244
+
245
+
246
+ def suspend_fabric_capacity(
247
+ capacity_name: str,
248
+ azure_subscription_id: str,
249
+ resource_group: str,
250
+ key_vault_uri: str,
251
+ key_vault_tenant_id: str,
252
+ key_vault_client_id: str,
253
+ key_vault_client_secret: str,
254
+ ):
255
+ """
256
+ This function suspends a Fabric capacity.
257
+
258
+ Parameters
259
+ ----------
260
+ capacity_name : str
261
+ Name of the Fabric capacity.
262
+ azure_subscription_id : str
263
+ The Azure subscription ID.
264
+ resource_group : str
265
+ The name of the Azure resource group.
266
+ key_vault_uri : str
267
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
268
+ key_vault_tenant_id : str
269
+ The name of the Azure key vault secret storing the Tenant ID.
270
+ key_vault_client_id : str
271
+ The name of the Azure key vault secret storing the Client ID.
272
+ key_vault_client_secret : str
273
+ The name of the Azure key vault secret storing the Client Secret.
274
+ """
275
+ # https://learn.microsoft.com/en-us/rest/api/microsoftfabric/fabric-capacities/suspend?view=rest-microsoftfabric-2023-11-01&tabs=HTTP
276
+
277
+ azure_token, credential, headers = get_azure_token_credentials(
278
+ key_vault_uri=key_vault_uri,
279
+ key_vault_tenant_id=key_vault_tenant_id,
280
+ key_vault_client_id=key_vault_client_id,
281
+ key_vault_client_secret=key_vault_client_secret,
282
+ )
283
+
284
+ 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}"
285
+
286
+ response = requests.post(url, headers=headers)
287
+
288
+ if response.status_code != 202:
289
+ raise FabricHTTPException(response)
290
+
291
+ print(f"{icons.green_dot} The '{capacity_name} capacity has been suspended.")
292
+
293
+
294
+ def resume_fabric_capacity(
295
+ capacity_name: str,
296
+ azure_subscription_id: str,
297
+ resource_group: str,
298
+ key_vault_uri: str,
299
+ key_vault_tenant_id: str,
300
+ key_vault_client_id: str,
301
+ key_vault_client_secret: str,
302
+ ):
303
+ """
304
+ This function resumes a Fabric capacity.
305
+
306
+ Parameters
307
+ ----------
308
+ capacity_name : str
309
+ Name of the Fabric capacity.
310
+ azure_subscription_id : str
311
+ The Azure subscription ID.
312
+ resource_group : str
313
+ The name of the Azure resource group.
314
+ key_vault_uri : str
315
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
316
+ key_vault_tenant_id : str
317
+ The name of the Azure key vault secret storing the Tenant ID.
318
+ key_vault_client_id : str
319
+ The name of the Azure key vault secret storing the Client ID.
320
+ key_vault_client_secret : str
321
+ The name of the Azure key vault secret storing the Client Secret.
322
+ """
323
+
324
+ # https://learn.microsoft.com/en-us/rest/api/microsoftfabric/fabric-capacities/resume?view=rest-microsoftfabric-2023-11-01&tabs=HTTP
325
+
326
+ azure_token, credential, headers = get_azure_token_credentials(
327
+ key_vault_uri=key_vault_uri,
328
+ key_vault_tenant_id=key_vault_tenant_id,
329
+ key_vault_client_id=key_vault_client_id,
330
+ key_vault_client_secret=key_vault_client_secret,
331
+ )
332
+
333
+ 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}"
334
+
335
+ response = requests.post(url, headers=headers)
336
+
337
+ if response.status_code != 202:
338
+ raise FabricHTTPException(response)
339
+
340
+ print(f"{icons.green_dot} The '{capacity_name} capacity has been resumed.")
341
+
342
+
343
+ def delete_embedded_capacity(
344
+ capacity_name: str,
345
+ azure_subscription_id: str,
346
+ resource_group: str,
347
+ key_vault_uri: str,
348
+ key_vault_tenant_id: str,
349
+ key_vault_client_id: str,
350
+ key_vault_client_secret: str,
351
+ ):
352
+ """
353
+ This function deletes a Power BI Embedded capacity.
354
+
355
+ Parameters
356
+ ----------
357
+ capacity_name : str
358
+ Name of the Fabric capacity.
359
+ azure_subscription_id : str
360
+ The Azure subscription ID.
361
+ resource_group : str
362
+ The name of the Azure resource group.
363
+ key_vault_uri : str
364
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
365
+ key_vault_tenant_id : str
366
+ The name of the Azure key vault secret storing the Tenant ID.
367
+ key_vault_client_id : str
368
+ The name of the Azure key vault secret storing the Client ID.
369
+ key_vault_client_secret : str
370
+ The name of the Azure key vault secret storing the Client Secret.
371
+ """
372
+
373
+ # https://learn.microsoft.com/en-us/rest/api/power-bi-embedded/capacities/delete?view=rest-power-bi-embedded-2021-01-01&tabs=HTTP
374
+
375
+ azure_token, credential, headers = get_azure_token_credentials(
376
+ key_vault_uri=key_vault_uri,
377
+ key_vault_tenant_id=key_vault_tenant_id,
378
+ key_vault_client_id=key_vault_client_id,
379
+ key_vault_client_secret=key_vault_client_secret,
380
+ )
381
+
382
+ 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}"
383
+
384
+ response = requests.delete(url, headers=headers)
385
+
386
+ if response.status_code not in [200, 202]:
387
+ raise FabricHTTPException(response)
388
+
389
+ print(f"{icons.green_dot} The '{capacity_name} capacity has been deleted.")
390
+
391
+
392
+ def delete_premium_capacity(capacity_name: str):
393
+ """
394
+ This function deletes a Power BI Premium capacity.
395
+
396
+ Parameters
397
+ ----------
398
+ capacity_name : str
399
+ Name of the Fabric capacity.
400
+ """
401
+
402
+ dfC = fabric.list_capacities()
403
+
404
+ dfC_filt = dfC[dfC["Display Name"] == capacity_name]
405
+ if len(dfC_filt) == 0:
406
+ raise ValueError(
407
+ f"{icons.red_dot} The '{capacity_name}' capacity does not exist."
408
+ )
409
+ capacity_id = dfC_filt["Id"].iloc[0].upper()
410
+
411
+ client = fabric.FabricRestClient()
412
+ response = client.delete(f"capacities/{capacity_id}")
413
+
414
+ if response.status_code != 204:
415
+ raise FabricHTTPException(response)
416
+
417
+ print(f"{icons.green_dot} The '{capacity_name}' capacity has been deleted.")
418
+
419
+
420
+ def delete_fabric_capacity(
421
+ capacity_name: str,
422
+ azure_subscription_id: str,
423
+ resource_group: str,
424
+ key_vault_uri: str,
425
+ key_vault_tenant_id: str,
426
+ key_vault_client_id: str,
427
+ key_vault_client_secret: str,
428
+ ):
429
+ """
430
+ This function deletes a Fabric capacity.
431
+
432
+ Parameters
433
+ ----------
434
+ capacity_name : str
435
+ Name of the Fabric capacity.
436
+ azure_subscription_id : str
437
+ The Azure subscription ID.
438
+ resource_group : str
439
+ The name of the Azure resource group.
440
+ key_vault_uri : str
441
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
442
+ key_vault_tenant_id : str
443
+ The name of the Azure key vault secret storing the Tenant ID.
444
+ key_vault_client_id : str
445
+ The name of the Azure key vault secret storing the Client ID.
446
+ key_vault_client_secret : str
447
+ The name of the Azure key vault secret storing the Client Secret.
448
+ """
449
+
450
+ # https://learn.microsoft.com/en-us/rest/api/microsoftfabric/fabric-capacities/delete?view=rest-microsoftfabric-2023-11-01&tabs=HTTP
451
+
452
+ azure_token, credential, headers = get_azure_token_credentials(
453
+ key_vault_uri=key_vault_uri,
454
+ key_vault_tenant_id=key_vault_tenant_id,
455
+ key_vault_client_id=key_vault_client_id,
456
+ key_vault_client_secret=key_vault_client_secret,
457
+ )
458
+
459
+ 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}"
460
+
461
+ response = requests.delete(url, headers=headers)
462
+
463
+ if response.status_code != 202:
464
+ raise FabricHTTPException(response)
465
+
466
+ print(f"{icons.green_dot} The '{capacity_name} capacity has been deleted.")
467
+
468
+
469
+ def update_fabric_capacity(
470
+ capacity_name: str,
471
+ azure_subscription_id: str,
472
+ resource_group: str,
473
+ key_vault_uri: str,
474
+ key_vault_tenant_id: str,
475
+ key_vault_client_id: str,
476
+ key_vault_client_secret: str,
477
+ sku: Optional[str] = None,
478
+ admin_members: Optional[str | List[str]] = None,
479
+ tags: Optional[dict] = None,
480
+ ):
481
+ """
482
+ This function updates a Fabric capacity's properties.
483
+
484
+ Parameters
485
+ ----------
486
+ capacity_name : str
487
+ Name of the Fabric capacity.
488
+ azure_subscription_id : str
489
+ The Azure subscription ID.
490
+ resource_group : str
491
+ The name of the Azure resource group.
492
+ key_vault_uri : str
493
+ The name of the `Azure key vault <https://azure.microsoft.com/products/key-vault>`_ URI. Example: "https://<Key Vault Name>.vault.azure.net/"
494
+ key_vault_tenant_id : str
495
+ The name of the Azure key vault secret storing the Tenant ID.
496
+ key_vault_client_id : str
497
+ The name of the Azure key vault secret storing the Client ID.
498
+ key_vault_client_secret : str
499
+ The name of the Azure key vault secret storing the Client Secret.
500
+ sku : str, default=None
501
+ The `sku size <https://azure.microsoft.com/pricing/details/microsoft-fabric/>`_ of the Fabric capacity.
502
+ admin_members : str | List[str], default=None
503
+ The email address(es) of the admin(s) of the Fabric capacity.
504
+ tags : dict, default=None
505
+ Tag(s) to add to the capacity. Example: {'tagName': 'tagValue'}.
506
+
507
+ """
508
+
509
+ # https://learn.microsoft.com/en-us/rest/api/microsoftfabric/fabric-capacities/update?view=rest-microsoftfabric-2023-11-01&tabs=HTTP
510
+
511
+ if isinstance(admin_members, str):
512
+ admin_members = [admin_members]
513
+ if tags is not None and not isinstance(tags, dict):
514
+ raise ValueError(
515
+ f"{icons.red_dot} If specified, the 'tags' parameter must be a dictionary."
516
+ )
517
+
518
+ azure_token, credential, headers = get_azure_token_credentials(
519
+ key_vault_uri=key_vault_uri,
520
+ key_vault_tenant_id=key_vault_tenant_id,
521
+ key_vault_client_id=key_vault_client_id,
522
+ key_vault_client_secret=key_vault_client_secret,
523
+ )
524
+
525
+ 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}"
526
+
527
+ payload = {}
528
+ if sku is not None:
529
+ payload["sku"] = {"name": sku, "tier": "Fabric"}
530
+ if admin_members is not None:
531
+ payload["properties"] = {"administration": {"members": [admin_members]}}
532
+
533
+ payload = _add_sll_tag(payload, tags)
534
+
535
+ if payload == {}:
536
+ raise ValueError(
537
+ f"{icons.warning} No parameters have been set to update the '{capacity_name}' capacity."
538
+ )
539
+
540
+ response = requests.patch(url, headers=headers, data=payload)
541
+
542
+ if response.status_code != 202:
543
+ raise FabricHTTPException(response)
544
+
545
+ print(
546
+ f"{icons.green_dot} The '{capacity_name} capacity has been updated accordingly."
547
+ )
548
+
549
+
550
+ def check_fabric_capacity_name_availablility(
551
+ capacity_name: str,
552
+ azure_subscription_id: str,
553
+ region: str,
554
+ key_vault_uri: str,
555
+ key_vault_tenant_id: str,
556
+ key_vault_client_id: str,
557
+ key_vault_client_secret: str,
558
+ ) -> bool:
559
+ # https://learn.microsoft.com/en-us/rest/api/microsoftfabric/fabric-capacities/check-name-availability?view=rest-microsoftfabric-2023-11-01&tabs=HTTP
560
+
561
+ azure_token, credential, headers = get_azure_token_credentials(
562
+ key_vault_uri=key_vault_uri,
563
+ key_vault_tenant_id=key_vault_tenant_id,
564
+ key_vault_client_id=key_vault_client_id,
565
+ key_vault_client_secret=key_vault_client_secret,
566
+ )
567
+
568
+ payload = {"name": capacity_name, "type": "Microsoft.Fabric/capacities"}
569
+
570
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/providers/Microsoft.Fabric/locations/{region}/checkNameAvailability?api-version={icons.azure_api_version}"
571
+
572
+ response = requests.post(url, headers=headers, data=payload)
573
+
574
+ if response.status_code != 202:
575
+ raise FabricHTTPException(response)
576
+
577
+ return bool(response.json().get("nameAvailable"))