databricks-sdk 0.44.1__py3-none-any.whl → 0.46.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.
- databricks/sdk/__init__.py +135 -116
- databricks/sdk/_base_client.py +112 -88
- databricks/sdk/_property.py +12 -7
- databricks/sdk/_widgets/__init__.py +13 -2
- databricks/sdk/_widgets/default_widgets_utils.py +21 -15
- databricks/sdk/_widgets/ipywidgets_utils.py +47 -24
- databricks/sdk/azure.py +8 -6
- databricks/sdk/casing.py +5 -5
- databricks/sdk/config.py +156 -99
- databricks/sdk/core.py +57 -47
- databricks/sdk/credentials_provider.py +306 -206
- databricks/sdk/data_plane.py +75 -50
- databricks/sdk/dbutils.py +123 -87
- databricks/sdk/environments.py +52 -35
- databricks/sdk/errors/base.py +61 -35
- databricks/sdk/errors/customizer.py +3 -3
- databricks/sdk/errors/deserializer.py +38 -25
- databricks/sdk/errors/details.py +417 -0
- databricks/sdk/errors/mapper.py +1 -1
- databricks/sdk/errors/overrides.py +27 -24
- databricks/sdk/errors/parser.py +26 -14
- databricks/sdk/errors/platform.py +10 -10
- databricks/sdk/errors/private_link.py +24 -24
- databricks/sdk/logger/round_trip_logger.py +28 -20
- databricks/sdk/mixins/compute.py +90 -60
- databricks/sdk/mixins/files.py +815 -145
- databricks/sdk/mixins/jobs.py +191 -16
- databricks/sdk/mixins/open_ai_client.py +26 -20
- databricks/sdk/mixins/workspace.py +45 -34
- databricks/sdk/oauth.py +379 -198
- databricks/sdk/retries.py +14 -12
- databricks/sdk/runtime/__init__.py +34 -17
- databricks/sdk/runtime/dbutils_stub.py +52 -39
- databricks/sdk/service/_internal.py +12 -7
- databricks/sdk/service/apps.py +618 -418
- databricks/sdk/service/billing.py +827 -604
- databricks/sdk/service/catalog.py +6552 -4474
- databricks/sdk/service/cleanrooms.py +550 -388
- databricks/sdk/service/compute.py +5263 -3536
- databricks/sdk/service/dashboards.py +1331 -924
- databricks/sdk/service/files.py +446 -309
- databricks/sdk/service/iam.py +2115 -1483
- databricks/sdk/service/jobs.py +4151 -2588
- databricks/sdk/service/marketplace.py +2210 -1517
- databricks/sdk/service/ml.py +3839 -2256
- databricks/sdk/service/oauth2.py +910 -584
- databricks/sdk/service/pipelines.py +1865 -1203
- databricks/sdk/service/provisioning.py +1435 -1029
- databricks/sdk/service/serving.py +2060 -1290
- databricks/sdk/service/settings.py +2846 -1929
- databricks/sdk/service/sharing.py +2201 -877
- databricks/sdk/service/sql.py +4650 -3103
- databricks/sdk/service/vectorsearch.py +816 -550
- databricks/sdk/service/workspace.py +1330 -906
- databricks/sdk/useragent.py +36 -22
- databricks/sdk/version.py +1 -1
- {databricks_sdk-0.44.1.dist-info → databricks_sdk-0.46.0.dist-info}/METADATA +31 -31
- databricks_sdk-0.46.0.dist-info/RECORD +70 -0
- {databricks_sdk-0.44.1.dist-info → databricks_sdk-0.46.0.dist-info}/WHEEL +1 -1
- databricks_sdk-0.44.1.dist-info/RECORD +0 -69
- {databricks_sdk-0.44.1.dist-info → databricks_sdk-0.46.0.dist-info}/LICENSE +0 -0
- {databricks_sdk-0.44.1.dist-info → databricks_sdk-0.46.0.dist-info}/NOTICE +0 -0
- {databricks_sdk-0.44.1.dist-info → databricks_sdk-0.46.0.dist-info}/top_level.txt +0 -0
databricks/sdk/service/oauth2.py
CHANGED
|
@@ -4,11 +4,12 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
6
|
from dataclasses import dataclass
|
|
7
|
-
from typing import Dict, Iterator, List, Optional
|
|
7
|
+
from typing import Any, Dict, Iterator, List, Optional
|
|
8
8
|
|
|
9
9
|
from ._internal import _from_dict, _repeated_dict
|
|
10
10
|
|
|
11
|
-
_LOG = logging.getLogger(
|
|
11
|
+
_LOG = logging.getLogger("databricks.sdk")
|
|
12
|
+
|
|
12
13
|
|
|
13
14
|
# all definitions in this file are in alphabetical order
|
|
14
15
|
|
|
@@ -38,35 +39,48 @@ class CreateCustomAppIntegration:
|
|
|
38
39
|
def as_dict(self) -> dict:
|
|
39
40
|
"""Serializes the CreateCustomAppIntegration into a dictionary suitable for use as a JSON request body."""
|
|
40
41
|
body = {}
|
|
41
|
-
if self.confidential is not None:
|
|
42
|
-
|
|
43
|
-
if self.
|
|
44
|
-
|
|
45
|
-
if self.
|
|
42
|
+
if self.confidential is not None:
|
|
43
|
+
body["confidential"] = self.confidential
|
|
44
|
+
if self.name is not None:
|
|
45
|
+
body["name"] = self.name
|
|
46
|
+
if self.redirect_urls:
|
|
47
|
+
body["redirect_urls"] = [v for v in self.redirect_urls]
|
|
48
|
+
if self.scopes:
|
|
49
|
+
body["scopes"] = [v for v in self.scopes]
|
|
50
|
+
if self.token_access_policy:
|
|
51
|
+
body["token_access_policy"] = self.token_access_policy.as_dict()
|
|
46
52
|
if self.user_authorized_scopes:
|
|
47
|
-
body[
|
|
53
|
+
body["user_authorized_scopes"] = [v for v in self.user_authorized_scopes]
|
|
48
54
|
return body
|
|
49
55
|
|
|
50
56
|
def as_shallow_dict(self) -> dict:
|
|
51
57
|
"""Serializes the CreateCustomAppIntegration into a shallow dictionary of its immediate attributes."""
|
|
52
58
|
body = {}
|
|
53
|
-
if self.confidential is not None:
|
|
54
|
-
|
|
55
|
-
if self.
|
|
56
|
-
|
|
57
|
-
if self.
|
|
58
|
-
|
|
59
|
+
if self.confidential is not None:
|
|
60
|
+
body["confidential"] = self.confidential
|
|
61
|
+
if self.name is not None:
|
|
62
|
+
body["name"] = self.name
|
|
63
|
+
if self.redirect_urls:
|
|
64
|
+
body["redirect_urls"] = self.redirect_urls
|
|
65
|
+
if self.scopes:
|
|
66
|
+
body["scopes"] = self.scopes
|
|
67
|
+
if self.token_access_policy:
|
|
68
|
+
body["token_access_policy"] = self.token_access_policy
|
|
69
|
+
if self.user_authorized_scopes:
|
|
70
|
+
body["user_authorized_scopes"] = self.user_authorized_scopes
|
|
59
71
|
return body
|
|
60
72
|
|
|
61
73
|
@classmethod
|
|
62
|
-
def from_dict(cls, d: Dict[str,
|
|
74
|
+
def from_dict(cls, d: Dict[str, Any]) -> CreateCustomAppIntegration:
|
|
63
75
|
"""Deserializes the CreateCustomAppIntegration from a dictionary."""
|
|
64
|
-
return cls(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
return cls(
|
|
77
|
+
confidential=d.get("confidential", None),
|
|
78
|
+
name=d.get("name", None),
|
|
79
|
+
redirect_urls=d.get("redirect_urls", None),
|
|
80
|
+
scopes=d.get("scopes", None),
|
|
81
|
+
token_access_policy=_from_dict(d, "token_access_policy", TokenAccessPolicy),
|
|
82
|
+
user_authorized_scopes=d.get("user_authorized_scopes", None),
|
|
83
|
+
)
|
|
70
84
|
|
|
71
85
|
|
|
72
86
|
@dataclass
|
|
@@ -84,25 +98,33 @@ class CreateCustomAppIntegrationOutput:
|
|
|
84
98
|
def as_dict(self) -> dict:
|
|
85
99
|
"""Serializes the CreateCustomAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
|
86
100
|
body = {}
|
|
87
|
-
if self.client_id is not None:
|
|
88
|
-
|
|
89
|
-
if self.
|
|
101
|
+
if self.client_id is not None:
|
|
102
|
+
body["client_id"] = self.client_id
|
|
103
|
+
if self.client_secret is not None:
|
|
104
|
+
body["client_secret"] = self.client_secret
|
|
105
|
+
if self.integration_id is not None:
|
|
106
|
+
body["integration_id"] = self.integration_id
|
|
90
107
|
return body
|
|
91
108
|
|
|
92
109
|
def as_shallow_dict(self) -> dict:
|
|
93
110
|
"""Serializes the CreateCustomAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
|
94
111
|
body = {}
|
|
95
|
-
if self.client_id is not None:
|
|
96
|
-
|
|
97
|
-
if self.
|
|
112
|
+
if self.client_id is not None:
|
|
113
|
+
body["client_id"] = self.client_id
|
|
114
|
+
if self.client_secret is not None:
|
|
115
|
+
body["client_secret"] = self.client_secret
|
|
116
|
+
if self.integration_id is not None:
|
|
117
|
+
body["integration_id"] = self.integration_id
|
|
98
118
|
return body
|
|
99
119
|
|
|
100
120
|
@classmethod
|
|
101
|
-
def from_dict(cls, d: Dict[str,
|
|
121
|
+
def from_dict(cls, d: Dict[str, Any]) -> CreateCustomAppIntegrationOutput:
|
|
102
122
|
"""Deserializes the CreateCustomAppIntegrationOutput from a dictionary."""
|
|
103
|
-
return cls(
|
|
104
|
-
|
|
105
|
-
|
|
123
|
+
return cls(
|
|
124
|
+
client_id=d.get("client_id", None),
|
|
125
|
+
client_secret=d.get("client_secret", None),
|
|
126
|
+
integration_id=d.get("integration_id", None),
|
|
127
|
+
)
|
|
106
128
|
|
|
107
129
|
|
|
108
130
|
@dataclass
|
|
@@ -116,22 +138,27 @@ class CreatePublishedAppIntegration:
|
|
|
116
138
|
def as_dict(self) -> dict:
|
|
117
139
|
"""Serializes the CreatePublishedAppIntegration into a dictionary suitable for use as a JSON request body."""
|
|
118
140
|
body = {}
|
|
119
|
-
if self.app_id is not None:
|
|
120
|
-
|
|
141
|
+
if self.app_id is not None:
|
|
142
|
+
body["app_id"] = self.app_id
|
|
143
|
+
if self.token_access_policy:
|
|
144
|
+
body["token_access_policy"] = self.token_access_policy.as_dict()
|
|
121
145
|
return body
|
|
122
146
|
|
|
123
147
|
def as_shallow_dict(self) -> dict:
|
|
124
148
|
"""Serializes the CreatePublishedAppIntegration into a shallow dictionary of its immediate attributes."""
|
|
125
149
|
body = {}
|
|
126
|
-
if self.app_id is not None:
|
|
127
|
-
|
|
150
|
+
if self.app_id is not None:
|
|
151
|
+
body["app_id"] = self.app_id
|
|
152
|
+
if self.token_access_policy:
|
|
153
|
+
body["token_access_policy"] = self.token_access_policy
|
|
128
154
|
return body
|
|
129
155
|
|
|
130
156
|
@classmethod
|
|
131
|
-
def from_dict(cls, d: Dict[str,
|
|
157
|
+
def from_dict(cls, d: Dict[str, Any]) -> CreatePublishedAppIntegration:
|
|
132
158
|
"""Deserializes the CreatePublishedAppIntegration from a dictionary."""
|
|
133
|
-
return cls(
|
|
134
|
-
|
|
159
|
+
return cls(
|
|
160
|
+
app_id=d.get("app_id", None), token_access_policy=_from_dict(d, "token_access_policy", TokenAccessPolicy)
|
|
161
|
+
)
|
|
135
162
|
|
|
136
163
|
|
|
137
164
|
@dataclass
|
|
@@ -142,19 +169,54 @@ class CreatePublishedAppIntegrationOutput:
|
|
|
142
169
|
def as_dict(self) -> dict:
|
|
143
170
|
"""Serializes the CreatePublishedAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
|
144
171
|
body = {}
|
|
145
|
-
if self.integration_id is not None:
|
|
172
|
+
if self.integration_id is not None:
|
|
173
|
+
body["integration_id"] = self.integration_id
|
|
146
174
|
return body
|
|
147
175
|
|
|
148
176
|
def as_shallow_dict(self) -> dict:
|
|
149
177
|
"""Serializes the CreatePublishedAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
|
150
178
|
body = {}
|
|
151
|
-
if self.integration_id is not None:
|
|
179
|
+
if self.integration_id is not None:
|
|
180
|
+
body["integration_id"] = self.integration_id
|
|
152
181
|
return body
|
|
153
182
|
|
|
154
183
|
@classmethod
|
|
155
|
-
def from_dict(cls, d: Dict[str,
|
|
184
|
+
def from_dict(cls, d: Dict[str, Any]) -> CreatePublishedAppIntegrationOutput:
|
|
156
185
|
"""Deserializes the CreatePublishedAppIntegrationOutput from a dictionary."""
|
|
157
|
-
return cls(integration_id=d.get(
|
|
186
|
+
return cls(integration_id=d.get("integration_id", None))
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
@dataclass
|
|
190
|
+
class CreateServicePrincipalSecretRequest:
|
|
191
|
+
lifetime: Optional[str] = None
|
|
192
|
+
"""The lifetime of the secret in seconds. If this parameter is not provided, the secret will have a
|
|
193
|
+
default lifetime of 730 days (63072000s)."""
|
|
194
|
+
|
|
195
|
+
service_principal_id: Optional[int] = None
|
|
196
|
+
"""The service principal ID."""
|
|
197
|
+
|
|
198
|
+
def as_dict(self) -> dict:
|
|
199
|
+
"""Serializes the CreateServicePrincipalSecretRequest into a dictionary suitable for use as a JSON request body."""
|
|
200
|
+
body = {}
|
|
201
|
+
if self.lifetime is not None:
|
|
202
|
+
body["lifetime"] = self.lifetime
|
|
203
|
+
if self.service_principal_id is not None:
|
|
204
|
+
body["service_principal_id"] = self.service_principal_id
|
|
205
|
+
return body
|
|
206
|
+
|
|
207
|
+
def as_shallow_dict(self) -> dict:
|
|
208
|
+
"""Serializes the CreateServicePrincipalSecretRequest into a shallow dictionary of its immediate attributes."""
|
|
209
|
+
body = {}
|
|
210
|
+
if self.lifetime is not None:
|
|
211
|
+
body["lifetime"] = self.lifetime
|
|
212
|
+
if self.service_principal_id is not None:
|
|
213
|
+
body["service_principal_id"] = self.service_principal_id
|
|
214
|
+
return body
|
|
215
|
+
|
|
216
|
+
@classmethod
|
|
217
|
+
def from_dict(cls, d: Dict[str, Any]) -> CreateServicePrincipalSecretRequest:
|
|
218
|
+
"""Deserializes the CreateServicePrincipalSecretRequest from a dictionary."""
|
|
219
|
+
return cls(lifetime=d.get("lifetime", None), service_principal_id=d.get("service_principal_id", None))
|
|
158
220
|
|
|
159
221
|
|
|
160
222
|
@dataclass
|
|
@@ -162,6 +224,9 @@ class CreateServicePrincipalSecretResponse:
|
|
|
162
224
|
create_time: Optional[str] = None
|
|
163
225
|
"""UTC time when the secret was created"""
|
|
164
226
|
|
|
227
|
+
expire_time: Optional[str] = None
|
|
228
|
+
"""UTC time when the secret will expire. If the field is not present, the secret does not expire."""
|
|
229
|
+
|
|
165
230
|
id: Optional[str] = None
|
|
166
231
|
"""ID of the secret"""
|
|
167
232
|
|
|
@@ -180,39 +245,57 @@ class CreateServicePrincipalSecretResponse:
|
|
|
180
245
|
def as_dict(self) -> dict:
|
|
181
246
|
"""Serializes the CreateServicePrincipalSecretResponse into a dictionary suitable for use as a JSON request body."""
|
|
182
247
|
body = {}
|
|
183
|
-
if self.create_time is not None:
|
|
184
|
-
|
|
185
|
-
if self.
|
|
186
|
-
|
|
187
|
-
if self.
|
|
188
|
-
|
|
248
|
+
if self.create_time is not None:
|
|
249
|
+
body["create_time"] = self.create_time
|
|
250
|
+
if self.expire_time is not None:
|
|
251
|
+
body["expire_time"] = self.expire_time
|
|
252
|
+
if self.id is not None:
|
|
253
|
+
body["id"] = self.id
|
|
254
|
+
if self.secret is not None:
|
|
255
|
+
body["secret"] = self.secret
|
|
256
|
+
if self.secret_hash is not None:
|
|
257
|
+
body["secret_hash"] = self.secret_hash
|
|
258
|
+
if self.status is not None:
|
|
259
|
+
body["status"] = self.status
|
|
260
|
+
if self.update_time is not None:
|
|
261
|
+
body["update_time"] = self.update_time
|
|
189
262
|
return body
|
|
190
263
|
|
|
191
264
|
def as_shallow_dict(self) -> dict:
|
|
192
265
|
"""Serializes the CreateServicePrincipalSecretResponse into a shallow dictionary of its immediate attributes."""
|
|
193
266
|
body = {}
|
|
194
|
-
if self.create_time is not None:
|
|
195
|
-
|
|
196
|
-
if self.
|
|
197
|
-
|
|
198
|
-
if self.
|
|
199
|
-
|
|
267
|
+
if self.create_time is not None:
|
|
268
|
+
body["create_time"] = self.create_time
|
|
269
|
+
if self.expire_time is not None:
|
|
270
|
+
body["expire_time"] = self.expire_time
|
|
271
|
+
if self.id is not None:
|
|
272
|
+
body["id"] = self.id
|
|
273
|
+
if self.secret is not None:
|
|
274
|
+
body["secret"] = self.secret
|
|
275
|
+
if self.secret_hash is not None:
|
|
276
|
+
body["secret_hash"] = self.secret_hash
|
|
277
|
+
if self.status is not None:
|
|
278
|
+
body["status"] = self.status
|
|
279
|
+
if self.update_time is not None:
|
|
280
|
+
body["update_time"] = self.update_time
|
|
200
281
|
return body
|
|
201
282
|
|
|
202
283
|
@classmethod
|
|
203
|
-
def from_dict(cls, d: Dict[str,
|
|
284
|
+
def from_dict(cls, d: Dict[str, Any]) -> CreateServicePrincipalSecretResponse:
|
|
204
285
|
"""Deserializes the CreateServicePrincipalSecretResponse from a dictionary."""
|
|
205
|
-
return cls(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
286
|
+
return cls(
|
|
287
|
+
create_time=d.get("create_time", None),
|
|
288
|
+
expire_time=d.get("expire_time", None),
|
|
289
|
+
id=d.get("id", None),
|
|
290
|
+
secret=d.get("secret", None),
|
|
291
|
+
secret_hash=d.get("secret_hash", None),
|
|
292
|
+
status=d.get("status", None),
|
|
293
|
+
update_time=d.get("update_time", None),
|
|
294
|
+
)
|
|
211
295
|
|
|
212
296
|
|
|
213
297
|
@dataclass
|
|
214
298
|
class DeleteCustomAppIntegrationOutput:
|
|
215
|
-
|
|
216
299
|
def as_dict(self) -> dict:
|
|
217
300
|
"""Serializes the DeleteCustomAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
|
218
301
|
body = {}
|
|
@@ -224,14 +307,13 @@ class DeleteCustomAppIntegrationOutput:
|
|
|
224
307
|
return body
|
|
225
308
|
|
|
226
309
|
@classmethod
|
|
227
|
-
def from_dict(cls, d: Dict[str,
|
|
310
|
+
def from_dict(cls, d: Dict[str, Any]) -> DeleteCustomAppIntegrationOutput:
|
|
228
311
|
"""Deserializes the DeleteCustomAppIntegrationOutput from a dictionary."""
|
|
229
312
|
return cls()
|
|
230
313
|
|
|
231
314
|
|
|
232
315
|
@dataclass
|
|
233
316
|
class DeletePublishedAppIntegrationOutput:
|
|
234
|
-
|
|
235
317
|
def as_dict(self) -> dict:
|
|
236
318
|
"""Serializes the DeletePublishedAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
|
237
319
|
body = {}
|
|
@@ -243,14 +325,13 @@ class DeletePublishedAppIntegrationOutput:
|
|
|
243
325
|
return body
|
|
244
326
|
|
|
245
327
|
@classmethod
|
|
246
|
-
def from_dict(cls, d: Dict[str,
|
|
328
|
+
def from_dict(cls, d: Dict[str, Any]) -> DeletePublishedAppIntegrationOutput:
|
|
247
329
|
"""Deserializes the DeletePublishedAppIntegrationOutput from a dictionary."""
|
|
248
330
|
return cls()
|
|
249
331
|
|
|
250
332
|
|
|
251
333
|
@dataclass
|
|
252
334
|
class DeleteResponse:
|
|
253
|
-
|
|
254
335
|
def as_dict(self) -> dict:
|
|
255
336
|
"""Serializes the DeleteResponse into a dictionary suitable for use as a JSON request body."""
|
|
256
337
|
body = {}
|
|
@@ -262,7 +343,7 @@ class DeleteResponse:
|
|
|
262
343
|
return body
|
|
263
344
|
|
|
264
345
|
@classmethod
|
|
265
|
-
def from_dict(cls, d: Dict[str,
|
|
346
|
+
def from_dict(cls, d: Dict[str, Any]) -> DeleteResponse:
|
|
266
347
|
"""Deserializes the DeleteResponse from a dictionary."""
|
|
267
348
|
return cls()
|
|
268
349
|
|
|
@@ -296,34 +377,48 @@ class FederationPolicy:
|
|
|
296
377
|
def as_dict(self) -> dict:
|
|
297
378
|
"""Serializes the FederationPolicy into a dictionary suitable for use as a JSON request body."""
|
|
298
379
|
body = {}
|
|
299
|
-
if self.create_time is not None:
|
|
300
|
-
|
|
301
|
-
if self.
|
|
302
|
-
|
|
303
|
-
if self.
|
|
304
|
-
|
|
380
|
+
if self.create_time is not None:
|
|
381
|
+
body["create_time"] = self.create_time
|
|
382
|
+
if self.description is not None:
|
|
383
|
+
body["description"] = self.description
|
|
384
|
+
if self.name is not None:
|
|
385
|
+
body["name"] = self.name
|
|
386
|
+
if self.oidc_policy:
|
|
387
|
+
body["oidc_policy"] = self.oidc_policy.as_dict()
|
|
388
|
+
if self.uid is not None:
|
|
389
|
+
body["uid"] = self.uid
|
|
390
|
+
if self.update_time is not None:
|
|
391
|
+
body["update_time"] = self.update_time
|
|
305
392
|
return body
|
|
306
393
|
|
|
307
394
|
def as_shallow_dict(self) -> dict:
|
|
308
395
|
"""Serializes the FederationPolicy into a shallow dictionary of its immediate attributes."""
|
|
309
396
|
body = {}
|
|
310
|
-
if self.create_time is not None:
|
|
311
|
-
|
|
312
|
-
if self.
|
|
313
|
-
|
|
314
|
-
if self.
|
|
315
|
-
|
|
397
|
+
if self.create_time is not None:
|
|
398
|
+
body["create_time"] = self.create_time
|
|
399
|
+
if self.description is not None:
|
|
400
|
+
body["description"] = self.description
|
|
401
|
+
if self.name is not None:
|
|
402
|
+
body["name"] = self.name
|
|
403
|
+
if self.oidc_policy:
|
|
404
|
+
body["oidc_policy"] = self.oidc_policy
|
|
405
|
+
if self.uid is not None:
|
|
406
|
+
body["uid"] = self.uid
|
|
407
|
+
if self.update_time is not None:
|
|
408
|
+
body["update_time"] = self.update_time
|
|
316
409
|
return body
|
|
317
410
|
|
|
318
411
|
@classmethod
|
|
319
|
-
def from_dict(cls, d: Dict[str,
|
|
412
|
+
def from_dict(cls, d: Dict[str, Any]) -> FederationPolicy:
|
|
320
413
|
"""Deserializes the FederationPolicy from a dictionary."""
|
|
321
|
-
return cls(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
414
|
+
return cls(
|
|
415
|
+
create_time=d.get("create_time", None),
|
|
416
|
+
description=d.get("description", None),
|
|
417
|
+
name=d.get("name", None),
|
|
418
|
+
oidc_policy=_from_dict(d, "oidc_policy", OidcFederationPolicy),
|
|
419
|
+
uid=d.get("uid", None),
|
|
420
|
+
update_time=d.get("update_time", None),
|
|
421
|
+
)
|
|
327
422
|
|
|
328
423
|
|
|
329
424
|
@dataclass
|
|
@@ -361,50 +456,73 @@ class GetCustomAppIntegrationOutput:
|
|
|
361
456
|
def as_dict(self) -> dict:
|
|
362
457
|
"""Serializes the GetCustomAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
|
363
458
|
body = {}
|
|
364
|
-
if self.client_id is not None:
|
|
365
|
-
|
|
366
|
-
if self.
|
|
367
|
-
|
|
368
|
-
if self.
|
|
369
|
-
|
|
370
|
-
if self.
|
|
371
|
-
|
|
372
|
-
if self.
|
|
373
|
-
|
|
459
|
+
if self.client_id is not None:
|
|
460
|
+
body["client_id"] = self.client_id
|
|
461
|
+
if self.confidential is not None:
|
|
462
|
+
body["confidential"] = self.confidential
|
|
463
|
+
if self.create_time is not None:
|
|
464
|
+
body["create_time"] = self.create_time
|
|
465
|
+
if self.created_by is not None:
|
|
466
|
+
body["created_by"] = self.created_by
|
|
467
|
+
if self.creator_username is not None:
|
|
468
|
+
body["creator_username"] = self.creator_username
|
|
469
|
+
if self.integration_id is not None:
|
|
470
|
+
body["integration_id"] = self.integration_id
|
|
471
|
+
if self.name is not None:
|
|
472
|
+
body["name"] = self.name
|
|
473
|
+
if self.redirect_urls:
|
|
474
|
+
body["redirect_urls"] = [v for v in self.redirect_urls]
|
|
475
|
+
if self.scopes:
|
|
476
|
+
body["scopes"] = [v for v in self.scopes]
|
|
477
|
+
if self.token_access_policy:
|
|
478
|
+
body["token_access_policy"] = self.token_access_policy.as_dict()
|
|
374
479
|
if self.user_authorized_scopes:
|
|
375
|
-
body[
|
|
480
|
+
body["user_authorized_scopes"] = [v for v in self.user_authorized_scopes]
|
|
376
481
|
return body
|
|
377
482
|
|
|
378
483
|
def as_shallow_dict(self) -> dict:
|
|
379
484
|
"""Serializes the GetCustomAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
|
380
485
|
body = {}
|
|
381
|
-
if self.client_id is not None:
|
|
382
|
-
|
|
383
|
-
if self.
|
|
384
|
-
|
|
385
|
-
if self.
|
|
386
|
-
|
|
387
|
-
if self.
|
|
388
|
-
|
|
389
|
-
if self.
|
|
390
|
-
|
|
391
|
-
if self.
|
|
486
|
+
if self.client_id is not None:
|
|
487
|
+
body["client_id"] = self.client_id
|
|
488
|
+
if self.confidential is not None:
|
|
489
|
+
body["confidential"] = self.confidential
|
|
490
|
+
if self.create_time is not None:
|
|
491
|
+
body["create_time"] = self.create_time
|
|
492
|
+
if self.created_by is not None:
|
|
493
|
+
body["created_by"] = self.created_by
|
|
494
|
+
if self.creator_username is not None:
|
|
495
|
+
body["creator_username"] = self.creator_username
|
|
496
|
+
if self.integration_id is not None:
|
|
497
|
+
body["integration_id"] = self.integration_id
|
|
498
|
+
if self.name is not None:
|
|
499
|
+
body["name"] = self.name
|
|
500
|
+
if self.redirect_urls:
|
|
501
|
+
body["redirect_urls"] = self.redirect_urls
|
|
502
|
+
if self.scopes:
|
|
503
|
+
body["scopes"] = self.scopes
|
|
504
|
+
if self.token_access_policy:
|
|
505
|
+
body["token_access_policy"] = self.token_access_policy
|
|
506
|
+
if self.user_authorized_scopes:
|
|
507
|
+
body["user_authorized_scopes"] = self.user_authorized_scopes
|
|
392
508
|
return body
|
|
393
509
|
|
|
394
510
|
@classmethod
|
|
395
|
-
def from_dict(cls, d: Dict[str,
|
|
511
|
+
def from_dict(cls, d: Dict[str, Any]) -> GetCustomAppIntegrationOutput:
|
|
396
512
|
"""Deserializes the GetCustomAppIntegrationOutput from a dictionary."""
|
|
397
|
-
return cls(
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
513
|
+
return cls(
|
|
514
|
+
client_id=d.get("client_id", None),
|
|
515
|
+
confidential=d.get("confidential", None),
|
|
516
|
+
create_time=d.get("create_time", None),
|
|
517
|
+
created_by=d.get("created_by", None),
|
|
518
|
+
creator_username=d.get("creator_username", None),
|
|
519
|
+
integration_id=d.get("integration_id", None),
|
|
520
|
+
name=d.get("name", None),
|
|
521
|
+
redirect_urls=d.get("redirect_urls", None),
|
|
522
|
+
scopes=d.get("scopes", None),
|
|
523
|
+
token_access_policy=_from_dict(d, "token_access_policy", TokenAccessPolicy),
|
|
524
|
+
user_authorized_scopes=d.get("user_authorized_scopes", None),
|
|
525
|
+
)
|
|
408
526
|
|
|
409
527
|
|
|
410
528
|
@dataclass
|
|
@@ -417,22 +535,28 @@ class GetCustomAppIntegrationsOutput:
|
|
|
417
535
|
def as_dict(self) -> dict:
|
|
418
536
|
"""Serializes the GetCustomAppIntegrationsOutput into a dictionary suitable for use as a JSON request body."""
|
|
419
537
|
body = {}
|
|
420
|
-
if self.apps:
|
|
421
|
-
|
|
538
|
+
if self.apps:
|
|
539
|
+
body["apps"] = [v.as_dict() for v in self.apps]
|
|
540
|
+
if self.next_page_token is not None:
|
|
541
|
+
body["next_page_token"] = self.next_page_token
|
|
422
542
|
return body
|
|
423
543
|
|
|
424
544
|
def as_shallow_dict(self) -> dict:
|
|
425
545
|
"""Serializes the GetCustomAppIntegrationsOutput into a shallow dictionary of its immediate attributes."""
|
|
426
546
|
body = {}
|
|
427
|
-
if self.apps:
|
|
428
|
-
|
|
547
|
+
if self.apps:
|
|
548
|
+
body["apps"] = self.apps
|
|
549
|
+
if self.next_page_token is not None:
|
|
550
|
+
body["next_page_token"] = self.next_page_token
|
|
429
551
|
return body
|
|
430
552
|
|
|
431
553
|
@classmethod
|
|
432
|
-
def from_dict(cls, d: Dict[str,
|
|
554
|
+
def from_dict(cls, d: Dict[str, Any]) -> GetCustomAppIntegrationsOutput:
|
|
433
555
|
"""Deserializes the GetCustomAppIntegrationsOutput from a dictionary."""
|
|
434
|
-
return cls(
|
|
435
|
-
|
|
556
|
+
return cls(
|
|
557
|
+
apps=_repeated_dict(d, "apps", GetCustomAppIntegrationOutput),
|
|
558
|
+
next_page_token=d.get("next_page_token", None),
|
|
559
|
+
)
|
|
436
560
|
|
|
437
561
|
|
|
438
562
|
@dataclass
|
|
@@ -456,34 +580,48 @@ class GetPublishedAppIntegrationOutput:
|
|
|
456
580
|
def as_dict(self) -> dict:
|
|
457
581
|
"""Serializes the GetPublishedAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
|
458
582
|
body = {}
|
|
459
|
-
if self.app_id is not None:
|
|
460
|
-
|
|
461
|
-
if self.
|
|
462
|
-
|
|
463
|
-
if self.
|
|
464
|
-
|
|
583
|
+
if self.app_id is not None:
|
|
584
|
+
body["app_id"] = self.app_id
|
|
585
|
+
if self.create_time is not None:
|
|
586
|
+
body["create_time"] = self.create_time
|
|
587
|
+
if self.created_by is not None:
|
|
588
|
+
body["created_by"] = self.created_by
|
|
589
|
+
if self.integration_id is not None:
|
|
590
|
+
body["integration_id"] = self.integration_id
|
|
591
|
+
if self.name is not None:
|
|
592
|
+
body["name"] = self.name
|
|
593
|
+
if self.token_access_policy:
|
|
594
|
+
body["token_access_policy"] = self.token_access_policy.as_dict()
|
|
465
595
|
return body
|
|
466
596
|
|
|
467
597
|
def as_shallow_dict(self) -> dict:
|
|
468
598
|
"""Serializes the GetPublishedAppIntegrationOutput into a shallow dictionary of its immediate attributes."""
|
|
469
599
|
body = {}
|
|
470
|
-
if self.app_id is not None:
|
|
471
|
-
|
|
472
|
-
if self.
|
|
473
|
-
|
|
474
|
-
if self.
|
|
475
|
-
|
|
600
|
+
if self.app_id is not None:
|
|
601
|
+
body["app_id"] = self.app_id
|
|
602
|
+
if self.create_time is not None:
|
|
603
|
+
body["create_time"] = self.create_time
|
|
604
|
+
if self.created_by is not None:
|
|
605
|
+
body["created_by"] = self.created_by
|
|
606
|
+
if self.integration_id is not None:
|
|
607
|
+
body["integration_id"] = self.integration_id
|
|
608
|
+
if self.name is not None:
|
|
609
|
+
body["name"] = self.name
|
|
610
|
+
if self.token_access_policy:
|
|
611
|
+
body["token_access_policy"] = self.token_access_policy
|
|
476
612
|
return body
|
|
477
613
|
|
|
478
614
|
@classmethod
|
|
479
|
-
def from_dict(cls, d: Dict[str,
|
|
615
|
+
def from_dict(cls, d: Dict[str, Any]) -> GetPublishedAppIntegrationOutput:
|
|
480
616
|
"""Deserializes the GetPublishedAppIntegrationOutput from a dictionary."""
|
|
481
|
-
return cls(
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
617
|
+
return cls(
|
|
618
|
+
app_id=d.get("app_id", None),
|
|
619
|
+
create_time=d.get("create_time", None),
|
|
620
|
+
created_by=d.get("created_by", None),
|
|
621
|
+
integration_id=d.get("integration_id", None),
|
|
622
|
+
name=d.get("name", None),
|
|
623
|
+
token_access_policy=_from_dict(d, "token_access_policy", TokenAccessPolicy),
|
|
624
|
+
)
|
|
487
625
|
|
|
488
626
|
|
|
489
627
|
@dataclass
|
|
@@ -496,22 +634,28 @@ class GetPublishedAppIntegrationsOutput:
|
|
|
496
634
|
def as_dict(self) -> dict:
|
|
497
635
|
"""Serializes the GetPublishedAppIntegrationsOutput into a dictionary suitable for use as a JSON request body."""
|
|
498
636
|
body = {}
|
|
499
|
-
if self.apps:
|
|
500
|
-
|
|
637
|
+
if self.apps:
|
|
638
|
+
body["apps"] = [v.as_dict() for v in self.apps]
|
|
639
|
+
if self.next_page_token is not None:
|
|
640
|
+
body["next_page_token"] = self.next_page_token
|
|
501
641
|
return body
|
|
502
642
|
|
|
503
643
|
def as_shallow_dict(self) -> dict:
|
|
504
644
|
"""Serializes the GetPublishedAppIntegrationsOutput into a shallow dictionary of its immediate attributes."""
|
|
505
645
|
body = {}
|
|
506
|
-
if self.apps:
|
|
507
|
-
|
|
646
|
+
if self.apps:
|
|
647
|
+
body["apps"] = self.apps
|
|
648
|
+
if self.next_page_token is not None:
|
|
649
|
+
body["next_page_token"] = self.next_page_token
|
|
508
650
|
return body
|
|
509
651
|
|
|
510
652
|
@classmethod
|
|
511
|
-
def from_dict(cls, d: Dict[str,
|
|
653
|
+
def from_dict(cls, d: Dict[str, Any]) -> GetPublishedAppIntegrationsOutput:
|
|
512
654
|
"""Deserializes the GetPublishedAppIntegrationsOutput from a dictionary."""
|
|
513
|
-
return cls(
|
|
514
|
-
|
|
655
|
+
return cls(
|
|
656
|
+
apps=_repeated_dict(d, "apps", GetPublishedAppIntegrationOutput),
|
|
657
|
+
next_page_token=d.get("next_page_token", None),
|
|
658
|
+
)
|
|
515
659
|
|
|
516
660
|
|
|
517
661
|
@dataclass
|
|
@@ -526,22 +670,25 @@ class GetPublishedAppsOutput:
|
|
|
526
670
|
def as_dict(self) -> dict:
|
|
527
671
|
"""Serializes the GetPublishedAppsOutput into a dictionary suitable for use as a JSON request body."""
|
|
528
672
|
body = {}
|
|
529
|
-
if self.apps:
|
|
530
|
-
|
|
673
|
+
if self.apps:
|
|
674
|
+
body["apps"] = [v.as_dict() for v in self.apps]
|
|
675
|
+
if self.next_page_token is not None:
|
|
676
|
+
body["next_page_token"] = self.next_page_token
|
|
531
677
|
return body
|
|
532
678
|
|
|
533
679
|
def as_shallow_dict(self) -> dict:
|
|
534
680
|
"""Serializes the GetPublishedAppsOutput into a shallow dictionary of its immediate attributes."""
|
|
535
681
|
body = {}
|
|
536
|
-
if self.apps:
|
|
537
|
-
|
|
682
|
+
if self.apps:
|
|
683
|
+
body["apps"] = self.apps
|
|
684
|
+
if self.next_page_token is not None:
|
|
685
|
+
body["next_page_token"] = self.next_page_token
|
|
538
686
|
return body
|
|
539
687
|
|
|
540
688
|
@classmethod
|
|
541
|
-
def from_dict(cls, d: Dict[str,
|
|
689
|
+
def from_dict(cls, d: Dict[str, Any]) -> GetPublishedAppsOutput:
|
|
542
690
|
"""Deserializes the GetPublishedAppsOutput from a dictionary."""
|
|
543
|
-
return cls(apps=_repeated_dict(d,
|
|
544
|
-
next_page_token=d.get('next_page_token', None))
|
|
691
|
+
return cls(apps=_repeated_dict(d, "apps", PublishedAppOutput), next_page_token=d.get("next_page_token", None))
|
|
545
692
|
|
|
546
693
|
|
|
547
694
|
@dataclass
|
|
@@ -553,22 +700,27 @@ class ListFederationPoliciesResponse:
|
|
|
553
700
|
def as_dict(self) -> dict:
|
|
554
701
|
"""Serializes the ListFederationPoliciesResponse into a dictionary suitable for use as a JSON request body."""
|
|
555
702
|
body = {}
|
|
556
|
-
if self.next_page_token is not None:
|
|
557
|
-
|
|
703
|
+
if self.next_page_token is not None:
|
|
704
|
+
body["next_page_token"] = self.next_page_token
|
|
705
|
+
if self.policies:
|
|
706
|
+
body["policies"] = [v.as_dict() for v in self.policies]
|
|
558
707
|
return body
|
|
559
708
|
|
|
560
709
|
def as_shallow_dict(self) -> dict:
|
|
561
710
|
"""Serializes the ListFederationPoliciesResponse into a shallow dictionary of its immediate attributes."""
|
|
562
711
|
body = {}
|
|
563
|
-
if self.next_page_token is not None:
|
|
564
|
-
|
|
712
|
+
if self.next_page_token is not None:
|
|
713
|
+
body["next_page_token"] = self.next_page_token
|
|
714
|
+
if self.policies:
|
|
715
|
+
body["policies"] = self.policies
|
|
565
716
|
return body
|
|
566
717
|
|
|
567
718
|
@classmethod
|
|
568
|
-
def from_dict(cls, d: Dict[str,
|
|
719
|
+
def from_dict(cls, d: Dict[str, Any]) -> ListFederationPoliciesResponse:
|
|
569
720
|
"""Deserializes the ListFederationPoliciesResponse from a dictionary."""
|
|
570
|
-
return cls(
|
|
571
|
-
|
|
721
|
+
return cls(
|
|
722
|
+
next_page_token=d.get("next_page_token", None), policies=_repeated_dict(d, "policies", FederationPolicy)
|
|
723
|
+
)
|
|
572
724
|
|
|
573
725
|
|
|
574
726
|
@dataclass
|
|
@@ -582,22 +734,25 @@ class ListServicePrincipalSecretsResponse:
|
|
|
582
734
|
def as_dict(self) -> dict:
|
|
583
735
|
"""Serializes the ListServicePrincipalSecretsResponse into a dictionary suitable for use as a JSON request body."""
|
|
584
736
|
body = {}
|
|
585
|
-
if self.next_page_token is not None:
|
|
586
|
-
|
|
737
|
+
if self.next_page_token is not None:
|
|
738
|
+
body["next_page_token"] = self.next_page_token
|
|
739
|
+
if self.secrets:
|
|
740
|
+
body["secrets"] = [v.as_dict() for v in self.secrets]
|
|
587
741
|
return body
|
|
588
742
|
|
|
589
743
|
def as_shallow_dict(self) -> dict:
|
|
590
744
|
"""Serializes the ListServicePrincipalSecretsResponse into a shallow dictionary of its immediate attributes."""
|
|
591
745
|
body = {}
|
|
592
|
-
if self.next_page_token is not None:
|
|
593
|
-
|
|
746
|
+
if self.next_page_token is not None:
|
|
747
|
+
body["next_page_token"] = self.next_page_token
|
|
748
|
+
if self.secrets:
|
|
749
|
+
body["secrets"] = self.secrets
|
|
594
750
|
return body
|
|
595
751
|
|
|
596
752
|
@classmethod
|
|
597
|
-
def from_dict(cls, d: Dict[str,
|
|
753
|
+
def from_dict(cls, d: Dict[str, Any]) -> ListServicePrincipalSecretsResponse:
|
|
598
754
|
"""Deserializes the ListServicePrincipalSecretsResponse from a dictionary."""
|
|
599
|
-
return cls(next_page_token=d.get(
|
|
600
|
-
secrets=_repeated_dict(d, 'secrets', SecretInfo))
|
|
755
|
+
return cls(next_page_token=d.get("next_page_token", None), secrets=_repeated_dict(d, "secrets", SecretInfo))
|
|
601
756
|
|
|
602
757
|
|
|
603
758
|
@dataclass
|
|
@@ -615,10 +770,11 @@ class OidcFederationPolicy:
|
|
|
615
770
|
"""The required token issuer, as specified in the 'iss' claim of federated tokens."""
|
|
616
771
|
|
|
617
772
|
jwks_json: Optional[str] = None
|
|
618
|
-
"""The public keys used to validate the signature of federated tokens, in JWKS format.
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
endpoint
|
|
773
|
+
"""The public keys used to validate the signature of federated tokens, in JWKS format. Most use
|
|
774
|
+
cases should not need to specify this field. If jwks_uri and jwks_json are both unspecified
|
|
775
|
+
(recommended), Databricks automatically fetches the public keys from your issuer’s well known
|
|
776
|
+
endpoint. Databricks strongly recommends relying on your issuer’s well known endpoint for
|
|
777
|
+
discovering public keys."""
|
|
622
778
|
|
|
623
779
|
subject: Optional[str] = None
|
|
624
780
|
"""The required token subject, as specified in the subject claim of federated tokens. Must be
|
|
@@ -631,31 +787,43 @@ class OidcFederationPolicy:
|
|
|
631
787
|
def as_dict(self) -> dict:
|
|
632
788
|
"""Serializes the OidcFederationPolicy into a dictionary suitable for use as a JSON request body."""
|
|
633
789
|
body = {}
|
|
634
|
-
if self.audiences:
|
|
635
|
-
|
|
636
|
-
if self.
|
|
637
|
-
|
|
638
|
-
if self.
|
|
790
|
+
if self.audiences:
|
|
791
|
+
body["audiences"] = [v for v in self.audiences]
|
|
792
|
+
if self.issuer is not None:
|
|
793
|
+
body["issuer"] = self.issuer
|
|
794
|
+
if self.jwks_json is not None:
|
|
795
|
+
body["jwks_json"] = self.jwks_json
|
|
796
|
+
if self.subject is not None:
|
|
797
|
+
body["subject"] = self.subject
|
|
798
|
+
if self.subject_claim is not None:
|
|
799
|
+
body["subject_claim"] = self.subject_claim
|
|
639
800
|
return body
|
|
640
801
|
|
|
641
802
|
def as_shallow_dict(self) -> dict:
|
|
642
803
|
"""Serializes the OidcFederationPolicy into a shallow dictionary of its immediate attributes."""
|
|
643
804
|
body = {}
|
|
644
|
-
if self.audiences:
|
|
645
|
-
|
|
646
|
-
if self.
|
|
647
|
-
|
|
648
|
-
if self.
|
|
805
|
+
if self.audiences:
|
|
806
|
+
body["audiences"] = self.audiences
|
|
807
|
+
if self.issuer is not None:
|
|
808
|
+
body["issuer"] = self.issuer
|
|
809
|
+
if self.jwks_json is not None:
|
|
810
|
+
body["jwks_json"] = self.jwks_json
|
|
811
|
+
if self.subject is not None:
|
|
812
|
+
body["subject"] = self.subject
|
|
813
|
+
if self.subject_claim is not None:
|
|
814
|
+
body["subject_claim"] = self.subject_claim
|
|
649
815
|
return body
|
|
650
816
|
|
|
651
817
|
@classmethod
|
|
652
|
-
def from_dict(cls, d: Dict[str,
|
|
818
|
+
def from_dict(cls, d: Dict[str, Any]) -> OidcFederationPolicy:
|
|
653
819
|
"""Deserializes the OidcFederationPolicy from a dictionary."""
|
|
654
|
-
return cls(
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
820
|
+
return cls(
|
|
821
|
+
audiences=d.get("audiences", None),
|
|
822
|
+
issuer=d.get("issuer", None),
|
|
823
|
+
jwks_json=d.get("jwks_json", None),
|
|
824
|
+
subject=d.get("subject", None),
|
|
825
|
+
subject_claim=d.get("subject_claim", None),
|
|
826
|
+
)
|
|
659
827
|
|
|
660
828
|
|
|
661
829
|
@dataclass
|
|
@@ -685,39 +853,53 @@ class PublishedAppOutput:
|
|
|
685
853
|
def as_dict(self) -> dict:
|
|
686
854
|
"""Serializes the PublishedAppOutput into a dictionary suitable for use as a JSON request body."""
|
|
687
855
|
body = {}
|
|
688
|
-
if self.app_id is not None:
|
|
689
|
-
|
|
690
|
-
if self.
|
|
856
|
+
if self.app_id is not None:
|
|
857
|
+
body["app_id"] = self.app_id
|
|
858
|
+
if self.client_id is not None:
|
|
859
|
+
body["client_id"] = self.client_id
|
|
860
|
+
if self.description is not None:
|
|
861
|
+
body["description"] = self.description
|
|
691
862
|
if self.is_confidential_client is not None:
|
|
692
|
-
body[
|
|
693
|
-
if self.name is not None:
|
|
694
|
-
|
|
695
|
-
if self.
|
|
863
|
+
body["is_confidential_client"] = self.is_confidential_client
|
|
864
|
+
if self.name is not None:
|
|
865
|
+
body["name"] = self.name
|
|
866
|
+
if self.redirect_urls:
|
|
867
|
+
body["redirect_urls"] = [v for v in self.redirect_urls]
|
|
868
|
+
if self.scopes:
|
|
869
|
+
body["scopes"] = [v for v in self.scopes]
|
|
696
870
|
return body
|
|
697
871
|
|
|
698
872
|
def as_shallow_dict(self) -> dict:
|
|
699
873
|
"""Serializes the PublishedAppOutput into a shallow dictionary of its immediate attributes."""
|
|
700
874
|
body = {}
|
|
701
|
-
if self.app_id is not None:
|
|
702
|
-
|
|
703
|
-
if self.
|
|
875
|
+
if self.app_id is not None:
|
|
876
|
+
body["app_id"] = self.app_id
|
|
877
|
+
if self.client_id is not None:
|
|
878
|
+
body["client_id"] = self.client_id
|
|
879
|
+
if self.description is not None:
|
|
880
|
+
body["description"] = self.description
|
|
704
881
|
if self.is_confidential_client is not None:
|
|
705
|
-
body[
|
|
706
|
-
if self.name is not None:
|
|
707
|
-
|
|
708
|
-
if self.
|
|
882
|
+
body["is_confidential_client"] = self.is_confidential_client
|
|
883
|
+
if self.name is not None:
|
|
884
|
+
body["name"] = self.name
|
|
885
|
+
if self.redirect_urls:
|
|
886
|
+
body["redirect_urls"] = self.redirect_urls
|
|
887
|
+
if self.scopes:
|
|
888
|
+
body["scopes"] = self.scopes
|
|
709
889
|
return body
|
|
710
890
|
|
|
711
891
|
@classmethod
|
|
712
|
-
def from_dict(cls, d: Dict[str,
|
|
892
|
+
def from_dict(cls, d: Dict[str, Any]) -> PublishedAppOutput:
|
|
713
893
|
"""Deserializes the PublishedAppOutput from a dictionary."""
|
|
714
|
-
return cls(
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
894
|
+
return cls(
|
|
895
|
+
app_id=d.get("app_id", None),
|
|
896
|
+
client_id=d.get("client_id", None),
|
|
897
|
+
description=d.get("description", None),
|
|
898
|
+
is_confidential_client=d.get("is_confidential_client", None),
|
|
899
|
+
name=d.get("name", None),
|
|
900
|
+
redirect_urls=d.get("redirect_urls", None),
|
|
901
|
+
scopes=d.get("scopes", None),
|
|
902
|
+
)
|
|
721
903
|
|
|
722
904
|
|
|
723
905
|
@dataclass
|
|
@@ -725,6 +907,9 @@ class SecretInfo:
|
|
|
725
907
|
create_time: Optional[str] = None
|
|
726
908
|
"""UTC time when the secret was created"""
|
|
727
909
|
|
|
910
|
+
expire_time: Optional[str] = None
|
|
911
|
+
"""UTC time when the secret will expire. If the field is not present, the secret does not expire."""
|
|
912
|
+
|
|
728
913
|
id: Optional[str] = None
|
|
729
914
|
"""ID of the secret"""
|
|
730
915
|
|
|
@@ -740,31 +925,48 @@ class SecretInfo:
|
|
|
740
925
|
def as_dict(self) -> dict:
|
|
741
926
|
"""Serializes the SecretInfo into a dictionary suitable for use as a JSON request body."""
|
|
742
927
|
body = {}
|
|
743
|
-
if self.create_time is not None:
|
|
744
|
-
|
|
745
|
-
if self.
|
|
746
|
-
|
|
747
|
-
if self.
|
|
928
|
+
if self.create_time is not None:
|
|
929
|
+
body["create_time"] = self.create_time
|
|
930
|
+
if self.expire_time is not None:
|
|
931
|
+
body["expire_time"] = self.expire_time
|
|
932
|
+
if self.id is not None:
|
|
933
|
+
body["id"] = self.id
|
|
934
|
+
if self.secret_hash is not None:
|
|
935
|
+
body["secret_hash"] = self.secret_hash
|
|
936
|
+
if self.status is not None:
|
|
937
|
+
body["status"] = self.status
|
|
938
|
+
if self.update_time is not None:
|
|
939
|
+
body["update_time"] = self.update_time
|
|
748
940
|
return body
|
|
749
941
|
|
|
750
942
|
def as_shallow_dict(self) -> dict:
|
|
751
943
|
"""Serializes the SecretInfo into a shallow dictionary of its immediate attributes."""
|
|
752
944
|
body = {}
|
|
753
|
-
if self.create_time is not None:
|
|
754
|
-
|
|
755
|
-
if self.
|
|
756
|
-
|
|
757
|
-
if self.
|
|
945
|
+
if self.create_time is not None:
|
|
946
|
+
body["create_time"] = self.create_time
|
|
947
|
+
if self.expire_time is not None:
|
|
948
|
+
body["expire_time"] = self.expire_time
|
|
949
|
+
if self.id is not None:
|
|
950
|
+
body["id"] = self.id
|
|
951
|
+
if self.secret_hash is not None:
|
|
952
|
+
body["secret_hash"] = self.secret_hash
|
|
953
|
+
if self.status is not None:
|
|
954
|
+
body["status"] = self.status
|
|
955
|
+
if self.update_time is not None:
|
|
956
|
+
body["update_time"] = self.update_time
|
|
758
957
|
return body
|
|
759
958
|
|
|
760
959
|
@classmethod
|
|
761
|
-
def from_dict(cls, d: Dict[str,
|
|
960
|
+
def from_dict(cls, d: Dict[str, Any]) -> SecretInfo:
|
|
762
961
|
"""Deserializes the SecretInfo from a dictionary."""
|
|
763
|
-
return cls(
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
962
|
+
return cls(
|
|
963
|
+
create_time=d.get("create_time", None),
|
|
964
|
+
expire_time=d.get("expire_time", None),
|
|
965
|
+
id=d.get("id", None),
|
|
966
|
+
secret_hash=d.get("secret_hash", None),
|
|
967
|
+
status=d.get("status", None),
|
|
968
|
+
update_time=d.get("update_time", None),
|
|
969
|
+
)
|
|
768
970
|
|
|
769
971
|
|
|
770
972
|
@dataclass
|
|
@@ -779,25 +981,27 @@ class TokenAccessPolicy:
|
|
|
779
981
|
"""Serializes the TokenAccessPolicy into a dictionary suitable for use as a JSON request body."""
|
|
780
982
|
body = {}
|
|
781
983
|
if self.access_token_ttl_in_minutes is not None:
|
|
782
|
-
body[
|
|
984
|
+
body["access_token_ttl_in_minutes"] = self.access_token_ttl_in_minutes
|
|
783
985
|
if self.refresh_token_ttl_in_minutes is not None:
|
|
784
|
-
body[
|
|
986
|
+
body["refresh_token_ttl_in_minutes"] = self.refresh_token_ttl_in_minutes
|
|
785
987
|
return body
|
|
786
988
|
|
|
787
989
|
def as_shallow_dict(self) -> dict:
|
|
788
990
|
"""Serializes the TokenAccessPolicy into a shallow dictionary of its immediate attributes."""
|
|
789
991
|
body = {}
|
|
790
992
|
if self.access_token_ttl_in_minutes is not None:
|
|
791
|
-
body[
|
|
993
|
+
body["access_token_ttl_in_minutes"] = self.access_token_ttl_in_minutes
|
|
792
994
|
if self.refresh_token_ttl_in_minutes is not None:
|
|
793
|
-
body[
|
|
995
|
+
body["refresh_token_ttl_in_minutes"] = self.refresh_token_ttl_in_minutes
|
|
794
996
|
return body
|
|
795
997
|
|
|
796
998
|
@classmethod
|
|
797
|
-
def from_dict(cls, d: Dict[str,
|
|
999
|
+
def from_dict(cls, d: Dict[str, Any]) -> TokenAccessPolicy:
|
|
798
1000
|
"""Deserializes the TokenAccessPolicy from a dictionary."""
|
|
799
|
-
return cls(
|
|
800
|
-
|
|
1001
|
+
return cls(
|
|
1002
|
+
access_token_ttl_in_minutes=d.get("access_token_ttl_in_minutes", None),
|
|
1003
|
+
refresh_token_ttl_in_minutes=d.get("refresh_token_ttl_in_minutes", None),
|
|
1004
|
+
)
|
|
801
1005
|
|
|
802
1006
|
|
|
803
1007
|
@dataclass
|
|
@@ -821,37 +1025,47 @@ class UpdateCustomAppIntegration:
|
|
|
821
1025
|
def as_dict(self) -> dict:
|
|
822
1026
|
"""Serializes the UpdateCustomAppIntegration into a dictionary suitable for use as a JSON request body."""
|
|
823
1027
|
body = {}
|
|
824
|
-
if self.integration_id is not None:
|
|
825
|
-
|
|
826
|
-
if self.
|
|
827
|
-
|
|
1028
|
+
if self.integration_id is not None:
|
|
1029
|
+
body["integration_id"] = self.integration_id
|
|
1030
|
+
if self.redirect_urls:
|
|
1031
|
+
body["redirect_urls"] = [v for v in self.redirect_urls]
|
|
1032
|
+
if self.scopes:
|
|
1033
|
+
body["scopes"] = [v for v in self.scopes]
|
|
1034
|
+
if self.token_access_policy:
|
|
1035
|
+
body["token_access_policy"] = self.token_access_policy.as_dict()
|
|
828
1036
|
if self.user_authorized_scopes:
|
|
829
|
-
body[
|
|
1037
|
+
body["user_authorized_scopes"] = [v for v in self.user_authorized_scopes]
|
|
830
1038
|
return body
|
|
831
1039
|
|
|
832
1040
|
def as_shallow_dict(self) -> dict:
|
|
833
1041
|
"""Serializes the UpdateCustomAppIntegration into a shallow dictionary of its immediate attributes."""
|
|
834
1042
|
body = {}
|
|
835
|
-
if self.integration_id is not None:
|
|
836
|
-
|
|
837
|
-
if self.
|
|
838
|
-
|
|
839
|
-
if self.
|
|
1043
|
+
if self.integration_id is not None:
|
|
1044
|
+
body["integration_id"] = self.integration_id
|
|
1045
|
+
if self.redirect_urls:
|
|
1046
|
+
body["redirect_urls"] = self.redirect_urls
|
|
1047
|
+
if self.scopes:
|
|
1048
|
+
body["scopes"] = self.scopes
|
|
1049
|
+
if self.token_access_policy:
|
|
1050
|
+
body["token_access_policy"] = self.token_access_policy
|
|
1051
|
+
if self.user_authorized_scopes:
|
|
1052
|
+
body["user_authorized_scopes"] = self.user_authorized_scopes
|
|
840
1053
|
return body
|
|
841
1054
|
|
|
842
1055
|
@classmethod
|
|
843
|
-
def from_dict(cls, d: Dict[str,
|
|
1056
|
+
def from_dict(cls, d: Dict[str, Any]) -> UpdateCustomAppIntegration:
|
|
844
1057
|
"""Deserializes the UpdateCustomAppIntegration from a dictionary."""
|
|
845
|
-
return cls(
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
1058
|
+
return cls(
|
|
1059
|
+
integration_id=d.get("integration_id", None),
|
|
1060
|
+
redirect_urls=d.get("redirect_urls", None),
|
|
1061
|
+
scopes=d.get("scopes", None),
|
|
1062
|
+
token_access_policy=_from_dict(d, "token_access_policy", TokenAccessPolicy),
|
|
1063
|
+
user_authorized_scopes=d.get("user_authorized_scopes", None),
|
|
1064
|
+
)
|
|
850
1065
|
|
|
851
1066
|
|
|
852
1067
|
@dataclass
|
|
853
1068
|
class UpdateCustomAppIntegrationOutput:
|
|
854
|
-
|
|
855
1069
|
def as_dict(self) -> dict:
|
|
856
1070
|
"""Serializes the UpdateCustomAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
|
857
1071
|
body = {}
|
|
@@ -863,7 +1077,7 @@ class UpdateCustomAppIntegrationOutput:
|
|
|
863
1077
|
return body
|
|
864
1078
|
|
|
865
1079
|
@classmethod
|
|
866
|
-
def from_dict(cls, d: Dict[str,
|
|
1080
|
+
def from_dict(cls, d: Dict[str, Any]) -> UpdateCustomAppIntegrationOutput:
|
|
867
1081
|
"""Deserializes the UpdateCustomAppIntegrationOutput from a dictionary."""
|
|
868
1082
|
return cls()
|
|
869
1083
|
|
|
@@ -878,27 +1092,32 @@ class UpdatePublishedAppIntegration:
|
|
|
878
1092
|
def as_dict(self) -> dict:
|
|
879
1093
|
"""Serializes the UpdatePublishedAppIntegration into a dictionary suitable for use as a JSON request body."""
|
|
880
1094
|
body = {}
|
|
881
|
-
if self.integration_id is not None:
|
|
882
|
-
|
|
1095
|
+
if self.integration_id is not None:
|
|
1096
|
+
body["integration_id"] = self.integration_id
|
|
1097
|
+
if self.token_access_policy:
|
|
1098
|
+
body["token_access_policy"] = self.token_access_policy.as_dict()
|
|
883
1099
|
return body
|
|
884
1100
|
|
|
885
1101
|
def as_shallow_dict(self) -> dict:
|
|
886
1102
|
"""Serializes the UpdatePublishedAppIntegration into a shallow dictionary of its immediate attributes."""
|
|
887
1103
|
body = {}
|
|
888
|
-
if self.integration_id is not None:
|
|
889
|
-
|
|
1104
|
+
if self.integration_id is not None:
|
|
1105
|
+
body["integration_id"] = self.integration_id
|
|
1106
|
+
if self.token_access_policy:
|
|
1107
|
+
body["token_access_policy"] = self.token_access_policy
|
|
890
1108
|
return body
|
|
891
1109
|
|
|
892
1110
|
@classmethod
|
|
893
|
-
def from_dict(cls, d: Dict[str,
|
|
1111
|
+
def from_dict(cls, d: Dict[str, Any]) -> UpdatePublishedAppIntegration:
|
|
894
1112
|
"""Deserializes the UpdatePublishedAppIntegration from a dictionary."""
|
|
895
|
-
return cls(
|
|
896
|
-
|
|
1113
|
+
return cls(
|
|
1114
|
+
integration_id=d.get("integration_id", None),
|
|
1115
|
+
token_access_policy=_from_dict(d, "token_access_policy", TokenAccessPolicy),
|
|
1116
|
+
)
|
|
897
1117
|
|
|
898
1118
|
|
|
899
1119
|
@dataclass
|
|
900
1120
|
class UpdatePublishedAppIntegrationOutput:
|
|
901
|
-
|
|
902
1121
|
def as_dict(self) -> dict:
|
|
903
1122
|
"""Serializes the UpdatePublishedAppIntegrationOutput into a dictionary suitable for use as a JSON request body."""
|
|
904
1123
|
body = {}
|
|
@@ -910,27 +1129,27 @@ class UpdatePublishedAppIntegrationOutput:
|
|
|
910
1129
|
return body
|
|
911
1130
|
|
|
912
1131
|
@classmethod
|
|
913
|
-
def from_dict(cls, d: Dict[str,
|
|
1132
|
+
def from_dict(cls, d: Dict[str, Any]) -> UpdatePublishedAppIntegrationOutput:
|
|
914
1133
|
"""Deserializes the UpdatePublishedAppIntegrationOutput from a dictionary."""
|
|
915
1134
|
return cls()
|
|
916
1135
|
|
|
917
1136
|
|
|
918
1137
|
class AccountFederationPolicyAPI:
|
|
919
1138
|
"""These APIs manage account federation policies.
|
|
920
|
-
|
|
1139
|
+
|
|
921
1140
|
Account federation policies allow users and service principals in your Databricks account to securely
|
|
922
1141
|
access Databricks APIs using tokens from your trusted identity providers (IdPs).
|
|
923
|
-
|
|
1142
|
+
|
|
924
1143
|
With token federation, your users and service principals can exchange tokens from your IdP for Databricks
|
|
925
1144
|
OAuth tokens, which can be used to access Databricks APIs. Token federation eliminates the need to manage
|
|
926
1145
|
Databricks secrets, and allows you to centralize management of token issuance policies in your IdP.
|
|
927
1146
|
Databricks token federation is typically used in combination with [SCIM], so users in your IdP are
|
|
928
1147
|
synchronized into your Databricks account.
|
|
929
|
-
|
|
1148
|
+
|
|
930
1149
|
Token federation is configured in your Databricks account using an account federation policy. An account
|
|
931
1150
|
federation policy specifies: * which IdP, or issuer, your Databricks account should accept tokens from *
|
|
932
1151
|
how to determine which Databricks user, or subject, a token is issued for
|
|
933
|
-
|
|
1152
|
+
|
|
934
1153
|
To configure a federation policy, you provide the following: * The required token __issuer__, as specified
|
|
935
1154
|
in the “iss” claim of your tokens. The issuer is an https URL that identifies your IdP. * The allowed
|
|
936
1155
|
token __audiences__, as specified in the “aud” claim of your tokens. This identifier is intended to
|
|
@@ -941,117 +1160,122 @@ class AccountFederationPolicyAPI:
|
|
|
941
1160
|
public keys used to validate the signature of your tokens, in JWKS format. If unspecified (recommended),
|
|
942
1161
|
Databricks automatically fetches the public keys from your issuer’s well known endpoint. Databricks
|
|
943
1162
|
strongly recommends relying on your issuer’s well known endpoint for discovering public keys.
|
|
944
|
-
|
|
1163
|
+
|
|
945
1164
|
An example federation policy is: ``` issuer: "https://idp.mycompany.com/oidc" audiences: ["databricks"]
|
|
946
1165
|
subject_claim: "sub" ```
|
|
947
|
-
|
|
1166
|
+
|
|
948
1167
|
An example JWT token body that matches this policy and could be used to authenticate to Databricks as user
|
|
949
1168
|
`username@mycompany.com` is: ``` { "iss": "https://idp.mycompany.com/oidc", "aud": "databricks", "sub":
|
|
950
1169
|
"username@mycompany.com" } ```
|
|
951
|
-
|
|
1170
|
+
|
|
952
1171
|
You may also need to configure your IdP to generate tokens for your users to exchange with Databricks, if
|
|
953
1172
|
your users do not already have the ability to generate tokens that are compatible with your federation
|
|
954
1173
|
policy.
|
|
955
|
-
|
|
1174
|
+
|
|
956
1175
|
You do not need to configure an OAuth application in Databricks to use token federation.
|
|
957
|
-
|
|
1176
|
+
|
|
958
1177
|
[SCIM]: https://docs.databricks.com/admin/users-groups/scim/index.html"""
|
|
959
1178
|
|
|
960
1179
|
def __init__(self, api_client):
|
|
961
1180
|
self._api = api_client
|
|
962
1181
|
|
|
963
|
-
def create(self,
|
|
964
|
-
*,
|
|
965
|
-
policy: Optional[FederationPolicy] = None,
|
|
966
|
-
policy_id: Optional[str] = None) -> FederationPolicy:
|
|
1182
|
+
def create(self, *, policy: Optional[FederationPolicy] = None, policy_id: Optional[str] = None) -> FederationPolicy:
|
|
967
1183
|
"""Create account federation policy.
|
|
968
|
-
|
|
1184
|
+
|
|
969
1185
|
:param policy: :class:`FederationPolicy` (optional)
|
|
970
1186
|
:param policy_id: str (optional)
|
|
971
1187
|
The identifier for the federation policy. The identifier must contain only lowercase alphanumeric
|
|
972
1188
|
characters, numbers, hyphens, and slashes. If unspecified, the id will be assigned by Databricks.
|
|
973
|
-
|
|
1189
|
+
|
|
974
1190
|
:returns: :class:`FederationPolicy`
|
|
975
1191
|
"""
|
|
976
1192
|
body = policy.as_dict()
|
|
977
1193
|
query = {}
|
|
978
|
-
if policy_id is not None:
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1194
|
+
if policy_id is not None:
|
|
1195
|
+
query["policy_id"] = policy_id
|
|
1196
|
+
headers = {
|
|
1197
|
+
"Accept": "application/json",
|
|
1198
|
+
"Content-Type": "application/json",
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
res = self._api.do(
|
|
1202
|
+
"POST",
|
|
1203
|
+
f"/api/2.0/accounts/{self._api.account_id}/federationPolicies",
|
|
1204
|
+
query=query,
|
|
1205
|
+
body=body,
|
|
1206
|
+
headers=headers,
|
|
1207
|
+
)
|
|
986
1208
|
return FederationPolicy.from_dict(res)
|
|
987
1209
|
|
|
988
1210
|
def delete(self, policy_id: str):
|
|
989
1211
|
"""Delete account federation policy.
|
|
990
|
-
|
|
1212
|
+
|
|
991
1213
|
:param policy_id: str
|
|
992
1214
|
The identifier for the federation policy.
|
|
993
|
-
|
|
994
|
-
|
|
1215
|
+
|
|
1216
|
+
|
|
995
1217
|
"""
|
|
996
1218
|
|
|
997
|
-
headers = {
|
|
1219
|
+
headers = {
|
|
1220
|
+
"Accept": "application/json",
|
|
1221
|
+
}
|
|
998
1222
|
|
|
999
|
-
self._api.do(
|
|
1000
|
-
|
|
1001
|
-
|
|
1223
|
+
self._api.do(
|
|
1224
|
+
"DELETE", f"/api/2.0/accounts/{self._api.account_id}/federationPolicies/{policy_id}", headers=headers
|
|
1225
|
+
)
|
|
1002
1226
|
|
|
1003
1227
|
def get(self, policy_id: str) -> FederationPolicy:
|
|
1004
1228
|
"""Get account federation policy.
|
|
1005
|
-
|
|
1229
|
+
|
|
1006
1230
|
:param policy_id: str
|
|
1007
1231
|
The identifier for the federation policy.
|
|
1008
|
-
|
|
1232
|
+
|
|
1009
1233
|
:returns: :class:`FederationPolicy`
|
|
1010
1234
|
"""
|
|
1011
1235
|
|
|
1012
|
-
headers = {
|
|
1236
|
+
headers = {
|
|
1237
|
+
"Accept": "application/json",
|
|
1238
|
+
}
|
|
1013
1239
|
|
|
1014
|
-
res = self._api.do(
|
|
1015
|
-
|
|
1016
|
-
|
|
1240
|
+
res = self._api.do(
|
|
1241
|
+
"GET", f"/api/2.0/accounts/{self._api.account_id}/federationPolicies/{policy_id}", headers=headers
|
|
1242
|
+
)
|
|
1017
1243
|
return FederationPolicy.from_dict(res)
|
|
1018
1244
|
|
|
1019
|
-
def list(self,
|
|
1020
|
-
*,
|
|
1021
|
-
page_size: Optional[int] = None,
|
|
1022
|
-
page_token: Optional[str] = None) -> Iterator[FederationPolicy]:
|
|
1245
|
+
def list(self, *, page_size: Optional[int] = None, page_token: Optional[str] = None) -> Iterator[FederationPolicy]:
|
|
1023
1246
|
"""List account federation policies.
|
|
1024
|
-
|
|
1247
|
+
|
|
1025
1248
|
:param page_size: int (optional)
|
|
1026
1249
|
:param page_token: str (optional)
|
|
1027
|
-
|
|
1250
|
+
|
|
1028
1251
|
:returns: Iterator over :class:`FederationPolicy`
|
|
1029
1252
|
"""
|
|
1030
1253
|
|
|
1031
1254
|
query = {}
|
|
1032
|
-
if page_size is not None:
|
|
1033
|
-
|
|
1034
|
-
|
|
1255
|
+
if page_size is not None:
|
|
1256
|
+
query["page_size"] = page_size
|
|
1257
|
+
if page_token is not None:
|
|
1258
|
+
query["page_token"] = page_token
|
|
1259
|
+
headers = {
|
|
1260
|
+
"Accept": "application/json",
|
|
1261
|
+
}
|
|
1035
1262
|
|
|
1036
1263
|
while True:
|
|
1037
|
-
json = self._api.do(
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
for v in json['policies']:
|
|
1264
|
+
json = self._api.do(
|
|
1265
|
+
"GET", f"/api/2.0/accounts/{self._api.account_id}/federationPolicies", query=query, headers=headers
|
|
1266
|
+
)
|
|
1267
|
+
if "policies" in json:
|
|
1268
|
+
for v in json["policies"]:
|
|
1043
1269
|
yield FederationPolicy.from_dict(v)
|
|
1044
|
-
if
|
|
1270
|
+
if "next_page_token" not in json or not json["next_page_token"]:
|
|
1045
1271
|
return
|
|
1046
|
-
query[
|
|
1272
|
+
query["page_token"] = json["next_page_token"]
|
|
1047
1273
|
|
|
1048
|
-
def update(
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
policy: Optional[FederationPolicy] = None,
|
|
1052
|
-
update_mask: Optional[str] = None) -> FederationPolicy:
|
|
1274
|
+
def update(
|
|
1275
|
+
self, policy_id: str, *, policy: Optional[FederationPolicy] = None, update_mask: Optional[str] = None
|
|
1276
|
+
) -> FederationPolicy:
|
|
1053
1277
|
"""Update account federation policy.
|
|
1054
|
-
|
|
1278
|
+
|
|
1055
1279
|
:param policy_id: str
|
|
1056
1280
|
The identifier for the federation policy.
|
|
1057
1281
|
:param policy: :class:`FederationPolicy` (optional)
|
|
@@ -1061,19 +1285,25 @@ class AccountFederationPolicyAPI:
|
|
|
1061
1285
|
should be updated (full replacement). If unspecified, all fields that are set in the policy provided
|
|
1062
1286
|
in the update request will overwrite the corresponding fields in the existing policy. Example value:
|
|
1063
1287
|
'description,oidc_policy.audiences'.
|
|
1064
|
-
|
|
1288
|
+
|
|
1065
1289
|
:returns: :class:`FederationPolicy`
|
|
1066
1290
|
"""
|
|
1067
1291
|
body = policy.as_dict()
|
|
1068
1292
|
query = {}
|
|
1069
|
-
if update_mask is not None:
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1293
|
+
if update_mask is not None:
|
|
1294
|
+
query["update_mask"] = update_mask
|
|
1295
|
+
headers = {
|
|
1296
|
+
"Accept": "application/json",
|
|
1297
|
+
"Content-Type": "application/json",
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
res = self._api.do(
|
|
1301
|
+
"PATCH",
|
|
1302
|
+
f"/api/2.0/accounts/{self._api.account_id}/federationPolicies/{policy_id}",
|
|
1303
|
+
query=query,
|
|
1304
|
+
body=body,
|
|
1305
|
+
headers=headers,
|
|
1306
|
+
)
|
|
1077
1307
|
return FederationPolicy.from_dict(res)
|
|
1078
1308
|
|
|
1079
1309
|
|
|
@@ -1084,20 +1314,22 @@ class CustomAppIntegrationAPI:
|
|
|
1084
1314
|
def __init__(self, api_client):
|
|
1085
1315
|
self._api = api_client
|
|
1086
1316
|
|
|
1087
|
-
def create(
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1317
|
+
def create(
|
|
1318
|
+
self,
|
|
1319
|
+
*,
|
|
1320
|
+
confidential: Optional[bool] = None,
|
|
1321
|
+
name: Optional[str] = None,
|
|
1322
|
+
redirect_urls: Optional[List[str]] = None,
|
|
1323
|
+
scopes: Optional[List[str]] = None,
|
|
1324
|
+
token_access_policy: Optional[TokenAccessPolicy] = None,
|
|
1325
|
+
user_authorized_scopes: Optional[List[str]] = None,
|
|
1326
|
+
) -> CreateCustomAppIntegrationOutput:
|
|
1095
1327
|
"""Create Custom OAuth App Integration.
|
|
1096
|
-
|
|
1328
|
+
|
|
1097
1329
|
Create Custom OAuth App Integration.
|
|
1098
|
-
|
|
1330
|
+
|
|
1099
1331
|
You can retrieve the custom OAuth app integration via :method:CustomAppIntegration/get.
|
|
1100
|
-
|
|
1332
|
+
|
|
1101
1333
|
:param confidential: bool (optional)
|
|
1102
1334
|
This field indicates whether an OAuth client secret is required to authenticate this client.
|
|
1103
1335
|
:param name: str (optional)
|
|
@@ -1112,108 +1344,135 @@ class CustomAppIntegrationAPI:
|
|
|
1112
1344
|
:param user_authorized_scopes: List[str] (optional)
|
|
1113
1345
|
Scopes that will need to be consented by end user to mint the access token. If the user does not
|
|
1114
1346
|
authorize the access token will not be minted. Must be a subset of scopes.
|
|
1115
|
-
|
|
1347
|
+
|
|
1116
1348
|
:returns: :class:`CreateCustomAppIntegrationOutput`
|
|
1117
1349
|
"""
|
|
1118
1350
|
body = {}
|
|
1119
|
-
if confidential is not None:
|
|
1120
|
-
|
|
1121
|
-
if
|
|
1122
|
-
|
|
1123
|
-
if
|
|
1351
|
+
if confidential is not None:
|
|
1352
|
+
body["confidential"] = confidential
|
|
1353
|
+
if name is not None:
|
|
1354
|
+
body["name"] = name
|
|
1355
|
+
if redirect_urls is not None:
|
|
1356
|
+
body["redirect_urls"] = [v for v in redirect_urls]
|
|
1357
|
+
if scopes is not None:
|
|
1358
|
+
body["scopes"] = [v for v in scopes]
|
|
1359
|
+
if token_access_policy is not None:
|
|
1360
|
+
body["token_access_policy"] = token_access_policy.as_dict()
|
|
1124
1361
|
if user_authorized_scopes is not None:
|
|
1125
|
-
body[
|
|
1126
|
-
headers = {
|
|
1362
|
+
body["user_authorized_scopes"] = [v for v in user_authorized_scopes]
|
|
1363
|
+
headers = {
|
|
1364
|
+
"Accept": "application/json",
|
|
1365
|
+
"Content-Type": "application/json",
|
|
1366
|
+
}
|
|
1127
1367
|
|
|
1128
|
-
res = self._api.do(
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1368
|
+
res = self._api.do(
|
|
1369
|
+
"POST",
|
|
1370
|
+
f"/api/2.0/accounts/{self._api.account_id}/oauth2/custom-app-integrations",
|
|
1371
|
+
body=body,
|
|
1372
|
+
headers=headers,
|
|
1373
|
+
)
|
|
1132
1374
|
return CreateCustomAppIntegrationOutput.from_dict(res)
|
|
1133
1375
|
|
|
1134
1376
|
def delete(self, integration_id: str):
|
|
1135
1377
|
"""Delete Custom OAuth App Integration.
|
|
1136
|
-
|
|
1378
|
+
|
|
1137
1379
|
Delete an existing Custom OAuth App Integration. You can retrieve the custom OAuth app integration via
|
|
1138
1380
|
:method:CustomAppIntegration/get.
|
|
1139
|
-
|
|
1381
|
+
|
|
1140
1382
|
:param integration_id: str
|
|
1141
|
-
|
|
1142
|
-
|
|
1383
|
+
|
|
1384
|
+
|
|
1143
1385
|
"""
|
|
1144
1386
|
|
|
1145
|
-
headers = {
|
|
1387
|
+
headers = {
|
|
1388
|
+
"Accept": "application/json",
|
|
1389
|
+
}
|
|
1146
1390
|
|
|
1147
1391
|
self._api.do(
|
|
1148
|
-
|
|
1149
|
-
f
|
|
1150
|
-
headers=headers
|
|
1392
|
+
"DELETE",
|
|
1393
|
+
f"/api/2.0/accounts/{self._api.account_id}/oauth2/custom-app-integrations/{integration_id}",
|
|
1394
|
+
headers=headers,
|
|
1395
|
+
)
|
|
1151
1396
|
|
|
1152
1397
|
def get(self, integration_id: str) -> GetCustomAppIntegrationOutput:
|
|
1153
1398
|
"""Get OAuth Custom App Integration.
|
|
1154
|
-
|
|
1399
|
+
|
|
1155
1400
|
Gets the Custom OAuth App Integration for the given integration id.
|
|
1156
|
-
|
|
1401
|
+
|
|
1157
1402
|
:param integration_id: str
|
|
1158
1403
|
The OAuth app integration ID.
|
|
1159
|
-
|
|
1404
|
+
|
|
1160
1405
|
:returns: :class:`GetCustomAppIntegrationOutput`
|
|
1161
1406
|
"""
|
|
1162
1407
|
|
|
1163
|
-
headers = {
|
|
1408
|
+
headers = {
|
|
1409
|
+
"Accept": "application/json",
|
|
1410
|
+
}
|
|
1164
1411
|
|
|
1165
1412
|
res = self._api.do(
|
|
1166
|
-
|
|
1167
|
-
f
|
|
1168
|
-
headers=headers
|
|
1413
|
+
"GET",
|
|
1414
|
+
f"/api/2.0/accounts/{self._api.account_id}/oauth2/custom-app-integrations/{integration_id}",
|
|
1415
|
+
headers=headers,
|
|
1416
|
+
)
|
|
1169
1417
|
return GetCustomAppIntegrationOutput.from_dict(res)
|
|
1170
1418
|
|
|
1171
|
-
def list(
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1419
|
+
def list(
|
|
1420
|
+
self,
|
|
1421
|
+
*,
|
|
1422
|
+
include_creator_username: Optional[bool] = None,
|
|
1423
|
+
page_size: Optional[int] = None,
|
|
1424
|
+
page_token: Optional[str] = None,
|
|
1425
|
+
) -> Iterator[GetCustomAppIntegrationOutput]:
|
|
1176
1426
|
"""Get custom oauth app integrations.
|
|
1177
|
-
|
|
1427
|
+
|
|
1178
1428
|
Get the list of custom OAuth app integrations for the specified Databricks account
|
|
1179
|
-
|
|
1429
|
+
|
|
1180
1430
|
:param include_creator_username: bool (optional)
|
|
1181
1431
|
:param page_size: int (optional)
|
|
1182
1432
|
:param page_token: str (optional)
|
|
1183
|
-
|
|
1433
|
+
|
|
1184
1434
|
:returns: Iterator over :class:`GetCustomAppIntegrationOutput`
|
|
1185
1435
|
"""
|
|
1186
1436
|
|
|
1187
1437
|
query = {}
|
|
1188
|
-
if include_creator_username is not None:
|
|
1189
|
-
|
|
1190
|
-
if
|
|
1191
|
-
|
|
1438
|
+
if include_creator_username is not None:
|
|
1439
|
+
query["include_creator_username"] = include_creator_username
|
|
1440
|
+
if page_size is not None:
|
|
1441
|
+
query["page_size"] = page_size
|
|
1442
|
+
if page_token is not None:
|
|
1443
|
+
query["page_token"] = page_token
|
|
1444
|
+
headers = {
|
|
1445
|
+
"Accept": "application/json",
|
|
1446
|
+
}
|
|
1192
1447
|
|
|
1193
1448
|
while True:
|
|
1194
|
-
json = self._api.do(
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1449
|
+
json = self._api.do(
|
|
1450
|
+
"GET",
|
|
1451
|
+
f"/api/2.0/accounts/{self._api.account_id}/oauth2/custom-app-integrations",
|
|
1452
|
+
query=query,
|
|
1453
|
+
headers=headers,
|
|
1454
|
+
)
|
|
1455
|
+
if "apps" in json:
|
|
1456
|
+
for v in json["apps"]:
|
|
1200
1457
|
yield GetCustomAppIntegrationOutput.from_dict(v)
|
|
1201
|
-
if
|
|
1458
|
+
if "next_page_token" not in json or not json["next_page_token"]:
|
|
1202
1459
|
return
|
|
1203
|
-
query[
|
|
1204
|
-
|
|
1205
|
-
def update(
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1460
|
+
query["page_token"] = json["next_page_token"]
|
|
1461
|
+
|
|
1462
|
+
def update(
|
|
1463
|
+
self,
|
|
1464
|
+
integration_id: str,
|
|
1465
|
+
*,
|
|
1466
|
+
redirect_urls: Optional[List[str]] = None,
|
|
1467
|
+
scopes: Optional[List[str]] = None,
|
|
1468
|
+
token_access_policy: Optional[TokenAccessPolicy] = None,
|
|
1469
|
+
user_authorized_scopes: Optional[List[str]] = None,
|
|
1470
|
+
):
|
|
1212
1471
|
"""Updates Custom OAuth App Integration.
|
|
1213
|
-
|
|
1472
|
+
|
|
1214
1473
|
Updates an existing custom OAuth App Integration. You can retrieve the custom OAuth app integration
|
|
1215
1474
|
via :method:CustomAppIntegration/get.
|
|
1216
|
-
|
|
1475
|
+
|
|
1217
1476
|
:param integration_id: str
|
|
1218
1477
|
:param redirect_urls: List[str] (optional)
|
|
1219
1478
|
List of OAuth redirect urls to be updated in the custom OAuth app integration
|
|
@@ -1225,22 +1484,29 @@ class CustomAppIntegrationAPI:
|
|
|
1225
1484
|
:param user_authorized_scopes: List[str] (optional)
|
|
1226
1485
|
Scopes that will need to be consented by end user to mint the access token. If the user does not
|
|
1227
1486
|
authorize the access token will not be minted. Must be a subset of scopes.
|
|
1228
|
-
|
|
1229
|
-
|
|
1487
|
+
|
|
1488
|
+
|
|
1230
1489
|
"""
|
|
1231
1490
|
body = {}
|
|
1232
|
-
if redirect_urls is not None:
|
|
1233
|
-
|
|
1234
|
-
if
|
|
1491
|
+
if redirect_urls is not None:
|
|
1492
|
+
body["redirect_urls"] = [v for v in redirect_urls]
|
|
1493
|
+
if scopes is not None:
|
|
1494
|
+
body["scopes"] = [v for v in scopes]
|
|
1495
|
+
if token_access_policy is not None:
|
|
1496
|
+
body["token_access_policy"] = token_access_policy.as_dict()
|
|
1235
1497
|
if user_authorized_scopes is not None:
|
|
1236
|
-
body[
|
|
1237
|
-
headers = {
|
|
1498
|
+
body["user_authorized_scopes"] = [v for v in user_authorized_scopes]
|
|
1499
|
+
headers = {
|
|
1500
|
+
"Accept": "application/json",
|
|
1501
|
+
"Content-Type": "application/json",
|
|
1502
|
+
}
|
|
1238
1503
|
|
|
1239
1504
|
self._api.do(
|
|
1240
|
-
|
|
1241
|
-
f
|
|
1505
|
+
"PATCH",
|
|
1506
|
+
f"/api/2.0/accounts/{self._api.account_id}/oauth2/custom-app-integrations/{integration_id}",
|
|
1242
1507
|
body=body,
|
|
1243
|
-
headers=headers
|
|
1508
|
+
headers=headers,
|
|
1509
|
+
)
|
|
1244
1510
|
|
|
1245
1511
|
|
|
1246
1512
|
class OAuthPublishedAppsAPI:
|
|
@@ -1251,38 +1517,40 @@ class OAuthPublishedAppsAPI:
|
|
|
1251
1517
|
def __init__(self, api_client):
|
|
1252
1518
|
self._api = api_client
|
|
1253
1519
|
|
|
1254
|
-
def list(
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
page_token: Optional[str] = None) -> Iterator[PublishedAppOutput]:
|
|
1520
|
+
def list(
|
|
1521
|
+
self, *, page_size: Optional[int] = None, page_token: Optional[str] = None
|
|
1522
|
+
) -> Iterator[PublishedAppOutput]:
|
|
1258
1523
|
"""Get all the published OAuth apps.
|
|
1259
|
-
|
|
1524
|
+
|
|
1260
1525
|
Get all the available published OAuth apps in Databricks.
|
|
1261
|
-
|
|
1526
|
+
|
|
1262
1527
|
:param page_size: int (optional)
|
|
1263
1528
|
The max number of OAuth published apps to return in one page.
|
|
1264
1529
|
:param page_token: str (optional)
|
|
1265
1530
|
A token that can be used to get the next page of results.
|
|
1266
|
-
|
|
1531
|
+
|
|
1267
1532
|
:returns: Iterator over :class:`PublishedAppOutput`
|
|
1268
1533
|
"""
|
|
1269
1534
|
|
|
1270
1535
|
query = {}
|
|
1271
|
-
if page_size is not None:
|
|
1272
|
-
|
|
1273
|
-
|
|
1536
|
+
if page_size is not None:
|
|
1537
|
+
query["page_size"] = page_size
|
|
1538
|
+
if page_token is not None:
|
|
1539
|
+
query["page_token"] = page_token
|
|
1540
|
+
headers = {
|
|
1541
|
+
"Accept": "application/json",
|
|
1542
|
+
}
|
|
1274
1543
|
|
|
1275
1544
|
while True:
|
|
1276
|
-
json = self._api.do(
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
for v in json['apps']:
|
|
1545
|
+
json = self._api.do(
|
|
1546
|
+
"GET", f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-apps", query=query, headers=headers
|
|
1547
|
+
)
|
|
1548
|
+
if "apps" in json:
|
|
1549
|
+
for v in json["apps"]:
|
|
1282
1550
|
yield PublishedAppOutput.from_dict(v)
|
|
1283
|
-
if
|
|
1551
|
+
if "next_page_token" not in json or not json["next_page_token"]:
|
|
1284
1552
|
return
|
|
1285
|
-
query[
|
|
1553
|
+
query["page_token"] = json["next_page_token"]
|
|
1286
1554
|
|
|
1287
1555
|
|
|
1288
1556
|
class PublishedAppIntegrationAPI:
|
|
@@ -1293,142 +1561,163 @@ class PublishedAppIntegrationAPI:
|
|
|
1293
1561
|
self._api = api_client
|
|
1294
1562
|
|
|
1295
1563
|
def create(
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
app_id: Optional[str] = None,
|
|
1299
|
-
token_access_policy: Optional[TokenAccessPolicy] = None) -> CreatePublishedAppIntegrationOutput:
|
|
1564
|
+
self, *, app_id: Optional[str] = None, token_access_policy: Optional[TokenAccessPolicy] = None
|
|
1565
|
+
) -> CreatePublishedAppIntegrationOutput:
|
|
1300
1566
|
"""Create Published OAuth App Integration.
|
|
1301
|
-
|
|
1567
|
+
|
|
1302
1568
|
Create Published OAuth App Integration.
|
|
1303
|
-
|
|
1569
|
+
|
|
1304
1570
|
You can retrieve the published OAuth app integration via :method:PublishedAppIntegration/get.
|
|
1305
|
-
|
|
1571
|
+
|
|
1306
1572
|
:param app_id: str (optional)
|
|
1307
1573
|
App id of the OAuth published app integration. For example power-bi, tableau-deskop
|
|
1308
1574
|
:param token_access_policy: :class:`TokenAccessPolicy` (optional)
|
|
1309
1575
|
Token access policy
|
|
1310
|
-
|
|
1576
|
+
|
|
1311
1577
|
:returns: :class:`CreatePublishedAppIntegrationOutput`
|
|
1312
1578
|
"""
|
|
1313
1579
|
body = {}
|
|
1314
|
-
if app_id is not None:
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1580
|
+
if app_id is not None:
|
|
1581
|
+
body["app_id"] = app_id
|
|
1582
|
+
if token_access_policy is not None:
|
|
1583
|
+
body["token_access_policy"] = token_access_policy.as_dict()
|
|
1584
|
+
headers = {
|
|
1585
|
+
"Accept": "application/json",
|
|
1586
|
+
"Content-Type": "application/json",
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
res = self._api.do(
|
|
1590
|
+
"POST",
|
|
1591
|
+
f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-app-integrations",
|
|
1592
|
+
body=body,
|
|
1593
|
+
headers=headers,
|
|
1594
|
+
)
|
|
1322
1595
|
return CreatePublishedAppIntegrationOutput.from_dict(res)
|
|
1323
1596
|
|
|
1324
1597
|
def delete(self, integration_id: str):
|
|
1325
1598
|
"""Delete Published OAuth App Integration.
|
|
1326
|
-
|
|
1599
|
+
|
|
1327
1600
|
Delete an existing Published OAuth App Integration. You can retrieve the published OAuth app
|
|
1328
1601
|
integration via :method:PublishedAppIntegration/get.
|
|
1329
|
-
|
|
1602
|
+
|
|
1330
1603
|
:param integration_id: str
|
|
1331
|
-
|
|
1332
|
-
|
|
1604
|
+
|
|
1605
|
+
|
|
1333
1606
|
"""
|
|
1334
1607
|
|
|
1335
|
-
headers = {
|
|
1608
|
+
headers = {
|
|
1609
|
+
"Accept": "application/json",
|
|
1610
|
+
}
|
|
1336
1611
|
|
|
1337
1612
|
self._api.do(
|
|
1338
|
-
|
|
1339
|
-
f
|
|
1340
|
-
headers=headers
|
|
1613
|
+
"DELETE",
|
|
1614
|
+
f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-app-integrations/{integration_id}",
|
|
1615
|
+
headers=headers,
|
|
1616
|
+
)
|
|
1341
1617
|
|
|
1342
1618
|
def get(self, integration_id: str) -> GetPublishedAppIntegrationOutput:
|
|
1343
1619
|
"""Get OAuth Published App Integration.
|
|
1344
|
-
|
|
1620
|
+
|
|
1345
1621
|
Gets the Published OAuth App Integration for the given integration id.
|
|
1346
|
-
|
|
1622
|
+
|
|
1347
1623
|
:param integration_id: str
|
|
1348
|
-
|
|
1624
|
+
|
|
1349
1625
|
:returns: :class:`GetPublishedAppIntegrationOutput`
|
|
1350
1626
|
"""
|
|
1351
1627
|
|
|
1352
|
-
headers = {
|
|
1628
|
+
headers = {
|
|
1629
|
+
"Accept": "application/json",
|
|
1630
|
+
}
|
|
1353
1631
|
|
|
1354
1632
|
res = self._api.do(
|
|
1355
|
-
|
|
1356
|
-
f
|
|
1357
|
-
headers=headers
|
|
1633
|
+
"GET",
|
|
1634
|
+
f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-app-integrations/{integration_id}",
|
|
1635
|
+
headers=headers,
|
|
1636
|
+
)
|
|
1358
1637
|
return GetPublishedAppIntegrationOutput.from_dict(res)
|
|
1359
1638
|
|
|
1360
|
-
def list(
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
page_token: Optional[str] = None) -> Iterator[GetPublishedAppIntegrationOutput]:
|
|
1639
|
+
def list(
|
|
1640
|
+
self, *, page_size: Optional[int] = None, page_token: Optional[str] = None
|
|
1641
|
+
) -> Iterator[GetPublishedAppIntegrationOutput]:
|
|
1364
1642
|
"""Get published oauth app integrations.
|
|
1365
|
-
|
|
1643
|
+
|
|
1366
1644
|
Get the list of published OAuth app integrations for the specified Databricks account
|
|
1367
|
-
|
|
1645
|
+
|
|
1368
1646
|
:param page_size: int (optional)
|
|
1369
1647
|
:param page_token: str (optional)
|
|
1370
|
-
|
|
1648
|
+
|
|
1371
1649
|
:returns: Iterator over :class:`GetPublishedAppIntegrationOutput`
|
|
1372
1650
|
"""
|
|
1373
1651
|
|
|
1374
1652
|
query = {}
|
|
1375
|
-
if page_size is not None:
|
|
1376
|
-
|
|
1377
|
-
|
|
1653
|
+
if page_size is not None:
|
|
1654
|
+
query["page_size"] = page_size
|
|
1655
|
+
if page_token is not None:
|
|
1656
|
+
query["page_token"] = page_token
|
|
1657
|
+
headers = {
|
|
1658
|
+
"Accept": "application/json",
|
|
1659
|
+
}
|
|
1378
1660
|
|
|
1379
1661
|
while True:
|
|
1380
|
-
json = self._api.do(
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1662
|
+
json = self._api.do(
|
|
1663
|
+
"GET",
|
|
1664
|
+
f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-app-integrations",
|
|
1665
|
+
query=query,
|
|
1666
|
+
headers=headers,
|
|
1667
|
+
)
|
|
1668
|
+
if "apps" in json:
|
|
1669
|
+
for v in json["apps"]:
|
|
1386
1670
|
yield GetPublishedAppIntegrationOutput.from_dict(v)
|
|
1387
|
-
if
|
|
1671
|
+
if "next_page_token" not in json or not json["next_page_token"]:
|
|
1388
1672
|
return
|
|
1389
|
-
query[
|
|
1673
|
+
query["page_token"] = json["next_page_token"]
|
|
1390
1674
|
|
|
1391
1675
|
def update(self, integration_id: str, *, token_access_policy: Optional[TokenAccessPolicy] = None):
|
|
1392
1676
|
"""Updates Published OAuth App Integration.
|
|
1393
|
-
|
|
1677
|
+
|
|
1394
1678
|
Updates an existing published OAuth App Integration. You can retrieve the published OAuth app
|
|
1395
1679
|
integration via :method:PublishedAppIntegration/get.
|
|
1396
|
-
|
|
1680
|
+
|
|
1397
1681
|
:param integration_id: str
|
|
1398
1682
|
:param token_access_policy: :class:`TokenAccessPolicy` (optional)
|
|
1399
1683
|
Token access policy to be updated in the published OAuth app integration
|
|
1400
|
-
|
|
1401
|
-
|
|
1684
|
+
|
|
1685
|
+
|
|
1402
1686
|
"""
|
|
1403
1687
|
body = {}
|
|
1404
|
-
if token_access_policy is not None:
|
|
1405
|
-
|
|
1688
|
+
if token_access_policy is not None:
|
|
1689
|
+
body["token_access_policy"] = token_access_policy.as_dict()
|
|
1690
|
+
headers = {
|
|
1691
|
+
"Accept": "application/json",
|
|
1692
|
+
"Content-Type": "application/json",
|
|
1693
|
+
}
|
|
1406
1694
|
|
|
1407
1695
|
self._api.do(
|
|
1408
|
-
|
|
1409
|
-
f
|
|
1696
|
+
"PATCH",
|
|
1697
|
+
f"/api/2.0/accounts/{self._api.account_id}/oauth2/published-app-integrations/{integration_id}",
|
|
1410
1698
|
body=body,
|
|
1411
|
-
headers=headers
|
|
1699
|
+
headers=headers,
|
|
1700
|
+
)
|
|
1412
1701
|
|
|
1413
1702
|
|
|
1414
1703
|
class ServicePrincipalFederationPolicyAPI:
|
|
1415
1704
|
"""These APIs manage service principal federation policies.
|
|
1416
|
-
|
|
1705
|
+
|
|
1417
1706
|
Service principal federation, also known as Workload Identity Federation, allows your automated workloads
|
|
1418
1707
|
running outside of Databricks to securely access Databricks APIs without the need for Databricks secrets.
|
|
1419
1708
|
With Workload Identity Federation, your application (or workload) authenticates to Databricks as a
|
|
1420
1709
|
Databricks service principal, using tokens provided by the workload runtime.
|
|
1421
|
-
|
|
1710
|
+
|
|
1422
1711
|
Databricks strongly recommends using Workload Identity Federation to authenticate to Databricks from
|
|
1423
1712
|
automated workloads, over alternatives such as OAuth client secrets or Personal Access Tokens, whenever
|
|
1424
1713
|
possible. Workload Identity Federation is supported by many popular services, including Github Actions,
|
|
1425
1714
|
Azure DevOps, GitLab, Terraform Cloud, and Kubernetes clusters, among others.
|
|
1426
|
-
|
|
1715
|
+
|
|
1427
1716
|
Workload identity federation is configured in your Databricks account using a service principal federation
|
|
1428
1717
|
policy. A service principal federation policy specifies: * which IdP, or issuer, the service principal is
|
|
1429
1718
|
allowed to authenticate from * which workload identity, or subject, is allowed to authenticate as the
|
|
1430
1719
|
Databricks service principal
|
|
1431
|
-
|
|
1720
|
+
|
|
1432
1721
|
To configure a federation policy, you provide the following: * The required token __issuer__, as specified
|
|
1433
1722
|
in the “iss” claim of workload identity tokens. The issuer is an https URL that identifies the
|
|
1434
1723
|
workload identity provider. * The required token __subject__, as specified in the “sub” claim of
|
|
@@ -1440,129 +1729,143 @@ class ServicePrincipalFederationPolicyAPI:
|
|
|
1440
1729
|
of the workload identity tokens, in JWKS format. If unspecified (recommended), Databricks automatically
|
|
1441
1730
|
fetches the public keys from the issuer’s well known endpoint. Databricks strongly recommends relying on
|
|
1442
1731
|
the issuer’s well known endpoint for discovering public keys.
|
|
1443
|
-
|
|
1732
|
+
|
|
1444
1733
|
An example service principal federation policy, for a Github Actions workload, is: ``` issuer:
|
|
1445
1734
|
"https://token.actions.githubusercontent.com" audiences: ["https://github.com/my-github-org"] subject:
|
|
1446
1735
|
"repo:my-github-org/my-repo:environment:prod" ```
|
|
1447
|
-
|
|
1736
|
+
|
|
1448
1737
|
An example JWT token body that matches this policy and could be used to authenticate to Databricks is: ```
|
|
1449
1738
|
{ "iss": "https://token.actions.githubusercontent.com", "aud": "https://github.com/my-github-org", "sub":
|
|
1450
1739
|
"repo:my-github-org/my-repo:environment:prod" } ```
|
|
1451
|
-
|
|
1740
|
+
|
|
1452
1741
|
You may also need to configure the workload runtime to generate tokens for your workloads.
|
|
1453
|
-
|
|
1742
|
+
|
|
1454
1743
|
You do not need to configure an OAuth application in Databricks to use token federation."""
|
|
1455
1744
|
|
|
1456
1745
|
def __init__(self, api_client):
|
|
1457
1746
|
self._api = api_client
|
|
1458
1747
|
|
|
1459
|
-
def create(
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
policy: Optional[FederationPolicy] = None,
|
|
1463
|
-
policy_id: Optional[str] = None) -> FederationPolicy:
|
|
1748
|
+
def create(
|
|
1749
|
+
self, service_principal_id: int, *, policy: Optional[FederationPolicy] = None, policy_id: Optional[str] = None
|
|
1750
|
+
) -> FederationPolicy:
|
|
1464
1751
|
"""Create service principal federation policy.
|
|
1465
|
-
|
|
1752
|
+
|
|
1466
1753
|
:param service_principal_id: int
|
|
1467
1754
|
The service principal id for the federation policy.
|
|
1468
1755
|
:param policy: :class:`FederationPolicy` (optional)
|
|
1469
1756
|
:param policy_id: str (optional)
|
|
1470
1757
|
The identifier for the federation policy. The identifier must contain only lowercase alphanumeric
|
|
1471
1758
|
characters, numbers, hyphens, and slashes. If unspecified, the id will be assigned by Databricks.
|
|
1472
|
-
|
|
1759
|
+
|
|
1473
1760
|
:returns: :class:`FederationPolicy`
|
|
1474
1761
|
"""
|
|
1475
1762
|
body = policy.as_dict()
|
|
1476
1763
|
query = {}
|
|
1477
|
-
if policy_id is not None:
|
|
1478
|
-
|
|
1764
|
+
if policy_id is not None:
|
|
1765
|
+
query["policy_id"] = policy_id
|
|
1766
|
+
headers = {
|
|
1767
|
+
"Accept": "application/json",
|
|
1768
|
+
"Content-Type": "application/json",
|
|
1769
|
+
}
|
|
1479
1770
|
|
|
1480
1771
|
res = self._api.do(
|
|
1481
|
-
|
|
1482
|
-
f
|
|
1772
|
+
"POST",
|
|
1773
|
+
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies",
|
|
1483
1774
|
query=query,
|
|
1484
1775
|
body=body,
|
|
1485
|
-
headers=headers
|
|
1776
|
+
headers=headers,
|
|
1777
|
+
)
|
|
1486
1778
|
return FederationPolicy.from_dict(res)
|
|
1487
1779
|
|
|
1488
1780
|
def delete(self, service_principal_id: int, policy_id: str):
|
|
1489
1781
|
"""Delete service principal federation policy.
|
|
1490
|
-
|
|
1782
|
+
|
|
1491
1783
|
:param service_principal_id: int
|
|
1492
1784
|
The service principal id for the federation policy.
|
|
1493
1785
|
:param policy_id: str
|
|
1494
1786
|
The identifier for the federation policy.
|
|
1495
|
-
|
|
1496
|
-
|
|
1787
|
+
|
|
1788
|
+
|
|
1497
1789
|
"""
|
|
1498
1790
|
|
|
1499
|
-
headers = {
|
|
1791
|
+
headers = {
|
|
1792
|
+
"Accept": "application/json",
|
|
1793
|
+
}
|
|
1500
1794
|
|
|
1501
1795
|
self._api.do(
|
|
1502
|
-
|
|
1503
|
-
f
|
|
1504
|
-
headers=headers
|
|
1796
|
+
"DELETE",
|
|
1797
|
+
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies/{policy_id}",
|
|
1798
|
+
headers=headers,
|
|
1799
|
+
)
|
|
1505
1800
|
|
|
1506
1801
|
def get(self, service_principal_id: int, policy_id: str) -> FederationPolicy:
|
|
1507
1802
|
"""Get service principal federation policy.
|
|
1508
|
-
|
|
1803
|
+
|
|
1509
1804
|
:param service_principal_id: int
|
|
1510
1805
|
The service principal id for the federation policy.
|
|
1511
1806
|
:param policy_id: str
|
|
1512
1807
|
The identifier for the federation policy.
|
|
1513
|
-
|
|
1808
|
+
|
|
1514
1809
|
:returns: :class:`FederationPolicy`
|
|
1515
1810
|
"""
|
|
1516
1811
|
|
|
1517
|
-
headers = {
|
|
1812
|
+
headers = {
|
|
1813
|
+
"Accept": "application/json",
|
|
1814
|
+
}
|
|
1518
1815
|
|
|
1519
1816
|
res = self._api.do(
|
|
1520
|
-
|
|
1521
|
-
f
|
|
1522
|
-
headers=headers
|
|
1817
|
+
"GET",
|
|
1818
|
+
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies/{policy_id}",
|
|
1819
|
+
headers=headers,
|
|
1820
|
+
)
|
|
1523
1821
|
return FederationPolicy.from_dict(res)
|
|
1524
1822
|
|
|
1525
|
-
def list(
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
page_size: Optional[int] = None,
|
|
1529
|
-
page_token: Optional[str] = None) -> Iterator[FederationPolicy]:
|
|
1823
|
+
def list(
|
|
1824
|
+
self, service_principal_id: int, *, page_size: Optional[int] = None, page_token: Optional[str] = None
|
|
1825
|
+
) -> Iterator[FederationPolicy]:
|
|
1530
1826
|
"""List service principal federation policies.
|
|
1531
|
-
|
|
1827
|
+
|
|
1532
1828
|
:param service_principal_id: int
|
|
1533
1829
|
The service principal id for the federation policy.
|
|
1534
1830
|
:param page_size: int (optional)
|
|
1535
1831
|
:param page_token: str (optional)
|
|
1536
|
-
|
|
1832
|
+
|
|
1537
1833
|
:returns: Iterator over :class:`FederationPolicy`
|
|
1538
1834
|
"""
|
|
1539
1835
|
|
|
1540
1836
|
query = {}
|
|
1541
|
-
if page_size is not None:
|
|
1542
|
-
|
|
1543
|
-
|
|
1837
|
+
if page_size is not None:
|
|
1838
|
+
query["page_size"] = page_size
|
|
1839
|
+
if page_token is not None:
|
|
1840
|
+
query["page_token"] = page_token
|
|
1841
|
+
headers = {
|
|
1842
|
+
"Accept": "application/json",
|
|
1843
|
+
}
|
|
1544
1844
|
|
|
1545
1845
|
while True:
|
|
1546
1846
|
json = self._api.do(
|
|
1547
|
-
|
|
1548
|
-
f
|
|
1847
|
+
"GET",
|
|
1848
|
+
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies",
|
|
1549
1849
|
query=query,
|
|
1550
|
-
headers=headers
|
|
1551
|
-
|
|
1552
|
-
|
|
1850
|
+
headers=headers,
|
|
1851
|
+
)
|
|
1852
|
+
if "policies" in json:
|
|
1853
|
+
for v in json["policies"]:
|
|
1553
1854
|
yield FederationPolicy.from_dict(v)
|
|
1554
|
-
if
|
|
1855
|
+
if "next_page_token" not in json or not json["next_page_token"]:
|
|
1555
1856
|
return
|
|
1556
|
-
query[
|
|
1557
|
-
|
|
1558
|
-
def update(
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1857
|
+
query["page_token"] = json["next_page_token"]
|
|
1858
|
+
|
|
1859
|
+
def update(
|
|
1860
|
+
self,
|
|
1861
|
+
service_principal_id: int,
|
|
1862
|
+
policy_id: str,
|
|
1863
|
+
*,
|
|
1864
|
+
policy: Optional[FederationPolicy] = None,
|
|
1865
|
+
update_mask: Optional[str] = None,
|
|
1866
|
+
) -> FederationPolicy:
|
|
1564
1867
|
"""Update service principal federation policy.
|
|
1565
|
-
|
|
1868
|
+
|
|
1566
1869
|
:param service_principal_id: int
|
|
1567
1870
|
The service principal id for the federation policy.
|
|
1568
1871
|
:param policy_id: str
|
|
@@ -1574,84 +1877,103 @@ class ServicePrincipalFederationPolicyAPI:
|
|
|
1574
1877
|
should be updated (full replacement). If unspecified, all fields that are set in the policy provided
|
|
1575
1878
|
in the update request will overwrite the corresponding fields in the existing policy. Example value:
|
|
1576
1879
|
'description,oidc_policy.audiences'.
|
|
1577
|
-
|
|
1880
|
+
|
|
1578
1881
|
:returns: :class:`FederationPolicy`
|
|
1579
1882
|
"""
|
|
1580
1883
|
body = policy.as_dict()
|
|
1581
1884
|
query = {}
|
|
1582
|
-
if update_mask is not None:
|
|
1583
|
-
|
|
1885
|
+
if update_mask is not None:
|
|
1886
|
+
query["update_mask"] = update_mask
|
|
1887
|
+
headers = {
|
|
1888
|
+
"Accept": "application/json",
|
|
1889
|
+
"Content-Type": "application/json",
|
|
1890
|
+
}
|
|
1584
1891
|
|
|
1585
1892
|
res = self._api.do(
|
|
1586
|
-
|
|
1587
|
-
f
|
|
1893
|
+
"PATCH",
|
|
1894
|
+
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/federationPolicies/{policy_id}",
|
|
1588
1895
|
query=query,
|
|
1589
1896
|
body=body,
|
|
1590
|
-
headers=headers
|
|
1897
|
+
headers=headers,
|
|
1898
|
+
)
|
|
1591
1899
|
return FederationPolicy.from_dict(res)
|
|
1592
1900
|
|
|
1593
1901
|
|
|
1594
1902
|
class ServicePrincipalSecretsAPI:
|
|
1595
1903
|
"""These APIs enable administrators to manage service principal secrets.
|
|
1596
|
-
|
|
1904
|
+
|
|
1597
1905
|
You can use the generated secrets to obtain OAuth access tokens for a service principal, which can then be
|
|
1598
1906
|
used to access Databricks Accounts and Workspace APIs. For more information, see [Authentication using
|
|
1599
1907
|
OAuth tokens for service principals],
|
|
1600
|
-
|
|
1908
|
+
|
|
1601
1909
|
In addition, the generated secrets can be used to configure the Databricks Terraform Provider to
|
|
1602
1910
|
authenticate with the service principal. For more information, see [Databricks Terraform Provider].
|
|
1603
|
-
|
|
1911
|
+
|
|
1604
1912
|
[Authentication using OAuth tokens for service principals]: https://docs.databricks.com/dev-tools/authentication-oauth.html
|
|
1605
|
-
[Databricks Terraform Provider]: https://github.com/databricks/terraform-provider-databricks/blob/master/docs/index.md#authenticating-with-service-principal
|
|
1913
|
+
[Databricks Terraform Provider]: https://github.com/databricks/terraform-provider-databricks/blob/master/docs/index.md#authenticating-with-service-principal
|
|
1914
|
+
"""
|
|
1606
1915
|
|
|
1607
1916
|
def __init__(self, api_client):
|
|
1608
1917
|
self._api = api_client
|
|
1609
1918
|
|
|
1610
|
-
def create(
|
|
1919
|
+
def create(
|
|
1920
|
+
self, service_principal_id: int, *, lifetime: Optional[str] = None
|
|
1921
|
+
) -> CreateServicePrincipalSecretResponse:
|
|
1611
1922
|
"""Create service principal secret.
|
|
1612
|
-
|
|
1923
|
+
|
|
1613
1924
|
Create a secret for the given service principal.
|
|
1614
|
-
|
|
1925
|
+
|
|
1615
1926
|
:param service_principal_id: int
|
|
1616
1927
|
The service principal ID.
|
|
1617
|
-
|
|
1928
|
+
:param lifetime: str (optional)
|
|
1929
|
+
The lifetime of the secret in seconds. If this parameter is not provided, the secret will have a
|
|
1930
|
+
default lifetime of 730 days (63072000s).
|
|
1931
|
+
|
|
1618
1932
|
:returns: :class:`CreateServicePrincipalSecretResponse`
|
|
1619
1933
|
"""
|
|
1620
|
-
|
|
1621
|
-
|
|
1934
|
+
body = {}
|
|
1935
|
+
if lifetime is not None:
|
|
1936
|
+
body["lifetime"] = lifetime
|
|
1937
|
+
headers = {
|
|
1938
|
+
"Accept": "application/json",
|
|
1939
|
+
"Content-Type": "application/json",
|
|
1940
|
+
}
|
|
1622
1941
|
|
|
1623
1942
|
res = self._api.do(
|
|
1624
|
-
|
|
1625
|
-
f
|
|
1626
|
-
|
|
1943
|
+
"POST",
|
|
1944
|
+
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/credentials/secrets",
|
|
1945
|
+
body=body,
|
|
1946
|
+
headers=headers,
|
|
1947
|
+
)
|
|
1627
1948
|
return CreateServicePrincipalSecretResponse.from_dict(res)
|
|
1628
1949
|
|
|
1629
1950
|
def delete(self, service_principal_id: int, secret_id: str):
|
|
1630
1951
|
"""Delete service principal secret.
|
|
1631
|
-
|
|
1952
|
+
|
|
1632
1953
|
Delete a secret from the given service principal.
|
|
1633
|
-
|
|
1954
|
+
|
|
1634
1955
|
:param service_principal_id: int
|
|
1635
1956
|
The service principal ID.
|
|
1636
1957
|
:param secret_id: str
|
|
1637
1958
|
The secret ID.
|
|
1638
|
-
|
|
1639
|
-
|
|
1959
|
+
|
|
1960
|
+
|
|
1640
1961
|
"""
|
|
1641
1962
|
|
|
1642
1963
|
headers = {}
|
|
1643
1964
|
|
|
1644
1965
|
self._api.do(
|
|
1645
|
-
|
|
1646
|
-
f
|
|
1647
|
-
headers=headers
|
|
1966
|
+
"DELETE",
|
|
1967
|
+
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/credentials/secrets/{secret_id}",
|
|
1968
|
+
headers=headers,
|
|
1969
|
+
)
|
|
1648
1970
|
|
|
1649
1971
|
def list(self, service_principal_id: int, *, page_token: Optional[str] = None) -> Iterator[SecretInfo]:
|
|
1650
1972
|
"""List service principal secrets.
|
|
1651
|
-
|
|
1973
|
+
|
|
1652
1974
|
List all secrets associated with the given service principal. This operation only returns information
|
|
1653
1975
|
about the secrets themselves and does not include the secret values.
|
|
1654
|
-
|
|
1976
|
+
|
|
1655
1977
|
:param service_principal_id: int
|
|
1656
1978
|
The service principal ID.
|
|
1657
1979
|
:param page_token: str (optional)
|
|
@@ -1661,23 +1983,27 @@ class ServicePrincipalSecretsAPI:
|
|
|
1661
1983
|
previous request. To list all of the secrets for a service principal, it is necessary to continue
|
|
1662
1984
|
requesting pages of entries until the response contains no `next_page_token`. Note that the number
|
|
1663
1985
|
of entries returned must not be used to determine when the listing is complete.
|
|
1664
|
-
|
|
1986
|
+
|
|
1665
1987
|
:returns: Iterator over :class:`SecretInfo`
|
|
1666
1988
|
"""
|
|
1667
1989
|
|
|
1668
1990
|
query = {}
|
|
1669
|
-
if page_token is not None:
|
|
1670
|
-
|
|
1991
|
+
if page_token is not None:
|
|
1992
|
+
query["page_token"] = page_token
|
|
1993
|
+
headers = {
|
|
1994
|
+
"Accept": "application/json",
|
|
1995
|
+
}
|
|
1671
1996
|
|
|
1672
1997
|
while True:
|
|
1673
1998
|
json = self._api.do(
|
|
1674
|
-
|
|
1675
|
-
f
|
|
1999
|
+
"GET",
|
|
2000
|
+
f"/api/2.0/accounts/{self._api.account_id}/servicePrincipals/{service_principal_id}/credentials/secrets",
|
|
1676
2001
|
query=query,
|
|
1677
|
-
headers=headers
|
|
1678
|
-
|
|
1679
|
-
|
|
2002
|
+
headers=headers,
|
|
2003
|
+
)
|
|
2004
|
+
if "secrets" in json:
|
|
2005
|
+
for v in json["secrets"]:
|
|
1680
2006
|
yield SecretInfo.from_dict(v)
|
|
1681
|
-
if
|
|
2007
|
+
if "next_page_token" not in json or not json["next_page_token"]:
|
|
1682
2008
|
return
|
|
1683
|
-
query[
|
|
2009
|
+
query["page_token"] = json["next_page_token"]
|