databricks-sdk 0.53.0__py3-none-any.whl → 0.55.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 +298 -255
- databricks/sdk/config.py +15 -4
- databricks/sdk/credentials_provider.py +101 -55
- databricks/sdk/errors/base.py +1 -30
- databricks/sdk/oauth.py +0 -5
- databricks/sdk/oidc.py +206 -0
- databricks/sdk/service/apps.py +58 -0
- databricks/sdk/service/catalog.py +1198 -181
- databricks/sdk/service/cleanrooms.py +116 -1
- databricks/sdk/service/compute.py +33 -68
- databricks/sdk/service/dashboards.py +7 -0
- databricks/sdk/service/iam.py +167 -103
- databricks/sdk/service/jobs.py +7 -6
- databricks/sdk/service/ml.py +1230 -55
- databricks/sdk/service/oauth2.py +17 -0
- databricks/sdk/service/pipelines.py +105 -0
- databricks/sdk/service/serving.py +314 -0
- databricks/sdk/service/settings.py +1284 -59
- databricks/sdk/service/sharing.py +388 -2
- databricks/sdk/service/sql.py +53 -84
- databricks/sdk/service/vectorsearch.py +0 -28
- databricks/sdk/version.py +1 -1
- {databricks_sdk-0.53.0.dist-info → databricks_sdk-0.55.0.dist-info}/METADATA +1 -1
- {databricks_sdk-0.53.0.dist-info → databricks_sdk-0.55.0.dist-info}/RECORD +28 -27
- {databricks_sdk-0.53.0.dist-info → databricks_sdk-0.55.0.dist-info}/WHEEL +1 -1
- {databricks_sdk-0.53.0.dist-info → databricks_sdk-0.55.0.dist-info}/licenses/LICENSE +0 -0
- {databricks_sdk-0.53.0.dist-info → databricks_sdk-0.55.0.dist-info}/licenses/NOTICE +0 -0
- {databricks_sdk-0.53.0.dist-info → databricks_sdk-0.55.0.dist-info}/top_level.txt +0 -0
databricks/sdk/oidc.py
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Package oidc provides utilities for working with OIDC ID tokens.
|
|
3
|
+
|
|
4
|
+
This package is experimental and subject to change.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import os
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
from . import oauth
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class IdToken:
|
|
20
|
+
"""Represents an OIDC ID token that can be exchanged for a Databricks access token.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
jwt : str
|
|
25
|
+
The signed JWT token string.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
jwt: str
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class IdTokenSource(ABC):
|
|
32
|
+
"""Abstract base class representing anything that returns an IDToken.
|
|
33
|
+
|
|
34
|
+
This class defines the interface for token sources that can provide OIDC ID tokens.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def id_token(self) -> IdToken:
|
|
39
|
+
"""Get an ID token.
|
|
40
|
+
|
|
41
|
+
Returns
|
|
42
|
+
-------
|
|
43
|
+
IdToken
|
|
44
|
+
An ID token.
|
|
45
|
+
|
|
46
|
+
Raises
|
|
47
|
+
------
|
|
48
|
+
Exception
|
|
49
|
+
Implementation specific exceptions.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class EnvIdTokenSource(IdTokenSource):
|
|
54
|
+
"""IDTokenSource that reads the ID token from an environment variable.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
env_var : str
|
|
59
|
+
The name of the environment variable containing the ID token.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def __init__(self, env_var: str):
|
|
63
|
+
self.env_var = env_var
|
|
64
|
+
|
|
65
|
+
def id_token(self) -> IdToken:
|
|
66
|
+
"""Get an ID token from an environment variable.
|
|
67
|
+
|
|
68
|
+
Returns
|
|
69
|
+
-------
|
|
70
|
+
IdToken
|
|
71
|
+
An ID token.
|
|
72
|
+
|
|
73
|
+
Raises
|
|
74
|
+
------
|
|
75
|
+
ValueError
|
|
76
|
+
If the environment variable is not set.
|
|
77
|
+
"""
|
|
78
|
+
token = os.getenv(self.env_var)
|
|
79
|
+
if not token:
|
|
80
|
+
raise ValueError(f"Missing env var {self.env_var!r}")
|
|
81
|
+
return IdToken(jwt=token)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class FileIdTokenSource(IdTokenSource):
|
|
85
|
+
"""IDTokenSource that reads the ID token from a file.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
path : str
|
|
90
|
+
The path to the file containing the ID token.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
def __init__(self, path: str):
|
|
94
|
+
self.path = path
|
|
95
|
+
|
|
96
|
+
def id_token(self) -> IdToken:
|
|
97
|
+
"""Get an ID token from a file.
|
|
98
|
+
|
|
99
|
+
Returns
|
|
100
|
+
-------
|
|
101
|
+
IdToken
|
|
102
|
+
An ID token.
|
|
103
|
+
|
|
104
|
+
Raises
|
|
105
|
+
------
|
|
106
|
+
ValueError
|
|
107
|
+
If the file is empty, does not exist, or cannot be read.
|
|
108
|
+
"""
|
|
109
|
+
if not self.path:
|
|
110
|
+
raise ValueError("Missing path")
|
|
111
|
+
|
|
112
|
+
token = None
|
|
113
|
+
try:
|
|
114
|
+
with open(self.path, "r") as f:
|
|
115
|
+
token = f.read().strip()
|
|
116
|
+
except FileNotFoundError:
|
|
117
|
+
raise ValueError(f"File {self.path!r} does not exist")
|
|
118
|
+
except Exception as e:
|
|
119
|
+
raise ValueError(f"Error reading token file: {str(e)}")
|
|
120
|
+
|
|
121
|
+
if not token:
|
|
122
|
+
raise ValueError(f"File {self.path!r} is empty")
|
|
123
|
+
return IdToken(jwt=token)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class DatabricksOidcTokenSource(oauth.TokenSource):
|
|
127
|
+
"""A TokenSource which exchanges a token using Workload Identity Federation.
|
|
128
|
+
|
|
129
|
+
Parameters
|
|
130
|
+
----------
|
|
131
|
+
host : str
|
|
132
|
+
The host of the Databricks account or workspace.
|
|
133
|
+
id_token_source : IdTokenSource
|
|
134
|
+
IDTokenSource that returns the IDToken to be used for the token exchange.
|
|
135
|
+
token_endpoint_provider : Callable[[], dict]
|
|
136
|
+
Returns the token endpoint for the Databricks OIDC application.
|
|
137
|
+
client_id : Optional[str], optional
|
|
138
|
+
ClientID of the Databricks OIDC application. It corresponds to the
|
|
139
|
+
Application ID of the Databricks Service Principal. Only required for
|
|
140
|
+
Workload Identity Federation and should be empty for Account-wide token
|
|
141
|
+
federation.
|
|
142
|
+
account_id : Optional[str], optional
|
|
143
|
+
The account ID of the Databricks Account. Only required for
|
|
144
|
+
Account-wide token federation.
|
|
145
|
+
audience : Optional[str], optional
|
|
146
|
+
The audience of the Databricks OIDC application. Only used for
|
|
147
|
+
Workspace level tokens.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
def __init__(
|
|
151
|
+
self,
|
|
152
|
+
host: str,
|
|
153
|
+
token_endpoint: str,
|
|
154
|
+
id_token_source: IdTokenSource,
|
|
155
|
+
client_id: Optional[str] = None,
|
|
156
|
+
account_id: Optional[str] = None,
|
|
157
|
+
audience: Optional[str] = None,
|
|
158
|
+
disable_async: bool = False,
|
|
159
|
+
):
|
|
160
|
+
self._host = host
|
|
161
|
+
self._id_token_source = id_token_source
|
|
162
|
+
self._token_endpoint = token_endpoint
|
|
163
|
+
self._client_id = client_id
|
|
164
|
+
self._account_id = account_id
|
|
165
|
+
self._audience = audience
|
|
166
|
+
self._disable_async = disable_async
|
|
167
|
+
|
|
168
|
+
def token(self) -> oauth.Token:
|
|
169
|
+
"""Get a token by exchanging the ID token.
|
|
170
|
+
|
|
171
|
+
Returns
|
|
172
|
+
-------
|
|
173
|
+
dict
|
|
174
|
+
The exchanged token.
|
|
175
|
+
|
|
176
|
+
Raises
|
|
177
|
+
------
|
|
178
|
+
ValueError
|
|
179
|
+
If the host is missing or other configuration errors occur.
|
|
180
|
+
"""
|
|
181
|
+
if not self._host:
|
|
182
|
+
logger.debug("Missing Host")
|
|
183
|
+
raise ValueError("missing Host")
|
|
184
|
+
|
|
185
|
+
if not self._client_id:
|
|
186
|
+
logger.debug("No ClientID provided, authenticating with Account-wide token federation")
|
|
187
|
+
else:
|
|
188
|
+
logger.debug("Client ID provided, authenticating with Workload Identity Federation")
|
|
189
|
+
|
|
190
|
+
id_token = self._id_token_source.id_token()
|
|
191
|
+
|
|
192
|
+
client = oauth.ClientCredentials(
|
|
193
|
+
client_id=self._client_id,
|
|
194
|
+
client_secret="", # we have no (rotatable) secrets in OIDC flow
|
|
195
|
+
token_url=self._token_endpoint,
|
|
196
|
+
endpoint_params={
|
|
197
|
+
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
|
|
198
|
+
"subject_token": id_token,
|
|
199
|
+
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
|
|
200
|
+
},
|
|
201
|
+
scopes=["all-apis"],
|
|
202
|
+
use_params=True,
|
|
203
|
+
disable_async=self._disable_async,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
return client.token()
|
databricks/sdk/service/apps.py
CHANGED
|
@@ -655,6 +655,8 @@ class AppResource:
|
|
|
655
655
|
|
|
656
656
|
sql_warehouse: Optional[AppResourceSqlWarehouse] = None
|
|
657
657
|
|
|
658
|
+
uc_securable: Optional[AppResourceUcSecurable] = None
|
|
659
|
+
|
|
658
660
|
def as_dict(self) -> dict:
|
|
659
661
|
"""Serializes the AppResource into a dictionary suitable for use as a JSON request body."""
|
|
660
662
|
body = {}
|
|
@@ -670,6 +672,8 @@ class AppResource:
|
|
|
670
672
|
body["serving_endpoint"] = self.serving_endpoint.as_dict()
|
|
671
673
|
if self.sql_warehouse:
|
|
672
674
|
body["sql_warehouse"] = self.sql_warehouse.as_dict()
|
|
675
|
+
if self.uc_securable:
|
|
676
|
+
body["uc_securable"] = self.uc_securable.as_dict()
|
|
673
677
|
return body
|
|
674
678
|
|
|
675
679
|
def as_shallow_dict(self) -> dict:
|
|
@@ -687,6 +691,8 @@ class AppResource:
|
|
|
687
691
|
body["serving_endpoint"] = self.serving_endpoint
|
|
688
692
|
if self.sql_warehouse:
|
|
689
693
|
body["sql_warehouse"] = self.sql_warehouse
|
|
694
|
+
if self.uc_securable:
|
|
695
|
+
body["uc_securable"] = self.uc_securable
|
|
690
696
|
return body
|
|
691
697
|
|
|
692
698
|
@classmethod
|
|
@@ -699,6 +705,7 @@ class AppResource:
|
|
|
699
705
|
secret=_from_dict(d, "secret", AppResourceSecret),
|
|
700
706
|
serving_endpoint=_from_dict(d, "serving_endpoint", AppResourceServingEndpoint),
|
|
701
707
|
sql_warehouse=_from_dict(d, "sql_warehouse", AppResourceSqlWarehouse),
|
|
708
|
+
uc_securable=_from_dict(d, "uc_securable", AppResourceUcSecurable),
|
|
702
709
|
)
|
|
703
710
|
|
|
704
711
|
|
|
@@ -880,6 +887,57 @@ class AppResourceSqlWarehouseSqlWarehousePermission(Enum):
|
|
|
880
887
|
IS_OWNER = "IS_OWNER"
|
|
881
888
|
|
|
882
889
|
|
|
890
|
+
@dataclass
|
|
891
|
+
class AppResourceUcSecurable:
|
|
892
|
+
securable_full_name: str
|
|
893
|
+
|
|
894
|
+
securable_type: AppResourceUcSecurableUcSecurableType
|
|
895
|
+
|
|
896
|
+
permission: AppResourceUcSecurableUcSecurablePermission
|
|
897
|
+
|
|
898
|
+
def as_dict(self) -> dict:
|
|
899
|
+
"""Serializes the AppResourceUcSecurable into a dictionary suitable for use as a JSON request body."""
|
|
900
|
+
body = {}
|
|
901
|
+
if self.permission is not None:
|
|
902
|
+
body["permission"] = self.permission.value
|
|
903
|
+
if self.securable_full_name is not None:
|
|
904
|
+
body["securable_full_name"] = self.securable_full_name
|
|
905
|
+
if self.securable_type is not None:
|
|
906
|
+
body["securable_type"] = self.securable_type.value
|
|
907
|
+
return body
|
|
908
|
+
|
|
909
|
+
def as_shallow_dict(self) -> dict:
|
|
910
|
+
"""Serializes the AppResourceUcSecurable into a shallow dictionary of its immediate attributes."""
|
|
911
|
+
body = {}
|
|
912
|
+
if self.permission is not None:
|
|
913
|
+
body["permission"] = self.permission
|
|
914
|
+
if self.securable_full_name is not None:
|
|
915
|
+
body["securable_full_name"] = self.securable_full_name
|
|
916
|
+
if self.securable_type is not None:
|
|
917
|
+
body["securable_type"] = self.securable_type
|
|
918
|
+
return body
|
|
919
|
+
|
|
920
|
+
@classmethod
|
|
921
|
+
def from_dict(cls, d: Dict[str, Any]) -> AppResourceUcSecurable:
|
|
922
|
+
"""Deserializes the AppResourceUcSecurable from a dictionary."""
|
|
923
|
+
return cls(
|
|
924
|
+
permission=_enum(d, "permission", AppResourceUcSecurableUcSecurablePermission),
|
|
925
|
+
securable_full_name=d.get("securable_full_name", None),
|
|
926
|
+
securable_type=_enum(d, "securable_type", AppResourceUcSecurableUcSecurableType),
|
|
927
|
+
)
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
class AppResourceUcSecurableUcSecurablePermission(Enum):
|
|
931
|
+
|
|
932
|
+
READ_VOLUME = "READ_VOLUME"
|
|
933
|
+
WRITE_VOLUME = "WRITE_VOLUME"
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
class AppResourceUcSecurableUcSecurableType(Enum):
|
|
937
|
+
|
|
938
|
+
VOLUME = "VOLUME"
|
|
939
|
+
|
|
940
|
+
|
|
883
941
|
class ApplicationState(Enum):
|
|
884
942
|
|
|
885
943
|
CRASHED = "CRASHED"
|