msfabricpysdkcore 0.0.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.
- msfabricpysdkcore/__init__.py +1 -0
- msfabricpysdkcore/auth.py +61 -0
- msfabricpysdkcore/client.py +283 -0
- msfabricpysdkcore/item.py +246 -0
- msfabricpysdkcore/job_instance.py +66 -0
- msfabricpysdkcore/long_running_operation.py +81 -0
- msfabricpysdkcore/onelakeshortcut.py +55 -0
- msfabricpysdkcore/workspace.py +481 -0
- msfabricpysdkcore-0.0.1.dist-info/LICENSE +21 -0
- msfabricpysdkcore-0.0.1.dist-info/METADATA +365 -0
- msfabricpysdkcore-0.0.1.dist-info/RECORD +13 -0
- msfabricpysdkcore-0.0.1.dist-info/WHEEL +5 -0
- msfabricpysdkcore-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1 @@
|
|
1
|
+
from .client import FabricClientCore
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import requests
|
2
|
+
from abc import abstractmethod
|
3
|
+
from azure.identity import AzureCliCredential
|
4
|
+
|
5
|
+
class FabricAuth():
|
6
|
+
"""FabricAuth class to interact with Entra ID"""
|
7
|
+
|
8
|
+
@abstractmethod
|
9
|
+
def get_token(self):
|
10
|
+
"""Get token from Azure AD"""
|
11
|
+
pass
|
12
|
+
|
13
|
+
def get_headers(self):
|
14
|
+
"""Get headers for API requests"""
|
15
|
+
access_token = self.get_token()
|
16
|
+
headers = {
|
17
|
+
'Authorization': 'Bearer ' + access_token,
|
18
|
+
'Content-Type': 'application/json'
|
19
|
+
}
|
20
|
+
return headers
|
21
|
+
|
22
|
+
|
23
|
+
class FabricAuthClient(FabricAuth):
|
24
|
+
"""FabricAuthClient class to interact with Entra ID"""
|
25
|
+
|
26
|
+
def __init__(self):
|
27
|
+
print("Using Azure CLI for authentication")
|
28
|
+
self.auth = AzureCliCredential()
|
29
|
+
|
30
|
+
def get_token(self):
|
31
|
+
"""Get token from Azure AD"""
|
32
|
+
token = self.auth.get_token("https://api.fabric.microsoft.com/.default")
|
33
|
+
return token.token
|
34
|
+
|
35
|
+
class FabricServicePrincipal(FabricAuth):
|
36
|
+
"""FabricServicePrincipal class to interact with Entra ID"""
|
37
|
+
|
38
|
+
def __init__(self, tenant_id, client_id, client_secret):
|
39
|
+
print("Using Service Principal for authentication")
|
40
|
+
|
41
|
+
self.tenant_id = tenant_id
|
42
|
+
self.client_id = client_id
|
43
|
+
self.client_secret = client_secret
|
44
|
+
|
45
|
+
self.scope = "https://api.fabric.microsoft.com/.default"
|
46
|
+
|
47
|
+
|
48
|
+
def get_token(self):
|
49
|
+
"""Get token from Azure AD"""
|
50
|
+
# Get token from Azure AD
|
51
|
+
url = f"https://login.microsoftonline.com/{self.tenant_id}/oauth2/v2.0/token"
|
52
|
+
payload = {
|
53
|
+
'grant_type': 'client_credentials',
|
54
|
+
'client_id': f'{self.client_id}',
|
55
|
+
'client_secret': f'{self.client_secret}',
|
56
|
+
'scope': self.scope
|
57
|
+
}
|
58
|
+
response = requests.post(url, data=payload)
|
59
|
+
access_token = response.json().get('access_token')
|
60
|
+
return access_token
|
61
|
+
|
@@ -0,0 +1,283 @@
|
|
1
|
+
import requests
|
2
|
+
import json
|
3
|
+
import os
|
4
|
+
from time import sleep
|
5
|
+
|
6
|
+
from msfabricpysdkcore.workspace import Workspace
|
7
|
+
from msfabricpysdkcore.auth import FabricAuthClient, FabricServicePrincipal
|
8
|
+
|
9
|
+
class FabricClientCore():
|
10
|
+
"""FabricClientCore class to interact with Fabric API"""
|
11
|
+
|
12
|
+
def __init__(self, tenant_id = None, client_id = None, client_secret = None) -> None:
|
13
|
+
"""Initialize FabricClientCore object"""
|
14
|
+
self.tenant_id = tenant_id if tenant_id else os.getenv("FABRIC_TENANT_ID")
|
15
|
+
self.client_id = client_id if client_id else os.getenv("FABRIC_CLIENT_ID")
|
16
|
+
self.client_secret = client_secret if client_secret else os.getenv("FABRIC_CLIENT_SECRET")
|
17
|
+
|
18
|
+
if self.client_id is None or self.client_secret is None or self.tenant_id is None:
|
19
|
+
self.auth = FabricAuthClient()
|
20
|
+
else:
|
21
|
+
self.auth = FabricServicePrincipal(tenant_id = self.tenant_id,
|
22
|
+
client_id = self.client_id,
|
23
|
+
client_secret = self.client_secret)
|
24
|
+
|
25
|
+
self.scope = "https://api.fabric.microsoft.com/.default"
|
26
|
+
|
27
|
+
|
28
|
+
def list_workspaces(self):
|
29
|
+
"""List all workspaces in the tenant"""
|
30
|
+
|
31
|
+
url = "https://api.fabric.microsoft.com/v1/workspaces"
|
32
|
+
|
33
|
+
for _ in range(10):
|
34
|
+
response = requests.get(url=url, headers=self.auth.get_headers())
|
35
|
+
if response.status_code == 429:
|
36
|
+
print("Too many requests, waiting 10 seconds")
|
37
|
+
sleep(10)
|
38
|
+
continue
|
39
|
+
if response.status_code not in (200, 429):
|
40
|
+
print(response.status_code)
|
41
|
+
print(response.text)
|
42
|
+
items = json.loads(response.text)["value"]
|
43
|
+
break
|
44
|
+
|
45
|
+
ws_list = []
|
46
|
+
for i in items:
|
47
|
+
ws = Workspace.from_dict(i, auth=self.auth)
|
48
|
+
ws_list.append(ws)
|
49
|
+
return ws_list
|
50
|
+
|
51
|
+
def get_workspace_by_name(self, name):
|
52
|
+
"""Get workspace by name"""
|
53
|
+
ws_list = self.list_workspaces()
|
54
|
+
for ws in ws_list:
|
55
|
+
if ws.display_name == name:
|
56
|
+
return ws
|
57
|
+
|
58
|
+
def get_workspace_by_id(self, id):
|
59
|
+
"""Get workspace by id"""
|
60
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{id}"
|
61
|
+
|
62
|
+
|
63
|
+
for _ in range(10):
|
64
|
+
response = requests.get(url=url, headers=self.auth.get_headers())
|
65
|
+
if response.status_code == 429:
|
66
|
+
print("Too many requests, waiting 10 seconds")
|
67
|
+
sleep(10)
|
68
|
+
continue
|
69
|
+
if response.status_code not in (200, 429):
|
70
|
+
print(response.status_code)
|
71
|
+
print(response.text)
|
72
|
+
ws_dict = json.loads(response.text)
|
73
|
+
if "id" not in ws_dict:
|
74
|
+
raise Exception(f"Error getting workspace: {response.status_code} {response.text}")
|
75
|
+
ws = Workspace.from_dict(json.loads(response.text), auth=self.auth)
|
76
|
+
|
77
|
+
return ws
|
78
|
+
|
79
|
+
|
80
|
+
def get_workspace(self, id = None, name = None):
|
81
|
+
"""Get workspace by id or name"""
|
82
|
+
if id:
|
83
|
+
return self.get_workspace_by_id(id)
|
84
|
+
if name:
|
85
|
+
return self.get_workspace_by_name(name)
|
86
|
+
raise ValueError("Either id or name must be provided")
|
87
|
+
|
88
|
+
def get_workspace_role_assignments(self, workspace_id):
|
89
|
+
"""Get role assignments for a workspace"""
|
90
|
+
ws = self.get_workspace_by_id(workspace_id)
|
91
|
+
return ws.get_role_assignments()
|
92
|
+
|
93
|
+
def create_workspace(self, display_name, capacity_id = None, description = None, exists_ok = True):
|
94
|
+
"""Create a workspace"""
|
95
|
+
body = dict()
|
96
|
+
body["displayName"] = display_name
|
97
|
+
if capacity_id:
|
98
|
+
body["capacityId"] = capacity_id
|
99
|
+
if description:
|
100
|
+
body["description"] = description
|
101
|
+
|
102
|
+
url = "https://api.fabric.microsoft.com/v1/workspaces"
|
103
|
+
|
104
|
+
for _ in range(10):
|
105
|
+
response = requests.post(url=url, headers=self.auth.get_headers(), json=body)
|
106
|
+
if response.status_code == 429:
|
107
|
+
print("Too many requests, waiting 10 seconds")
|
108
|
+
sleep(10)
|
109
|
+
continue
|
110
|
+
ws_dict = json.loads(response.text)
|
111
|
+
if response.status_code not in (201, 429):
|
112
|
+
if "errorCode" in ws_dict and ws_dict["errorCode"] == "WorkspaceNameAlreadyExists" and exists_ok:
|
113
|
+
return self.get_workspace_by_name(display_name)
|
114
|
+
else:
|
115
|
+
print(response.status_code)
|
116
|
+
print(response.text)
|
117
|
+
raise Exception(f"Error creating workspace: {response.text}")
|
118
|
+
break
|
119
|
+
|
120
|
+
ws = Workspace.from_dict(ws_dict, auth=self.auth)
|
121
|
+
return ws
|
122
|
+
|
123
|
+
def delete_workspace(self, workspace_id = None, display_name = None):
|
124
|
+
"""Delete a workspace"""
|
125
|
+
if workspace_id is None and display_name is None:
|
126
|
+
raise ValueError("Either workspace_id or display_name must be provided")
|
127
|
+
ws = self.get_workspace(id = workspace_id, name = display_name)
|
128
|
+
reponse = ws.delete()
|
129
|
+
return reponse
|
130
|
+
|
131
|
+
def add_workspace_role_assignment(self, workspace_id, role, principal):
|
132
|
+
"""Add a role assignment to a workspace"""
|
133
|
+
ws = self.get_workspace_by_id(workspace_id)
|
134
|
+
return ws.add_role_assignment(role, principal)
|
135
|
+
|
136
|
+
def delete_workspace_role_assignment(self, workspace_id, principal_id):
|
137
|
+
"""Delete a role assignment from a workspace"""
|
138
|
+
ws = self.get_workspace_by_id(workspace_id)
|
139
|
+
return ws.delete_role_assignment(principal_id)
|
140
|
+
|
141
|
+
def update_workspace(self, workspace_id, display_name = None, description = None):
|
142
|
+
"""Update a workspace"""
|
143
|
+
ws = self.get_workspace_by_id(workspace_id)
|
144
|
+
return ws.update(display_name, description)
|
145
|
+
|
146
|
+
def update_workspace_role_assignment(self, workspace_id, role, principal_id):
|
147
|
+
"""Update a role assignment for a workspace"""
|
148
|
+
ws = self.get_workspace_by_id(workspace_id)
|
149
|
+
return ws.update_role_assignment(role, principal_id)
|
150
|
+
|
151
|
+
def assign_to_capacity(self, workspace_id, capacity_id):
|
152
|
+
"""Assign a workspace to a capacity"""
|
153
|
+
ws = self.get_workspace_by_id(workspace_id)
|
154
|
+
return ws.assign_to_capacity(capacity_id)
|
155
|
+
|
156
|
+
def unassign_from_capacity(self, workspace_id):
|
157
|
+
"""Unassign a workspace from a capacity"""
|
158
|
+
ws = self.get_workspace_by_id(workspace_id)
|
159
|
+
return ws.unassign_from_capacity()
|
160
|
+
|
161
|
+
def list_capacities(self):
|
162
|
+
"""List all capacities in the tenant"""
|
163
|
+
url = "https://api.fabric.microsoft.com/v1/capacities"
|
164
|
+
|
165
|
+
for _ in range(10):
|
166
|
+
response = requests.get(url=url, headers=self.auth.get_headers())
|
167
|
+
if response.status_code == 429:
|
168
|
+
print("Too many requests, waiting 10 seconds")
|
169
|
+
sleep(10)
|
170
|
+
continue
|
171
|
+
if response.status_code not in (200, 429):
|
172
|
+
print(response.status_code)
|
173
|
+
print(response.text)
|
174
|
+
raise Exception(f"Error listing capacities: {response.text}")
|
175
|
+
break
|
176
|
+
|
177
|
+
items = json.loads(response.text)["value"]
|
178
|
+
|
179
|
+
return items
|
180
|
+
|
181
|
+
def create_item(self, workspace_id, display_name, type, definition = None, description = None):
|
182
|
+
"""Create an item in a workspace"""
|
183
|
+
ws = self.get_workspace_by_id(workspace_id)
|
184
|
+
|
185
|
+
return ws.create_item(display_name = display_name,
|
186
|
+
type = type,
|
187
|
+
definition = definition,
|
188
|
+
description = description)
|
189
|
+
|
190
|
+
def get_item(self, workspace_id, item_id):
|
191
|
+
"""Get an item from a workspace"""
|
192
|
+
ws = self.get_workspace_by_id(workspace_id)
|
193
|
+
return ws.get_item(item_id)
|
194
|
+
|
195
|
+
def delete_item(self, workspace_id, item_id):
|
196
|
+
"""Delete an item from a workspace"""
|
197
|
+
ws = self.get_workspace_by_id(workspace_id)
|
198
|
+
return ws.delete_item(item_id)
|
199
|
+
|
200
|
+
def list_items(self, workspace_id):
|
201
|
+
"""List items in a workspace"""
|
202
|
+
ws = self.get_workspace_by_id(workspace_id)
|
203
|
+
return ws.list_items()
|
204
|
+
|
205
|
+
def get_item_definition(self, workspace_id, item_id):
|
206
|
+
"""Get the definition of an item"""
|
207
|
+
ws = self.get_workspace_by_id(workspace_id)
|
208
|
+
return ws.get_item_definition(item_id)
|
209
|
+
|
210
|
+
def update_item(self, workspace_id, item_id, display_name = None, description = None):
|
211
|
+
"""Update an item in a workspace"""
|
212
|
+
ws = self.get_workspace_by_id(workspace_id)
|
213
|
+
return ws.get_item(item_id).update(display_name, description)
|
214
|
+
|
215
|
+
def update_item_definition(self, workspace_id, item_id, definition):
|
216
|
+
"""Update the definition of an item"""
|
217
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
218
|
+
return ws.get_item(item_id=item_id).update_definition(definition=definition)
|
219
|
+
|
220
|
+
def create_shortcut(self, workspace_id, item_id, path, name, target):
|
221
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
222
|
+
return ws.get_item(item_id=item_id).create_shortcut(path=path, name=name, target=target)
|
223
|
+
|
224
|
+
def get_shortcut(self, workspace_id, item_id, path, name):
|
225
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
226
|
+
return ws.get_item(item_id=item_id).get_shortcut(path=path, name=name)
|
227
|
+
|
228
|
+
def delete_shortcut(self, workspace_id, item_id, path, name):
|
229
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
230
|
+
return ws.get_item(item_id=item_id).delete_shortcut(path=path, name=name)
|
231
|
+
|
232
|
+
def get_item_job_instance(self, workspace_id, item_id, job_instance_id):
|
233
|
+
"""Get a job instance for an item"""
|
234
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
235
|
+
return ws.get_item(item_id=item_id).get_item_job_instance(job_instance_id=job_instance_id)
|
236
|
+
|
237
|
+
def run_on_demand_item_job(self, workspace_id, item_id, job_type, execution_data = None):
|
238
|
+
"""Run an on demand job for an item"""
|
239
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
240
|
+
return ws.get_item(item_id=item_id).run_on_demand_item_job(job_type=job_type, execution_data=execution_data)
|
241
|
+
|
242
|
+
def cancel_item_job_instance(self, workspace_id, item_id, job_instance_id):
|
243
|
+
"""Cancel a job instance for an item"""
|
244
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
245
|
+
return ws.get_item(item_id=item_id).get_item_job_instance(job_instance_id=job_instance_id).cancel()
|
246
|
+
|
247
|
+
def commit_to_git(self, workspace_id,mode, comment=None, items=None, workspace_head=None):
|
248
|
+
"""Commit changes to git"""
|
249
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
250
|
+
return ws.commit_to_git(mode=mode, comment=comment, items=items, workspace_head=workspace_head)
|
251
|
+
|
252
|
+
def git_connect(self, workspace_id, git_provider_details):
|
253
|
+
"""Connect to git"""
|
254
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
255
|
+
return ws.git_connect(git_provider_details=git_provider_details)
|
256
|
+
|
257
|
+
def git_disconnect(self, workspace_id):
|
258
|
+
"""Disconnect from git"""
|
259
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
260
|
+
return ws.git_disconnect()
|
261
|
+
|
262
|
+
def git_get_connection(self, workspace_id):
|
263
|
+
"""Get git connection details"""
|
264
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
265
|
+
return ws.git_get_connection()
|
266
|
+
|
267
|
+
def git_get_status(self, workspace_id):
|
268
|
+
"""Get git status"""
|
269
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
270
|
+
return ws.git_get_status()
|
271
|
+
|
272
|
+
def git_initialize_connection(self, workspace_id, initialization_strategy):
|
273
|
+
"""Initialize git"""
|
274
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
275
|
+
return ws.git_initialize_connection(initialization_strategy=initialization_strategy)
|
276
|
+
|
277
|
+
def update_from_git(self, workspace_id, remote_commit_hash, conflict_resolution = None, options = None, workspace_head = None):
|
278
|
+
"""Update workspace from git"""
|
279
|
+
ws = self.get_workspace_by_id(id=workspace_id)
|
280
|
+
return ws.update_from_git(remote_commit_hash=remote_commit_hash,
|
281
|
+
conflict_resolution=conflict_resolution,
|
282
|
+
options=options,
|
283
|
+
workspace_head=workspace_head)
|
@@ -0,0 +1,246 @@
|
|
1
|
+
import json
|
2
|
+
import requests
|
3
|
+
from time import sleep
|
4
|
+
|
5
|
+
from msfabricpysdkcore.onelakeshortcut import OneLakeShortcut
|
6
|
+
from msfabricpysdkcore.job_instance import JobInstance
|
7
|
+
from msfabricpysdkcore.long_running_operation import check_long_running_operation
|
8
|
+
|
9
|
+
class Item:
|
10
|
+
"""Class to represent a item in Microsoft Fabric"""
|
11
|
+
|
12
|
+
def __init__(self, id, display_name, type, workspace_id, auth, properties = None, definition=None, description="") -> None:
|
13
|
+
|
14
|
+
self.id = id
|
15
|
+
self.display_name = display_name
|
16
|
+
self.description = description
|
17
|
+
self.type = type
|
18
|
+
self.definition = definition
|
19
|
+
self.properties = properties
|
20
|
+
self.workspace_id = workspace_id
|
21
|
+
|
22
|
+
self.auth = auth
|
23
|
+
|
24
|
+
def __str__(self) -> str:
|
25
|
+
"""Return a string representation of the workspace object"""
|
26
|
+
dict_ = {
|
27
|
+
'id': self.id,
|
28
|
+
'display_name': self.display_name,
|
29
|
+
'description': self.description,
|
30
|
+
'type': self.type,
|
31
|
+
'definition': self.definition,
|
32
|
+
'workspace_id': self.workspace_id,
|
33
|
+
'properties': self.properties
|
34
|
+
}
|
35
|
+
return json.dumps(dict_, indent=2)
|
36
|
+
|
37
|
+
def from_dict(item_dict, auth):
|
38
|
+
"""Create Item object from dictionary"""
|
39
|
+
return Item(id=item_dict['id'], display_name=item_dict['displayName'], type=item_dict['type'], workspace_id=item_dict['workspaceId'],
|
40
|
+
properties=item_dict.get('properties', None),
|
41
|
+
definition=item_dict.get('definition', None), description=item_dict.get('description', ""), auth=auth)
|
42
|
+
|
43
|
+
def delete(self):
|
44
|
+
"""Delete the workspace item"""
|
45
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}"
|
46
|
+
for _ in range(10):
|
47
|
+
response = requests.delete(url=url, headers=self.auth.get_headers())
|
48
|
+
if response.status_code == 429:
|
49
|
+
print("Too many requests, waiting 10 seconds")
|
50
|
+
sleep(10)
|
51
|
+
continue
|
52
|
+
if response.status_code not in (200, 429):
|
53
|
+
print(response.status_code)
|
54
|
+
print(response.text)
|
55
|
+
raise Exception(f"Error deleting item: {response.text}")
|
56
|
+
break
|
57
|
+
|
58
|
+
return response.status_code
|
59
|
+
|
60
|
+
def get_definition(self):
|
61
|
+
"""Get the definition of the item"""
|
62
|
+
|
63
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/getDefinition"
|
64
|
+
|
65
|
+
for _ in range(10):
|
66
|
+
response = requests.post(url=url, headers=self.auth.get_headers())
|
67
|
+
if response.status_code == 429:
|
68
|
+
print("Too many requests, waiting 10 seconds")
|
69
|
+
sleep(10)
|
70
|
+
continue
|
71
|
+
if response.status_code == 202:
|
72
|
+
check_long_running_operation( response.headers, self.auth)
|
73
|
+
|
74
|
+
if response.status_code not in (200, 202, 429):
|
75
|
+
print(response.status_code)
|
76
|
+
print(response.text)
|
77
|
+
raise Exception(f"Error getting item definition: {response.text}")
|
78
|
+
break
|
79
|
+
|
80
|
+
print(response.text)
|
81
|
+
print(response.status_code)
|
82
|
+
return json.loads(response.text)
|
83
|
+
|
84
|
+
def update(self, display_name = None, description = None):
|
85
|
+
"""Update the item"""
|
86
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}"
|
87
|
+
|
88
|
+
payload = dict()
|
89
|
+
if display_name:
|
90
|
+
payload['displayName'] = display_name
|
91
|
+
if description:
|
92
|
+
payload['description'] = description
|
93
|
+
|
94
|
+
for _ in range(10):
|
95
|
+
response = requests.patch(url=url, headers=self.auth.get_headers(), json=payload)
|
96
|
+
if response.status_code == 429:
|
97
|
+
print("Too many requests, waiting 10 seconds")
|
98
|
+
sleep(10)
|
99
|
+
continue
|
100
|
+
if response.status_code not in (200, 429):
|
101
|
+
print(response.status_code)
|
102
|
+
print(response.text)
|
103
|
+
|
104
|
+
raise Exception(f"Error updating item: {response.text}")
|
105
|
+
break
|
106
|
+
if display_name:
|
107
|
+
self.display_name = payload['displayName']
|
108
|
+
if description:
|
109
|
+
self.description = payload['description']
|
110
|
+
|
111
|
+
return self
|
112
|
+
|
113
|
+
def update_definition(self, definition):
|
114
|
+
"""Update the item definition"""
|
115
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/updateDefinition"
|
116
|
+
payload = {
|
117
|
+
'definition': definition
|
118
|
+
}
|
119
|
+
for _ in range(10):
|
120
|
+
response = requests.post(url=url, headers=self.auth.get_headers(), json=payload)
|
121
|
+
if response.status_code == 429:
|
122
|
+
print("Too many requests, waiting 10 seconds")
|
123
|
+
sleep(10)
|
124
|
+
continue
|
125
|
+
if response.status_code == 202:
|
126
|
+
check_long_running_operation( response.headers, self.auth)
|
127
|
+
if response.status_code not in (200, 202, 429):
|
128
|
+
print(response.status_code)
|
129
|
+
print(response.text)
|
130
|
+
|
131
|
+
raise Exception(f"Error updating item definition: {response.text}")
|
132
|
+
break
|
133
|
+
|
134
|
+
self.definition = payload['definition']
|
135
|
+
return self
|
136
|
+
|
137
|
+
def get_shortcut(self, path, name):
|
138
|
+
"""Get the shortcut in the item"""
|
139
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/shortcuts/{path}/{name}"
|
140
|
+
|
141
|
+
for _ in range(10):
|
142
|
+
response = requests.get(url=url, headers=self.auth.get_headers())
|
143
|
+
if response.status_code == 429:
|
144
|
+
print("Too many requests, waiting 10 seconds")
|
145
|
+
sleep(10)
|
146
|
+
continue
|
147
|
+
if response.status_code not in (200, 429):
|
148
|
+
print(response.status_code)
|
149
|
+
print(response.text)
|
150
|
+
|
151
|
+
raise Exception(f"Error getting shortcut: {response.text}")
|
152
|
+
break
|
153
|
+
|
154
|
+
shortcut_dict = json.loads(response.text)
|
155
|
+
shortcut_dict['workspaceId'] = self.workspace_id
|
156
|
+
shortcut_dict['itemId'] = self.id
|
157
|
+
return OneLakeShortcut.from_dict(shortcut_dict,
|
158
|
+
auth = self.auth)
|
159
|
+
|
160
|
+
def create_shortcut(self, path, name, target):
|
161
|
+
"""Create a shortcut in the item"""
|
162
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/shortcuts"
|
163
|
+
|
164
|
+
body = {'name': name,
|
165
|
+
'path': path,
|
166
|
+
'target': target}
|
167
|
+
|
168
|
+
for _ in range(10):
|
169
|
+
response = requests.post(url=url, headers=self.auth.get_headers(), json=body)
|
170
|
+
if response.status_code == 429:
|
171
|
+
print("Too many requests, waiting 10 seconds")
|
172
|
+
sleep(10)
|
173
|
+
continue
|
174
|
+
if response.status_code not in (201, 429):
|
175
|
+
print(response.status_code)
|
176
|
+
print(response.text)
|
177
|
+
|
178
|
+
raise Exception(f"Error creating shortcut: {response.text}")
|
179
|
+
break
|
180
|
+
|
181
|
+
shortcut_dict = json.loads(response.text)
|
182
|
+
shortcut_dict['workspaceId'] = self.workspace_id
|
183
|
+
shortcut_dict['itemId'] = self.id
|
184
|
+
return OneLakeShortcut.from_dict(shortcut_dict,
|
185
|
+
auth = self.auth)
|
186
|
+
|
187
|
+
def delete_shortcut(self, path, name):
|
188
|
+
"""Delete the shortcut in the item"""
|
189
|
+
return self.get_shortcut(path, name).delete()
|
190
|
+
|
191
|
+
|
192
|
+
def run_on_demand_item_job(self, job_type, execution_data = None):
|
193
|
+
"""Run an on demand job on the item"""
|
194
|
+
|
195
|
+
# POST https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/jobs/instances?jobType={jobType}
|
196
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/jobs/instances?jobType={job_type}"
|
197
|
+
payload = {
|
198
|
+
'executionData': execution_data
|
199
|
+
}
|
200
|
+
|
201
|
+
for _ in range(10):
|
202
|
+
if execution_data:
|
203
|
+
response = requests.post(url=url, headers=self.auth.get_headers(), json=payload)
|
204
|
+
else:
|
205
|
+
response = requests.post(url=url, headers=self.auth.get_headers())
|
206
|
+
if response.status_code == 429:
|
207
|
+
print("Too many requests, waiting 10 seconds")
|
208
|
+
sleep(10)
|
209
|
+
continue
|
210
|
+
|
211
|
+
if response.status_code not in (202, 429):
|
212
|
+
print(response.status_code)
|
213
|
+
print(response.text)
|
214
|
+
|
215
|
+
raise Exception(f"Error running on demand job: {response.text}")
|
216
|
+
break
|
217
|
+
job_instance_id = response.headers["Location"].split("/")[-1]
|
218
|
+
job_instance = self.get_item_job_instance(job_instance_id=job_instance_id)
|
219
|
+
return job_instance
|
220
|
+
|
221
|
+
def get_item_job_instance(self, job_instance_id):
|
222
|
+
"""Get the job instance of the item"""
|
223
|
+
|
224
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/jobs/instances/{job_instance_id}"
|
225
|
+
for _ in range(10):
|
226
|
+
response = requests.get(url=url, headers=self.auth.get_headers())
|
227
|
+
if response.status_code == 429:
|
228
|
+
print("Too many requests, waiting 10 seconds")
|
229
|
+
sleep(10)
|
230
|
+
continue
|
231
|
+
if response.status_code not in (200, 429):
|
232
|
+
print(response.status_code)
|
233
|
+
print(response.text)
|
234
|
+
|
235
|
+
raise Exception(f"Error getting job instance: {response.text}")
|
236
|
+
break
|
237
|
+
|
238
|
+
job_dict = json.loads(response.text)
|
239
|
+
job_dict['workspaceId'] = self.workspace_id
|
240
|
+
job_dict['itemId'] = self.id
|
241
|
+
return JobInstance.from_dict(job_dict, auth=self.auth)
|
242
|
+
|
243
|
+
def cancel_item_job_instance(self, job_instance_id):
|
244
|
+
"""Cancel a job instance ofjob the item"""
|
245
|
+
return self.get_item_job_instance(job_instance_id=job_instance_id).cancel()
|
246
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import json
|
2
|
+
import requests
|
3
|
+
from time import sleep
|
4
|
+
from msfabricpysdkcore.long_running_operation import check_long_running_operation
|
5
|
+
|
6
|
+
class JobInstance:
|
7
|
+
"""Class to represent a job instance in Microsoft Fabric"""
|
8
|
+
|
9
|
+
def __init__(self, id, item_id, workspace_id, auth, job_type, invoke_type, status, root_activity_id,
|
10
|
+
start_time_utc, end_time_utc, failureReason):
|
11
|
+
|
12
|
+
self.id = id
|
13
|
+
self.item_id = item_id
|
14
|
+
self.workspace_id = workspace_id
|
15
|
+
self.job_type = job_type
|
16
|
+
self.invoke_type = invoke_type
|
17
|
+
self.status = status
|
18
|
+
self.root_activity_id = root_activity_id
|
19
|
+
self.start_time_utc = start_time_utc
|
20
|
+
self.end_time_utc = end_time_utc
|
21
|
+
self.failureReason = failureReason
|
22
|
+
|
23
|
+
self.auth = auth
|
24
|
+
|
25
|
+
|
26
|
+
def __str__(self) -> str:
|
27
|
+
"""Return a string representation of the workspace object"""
|
28
|
+
dict_ = {
|
29
|
+
'id': self.id,
|
30
|
+
'item_id': self.item_id,
|
31
|
+
'workspace_id': self.workspace_id,
|
32
|
+
'job_type': self.job_type,
|
33
|
+
'invoke_type': self.invoke_type,
|
34
|
+
'status': self.status,
|
35
|
+
'root_activity_id': self.root_activity_id,
|
36
|
+
'start_time_utc': self.start_time_utc,
|
37
|
+
'end_time_utc': self.end_time_utc,
|
38
|
+
'failureReason': self.failureReason
|
39
|
+
}
|
40
|
+
return json.dumps(dict_, indent=2)
|
41
|
+
|
42
|
+
def from_dict(job_dict, auth):
|
43
|
+
"""Create JobInstance object from dictionary"""
|
44
|
+
return JobInstance(id=job_dict['id'], item_id=job_dict['itemId'], workspace_id=job_dict['workspaceId'],
|
45
|
+
job_type=job_dict['jobType'], invoke_type=job_dict['invokeType'], status=job_dict['status'],
|
46
|
+
root_activity_id=job_dict['rootActivityId'], start_time_utc=job_dict['startTimeUtc'],
|
47
|
+
end_time_utc=job_dict['endTimeUtc'], failureReason=job_dict['failureReason'], auth=auth)
|
48
|
+
|
49
|
+
def cancel(self):
|
50
|
+
"""Cancel the job instance"""
|
51
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.item_id}/jobs/instances/{self.id}/cancel"
|
52
|
+
for _ in range(10):
|
53
|
+
response = requests.post(url=url, headers=self.auth.get_headers())
|
54
|
+
if response.status_code == 429:
|
55
|
+
print("Too many requests, waiting 10 seconds")
|
56
|
+
sleep(10)
|
57
|
+
continue
|
58
|
+
|
59
|
+
if response.status_code not in (202, 429):
|
60
|
+
print(response.status_code)
|
61
|
+
print(response.text)
|
62
|
+
|
63
|
+
raise Exception(f"Error running on demand job: {response.text}")
|
64
|
+
break
|
65
|
+
|
66
|
+
return response.status_code
|