databricks-sdk 0.44.0__py3-none-any.whl → 0.44.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of databricks-sdk might be problematic. Click here for more details.
- databricks/sdk/credentials_provider.py +71 -16
- databricks/sdk/mixins/jobs.py +12 -6
- databricks/sdk/version.py +1 -1
- {databricks_sdk-0.44.0.dist-info → databricks_sdk-0.44.1.dist-info}/METADATA +1 -1
- {databricks_sdk-0.44.0.dist-info → databricks_sdk-0.44.1.dist-info}/RECORD +9 -9
- {databricks_sdk-0.44.0.dist-info → databricks_sdk-0.44.1.dist-info}/LICENSE +0 -0
- {databricks_sdk-0.44.0.dist-info → databricks_sdk-0.44.1.dist-info}/NOTICE +0 -0
- {databricks_sdk-0.44.0.dist-info → databricks_sdk-0.44.1.dist-info}/WHEEL +0 -0
- {databricks_sdk-0.44.0.dist-info → databricks_sdk-0.44.1.dist-info}/top_level.txt +0 -0
|
@@ -9,6 +9,7 @@ import pathlib
|
|
|
9
9
|
import platform
|
|
10
10
|
import subprocess
|
|
11
11
|
import sys
|
|
12
|
+
import threading
|
|
12
13
|
import time
|
|
13
14
|
from datetime import datetime
|
|
14
15
|
from typing import Callable, Dict, List, Optional, Tuple, Union
|
|
@@ -723,14 +724,17 @@ def metadata_service(cfg: 'Config') -> Optional[CredentialsProvider]:
|
|
|
723
724
|
# This Code is derived from Mlflow DatabricksModelServingConfigProvider
|
|
724
725
|
# https://github.com/mlflow/mlflow/blob/1219e3ef1aac7d337a618a352cd859b336cf5c81/mlflow/legacy_databricks_cli/configure/provider.py#L332
|
|
725
726
|
class ModelServingAuthProvider():
|
|
727
|
+
USER_CREDENTIALS = "user_credentials"
|
|
728
|
+
|
|
726
729
|
_MODEL_DEPENDENCY_OAUTH_TOKEN_FILE_PATH = "/var/credentials-secret/model-dependencies-oauth-token"
|
|
727
730
|
|
|
728
|
-
def __init__(self):
|
|
731
|
+
def __init__(self, credential_type: Optional[str]):
|
|
729
732
|
self.expiry_time = -1
|
|
730
733
|
self.current_token = None
|
|
731
734
|
self.refresh_duration = 300 # 300 Seconds
|
|
735
|
+
self.credential_type = credential_type
|
|
732
736
|
|
|
733
|
-
def should_fetch_model_serving_environment_oauth(
|
|
737
|
+
def should_fetch_model_serving_environment_oauth() -> bool:
|
|
734
738
|
"""
|
|
735
739
|
Check whether this is the model serving environment
|
|
736
740
|
Additionally check if the oauth token file path exists
|
|
@@ -739,15 +743,15 @@ class ModelServingAuthProvider():
|
|
|
739
743
|
is_in_model_serving_env = (os.environ.get("IS_IN_DB_MODEL_SERVING_ENV")
|
|
740
744
|
or os.environ.get("IS_IN_DATABRICKS_MODEL_SERVING_ENV") or "false")
|
|
741
745
|
return (is_in_model_serving_env == "true"
|
|
742
|
-
and os.path.isfile(
|
|
746
|
+
and os.path.isfile(ModelServingAuthProvider._MODEL_DEPENDENCY_OAUTH_TOKEN_FILE_PATH))
|
|
743
747
|
|
|
744
|
-
def
|
|
748
|
+
def _get_model_dependency_oauth_token(self, should_retry=True) -> str:
|
|
745
749
|
# Use Cached value if it is valid
|
|
746
750
|
if self.current_token is not None and self.expiry_time > time.time():
|
|
747
751
|
return self.current_token
|
|
748
752
|
|
|
749
753
|
try:
|
|
750
|
-
with open(
|
|
754
|
+
with open(ModelServingAuthProvider._MODEL_DEPENDENCY_OAUTH_TOKEN_FILE_PATH) as f:
|
|
751
755
|
oauth_dict = json.load(f)
|
|
752
756
|
self.current_token = oauth_dict["OAUTH_TOKEN"][0]["oauthTokenValue"]
|
|
753
757
|
self.expiry_time = time.time() + self.refresh_duration
|
|
@@ -757,32 +761,43 @@ class ModelServingAuthProvider():
|
|
|
757
761
|
logger.warning("Unable to read oauth token on first attmept in Model Serving Environment",
|
|
758
762
|
exc_info=e)
|
|
759
763
|
time.sleep(0.5)
|
|
760
|
-
return self.
|
|
764
|
+
return self._get_model_dependency_oauth_token(should_retry=False)
|
|
761
765
|
else:
|
|
762
766
|
raise RuntimeError(
|
|
763
767
|
"Unable to read OAuth credentials from the file mounted in Databricks Model Serving"
|
|
764
768
|
) from e
|
|
765
769
|
return self.current_token
|
|
766
770
|
|
|
771
|
+
def _get_invokers_token(self):
|
|
772
|
+
current_thread = threading.current_thread()
|
|
773
|
+
thread_data = current_thread.__dict__
|
|
774
|
+
invokers_token = None
|
|
775
|
+
if "invokers_token" in thread_data:
|
|
776
|
+
invokers_token = thread_data["invokers_token"]
|
|
777
|
+
|
|
778
|
+
if invokers_token is None:
|
|
779
|
+
raise RuntimeError("Unable to read Invokers Token in Databricks Model Serving")
|
|
780
|
+
|
|
781
|
+
return invokers_token
|
|
782
|
+
|
|
767
783
|
def get_databricks_host_token(self) -> Optional[Tuple[str, str]]:
|
|
768
|
-
if not
|
|
784
|
+
if not ModelServingAuthProvider.should_fetch_model_serving_environment_oauth():
|
|
769
785
|
return None
|
|
770
786
|
|
|
771
787
|
# read from DB_MODEL_SERVING_HOST_ENV_VAR if available otherwise MODEL_SERVING_HOST_ENV_VAR
|
|
772
788
|
host = os.environ.get("DATABRICKS_MODEL_SERVING_HOST_URL") or os.environ.get(
|
|
773
789
|
"DB_MODEL_SERVING_HOST_URL")
|
|
774
|
-
token = self.get_model_dependency_oauth_token()
|
|
775
790
|
|
|
776
|
-
|
|
791
|
+
if self.credential_type == ModelServingAuthProvider.USER_CREDENTIALS:
|
|
792
|
+
return (host, self._get_invokers_token())
|
|
793
|
+
else:
|
|
794
|
+
return (host, self._get_model_dependency_oauth_token())
|
|
777
795
|
|
|
778
796
|
|
|
779
|
-
|
|
780
|
-
|
|
797
|
+
def model_serving_auth_visitor(cfg: 'Config',
|
|
798
|
+
credential_type: Optional[str] = None) -> Optional[CredentialsProvider]:
|
|
781
799
|
try:
|
|
782
|
-
model_serving_auth_provider = ModelServingAuthProvider()
|
|
783
|
-
if not model_serving_auth_provider.should_fetch_model_serving_environment_oauth():
|
|
784
|
-
logger.debug("model-serving: Not in Databricks Model Serving, skipping")
|
|
785
|
-
return None
|
|
800
|
+
model_serving_auth_provider = ModelServingAuthProvider(credential_type)
|
|
786
801
|
host, token = model_serving_auth_provider.get_databricks_host_token()
|
|
787
802
|
if token is None:
|
|
788
803
|
raise ValueError(
|
|
@@ -793,7 +808,6 @@ def model_serving_auth(cfg: 'Config') -> Optional[CredentialsProvider]:
|
|
|
793
808
|
except Exception as e:
|
|
794
809
|
logger.warning("Unable to get auth from Databricks Model Serving Environment", exc_info=e)
|
|
795
810
|
return None
|
|
796
|
-
|
|
797
811
|
logger.info("Using Databricks Model Serving Authentication")
|
|
798
812
|
|
|
799
813
|
def inner() -> Dict[str, str]:
|
|
@@ -804,6 +818,15 @@ def model_serving_auth(cfg: 'Config') -> Optional[CredentialsProvider]:
|
|
|
804
818
|
return inner
|
|
805
819
|
|
|
806
820
|
|
|
821
|
+
@credentials_strategy('model-serving', [])
|
|
822
|
+
def model_serving_auth(cfg: 'Config') -> Optional[CredentialsProvider]:
|
|
823
|
+
if not ModelServingAuthProvider.should_fetch_model_serving_environment_oauth():
|
|
824
|
+
logger.debug("model-serving: Not in Databricks Model Serving, skipping")
|
|
825
|
+
return None
|
|
826
|
+
|
|
827
|
+
return model_serving_auth_visitor(cfg)
|
|
828
|
+
|
|
829
|
+
|
|
807
830
|
class DefaultCredentials:
|
|
808
831
|
""" Select the first applicable credential provider from the chain """
|
|
809
832
|
|
|
@@ -846,3 +869,35 @@ class DefaultCredentials:
|
|
|
846
869
|
raise ValueError(
|
|
847
870
|
f'cannot configure default credentials, please check {auth_flow_url} to configure credentials for your preferred authentication method.'
|
|
848
871
|
)
|
|
872
|
+
|
|
873
|
+
|
|
874
|
+
class ModelServingUserCredentials(CredentialsStrategy):
|
|
875
|
+
"""
|
|
876
|
+
This credential strategy is designed for authenticating the Databricks SDK in the model serving environment using user-specific rights.
|
|
877
|
+
In the model serving environment, the strategy retrieves a downscoped user token from the thread-local variable.
|
|
878
|
+
In any other environments, the class defaults to the DefaultCredentialStrategy.
|
|
879
|
+
To use this credential strategy, instantiate the WorkspaceClient with the ModelServingUserCredentials strategy as follows:
|
|
880
|
+
|
|
881
|
+
invokers_client = WorkspaceClient(credential_strategy = ModelServingUserCredentials())
|
|
882
|
+
"""
|
|
883
|
+
|
|
884
|
+
def __init__(self):
|
|
885
|
+
self.credential_type = ModelServingAuthProvider.USER_CREDENTIALS
|
|
886
|
+
self.default_credentials = DefaultCredentials()
|
|
887
|
+
|
|
888
|
+
def auth_type(self):
|
|
889
|
+
if ModelServingAuthProvider.should_fetch_model_serving_environment_oauth():
|
|
890
|
+
return "model_serving_" + self.credential_type
|
|
891
|
+
else:
|
|
892
|
+
return self.default_credentials.auth_type()
|
|
893
|
+
|
|
894
|
+
def __call__(self, cfg: 'Config') -> CredentialsProvider:
|
|
895
|
+
if ModelServingAuthProvider.should_fetch_model_serving_environment_oauth():
|
|
896
|
+
header_factory = model_serving_auth_visitor(cfg, self.credential_type)
|
|
897
|
+
if not header_factory:
|
|
898
|
+
raise ValueError(
|
|
899
|
+
f"Unable to authenticate using {self.credential_type} in Databricks Model Serving Environment"
|
|
900
|
+
)
|
|
901
|
+
return header_factory
|
|
902
|
+
else:
|
|
903
|
+
return self.default_credentials(cfg)
|
databricks/sdk/mixins/jobs.py
CHANGED
|
@@ -11,9 +11,10 @@ class JobsExt(jobs.JobsAPI):
|
|
|
11
11
|
include_history: Optional[bool] = None,
|
|
12
12
|
include_resolved_values: Optional[bool] = None,
|
|
13
13
|
page_token: Optional[str] = None) -> jobs.Run:
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
it will paginate through all pages and
|
|
14
|
+
"""Get a single job run.
|
|
15
|
+
|
|
16
|
+
Retrieve the metadata of a run. If a run has multiple pages of tasks, it will paginate through all pages of tasks, iterations, job_clusters, job_parameters, and repair history.
|
|
17
|
+
|
|
17
18
|
:param run_id: int
|
|
18
19
|
The canonical identifier of the run for which to retrieve the metadata. This field is required.
|
|
19
20
|
:param include_history: bool (optional)
|
|
@@ -21,8 +22,9 @@ class JobsExt(jobs.JobsAPI):
|
|
|
21
22
|
:param include_resolved_values: bool (optional)
|
|
22
23
|
Whether to include resolved parameter values in the response.
|
|
23
24
|
:param page_token: str (optional)
|
|
24
|
-
To list the next page
|
|
25
|
-
|
|
25
|
+
To list the next page of job tasks, set this field to the value of the `next_page_token` returned in
|
|
26
|
+
the GetJob response.
|
|
27
|
+
|
|
26
28
|
:returns: :class:`Run`
|
|
27
29
|
"""
|
|
28
30
|
run = super().get_run(run_id,
|
|
@@ -34,6 +36,7 @@ class JobsExt(jobs.JobsAPI):
|
|
|
34
36
|
# When querying a ForEach task run, a page token is returned when there are more than 100 iterations. Only a single task is returned, corresponding to the ForEach task itself. Therefore, the client only reads the iterations from the next page and not the tasks.
|
|
35
37
|
is_paginating_iterations = run.iterations is not None and len(run.iterations) > 0
|
|
36
38
|
|
|
39
|
+
# runs/get response includes next_page_token as long as there are more pages to fetch.
|
|
37
40
|
while run.next_page_token is not None:
|
|
38
41
|
next_run = super().get_run(run_id,
|
|
39
42
|
include_history=include_history,
|
|
@@ -43,7 +46,10 @@ class JobsExt(jobs.JobsAPI):
|
|
|
43
46
|
run.iterations.extend(next_run.iterations)
|
|
44
47
|
else:
|
|
45
48
|
run.tasks.extend(next_run.tasks)
|
|
49
|
+
# Each new page of runs/get response includes the next page of the job_clusters, job_parameters, and repair history.
|
|
50
|
+
run.job_clusters.extend(next_run.job_clusters)
|
|
51
|
+
run.job_parameters.extend(next_run.job_parameters)
|
|
52
|
+
run.repair_history.extend(next_run.repair_history)
|
|
46
53
|
run.next_page_token = next_run.next_page_token
|
|
47
54
|
|
|
48
|
-
run.prev_page_token = None
|
|
49
55
|
return run
|
databricks/sdk/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '0.44.
|
|
1
|
+
__version__ = '0.44.1'
|
|
@@ -7,7 +7,7 @@ databricks/sdk/casing.py,sha256=NKYPrfPbQjM7lU4hhNQK3z1jb_VEA29BfH4FEdby2tg,1137
|
|
|
7
7
|
databricks/sdk/clock.py,sha256=Ivlow0r_TkXcTJ8UXkxSA0czKrY0GvwHAeOvjPkJnAQ,1360
|
|
8
8
|
databricks/sdk/config.py,sha256=fUCRZX7tpY4LNvh3ilPtbaoC6wlFauWj9jyONsMDLWM,20314
|
|
9
9
|
databricks/sdk/core.py,sha256=s8W2UlRg8y9vCencdiFocYs49hLS3bltswLi00_cn38,4086
|
|
10
|
-
databricks/sdk/credentials_provider.py,sha256=
|
|
10
|
+
databricks/sdk/credentials_provider.py,sha256=ioH9ZYNc7e9L2KDCQRL2oOUiFifzHqqn11a2wG6kxj0,37817
|
|
11
11
|
databricks/sdk/data_plane.py,sha256=Kr81rnBlgqnlwNlDbV4JWzzTA5NSVlf0J-DQOylp0w4,2582
|
|
12
12
|
databricks/sdk/dbutils.py,sha256=HFCuB-el6SFKhF8qRfJxYANtyLTm-VG9GtQuQgZXFkM,15741
|
|
13
13
|
databricks/sdk/environments.py,sha256=5KoVuVfF-ZX17rua1sH3EJCCtniVrREXBXsMNDEV-UU,4293
|
|
@@ -15,7 +15,7 @@ databricks/sdk/oauth.py,sha256=ZlIzEGlKTUgGGgLfv5NQJr3Y_mWpKgTr8-hUEwwqfEE,23861
|
|
|
15
15
|
databricks/sdk/py.typed,sha256=pSvaHpbY1UPNEXyVFUjlgBhjPFZMmVC_UNrPC7eMOHI,74
|
|
16
16
|
databricks/sdk/retries.py,sha256=kdCKGIJjSkGLZYmQ0oI_hiGj7FP7MIqK9-nIr7WbykU,2574
|
|
17
17
|
databricks/sdk/useragent.py,sha256=o9cojoaVwI7C6tbIZy6jcQ8QiYuUmdL5_zATu6IZSaw,7373
|
|
18
|
-
databricks/sdk/version.py,sha256
|
|
18
|
+
databricks/sdk/version.py,sha256=-1tkgtTZjJHtveKwFUf8Bh2OZhXwVDjVJDxyd7uV6Ic,23
|
|
19
19
|
databricks/sdk/_widgets/__init__.py,sha256=Qm3JB8LmdPgEn_-VgxKkodTO4gn6OdaDPwsYcDmeIRI,2667
|
|
20
20
|
databricks/sdk/_widgets/default_widgets_utils.py,sha256=Rk59AFzVYVpOektB_yC_7j-vSt5OdtZA85IlG0kw0xA,1202
|
|
21
21
|
databricks/sdk/_widgets/ipywidgets_utils.py,sha256=P-AyGeahPiX3S59mxpAMgffi4gyJ0irEOY7Ekkn9nQ0,2850
|
|
@@ -34,7 +34,7 @@ databricks/sdk/logger/round_trip_logger.py,sha256=SMtHDfdqy5Noge2iZO-LpuEm92rz3A
|
|
|
34
34
|
databricks/sdk/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
35
|
databricks/sdk/mixins/compute.py,sha256=khb00BzBckc4RLUF4-GnNMCSO5lXKt_XYMM3IhiUxlA,11237
|
|
36
36
|
databricks/sdk/mixins/files.py,sha256=G5Tv0lbQGgOECwvFxmACX5X24ZMP6ZQD7ZudtkORbDw,28283
|
|
37
|
-
databricks/sdk/mixins/jobs.py,sha256=
|
|
37
|
+
databricks/sdk/mixins/jobs.py,sha256=xDXHKG5dSTF-K9tlyfwSu47get_7PF8koBnhHXnROLw,2966
|
|
38
38
|
databricks/sdk/mixins/open_ai_client.py,sha256=gvh8xKm1O8B23gNmIv6vxSxk8tNmphUqvS-XkkS260U,4776
|
|
39
39
|
databricks/sdk/mixins/workspace.py,sha256=dWMNvuEi8jJ5wMhrDt1LiqxNdWSsmEuDTzrcZR-eJzY,4896
|
|
40
40
|
databricks/sdk/runtime/__init__.py,sha256=9NnZkBzeZXZRQxcE1qKzAszQEzcpIgpL7lQzW3_kxEU,7266
|
|
@@ -61,9 +61,9 @@ databricks/sdk/service/sharing.py,sha256=vs69Y2FE28A4XnLxDGKL2HvV-LKgB-DV7nSnbYc
|
|
|
61
61
|
databricks/sdk/service/sql.py,sha256=GU_8ALx1r3lgu_FCmEJs8zTcWFKtJhKQ2CJcIcJgxzo,399590
|
|
62
62
|
databricks/sdk/service/vectorsearch.py,sha256=5p5pW94Bv_Q2tw4j8kFb35nAoFa9GUG5FIHTdfAHWps,77997
|
|
63
63
|
databricks/sdk/service/workspace.py,sha256=BCoi43R1L2eJI9DYq9vwCVdjbMsdLuzDebN6AZvT4kg,128751
|
|
64
|
-
databricks_sdk-0.44.
|
|
65
|
-
databricks_sdk-0.44.
|
|
66
|
-
databricks_sdk-0.44.
|
|
67
|
-
databricks_sdk-0.44.
|
|
68
|
-
databricks_sdk-0.44.
|
|
69
|
-
databricks_sdk-0.44.
|
|
64
|
+
databricks_sdk-0.44.1.dist-info/LICENSE,sha256=afBgTZo-JsYqj4VOjnejBetMuHKcFR30YobDdpVFkqY,11411
|
|
65
|
+
databricks_sdk-0.44.1.dist-info/METADATA,sha256=iCnThrfuodH8SezEZUmnw5lHzZcHnUjK-nanS8oNJh0,38301
|
|
66
|
+
databricks_sdk-0.44.1.dist-info/NOTICE,sha256=tkRcQYA1k68wDLcnOWbg2xJDsUOJw8G8DGBhb8dnI3w,1588
|
|
67
|
+
databricks_sdk-0.44.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
68
|
+
databricks_sdk-0.44.1.dist-info/top_level.txt,sha256=7kRdatoSgU0EUurRQJ_3F1Nv4EOSHWAr6ng25tJOJKU,11
|
|
69
|
+
databricks_sdk-0.44.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|