msfabricpysdkcore 0.0.12__py3-none-any.whl → 0.0.13__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/adminapi.py +49 -1
- msfabricpysdkcore/coreapi.py +46 -1
- msfabricpysdkcore/environment.py +11 -10
- msfabricpysdkcore/item.py +147 -6
- msfabricpysdkcore/tests/test_admin_apis.py +20 -0
- msfabricpysdkcore/tests/test_external_data_shares.py +51 -0
- msfabricpysdkcore/tests/test_one_lake_data_access_security.py +65 -0
- msfabricpysdkcore/workspace.py +42 -0
- {msfabricpysdkcore-0.0.12.dist-info → msfabricpysdkcore-0.0.13.dist-info}/METADATA +102 -1
- {msfabricpysdkcore-0.0.12.dist-info → msfabricpysdkcore-0.0.13.dist-info}/RECORD +13 -11
- {msfabricpysdkcore-0.0.12.dist-info → msfabricpysdkcore-0.0.13.dist-info}/LICENSE +0 -0
- {msfabricpysdkcore-0.0.12.dist-info → msfabricpysdkcore-0.0.13.dist-info}/WHEEL +0 -0
- {msfabricpysdkcore-0.0.12.dist-info → msfabricpysdkcore-0.0.13.dist-info}/top_level.txt +0 -0
msfabricpysdkcore/adminapi.py
CHANGED
@@ -658,4 +658,52 @@ class FabricClientAdmin(FabricClient):
|
|
658
658
|
break
|
659
659
|
|
660
660
|
response = json.loads(response.text)
|
661
|
-
return response
|
661
|
+
return response
|
662
|
+
|
663
|
+
def list_external_data_shares(self, continuationToken = None):
|
664
|
+
# GET https://api.fabric.microsoft.com/v1/admin/items/externalDataShares
|
665
|
+
"""List external data shares
|
666
|
+
|
667
|
+
Returns:
|
668
|
+
list: The list of external data shares
|
669
|
+
"""
|
670
|
+
url = "https://api.fabric.microsoft.com/v1/admin/items/externalDataShares"
|
671
|
+
|
672
|
+
if continuationToken:
|
673
|
+
url = f"{url}?continuationToken={continuationToken}"
|
674
|
+
|
675
|
+
for _ in range(10):
|
676
|
+
response = requests.get(url=url, headers=self.auth.get_headers())
|
677
|
+
if response.status_code == 429:
|
678
|
+
print("Too many requests, waiting 10 seconds")
|
679
|
+
sleep(10)
|
680
|
+
continue
|
681
|
+
if response.status_code not in (200, 429):
|
682
|
+
raise Exception(f"Error listing external data shares: {response.status_code}, {response.text}")
|
683
|
+
break
|
684
|
+
|
685
|
+
response = json.loads(response.text)
|
686
|
+
list_data_shares = response["value"]
|
687
|
+
|
688
|
+
if "continuationToken" in response and response["continuationToken"] is not None:
|
689
|
+
list_data_shares_next = self.list_external_data_shares(continuationToken=response["continuationToken"])
|
690
|
+
list_data_shares.extend(list_data_shares_next)
|
691
|
+
return list_data_shares
|
692
|
+
|
693
|
+
def revoke_external_data_share(self, external_data_share_id, item_id, workspace_id):
|
694
|
+
# POST https://api.fabric.microsoft.com/v1/admin/workspaces/{workspaceId}/items/{itemId}/externalDataShares/{externalDataShareId}/revoke
|
695
|
+
"""Revoke an external data share"""
|
696
|
+
url = f"https://api.fabric.microsoft.com/v1/admin/workspaces/{workspace_id}/items/{item_id}/externalDataShares/{external_data_share_id}/revoke"
|
697
|
+
|
698
|
+
for _ in range(10):
|
699
|
+
response = requests.post(url=url, headers=self.auth.get_headers())
|
700
|
+
if response.status_code == 429:
|
701
|
+
print("Too many requests, waiting 10 seconds")
|
702
|
+
sleep(10)
|
703
|
+
continue
|
704
|
+
if response.status_code not in (200, 429):
|
705
|
+
raise Exception(f"Error revoking external data share: {response.status_code}, {response.text}")
|
706
|
+
break
|
707
|
+
|
708
|
+
return response.status_code
|
709
|
+
|
msfabricpysdkcore/coreapi.py
CHANGED
@@ -1011,4 +1011,49 @@ class FabricClientCore(FabricClient):
|
|
1011
1011
|
return ws.update_spark_settings(automatic_log=automatic_log,
|
1012
1012
|
environment=environment,
|
1013
1013
|
high_concurrency=high_concurrency,
|
1014
|
-
pool=pool)
|
1014
|
+
pool=pool)
|
1015
|
+
|
1016
|
+
|
1017
|
+
# External Data Shares
|
1018
|
+
|
1019
|
+
# create
|
1020
|
+
|
1021
|
+
def create_external_data_share(self, workspace_id, item_id, paths, recipient):
|
1022
|
+
ws = self.get_workspace_by_id(workspace_id)
|
1023
|
+
return ws.create_external_data_share(item_id=item_id, paths = paths, recipient = recipient)
|
1024
|
+
|
1025
|
+
# get
|
1026
|
+
|
1027
|
+
def get_external_data_share(self, workspace_id, item_id, external_data_share_id):
|
1028
|
+
ws = self.get_workspace_by_id(workspace_id)
|
1029
|
+
return ws.get_external_data_share(item_id=item_id, external_data_share_id=external_data_share_id)
|
1030
|
+
|
1031
|
+
# list
|
1032
|
+
|
1033
|
+
def list_external_data_shares_in_item(self, workspace_id, item_id):
|
1034
|
+
ws = self.get_workspace_by_id(workspace_id)
|
1035
|
+
return ws.list_external_data_shares_in_item(item_id=item_id)
|
1036
|
+
|
1037
|
+
# revoke
|
1038
|
+
|
1039
|
+
def revoke_external_data_share(self, workspace_id, item_id, external_data_share_id):
|
1040
|
+
ws = self.get_workspace_by_id(workspace_id)
|
1041
|
+
return ws.revoke_external_data_share(item_id=item_id, external_data_share_id=external_data_share_id)
|
1042
|
+
|
1043
|
+
|
1044
|
+
# One Lake Data Access Security
|
1045
|
+
|
1046
|
+
# create and update
|
1047
|
+
|
1048
|
+
def create_or_update_data_access_roles(self, workspace_id, item_id, data_access_roles, dryrun = False, etag_match = None):
|
1049
|
+
ws = self.get_workspace_by_id(workspace_id)
|
1050
|
+
item = ws.get_item(item_id=item_id).create_or_update_data_access_roles(data_access_roles = data_access_roles,
|
1051
|
+
dryrun = dryrun, etag_match = etag_match)
|
1052
|
+
return item
|
1053
|
+
|
1054
|
+
# list
|
1055
|
+
|
1056
|
+
def list_data_access_roles(self, workspace_id, item_id):
|
1057
|
+
ws = self.get_workspace_by_id(workspace_id)
|
1058
|
+
item = ws.get_item(item_id=item_id)
|
1059
|
+
return item.list_data_access_roles()
|
msfabricpysdkcore/environment.py
CHANGED
@@ -135,16 +135,17 @@ class Environment(Item):
|
|
135
135
|
# POST https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/environments/{environmentId}/staging/libraries
|
136
136
|
raise NotImplementedError("Not implemented yet")
|
137
137
|
# url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/environments/{self.id}/staging/libraries"
|
138
|
-
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
138
|
+
# with open(file_path, 'rb') as f:
|
139
|
+
# files = {"upload_file.whl": f}
|
140
|
+
# for _ in range(10):
|
141
|
+
# response = requests.post(url=url, files=files, headers=self.auth.get_headers())
|
142
|
+
# if response.status_code == 429:
|
143
|
+
# print("Too many requests, waiting 10 seconds")
|
144
|
+
# sleep(10)
|
145
|
+
# continue
|
146
|
+
# if response.status_code not in (200, 429):
|
147
|
+
# raise Exception(f"Error uploading staging libraries: {response.status_code}, {response.text}")
|
148
|
+
# break
|
148
149
|
|
149
150
|
# return json.loads(response.text)
|
150
151
|
|
msfabricpysdkcore/item.py
CHANGED
@@ -6,7 +6,6 @@ from msfabricpysdkcore.onelakeshortcut import OneLakeShortcut
|
|
6
6
|
from msfabricpysdkcore.job_instance import JobInstance
|
7
7
|
from msfabricpysdkcore.long_running_operation import check_long_running_operation
|
8
8
|
|
9
|
-
|
10
9
|
class Item:
|
11
10
|
"""Class to represent a item in Microsoft Fabric"""
|
12
11
|
|
@@ -247,10 +246,7 @@ class Item:
|
|
247
246
|
sleep(10)
|
248
247
|
continue
|
249
248
|
if response.status_code not in (200, 429):
|
250
|
-
|
251
|
-
print(response.text)
|
252
|
-
|
253
|
-
raise Exception(f"Error getting job instance: {response.text}")
|
249
|
+
raise Exception(f"Error getting job instance: {response.status_code}, {response.text}")
|
254
250
|
break
|
255
251
|
|
256
252
|
job_dict = json.loads(response.text)
|
@@ -268,4 +264,149 @@ class Item:
|
|
268
264
|
def load_table(self, table_name, path_type, relative_path,
|
269
265
|
file_extension = None, format_options = None,
|
270
266
|
mode = None, recursive = None, wait_for_completion = True):
|
271
|
-
raise NotImplementedError("Load table only works on Lakehouse Items")
|
267
|
+
raise NotImplementedError("Load table only works on Lakehouse Items")
|
268
|
+
|
269
|
+
def create_external_data_share(self, paths, recipient):
|
270
|
+
# POST https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/externalDataShares
|
271
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/externalDataShares"
|
272
|
+
|
273
|
+
body = {
|
274
|
+
'paths': paths,
|
275
|
+
'recipient': recipient
|
276
|
+
}
|
277
|
+
|
278
|
+
for _ in range(10):
|
279
|
+
response = requests.post(url=url, headers=self.auth.get_headers(), json=body)
|
280
|
+
if response.status_code == 429:
|
281
|
+
print("Too many requests, waiting 10 seconds")
|
282
|
+
sleep(10)
|
283
|
+
continue
|
284
|
+
if response.status_code not in (201, 429):
|
285
|
+
raise Exception(f"Error creating external data share: {response.status_code}, {response.text}")
|
286
|
+
break
|
287
|
+
return json.loads(response.text)
|
288
|
+
|
289
|
+
def get_external_data_share(self, external_data_share_id):
|
290
|
+
# GET https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/externalDataShares/{externalDataShareId}
|
291
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/externalDataShares/{external_data_share_id}"
|
292
|
+
|
293
|
+
for _ in range(10):
|
294
|
+
response = requests.get(url=url, headers=self.auth.get_headers())
|
295
|
+
if response.status_code == 429:
|
296
|
+
print("Too many requests, waiting 10 seconds")
|
297
|
+
sleep(10)
|
298
|
+
continue
|
299
|
+
if response.status_code not in (200, 429):
|
300
|
+
raise Exception(f"Error getting external data share: {response.status_code}, {response.text}")
|
301
|
+
break
|
302
|
+
return json.loads(response.text)
|
303
|
+
|
304
|
+
def list_external_data_shares_in_item(self, continuationToken = None):
|
305
|
+
# GET GET https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/externalDataShares?continuationToken={continuationToken}
|
306
|
+
|
307
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/externalDataShares"
|
308
|
+
|
309
|
+
if continuationToken:
|
310
|
+
url += f"?continuationToken={continuationToken}"
|
311
|
+
|
312
|
+
for _ in range(10):
|
313
|
+
response = requests.get(url=url, headers=self.auth.get_headers())
|
314
|
+
if response.status_code == 429:
|
315
|
+
print("Too many requests, waiting 10 seconds")
|
316
|
+
sleep(10)
|
317
|
+
continue
|
318
|
+
|
319
|
+
if response.status_code not in (200, 429):
|
320
|
+
raise Exception(f"Error listing external data shares: {response.status_code}, {response.text}")
|
321
|
+
break
|
322
|
+
|
323
|
+
resp = json.loads(response.text)
|
324
|
+
external_data_shares = resp['value']
|
325
|
+
|
326
|
+
if 'continuationToken' in resp:
|
327
|
+
external_data_shares_new = self.list_external_data_shares_in_item(continuationToken=resp['continuationToken'])
|
328
|
+
external_data_shares.extend(external_data_shares_new)
|
329
|
+
|
330
|
+
return external_data_shares
|
331
|
+
|
332
|
+
def revoke_external_data_share(self, external_data_share_id):
|
333
|
+
# POST https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/externalDataShares/{externalDataShareId}/revoke
|
334
|
+
|
335
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/externalDataShares/{external_data_share_id}/revoke"
|
336
|
+
|
337
|
+
for _ in range(10):
|
338
|
+
response = requests.post(url=url, headers=self.auth.get_headers())
|
339
|
+
if response.status_code == 429:
|
340
|
+
print("Too many requests, waiting 10 seconds")
|
341
|
+
sleep(10)
|
342
|
+
continue
|
343
|
+
if response.status_code not in (200, 429):
|
344
|
+
raise Exception(f"Error revoking external data share: {response.status_code}, {response.text}")
|
345
|
+
break
|
346
|
+
|
347
|
+
return response.status_code
|
348
|
+
|
349
|
+
|
350
|
+
# One Lake data access security
|
351
|
+
|
352
|
+
def list_data_access_roles(self, continuationToken = None):
|
353
|
+
# GET https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/dataAccessRoles
|
354
|
+
|
355
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/dataAccessRoles"
|
356
|
+
|
357
|
+
if continuationToken:
|
358
|
+
url += f"?continuationToken={continuationToken}"
|
359
|
+
|
360
|
+
for _ in range(10):
|
361
|
+
response = requests.get(url=url, headers=self.auth.get_headers())
|
362
|
+
if response.status_code == 429:
|
363
|
+
print("Too many requests, waiting 10 seconds")
|
364
|
+
sleep(10)
|
365
|
+
continue
|
366
|
+
if response.status_code not in (200, 429):
|
367
|
+
raise Exception(f"Error revoking external data share: {response.status_code}, {response.text}")
|
368
|
+
break
|
369
|
+
|
370
|
+
resp_dict = json.loads(response.text)
|
371
|
+
data_access_roles = resp_dict['value']
|
372
|
+
etag = response.headers.get('ETag', None)
|
373
|
+
|
374
|
+
if 'continuationToken' in resp_dict and resp_dict['continuationToken']:
|
375
|
+
data_access_roles_new, etag = self.list_data_access_roles(continuationToken=resp_dict['continuationToken'])
|
376
|
+
data_access_roles.extend(data_access_roles_new)
|
377
|
+
|
378
|
+
return data_access_roles, etag
|
379
|
+
|
380
|
+
def create_or_update_data_access_roles(self, data_access_roles, dryrun = False, etag_match = None):
|
381
|
+
# PUT https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/items/{itemId}/dataAccessRoles
|
382
|
+
|
383
|
+
url = f"https://api.fabric.microsoft.com/v1/workspaces/{self.workspace_id}/items/{self.id}/dataAccessRoles"
|
384
|
+
|
385
|
+
if dryrun:
|
386
|
+
url += "?dryrun=true"
|
387
|
+
|
388
|
+
if etag_match:
|
389
|
+
if 'If-Match' in etag_match:
|
390
|
+
headers = self.auth.get_headers()
|
391
|
+
headers['If-Match'] = etag_match['If-Match']
|
392
|
+
elif 'If-None-Match' in etag_match:
|
393
|
+
headers = self.auth.get_headers()
|
394
|
+
headers['If-None-Match'] = etag_match['If-None-Match']
|
395
|
+
else:
|
396
|
+
raise Exception("Etag match should include If-Match or If-None-Match")
|
397
|
+
else:
|
398
|
+
headers = self.auth.get_headers()
|
399
|
+
|
400
|
+
body = {"value" : data_access_roles}
|
401
|
+
|
402
|
+
for _ in range(10):
|
403
|
+
response = requests.put(url=url, headers=headers, json=body)
|
404
|
+
if response.status_code == 429:
|
405
|
+
print("Too many requests, waiting 10 seconds")
|
406
|
+
sleep(10)
|
407
|
+
continue
|
408
|
+
if response.status_code not in (200, 429):
|
409
|
+
raise Exception(f"Error creating or updating data access roles: {response.status_code}, {response.text}")
|
410
|
+
break
|
411
|
+
|
412
|
+
return response
|
@@ -77,3 +77,23 @@ class TestFabricClientCore(unittest.TestCase):
|
|
77
77
|
self.assertEqual(resp["itemsChangeLabelStatus"][0]["status"], "Succeeded")
|
78
78
|
resp = fca.bulk_remove_labels(items=items)
|
79
79
|
self.assertEqual(resp["itemsChangeLabelStatus"][0]["status"], "Succeeded")
|
80
|
+
|
81
|
+
def test_admin_external_data_shares(self):
|
82
|
+
|
83
|
+
fca = self.fca
|
84
|
+
|
85
|
+
data_shares = fca.list_external_data_shares()
|
86
|
+
ws = fca.list_workspaces(name="testworkspace")[0]
|
87
|
+
|
88
|
+
data_shares = [d for d in data_shares if d['workspaceId'] == ws.id]
|
89
|
+
|
90
|
+
self.assertGreater(len(data_shares), 0)
|
91
|
+
fca.revoke_external_data_share(external_data_share_id = data_shares[0]['id'],
|
92
|
+
item_id = data_shares[0]['itemId'],
|
93
|
+
workspace_id = data_shares[0]['workspaceId'])
|
94
|
+
data_shares = fca.list_external_data_shares()
|
95
|
+
ws = fca.list_workspaces(name="testworkspace")[0]
|
96
|
+
|
97
|
+
data_shares = [d for d in data_shares if d['workspaceId'] == ws.id]
|
98
|
+
|
99
|
+
self.assertEqual(data_shares[0]['status'], 'Revoked')
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import unittest
|
2
|
+
from dotenv import load_dotenv
|
3
|
+
from msfabricpysdkcore.coreapi import FabricClientCore
|
4
|
+
|
5
|
+
load_dotenv()
|
6
|
+
|
7
|
+
class TestFabricClientCore(unittest.TestCase):
|
8
|
+
|
9
|
+
def __init__(self, *args, **kwargs):
|
10
|
+
super(TestFabricClientCore, self).__init__(*args, **kwargs)
|
11
|
+
self.fc = FabricClientCore()
|
12
|
+
|
13
|
+
def test_external_data_shares(self):
|
14
|
+
|
15
|
+
fc = self.fc
|
16
|
+
|
17
|
+
workspace_id = 'c3352d34-0b54-40f0-b204-cc964b1beb8d'
|
18
|
+
item_id = 'e2c09c89-bf97-4f71-bdeb-36338795ec36'
|
19
|
+
|
20
|
+
recipient = {
|
21
|
+
"userPrincipalName": "lisa4@fabrikam.com"
|
22
|
+
}
|
23
|
+
paths=["Files/external"]
|
24
|
+
|
25
|
+
resp = fc.create_external_data_share(workspace_id, item_id, paths, recipient)
|
26
|
+
self.assertIsNotNone(resp)
|
27
|
+
self.assertIn('id', resp)
|
28
|
+
|
29
|
+
|
30
|
+
get = fc.get_external_data_share(workspace_id, item_id, resp['id'])
|
31
|
+
self.assertIsNotNone(get)
|
32
|
+
self.assertEqual(get['id'], resp['id'])
|
33
|
+
|
34
|
+
|
35
|
+
resp = fc.list_external_data_shares_in_item(workspace_id, item_id)
|
36
|
+
self.assertGreater(len(resp), 0)
|
37
|
+
|
38
|
+
data_share_ids = [ds['id'] for ds in resp]
|
39
|
+
self.assertIn(get['id'], data_share_ids)
|
40
|
+
|
41
|
+
|
42
|
+
resp = fc.revoke_external_data_share(workspace_id, item_id, get['id'])
|
43
|
+
self.assertEqual(resp, 200)
|
44
|
+
|
45
|
+
get2 = fc.get_external_data_share(workspace_id, item_id, get['id'])
|
46
|
+
self.assertIsNotNone(get2)
|
47
|
+
|
48
|
+
self.assertEqual(get['id'], get2['id'])
|
49
|
+
self.assertEqual(get2['status'], 'Revoked')
|
50
|
+
|
51
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import unittest
|
2
|
+
from dotenv import load_dotenv
|
3
|
+
from msfabricpysdkcore.coreapi import FabricClientCore
|
4
|
+
|
5
|
+
load_dotenv()
|
6
|
+
|
7
|
+
class TestFabricClientCore(unittest.TestCase):
|
8
|
+
|
9
|
+
def __init__(self, *args, **kwargs):
|
10
|
+
super(TestFabricClientCore, self).__init__(*args, **kwargs)
|
11
|
+
self.fc = FabricClientCore()
|
12
|
+
|
13
|
+
def test_one_lake_data_access_security(self):
|
14
|
+
|
15
|
+
fc = self.fc
|
16
|
+
|
17
|
+
workspace_id = "d8a5abe0-9eed-406d-ab46-343bc57ddbe5"
|
18
|
+
item_id = "50368cf3-29e7-4a09-aaf0-289fb5748364"
|
19
|
+
|
20
|
+
resp = fc.list_data_access_roles(workspace_id=workspace_id, item_id=item_id)
|
21
|
+
self.assertEqual(len(resp), 2)
|
22
|
+
|
23
|
+
roles = resp[0]
|
24
|
+
etag = resp[1]
|
25
|
+
|
26
|
+
role1 = roles[1]
|
27
|
+
|
28
|
+
self.assertIn('members', role1)
|
29
|
+
self.assertIn('fabricItemMembers', role1['members'])
|
30
|
+
self.assertGreater(len(role1['members']['fabricItemMembers']), 0)
|
31
|
+
self.assertIn('itemAccess', role1['members']['fabricItemMembers'][0])
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
item_access = role1["members"]["fabricItemMembers"][0]['itemAccess']
|
36
|
+
item_access_old = list(item_access)
|
37
|
+
if 'ReadAll' in item_access:
|
38
|
+
item_access = ['Read', 'Write', 'Execute']
|
39
|
+
else:
|
40
|
+
item_access.append('ReadAll')
|
41
|
+
|
42
|
+
role1["members"]["fabricItemMembers"][0]['itemAccess'] = item_access
|
43
|
+
roles[1] = role1
|
44
|
+
|
45
|
+
resp = fc.create_or_update_data_access_roles(workspace_id=workspace_id,
|
46
|
+
item_id=item_id,
|
47
|
+
data_access_roles=roles,
|
48
|
+
etag_match={"If-Match":etag})
|
49
|
+
|
50
|
+
|
51
|
+
resp = fc.list_data_access_roles(workspace_id=workspace_id, item_id=item_id)
|
52
|
+
self.assertEqual(len(resp), 2)
|
53
|
+
|
54
|
+
roles = resp[0]
|
55
|
+
etag = resp[1]
|
56
|
+
|
57
|
+
role1 = roles[1]
|
58
|
+
|
59
|
+
self.assertIn('members', role1)
|
60
|
+
self.assertIn('fabricItemMembers', role1['members'])
|
61
|
+
self.assertGreater(len(role1['members']['fabricItemMembers']), 0)
|
62
|
+
self.assertIn('itemAccess', role1['members']['fabricItemMembers'][0])
|
63
|
+
|
64
|
+
item_access = role1["members"]["fabricItemMembers"][0]['itemAccess']
|
65
|
+
self.assertNotEqual(item_access, item_access_old)
|
msfabricpysdkcore/workspace.py
CHANGED
@@ -1472,3 +1472,45 @@ class Workspace:
|
|
1472
1472
|
|
1473
1473
|
return json.loads(response.text)
|
1474
1474
|
|
1475
|
+
# External Data Shares
|
1476
|
+
|
1477
|
+
# create
|
1478
|
+
|
1479
|
+
def create_external_data_share(self, item_id, paths, recipient):
|
1480
|
+
item = self.get_item(item_id=item_id)
|
1481
|
+
return item.create_external_data_share(paths = paths, recipient = recipient)
|
1482
|
+
|
1483
|
+
# get
|
1484
|
+
|
1485
|
+
def get_external_data_share(self, item_id, external_data_share_id):
|
1486
|
+
item = self.get_item(item_id=item_id)
|
1487
|
+
return item.get_external_data_share(external_data_share_id=external_data_share_id)
|
1488
|
+
|
1489
|
+
|
1490
|
+
# list
|
1491
|
+
|
1492
|
+
def list_external_data_shares_in_item(self, item_id):
|
1493
|
+
item = self.get_item(item_id=item_id)
|
1494
|
+
return item.list_external_data_shares_in_item()
|
1495
|
+
|
1496
|
+
# revoke
|
1497
|
+
|
1498
|
+
def revoke_external_data_share(self, item_id, external_data_share_id):
|
1499
|
+
item = self.get_item(item_id=item_id)
|
1500
|
+
return item.revoke_external_data_share(external_data_share_id=external_data_share_id)
|
1501
|
+
|
1502
|
+
|
1503
|
+
# One Lake Data Access Security
|
1504
|
+
|
1505
|
+
# create and update
|
1506
|
+
|
1507
|
+
def create_or_update_data_access_roles(self, item_id, data_access_roles, dryrun = False, etag_match = None):
|
1508
|
+
item = self.get_item(item_id=item_id).create_or_update_data_access_roles(data_access_roles = data_access_roles,
|
1509
|
+
dryrun = dryrun, etag_match = etag_match)
|
1510
|
+
return item
|
1511
|
+
|
1512
|
+
# list
|
1513
|
+
|
1514
|
+
def list_data_access_roles(self, item_id):
|
1515
|
+
item = self.get_item(item_id=item_id)
|
1516
|
+
return item.list_data_access_roles()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: msfabricpysdkcore
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.13
|
4
4
|
Summary: A Python SDK for Microsoft Fabric
|
5
5
|
Author: Andreas Rederer
|
6
6
|
Project-URL: Homepage, https://github.com/DaSenf1860/ms-fabric-sdk-core
|
@@ -38,14 +38,17 @@ Currently it supports all Core APIs, Admin APIs, Lakehouse APIs and all other it
|
|
38
38
|
- Core APIs
|
39
39
|
- [Capacities](#working-with-capacities)
|
40
40
|
- [Deployment Pipelines](#deployment-pipelines)
|
41
|
+
- [External Data Shares](#external-data-shares)
|
41
42
|
- [Git](#working-with-git)
|
42
43
|
- [Items](#working-with-items)
|
43
44
|
- [Job Scheduler](#working-with-job-scheduler)
|
44
45
|
- [Long Running Operations](#long-running-operations)
|
46
|
+
- [OneLakeDataAccessSecurity](#one-lake-data-access-security)
|
45
47
|
- [OneLakeShortcuts](#working-with-one-lake-shortcuts)
|
46
48
|
- [Workspaces](#working-with-workspaces)
|
47
49
|
- Admin APIs
|
48
50
|
- [Domains](#admin-api-for-domains)
|
51
|
+
- [External Data Shares](#admin-api-for-external-data-shares)
|
49
52
|
- [Items](#admin-api-for-items)
|
50
53
|
- [Labels](#admin-api-for-labels)
|
51
54
|
- [Tenants](#admin-api-for-tenants)
|
@@ -249,6 +252,43 @@ response = pipe.deploy(source_stage_id=dev_stage.id,target_stage_id=prod_stage.i
|
|
249
252
|
|
250
253
|
```
|
251
254
|
|
255
|
+
### External Data Shares
|
256
|
+
|
257
|
+
```python
|
258
|
+
from msfabricpysdkcore.coreapi import FabricClientCore
|
259
|
+
|
260
|
+
fc = FabricClientCore()
|
261
|
+
|
262
|
+
workspace_id = 'yxcvyxcvyxcv'
|
263
|
+
item_id = 'sdfsdfsdfsf'
|
264
|
+
|
265
|
+
|
266
|
+
# Create
|
267
|
+
|
268
|
+
recipient = {
|
269
|
+
"userPrincipalName": "lisa4@fabrikam.com"
|
270
|
+
}
|
271
|
+
paths=["Files/external"]
|
272
|
+
|
273
|
+
data_share = fc.create_external_data_share(workspace_id, item_id, paths, recipient)
|
274
|
+
|
275
|
+
# Get
|
276
|
+
|
277
|
+
data_share2 = fc.get_external_data_share(workspace_id, item_id, data_share['id'])
|
278
|
+
|
279
|
+
# List
|
280
|
+
|
281
|
+
data_share_list = fc.list_external_data_shares_in_item(workspace_id, item_id)
|
282
|
+
|
283
|
+
data_share_ids = [ds['id'] for ds in data_share_list]
|
284
|
+
|
285
|
+
# Revoke
|
286
|
+
|
287
|
+
response_code = fc.revoke_external_data_share(workspace_id, item_id, data_share['id'])
|
288
|
+
|
289
|
+
```
|
290
|
+
|
291
|
+
|
252
292
|
### Working with items
|
253
293
|
|
254
294
|
```python
|
@@ -452,6 +492,44 @@ results = fc.get_operation_results(operation_id)
|
|
452
492
|
|
453
493
|
```
|
454
494
|
|
495
|
+
### One Lake Data Access Security
|
496
|
+
|
497
|
+
```python
|
498
|
+
from msfabricpysdkcore import FabricClientCore
|
499
|
+
|
500
|
+
fc = FabricClientCore()
|
501
|
+
|
502
|
+
workspace_id = "d8aafgasdsdbe5"
|
503
|
+
item_id = "503hsdfhs48364"
|
504
|
+
|
505
|
+
# List
|
506
|
+
|
507
|
+
resp = fc.list_data_access_roles(workspace_id=workspace_id, item_id=item_id)
|
508
|
+
|
509
|
+
roles = resp[0]
|
510
|
+
etag = resp[1]
|
511
|
+
|
512
|
+
|
513
|
+
# Create or Update
|
514
|
+
|
515
|
+
role1 = roles[1]
|
516
|
+
|
517
|
+
item_access = role1["members"]["fabricItemMembers"][0]['itemAccess']
|
518
|
+
+
|
519
|
+
if 'ReadAll' in item_access:
|
520
|
+
item_access = ['Read', 'Write', 'Execute']
|
521
|
+
else:
|
522
|
+
item_access.append('ReadAll')
|
523
|
+
|
524
|
+
role1["members"]["fabricItemMembers"][0]['itemAccess'] = item_access
|
525
|
+
roles[1] = role1
|
526
|
+
|
527
|
+
resp = fc.create_or_update_data_access_roles(workspace_id=workspace_id,
|
528
|
+
item_id=item_id,
|
529
|
+
data_access_roles=roles,
|
530
|
+
etag_match={"If-Match":etag})
|
531
|
+
|
532
|
+
```
|
455
533
|
|
456
534
|
### Admin API for Workspaces
|
457
535
|
|
@@ -611,6 +689,29 @@ status_code = fca.role_assignments_bulk_unassign(domain.id, "Contributors", [pri
|
|
611
689
|
status_code = fca.delete_domain(domain.id)
|
612
690
|
```
|
613
691
|
|
692
|
+
### Admin API for External Data Shares
|
693
|
+
|
694
|
+
```python
|
695
|
+
from msfabricpysdkcore import FabricClientAdmin
|
696
|
+
|
697
|
+
fca = FabricClientAdmin()
|
698
|
+
|
699
|
+
# List external data shares
|
700
|
+
|
701
|
+
data_shares = fca.list_external_data_shares()
|
702
|
+
ws = fca.list_workspaces(name="testworkspace")[0]
|
703
|
+
|
704
|
+
data_shares = [d for d in data_shares if d['workspaceId'] == ws.id]
|
705
|
+
|
706
|
+
# Revoke external data share
|
707
|
+
|
708
|
+
fca.revoke_external_data_share(external_data_share_id = data_shares[0]['id'],
|
709
|
+
item_id = data_shares[0]['itemId'],
|
710
|
+
workspace_id = data_shares[0]['workspaceId'])
|
711
|
+
|
712
|
+
|
713
|
+
```
|
714
|
+
|
614
715
|
|
615
716
|
Note: This SDK is not an official SDK from Microsoft. It is a community project and not supported by Microsoft. Use it at your own risk.
|
616
717
|
Also the API is still in preview and might change. This SDK is not yet feature complete and might not cover all APIs yet. Feel free to contribute to this project to make it better.
|
@@ -1,39 +1,41 @@
|
|
1
1
|
msfabricpysdkcore/__init__.py,sha256=nh8-lxdMBWYSbQpbRxWkn3ZRpGipmQplTudjskN2l88,78
|
2
2
|
msfabricpysdkcore/admin_item.py,sha256=OGVfMMqAKy80Ukp8TJnpXoRq8WbWX7Qq1hz7tmfiUBU,4020
|
3
3
|
msfabricpysdkcore/admin_workspace.py,sha256=RctVsXZ57ppiybua69BW_yVpUbrGic6fYOjFPZFPAzA,4862
|
4
|
-
msfabricpysdkcore/adminapi.py,sha256=
|
4
|
+
msfabricpysdkcore/adminapi.py,sha256=g4q2KNYmMdp7HSrLJYM8rIWKMbmN0XUEDj_T8K-Ue4g,27920
|
5
5
|
msfabricpysdkcore/auth.py,sha256=v5YkI4jA6T7lv5rjqTK-GEPx2ATDPKQ1LVcaCg98oLM,2562
|
6
6
|
msfabricpysdkcore/capacity.py,sha256=Q_2-XrZtdf9F67fY0qU3D0ocEOGQq4KtIXAv9dXjQhI,1761
|
7
7
|
msfabricpysdkcore/client.py,sha256=yOZ1CW2ilL8a7J_SRNa-EQbG8xNlJKW3ygniIrsADsw,1300
|
8
|
-
msfabricpysdkcore/coreapi.py,sha256=
|
8
|
+
msfabricpysdkcore/coreapi.py,sha256=UP13F3xdtv710PEVjZSv5txmvAOEMB-5U8Q26byEZFQ,51430
|
9
9
|
msfabricpysdkcore/deployment_pipeline.py,sha256=RFI86rtG-eTpV-_tVl3cXtcTl9ekRvOI5fLsXo9CMVA,9739
|
10
10
|
msfabricpysdkcore/domain.py,sha256=i8jMJEutDRL5XuQ69woCVQEzLS_lm9uUxl4Kp3xtxHc,14722
|
11
|
-
msfabricpysdkcore/environment.py,sha256=
|
12
|
-
msfabricpysdkcore/item.py,sha256=
|
11
|
+
msfabricpysdkcore/environment.py,sha256=V4ASiGp-vkdMZYP5Syz8QNJtaez4TJFCzuNlRIxbArw,10182
|
12
|
+
msfabricpysdkcore/item.py,sha256=YCDYodA0yDNi5NdZSriGnb-lNdmav-PPPR7zTTnKR-w,18092
|
13
13
|
msfabricpysdkcore/job_instance.py,sha256=C9kKsV-BIJSeU6DfoTnLlg4DLp-8RYpovs0A-mKwi4o,2745
|
14
14
|
msfabricpysdkcore/lakehouse.py,sha256=nv95SBz_jsssT5dEw622WqtDHUyh5bFFsVTwiqo8s-c,6055
|
15
15
|
msfabricpysdkcore/long_running_operation.py,sha256=Itm8ohr9fPIdP7UO9_xehQ6wb6t4hsCuvDbcOSzAgVA,2981
|
16
16
|
msfabricpysdkcore/onelakeshortcut.py,sha256=EYZfP-rl60HdCqJD1O1NXrQTgrYTIw-EWisF4hs4bTU,2102
|
17
17
|
msfabricpysdkcore/otheritems.py,sha256=D-sGriO9ck4pqzsLY6bZLJUDXIBkyNyqCPoJmgextbk,12571
|
18
18
|
msfabricpysdkcore/spark_custom_pool.py,sha256=2H-GkGcDsiKxSpXFSf8Zi7xJI5_krb_8sGdF5vDjEy8,4635
|
19
|
-
msfabricpysdkcore/workspace.py,sha256=
|
19
|
+
msfabricpysdkcore/workspace.py,sha256=zDE9XHIY4yLYW5GmQY_ESKqxXlfb1MyloUv6QlqtiSY,70072
|
20
20
|
msfabricpysdkcore/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
-
msfabricpysdkcore/tests/test_admin_apis.py,sha256=
|
21
|
+
msfabricpysdkcore/tests/test_admin_apis.py,sha256=8bod82lNeTx7HbLxxTxF1gBvn3O_pW_xk1ND-0S56pg,3415
|
22
22
|
msfabricpysdkcore/tests/test_datapipelines.py,sha256=rIeZfv-MGewYYscb36jmjL8DLZ3Z1dJWv09foR9z_y8,1812
|
23
23
|
msfabricpysdkcore/tests/test_deployment_pipeline.py,sha256=7bXqSpnU8Hb7KyKldhA7hVM8QqKHj0WoT9_kC27hsxM,2058
|
24
24
|
msfabricpysdkcore/tests/test_domains.py,sha256=KFGQyl0G2v4JjX_xYHY-vPSjYxeLEx3AcXMdiRZzClc,4620
|
25
25
|
msfabricpysdkcore/tests/test_environments.py,sha256=zSIMhkQscMB7doJEQRBRMvAEBxO1Kl1N85MKXP3yeYI,3120
|
26
26
|
msfabricpysdkcore/tests/test_evenstreams.py,sha256=i6hhsOnDJ-BN7kStg7gQhZVPMVaB73K7KJez6pEKlv0,1628
|
27
|
+
msfabricpysdkcore/tests/test_external_data_shares.py,sha256=M3nbjNCZU5BDxXGt5649HQtIgaiK_U4hLvm770yVcSw,1550
|
27
28
|
msfabricpysdkcore/tests/test_git.py,sha256=pmhVYZGDMEFtgy51hKrDWqtea-MryyeyvPKVCaTsIEA,2415
|
28
29
|
msfabricpysdkcore/tests/test_items_incl_lakehouse.py,sha256=zWNmOI_Ysh96d8P-Sm4IOCzMqXTCEBg63lxCDZZ_9b8,17987
|
29
30
|
msfabricpysdkcore/tests/test_jobs.py,sha256=DC1nQTav_Re7uunRA07wD_56giLqe9KOsgm56Il8Zr4,1632
|
30
31
|
msfabricpysdkcore/tests/test_kqldatabases.py,sha256=Oc2ZzpQAVbiJeZ5ytwlP2Jb-tKe-2e9-1oA-upwRKBQ,1921
|
32
|
+
msfabricpysdkcore/tests/test_one_lake_data_access_security.py,sha256=GY5jm3Rz8WgPbUP7L8Y3V8sE4iV3LyyhGhLik__TX0w,2301
|
31
33
|
msfabricpysdkcore/tests/test_shortcuts.py,sha256=TqGLzEWsDyiQ0Gf6JpT_qBHUCgcvYXfVwpXxOay7Qz4,2407
|
32
34
|
msfabricpysdkcore/tests/test_spark.py,sha256=5BCAgHRiuXjIRnGrbvNNh9emq0VyZXlvIWgWAEir5ZQ,3437
|
33
35
|
msfabricpysdkcore/tests/test_sparkjobdefinition.py,sha256=whADi8l4opMaoB4b1W5EbuddyB5tC5OEqGRFKVUYMH4,2820
|
34
36
|
msfabricpysdkcore/tests/test_workspaces_capacities.py,sha256=52FqGZRVvHDegLgu71kGX_Tx4cRh9lO_wuK8BG_czkQ,6699
|
35
|
-
msfabricpysdkcore-0.0.
|
36
|
-
msfabricpysdkcore-0.0.
|
37
|
-
msfabricpysdkcore-0.0.
|
38
|
-
msfabricpysdkcore-0.0.
|
39
|
-
msfabricpysdkcore-0.0.
|
37
|
+
msfabricpysdkcore-0.0.13.dist-info/LICENSE,sha256=1NrGuF-zOmzbwzk3iI6lsP9koyDeKO1B0-8OD_tTvOQ,1156
|
38
|
+
msfabricpysdkcore-0.0.13.dist-info/METADATA,sha256=7AGKbri3_NsPkOfSgs-0naa8IpmRU_fSSBZhQUzj5Ws,20401
|
39
|
+
msfabricpysdkcore-0.0.13.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
40
|
+
msfabricpysdkcore-0.0.13.dist-info/top_level.txt,sha256=3iRonu6ptDGQN4Yl6G76XGM7xbFNsskiEHW-P2gMQGY,18
|
41
|
+
msfabricpysdkcore-0.0.13.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|