databricks-sdk 0.65.0__py3-none-any.whl → 0.67.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of databricks-sdk might be problematic. Click here for more details.

@@ -124,6 +124,244 @@ class AccessControlResponse:
124
124
  )
125
125
 
126
126
 
127
+ @dataclass
128
+ class AccountGroup:
129
+ account_id: Optional[str] = None
130
+ """Databricks account ID"""
131
+
132
+ display_name: Optional[str] = None
133
+ """String that represents a human-readable group name"""
134
+
135
+ external_id: Optional[str] = None
136
+ """external_id should be unique for identifying groups"""
137
+
138
+ id: Optional[str] = None
139
+ """Databricks group ID"""
140
+
141
+ members: Optional[List[ComplexValue]] = None
142
+
143
+ meta: Optional[ResourceMeta] = None
144
+ """Container for the group identifier. Workspace local versus account."""
145
+
146
+ roles: Optional[List[ComplexValue]] = None
147
+ """Indicates if the group has the admin role."""
148
+
149
+ def as_dict(self) -> dict:
150
+ """Serializes the AccountGroup into a dictionary suitable for use as a JSON request body."""
151
+ body = {}
152
+ if self.account_id is not None:
153
+ body["account_id"] = self.account_id
154
+ if self.display_name is not None:
155
+ body["displayName"] = self.display_name
156
+ if self.external_id is not None:
157
+ body["externalId"] = self.external_id
158
+ if self.id is not None:
159
+ body["id"] = self.id
160
+ if self.members:
161
+ body["members"] = [v.as_dict() for v in self.members]
162
+ if self.meta:
163
+ body["meta"] = self.meta.as_dict()
164
+ if self.roles:
165
+ body["roles"] = [v.as_dict() for v in self.roles]
166
+ return body
167
+
168
+ def as_shallow_dict(self) -> dict:
169
+ """Serializes the AccountGroup into a shallow dictionary of its immediate attributes."""
170
+ body = {}
171
+ if self.account_id is not None:
172
+ body["account_id"] = self.account_id
173
+ if self.display_name is not None:
174
+ body["displayName"] = self.display_name
175
+ if self.external_id is not None:
176
+ body["externalId"] = self.external_id
177
+ if self.id is not None:
178
+ body["id"] = self.id
179
+ if self.members:
180
+ body["members"] = self.members
181
+ if self.meta:
182
+ body["meta"] = self.meta
183
+ if self.roles:
184
+ body["roles"] = self.roles
185
+ return body
186
+
187
+ @classmethod
188
+ def from_dict(cls, d: Dict[str, Any]) -> AccountGroup:
189
+ """Deserializes the AccountGroup from a dictionary."""
190
+ return cls(
191
+ account_id=d.get("account_id", None),
192
+ display_name=d.get("displayName", None),
193
+ external_id=d.get("externalId", None),
194
+ id=d.get("id", None),
195
+ members=_repeated_dict(d, "members", ComplexValue),
196
+ meta=_from_dict(d, "meta", ResourceMeta),
197
+ roles=_repeated_dict(d, "roles", ComplexValue),
198
+ )
199
+
200
+
201
+ @dataclass
202
+ class AccountServicePrincipal:
203
+ account_id: Optional[str] = None
204
+ """Databricks account ID"""
205
+
206
+ active: Optional[bool] = None
207
+ """If this user is active"""
208
+
209
+ application_id: Optional[str] = None
210
+ """UUID relating to the service principal"""
211
+
212
+ display_name: Optional[str] = None
213
+ """String that represents a concatenation of given and family names."""
214
+
215
+ external_id: Optional[str] = None
216
+
217
+ id: Optional[str] = None
218
+ """Databricks service principal ID."""
219
+
220
+ roles: Optional[List[ComplexValue]] = None
221
+ """Indicates if the group has the admin role."""
222
+
223
+ def as_dict(self) -> dict:
224
+ """Serializes the AccountServicePrincipal into a dictionary suitable for use as a JSON request body."""
225
+ body = {}
226
+ if self.account_id is not None:
227
+ body["account_id"] = self.account_id
228
+ if self.active is not None:
229
+ body["active"] = self.active
230
+ if self.application_id is not None:
231
+ body["applicationId"] = self.application_id
232
+ if self.display_name is not None:
233
+ body["displayName"] = self.display_name
234
+ if self.external_id is not None:
235
+ body["externalId"] = self.external_id
236
+ if self.id is not None:
237
+ body["id"] = self.id
238
+ if self.roles:
239
+ body["roles"] = [v.as_dict() for v in self.roles]
240
+ return body
241
+
242
+ def as_shallow_dict(self) -> dict:
243
+ """Serializes the AccountServicePrincipal into a shallow dictionary of its immediate attributes."""
244
+ body = {}
245
+ if self.account_id is not None:
246
+ body["account_id"] = self.account_id
247
+ if self.active is not None:
248
+ body["active"] = self.active
249
+ if self.application_id is not None:
250
+ body["applicationId"] = self.application_id
251
+ if self.display_name is not None:
252
+ body["displayName"] = self.display_name
253
+ if self.external_id is not None:
254
+ body["externalId"] = self.external_id
255
+ if self.id is not None:
256
+ body["id"] = self.id
257
+ if self.roles:
258
+ body["roles"] = self.roles
259
+ return body
260
+
261
+ @classmethod
262
+ def from_dict(cls, d: Dict[str, Any]) -> AccountServicePrincipal:
263
+ """Deserializes the AccountServicePrincipal from a dictionary."""
264
+ return cls(
265
+ account_id=d.get("account_id", None),
266
+ active=d.get("active", None),
267
+ application_id=d.get("applicationId", None),
268
+ display_name=d.get("displayName", None),
269
+ external_id=d.get("externalId", None),
270
+ id=d.get("id", None),
271
+ roles=_repeated_dict(d, "roles", ComplexValue),
272
+ )
273
+
274
+
275
+ @dataclass
276
+ class AccountUser:
277
+ account_id: Optional[str] = None
278
+ """Databricks account ID"""
279
+
280
+ active: Optional[bool] = None
281
+ """If this user is active"""
282
+
283
+ display_name: Optional[str] = None
284
+ """String that represents a concatenation of given and family names. For example `John Smith`."""
285
+
286
+ emails: Optional[List[ComplexValue]] = None
287
+ """All the emails associated with the Databricks user."""
288
+
289
+ external_id: Optional[str] = None
290
+ """External ID is not currently supported. It is reserved for future use."""
291
+
292
+ id: Optional[str] = None
293
+ """Databricks user ID."""
294
+
295
+ name: Optional[Name] = None
296
+
297
+ roles: Optional[List[ComplexValue]] = None
298
+ """Indicates if the group has the admin role."""
299
+
300
+ user_name: Optional[str] = None
301
+ """Email address of the Databricks user."""
302
+
303
+ def as_dict(self) -> dict:
304
+ """Serializes the AccountUser into a dictionary suitable for use as a JSON request body."""
305
+ body = {}
306
+ if self.account_id is not None:
307
+ body["account_id"] = self.account_id
308
+ if self.active is not None:
309
+ body["active"] = self.active
310
+ if self.display_name is not None:
311
+ body["displayName"] = self.display_name
312
+ if self.emails:
313
+ body["emails"] = [v.as_dict() for v in self.emails]
314
+ if self.external_id is not None:
315
+ body["externalId"] = self.external_id
316
+ if self.id is not None:
317
+ body["id"] = self.id
318
+ if self.name:
319
+ body["name"] = self.name.as_dict()
320
+ if self.roles:
321
+ body["roles"] = [v.as_dict() for v in self.roles]
322
+ if self.user_name is not None:
323
+ body["userName"] = self.user_name
324
+ return body
325
+
326
+ def as_shallow_dict(self) -> dict:
327
+ """Serializes the AccountUser into a shallow dictionary of its immediate attributes."""
328
+ body = {}
329
+ if self.account_id is not None:
330
+ body["account_id"] = self.account_id
331
+ if self.active is not None:
332
+ body["active"] = self.active
333
+ if self.display_name is not None:
334
+ body["displayName"] = self.display_name
335
+ if self.emails:
336
+ body["emails"] = self.emails
337
+ if self.external_id is not None:
338
+ body["externalId"] = self.external_id
339
+ if self.id is not None:
340
+ body["id"] = self.id
341
+ if self.name:
342
+ body["name"] = self.name
343
+ if self.roles:
344
+ body["roles"] = self.roles
345
+ if self.user_name is not None:
346
+ body["userName"] = self.user_name
347
+ return body
348
+
349
+ @classmethod
350
+ def from_dict(cls, d: Dict[str, Any]) -> AccountUser:
351
+ """Deserializes the AccountUser from a dictionary."""
352
+ return cls(
353
+ account_id=d.get("account_id", None),
354
+ active=d.get("active", None),
355
+ display_name=d.get("displayName", None),
356
+ emails=_repeated_dict(d, "emails", ComplexValue),
357
+ external_id=d.get("externalId", None),
358
+ id=d.get("id", None),
359
+ name=_from_dict(d, "name", Name),
360
+ roles=_repeated_dict(d, "roles", ComplexValue),
361
+ user_name=d.get("userName", None),
362
+ )
363
+
364
+
127
365
  @dataclass
128
366
  class Actor:
129
367
  """represents an identity trying to access a resource - user or a service principal group can be a
@@ -425,6 +663,7 @@ class Group:
425
663
  [assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements"""
426
664
 
427
665
  external_id: Optional[str] = None
666
+ """external_id should be unique for identifying groups"""
428
667
 
429
668
  groups: Optional[List[ComplexValue]] = None
430
669
 
@@ -510,16 +749,13 @@ class GroupSchema(Enum):
510
749
 
511
750
 
512
751
  @dataclass
513
- class ListGroupsResponse:
752
+ class ListAccountGroupsResponse:
514
753
  items_per_page: Optional[int] = None
515
754
  """Total results returned in the response."""
516
755
 
517
- resources: Optional[List[Group]] = None
756
+ resources: Optional[List[AccountGroup]] = None
518
757
  """User objects returned in the response."""
519
758
 
520
- schemas: Optional[List[ListResponseSchema]] = None
521
- """The schema of the service principal."""
522
-
523
759
  start_index: Optional[int] = None
524
760
  """Starting index of all the results that matched the request filters. First item is number 1."""
525
761
 
@@ -527,14 +763,12 @@ class ListGroupsResponse:
527
763
  """Total results that match the request filters."""
528
764
 
529
765
  def as_dict(self) -> dict:
530
- """Serializes the ListGroupsResponse into a dictionary suitable for use as a JSON request body."""
766
+ """Serializes the ListAccountGroupsResponse into a dictionary suitable for use as a JSON request body."""
531
767
  body = {}
532
768
  if self.items_per_page is not None:
533
769
  body["itemsPerPage"] = self.items_per_page
534
770
  if self.resources:
535
771
  body["Resources"] = [v.as_dict() for v in self.resources]
536
- if self.schemas:
537
- body["schemas"] = [v.value for v in self.schemas]
538
772
  if self.start_index is not None:
539
773
  body["startIndex"] = self.start_index
540
774
  if self.total_results is not None:
@@ -542,14 +776,12 @@ class ListGroupsResponse:
542
776
  return body
543
777
 
544
778
  def as_shallow_dict(self) -> dict:
545
- """Serializes the ListGroupsResponse into a shallow dictionary of its immediate attributes."""
779
+ """Serializes the ListAccountGroupsResponse into a shallow dictionary of its immediate attributes."""
546
780
  body = {}
547
781
  if self.items_per_page is not None:
548
782
  body["itemsPerPage"] = self.items_per_page
549
783
  if self.resources:
550
784
  body["Resources"] = self.resources
551
- if self.schemas:
552
- body["schemas"] = self.schemas
553
785
  if self.start_index is not None:
554
786
  body["startIndex"] = self.start_index
555
787
  if self.total_results is not None:
@@ -557,33 +789,24 @@ class ListGroupsResponse:
557
789
  return body
558
790
 
559
791
  @classmethod
560
- def from_dict(cls, d: Dict[str, Any]) -> ListGroupsResponse:
561
- """Deserializes the ListGroupsResponse from a dictionary."""
792
+ def from_dict(cls, d: Dict[str, Any]) -> ListAccountGroupsResponse:
793
+ """Deserializes the ListAccountGroupsResponse from a dictionary."""
562
794
  return cls(
563
795
  items_per_page=d.get("itemsPerPage", None),
564
- resources=_repeated_dict(d, "Resources", Group),
565
- schemas=_repeated_enum(d, "schemas", ListResponseSchema),
796
+ resources=_repeated_dict(d, "Resources", AccountGroup),
566
797
  start_index=d.get("startIndex", None),
567
798
  total_results=d.get("totalResults", None),
568
799
  )
569
800
 
570
801
 
571
- class ListResponseSchema(Enum):
572
-
573
- URN_IETF_PARAMS_SCIM_API_MESSAGES_2_0_LIST_RESPONSE = "urn:ietf:params:scim:api:messages:2.0:ListResponse"
574
-
575
-
576
802
  @dataclass
577
- class ListServicePrincipalResponse:
803
+ class ListAccountServicePrincipalsResponse:
578
804
  items_per_page: Optional[int] = None
579
805
  """Total results returned in the response."""
580
806
 
581
- resources: Optional[List[ServicePrincipal]] = None
807
+ resources: Optional[List[AccountServicePrincipal]] = None
582
808
  """User objects returned in the response."""
583
809
 
584
- schemas: Optional[List[ListResponseSchema]] = None
585
- """The schema of the List response."""
586
-
587
810
  start_index: Optional[int] = None
588
811
  """Starting index of all the results that matched the request filters. First item is number 1."""
589
812
 
@@ -591,14 +814,12 @@ class ListServicePrincipalResponse:
591
814
  """Total results that match the request filters."""
592
815
 
593
816
  def as_dict(self) -> dict:
594
- """Serializes the ListServicePrincipalResponse into a dictionary suitable for use as a JSON request body."""
817
+ """Serializes the ListAccountServicePrincipalsResponse into a dictionary suitable for use as a JSON request body."""
595
818
  body = {}
596
819
  if self.items_per_page is not None:
597
820
  body["itemsPerPage"] = self.items_per_page
598
821
  if self.resources:
599
822
  body["Resources"] = [v.as_dict() for v in self.resources]
600
- if self.schemas:
601
- body["schemas"] = [v.value for v in self.schemas]
602
823
  if self.start_index is not None:
603
824
  body["startIndex"] = self.start_index
604
825
  if self.total_results is not None:
@@ -606,14 +827,12 @@ class ListServicePrincipalResponse:
606
827
  return body
607
828
 
608
829
  def as_shallow_dict(self) -> dict:
609
- """Serializes the ListServicePrincipalResponse into a shallow dictionary of its immediate attributes."""
830
+ """Serializes the ListAccountServicePrincipalsResponse into a shallow dictionary of its immediate attributes."""
610
831
  body = {}
611
832
  if self.items_per_page is not None:
612
833
  body["itemsPerPage"] = self.items_per_page
613
834
  if self.resources:
614
835
  body["Resources"] = self.resources
615
- if self.schemas:
616
- body["schemas"] = self.schemas
617
836
  if self.start_index is not None:
618
837
  body["startIndex"] = self.start_index
619
838
  if self.total_results is not None:
@@ -621,34 +840,24 @@ class ListServicePrincipalResponse:
621
840
  return body
622
841
 
623
842
  @classmethod
624
- def from_dict(cls, d: Dict[str, Any]) -> ListServicePrincipalResponse:
625
- """Deserializes the ListServicePrincipalResponse from a dictionary."""
843
+ def from_dict(cls, d: Dict[str, Any]) -> ListAccountServicePrincipalsResponse:
844
+ """Deserializes the ListAccountServicePrincipalsResponse from a dictionary."""
626
845
  return cls(
627
846
  items_per_page=d.get("itemsPerPage", None),
628
- resources=_repeated_dict(d, "Resources", ServicePrincipal),
629
- schemas=_repeated_enum(d, "schemas", ListResponseSchema),
847
+ resources=_repeated_dict(d, "Resources", AccountServicePrincipal),
630
848
  start_index=d.get("startIndex", None),
631
849
  total_results=d.get("totalResults", None),
632
850
  )
633
851
 
634
852
 
635
- class ListSortOrder(Enum):
636
-
637
- ASCENDING = "ascending"
638
- DESCENDING = "descending"
639
-
640
-
641
853
  @dataclass
642
- class ListUsersResponse:
854
+ class ListAccountUsersResponse:
643
855
  items_per_page: Optional[int] = None
644
856
  """Total results returned in the response."""
645
857
 
646
- resources: Optional[List[User]] = None
858
+ resources: Optional[List[AccountUser]] = None
647
859
  """User objects returned in the response."""
648
860
 
649
- schemas: Optional[List[ListResponseSchema]] = None
650
- """The schema of the List response."""
651
-
652
861
  start_index: Optional[int] = None
653
862
  """Starting index of all the results that matched the request filters. First item is number 1."""
654
863
 
@@ -656,14 +865,12 @@ class ListUsersResponse:
656
865
  """Total results that match the request filters."""
657
866
 
658
867
  def as_dict(self) -> dict:
659
- """Serializes the ListUsersResponse into a dictionary suitable for use as a JSON request body."""
868
+ """Serializes the ListAccountUsersResponse into a dictionary suitable for use as a JSON request body."""
660
869
  body = {}
661
870
  if self.items_per_page is not None:
662
871
  body["itemsPerPage"] = self.items_per_page
663
872
  if self.resources:
664
873
  body["Resources"] = [v.as_dict() for v in self.resources]
665
- if self.schemas:
666
- body["schemas"] = [v.value for v in self.schemas]
667
874
  if self.start_index is not None:
668
875
  body["startIndex"] = self.start_index
669
876
  if self.total_results is not None:
@@ -671,14 +878,12 @@ class ListUsersResponse:
671
878
  return body
672
879
 
673
880
  def as_shallow_dict(self) -> dict:
674
- """Serializes the ListUsersResponse into a shallow dictionary of its immediate attributes."""
881
+ """Serializes the ListAccountUsersResponse into a shallow dictionary of its immediate attributes."""
675
882
  body = {}
676
883
  if self.items_per_page is not None:
677
884
  body["itemsPerPage"] = self.items_per_page
678
885
  if self.resources:
679
886
  body["Resources"] = self.resources
680
- if self.schemas:
681
- body["schemas"] = self.schemas
682
887
  if self.start_index is not None:
683
888
  body["startIndex"] = self.start_index
684
889
  if self.total_results is not None:
@@ -686,21 +891,208 @@ class ListUsersResponse:
686
891
  return body
687
892
 
688
893
  @classmethod
689
- def from_dict(cls, d: Dict[str, Any]) -> ListUsersResponse:
690
- """Deserializes the ListUsersResponse from a dictionary."""
894
+ def from_dict(cls, d: Dict[str, Any]) -> ListAccountUsersResponse:
895
+ """Deserializes the ListAccountUsersResponse from a dictionary."""
691
896
  return cls(
692
897
  items_per_page=d.get("itemsPerPage", None),
693
- resources=_repeated_dict(d, "Resources", User),
694
- schemas=_repeated_enum(d, "schemas", ListResponseSchema),
898
+ resources=_repeated_dict(d, "Resources", AccountUser),
695
899
  start_index=d.get("startIndex", None),
696
900
  total_results=d.get("totalResults", None),
697
901
  )
698
902
 
699
903
 
700
904
  @dataclass
701
- class MigratePermissionsResponse:
702
- permissions_migrated: Optional[int] = None
703
- """Number of permissions migrated."""
905
+ class ListGroupsResponse:
906
+ items_per_page: Optional[int] = None
907
+ """Total results returned in the response."""
908
+
909
+ resources: Optional[List[Group]] = None
910
+ """User objects returned in the response."""
911
+
912
+ schemas: Optional[List[ListResponseSchema]] = None
913
+ """The schema of the service principal."""
914
+
915
+ start_index: Optional[int] = None
916
+ """Starting index of all the results that matched the request filters. First item is number 1."""
917
+
918
+ total_results: Optional[int] = None
919
+ """Total results that match the request filters."""
920
+
921
+ def as_dict(self) -> dict:
922
+ """Serializes the ListGroupsResponse into a dictionary suitable for use as a JSON request body."""
923
+ body = {}
924
+ if self.items_per_page is not None:
925
+ body["itemsPerPage"] = self.items_per_page
926
+ if self.resources:
927
+ body["Resources"] = [v.as_dict() for v in self.resources]
928
+ if self.schemas:
929
+ body["schemas"] = [v.value for v in self.schemas]
930
+ if self.start_index is not None:
931
+ body["startIndex"] = self.start_index
932
+ if self.total_results is not None:
933
+ body["totalResults"] = self.total_results
934
+ return body
935
+
936
+ def as_shallow_dict(self) -> dict:
937
+ """Serializes the ListGroupsResponse into a shallow dictionary of its immediate attributes."""
938
+ body = {}
939
+ if self.items_per_page is not None:
940
+ body["itemsPerPage"] = self.items_per_page
941
+ if self.resources:
942
+ body["Resources"] = self.resources
943
+ if self.schemas:
944
+ body["schemas"] = self.schemas
945
+ if self.start_index is not None:
946
+ body["startIndex"] = self.start_index
947
+ if self.total_results is not None:
948
+ body["totalResults"] = self.total_results
949
+ return body
950
+
951
+ @classmethod
952
+ def from_dict(cls, d: Dict[str, Any]) -> ListGroupsResponse:
953
+ """Deserializes the ListGroupsResponse from a dictionary."""
954
+ return cls(
955
+ items_per_page=d.get("itemsPerPage", None),
956
+ resources=_repeated_dict(d, "Resources", Group),
957
+ schemas=_repeated_enum(d, "schemas", ListResponseSchema),
958
+ start_index=d.get("startIndex", None),
959
+ total_results=d.get("totalResults", None),
960
+ )
961
+
962
+
963
+ class ListResponseSchema(Enum):
964
+
965
+ URN_IETF_PARAMS_SCIM_API_MESSAGES_2_0_LIST_RESPONSE = "urn:ietf:params:scim:api:messages:2.0:ListResponse"
966
+
967
+
968
+ @dataclass
969
+ class ListServicePrincipalResponse:
970
+ items_per_page: Optional[int] = None
971
+ """Total results returned in the response."""
972
+
973
+ resources: Optional[List[ServicePrincipal]] = None
974
+ """User objects returned in the response."""
975
+
976
+ schemas: Optional[List[ListResponseSchema]] = None
977
+ """The schema of the List response."""
978
+
979
+ start_index: Optional[int] = None
980
+ """Starting index of all the results that matched the request filters. First item is number 1."""
981
+
982
+ total_results: Optional[int] = None
983
+ """Total results that match the request filters."""
984
+
985
+ def as_dict(self) -> dict:
986
+ """Serializes the ListServicePrincipalResponse into a dictionary suitable for use as a JSON request body."""
987
+ body = {}
988
+ if self.items_per_page is not None:
989
+ body["itemsPerPage"] = self.items_per_page
990
+ if self.resources:
991
+ body["Resources"] = [v.as_dict() for v in self.resources]
992
+ if self.schemas:
993
+ body["schemas"] = [v.value for v in self.schemas]
994
+ if self.start_index is not None:
995
+ body["startIndex"] = self.start_index
996
+ if self.total_results is not None:
997
+ body["totalResults"] = self.total_results
998
+ return body
999
+
1000
+ def as_shallow_dict(self) -> dict:
1001
+ """Serializes the ListServicePrincipalResponse into a shallow dictionary of its immediate attributes."""
1002
+ body = {}
1003
+ if self.items_per_page is not None:
1004
+ body["itemsPerPage"] = self.items_per_page
1005
+ if self.resources:
1006
+ body["Resources"] = self.resources
1007
+ if self.schemas:
1008
+ body["schemas"] = self.schemas
1009
+ if self.start_index is not None:
1010
+ body["startIndex"] = self.start_index
1011
+ if self.total_results is not None:
1012
+ body["totalResults"] = self.total_results
1013
+ return body
1014
+
1015
+ @classmethod
1016
+ def from_dict(cls, d: Dict[str, Any]) -> ListServicePrincipalResponse:
1017
+ """Deserializes the ListServicePrincipalResponse from a dictionary."""
1018
+ return cls(
1019
+ items_per_page=d.get("itemsPerPage", None),
1020
+ resources=_repeated_dict(d, "Resources", ServicePrincipal),
1021
+ schemas=_repeated_enum(d, "schemas", ListResponseSchema),
1022
+ start_index=d.get("startIndex", None),
1023
+ total_results=d.get("totalResults", None),
1024
+ )
1025
+
1026
+
1027
+ class ListSortOrder(Enum):
1028
+
1029
+ ASCENDING = "ascending"
1030
+ DESCENDING = "descending"
1031
+
1032
+
1033
+ @dataclass
1034
+ class ListUsersResponse:
1035
+ items_per_page: Optional[int] = None
1036
+ """Total results returned in the response."""
1037
+
1038
+ resources: Optional[List[User]] = None
1039
+ """User objects returned in the response."""
1040
+
1041
+ schemas: Optional[List[ListResponseSchema]] = None
1042
+ """The schema of the List response."""
1043
+
1044
+ start_index: Optional[int] = None
1045
+ """Starting index of all the results that matched the request filters. First item is number 1."""
1046
+
1047
+ total_results: Optional[int] = None
1048
+ """Total results that match the request filters."""
1049
+
1050
+ def as_dict(self) -> dict:
1051
+ """Serializes the ListUsersResponse into a dictionary suitable for use as a JSON request body."""
1052
+ body = {}
1053
+ if self.items_per_page is not None:
1054
+ body["itemsPerPage"] = self.items_per_page
1055
+ if self.resources:
1056
+ body["Resources"] = [v.as_dict() for v in self.resources]
1057
+ if self.schemas:
1058
+ body["schemas"] = [v.value for v in self.schemas]
1059
+ if self.start_index is not None:
1060
+ body["startIndex"] = self.start_index
1061
+ if self.total_results is not None:
1062
+ body["totalResults"] = self.total_results
1063
+ return body
1064
+
1065
+ def as_shallow_dict(self) -> dict:
1066
+ """Serializes the ListUsersResponse into a shallow dictionary of its immediate attributes."""
1067
+ body = {}
1068
+ if self.items_per_page is not None:
1069
+ body["itemsPerPage"] = self.items_per_page
1070
+ if self.resources:
1071
+ body["Resources"] = self.resources
1072
+ if self.schemas:
1073
+ body["schemas"] = self.schemas
1074
+ if self.start_index is not None:
1075
+ body["startIndex"] = self.start_index
1076
+ if self.total_results is not None:
1077
+ body["totalResults"] = self.total_results
1078
+ return body
1079
+
1080
+ @classmethod
1081
+ def from_dict(cls, d: Dict[str, Any]) -> ListUsersResponse:
1082
+ """Deserializes the ListUsersResponse from a dictionary."""
1083
+ return cls(
1084
+ items_per_page=d.get("itemsPerPage", None),
1085
+ resources=_repeated_dict(d, "Resources", User),
1086
+ schemas=_repeated_enum(d, "schemas", ListResponseSchema),
1087
+ start_index=d.get("startIndex", None),
1088
+ total_results=d.get("totalResults", None),
1089
+ )
1090
+
1091
+
1092
+ @dataclass
1093
+ class MigratePermissionsResponse:
1094
+ permissions_migrated: Optional[int] = None
1095
+ """Number of permissions migrated."""
704
1096
 
705
1097
  def as_dict(self) -> dict:
706
1098
  """Serializes the MigratePermissionsResponse into a dictionary suitable for use as a JSON request body."""
@@ -1647,24 +2039,6 @@ class ServicePrincipalSchema(Enum):
1647
2039
  URN_IETF_PARAMS_SCIM_SCHEMAS_CORE_2_0_SERVICE_PRINCIPAL = "urn:ietf:params:scim:schemas:core:2.0:ServicePrincipal"
1648
2040
 
1649
2041
 
1650
- @dataclass
1651
- class UpdateResponse:
1652
- def as_dict(self) -> dict:
1653
- """Serializes the UpdateResponse into a dictionary suitable for use as a JSON request body."""
1654
- body = {}
1655
- return body
1656
-
1657
- def as_shallow_dict(self) -> dict:
1658
- """Serializes the UpdateResponse into a shallow dictionary of its immediate attributes."""
1659
- body = {}
1660
- return body
1661
-
1662
- @classmethod
1663
- def from_dict(cls, d: Dict[str, Any]) -> UpdateResponse:
1664
- """Deserializes the UpdateResponse from a dictionary."""
1665
- return cls()
1666
-
1667
-
1668
2042
  @dataclass
1669
2043
  class User:
1670
2044
  active: Optional[bool] = None
@@ -1886,7 +2260,8 @@ class AccountAccessControlAPI:
1886
2260
  Examples | Summary :--- | :--- `resource=accounts/<ACCOUNT_ID>` | A resource name for the account.
1887
2261
  `resource=accounts/<ACCOUNT_ID>/groups/<GROUP_ID>` | A resource name for the group.
1888
2262
  `resource=accounts/<ACCOUNT_ID>/servicePrincipals/<SP_ID>` | A resource name for the service
1889
- principal.
2263
+ principal. `resource=accounts/<ACCOUNT_ID>/tagPolicies/<TAG_POLICY_ID>` | A resource name for the
2264
+ tag policy.
1890
2265
 
1891
2266
  :returns: :class:`GetAssignableRolesForResourceResponse`
1892
2267
  """
@@ -1918,6 +2293,8 @@ class AccountAccessControlAPI:
1918
2293
  set on the group.
1919
2294
  `name=accounts/<ACCOUNT_ID>/servicePrincipals/<SERVICE_PRINCIPAL_APPLICATION_ID>/ruleSets/default` |
1920
2295
  A name for a rule set on the service principal.
2296
+ `name=accounts/<ACCOUNT_ID>/tagPolicies/<TAG_POLICY_ID>/ruleSets/default` | A name for a rule set on
2297
+ the tag policy.
1921
2298
  :param etag: str
1922
2299
  Etag used for versioning. The response is at least as fresh as the eTag provided. Etag is used for
1923
2300
  optimistic concurrency control as a way to help prevent simultaneous updates of a rule set from
@@ -1997,7 +2374,8 @@ class AccountAccessControlProxyAPI:
1997
2374
  Examples | Summary :--- | :--- `resource=accounts/<ACCOUNT_ID>` | A resource name for the account.
1998
2375
  `resource=accounts/<ACCOUNT_ID>/groups/<GROUP_ID>` | A resource name for the group.
1999
2376
  `resource=accounts/<ACCOUNT_ID>/servicePrincipals/<SP_ID>` | A resource name for the service
2000
- principal.
2377
+ principal. `resource=accounts/<ACCOUNT_ID>/tagPolicies/<TAG_POLICY_ID>` | A resource name for the
2378
+ tag policy.
2001
2379
 
2002
2380
  :returns: :class:`GetAssignableRolesForResourceResponse`
2003
2381
  """
@@ -2026,6 +2404,8 @@ class AccountAccessControlProxyAPI:
2026
2404
  set on the group.
2027
2405
  `name=accounts/<ACCOUNT_ID>/servicePrincipals/<SERVICE_PRINCIPAL_APPLICATION_ID>/ruleSets/default` |
2028
2406
  A name for a rule set on the service principal.
2407
+ `name=accounts/<ACCOUNT_ID>/tagPolicies/<TAG_POLICY_ID>/ruleSets/default` | A name for a rule set on
2408
+ the tag policy.
2029
2409
  :param etag: str
2030
2410
  Etag used for versioning. The response is at least as fresh as the eTag provided. Etag is used for
2031
2411
  optimistic concurrency control as a way to help prevent simultaneous updates of a rule set from
@@ -2077,6 +2457,2006 @@ class AccountAccessControlProxyAPI:
2077
2457
  return RuleSetResponse.from_dict(res)
2078
2458
 
2079
2459
 
2460
+ class AccountGroupsV2API:
2461
+ """Groups simplify identity management, making it easier to assign access to Databricks account, data, and
2462
+ other securable objects.
2463
+
2464
+ It is best practice to assign access to workspaces and access-control policies in Unity Catalog to groups,
2465
+ instead of to users individually. All Databricks account identities can be assigned as members of groups,
2466
+ and members inherit permissions that are assigned to their group."""
2467
+
2468
+ def __init__(self, api_client):
2469
+ self._api = api_client
2470
+
2471
+ def create(
2472
+ self,
2473
+ *,
2474
+ display_name: Optional[str] = None,
2475
+ external_id: Optional[str] = None,
2476
+ id: Optional[str] = None,
2477
+ members: Optional[List[ComplexValue]] = None,
2478
+ meta: Optional[ResourceMeta] = None,
2479
+ roles: Optional[List[ComplexValue]] = None,
2480
+ ) -> AccountGroup:
2481
+ """Creates a group in the Databricks account with a unique name, using the supplied group details.
2482
+
2483
+ :param display_name: str (optional)
2484
+ String that represents a human-readable group name
2485
+ :param external_id: str (optional)
2486
+ :param id: str (optional)
2487
+ Databricks group ID
2488
+ :param members: List[:class:`ComplexValue`] (optional)
2489
+ :param meta: :class:`ResourceMeta` (optional)
2490
+ Container for the group identifier. Workspace local versus account.
2491
+ :param roles: List[:class:`ComplexValue`] (optional)
2492
+ Indicates if the group has the admin role.
2493
+
2494
+ :returns: :class:`AccountGroup`
2495
+ """
2496
+ body = {}
2497
+ if display_name is not None:
2498
+ body["displayName"] = display_name
2499
+ if external_id is not None:
2500
+ body["externalId"] = external_id
2501
+ if id is not None:
2502
+ body["id"] = id
2503
+ if members is not None:
2504
+ body["members"] = [v.as_dict() for v in members]
2505
+ if meta is not None:
2506
+ body["meta"] = meta.as_dict()
2507
+ if roles is not None:
2508
+ body["roles"] = [v.as_dict() for v in roles]
2509
+ headers = {
2510
+ "Accept": "application/json",
2511
+ "Content-Type": "application/json",
2512
+ }
2513
+
2514
+ res = self._api.do(
2515
+ "POST", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups", body=body, headers=headers
2516
+ )
2517
+ return AccountGroup.from_dict(res)
2518
+
2519
+ def delete(self, id: str):
2520
+ """Deletes a group from the Databricks account.
2521
+
2522
+ :param id: str
2523
+ Unique ID for a group in the Databricks account.
2524
+
2525
+
2526
+ """
2527
+
2528
+ headers = {}
2529
+
2530
+ self._api.do("DELETE", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", headers=headers)
2531
+
2532
+ def get(self, id: str) -> AccountGroup:
2533
+ """Gets the information for a specific group in the Databricks account.
2534
+
2535
+ :param id: str
2536
+ Unique ID for a group in the Databricks account.
2537
+
2538
+ :returns: :class:`AccountGroup`
2539
+ """
2540
+
2541
+ headers = {
2542
+ "Accept": "application/json",
2543
+ }
2544
+
2545
+ res = self._api.do("GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", headers=headers)
2546
+ return AccountGroup.from_dict(res)
2547
+
2548
+ def list(
2549
+ self,
2550
+ *,
2551
+ attributes: Optional[str] = None,
2552
+ count: Optional[int] = None,
2553
+ excluded_attributes: Optional[str] = None,
2554
+ filter: Optional[str] = None,
2555
+ sort_by: Optional[str] = None,
2556
+ sort_order: Optional[ListSortOrder] = None,
2557
+ start_index: Optional[int] = None,
2558
+ ) -> Iterator[AccountGroup]:
2559
+ """Gets all details of the groups associated with the Databricks account. As of 08/22/2025, this endpoint
2560
+ will not return members. Instead, members should be retrieved by iterating through `Get group
2561
+ details`.
2562
+
2563
+ :param attributes: str (optional)
2564
+ Comma-separated list of attributes to return in response.
2565
+ :param count: int (optional)
2566
+ Desired number of results per page. Default is 10000.
2567
+ :param excluded_attributes: str (optional)
2568
+ Comma-separated list of attributes to exclude in response.
2569
+ :param filter: str (optional)
2570
+ Query by which the results have to be filtered. Supported operators are equals(`eq`),
2571
+ contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
2572
+ formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
2573
+ only support simple expressions.
2574
+
2575
+ [SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
2576
+ :param sort_by: str (optional)
2577
+ Attribute to sort the results.
2578
+ :param sort_order: :class:`ListSortOrder` (optional)
2579
+ The order to sort the results.
2580
+ :param start_index: int (optional)
2581
+ Specifies the index of the first result. First item is number 1.
2582
+
2583
+ :returns: Iterator over :class:`AccountGroup`
2584
+ """
2585
+
2586
+ query = {}
2587
+ if attributes is not None:
2588
+ query["attributes"] = attributes
2589
+ if count is not None:
2590
+ query["count"] = count
2591
+ if excluded_attributes is not None:
2592
+ query["excludedAttributes"] = excluded_attributes
2593
+ if filter is not None:
2594
+ query["filter"] = filter
2595
+ if sort_by is not None:
2596
+ query["sortBy"] = sort_by
2597
+ if sort_order is not None:
2598
+ query["sortOrder"] = sort_order.value
2599
+ if start_index is not None:
2600
+ query["startIndex"] = start_index
2601
+ headers = {
2602
+ "Accept": "application/json",
2603
+ }
2604
+
2605
+ query["startIndex"] = 1
2606
+ if "count" not in query:
2607
+ query["count"] = 10000
2608
+ while True:
2609
+ json = self._api.do(
2610
+ "GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups", query=query, headers=headers
2611
+ )
2612
+ if "Resources" in json:
2613
+ for v in json["Resources"]:
2614
+ yield AccountGroup.from_dict(v)
2615
+ if "Resources" not in json or not json["Resources"]:
2616
+ return
2617
+ query["startIndex"] += len(json["Resources"])
2618
+
2619
+ def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
2620
+ """Partially updates the details of a group.
2621
+
2622
+ :param id: str
2623
+ Unique ID in the Databricks workspace.
2624
+ :param operations: List[:class:`Patch`] (optional)
2625
+ :param schemas: List[:class:`PatchSchema`] (optional)
2626
+ The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
2627
+
2628
+
2629
+ """
2630
+ body = {}
2631
+ if operations is not None:
2632
+ body["Operations"] = [v.as_dict() for v in operations]
2633
+ if schemas is not None:
2634
+ body["schemas"] = [v.value for v in schemas]
2635
+ headers = {
2636
+ "Content-Type": "application/json",
2637
+ }
2638
+
2639
+ self._api.do(
2640
+ "PATCH", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", body=body, headers=headers
2641
+ )
2642
+
2643
+ def update(
2644
+ self,
2645
+ id: str,
2646
+ *,
2647
+ display_name: Optional[str] = None,
2648
+ external_id: Optional[str] = None,
2649
+ members: Optional[List[ComplexValue]] = None,
2650
+ meta: Optional[ResourceMeta] = None,
2651
+ roles: Optional[List[ComplexValue]] = None,
2652
+ ):
2653
+ """Updates the details of a group by replacing the entire group entity.
2654
+
2655
+ :param id: str
2656
+ Databricks group ID
2657
+ :param display_name: str (optional)
2658
+ String that represents a human-readable group name
2659
+ :param external_id: str (optional)
2660
+ :param members: List[:class:`ComplexValue`] (optional)
2661
+ :param meta: :class:`ResourceMeta` (optional)
2662
+ Container for the group identifier. Workspace local versus account.
2663
+ :param roles: List[:class:`ComplexValue`] (optional)
2664
+ Indicates if the group has the admin role.
2665
+
2666
+
2667
+ """
2668
+ body = {}
2669
+ if display_name is not None:
2670
+ body["displayName"] = display_name
2671
+ if external_id is not None:
2672
+ body["externalId"] = external_id
2673
+ if members is not None:
2674
+ body["members"] = [v.as_dict() for v in members]
2675
+ if meta is not None:
2676
+ body["meta"] = meta.as_dict()
2677
+ if roles is not None:
2678
+ body["roles"] = [v.as_dict() for v in roles]
2679
+ headers = {
2680
+ "Accept": "application/json",
2681
+ "Content-Type": "application/json",
2682
+ }
2683
+
2684
+ self._api.do("PUT", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Groups/{id}", body=body, headers=headers)
2685
+
2686
+
2687
+ class AccountServicePrincipalsV2API:
2688
+ """Identities for use with jobs, automated tools, and systems such as scripts, apps, and CI/CD platforms.
2689
+ Databricks recommends creating service principals to run production jobs or modify production data. If all
2690
+ processes that act on production data run with service principals, interactive users do not need any
2691
+ write, delete, or modify privileges in production. This eliminates the risk of a user overwriting
2692
+ production data by accident."""
2693
+
2694
+ def __init__(self, api_client):
2695
+ self._api = api_client
2696
+
2697
+ def create(
2698
+ self,
2699
+ *,
2700
+ active: Optional[bool] = None,
2701
+ application_id: Optional[str] = None,
2702
+ display_name: Optional[str] = None,
2703
+ external_id: Optional[str] = None,
2704
+ id: Optional[str] = None,
2705
+ roles: Optional[List[ComplexValue]] = None,
2706
+ ) -> AccountServicePrincipal:
2707
+ """Creates a new service principal in the Databricks account.
2708
+
2709
+ :param active: bool (optional)
2710
+ If this user is active
2711
+ :param application_id: str (optional)
2712
+ UUID relating to the service principal
2713
+ :param display_name: str (optional)
2714
+ String that represents a concatenation of given and family names.
2715
+ :param external_id: str (optional)
2716
+ :param id: str (optional)
2717
+ Databricks service principal ID.
2718
+ :param roles: List[:class:`ComplexValue`] (optional)
2719
+ Indicates if the group has the admin role.
2720
+
2721
+ :returns: :class:`AccountServicePrincipal`
2722
+ """
2723
+ body = {}
2724
+ if active is not None:
2725
+ body["active"] = active
2726
+ if application_id is not None:
2727
+ body["applicationId"] = application_id
2728
+ if display_name is not None:
2729
+ body["displayName"] = display_name
2730
+ if external_id is not None:
2731
+ body["externalId"] = external_id
2732
+ if id is not None:
2733
+ body["id"] = id
2734
+ if roles is not None:
2735
+ body["roles"] = [v.as_dict() for v in roles]
2736
+ headers = {
2737
+ "Accept": "application/json",
2738
+ "Content-Type": "application/json",
2739
+ }
2740
+
2741
+ res = self._api.do(
2742
+ "POST", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals", body=body, headers=headers
2743
+ )
2744
+ return AccountServicePrincipal.from_dict(res)
2745
+
2746
+ def delete(self, id: str):
2747
+ """Delete a single service principal in the Databricks account.
2748
+
2749
+ :param id: str
2750
+ Unique ID for a service principal in the Databricks account.
2751
+
2752
+
2753
+ """
2754
+
2755
+ headers = {}
2756
+
2757
+ self._api.do(
2758
+ "DELETE", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}", headers=headers
2759
+ )
2760
+
2761
+ def get(self, id: str) -> AccountServicePrincipal:
2762
+ """Gets the details for a single service principal define in the Databricks account.
2763
+
2764
+ :param id: str
2765
+ Unique ID for a service principal in the Databricks account.
2766
+
2767
+ :returns: :class:`AccountServicePrincipal`
2768
+ """
2769
+
2770
+ headers = {
2771
+ "Accept": "application/json",
2772
+ }
2773
+
2774
+ res = self._api.do(
2775
+ "GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}", headers=headers
2776
+ )
2777
+ return AccountServicePrincipal.from_dict(res)
2778
+
2779
+ def list(
2780
+ self,
2781
+ *,
2782
+ attributes: Optional[str] = None,
2783
+ count: Optional[int] = None,
2784
+ excluded_attributes: Optional[str] = None,
2785
+ filter: Optional[str] = None,
2786
+ sort_by: Optional[str] = None,
2787
+ sort_order: Optional[ListSortOrder] = None,
2788
+ start_index: Optional[int] = None,
2789
+ ) -> Iterator[AccountServicePrincipal]:
2790
+ """Gets the set of service principals associated with a Databricks account.
2791
+
2792
+ :param attributes: str (optional)
2793
+ Comma-separated list of attributes to return in response.
2794
+ :param count: int (optional)
2795
+ Desired number of results per page. Default is 10000.
2796
+ :param excluded_attributes: str (optional)
2797
+ Comma-separated list of attributes to exclude in response.
2798
+ :param filter: str (optional)
2799
+ Query by which the results have to be filtered. Supported operators are equals(`eq`),
2800
+ contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
2801
+ formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
2802
+ only support simple expressions.
2803
+
2804
+ [SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
2805
+ :param sort_by: str (optional)
2806
+ Attribute to sort the results.
2807
+ :param sort_order: :class:`ListSortOrder` (optional)
2808
+ The order to sort the results.
2809
+ :param start_index: int (optional)
2810
+ Specifies the index of the first result. First item is number 1.
2811
+
2812
+ :returns: Iterator over :class:`AccountServicePrincipal`
2813
+ """
2814
+
2815
+ query = {}
2816
+ if attributes is not None:
2817
+ query["attributes"] = attributes
2818
+ if count is not None:
2819
+ query["count"] = count
2820
+ if excluded_attributes is not None:
2821
+ query["excludedAttributes"] = excluded_attributes
2822
+ if filter is not None:
2823
+ query["filter"] = filter
2824
+ if sort_by is not None:
2825
+ query["sortBy"] = sort_by
2826
+ if sort_order is not None:
2827
+ query["sortOrder"] = sort_order.value
2828
+ if start_index is not None:
2829
+ query["startIndex"] = start_index
2830
+ headers = {
2831
+ "Accept": "application/json",
2832
+ }
2833
+
2834
+ query["startIndex"] = 1
2835
+ if "count" not in query:
2836
+ query["count"] = 10000
2837
+ while True:
2838
+ json = self._api.do(
2839
+ "GET",
2840
+ f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals",
2841
+ query=query,
2842
+ headers=headers,
2843
+ )
2844
+ if "Resources" in json:
2845
+ for v in json["Resources"]:
2846
+ yield AccountServicePrincipal.from_dict(v)
2847
+ if "Resources" not in json or not json["Resources"]:
2848
+ return
2849
+ query["startIndex"] += len(json["Resources"])
2850
+
2851
+ def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
2852
+ """Partially updates the details of a single service principal in the Databricks account.
2853
+
2854
+ :param id: str
2855
+ Unique ID in the Databricks workspace.
2856
+ :param operations: List[:class:`Patch`] (optional)
2857
+ :param schemas: List[:class:`PatchSchema`] (optional)
2858
+ The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
2859
+
2860
+
2861
+ """
2862
+ body = {}
2863
+ if operations is not None:
2864
+ body["Operations"] = [v.as_dict() for v in operations]
2865
+ if schemas is not None:
2866
+ body["schemas"] = [v.value for v in schemas]
2867
+ headers = {
2868
+ "Accept": "application/json",
2869
+ "Content-Type": "application/json",
2870
+ }
2871
+
2872
+ self._api.do(
2873
+ "PATCH",
2874
+ f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}",
2875
+ body=body,
2876
+ headers=headers,
2877
+ )
2878
+
2879
+ def update(
2880
+ self,
2881
+ id: str,
2882
+ *,
2883
+ active: Optional[bool] = None,
2884
+ application_id: Optional[str] = None,
2885
+ display_name: Optional[str] = None,
2886
+ external_id: Optional[str] = None,
2887
+ roles: Optional[List[ComplexValue]] = None,
2888
+ ):
2889
+ """Updates the details of a single service principal.
2890
+
2891
+ This action replaces the existing service principal with the same name.
2892
+
2893
+ :param id: str
2894
+ Databricks service principal ID.
2895
+ :param active: bool (optional)
2896
+ If this user is active
2897
+ :param application_id: str (optional)
2898
+ UUID relating to the service principal
2899
+ :param display_name: str (optional)
2900
+ String that represents a concatenation of given and family names.
2901
+ :param external_id: str (optional)
2902
+ :param roles: List[:class:`ComplexValue`] (optional)
2903
+ Indicates if the group has the admin role.
2904
+
2905
+
2906
+ """
2907
+ body = {}
2908
+ if active is not None:
2909
+ body["active"] = active
2910
+ if application_id is not None:
2911
+ body["applicationId"] = application_id
2912
+ if display_name is not None:
2913
+ body["displayName"] = display_name
2914
+ if external_id is not None:
2915
+ body["externalId"] = external_id
2916
+ if roles is not None:
2917
+ body["roles"] = [v.as_dict() for v in roles]
2918
+ headers = {
2919
+ "Accept": "application/json",
2920
+ "Content-Type": "application/json",
2921
+ }
2922
+
2923
+ self._api.do(
2924
+ "PUT",
2925
+ f"/api/2.0/accounts/{self._api.account_id}/scim/v2/ServicePrincipals/{id}",
2926
+ body=body,
2927
+ headers=headers,
2928
+ )
2929
+
2930
+
2931
+ class AccountUsersV2API:
2932
+ """User identities recognized by Databricks and represented by email addresses.
2933
+
2934
+ Databricks recommends using SCIM provisioning to sync users and groups automatically from your identity
2935
+ provider to your Databricks account. SCIM streamlines onboarding a new employee or team by using your
2936
+ identity provider to create users and groups in Databricks account and give them the proper level of
2937
+ access. When a user leaves your organization or no longer needs access to Databricks account, admins can
2938
+ terminate the user in your identity provider and that user’s account will also be removed from
2939
+ Databricks account. This ensures a consistent offboarding process and prevents unauthorized users from
2940
+ accessing sensitive data."""
2941
+
2942
+ def __init__(self, api_client):
2943
+ self._api = api_client
2944
+
2945
+ def create(
2946
+ self,
2947
+ *,
2948
+ active: Optional[bool] = None,
2949
+ display_name: Optional[str] = None,
2950
+ emails: Optional[List[ComplexValue]] = None,
2951
+ external_id: Optional[str] = None,
2952
+ id: Optional[str] = None,
2953
+ name: Optional[Name] = None,
2954
+ roles: Optional[List[ComplexValue]] = None,
2955
+ user_name: Optional[str] = None,
2956
+ ) -> AccountUser:
2957
+ """Creates a new user in the Databricks account. This new user will also be added to the Databricks
2958
+ account.
2959
+
2960
+ :param active: bool (optional)
2961
+ If this user is active
2962
+ :param display_name: str (optional)
2963
+ String that represents a concatenation of given and family names. For example `John Smith`.
2964
+ :param emails: List[:class:`ComplexValue`] (optional)
2965
+ All the emails associated with the Databricks user.
2966
+ :param external_id: str (optional)
2967
+ External ID is not currently supported. It is reserved for future use.
2968
+ :param id: str (optional)
2969
+ Databricks user ID.
2970
+ :param name: :class:`Name` (optional)
2971
+ :param roles: List[:class:`ComplexValue`] (optional)
2972
+ Indicates if the group has the admin role.
2973
+ :param user_name: str (optional)
2974
+ Email address of the Databricks user.
2975
+
2976
+ :returns: :class:`AccountUser`
2977
+ """
2978
+ body = {}
2979
+ if active is not None:
2980
+ body["active"] = active
2981
+ if display_name is not None:
2982
+ body["displayName"] = display_name
2983
+ if emails is not None:
2984
+ body["emails"] = [v.as_dict() for v in emails]
2985
+ if external_id is not None:
2986
+ body["externalId"] = external_id
2987
+ if id is not None:
2988
+ body["id"] = id
2989
+ if name is not None:
2990
+ body["name"] = name.as_dict()
2991
+ if roles is not None:
2992
+ body["roles"] = [v.as_dict() for v in roles]
2993
+ if user_name is not None:
2994
+ body["userName"] = user_name
2995
+ headers = {
2996
+ "Accept": "application/json",
2997
+ "Content-Type": "application/json",
2998
+ }
2999
+
3000
+ res = self._api.do(
3001
+ "POST", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users", body=body, headers=headers
3002
+ )
3003
+ return AccountUser.from_dict(res)
3004
+
3005
+ def delete(self, id: str):
3006
+ """Deletes a user. Deleting a user from a Databricks account also removes objects associated with the
3007
+ user.
3008
+
3009
+ :param id: str
3010
+ Unique ID for a user in the Databricks account.
3011
+
3012
+
3013
+ """
3014
+
3015
+ headers = {}
3016
+
3017
+ self._api.do("DELETE", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", headers=headers)
3018
+
3019
+ def get(
3020
+ self,
3021
+ id: str,
3022
+ *,
3023
+ attributes: Optional[str] = None,
3024
+ count: Optional[int] = None,
3025
+ excluded_attributes: Optional[str] = None,
3026
+ filter: Optional[str] = None,
3027
+ sort_by: Optional[str] = None,
3028
+ sort_order: Optional[GetSortOrder] = None,
3029
+ start_index: Optional[int] = None,
3030
+ ) -> AccountUser:
3031
+ """Gets information for a specific user in Databricks account.
3032
+
3033
+ :param id: str
3034
+ Unique ID for a user in the Databricks account.
3035
+ :param attributes: str (optional)
3036
+ Comma-separated list of attributes to return in response.
3037
+ :param count: int (optional)
3038
+ Desired number of results per page. Default is 10000.
3039
+ :param excluded_attributes: str (optional)
3040
+ Comma-separated list of attributes to exclude in response.
3041
+ :param filter: str (optional)
3042
+ Query by which the results have to be filtered. Supported operators are equals(`eq`),
3043
+ contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
3044
+ formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
3045
+ only support simple expressions.
3046
+
3047
+ [SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
3048
+ :param sort_by: str (optional)
3049
+ Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
3050
+ `name.givenName`, and `emails`.
3051
+ :param sort_order: :class:`GetSortOrder` (optional)
3052
+ The order to sort the results.
3053
+ :param start_index: int (optional)
3054
+ Specifies the index of the first result. First item is number 1.
3055
+
3056
+ :returns: :class:`AccountUser`
3057
+ """
3058
+
3059
+ query = {}
3060
+ if attributes is not None:
3061
+ query["attributes"] = attributes
3062
+ if count is not None:
3063
+ query["count"] = count
3064
+ if excluded_attributes is not None:
3065
+ query["excludedAttributes"] = excluded_attributes
3066
+ if filter is not None:
3067
+ query["filter"] = filter
3068
+ if sort_by is not None:
3069
+ query["sortBy"] = sort_by
3070
+ if sort_order is not None:
3071
+ query["sortOrder"] = sort_order.value
3072
+ if start_index is not None:
3073
+ query["startIndex"] = start_index
3074
+ headers = {
3075
+ "Accept": "application/json",
3076
+ }
3077
+
3078
+ res = self._api.do(
3079
+ "GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", query=query, headers=headers
3080
+ )
3081
+ return AccountUser.from_dict(res)
3082
+
3083
+ def list(
3084
+ self,
3085
+ *,
3086
+ attributes: Optional[str] = None,
3087
+ count: Optional[int] = None,
3088
+ excluded_attributes: Optional[str] = None,
3089
+ filter: Optional[str] = None,
3090
+ sort_by: Optional[str] = None,
3091
+ sort_order: Optional[ListSortOrder] = None,
3092
+ start_index: Optional[int] = None,
3093
+ ) -> Iterator[AccountUser]:
3094
+ """Gets details for all the users associated with a Databricks account.
3095
+
3096
+ :param attributes: str (optional)
3097
+ Comma-separated list of attributes to return in response.
3098
+ :param count: int (optional)
3099
+ Desired number of results per page. Default is 10000.
3100
+ :param excluded_attributes: str (optional)
3101
+ Comma-separated list of attributes to exclude in response.
3102
+ :param filter: str (optional)
3103
+ Query by which the results have to be filtered. Supported operators are equals(`eq`),
3104
+ contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
3105
+ formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
3106
+ only support simple expressions.
3107
+
3108
+ [SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
3109
+ :param sort_by: str (optional)
3110
+ Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
3111
+ `name.givenName`, and `emails`.
3112
+ :param sort_order: :class:`ListSortOrder` (optional)
3113
+ The order to sort the results.
3114
+ :param start_index: int (optional)
3115
+ Specifies the index of the first result. First item is number 1.
3116
+
3117
+ :returns: Iterator over :class:`AccountUser`
3118
+ """
3119
+
3120
+ query = {}
3121
+ if attributes is not None:
3122
+ query["attributes"] = attributes
3123
+ if count is not None:
3124
+ query["count"] = count
3125
+ if excluded_attributes is not None:
3126
+ query["excludedAttributes"] = excluded_attributes
3127
+ if filter is not None:
3128
+ query["filter"] = filter
3129
+ if sort_by is not None:
3130
+ query["sortBy"] = sort_by
3131
+ if sort_order is not None:
3132
+ query["sortOrder"] = sort_order.value
3133
+ if start_index is not None:
3134
+ query["startIndex"] = start_index
3135
+ headers = {
3136
+ "Accept": "application/json",
3137
+ }
3138
+
3139
+ query["startIndex"] = 1
3140
+ if "count" not in query:
3141
+ query["count"] = 10000
3142
+ while True:
3143
+ json = self._api.do(
3144
+ "GET", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users", query=query, headers=headers
3145
+ )
3146
+ if "Resources" in json:
3147
+ for v in json["Resources"]:
3148
+ yield AccountUser.from_dict(v)
3149
+ if "Resources" not in json or not json["Resources"]:
3150
+ return
3151
+ query["startIndex"] += len(json["Resources"])
3152
+
3153
+ def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
3154
+ """Partially updates a user resource by applying the supplied operations on specific user attributes.
3155
+
3156
+ :param id: str
3157
+ Unique ID in the Databricks workspace.
3158
+ :param operations: List[:class:`Patch`] (optional)
3159
+ :param schemas: List[:class:`PatchSchema`] (optional)
3160
+ The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
3161
+
3162
+
3163
+ """
3164
+ body = {}
3165
+ if operations is not None:
3166
+ body["Operations"] = [v.as_dict() for v in operations]
3167
+ if schemas is not None:
3168
+ body["schemas"] = [v.value for v in schemas]
3169
+ headers = {
3170
+ "Accept": "application/json",
3171
+ "Content-Type": "application/json",
3172
+ }
3173
+
3174
+ self._api.do(
3175
+ "PATCH", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", body=body, headers=headers
3176
+ )
3177
+
3178
+ def update(
3179
+ self,
3180
+ id: str,
3181
+ *,
3182
+ active: Optional[bool] = None,
3183
+ display_name: Optional[str] = None,
3184
+ emails: Optional[List[ComplexValue]] = None,
3185
+ external_id: Optional[str] = None,
3186
+ name: Optional[Name] = None,
3187
+ roles: Optional[List[ComplexValue]] = None,
3188
+ user_name: Optional[str] = None,
3189
+ ):
3190
+ """Replaces a user's information with the data supplied in request.
3191
+
3192
+ :param id: str
3193
+ Databricks user ID.
3194
+ :param active: bool (optional)
3195
+ If this user is active
3196
+ :param display_name: str (optional)
3197
+ String that represents a concatenation of given and family names. For example `John Smith`.
3198
+ :param emails: List[:class:`ComplexValue`] (optional)
3199
+ All the emails associated with the Databricks user.
3200
+ :param external_id: str (optional)
3201
+ External ID is not currently supported. It is reserved for future use.
3202
+ :param name: :class:`Name` (optional)
3203
+ :param roles: List[:class:`ComplexValue`] (optional)
3204
+ Indicates if the group has the admin role.
3205
+ :param user_name: str (optional)
3206
+ Email address of the Databricks user.
3207
+
3208
+
3209
+ """
3210
+ body = {}
3211
+ if active is not None:
3212
+ body["active"] = active
3213
+ if display_name is not None:
3214
+ body["displayName"] = display_name
3215
+ if emails is not None:
3216
+ body["emails"] = [v.as_dict() for v in emails]
3217
+ if external_id is not None:
3218
+ body["externalId"] = external_id
3219
+ if name is not None:
3220
+ body["name"] = name.as_dict()
3221
+ if roles is not None:
3222
+ body["roles"] = [v.as_dict() for v in roles]
3223
+ if user_name is not None:
3224
+ body["userName"] = user_name
3225
+ headers = {
3226
+ "Accept": "application/json",
3227
+ "Content-Type": "application/json",
3228
+ }
3229
+
3230
+ self._api.do("PUT", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", body=body, headers=headers)
3231
+
3232
+
3233
+ class CurrentUserAPI:
3234
+ """This API allows retrieving information about currently authenticated user or service principal."""
3235
+
3236
+ def __init__(self, api_client):
3237
+ self._api = api_client
3238
+
3239
+ def me(self) -> User:
3240
+ """Get details about the current method caller's identity.
3241
+
3242
+
3243
+ :returns: :class:`User`
3244
+ """
3245
+
3246
+ headers = {
3247
+ "Accept": "application/json",
3248
+ }
3249
+
3250
+ res = self._api.do("GET", "/api/2.0/preview/scim/v2/Me", headers=headers)
3251
+ return User.from_dict(res)
3252
+
3253
+
3254
+ class GroupsV2API:
3255
+ """Groups simplify identity management, making it easier to assign access to Databricks workspace, data, and
3256
+ other securable objects.
3257
+
3258
+ It is best practice to assign access to workspaces and access-control policies in Unity Catalog to groups,
3259
+ instead of to users individually. All Databricks workspace identities can be assigned as members of
3260
+ groups, and members inherit permissions that are assigned to their group."""
3261
+
3262
+ def __init__(self, api_client):
3263
+ self._api = api_client
3264
+
3265
+ def create(
3266
+ self,
3267
+ *,
3268
+ display_name: Optional[str] = None,
3269
+ entitlements: Optional[List[ComplexValue]] = None,
3270
+ external_id: Optional[str] = None,
3271
+ groups: Optional[List[ComplexValue]] = None,
3272
+ id: Optional[str] = None,
3273
+ members: Optional[List[ComplexValue]] = None,
3274
+ meta: Optional[ResourceMeta] = None,
3275
+ roles: Optional[List[ComplexValue]] = None,
3276
+ schemas: Optional[List[GroupSchema]] = None,
3277
+ ) -> Group:
3278
+ """Creates a group in the Databricks workspace with a unique name, using the supplied group details.
3279
+
3280
+ :param display_name: str (optional)
3281
+ String that represents a human-readable group name
3282
+ :param entitlements: List[:class:`ComplexValue`] (optional)
3283
+ Entitlements assigned to the group. See [assigning entitlements] for a full list of supported
3284
+ values.
3285
+
3286
+ [assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
3287
+ :param external_id: str (optional)
3288
+ :param groups: List[:class:`ComplexValue`] (optional)
3289
+ :param id: str (optional)
3290
+ Databricks group ID
3291
+ :param members: List[:class:`ComplexValue`] (optional)
3292
+ :param meta: :class:`ResourceMeta` (optional)
3293
+ Container for the group identifier. Workspace local versus account.
3294
+ :param roles: List[:class:`ComplexValue`] (optional)
3295
+ Corresponds to AWS instance profile/arn role.
3296
+ :param schemas: List[:class:`GroupSchema`] (optional)
3297
+ The schema of the group.
3298
+
3299
+ :returns: :class:`Group`
3300
+ """
3301
+ body = {}
3302
+ if display_name is not None:
3303
+ body["displayName"] = display_name
3304
+ if entitlements is not None:
3305
+ body["entitlements"] = [v.as_dict() for v in entitlements]
3306
+ if external_id is not None:
3307
+ body["externalId"] = external_id
3308
+ if groups is not None:
3309
+ body["groups"] = [v.as_dict() for v in groups]
3310
+ if id is not None:
3311
+ body["id"] = id
3312
+ if members is not None:
3313
+ body["members"] = [v.as_dict() for v in members]
3314
+ if meta is not None:
3315
+ body["meta"] = meta.as_dict()
3316
+ if roles is not None:
3317
+ body["roles"] = [v.as_dict() for v in roles]
3318
+ if schemas is not None:
3319
+ body["schemas"] = [v.value for v in schemas]
3320
+ headers = {
3321
+ "Accept": "application/json",
3322
+ "Content-Type": "application/json",
3323
+ }
3324
+
3325
+ res = self._api.do("POST", "/api/2.0/preview/scim/v2/Groups", body=body, headers=headers)
3326
+ return Group.from_dict(res)
3327
+
3328
+ def delete(self, id: str):
3329
+ """Deletes a group from the Databricks workspace.
3330
+
3331
+ :param id: str
3332
+ Unique ID for a group in the Databricks workspace.
3333
+
3334
+
3335
+ """
3336
+
3337
+ headers = {}
3338
+
3339
+ self._api.do("DELETE", f"/api/2.0/preview/scim/v2/Groups/{id}", headers=headers)
3340
+
3341
+ def get(self, id: str) -> Group:
3342
+ """Gets the information for a specific group in the Databricks workspace.
3343
+
3344
+ :param id: str
3345
+ Unique ID for a group in the Databricks workspace.
3346
+
3347
+ :returns: :class:`Group`
3348
+ """
3349
+
3350
+ headers = {
3351
+ "Accept": "application/json",
3352
+ }
3353
+
3354
+ res = self._api.do("GET", f"/api/2.0/preview/scim/v2/Groups/{id}", headers=headers)
3355
+ return Group.from_dict(res)
3356
+
3357
+ def list(
3358
+ self,
3359
+ *,
3360
+ attributes: Optional[str] = None,
3361
+ count: Optional[int] = None,
3362
+ excluded_attributes: Optional[str] = None,
3363
+ filter: Optional[str] = None,
3364
+ sort_by: Optional[str] = None,
3365
+ sort_order: Optional[ListSortOrder] = None,
3366
+ start_index: Optional[int] = None,
3367
+ ) -> Iterator[Group]:
3368
+ """Gets all details of the groups associated with the Databricks workspace.
3369
+
3370
+ :param attributes: str (optional)
3371
+ Comma-separated list of attributes to return in response.
3372
+ :param count: int (optional)
3373
+ Desired number of results per page.
3374
+ :param excluded_attributes: str (optional)
3375
+ Comma-separated list of attributes to exclude in response.
3376
+ :param filter: str (optional)
3377
+ Query by which the results have to be filtered. Supported operators are equals(`eq`),
3378
+ contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
3379
+ formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
3380
+ only support simple expressions.
3381
+
3382
+ [SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
3383
+ :param sort_by: str (optional)
3384
+ Attribute to sort the results.
3385
+ :param sort_order: :class:`ListSortOrder` (optional)
3386
+ The order to sort the results.
3387
+ :param start_index: int (optional)
3388
+ Specifies the index of the first result. First item is number 1.
3389
+
3390
+ :returns: Iterator over :class:`Group`
3391
+ """
3392
+
3393
+ query = {}
3394
+ if attributes is not None:
3395
+ query["attributes"] = attributes
3396
+ if count is not None:
3397
+ query["count"] = count
3398
+ if excluded_attributes is not None:
3399
+ query["excludedAttributes"] = excluded_attributes
3400
+ if filter is not None:
3401
+ query["filter"] = filter
3402
+ if sort_by is not None:
3403
+ query["sortBy"] = sort_by
3404
+ if sort_order is not None:
3405
+ query["sortOrder"] = sort_order.value
3406
+ if start_index is not None:
3407
+ query["startIndex"] = start_index
3408
+ headers = {
3409
+ "Accept": "application/json",
3410
+ }
3411
+
3412
+ query["startIndex"] = 1
3413
+ if "count" not in query:
3414
+ query["count"] = 10000
3415
+ while True:
3416
+ json = self._api.do("GET", "/api/2.0/preview/scim/v2/Groups", query=query, headers=headers)
3417
+ if "Resources" in json:
3418
+ for v in json["Resources"]:
3419
+ yield Group.from_dict(v)
3420
+ if "Resources" not in json or not json["Resources"]:
3421
+ return
3422
+ query["startIndex"] += len(json["Resources"])
3423
+
3424
+ def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
3425
+ """Partially updates the details of a group.
3426
+
3427
+ :param id: str
3428
+ Unique ID in the Databricks workspace.
3429
+ :param operations: List[:class:`Patch`] (optional)
3430
+ :param schemas: List[:class:`PatchSchema`] (optional)
3431
+ The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
3432
+
3433
+
3434
+ """
3435
+ body = {}
3436
+ if operations is not None:
3437
+ body["Operations"] = [v.as_dict() for v in operations]
3438
+ if schemas is not None:
3439
+ body["schemas"] = [v.value for v in schemas]
3440
+ headers = {
3441
+ "Accept": "application/json",
3442
+ "Content-Type": "application/json",
3443
+ }
3444
+
3445
+ self._api.do("PATCH", f"/api/2.0/preview/scim/v2/Groups/{id}", body=body, headers=headers)
3446
+
3447
+ def update(
3448
+ self,
3449
+ id: str,
3450
+ *,
3451
+ display_name: Optional[str] = None,
3452
+ entitlements: Optional[List[ComplexValue]] = None,
3453
+ external_id: Optional[str] = None,
3454
+ groups: Optional[List[ComplexValue]] = None,
3455
+ members: Optional[List[ComplexValue]] = None,
3456
+ meta: Optional[ResourceMeta] = None,
3457
+ roles: Optional[List[ComplexValue]] = None,
3458
+ schemas: Optional[List[GroupSchema]] = None,
3459
+ ):
3460
+ """Updates the details of a group by replacing the entire group entity.
3461
+
3462
+ :param id: str
3463
+ Databricks group ID
3464
+ :param display_name: str (optional)
3465
+ String that represents a human-readable group name
3466
+ :param entitlements: List[:class:`ComplexValue`] (optional)
3467
+ Entitlements assigned to the group. See [assigning entitlements] for a full list of supported
3468
+ values.
3469
+
3470
+ [assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
3471
+ :param external_id: str (optional)
3472
+ :param groups: List[:class:`ComplexValue`] (optional)
3473
+ :param members: List[:class:`ComplexValue`] (optional)
3474
+ :param meta: :class:`ResourceMeta` (optional)
3475
+ Container for the group identifier. Workspace local versus account.
3476
+ :param roles: List[:class:`ComplexValue`] (optional)
3477
+ Corresponds to AWS instance profile/arn role.
3478
+ :param schemas: List[:class:`GroupSchema`] (optional)
3479
+ The schema of the group.
3480
+
3481
+
3482
+ """
3483
+ body = {}
3484
+ if display_name is not None:
3485
+ body["displayName"] = display_name
3486
+ if entitlements is not None:
3487
+ body["entitlements"] = [v.as_dict() for v in entitlements]
3488
+ if external_id is not None:
3489
+ body["externalId"] = external_id
3490
+ if groups is not None:
3491
+ body["groups"] = [v.as_dict() for v in groups]
3492
+ if members is not None:
3493
+ body["members"] = [v.as_dict() for v in members]
3494
+ if meta is not None:
3495
+ body["meta"] = meta.as_dict()
3496
+ if roles is not None:
3497
+ body["roles"] = [v.as_dict() for v in roles]
3498
+ if schemas is not None:
3499
+ body["schemas"] = [v.value for v in schemas]
3500
+ headers = {
3501
+ "Accept": "application/json",
3502
+ "Content-Type": "application/json",
3503
+ }
3504
+
3505
+ self._api.do("PUT", f"/api/2.0/preview/scim/v2/Groups/{id}", body=body, headers=headers)
3506
+
3507
+
3508
+ class PermissionMigrationAPI:
3509
+ """APIs for migrating acl permissions, used only by the ucx tool: https://github.com/databrickslabs/ucx"""
3510
+
3511
+ def __init__(self, api_client):
3512
+ self._api = api_client
3513
+
3514
+ def migrate_permissions(
3515
+ self,
3516
+ workspace_id: int,
3517
+ from_workspace_group_name: str,
3518
+ to_account_group_name: str,
3519
+ *,
3520
+ size: Optional[int] = None,
3521
+ ) -> MigratePermissionsResponse:
3522
+ """Migrate Permissions.
3523
+
3524
+ :param workspace_id: int
3525
+ WorkspaceId of the associated workspace where the permission migration will occur.
3526
+ :param from_workspace_group_name: str
3527
+ The name of the workspace group that permissions will be migrated from.
3528
+ :param to_account_group_name: str
3529
+ The name of the account group that permissions will be migrated to.
3530
+ :param size: int (optional)
3531
+ The maximum number of permissions that will be migrated.
3532
+
3533
+ :returns: :class:`MigratePermissionsResponse`
3534
+ """
3535
+ body = {}
3536
+ if from_workspace_group_name is not None:
3537
+ body["from_workspace_group_name"] = from_workspace_group_name
3538
+ if size is not None:
3539
+ body["size"] = size
3540
+ if to_account_group_name is not None:
3541
+ body["to_account_group_name"] = to_account_group_name
3542
+ if workspace_id is not None:
3543
+ body["workspace_id"] = workspace_id
3544
+ headers = {
3545
+ "Accept": "application/json",
3546
+ "Content-Type": "application/json",
3547
+ }
3548
+
3549
+ res = self._api.do("POST", "/api/2.0/permissionmigration", body=body, headers=headers)
3550
+ return MigratePermissionsResponse.from_dict(res)
3551
+
3552
+
3553
+ class PermissionsAPI:
3554
+ """Permissions API are used to create read, write, edit, update and manage access for various users on
3555
+ different objects and endpoints. * **[Apps permissions](:service:apps)** — Manage which users can manage
3556
+ or use apps. * **[Cluster permissions](:service:clusters)** — Manage which users can manage, restart, or
3557
+ attach to clusters. * **[Cluster policy permissions](:service:clusterpolicies)** — Manage which users
3558
+ can use cluster policies. * **[Delta Live Tables pipeline permissions](:service:pipelines)** — Manage
3559
+ which users can view, manage, run, cancel, or own a Delta Live Tables pipeline. * **[Job
3560
+ permissions](:service:jobs)** — Manage which users can view, manage, trigger, cancel, or own a job. *
3561
+ **[MLflow experiment permissions](:service:experiments)** — Manage which users can read, edit, or manage
3562
+ MLflow experiments. * **[MLflow registered model permissions](:service:modelregistry)** — Manage which
3563
+ users can read, edit, or manage MLflow registered models. * **[Instance Pool
3564
+ permissions](:service:instancepools)** — Manage which users can manage or attach to pools. * **[Repo
3565
+ permissions](repos)** — Manage which users can read, run, edit, or manage a repo. * **[Serving endpoint
3566
+ permissions](:service:servingendpoints)** — Manage which users can view, query, or manage a serving
3567
+ endpoint. * **[SQL warehouse permissions](:service:warehouses)** — Manage which users can use or manage
3568
+ SQL warehouses. * **[Token permissions](:service:tokenmanagement)** — Manage which users can create or
3569
+ use tokens. * **[Workspace object permissions](:service:workspace)** — Manage which users can read, run,
3570
+ edit, or manage alerts, dbsql-dashboards, directories, files, notebooks and queries. For the mapping of
3571
+ the required permissions for specific actions or abilities and other important information, see [Access
3572
+ Control]. Note that to manage access control on service principals, use **[Account Access Control
3573
+ Proxy](:service:accountaccesscontrolproxy)**.
3574
+
3575
+ [Access Control]: https://docs.databricks.com/security/auth-authz/access-control/index.html"""
3576
+
3577
+ def __init__(self, api_client):
3578
+ self._api = api_client
3579
+
3580
+ def get(self, request_object_type: str, request_object_id: str) -> ObjectPermissions:
3581
+ """Gets the permissions of an object. Objects can inherit permissions from their parent objects or root
3582
+ object.
3583
+
3584
+ :param request_object_type: str
3585
+ The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
3586
+ clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files, genie,
3587
+ instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
3588
+ warehouses.
3589
+ :param request_object_id: str
3590
+ The id of the request object.
3591
+
3592
+ :returns: :class:`ObjectPermissions`
3593
+ """
3594
+
3595
+ headers = {
3596
+ "Accept": "application/json",
3597
+ }
3598
+
3599
+ res = self._api.do("GET", f"/api/2.0/permissions/{request_object_type}/{request_object_id}", headers=headers)
3600
+ return ObjectPermissions.from_dict(res)
3601
+
3602
+ def get_permission_levels(self, request_object_type: str, request_object_id: str) -> GetPermissionLevelsResponse:
3603
+ """Gets the permission levels that a user can have on an object.
3604
+
3605
+ :param request_object_type: str
3606
+ The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
3607
+ clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files, genie,
3608
+ instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
3609
+ warehouses.
3610
+ :param request_object_id: str
3611
+
3612
+ :returns: :class:`GetPermissionLevelsResponse`
3613
+ """
3614
+
3615
+ headers = {
3616
+ "Accept": "application/json",
3617
+ }
3618
+
3619
+ res = self._api.do(
3620
+ "GET", f"/api/2.0/permissions/{request_object_type}/{request_object_id}/permissionLevels", headers=headers
3621
+ )
3622
+ return GetPermissionLevelsResponse.from_dict(res)
3623
+
3624
+ def set(
3625
+ self,
3626
+ request_object_type: str,
3627
+ request_object_id: str,
3628
+ *,
3629
+ access_control_list: Optional[List[AccessControlRequest]] = None,
3630
+ ) -> ObjectPermissions:
3631
+ """Sets permissions on an object, replacing existing permissions if they exist. Deletes all direct
3632
+ permissions if none are specified. Objects can inherit permissions from their parent objects or root
3633
+ object.
3634
+
3635
+ :param request_object_type: str
3636
+ The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
3637
+ clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files, genie,
3638
+ instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
3639
+ warehouses.
3640
+ :param request_object_id: str
3641
+ The id of the request object.
3642
+ :param access_control_list: List[:class:`AccessControlRequest`] (optional)
3643
+
3644
+ :returns: :class:`ObjectPermissions`
3645
+ """
3646
+ body = {}
3647
+ if access_control_list is not None:
3648
+ body["access_control_list"] = [v.as_dict() for v in access_control_list]
3649
+ headers = {
3650
+ "Accept": "application/json",
3651
+ "Content-Type": "application/json",
3652
+ }
3653
+
3654
+ res = self._api.do(
3655
+ "PUT", f"/api/2.0/permissions/{request_object_type}/{request_object_id}", body=body, headers=headers
3656
+ )
3657
+ return ObjectPermissions.from_dict(res)
3658
+
3659
+ def update(
3660
+ self,
3661
+ request_object_type: str,
3662
+ request_object_id: str,
3663
+ *,
3664
+ access_control_list: Optional[List[AccessControlRequest]] = None,
3665
+ ) -> ObjectPermissions:
3666
+ """Updates the permissions on an object. Objects can inherit permissions from their parent objects or
3667
+ root object.
3668
+
3669
+ :param request_object_type: str
3670
+ The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
3671
+ clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files, genie,
3672
+ instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
3673
+ warehouses.
3674
+ :param request_object_id: str
3675
+ The id of the request object.
3676
+ :param access_control_list: List[:class:`AccessControlRequest`] (optional)
3677
+
3678
+ :returns: :class:`ObjectPermissions`
3679
+ """
3680
+ body = {}
3681
+ if access_control_list is not None:
3682
+ body["access_control_list"] = [v.as_dict() for v in access_control_list]
3683
+ headers = {
3684
+ "Accept": "application/json",
3685
+ "Content-Type": "application/json",
3686
+ }
3687
+
3688
+ res = self._api.do(
3689
+ "PATCH", f"/api/2.0/permissions/{request_object_type}/{request_object_id}", body=body, headers=headers
3690
+ )
3691
+ return ObjectPermissions.from_dict(res)
3692
+
3693
+
3694
+ class ServicePrincipalsV2API:
3695
+ """Identities for use with jobs, automated tools, and systems such as scripts, apps, and CI/CD platforms.
3696
+ Databricks recommends creating service principals to run production jobs or modify production data. If all
3697
+ processes that act on production data run with service principals, interactive users do not need any
3698
+ write, delete, or modify privileges in production. This eliminates the risk of a user overwriting
3699
+ production data by accident."""
3700
+
3701
+ def __init__(self, api_client):
3702
+ self._api = api_client
3703
+
3704
+ def create(
3705
+ self,
3706
+ *,
3707
+ active: Optional[bool] = None,
3708
+ application_id: Optional[str] = None,
3709
+ display_name: Optional[str] = None,
3710
+ entitlements: Optional[List[ComplexValue]] = None,
3711
+ external_id: Optional[str] = None,
3712
+ groups: Optional[List[ComplexValue]] = None,
3713
+ id: Optional[str] = None,
3714
+ roles: Optional[List[ComplexValue]] = None,
3715
+ schemas: Optional[List[ServicePrincipalSchema]] = None,
3716
+ ) -> ServicePrincipal:
3717
+ """Creates a new service principal in the Databricks workspace.
3718
+
3719
+ :param active: bool (optional)
3720
+ If this user is active
3721
+ :param application_id: str (optional)
3722
+ UUID relating to the service principal
3723
+ :param display_name: str (optional)
3724
+ String that represents a concatenation of given and family names.
3725
+ :param entitlements: List[:class:`ComplexValue`] (optional)
3726
+ Entitlements assigned to the service principal. See [assigning entitlements] for a full list of
3727
+ supported values.
3728
+
3729
+ [assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
3730
+ :param external_id: str (optional)
3731
+ :param groups: List[:class:`ComplexValue`] (optional)
3732
+ :param id: str (optional)
3733
+ Databricks service principal ID.
3734
+ :param roles: List[:class:`ComplexValue`] (optional)
3735
+ Corresponds to AWS instance profile/arn role.
3736
+ :param schemas: List[:class:`ServicePrincipalSchema`] (optional)
3737
+ The schema of the List response.
3738
+
3739
+ :returns: :class:`ServicePrincipal`
3740
+ """
3741
+ body = {}
3742
+ if active is not None:
3743
+ body["active"] = active
3744
+ if application_id is not None:
3745
+ body["applicationId"] = application_id
3746
+ if display_name is not None:
3747
+ body["displayName"] = display_name
3748
+ if entitlements is not None:
3749
+ body["entitlements"] = [v.as_dict() for v in entitlements]
3750
+ if external_id is not None:
3751
+ body["externalId"] = external_id
3752
+ if groups is not None:
3753
+ body["groups"] = [v.as_dict() for v in groups]
3754
+ if id is not None:
3755
+ body["id"] = id
3756
+ if roles is not None:
3757
+ body["roles"] = [v.as_dict() for v in roles]
3758
+ if schemas is not None:
3759
+ body["schemas"] = [v.value for v in schemas]
3760
+ headers = {
3761
+ "Accept": "application/json",
3762
+ "Content-Type": "application/json",
3763
+ }
3764
+
3765
+ res = self._api.do("POST", "/api/2.0/preview/scim/v2/ServicePrincipals", body=body, headers=headers)
3766
+ return ServicePrincipal.from_dict(res)
3767
+
3768
+ def delete(self, id: str):
3769
+ """Delete a single service principal in the Databricks workspace.
3770
+
3771
+ :param id: str
3772
+ Unique ID for a service principal in the Databricks workspace.
3773
+
3774
+
3775
+ """
3776
+
3777
+ headers = {}
3778
+
3779
+ self._api.do("DELETE", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", headers=headers)
3780
+
3781
+ def get(self, id: str) -> ServicePrincipal:
3782
+ """Gets the details for a single service principal define in the Databricks workspace.
3783
+
3784
+ :param id: str
3785
+ Unique ID for a service principal in the Databricks workspace.
3786
+
3787
+ :returns: :class:`ServicePrincipal`
3788
+ """
3789
+
3790
+ headers = {
3791
+ "Accept": "application/json",
3792
+ }
3793
+
3794
+ res = self._api.do("GET", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", headers=headers)
3795
+ return ServicePrincipal.from_dict(res)
3796
+
3797
+ def list(
3798
+ self,
3799
+ *,
3800
+ attributes: Optional[str] = None,
3801
+ count: Optional[int] = None,
3802
+ excluded_attributes: Optional[str] = None,
3803
+ filter: Optional[str] = None,
3804
+ sort_by: Optional[str] = None,
3805
+ sort_order: Optional[ListSortOrder] = None,
3806
+ start_index: Optional[int] = None,
3807
+ ) -> Iterator[ServicePrincipal]:
3808
+ """Gets the set of service principals associated with a Databricks workspace.
3809
+
3810
+ :param attributes: str (optional)
3811
+ Comma-separated list of attributes to return in response.
3812
+ :param count: int (optional)
3813
+ Desired number of results per page.
3814
+ :param excluded_attributes: str (optional)
3815
+ Comma-separated list of attributes to exclude in response.
3816
+ :param filter: str (optional)
3817
+ Query by which the results have to be filtered. Supported operators are equals(`eq`),
3818
+ contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
3819
+ formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
3820
+ only support simple expressions.
3821
+
3822
+ [SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
3823
+ :param sort_by: str (optional)
3824
+ Attribute to sort the results.
3825
+ :param sort_order: :class:`ListSortOrder` (optional)
3826
+ The order to sort the results.
3827
+ :param start_index: int (optional)
3828
+ Specifies the index of the first result. First item is number 1.
3829
+
3830
+ :returns: Iterator over :class:`ServicePrincipal`
3831
+ """
3832
+
3833
+ query = {}
3834
+ if attributes is not None:
3835
+ query["attributes"] = attributes
3836
+ if count is not None:
3837
+ query["count"] = count
3838
+ if excluded_attributes is not None:
3839
+ query["excludedAttributes"] = excluded_attributes
3840
+ if filter is not None:
3841
+ query["filter"] = filter
3842
+ if sort_by is not None:
3843
+ query["sortBy"] = sort_by
3844
+ if sort_order is not None:
3845
+ query["sortOrder"] = sort_order.value
3846
+ if start_index is not None:
3847
+ query["startIndex"] = start_index
3848
+ headers = {
3849
+ "Accept": "application/json",
3850
+ }
3851
+
3852
+ query["startIndex"] = 1
3853
+ if "count" not in query:
3854
+ query["count"] = 10000
3855
+ while True:
3856
+ json = self._api.do("GET", "/api/2.0/preview/scim/v2/ServicePrincipals", query=query, headers=headers)
3857
+ if "Resources" in json:
3858
+ for v in json["Resources"]:
3859
+ yield ServicePrincipal.from_dict(v)
3860
+ if "Resources" not in json or not json["Resources"]:
3861
+ return
3862
+ query["startIndex"] += len(json["Resources"])
3863
+
3864
+ def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
3865
+ """Partially updates the details of a single service principal in the Databricks workspace.
3866
+
3867
+ :param id: str
3868
+ Unique ID in the Databricks workspace.
3869
+ :param operations: List[:class:`Patch`] (optional)
3870
+ :param schemas: List[:class:`PatchSchema`] (optional)
3871
+ The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
3872
+
3873
+
3874
+ """
3875
+ body = {}
3876
+ if operations is not None:
3877
+ body["Operations"] = [v.as_dict() for v in operations]
3878
+ if schemas is not None:
3879
+ body["schemas"] = [v.value for v in schemas]
3880
+ headers = {
3881
+ "Accept": "application/json",
3882
+ "Content-Type": "application/json",
3883
+ }
3884
+
3885
+ self._api.do("PATCH", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", body=body, headers=headers)
3886
+
3887
+ def update(
3888
+ self,
3889
+ id: str,
3890
+ *,
3891
+ active: Optional[bool] = None,
3892
+ application_id: Optional[str] = None,
3893
+ display_name: Optional[str] = None,
3894
+ entitlements: Optional[List[ComplexValue]] = None,
3895
+ external_id: Optional[str] = None,
3896
+ groups: Optional[List[ComplexValue]] = None,
3897
+ roles: Optional[List[ComplexValue]] = None,
3898
+ schemas: Optional[List[ServicePrincipalSchema]] = None,
3899
+ ):
3900
+ """Updates the details of a single service principal.
3901
+
3902
+ This action replaces the existing service principal with the same name.
3903
+
3904
+ :param id: str
3905
+ Databricks service principal ID.
3906
+ :param active: bool (optional)
3907
+ If this user is active
3908
+ :param application_id: str (optional)
3909
+ UUID relating to the service principal
3910
+ :param display_name: str (optional)
3911
+ String that represents a concatenation of given and family names.
3912
+ :param entitlements: List[:class:`ComplexValue`] (optional)
3913
+ Entitlements assigned to the service principal. See [assigning entitlements] for a full list of
3914
+ supported values.
3915
+
3916
+ [assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
3917
+ :param external_id: str (optional)
3918
+ :param groups: List[:class:`ComplexValue`] (optional)
3919
+ :param roles: List[:class:`ComplexValue`] (optional)
3920
+ Corresponds to AWS instance profile/arn role.
3921
+ :param schemas: List[:class:`ServicePrincipalSchema`] (optional)
3922
+ The schema of the List response.
3923
+
3924
+
3925
+ """
3926
+ body = {}
3927
+ if active is not None:
3928
+ body["active"] = active
3929
+ if application_id is not None:
3930
+ body["applicationId"] = application_id
3931
+ if display_name is not None:
3932
+ body["displayName"] = display_name
3933
+ if entitlements is not None:
3934
+ body["entitlements"] = [v.as_dict() for v in entitlements]
3935
+ if external_id is not None:
3936
+ body["externalId"] = external_id
3937
+ if groups is not None:
3938
+ body["groups"] = [v.as_dict() for v in groups]
3939
+ if roles is not None:
3940
+ body["roles"] = [v.as_dict() for v in roles]
3941
+ if schemas is not None:
3942
+ body["schemas"] = [v.value for v in schemas]
3943
+ headers = {
3944
+ "Accept": "application/json",
3945
+ "Content-Type": "application/json",
3946
+ }
3947
+
3948
+ self._api.do("PUT", f"/api/2.0/preview/scim/v2/ServicePrincipals/{id}", body=body, headers=headers)
3949
+
3950
+
3951
+ class UsersV2API:
3952
+ """User identities recognized by Databricks and represented by email addresses.
3953
+
3954
+ Databricks recommends using SCIM provisioning to sync users and groups automatically from your identity
3955
+ provider to your Databricks workspace. SCIM streamlines onboarding a new employee or team by using your
3956
+ identity provider to create users and groups in Databricks workspace and give them the proper level of
3957
+ access. When a user leaves your organization or no longer needs access to Databricks workspace, admins can
3958
+ terminate the user in your identity provider and that user’s account will also be removed from
3959
+ Databricks workspace. This ensures a consistent offboarding process and prevents unauthorized users from
3960
+ accessing sensitive data."""
3961
+
3962
+ def __init__(self, api_client):
3963
+ self._api = api_client
3964
+
3965
+ def create(
3966
+ self,
3967
+ *,
3968
+ active: Optional[bool] = None,
3969
+ display_name: Optional[str] = None,
3970
+ emails: Optional[List[ComplexValue]] = None,
3971
+ entitlements: Optional[List[ComplexValue]] = None,
3972
+ external_id: Optional[str] = None,
3973
+ groups: Optional[List[ComplexValue]] = None,
3974
+ id: Optional[str] = None,
3975
+ name: Optional[Name] = None,
3976
+ roles: Optional[List[ComplexValue]] = None,
3977
+ schemas: Optional[List[UserSchema]] = None,
3978
+ user_name: Optional[str] = None,
3979
+ ) -> User:
3980
+ """Creates a new user in the Databricks workspace. This new user will also be added to the Databricks
3981
+ account.
3982
+
3983
+ :param active: bool (optional)
3984
+ If this user is active
3985
+ :param display_name: str (optional)
3986
+ String that represents a concatenation of given and family names. For example `John Smith`. This
3987
+ field cannot be updated through the Workspace SCIM APIs when [identity federation is enabled]. Use
3988
+ Account SCIM APIs to update `displayName`.
3989
+
3990
+ [identity federation is enabled]: https://docs.databricks.com/administration-guide/users-groups/best-practices.html#enable-identity-federation
3991
+ :param emails: List[:class:`ComplexValue`] (optional)
3992
+ All the emails associated with the Databricks user.
3993
+ :param entitlements: List[:class:`ComplexValue`] (optional)
3994
+ Entitlements assigned to the user. See [assigning entitlements] for a full list of supported values.
3995
+
3996
+ [assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
3997
+ :param external_id: str (optional)
3998
+ External ID is not currently supported. It is reserved for future use.
3999
+ :param groups: List[:class:`ComplexValue`] (optional)
4000
+ :param id: str (optional)
4001
+ Databricks user ID.
4002
+ :param name: :class:`Name` (optional)
4003
+ :param roles: List[:class:`ComplexValue`] (optional)
4004
+ Corresponds to AWS instance profile/arn role.
4005
+ :param schemas: List[:class:`UserSchema`] (optional)
4006
+ The schema of the user.
4007
+ :param user_name: str (optional)
4008
+ Email address of the Databricks user.
4009
+
4010
+ :returns: :class:`User`
4011
+ """
4012
+ body = {}
4013
+ if active is not None:
4014
+ body["active"] = active
4015
+ if display_name is not None:
4016
+ body["displayName"] = display_name
4017
+ if emails is not None:
4018
+ body["emails"] = [v.as_dict() for v in emails]
4019
+ if entitlements is not None:
4020
+ body["entitlements"] = [v.as_dict() for v in entitlements]
4021
+ if external_id is not None:
4022
+ body["externalId"] = external_id
4023
+ if groups is not None:
4024
+ body["groups"] = [v.as_dict() for v in groups]
4025
+ if id is not None:
4026
+ body["id"] = id
4027
+ if name is not None:
4028
+ body["name"] = name.as_dict()
4029
+ if roles is not None:
4030
+ body["roles"] = [v.as_dict() for v in roles]
4031
+ if schemas is not None:
4032
+ body["schemas"] = [v.value for v in schemas]
4033
+ if user_name is not None:
4034
+ body["userName"] = user_name
4035
+ headers = {
4036
+ "Accept": "application/json",
4037
+ "Content-Type": "application/json",
4038
+ }
4039
+
4040
+ res = self._api.do("POST", "/api/2.0/preview/scim/v2/Users", body=body, headers=headers)
4041
+ return User.from_dict(res)
4042
+
4043
+ def delete(self, id: str):
4044
+ """Deletes a user. Deleting a user from a Databricks workspace also removes objects associated with the
4045
+ user.
4046
+
4047
+ :param id: str
4048
+ Unique ID for a user in the Databricks workspace.
4049
+
4050
+
4051
+ """
4052
+
4053
+ headers = {}
4054
+
4055
+ self._api.do("DELETE", f"/api/2.0/preview/scim/v2/Users/{id}", headers=headers)
4056
+
4057
+ def get(
4058
+ self,
4059
+ id: str,
4060
+ *,
4061
+ attributes: Optional[str] = None,
4062
+ count: Optional[int] = None,
4063
+ excluded_attributes: Optional[str] = None,
4064
+ filter: Optional[str] = None,
4065
+ sort_by: Optional[str] = None,
4066
+ sort_order: Optional[GetSortOrder] = None,
4067
+ start_index: Optional[int] = None,
4068
+ ) -> User:
4069
+ """Gets information for a specific user in Databricks workspace.
4070
+
4071
+ :param id: str
4072
+ Unique ID for a user in the Databricks workspace.
4073
+ :param attributes: str (optional)
4074
+ Comma-separated list of attributes to return in response.
4075
+ :param count: int (optional)
4076
+ Desired number of results per page.
4077
+ :param excluded_attributes: str (optional)
4078
+ Comma-separated list of attributes to exclude in response.
4079
+ :param filter: str (optional)
4080
+ Query by which the results have to be filtered. Supported operators are equals(`eq`),
4081
+ contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
4082
+ formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
4083
+ only support simple expressions.
4084
+
4085
+ [SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
4086
+ :param sort_by: str (optional)
4087
+ Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
4088
+ `name.givenName`, and `emails`.
4089
+ :param sort_order: :class:`GetSortOrder` (optional)
4090
+ The order to sort the results.
4091
+ :param start_index: int (optional)
4092
+ Specifies the index of the first result. First item is number 1.
4093
+
4094
+ :returns: :class:`User`
4095
+ """
4096
+
4097
+ query = {}
4098
+ if attributes is not None:
4099
+ query["attributes"] = attributes
4100
+ if count is not None:
4101
+ query["count"] = count
4102
+ if excluded_attributes is not None:
4103
+ query["excludedAttributes"] = excluded_attributes
4104
+ if filter is not None:
4105
+ query["filter"] = filter
4106
+ if sort_by is not None:
4107
+ query["sortBy"] = sort_by
4108
+ if sort_order is not None:
4109
+ query["sortOrder"] = sort_order.value
4110
+ if start_index is not None:
4111
+ query["startIndex"] = start_index
4112
+ headers = {
4113
+ "Accept": "application/json",
4114
+ }
4115
+
4116
+ res = self._api.do("GET", f"/api/2.0/preview/scim/v2/Users/{id}", query=query, headers=headers)
4117
+ return User.from_dict(res)
4118
+
4119
+ def get_permission_levels(self) -> GetPasswordPermissionLevelsResponse:
4120
+ """Gets the permission levels that a user can have on an object.
4121
+
4122
+
4123
+ :returns: :class:`GetPasswordPermissionLevelsResponse`
4124
+ """
4125
+
4126
+ headers = {
4127
+ "Accept": "application/json",
4128
+ }
4129
+
4130
+ res = self._api.do("GET", "/api/2.0/permissions/authorization/passwords/permissionLevels", headers=headers)
4131
+ return GetPasswordPermissionLevelsResponse.from_dict(res)
4132
+
4133
+ def get_permissions(self) -> PasswordPermissions:
4134
+ """Gets the permissions of all passwords. Passwords can inherit permissions from their root object.
4135
+
4136
+
4137
+ :returns: :class:`PasswordPermissions`
4138
+ """
4139
+
4140
+ headers = {
4141
+ "Accept": "application/json",
4142
+ }
4143
+
4144
+ res = self._api.do("GET", "/api/2.0/permissions/authorization/passwords", headers=headers)
4145
+ return PasswordPermissions.from_dict(res)
4146
+
4147
+ def list(
4148
+ self,
4149
+ *,
4150
+ attributes: Optional[str] = None,
4151
+ count: Optional[int] = None,
4152
+ excluded_attributes: Optional[str] = None,
4153
+ filter: Optional[str] = None,
4154
+ sort_by: Optional[str] = None,
4155
+ sort_order: Optional[ListSortOrder] = None,
4156
+ start_index: Optional[int] = None,
4157
+ ) -> Iterator[User]:
4158
+ """Gets details for all the users associated with a Databricks workspace.
4159
+
4160
+ :param attributes: str (optional)
4161
+ Comma-separated list of attributes to return in response.
4162
+ :param count: int (optional)
4163
+ Desired number of results per page.
4164
+ :param excluded_attributes: str (optional)
4165
+ Comma-separated list of attributes to exclude in response.
4166
+ :param filter: str (optional)
4167
+ Query by which the results have to be filtered. Supported operators are equals(`eq`),
4168
+ contains(`co`), starts with(`sw`) and not equals(`ne`). Additionally, simple expressions can be
4169
+ formed using logical operators - `and` and `or`. The [SCIM RFC] has more details but we currently
4170
+ only support simple expressions.
4171
+
4172
+ [SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
4173
+ :param sort_by: str (optional)
4174
+ Attribute to sort the results. Multi-part paths are supported. For example, `userName`,
4175
+ `name.givenName`, and `emails`.
4176
+ :param sort_order: :class:`ListSortOrder` (optional)
4177
+ The order to sort the results.
4178
+ :param start_index: int (optional)
4179
+ Specifies the index of the first result. First item is number 1.
4180
+
4181
+ :returns: Iterator over :class:`User`
4182
+ """
4183
+
4184
+ query = {}
4185
+ if attributes is not None:
4186
+ query["attributes"] = attributes
4187
+ if count is not None:
4188
+ query["count"] = count
4189
+ if excluded_attributes is not None:
4190
+ query["excludedAttributes"] = excluded_attributes
4191
+ if filter is not None:
4192
+ query["filter"] = filter
4193
+ if sort_by is not None:
4194
+ query["sortBy"] = sort_by
4195
+ if sort_order is not None:
4196
+ query["sortOrder"] = sort_order.value
4197
+ if start_index is not None:
4198
+ query["startIndex"] = start_index
4199
+ headers = {
4200
+ "Accept": "application/json",
4201
+ }
4202
+
4203
+ query["startIndex"] = 1
4204
+ if "count" not in query:
4205
+ query["count"] = 10000
4206
+ while True:
4207
+ json = self._api.do("GET", "/api/2.0/preview/scim/v2/Users", query=query, headers=headers)
4208
+ if "Resources" in json:
4209
+ for v in json["Resources"]:
4210
+ yield User.from_dict(v)
4211
+ if "Resources" not in json or not json["Resources"]:
4212
+ return
4213
+ query["startIndex"] += len(json["Resources"])
4214
+
4215
+ def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
4216
+ """Partially updates a user resource by applying the supplied operations on specific user attributes.
4217
+
4218
+ :param id: str
4219
+ Unique ID in the Databricks workspace.
4220
+ :param operations: List[:class:`Patch`] (optional)
4221
+ :param schemas: List[:class:`PatchSchema`] (optional)
4222
+ The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
4223
+
4224
+
4225
+ """
4226
+ body = {}
4227
+ if operations is not None:
4228
+ body["Operations"] = [v.as_dict() for v in operations]
4229
+ if schemas is not None:
4230
+ body["schemas"] = [v.value for v in schemas]
4231
+ headers = {
4232
+ "Accept": "application/json",
4233
+ "Content-Type": "application/json",
4234
+ }
4235
+
4236
+ self._api.do("PATCH", f"/api/2.0/preview/scim/v2/Users/{id}", body=body, headers=headers)
4237
+
4238
+ def set_permissions(
4239
+ self, *, access_control_list: Optional[List[PasswordAccessControlRequest]] = None
4240
+ ) -> PasswordPermissions:
4241
+ """Sets permissions on an object, replacing existing permissions if they exist. Deletes all direct
4242
+ permissions if none are specified. Objects can inherit permissions from their root object.
4243
+
4244
+ :param access_control_list: List[:class:`PasswordAccessControlRequest`] (optional)
4245
+
4246
+ :returns: :class:`PasswordPermissions`
4247
+ """
4248
+ body = {}
4249
+ if access_control_list is not None:
4250
+ body["access_control_list"] = [v.as_dict() for v in access_control_list]
4251
+ headers = {
4252
+ "Accept": "application/json",
4253
+ "Content-Type": "application/json",
4254
+ }
4255
+
4256
+ res = self._api.do("PUT", "/api/2.0/permissions/authorization/passwords", body=body, headers=headers)
4257
+ return PasswordPermissions.from_dict(res)
4258
+
4259
+ def update(
4260
+ self,
4261
+ id: str,
4262
+ *,
4263
+ active: Optional[bool] = None,
4264
+ display_name: Optional[str] = None,
4265
+ emails: Optional[List[ComplexValue]] = None,
4266
+ entitlements: Optional[List[ComplexValue]] = None,
4267
+ external_id: Optional[str] = None,
4268
+ groups: Optional[List[ComplexValue]] = None,
4269
+ name: Optional[Name] = None,
4270
+ roles: Optional[List[ComplexValue]] = None,
4271
+ schemas: Optional[List[UserSchema]] = None,
4272
+ user_name: Optional[str] = None,
4273
+ ):
4274
+ """Replaces a user's information with the data supplied in request.
4275
+
4276
+ :param id: str
4277
+ Databricks user ID.
4278
+ :param active: bool (optional)
4279
+ If this user is active
4280
+ :param display_name: str (optional)
4281
+ String that represents a concatenation of given and family names. For example `John Smith`. This
4282
+ field cannot be updated through the Workspace SCIM APIs when [identity federation is enabled]. Use
4283
+ Account SCIM APIs to update `displayName`.
4284
+
4285
+ [identity federation is enabled]: https://docs.databricks.com/administration-guide/users-groups/best-practices.html#enable-identity-federation
4286
+ :param emails: List[:class:`ComplexValue`] (optional)
4287
+ All the emails associated with the Databricks user.
4288
+ :param entitlements: List[:class:`ComplexValue`] (optional)
4289
+ Entitlements assigned to the user. See [assigning entitlements] for a full list of supported values.
4290
+
4291
+ [assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
4292
+ :param external_id: str (optional)
4293
+ External ID is not currently supported. It is reserved for future use.
4294
+ :param groups: List[:class:`ComplexValue`] (optional)
4295
+ :param name: :class:`Name` (optional)
4296
+ :param roles: List[:class:`ComplexValue`] (optional)
4297
+ Corresponds to AWS instance profile/arn role.
4298
+ :param schemas: List[:class:`UserSchema`] (optional)
4299
+ The schema of the user.
4300
+ :param user_name: str (optional)
4301
+ Email address of the Databricks user.
4302
+
4303
+
4304
+ """
4305
+ body = {}
4306
+ if active is not None:
4307
+ body["active"] = active
4308
+ if display_name is not None:
4309
+ body["displayName"] = display_name
4310
+ if emails is not None:
4311
+ body["emails"] = [v.as_dict() for v in emails]
4312
+ if entitlements is not None:
4313
+ body["entitlements"] = [v.as_dict() for v in entitlements]
4314
+ if external_id is not None:
4315
+ body["externalId"] = external_id
4316
+ if groups is not None:
4317
+ body["groups"] = [v.as_dict() for v in groups]
4318
+ if name is not None:
4319
+ body["name"] = name.as_dict()
4320
+ if roles is not None:
4321
+ body["roles"] = [v.as_dict() for v in roles]
4322
+ if schemas is not None:
4323
+ body["schemas"] = [v.value for v in schemas]
4324
+ if user_name is not None:
4325
+ body["userName"] = user_name
4326
+ headers = {
4327
+ "Accept": "application/json",
4328
+ "Content-Type": "application/json",
4329
+ }
4330
+
4331
+ self._api.do("PUT", f"/api/2.0/preview/scim/v2/Users/{id}", body=body, headers=headers)
4332
+
4333
+ def update_permissions(
4334
+ self, *, access_control_list: Optional[List[PasswordAccessControlRequest]] = None
4335
+ ) -> PasswordPermissions:
4336
+ """Updates the permissions on all passwords. Passwords can inherit permissions from their root object.
4337
+
4338
+ :param access_control_list: List[:class:`PasswordAccessControlRequest`] (optional)
4339
+
4340
+ :returns: :class:`PasswordPermissions`
4341
+ """
4342
+ body = {}
4343
+ if access_control_list is not None:
4344
+ body["access_control_list"] = [v.as_dict() for v in access_control_list]
4345
+ headers = {
4346
+ "Accept": "application/json",
4347
+ "Content-Type": "application/json",
4348
+ }
4349
+
4350
+ res = self._api.do("PATCH", "/api/2.0/permissions/authorization/passwords", body=body, headers=headers)
4351
+ return PasswordPermissions.from_dict(res)
4352
+
4353
+
4354
+ class WorkspaceAssignmentAPI:
4355
+ """The Workspace Permission Assignment API allows you to manage workspace permissions for principals in your
4356
+ account."""
4357
+
4358
+ def __init__(self, api_client):
4359
+ self._api = api_client
4360
+
4361
+ def delete(self, workspace_id: int, principal_id: int):
4362
+ """Deletes the workspace permissions assignment in a given account and workspace for the specified
4363
+ principal.
4364
+
4365
+ :param workspace_id: int
4366
+ The workspace ID for the account.
4367
+ :param principal_id: int
4368
+ The ID of the user, service principal, or group.
4369
+
4370
+
4371
+ """
4372
+
4373
+ headers = {
4374
+ "Accept": "application/json",
4375
+ }
4376
+
4377
+ self._api.do(
4378
+ "DELETE",
4379
+ f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments/principals/{principal_id}",
4380
+ headers=headers,
4381
+ )
4382
+
4383
+ def get(self, workspace_id: int) -> WorkspacePermissions:
4384
+ """Get an array of workspace permissions for the specified account and workspace.
4385
+
4386
+ :param workspace_id: int
4387
+ The workspace ID.
4388
+
4389
+ :returns: :class:`WorkspacePermissions`
4390
+ """
4391
+
4392
+ headers = {
4393
+ "Accept": "application/json",
4394
+ }
4395
+
4396
+ res = self._api.do(
4397
+ "GET",
4398
+ f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments/permissions",
4399
+ headers=headers,
4400
+ )
4401
+ return WorkspacePermissions.from_dict(res)
4402
+
4403
+ def list(self, workspace_id: int) -> Iterator[PermissionAssignment]:
4404
+ """Get the permission assignments for the specified Databricks account and Databricks workspace.
4405
+
4406
+ :param workspace_id: int
4407
+ The workspace ID for the account.
4408
+
4409
+ :returns: Iterator over :class:`PermissionAssignment`
4410
+ """
4411
+
4412
+ headers = {
4413
+ "Accept": "application/json",
4414
+ }
4415
+
4416
+ json = self._api.do(
4417
+ "GET",
4418
+ f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments",
4419
+ headers=headers,
4420
+ )
4421
+ parsed = PermissionAssignments.from_dict(json).permission_assignments
4422
+ return parsed if parsed is not None else []
4423
+
4424
+ def update(
4425
+ self, workspace_id: int, principal_id: int, *, permissions: Optional[List[WorkspacePermission]] = None
4426
+ ) -> PermissionAssignment:
4427
+ """Creates or updates the workspace permissions assignment in a given account and workspace for the
4428
+ specified principal.
4429
+
4430
+ :param workspace_id: int
4431
+ The workspace ID.
4432
+ :param principal_id: int
4433
+ The ID of the user, service principal, or group.
4434
+ :param permissions: List[:class:`WorkspacePermission`] (optional)
4435
+ Array of permissions assignments to update on the workspace. Valid values are "USER" and "ADMIN"
4436
+ (case-sensitive). If both "USER" and "ADMIN" are provided, "ADMIN" takes precedence. Other values
4437
+ will be ignored. Note that excluding this field, or providing unsupported values, will have the same
4438
+ effect as providing an empty list, which will result in the deletion of all permissions for the
4439
+ principal.
4440
+
4441
+ :returns: :class:`PermissionAssignment`
4442
+ """
4443
+ body = {}
4444
+ if permissions is not None:
4445
+ body["permissions"] = [v.value for v in permissions]
4446
+ headers = {
4447
+ "Accept": "application/json",
4448
+ "Content-Type": "application/json",
4449
+ }
4450
+
4451
+ res = self._api.do(
4452
+ "PUT",
4453
+ f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments/principals/{principal_id}",
4454
+ body=body,
4455
+ headers=headers,
4456
+ )
4457
+ return PermissionAssignment.from_dict(res)
4458
+
4459
+
2080
4460
  class AccountGroupsAPI:
2081
4461
  """Groups simplify identity management, making it easier to assign access to Databricks account, data, and
2082
4462
  other securable objects.
@@ -2193,9 +4573,7 @@ class AccountGroupsAPI:
2193
4573
  sort_order: Optional[ListSortOrder] = None,
2194
4574
  start_index: Optional[int] = None,
2195
4575
  ) -> Iterator[Group]:
2196
- """Gets all details of the groups associated with the Databricks account. As of 08/22/2025, this endpoint
2197
- will not return members. Instead, members should be retrieved by iterating through `Get group
2198
- details`.
4576
+ """Gets all details of the groups associated with the Databricks account.
2199
4577
 
2200
4578
  :param attributes: str (optional)
2201
4579
  Comma-separated list of attributes to return in response.
@@ -2971,27 +5349,6 @@ class AccountUsersAPI:
2971
5349
  self._api.do("PUT", f"/api/2.0/accounts/{self._api.account_id}/scim/v2/Users/{id}", body=body, headers=headers)
2972
5350
 
2973
5351
 
2974
- class CurrentUserAPI:
2975
- """This API allows retrieving information about currently authenticated user or service principal."""
2976
-
2977
- def __init__(self, api_client):
2978
- self._api = api_client
2979
-
2980
- def me(self) -> User:
2981
- """Get details about the current method caller's identity.
2982
-
2983
-
2984
- :returns: :class:`User`
2985
- """
2986
-
2987
- headers = {
2988
- "Accept": "application/json",
2989
- }
2990
-
2991
- res = self._api.do("GET", "/api/2.0/preview/scim/v2/Me", headers=headers)
2992
- return User.from_dict(res)
2993
-
2994
-
2995
5352
  class GroupsAPI:
2996
5353
  """Groups simplify identity management, making it easier to assign access to Databricks workspace, data, and
2997
5354
  other securable objects.
@@ -3121,319 +5478,133 @@ class GroupsAPI:
3121
5478
  only support simple expressions.
3122
5479
 
3123
5480
  [SCIM RFC]: https://tools.ietf.org/html/rfc7644#section-3.4.2.2
3124
- :param sort_by: str (optional)
3125
- Attribute to sort the results.
3126
- :param sort_order: :class:`ListSortOrder` (optional)
3127
- The order to sort the results.
3128
- :param start_index: int (optional)
3129
- Specifies the index of the first result. First item is number 1.
3130
-
3131
- :returns: Iterator over :class:`Group`
3132
- """
3133
-
3134
- query = {}
3135
- if attributes is not None:
3136
- query["attributes"] = attributes
3137
- if count is not None:
3138
- query["count"] = count
3139
- if excluded_attributes is not None:
3140
- query["excludedAttributes"] = excluded_attributes
3141
- if filter is not None:
3142
- query["filter"] = filter
3143
- if sort_by is not None:
3144
- query["sortBy"] = sort_by
3145
- if sort_order is not None:
3146
- query["sortOrder"] = sort_order.value
3147
- if start_index is not None:
3148
- query["startIndex"] = start_index
3149
- headers = {
3150
- "Accept": "application/json",
3151
- }
3152
-
3153
- # deduplicate items that may have been added during iteration
3154
- seen = set()
3155
- query["startIndex"] = 1
3156
- if "count" not in query:
3157
- query["count"] = 10000
3158
- while True:
3159
- json = self._api.do("GET", "/api/2.0/preview/scim/v2/Groups", query=query, headers=headers)
3160
- if "Resources" in json:
3161
- for v in json["Resources"]:
3162
- i = v["id"]
3163
- if i in seen:
3164
- continue
3165
- seen.add(i)
3166
- yield Group.from_dict(v)
3167
- if "Resources" not in json or not json["Resources"]:
3168
- return
3169
- query["startIndex"] += len(json["Resources"])
3170
-
3171
- def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
3172
- """Partially updates the details of a group.
3173
-
3174
- :param id: str
3175
- Unique ID in the Databricks workspace.
3176
- :param operations: List[:class:`Patch`] (optional)
3177
- :param schemas: List[:class:`PatchSchema`] (optional)
3178
- The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
3179
-
3180
-
3181
- """
3182
- body = {}
3183
- if operations is not None:
3184
- body["Operations"] = [v.as_dict() for v in operations]
3185
- if schemas is not None:
3186
- body["schemas"] = [v.value for v in schemas]
3187
- headers = {
3188
- "Content-Type": "application/json",
3189
- }
3190
-
3191
- self._api.do("PATCH", f"/api/2.0/preview/scim/v2/Groups/{id}", body=body, headers=headers)
3192
-
3193
- def update(
3194
- self,
3195
- id: str,
3196
- *,
3197
- display_name: Optional[str] = None,
3198
- entitlements: Optional[List[ComplexValue]] = None,
3199
- external_id: Optional[str] = None,
3200
- groups: Optional[List[ComplexValue]] = None,
3201
- members: Optional[List[ComplexValue]] = None,
3202
- meta: Optional[ResourceMeta] = None,
3203
- roles: Optional[List[ComplexValue]] = None,
3204
- schemas: Optional[List[GroupSchema]] = None,
3205
- ):
3206
- """Updates the details of a group by replacing the entire group entity.
3207
-
3208
- :param id: str
3209
- Databricks group ID
3210
- :param display_name: str (optional)
3211
- String that represents a human-readable group name
3212
- :param entitlements: List[:class:`ComplexValue`] (optional)
3213
- Entitlements assigned to the group. See [assigning entitlements] for a full list of supported
3214
- values.
3215
-
3216
- [assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
3217
- :param external_id: str (optional)
3218
- :param groups: List[:class:`ComplexValue`] (optional)
3219
- :param members: List[:class:`ComplexValue`] (optional)
3220
- :param meta: :class:`ResourceMeta` (optional)
3221
- Container for the group identifier. Workspace local versus account.
3222
- :param roles: List[:class:`ComplexValue`] (optional)
3223
- Corresponds to AWS instance profile/arn role.
3224
- :param schemas: List[:class:`GroupSchema`] (optional)
3225
- The schema of the group.
3226
-
3227
-
3228
- """
3229
- body = {}
3230
- if display_name is not None:
3231
- body["displayName"] = display_name
3232
- if entitlements is not None:
3233
- body["entitlements"] = [v.as_dict() for v in entitlements]
3234
- if external_id is not None:
3235
- body["externalId"] = external_id
3236
- if groups is not None:
3237
- body["groups"] = [v.as_dict() for v in groups]
3238
- if members is not None:
3239
- body["members"] = [v.as_dict() for v in members]
3240
- if meta is not None:
3241
- body["meta"] = meta.as_dict()
3242
- if roles is not None:
3243
- body["roles"] = [v.as_dict() for v in roles]
3244
- if schemas is not None:
3245
- body["schemas"] = [v.value for v in schemas]
3246
- headers = {
3247
- "Content-Type": "application/json",
3248
- }
3249
-
3250
- self._api.do("PUT", f"/api/2.0/preview/scim/v2/Groups/{id}", body=body, headers=headers)
3251
-
3252
-
3253
- class PermissionMigrationAPI:
3254
- """APIs for migrating acl permissions, used only by the ucx tool: https://github.com/databrickslabs/ucx"""
3255
-
3256
- def __init__(self, api_client):
3257
- self._api = api_client
3258
-
3259
- def migrate_permissions(
3260
- self,
3261
- workspace_id: int,
3262
- from_workspace_group_name: str,
3263
- to_account_group_name: str,
3264
- *,
3265
- size: Optional[int] = None,
3266
- ) -> MigratePermissionsResponse:
3267
- """Migrate Permissions.
3268
-
3269
- :param workspace_id: int
3270
- WorkspaceId of the associated workspace where the permission migration will occur.
3271
- :param from_workspace_group_name: str
3272
- The name of the workspace group that permissions will be migrated from.
3273
- :param to_account_group_name: str
3274
- The name of the account group that permissions will be migrated to.
3275
- :param size: int (optional)
3276
- The maximum number of permissions that will be migrated.
3277
-
3278
- :returns: :class:`MigratePermissionsResponse`
3279
- """
3280
- body = {}
3281
- if from_workspace_group_name is not None:
3282
- body["from_workspace_group_name"] = from_workspace_group_name
3283
- if size is not None:
3284
- body["size"] = size
3285
- if to_account_group_name is not None:
3286
- body["to_account_group_name"] = to_account_group_name
3287
- if workspace_id is not None:
3288
- body["workspace_id"] = workspace_id
3289
- headers = {
3290
- "Accept": "application/json",
3291
- "Content-Type": "application/json",
3292
- }
3293
-
3294
- res = self._api.do("POST", "/api/2.0/permissionmigration", body=body, headers=headers)
3295
- return MigratePermissionsResponse.from_dict(res)
3296
-
3297
-
3298
- class PermissionsAPI:
3299
- """Permissions API are used to create read, write, edit, update and manage access for various users on
3300
- different objects and endpoints. * **[Apps permissions](:service:apps)** — Manage which users can manage
3301
- or use apps. * **[Cluster permissions](:service:clusters)** — Manage which users can manage, restart, or
3302
- attach to clusters. * **[Cluster policy permissions](:service:clusterpolicies)** — Manage which users
3303
- can use cluster policies. * **[Delta Live Tables pipeline permissions](:service:pipelines)** — Manage
3304
- which users can view, manage, run, cancel, or own a Delta Live Tables pipeline. * **[Job
3305
- permissions](:service:jobs)** — Manage which users can view, manage, trigger, cancel, or own a job. *
3306
- **[MLflow experiment permissions](:service:experiments)** — Manage which users can read, edit, or manage
3307
- MLflow experiments. * **[MLflow registered model permissions](:service:modelregistry)** — Manage which
3308
- users can read, edit, or manage MLflow registered models. * **[Instance Pool
3309
- permissions](:service:instancepools)** — Manage which users can manage or attach to pools. * **[Repo
3310
- permissions](repos)** — Manage which users can read, run, edit, or manage a repo. * **[Serving endpoint
3311
- permissions](:service:servingendpoints)** — Manage which users can view, query, or manage a serving
3312
- endpoint. * **[SQL warehouse permissions](:service:warehouses)** — Manage which users can use or manage
3313
- SQL warehouses. * **[Token permissions](:service:tokenmanagement)** — Manage which users can create or
3314
- use tokens. * **[Workspace object permissions](:service:workspace)** — Manage which users can read, run,
3315
- edit, or manage alerts, dbsql-dashboards, directories, files, notebooks and queries. For the mapping of
3316
- the required permissions for specific actions or abilities and other important information, see [Access
3317
- Control]. Note that to manage access control on service principals, use **[Account Access Control
3318
- Proxy](:service:accountaccesscontrolproxy)**.
3319
-
3320
- [Access Control]: https://docs.databricks.com/security/auth-authz/access-control/index.html"""
3321
-
3322
- def __init__(self, api_client):
3323
- self._api = api_client
3324
-
3325
- def get(self, request_object_type: str, request_object_id: str) -> ObjectPermissions:
3326
- """Gets the permissions of an object. Objects can inherit permissions from their parent objects or root
3327
- object.
3328
-
3329
- :param request_object_type: str
3330
- The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
3331
- clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files,
3332
- instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
3333
- warehouses.
3334
- :param request_object_id: str
3335
- The id of the request object.
3336
-
3337
- :returns: :class:`ObjectPermissions`
3338
- """
3339
-
3340
- headers = {
3341
- "Accept": "application/json",
3342
- }
3343
-
3344
- res = self._api.do("GET", f"/api/2.0/permissions/{request_object_type}/{request_object_id}", headers=headers)
3345
- return ObjectPermissions.from_dict(res)
3346
-
3347
- def get_permission_levels(self, request_object_type: str, request_object_id: str) -> GetPermissionLevelsResponse:
3348
- """Gets the permission levels that a user can have on an object.
3349
-
3350
- :param request_object_type: str
3351
- The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
3352
- clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files,
3353
- instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
3354
- warehouses.
3355
- :param request_object_id: str
5481
+ :param sort_by: str (optional)
5482
+ Attribute to sort the results.
5483
+ :param sort_order: :class:`ListSortOrder` (optional)
5484
+ The order to sort the results.
5485
+ :param start_index: int (optional)
5486
+ Specifies the index of the first result. First item is number 1.
3356
5487
 
3357
- :returns: :class:`GetPermissionLevelsResponse`
5488
+ :returns: Iterator over :class:`Group`
3358
5489
  """
3359
5490
 
5491
+ query = {}
5492
+ if attributes is not None:
5493
+ query["attributes"] = attributes
5494
+ if count is not None:
5495
+ query["count"] = count
5496
+ if excluded_attributes is not None:
5497
+ query["excludedAttributes"] = excluded_attributes
5498
+ if filter is not None:
5499
+ query["filter"] = filter
5500
+ if sort_by is not None:
5501
+ query["sortBy"] = sort_by
5502
+ if sort_order is not None:
5503
+ query["sortOrder"] = sort_order.value
5504
+ if start_index is not None:
5505
+ query["startIndex"] = start_index
3360
5506
  headers = {
3361
5507
  "Accept": "application/json",
3362
5508
  }
3363
5509
 
3364
- res = self._api.do(
3365
- "GET", f"/api/2.0/permissions/{request_object_type}/{request_object_id}/permissionLevels", headers=headers
3366
- )
3367
- return GetPermissionLevelsResponse.from_dict(res)
5510
+ # deduplicate items that may have been added during iteration
5511
+ seen = set()
5512
+ query["startIndex"] = 1
5513
+ if "count" not in query:
5514
+ query["count"] = 10000
5515
+ while True:
5516
+ json = self._api.do("GET", "/api/2.0/preview/scim/v2/Groups", query=query, headers=headers)
5517
+ if "Resources" in json:
5518
+ for v in json["Resources"]:
5519
+ i = v["id"]
5520
+ if i in seen:
5521
+ continue
5522
+ seen.add(i)
5523
+ yield Group.from_dict(v)
5524
+ if "Resources" not in json or not json["Resources"]:
5525
+ return
5526
+ query["startIndex"] += len(json["Resources"])
3368
5527
 
3369
- def set(
3370
- self,
3371
- request_object_type: str,
3372
- request_object_id: str,
3373
- *,
3374
- access_control_list: Optional[List[AccessControlRequest]] = None,
3375
- ) -> ObjectPermissions:
3376
- """Sets permissions on an object, replacing existing permissions if they exist. Deletes all direct
3377
- permissions if none are specified. Objects can inherit permissions from their parent objects or root
3378
- object.
5528
+ def patch(self, id: str, *, operations: Optional[List[Patch]] = None, schemas: Optional[List[PatchSchema]] = None):
5529
+ """Partially updates the details of a group.
5530
+
5531
+ :param id: str
5532
+ Unique ID in the Databricks workspace.
5533
+ :param operations: List[:class:`Patch`] (optional)
5534
+ :param schemas: List[:class:`PatchSchema`] (optional)
5535
+ The schema of the patch request. Must be ["urn:ietf:params:scim:api:messages:2.0:PatchOp"].
3379
5536
 
3380
- :param request_object_type: str
3381
- The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
3382
- clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files,
3383
- instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
3384
- warehouses.
3385
- :param request_object_id: str
3386
- The id of the request object.
3387
- :param access_control_list: List[:class:`AccessControlRequest`] (optional)
3388
5537
 
3389
- :returns: :class:`ObjectPermissions`
3390
5538
  """
3391
5539
  body = {}
3392
- if access_control_list is not None:
3393
- body["access_control_list"] = [v.as_dict() for v in access_control_list]
5540
+ if operations is not None:
5541
+ body["Operations"] = [v.as_dict() for v in operations]
5542
+ if schemas is not None:
5543
+ body["schemas"] = [v.value for v in schemas]
3394
5544
  headers = {
3395
- "Accept": "application/json",
3396
5545
  "Content-Type": "application/json",
3397
5546
  }
3398
5547
 
3399
- res = self._api.do(
3400
- "PUT", f"/api/2.0/permissions/{request_object_type}/{request_object_id}", body=body, headers=headers
3401
- )
3402
- return ObjectPermissions.from_dict(res)
5548
+ self._api.do("PATCH", f"/api/2.0/preview/scim/v2/Groups/{id}", body=body, headers=headers)
3403
5549
 
3404
5550
  def update(
3405
5551
  self,
3406
- request_object_type: str,
3407
- request_object_id: str,
5552
+ id: str,
3408
5553
  *,
3409
- access_control_list: Optional[List[AccessControlRequest]] = None,
3410
- ) -> ObjectPermissions:
3411
- """Updates the permissions on an object. Objects can inherit permissions from their parent objects or
3412
- root object.
5554
+ display_name: Optional[str] = None,
5555
+ entitlements: Optional[List[ComplexValue]] = None,
5556
+ external_id: Optional[str] = None,
5557
+ groups: Optional[List[ComplexValue]] = None,
5558
+ members: Optional[List[ComplexValue]] = None,
5559
+ meta: Optional[ResourceMeta] = None,
5560
+ roles: Optional[List[ComplexValue]] = None,
5561
+ schemas: Optional[List[GroupSchema]] = None,
5562
+ ):
5563
+ """Updates the details of a group by replacing the entire group entity.
5564
+
5565
+ :param id: str
5566
+ Databricks group ID
5567
+ :param display_name: str (optional)
5568
+ String that represents a human-readable group name
5569
+ :param entitlements: List[:class:`ComplexValue`] (optional)
5570
+ Entitlements assigned to the group. See [assigning entitlements] for a full list of supported
5571
+ values.
5572
+
5573
+ [assigning entitlements]: https://docs.databricks.com/administration-guide/users-groups/index.html#assigning-entitlements
5574
+ :param external_id: str (optional)
5575
+ :param groups: List[:class:`ComplexValue`] (optional)
5576
+ :param members: List[:class:`ComplexValue`] (optional)
5577
+ :param meta: :class:`ResourceMeta` (optional)
5578
+ Container for the group identifier. Workspace local versus account.
5579
+ :param roles: List[:class:`ComplexValue`] (optional)
5580
+ Corresponds to AWS instance profile/arn role.
5581
+ :param schemas: List[:class:`GroupSchema`] (optional)
5582
+ The schema of the group.
3413
5583
 
3414
- :param request_object_type: str
3415
- The type of the request object. Can be one of the following: alerts, alertsv2, authorization,
3416
- clusters, cluster-policies, dashboards, dbsql-dashboards, directories, experiments, files,
3417
- instance-pools, jobs, notebooks, pipelines, queries, registered-models, repos, serving-endpoints, or
3418
- warehouses.
3419
- :param request_object_id: str
3420
- The id of the request object.
3421
- :param access_control_list: List[:class:`AccessControlRequest`] (optional)
3422
5584
 
3423
- :returns: :class:`ObjectPermissions`
3424
5585
  """
3425
5586
  body = {}
3426
- if access_control_list is not None:
3427
- body["access_control_list"] = [v.as_dict() for v in access_control_list]
5587
+ if display_name is not None:
5588
+ body["displayName"] = display_name
5589
+ if entitlements is not None:
5590
+ body["entitlements"] = [v.as_dict() for v in entitlements]
5591
+ if external_id is not None:
5592
+ body["externalId"] = external_id
5593
+ if groups is not None:
5594
+ body["groups"] = [v.as_dict() for v in groups]
5595
+ if members is not None:
5596
+ body["members"] = [v.as_dict() for v in members]
5597
+ if meta is not None:
5598
+ body["meta"] = meta.as_dict()
5599
+ if roles is not None:
5600
+ body["roles"] = [v.as_dict() for v in roles]
5601
+ if schemas is not None:
5602
+ body["schemas"] = [v.value for v in schemas]
3428
5603
  headers = {
3429
- "Accept": "application/json",
3430
5604
  "Content-Type": "application/json",
3431
5605
  }
3432
5606
 
3433
- res = self._api.do(
3434
- "PATCH", f"/api/2.0/permissions/{request_object_type}/{request_object_id}", body=body, headers=headers
3435
- )
3436
- return ObjectPermissions.from_dict(res)
5607
+ self._api.do("PUT", f"/api/2.0/preview/scim/v2/Groups/{id}", body=body, headers=headers)
3437
5608
 
3438
5609
 
3439
5610
  class ServicePrincipalsAPI:
@@ -4102,109 +6273,3 @@ class UsersAPI:
4102
6273
 
4103
6274
  res = self._api.do("PATCH", "/api/2.0/permissions/authorization/passwords", body=body, headers=headers)
4104
6275
  return PasswordPermissions.from_dict(res)
4105
-
4106
-
4107
- class WorkspaceAssignmentAPI:
4108
- """The Workspace Permission Assignment API allows you to manage workspace permissions for principals in your
4109
- account."""
4110
-
4111
- def __init__(self, api_client):
4112
- self._api = api_client
4113
-
4114
- def delete(self, workspace_id: int, principal_id: int):
4115
- """Deletes the workspace permissions assignment in a given account and workspace for the specified
4116
- principal.
4117
-
4118
- :param workspace_id: int
4119
- The workspace ID for the account.
4120
- :param principal_id: int
4121
- The ID of the user, service principal, or group.
4122
-
4123
-
4124
- """
4125
-
4126
- headers = {
4127
- "Accept": "application/json",
4128
- }
4129
-
4130
- self._api.do(
4131
- "DELETE",
4132
- f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments/principals/{principal_id}",
4133
- headers=headers,
4134
- )
4135
-
4136
- def get(self, workspace_id: int) -> WorkspacePermissions:
4137
- """Get an array of workspace permissions for the specified account and workspace.
4138
-
4139
- :param workspace_id: int
4140
- The workspace ID.
4141
-
4142
- :returns: :class:`WorkspacePermissions`
4143
- """
4144
-
4145
- headers = {
4146
- "Accept": "application/json",
4147
- }
4148
-
4149
- res = self._api.do(
4150
- "GET",
4151
- f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments/permissions",
4152
- headers=headers,
4153
- )
4154
- return WorkspacePermissions.from_dict(res)
4155
-
4156
- def list(self, workspace_id: int) -> Iterator[PermissionAssignment]:
4157
- """Get the permission assignments for the specified Databricks account and Databricks workspace.
4158
-
4159
- :param workspace_id: int
4160
- The workspace ID for the account.
4161
-
4162
- :returns: Iterator over :class:`PermissionAssignment`
4163
- """
4164
-
4165
- headers = {
4166
- "Accept": "application/json",
4167
- }
4168
-
4169
- json = self._api.do(
4170
- "GET",
4171
- f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments",
4172
- headers=headers,
4173
- )
4174
- parsed = PermissionAssignments.from_dict(json).permission_assignments
4175
- return parsed if parsed is not None else []
4176
-
4177
- def update(
4178
- self, workspace_id: int, principal_id: int, *, permissions: Optional[List[WorkspacePermission]] = None
4179
- ) -> PermissionAssignment:
4180
- """Creates or updates the workspace permissions assignment in a given account and workspace for the
4181
- specified principal.
4182
-
4183
- :param workspace_id: int
4184
- The workspace ID.
4185
- :param principal_id: int
4186
- The ID of the user, service principal, or group.
4187
- :param permissions: List[:class:`WorkspacePermission`] (optional)
4188
- Array of permissions assignments to update on the workspace. Valid values are "USER" and "ADMIN"
4189
- (case-sensitive). If both "USER" and "ADMIN" are provided, "ADMIN" takes precedence. Other values
4190
- will be ignored. Note that excluding this field, or providing unsupported values, will have the same
4191
- effect as providing an empty list, which will result in the deletion of all permissions for the
4192
- principal.
4193
-
4194
- :returns: :class:`PermissionAssignment`
4195
- """
4196
- body = {}
4197
- if permissions is not None:
4198
- body["permissions"] = [v.value for v in permissions]
4199
- headers = {
4200
- "Accept": "application/json",
4201
- "Content-Type": "application/json",
4202
- }
4203
-
4204
- res = self._api.do(
4205
- "PUT",
4206
- f"/api/2.0/accounts/{self._api.account_id}/workspaces/{workspace_id}/permissionassignments/principals/{principal_id}",
4207
- body=body,
4208
- headers=headers,
4209
- )
4210
- return PermissionAssignment.from_dict(res)