semantic-link-labs 0.12.8__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.
Files changed (243) hide show
  1. semantic_link_labs-0.12.8.dist-info/METADATA +354 -0
  2. semantic_link_labs-0.12.8.dist-info/RECORD +243 -0
  3. semantic_link_labs-0.12.8.dist-info/WHEEL +5 -0
  4. semantic_link_labs-0.12.8.dist-info/licenses/LICENSE +21 -0
  5. semantic_link_labs-0.12.8.dist-info/top_level.txt +1 -0
  6. sempy_labs/__init__.py +606 -0
  7. sempy_labs/_a_lib_info.py +2 -0
  8. sempy_labs/_ai.py +437 -0
  9. sempy_labs/_authentication.py +264 -0
  10. sempy_labs/_bpa_translation/_model/_translations_am-ET.po +869 -0
  11. sempy_labs/_bpa_translation/_model/_translations_ar-AE.po +908 -0
  12. sempy_labs/_bpa_translation/_model/_translations_bg-BG.po +968 -0
  13. sempy_labs/_bpa_translation/_model/_translations_ca-ES.po +963 -0
  14. sempy_labs/_bpa_translation/_model/_translations_cs-CZ.po +943 -0
  15. sempy_labs/_bpa_translation/_model/_translations_da-DK.po +945 -0
  16. sempy_labs/_bpa_translation/_model/_translations_de-DE.po +988 -0
  17. sempy_labs/_bpa_translation/_model/_translations_el-GR.po +993 -0
  18. sempy_labs/_bpa_translation/_model/_translations_es-ES.po +971 -0
  19. sempy_labs/_bpa_translation/_model/_translations_fa-IR.po +933 -0
  20. sempy_labs/_bpa_translation/_model/_translations_fi-FI.po +942 -0
  21. sempy_labs/_bpa_translation/_model/_translations_fr-FR.po +994 -0
  22. sempy_labs/_bpa_translation/_model/_translations_ga-IE.po +967 -0
  23. sempy_labs/_bpa_translation/_model/_translations_he-IL.po +902 -0
  24. sempy_labs/_bpa_translation/_model/_translations_hi-IN.po +944 -0
  25. sempy_labs/_bpa_translation/_model/_translations_hu-HU.po +963 -0
  26. sempy_labs/_bpa_translation/_model/_translations_id-ID.po +946 -0
  27. sempy_labs/_bpa_translation/_model/_translations_is-IS.po +939 -0
  28. sempy_labs/_bpa_translation/_model/_translations_it-IT.po +986 -0
  29. sempy_labs/_bpa_translation/_model/_translations_ja-JP.po +846 -0
  30. sempy_labs/_bpa_translation/_model/_translations_ko-KR.po +839 -0
  31. sempy_labs/_bpa_translation/_model/_translations_mt-MT.po +967 -0
  32. sempy_labs/_bpa_translation/_model/_translations_nl-NL.po +978 -0
  33. sempy_labs/_bpa_translation/_model/_translations_pl-PL.po +962 -0
  34. sempy_labs/_bpa_translation/_model/_translations_pt-BR.po +962 -0
  35. sempy_labs/_bpa_translation/_model/_translations_pt-PT.po +957 -0
  36. sempy_labs/_bpa_translation/_model/_translations_ro-RO.po +968 -0
  37. sempy_labs/_bpa_translation/_model/_translations_ru-RU.po +964 -0
  38. sempy_labs/_bpa_translation/_model/_translations_sk-SK.po +952 -0
  39. sempy_labs/_bpa_translation/_model/_translations_sl-SL.po +950 -0
  40. sempy_labs/_bpa_translation/_model/_translations_sv-SE.po +942 -0
  41. sempy_labs/_bpa_translation/_model/_translations_ta-IN.po +976 -0
  42. sempy_labs/_bpa_translation/_model/_translations_te-IN.po +947 -0
  43. sempy_labs/_bpa_translation/_model/_translations_th-TH.po +924 -0
  44. sempy_labs/_bpa_translation/_model/_translations_tr-TR.po +953 -0
  45. sempy_labs/_bpa_translation/_model/_translations_uk-UA.po +961 -0
  46. sempy_labs/_bpa_translation/_model/_translations_zh-CN.po +804 -0
  47. sempy_labs/_bpa_translation/_model/_translations_zu-ZA.po +969 -0
  48. sempy_labs/_capacities.py +1198 -0
  49. sempy_labs/_capacity_migration.py +660 -0
  50. sempy_labs/_clear_cache.py +351 -0
  51. sempy_labs/_connections.py +610 -0
  52. sempy_labs/_dashboards.py +69 -0
  53. sempy_labs/_data_access_security.py +98 -0
  54. sempy_labs/_data_pipelines.py +162 -0
  55. sempy_labs/_dataflows.py +668 -0
  56. sempy_labs/_dax.py +501 -0
  57. sempy_labs/_daxformatter.py +80 -0
  58. sempy_labs/_delta_analyzer.py +467 -0
  59. sempy_labs/_delta_analyzer_history.py +301 -0
  60. sempy_labs/_dictionary_diffs.py +221 -0
  61. sempy_labs/_documentation.py +147 -0
  62. sempy_labs/_domains.py +51 -0
  63. sempy_labs/_eventhouses.py +182 -0
  64. sempy_labs/_external_data_shares.py +230 -0
  65. sempy_labs/_gateways.py +521 -0
  66. sempy_labs/_generate_semantic_model.py +521 -0
  67. sempy_labs/_get_connection_string.py +84 -0
  68. sempy_labs/_git.py +543 -0
  69. sempy_labs/_graphQL.py +90 -0
  70. sempy_labs/_helper_functions.py +2833 -0
  71. sempy_labs/_icons.py +149 -0
  72. sempy_labs/_job_scheduler.py +609 -0
  73. sempy_labs/_kql_databases.py +149 -0
  74. sempy_labs/_kql_querysets.py +124 -0
  75. sempy_labs/_kusto.py +137 -0
  76. sempy_labs/_labels.py +124 -0
  77. sempy_labs/_list_functions.py +1720 -0
  78. sempy_labs/_managed_private_endpoints.py +253 -0
  79. sempy_labs/_mirrored_databases.py +416 -0
  80. sempy_labs/_mirrored_warehouses.py +60 -0
  81. sempy_labs/_ml_experiments.py +113 -0
  82. sempy_labs/_model_auto_build.py +140 -0
  83. sempy_labs/_model_bpa.py +557 -0
  84. sempy_labs/_model_bpa_bulk.py +378 -0
  85. sempy_labs/_model_bpa_rules.py +859 -0
  86. sempy_labs/_model_dependencies.py +343 -0
  87. sempy_labs/_mounted_data_factories.py +123 -0
  88. sempy_labs/_notebooks.py +441 -0
  89. sempy_labs/_one_lake_integration.py +151 -0
  90. sempy_labs/_onelake.py +131 -0
  91. sempy_labs/_query_scale_out.py +433 -0
  92. sempy_labs/_refresh_semantic_model.py +435 -0
  93. sempy_labs/_semantic_models.py +468 -0
  94. sempy_labs/_spark.py +455 -0
  95. sempy_labs/_sql.py +241 -0
  96. sempy_labs/_sql_audit_settings.py +207 -0
  97. sempy_labs/_sql_endpoints.py +214 -0
  98. sempy_labs/_tags.py +201 -0
  99. sempy_labs/_translations.py +43 -0
  100. sempy_labs/_user_delegation_key.py +44 -0
  101. sempy_labs/_utils.py +79 -0
  102. sempy_labs/_vertipaq.py +1021 -0
  103. sempy_labs/_vpax.py +388 -0
  104. sempy_labs/_warehouses.py +234 -0
  105. sempy_labs/_workloads.py +140 -0
  106. sempy_labs/_workspace_identity.py +72 -0
  107. sempy_labs/_workspaces.py +595 -0
  108. sempy_labs/admin/__init__.py +170 -0
  109. sempy_labs/admin/_activities.py +167 -0
  110. sempy_labs/admin/_apps.py +145 -0
  111. sempy_labs/admin/_artifacts.py +65 -0
  112. sempy_labs/admin/_basic_functions.py +463 -0
  113. sempy_labs/admin/_capacities.py +508 -0
  114. sempy_labs/admin/_dataflows.py +45 -0
  115. sempy_labs/admin/_datasets.py +186 -0
  116. sempy_labs/admin/_domains.py +522 -0
  117. sempy_labs/admin/_external_data_share.py +100 -0
  118. sempy_labs/admin/_git.py +72 -0
  119. sempy_labs/admin/_items.py +265 -0
  120. sempy_labs/admin/_labels.py +211 -0
  121. sempy_labs/admin/_reports.py +241 -0
  122. sempy_labs/admin/_scanner.py +118 -0
  123. sempy_labs/admin/_shared.py +82 -0
  124. sempy_labs/admin/_sharing_links.py +110 -0
  125. sempy_labs/admin/_tags.py +131 -0
  126. sempy_labs/admin/_tenant.py +503 -0
  127. sempy_labs/admin/_tenant_keys.py +89 -0
  128. sempy_labs/admin/_users.py +140 -0
  129. sempy_labs/admin/_workspaces.py +236 -0
  130. sempy_labs/deployment_pipeline/__init__.py +23 -0
  131. sempy_labs/deployment_pipeline/_items.py +580 -0
  132. sempy_labs/directlake/__init__.py +57 -0
  133. sempy_labs/directlake/_autosync.py +58 -0
  134. sempy_labs/directlake/_directlake_schema_compare.py +120 -0
  135. sempy_labs/directlake/_directlake_schema_sync.py +161 -0
  136. sempy_labs/directlake/_dl_helper.py +274 -0
  137. sempy_labs/directlake/_generate_shared_expression.py +94 -0
  138. sempy_labs/directlake/_get_directlake_lakehouse.py +62 -0
  139. sempy_labs/directlake/_get_shared_expression.py +34 -0
  140. sempy_labs/directlake/_guardrails.py +96 -0
  141. sempy_labs/directlake/_list_directlake_model_calc_tables.py +70 -0
  142. sempy_labs/directlake/_show_unsupported_directlake_objects.py +90 -0
  143. sempy_labs/directlake/_update_directlake_model_lakehouse_connection.py +239 -0
  144. sempy_labs/directlake/_update_directlake_partition_entity.py +259 -0
  145. sempy_labs/directlake/_warm_cache.py +236 -0
  146. sempy_labs/dotnet_lib/dotnet.runtime.config.json +10 -0
  147. sempy_labs/environment/__init__.py +23 -0
  148. sempy_labs/environment/_items.py +212 -0
  149. sempy_labs/environment/_pubstage.py +223 -0
  150. sempy_labs/eventstream/__init__.py +37 -0
  151. sempy_labs/eventstream/_items.py +263 -0
  152. sempy_labs/eventstream/_topology.py +652 -0
  153. sempy_labs/graph/__init__.py +59 -0
  154. sempy_labs/graph/_groups.py +651 -0
  155. sempy_labs/graph/_sensitivity_labels.py +120 -0
  156. sempy_labs/graph/_teams.py +125 -0
  157. sempy_labs/graph/_user_licenses.py +96 -0
  158. sempy_labs/graph/_users.py +516 -0
  159. sempy_labs/graph_model/__init__.py +15 -0
  160. sempy_labs/graph_model/_background_jobs.py +63 -0
  161. sempy_labs/graph_model/_items.py +149 -0
  162. sempy_labs/lakehouse/__init__.py +67 -0
  163. sempy_labs/lakehouse/_blobs.py +247 -0
  164. sempy_labs/lakehouse/_get_lakehouse_columns.py +102 -0
  165. sempy_labs/lakehouse/_get_lakehouse_tables.py +274 -0
  166. sempy_labs/lakehouse/_helper.py +250 -0
  167. sempy_labs/lakehouse/_lakehouse.py +351 -0
  168. sempy_labs/lakehouse/_livy_sessions.py +143 -0
  169. sempy_labs/lakehouse/_materialized_lake_views.py +157 -0
  170. sempy_labs/lakehouse/_partitioning.py +165 -0
  171. sempy_labs/lakehouse/_schemas.py +217 -0
  172. sempy_labs/lakehouse/_shortcuts.py +440 -0
  173. sempy_labs/migration/__init__.py +35 -0
  174. sempy_labs/migration/_create_pqt_file.py +238 -0
  175. sempy_labs/migration/_direct_lake_to_import.py +105 -0
  176. sempy_labs/migration/_migrate_calctables_to_lakehouse.py +398 -0
  177. sempy_labs/migration/_migrate_calctables_to_semantic_model.py +148 -0
  178. sempy_labs/migration/_migrate_model_objects_to_semantic_model.py +533 -0
  179. sempy_labs/migration/_migrate_tables_columns_to_semantic_model.py +172 -0
  180. sempy_labs/migration/_migration_validation.py +71 -0
  181. sempy_labs/migration/_refresh_calc_tables.py +131 -0
  182. sempy_labs/mirrored_azure_databricks_catalog/__init__.py +15 -0
  183. sempy_labs/mirrored_azure_databricks_catalog/_discover.py +213 -0
  184. sempy_labs/mirrored_azure_databricks_catalog/_refresh_catalog_metadata.py +45 -0
  185. sempy_labs/ml_model/__init__.py +23 -0
  186. sempy_labs/ml_model/_functions.py +427 -0
  187. sempy_labs/report/_BPAReportTemplate.json +232 -0
  188. sempy_labs/report/__init__.py +55 -0
  189. sempy_labs/report/_bpareporttemplate/.pbi/localSettings.json +9 -0
  190. sempy_labs/report/_bpareporttemplate/.platform +11 -0
  191. sempy_labs/report/_bpareporttemplate/StaticResources/SharedResources/BaseThemes/CY24SU06.json +710 -0
  192. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/page.json +11 -0
  193. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/1b08bce3bebabb0a27a8/visual.json +191 -0
  194. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/2f22ddb70c301693c165/visual.json +438 -0
  195. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/3b1182230aa6c600b43a/visual.json +127 -0
  196. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/58577ba6380c69891500/visual.json +576 -0
  197. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/a2a8fa5028b3b776c96c/visual.json +207 -0
  198. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/adfd47ef30652707b987/visual.json +506 -0
  199. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/b6a80ee459e716e170b1/visual.json +127 -0
  200. sempy_labs/report/_bpareporttemplate/definition/pages/01d72098bda5055bd500/visuals/ce3130a721c020cc3d81/visual.json +513 -0
  201. sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/page.json +8 -0
  202. sempy_labs/report/_bpareporttemplate/definition/pages/92735ae19b31712208ad/visuals/66e60dfb526437cd78d1/visual.json +112 -0
  203. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/page.json +11 -0
  204. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/07deb8bce824e1be37d7/visual.json +513 -0
  205. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0b1c68838818b32ad03b/visual.json +352 -0
  206. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0c171de9d2683d10b930/visual.json +37 -0
  207. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/0efa01be0510e40a645e/visual.json +542 -0
  208. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/6bf2f0eb830ab53cc668/visual.json +221 -0
  209. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/88d8141cb8500b60030c/visual.json +127 -0
  210. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/a753273590beed656a03/visual.json +576 -0
  211. sempy_labs/report/_bpareporttemplate/definition/pages/c597da16dc7e63222a82/visuals/b8fdc82cddd61ac447bc/visual.json +127 -0
  212. sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/page.json +9 -0
  213. sempy_labs/report/_bpareporttemplate/definition/pages/d37dce724a0ccc30044b/visuals/ce8532a7e25020271077/visual.json +38 -0
  214. sempy_labs/report/_bpareporttemplate/definition/pages/pages.json +10 -0
  215. sempy_labs/report/_bpareporttemplate/definition/report.json +176 -0
  216. sempy_labs/report/_bpareporttemplate/definition/version.json +4 -0
  217. sempy_labs/report/_bpareporttemplate/definition.pbir +14 -0
  218. sempy_labs/report/_download_report.py +76 -0
  219. sempy_labs/report/_export_report.py +257 -0
  220. sempy_labs/report/_generate_report.py +427 -0
  221. sempy_labs/report/_paginated.py +76 -0
  222. sempy_labs/report/_report_bpa.py +354 -0
  223. sempy_labs/report/_report_bpa_rules.py +115 -0
  224. sempy_labs/report/_report_functions.py +581 -0
  225. sempy_labs/report/_report_helper.py +227 -0
  226. sempy_labs/report/_report_list_functions.py +110 -0
  227. sempy_labs/report/_report_rebind.py +149 -0
  228. sempy_labs/report/_reportwrapper.py +3100 -0
  229. sempy_labs/report/_save_report.py +147 -0
  230. sempy_labs/snowflake_database/__init__.py +10 -0
  231. sempy_labs/snowflake_database/_items.py +105 -0
  232. sempy_labs/sql_database/__init__.py +21 -0
  233. sempy_labs/sql_database/_items.py +201 -0
  234. sempy_labs/sql_database/_mirroring.py +79 -0
  235. sempy_labs/theme/__init__.py +12 -0
  236. sempy_labs/theme/_org_themes.py +129 -0
  237. sempy_labs/tom/__init__.py +3 -0
  238. sempy_labs/tom/_model.py +5977 -0
  239. sempy_labs/variable_library/__init__.py +19 -0
  240. sempy_labs/variable_library/_functions.py +403 -0
  241. sempy_labs/warehouse/__init__.py +28 -0
  242. sempy_labs/warehouse/_items.py +234 -0
  243. sempy_labs/warehouse/_restore_points.py +309 -0
@@ -0,0 +1,1198 @@
1
+ from typing import Optional, List, Tuple
2
+ from sempy._utils._log import log
3
+ import sempy_labs._icons as icons
4
+ from sempy.fabric.exceptions import FabricHTTPException
5
+ import requests
6
+ import pandas as pd
7
+ from sempy_labs._authentication import (
8
+ _get_headers,
9
+ ServicePrincipalTokenProvider,
10
+ )
11
+ from uuid import UUID
12
+ from sempy_labs._helper_functions import (
13
+ _is_valid_uuid,
14
+ _update_dataframe_datatypes,
15
+ _base_api,
16
+ _create_dataframe,
17
+ )
18
+ import sempy_labs._authentication as auth
19
+
20
+
21
+ def _add_sll_tag(payload, tags):
22
+
23
+ if tags is None:
24
+ payload["tags"] = {"SLL": 1}
25
+ else:
26
+ if "tags" not in payload:
27
+ payload["tags"] = tags
28
+ payload["tags"]["SLL"] = 1
29
+
30
+ return payload
31
+
32
+
33
+ @log
34
+ def create_fabric_capacity(
35
+ capacity_name: str,
36
+ azure_subscription_id: str,
37
+ resource_group: str,
38
+ region: str,
39
+ sku: str,
40
+ admin_members: str | List[str],
41
+ tags: Optional[dict] = None,
42
+ **kwargs,
43
+ ):
44
+ """
45
+ This function creates a new Fabric capacity within an Azure subscription.
46
+
47
+ 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>`_.
48
+
49
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
50
+
51
+ Parameters
52
+ ----------
53
+ capacity_name : str
54
+ Name of the Fabric capacity.
55
+ azure_subscription_id : str
56
+ The Azure subscription ID.
57
+ resource_group : str
58
+ The name of the Azure resource group.
59
+ region : str
60
+ The name of the region in which the capacity will be created.
61
+ sku : str
62
+ The `sku size <https://azure.microsoft.com/pricing/details/microsoft-fabric/>`_ of the Fabric capacity.
63
+ admin_members : str | List[str]
64
+ The email address(es) of the admin(s) of the Fabric capacity.
65
+ tags: dict, default=None
66
+ Tag(s) to add to the capacity. Example: {'tagName': 'tagValue'}.
67
+ """
68
+
69
+ if isinstance(admin_members, str):
70
+ admin_members = [admin_members]
71
+
72
+ # list source: https://learn.microsoft.com/fabric/admin/region-availability
73
+ region_list = [
74
+ "Brazil South",
75
+ "North Europe",
76
+ "UAE North",
77
+ "South Africa North",
78
+ "Australia East",
79
+ "Canada Central",
80
+ "West Europe",
81
+ "Australia Southeast",
82
+ "Canada East",
83
+ "France Central",
84
+ "Central India",
85
+ "East US",
86
+ "Germany West Central",
87
+ "East Asia",
88
+ "East US 2",
89
+ "Norway East",
90
+ "Japan East",
91
+ "North Central US",
92
+ "Sweden Central",
93
+ "Korea Central",
94
+ "South Central US",
95
+ "Switzerland North",
96
+ "Southeast Asia",
97
+ "West US",
98
+ "Switzerland West",
99
+ "South India",
100
+ "West US 2",
101
+ "UK South",
102
+ "West US 3",
103
+ "UK West",
104
+ "brazilsouth",
105
+ "northeurope",
106
+ "uaenorth",
107
+ "southafricanorth",
108
+ "australiaeast",
109
+ "canadacentral",
110
+ "westeurope",
111
+ "australiasoutheast",
112
+ "canadaeast",
113
+ "francecentral",
114
+ "centralindia",
115
+ "eastus",
116
+ "germanywestcentral",
117
+ "eastasia",
118
+ "eastus2",
119
+ "norwayeast",
120
+ "japaneast",
121
+ "northcentralus",
122
+ "swedencentral",
123
+ "koreacentral",
124
+ "southcentralus",
125
+ "switzerlandnorth",
126
+ "southeastasia",
127
+ "westus",
128
+ "switzerlandwest",
129
+ "southindia",
130
+ "westus2",
131
+ "uksouth",
132
+ "westus3",
133
+ "ukwest",
134
+ ]
135
+
136
+ valid_regions = [
137
+ region for region in region_list if any(char.isupper() for char in region)
138
+ ]
139
+
140
+ if region not in region_list:
141
+ raise ValueError(
142
+ f"{icons.red_dot} Invalid region. Valid options: {valid_regions}."
143
+ )
144
+
145
+ token_provider = auth.token_provider.get()
146
+ if token_provider is None:
147
+ token_provider = ServicePrincipalTokenProvider.from_azure_key_vault(
148
+ key_vault_uri=kwargs["key_vault_uri"],
149
+ key_vault_tenant_id=kwargs["key_vault_tenant_id"],
150
+ key_vault_client_id=kwargs["key_vault_client_id"],
151
+ key_vault_client_secret=kwargs["key_vault_client_secret"],
152
+ )
153
+ print(
154
+ 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."
155
+ )
156
+ headers = _get_headers(token_provider, audience="azure")
157
+
158
+ if resource_group is None:
159
+ dfRG = list_resource_groups(
160
+ azure_subscription_id=azure_subscription_id,
161
+ filter="resourceType eq 'Microsoft.PowerBIDedicated/capacities'",
162
+ )
163
+ dfRG_filt = dfRG[
164
+ dfRG["Resource Group Name"]
165
+ == capacity_name.removesuffix(icons.migrate_capacity_suffix)
166
+ ]
167
+ if not dfRG_filt.empty:
168
+ resource_group = dfRG_filt["Resource Group Name"].iloc[0]
169
+ print(
170
+ f"{icons.yellow_dot} Override resource group flag detected for A SKUs - using the existing resource group '{resource_group}' for the '{capacity_name}' capacity."
171
+ )
172
+ else:
173
+ # Attempt to get the resource group
174
+ try:
175
+ dfRG = get_resource_group(
176
+ azure_subscription_id=azure_subscription_id,
177
+ resource_group=resource_group,
178
+ )
179
+ if dfRG["Location"].iloc[0] != region:
180
+ print(
181
+ f"{icons.yellow_dot} The '{resource_group}' resource group exists, but in a different region."
182
+ )
183
+ except Exception:
184
+ # If the resource group does not exist, create it
185
+ print(
186
+ f"{icons.yellow_dot} The '{resource_group}' resource group does not exist."
187
+ )
188
+ print(
189
+ f"{icons.in_progress} Creating the '{resource_group}' resource group in the '{region}' region"
190
+ )
191
+ create_or_update_resource_group(
192
+ azure_subscription_id=azure_subscription_id,
193
+ resource_group=resource_group,
194
+ region=region,
195
+ )
196
+
197
+ payload = {
198
+ "properties": {"administration": {"members": admin_members}},
199
+ "sku": {"name": sku, "tier": "Fabric"},
200
+ "location": region,
201
+ }
202
+
203
+ payload = _add_sll_tag(payload, tags)
204
+
205
+ print(
206
+ f"{icons.in_progress} Creating the '{capacity_name}' capacity as an '{sku}' SKU within the '{region}' region..."
207
+ )
208
+
209
+ 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}"
210
+
211
+ response = requests.put(url, headers=headers, json=payload)
212
+
213
+ if response.status_code not in [200, 201]:
214
+ raise FabricHTTPException(response)
215
+
216
+ print(
217
+ f"{icons.green_dot} Successfully created the '{capacity_name}' capacity within the '{region}' region."
218
+ )
219
+
220
+
221
+ @log
222
+ def list_vcores() -> pd.DataFrame:
223
+
224
+ columns = {
225
+ "Total Purchased Cores": "int",
226
+ "Available Cores": "int",
227
+ }
228
+ df = _create_dataframe(columns=columns)
229
+
230
+ response = _base_api(request="capacities/vcores")
231
+ response_json = response.json()
232
+ new_data = {
233
+ "Total Purchased Cores": response_json.get("totalPurchasedCores"),
234
+ "Available Cores": response_json.get("availableCores"),
235
+ }
236
+
237
+ df = pd.DataFrame([new_data], columns=columns.keys())
238
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
239
+
240
+ return df
241
+
242
+
243
+ @log
244
+ def get_capacity_resource_governance(capacity_name: str):
245
+
246
+ dfC = list_capacities()
247
+ dfC_filt = dfC[dfC["Display Name"] == capacity_name]
248
+ capacity_id = dfC_filt["Id"].iloc[0].upper()
249
+
250
+ response = _base_api(request=f"capacities/{capacity_id}/resourceGovernance")
251
+
252
+ return response.json().get("workloadSettings", {})
253
+
254
+
255
+ @log
256
+ def suspend_fabric_capacity(
257
+ capacity_name: str,
258
+ azure_subscription_id: str,
259
+ resource_group: str,
260
+ ):
261
+ """
262
+ This function suspends a Fabric capacity.
263
+
264
+ 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>`_.
265
+
266
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
267
+
268
+ Parameters
269
+ ----------
270
+ capacity_name : str
271
+ Name of the Fabric capacity.
272
+ azure_subscription_id : str
273
+ The Azure subscription ID.
274
+ resource_group : str
275
+ The name of the Azure resource group.
276
+ """
277
+
278
+ 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}"
279
+
280
+ _base_api(request=url, client="azure", method="post", status_codes=202)
281
+
282
+ print(f"{icons.green_dot} The '{capacity_name}' capacity has been suspended.")
283
+
284
+
285
+ @log
286
+ def resume_fabric_capacity(
287
+ capacity_name: str,
288
+ azure_subscription_id: str,
289
+ resource_group: str,
290
+ ):
291
+ """
292
+ This function resumes a Fabric capacity.
293
+
294
+ 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>`_.
295
+
296
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
297
+
298
+ Parameters
299
+ ----------
300
+ capacity_name : str
301
+ Name of the Fabric capacity.
302
+ azure_subscription_id : str
303
+ The Azure subscription ID.
304
+ resource_group : str
305
+ The name of the Azure resource group.
306
+ """
307
+
308
+ 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}"
309
+
310
+ _base_api(request=url, client="azure", method="post", status_codes=202)
311
+
312
+ print(f"{icons.green_dot} The '{capacity_name}' capacity has been resumed.")
313
+
314
+
315
+ @log
316
+ def delete_embedded_capacity(
317
+ capacity_name: str,
318
+ azure_subscription_id: str,
319
+ resource_group: str,
320
+ ):
321
+ """
322
+ This function deletes a Power BI Embedded capacity.
323
+
324
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
325
+
326
+ Parameters
327
+ ----------
328
+ capacity_name : str
329
+ Name of the Fabric capacity.
330
+ azure_subscription_id : str
331
+ The Azure subscription ID.
332
+ resource_group : str
333
+ The name of the Azure resource group.
334
+ """
335
+
336
+ 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}"
337
+
338
+ _base_api(request=url, client="azure", method="delete", status_codes=[200, 202])
339
+
340
+ print(f"{icons.green_dot} The '{capacity_name}' capacity has been deleted.")
341
+
342
+
343
+ @log
344
+ def delete_premium_capacity(capacity: str | UUID, **kwargs):
345
+ """
346
+ This function deletes a Power BI Premium capacity.
347
+
348
+ Parameters
349
+ ----------
350
+ capacity : str | uuid.UUID
351
+ Name or ID of the Fabric capacity.
352
+ """
353
+ from sempy_labs._helper_functions import resolve_capacity_id
354
+
355
+ if "capacity_name" in kwargs:
356
+ capacity = kwargs["capacity_name"]
357
+ print(
358
+ f"{icons.warning} The 'capacity_name' parameter is deprecated. Please use 'capacity' instead."
359
+ )
360
+
361
+ capacity_id = resolve_capacity_id(capacity=capacity).upper()
362
+
363
+ _base_api(request=f"capacities/{capacity_id}", method="delete", status_codes=204)
364
+
365
+ print(f"{icons.green_dot} The '{capacity}' capacity has been deleted.")
366
+
367
+
368
+ @log
369
+ def delete_fabric_capacity(
370
+ capacity_name: str,
371
+ azure_subscription_id: str,
372
+ resource_group: str,
373
+ ):
374
+ """
375
+ This function deletes a Fabric capacity.
376
+
377
+ 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>`_.
378
+
379
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
380
+
381
+ Parameters
382
+ ----------
383
+ capacity_name : str
384
+ Name of the Fabric capacity.
385
+ azure_subscription_id : str
386
+ The Azure subscription ID.
387
+ resource_group : str
388
+ The name of the Azure resource group.
389
+ """
390
+
391
+ 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}"
392
+
393
+ _base_api(request=url, client="azure", method="delete", status_codes=202)
394
+
395
+ print(f"{icons.green_dot} The '{capacity_name}' capacity has been deleted.")
396
+
397
+
398
+ @log
399
+ def update_fabric_capacity(
400
+ capacity_name: str,
401
+ azure_subscription_id: str,
402
+ resource_group: str,
403
+ sku: Optional[str] = None,
404
+ admin_members: Optional[str | List[str]] = None,
405
+ tags: Optional[dict] = None,
406
+ ):
407
+ """
408
+ This function updates a Fabric capacity's properties.
409
+
410
+ 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>`_.
411
+
412
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
413
+
414
+ Parameters
415
+ ----------
416
+ capacity_name : str
417
+ Name of the Fabric capacity.
418
+ azure_subscription_id : str
419
+ The Azure subscription ID.
420
+ resource_group : str
421
+ The name of the Azure resource group.
422
+ sku : str, default=None
423
+ The `sku size <https://azure.microsoft.com/pricing/details/microsoft-fabric/>`_ of the Fabric capacity.
424
+ admin_members : str | List[str], default=None
425
+ The email address(es) of the admin(s) of the Fabric capacity.
426
+ tags : dict, default=None
427
+ Tag(s) to add to the capacity. Example: {'tagName': 'tagValue'}.
428
+ """
429
+
430
+ 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}"
431
+
432
+ get_response = _base_api(request=url, client="azure")
433
+
434
+ get_json = get_response.json()
435
+ current_sku = get_json.get("sku", {}).get("name")
436
+ current_admins = (
437
+ get_json.get("properties", {}).get("administration", {}).get("members")
438
+ )
439
+ current_tags = get_json.get("tags")
440
+
441
+ payload = {}
442
+ payload["sku"] = {
443
+ "name": current_sku,
444
+ "tier": "Fabric",
445
+ }
446
+ payload["tags"] = current_tags
447
+ payload["properties"] = get_json["properties"]
448
+
449
+ if sku is not None:
450
+ payload["sku"]["name"] = sku
451
+ if admin_members is not None:
452
+ payload["properties"] = {"administration": {"members": admin_members}}
453
+ if tags is not None:
454
+ payload["tags"] = tags
455
+
456
+ # Do not proceed if no properties are being changed
457
+ if current_sku == sku and current_admins == admin_members and current_tags == tags:
458
+ print(
459
+ f"{icons.yellow_dot} The properties of the '{capacity_name}' are the same as those specified in the parameters of this function. No changes have been made."
460
+ )
461
+ return
462
+
463
+ payload = _add_sll_tag(payload, tags)
464
+ _base_api(
465
+ request=url, client="azure", method="patch", payload=payload, status_codes=202
466
+ )
467
+
468
+ print(
469
+ f"{icons.green_dot} The '{capacity_name}' capacity has been updated accordingly."
470
+ )
471
+
472
+
473
+ @log
474
+ def check_fabric_capacity_name_availablility(
475
+ capacity_name: str,
476
+ azure_subscription_id: str,
477
+ region: str,
478
+ **kwargs,
479
+ ) -> bool:
480
+ """
481
+ This function updates a Fabric capacity's properties.
482
+
483
+ 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>`_.
484
+
485
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
486
+
487
+ Parameters
488
+ ----------
489
+ capacity_name : str
490
+ Name of the Fabric capacity.
491
+ azure_subscription_id : str
492
+ The Azure subscription ID.
493
+ region : str
494
+ The region name.
495
+
496
+ Returns
497
+ -------
498
+ bool
499
+ An indication as to whether the Fabric capacity name is available or not.
500
+ """
501
+
502
+ payload = {"name": capacity_name, "type": "Microsoft.Fabric/capacities"}
503
+
504
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/providers/Microsoft.Fabric/locations/{region}/checkNameAvailability?api-version={icons.azure_api_version}"
505
+
506
+ response = _base_api(
507
+ request=url, client="azure", method="post", payload=payload, status_codes=202
508
+ )
509
+
510
+ return bool(response.json().get("nameAvailable"))
511
+
512
+
513
+ @log
514
+ def create_resource_group(
515
+ azure_subscription_id: str,
516
+ resource_group: str,
517
+ region: str,
518
+ **kwargs,
519
+ ):
520
+ """
521
+ This function creates a resource group in a region within an Azure subscription.
522
+
523
+ 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>`_.
524
+
525
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
526
+
527
+ Parameters
528
+ ----------
529
+ azure_subscription_id : str
530
+ The Azure subscription ID.
531
+ resource_group : str
532
+ The name of the Azure resource group to be created.
533
+ region : str
534
+ The name of the region in which the resource group will be created.
535
+ """
536
+
537
+ if check_resource_group_existence(
538
+ azure_subscription_id=azure_subscription_id,
539
+ resource_group=resource_group,
540
+ ):
541
+ print(
542
+ f"{icons.info} The '{resource_group}' resource group already exists in the '{region}' region within the '{azure_subscription_id}' Azure subscription."
543
+ )
544
+ return
545
+
546
+ create_or_update_resource_group(
547
+ azure_subscription_id=azure_subscription_id,
548
+ resource_group=resource_group,
549
+ region=region,
550
+ )
551
+
552
+
553
+ @log
554
+ def list_skus_for_capacity(
555
+ capacity: str,
556
+ azure_subscription_id: str,
557
+ resource_group: str,
558
+ ) -> pd.DataFrame:
559
+ """
560
+ Lists eligible SKUs for a Microsoft Fabric resource.
561
+
562
+ 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>`_.
563
+
564
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
565
+
566
+ Parameters
567
+ ----------
568
+ capacity : str
569
+ The capacity name.
570
+ azure_subscription_id : str
571
+ The Azure subscription ID.
572
+ resource_group : str
573
+ The name of the resource group.
574
+
575
+ Returns
576
+ -------
577
+ pandas.DataFrame
578
+ A pandas dataframe showing a list of eligible SKUs for a Microsoft Fabric resource.
579
+ """
580
+
581
+ columns = {
582
+ "Resource Type": "string",
583
+ "Sku": "string",
584
+ "Sku Tier": "string",
585
+ }
586
+ df = _create_dataframe(columns=columns)
587
+
588
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Fabric/capacities/{capacity}/skus?api-version=2023-11-01"
589
+ response = _base_api(request=url, client="azure")
590
+
591
+ rows = []
592
+ for v in response.json().get("value", []):
593
+ sku = v.get("sku", {})
594
+ rows.append(
595
+ {
596
+ "Resource Type": v.get("resourceType"),
597
+ "Sku": sku.get("name"),
598
+ "Sku Tier": sku.get("tier"),
599
+ }
600
+ )
601
+
602
+ if rows:
603
+ df = pd.DataFrame(rows, columns=columns.keys())
604
+
605
+ return df
606
+
607
+
608
+ @log
609
+ def list_skus(
610
+ azure_subscription_id: str,
611
+ ) -> pd.DataFrame:
612
+ """
613
+ Lists eligible SKUs for Microsoft Fabric resource provider.
614
+
615
+ 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>`_.
616
+
617
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
618
+
619
+ Parameters
620
+ ----------
621
+ azure_subscription_id : str
622
+ The Azure subscription ID.
623
+
624
+ Returns
625
+ -------
626
+ pandas.DataFrame
627
+ A pandas dataframe showing a list of eligible SKUs for Microsoft Fabric resource provider.
628
+ """
629
+
630
+ columns = {
631
+ "Sku": "string",
632
+ "Locations": "str",
633
+ }
634
+ df = _create_dataframe(columns=columns)
635
+
636
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/providers/Microsoft.Fabric/skus?api-version=2023-11-01"
637
+ response = _base_api(request=url, client="azure")
638
+
639
+ rows = []
640
+ for v in response.json().get("value", []):
641
+ rows.append(
642
+ {
643
+ "Sku": v.get("name"),
644
+ "Locations": v.get("locations", []),
645
+ }
646
+ )
647
+
648
+ if rows:
649
+ df = pd.DataFrame(rows, columns=columns.keys())
650
+
651
+ return df
652
+
653
+
654
+ @log
655
+ def list_subscriptions() -> pd.DataFrame:
656
+ """
657
+ Gets all subscriptions for a tenant.
658
+
659
+ 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>`_.
660
+
661
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
662
+
663
+ Returns
664
+ -------
665
+ pandas.DataFrame
666
+ A pandas dataframe showing a list of all subscriptions for a tenant.
667
+ """
668
+
669
+ columns = {
670
+ "Subscription Id": "string",
671
+ "Subscription Name": "string",
672
+ "Tenant Id": "string",
673
+ "State": "string",
674
+ "Location Placement Id": "string",
675
+ "Quota Id": "string",
676
+ "Spending Limit": "string",
677
+ "Authorization Source": "string",
678
+ "Managed by Tenants": "string",
679
+ "Tags": "string",
680
+ }
681
+ df = _create_dataframe(columns=columns)
682
+
683
+ url = "https://management.azure.com/subscriptions?api-version=2022-12-01"
684
+ response = _base_api(request=url, client="azure")
685
+
686
+ rows = []
687
+ for v in response.json().get("value", []):
688
+ policy = v.get("subscriptionPolicies", {})
689
+ tenants = v.get("managedByTenants")
690
+ rows.append(
691
+ {
692
+ "Subscription Id": v.get("subscriptionId"),
693
+ "Subscription Name": v.get("displayName"),
694
+ "Tenant Id": v.get("tenantId"),
695
+ "State": v.get("state"),
696
+ "Location Placement Id": policy.get("locationPlacementId"),
697
+ "Quota Id": policy.get("quotaId"),
698
+ "Spending Limit": policy.get("spendingLimit"),
699
+ "Authorization Source": v.get("authorizationSource"),
700
+ "Managed by Tenants": tenants if tenants is not None else [],
701
+ "Tags": v.get("tags", {}),
702
+ }
703
+ )
704
+
705
+ if rows:
706
+ df = pd.DataFrame(rows, columns=columns.keys())
707
+
708
+ return df
709
+
710
+
711
+ @log
712
+ def get_subscription(azure_subscription_id: str) -> pd.DataFrame:
713
+ """
714
+ Gets details about a specified subscription.
715
+
716
+ 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>`_.
717
+
718
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
719
+
720
+ Parameters
721
+ ----------
722
+ azure_subscription_id : str
723
+ The Azure subscription ID.
724
+
725
+ Returns
726
+ -------
727
+ pandas.DataFrame
728
+ A pandas dataframe showing details of a specific subscription.
729
+ """
730
+
731
+ columns = {
732
+ "Subscription Id": "string",
733
+ "Subscription Name": "string",
734
+ "Tenant Id": "string",
735
+ "State": "string",
736
+ "Location Placement Id": "string",
737
+ "Quota Id": "string",
738
+ "Spending Limit": "string",
739
+ "Authorization Source": "string",
740
+ "Managed by Tenants": "string",
741
+ "Tags": "string",
742
+ }
743
+ df = _create_dataframe(columns=columns)
744
+
745
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}?api-version=2022-12-01"
746
+
747
+ response = _base_api(request=url, client="azure")
748
+ v = response.json()
749
+ policy = v.get("subscriptionPolicies", {})
750
+ tenants = v.get("managedByTenants")
751
+ new_data = {
752
+ "Subscription Id": v.get("subscriptionId"),
753
+ "Subscription Name": v.get("displayName"),
754
+ "Tenant Id": v.get("tenantId"),
755
+ "State": v.get("state"),
756
+ "Location Placement Id": policy.get("locationPlacementId"),
757
+ "Quota Id": policy.get("quotaId"),
758
+ "Spending Limit": policy.get("spendingLimit"),
759
+ "Authorization Source": v.get("authorizationSource"),
760
+ "Managed by Tenants": tenants if tenants is not None else [],
761
+ "Tags": v.get("tags", {}),
762
+ }
763
+
764
+ df = pd.DataFrame([new_data], columns=columns.keys())
765
+
766
+ return df
767
+
768
+
769
+ def _resolve_subscription_name_and_id(
770
+ azure_subscription: str | UUID,
771
+ ) -> Tuple[str, UUID]:
772
+
773
+ if _is_valid_uuid(azure_subscription):
774
+ subscription_id = azure_subscription
775
+ df = get_subscription(azure_subscription_id=subscription_id)
776
+ if df.empty:
777
+ raise ValueError(f"{icons.red_dot} The subscription ID does not exist.")
778
+ subscription_name = df["Subscription Name"].iloc[0]
779
+ else:
780
+ subscription_name = azure_subscription
781
+ df = list_subscriptions()
782
+ df_filt = df[df["Subscription Name"] == subscription_name]
783
+ if df_filt.empty:
784
+ raise ValueError(f"{icons.red_dot} The subscription name does not exist.")
785
+ subscription_id = df_filt["Subscription Id"].iloc[0]
786
+
787
+ return subscription_name, subscription_id
788
+
789
+
790
+ @log
791
+ def list_tenants() -> pd.DataFrame:
792
+ """
793
+ Gets the tenants for your account.
794
+
795
+ 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>`_.
796
+
797
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
798
+
799
+ Returns
800
+ -------
801
+ pandas.DataFrame
802
+ A pandas dataframe showing a list of all tenants for your account.
803
+ """
804
+
805
+ columns = {
806
+ "Tenant Id": "string",
807
+ "Tenant Name": "string",
808
+ "Country Code": "string",
809
+ "Domains": "string",
810
+ "Tenant Category": "string",
811
+ "Default Domain": "string",
812
+ "Tenant Type": "string",
813
+ "Tenant Branding Logo Url": "string",
814
+ }
815
+ df = _create_dataframe(columns=columns)
816
+
817
+ url = "https://management.azure.com/tenants?api-version=2022-12-01"
818
+
819
+ response = _base_api(request=url, client="azure")
820
+
821
+ rows = []
822
+ for v in response.json().get("value", []):
823
+ d = v.get("domains")
824
+ rows.append(
825
+ {
826
+ "Tenant Id": v.get("tenantId"),
827
+ "Tenant Name": v.get("displayName"),
828
+ "Country Code": v.get("countryCode"),
829
+ "Domains": d if d is not None else "",
830
+ "Tenant Category": v.get("tenantCategory"),
831
+ "Default Domain": v.get("defaultDomain"),
832
+ "Tenant Type": v.get("tenantType"),
833
+ "Tenant Branding Logo Url": v.get("tenantBrandingLogoUrl"),
834
+ }
835
+ )
836
+
837
+ if rows:
838
+ df = pd.DataFrame(rows, columns=columns.keys())
839
+
840
+ return df
841
+
842
+
843
+ @log
844
+ def create_or_update_resource_group(
845
+ azure_subscription_id: str,
846
+ resource_group: str,
847
+ region: str,
848
+ ):
849
+ """
850
+ Creates or updates a resource group.
851
+
852
+ 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>`_.
853
+
854
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
855
+
856
+ Parameters
857
+ ----------
858
+ azure_subscription_id : str
859
+ The Azure subscription Id.
860
+ resource_group : str
861
+ The name of the resource group.
862
+ region : str
863
+ The name of the region.
864
+ """
865
+
866
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourcegroups/{resource_group}?api-version=2021-04-01"
867
+
868
+ payload = {
869
+ "location": region,
870
+ }
871
+
872
+ _base_api(
873
+ request=url,
874
+ client="azure",
875
+ method="put",
876
+ payload=payload,
877
+ status_codes=[200, 201],
878
+ )
879
+
880
+ print(
881
+ f"{icons.green_dot} The '{resource_group}' resource group has been created/updated."
882
+ )
883
+
884
+
885
+ @log
886
+ def create_storage_account(
887
+ azure_subscription_id: str,
888
+ resource_group: str,
889
+ storage_account: str,
890
+ region: str,
891
+ ):
892
+ """
893
+ 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.
894
+
895
+ This is a wrapper function for the following API: `Storage Accounts - Create <https://learn.microsoft.com/rest/api/storagerp/storage-accounts/create>`_.
896
+
897
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
898
+
899
+ Parameters
900
+ ----------
901
+ azure_subscription_id : str
902
+ The Azure subscription Id.
903
+ resource_group : str
904
+ The name of the resource group.
905
+ storage_account : str
906
+ The name of the storage account to be created.
907
+ region : str
908
+ The name of the region.
909
+ """
910
+
911
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Storage/storageAccounts/{storage_account}?api-version=2018-02-01"
912
+
913
+ payload = {
914
+ "sku": {"name": "Standard_GRS"},
915
+ "kind": "StorageV2",
916
+ "location": region,
917
+ }
918
+
919
+ _base_api(request=url, client="azure", method="put", payload=payload)
920
+
921
+ print(
922
+ f"{icons.green_dot} The '{storage_account}' storage account has been created."
923
+ )
924
+
925
+
926
+ @log
927
+ def list_storage_accounts(
928
+ azure_subscription_id: str,
929
+ resource_group: Optional[str] = None,
930
+ ) -> pd.DataFrame:
931
+ """
932
+ 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.
933
+
934
+ 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>`_.
935
+
936
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
937
+
938
+ Parameters
939
+ ----------
940
+ azure_subscription_id : str
941
+ The Azure subscription Id.
942
+ resource_group : str, default=None
943
+ If set to None, retrieves all storage accounts for the subscription. If not None, shows the storage accounts within that resource group.
944
+
945
+ Returns
946
+ -------
947
+ pandas.DataFrame
948
+ A pandas dataframe showing a list of all storage accounts within the subscription (or resource group).
949
+ """
950
+
951
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}"
952
+
953
+ if resource_group is not None:
954
+ url += f"/resourceGroups/{resource_group}"
955
+
956
+ url += "/providers/Microsoft.Storage/storageAccounts?api-version=2023-05-01"
957
+
958
+ columns = {
959
+ "Storage Account Id": "string",
960
+ "Storage Account Name": "string",
961
+ "Kind": "string",
962
+ "Location": "string",
963
+ "Sku Name": "string",
964
+ "Sku Tier": "string",
965
+ "Is HNS Enabled": "bool",
966
+ "Creation Time": "datetime",
967
+ "Web Endpoint": "string",
968
+ "DFS Endpoint": "string",
969
+ "Blob Endpoint": "string",
970
+ "File Endpoint": "string",
971
+ "Queue Endpoint": "string",
972
+ "Table Endpoint": "string",
973
+ "Primary Location": "string",
974
+ "Provisioning State": "string",
975
+ "Secondary Location": "string",
976
+ "Status of Primary": "string",
977
+ "Status of Secondary": "string",
978
+ "Supports HTTPS Traffic Only": "bool",
979
+ "Tags": "string",
980
+ }
981
+ df = _create_dataframe(columns=columns)
982
+
983
+ response = _base_api(request=url, client="azure")
984
+
985
+ rows = []
986
+ for v in response.json().get("value", []):
987
+ p = v.get("properties", {})
988
+ rows.append(
989
+ {
990
+ "Storage Account Id": v.get("id"),
991
+ "Storage Account Name": v.get("name"),
992
+ "Kind": v.get("kind"),
993
+ "Location": v.get("location"),
994
+ "Sku Name": v.get("sku", {}).get("name"),
995
+ "Sku Tier": v.get("sku", {}).get("tier"),
996
+ "Is HNS Enabled": p.get("isHnsEnabled"),
997
+ "Creation Time": p.get("creationTime"),
998
+ "Web Endpoint": p.get("primaryEndpoints", {}).get("web"),
999
+ "DFS Endpoint": p.get("primaryEndpoints", {}).get("dfs"),
1000
+ "Blob Endpoint": p.get("primaryEndpoints", {}).get("blob"),
1001
+ "File Endpoint": p.get("primaryEndpoints", {}).get("file"),
1002
+ "Queue Endpoint": p.get("primaryEndpoints", {}).get("queue"),
1003
+ "Table Endpoint": p.get("primaryEndpoints", {}).get("table"),
1004
+ "Primary Location": p.get("primaryLocation"),
1005
+ "Provisioning State": p.get("provisioningState"),
1006
+ "Secondary Location": p.get("secondaryLocation"),
1007
+ "Status of Primary": p.get("statusOfPrimary"),
1008
+ "Status of Secondary": p.get("statusOfSecondary"),
1009
+ "Supports HTTPS Traffic Only": p.get("supportsHttpsTrafficOnly"),
1010
+ "Tags": v.get("tags"),
1011
+ }
1012
+ )
1013
+
1014
+ if rows:
1015
+ df = pd.DataFrame(rows, columns=columns.keys())
1016
+ _update_dataframe_datatypes(dataframe=df, column_map=columns)
1017
+
1018
+ return df
1019
+
1020
+
1021
+ @log
1022
+ def check_resource_group_existence(
1023
+ azure_subscription_id: str, resource_group: str
1024
+ ) -> bool:
1025
+ """
1026
+ Checks whether a resource group exists.
1027
+
1028
+ This is a wrapper function for the following API: `Resource Groups - Check Existence <https://learn.microsoft.com/rest/api/resources/resource-groups/check-existence>`_.
1029
+
1030
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
1031
+
1032
+ Parameters
1033
+ ----------
1034
+ azure_subscription_id : str
1035
+ The Azure subscription Id.
1036
+ resource_group : str
1037
+ The name of the resource group.
1038
+
1039
+ Returns
1040
+ -------
1041
+ bool
1042
+ True/False indicating if the resource group exists or not.
1043
+ """
1044
+
1045
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}?api-version=2021-04-01"
1046
+
1047
+ response = _base_api(request=url, client="azure", status_codes=[200, 204, 404])
1048
+
1049
+ if response.status_code == 200:
1050
+ return True
1051
+ elif response.status_code in [204, 404]:
1052
+ return False
1053
+
1054
+
1055
+ @log
1056
+ def list_resource_groups(
1057
+ azure_subscription_id: str,
1058
+ filter: Optional[str] = None,
1059
+ top: Optional[int] = None,
1060
+ ) -> pd.DataFrame:
1061
+ """
1062
+ Lists all resource groups within a subscription.
1063
+
1064
+ This is a wrapper function for the following API: `Resource Groups - List <https://learn.microsoft.com/rest/api/resources/resource-groups/list>`_.
1065
+
1066
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
1067
+
1068
+ Parameters
1069
+ ----------
1070
+ azure_subscription_id : str
1071
+ The Azure subscription Id.
1072
+ filter : str, default=None
1073
+ The filter to apply to the operation. Example: filter="tagname eq 'tagvalue'".
1074
+ top : int, default=None
1075
+ The number of results to return. If not specified, returns all results.
1076
+
1077
+ Returns
1078
+ -------
1079
+ pandas.DataFrame
1080
+ A pandas dataframe showing a list of all resource groups within the subscription.
1081
+ """
1082
+
1083
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups?"
1084
+
1085
+ if filter is not None:
1086
+ url += f"$filter={filter}&"
1087
+ if top is not None:
1088
+ url += f"$top={top}&"
1089
+
1090
+ url += "api-version=2021-04-01"
1091
+
1092
+ columns = {
1093
+ "Resource Group Name": "string",
1094
+ "Location": "string",
1095
+ "Tags": "string",
1096
+ }
1097
+ df = _create_dataframe(columns=columns)
1098
+
1099
+ response = _base_api(request=url, client="azure")
1100
+
1101
+ rows = []
1102
+ for v in response.json().get("value", []):
1103
+ rows.append(
1104
+ {
1105
+ "Resource Group Id": v.get("id"),
1106
+ "Resource Group Name": v.get("name"),
1107
+ "Location": v.get("location"),
1108
+ "Managed By": v.get("managedBy"),
1109
+ "Tags": v.get("tags"),
1110
+ "Type": v.get("type"),
1111
+ "Provisioning State": v.get("properties", {}).get("provisioningState"),
1112
+ }
1113
+ )
1114
+
1115
+ if rows:
1116
+ df = pd.DataFrame(rows, columns=columns.keys())
1117
+
1118
+ return df
1119
+
1120
+
1121
+ @log
1122
+ def get_resource_group(azure_subscription_id: str, resource_group: str) -> pd.DataFrame:
1123
+ """
1124
+ Gets details about a specified resource group.
1125
+
1126
+ This is a wrapper function for the following API: `Resource Groups - Get <https://learn.microsoft.com/rest/api/resources/resource-groups/get>`_.
1127
+
1128
+ Service Principal Authentication is required (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
1129
+
1130
+ Parameters
1131
+ ----------
1132
+ azure_subscription_id : str
1133
+ The Azure subscription Id.
1134
+ resource_group : str
1135
+ The name of the resource group.
1136
+
1137
+ Returns
1138
+ -------
1139
+ pandas.DataFrame
1140
+ A pandas dataframe showing details of a specific resource group.
1141
+ """
1142
+
1143
+ url = f"https://management.azure.com/subscriptions/{azure_subscription_id}/resourceGroups/{resource_group}?api-version=2021-04-01"
1144
+ response = _base_api(request=url, client="azure")
1145
+
1146
+ v = response.json()
1147
+ new_data = {
1148
+ "Resource Group Id": v.get("id"),
1149
+ "Resource Group Name": v.get("name"),
1150
+ "Location": v.get("location"),
1151
+ "Managed By": v.get("managedBy"),
1152
+ "Tags": v.get("tags"),
1153
+ "Type": v.get("type"),
1154
+ "Provisioning State": v.get("properties", {}).get("provisioningState"),
1155
+ }
1156
+
1157
+ return pd.DataFrame(new_data, index=[0])
1158
+
1159
+
1160
+ def list_capacities() -> pd.DataFrame:
1161
+ """
1162
+ Shows the capacities and their properties.
1163
+
1164
+ Returns
1165
+ -------
1166
+ pandas.DataFrame
1167
+ A pandas dataframe showing the capacities and their properties
1168
+ """
1169
+
1170
+ columns = {
1171
+ "Id": "string",
1172
+ "Display Name": "string",
1173
+ "Sku": "string",
1174
+ "Region": "string",
1175
+ "State": "string",
1176
+ "Admins": "string",
1177
+ }
1178
+ df = _create_dataframe(columns=columns)
1179
+
1180
+ response = _base_api(request="/v1.0/myorg/capacities", client="fabric_sp")
1181
+
1182
+ rows = []
1183
+ for i in response.json().get("value", []):
1184
+ rows.append(
1185
+ {
1186
+ "Id": i.get("id").lower(),
1187
+ "Display Name": i.get("displayName"),
1188
+ "Sku": i.get("sku"),
1189
+ "Region": i.get("region"),
1190
+ "State": i.get("state"),
1191
+ "Admins": [i.get("admins", [])],
1192
+ }
1193
+ )
1194
+
1195
+ if rows:
1196
+ df = pd.DataFrame(rows, columns=columns.keys())
1197
+
1198
+ return df