databricks-sdk 0.29.0__py3-none-any.whl → 0.31.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 +89 -21
- databricks/sdk/config.py +61 -75
- databricks/sdk/core.py +16 -9
- databricks/sdk/credentials_provider.py +15 -15
- databricks/sdk/data_plane.py +65 -0
- databricks/sdk/errors/overrides.py +8 -0
- databricks/sdk/errors/platform.py +5 -0
- databricks/sdk/mixins/files.py +12 -4
- databricks/sdk/service/apps.py +977 -0
- databricks/sdk/service/billing.py +602 -218
- databricks/sdk/service/catalog.py +324 -34
- databricks/sdk/service/compute.py +766 -81
- databricks/sdk/service/dashboards.py +628 -18
- databricks/sdk/service/iam.py +99 -88
- databricks/sdk/service/jobs.py +332 -23
- databricks/sdk/service/marketplace.py +2 -122
- databricks/sdk/service/oauth2.py +127 -70
- databricks/sdk/service/pipelines.py +72 -52
- databricks/sdk/service/serving.py +303 -750
- databricks/sdk/service/settings.py +423 -4
- databricks/sdk/service/sharing.py +235 -25
- databricks/sdk/service/sql.py +2328 -544
- databricks/sdk/useragent.py +151 -0
- databricks/sdk/version.py +1 -1
- {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/METADATA +36 -16
- {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/RECORD +30 -27
- {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/WHEEL +1 -1
- {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/LICENSE +0 -0
- {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/NOTICE +0 -0
- {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/top_level.txt +0 -0
databricks/sdk/service/jobs.py
CHANGED
|
@@ -15,7 +15,7 @@ from ._internal import Wait, _enum, _from_dict, _repeated_dict
|
|
|
15
15
|
|
|
16
16
|
_LOG = logging.getLogger('databricks.sdk')
|
|
17
17
|
|
|
18
|
-
from databricks.sdk.service import compute
|
|
18
|
+
from databricks.sdk.service import compute
|
|
19
19
|
|
|
20
20
|
# all definitions in this file are in alphabetical order
|
|
21
21
|
|
|
@@ -58,8 +58,8 @@ class BaseJob:
|
|
|
58
58
|
class BaseRun:
|
|
59
59
|
attempt_number: Optional[int] = None
|
|
60
60
|
"""The sequence number of this run attempt for a triggered job run. The initial attempt of a run
|
|
61
|
-
has an attempt_number of 0
|
|
62
|
-
(`max_retries`
|
|
61
|
+
has an attempt_number of 0. If the initial run attempt fails, and the job has a retry policy
|
|
62
|
+
(`max_retries` > 0), subsequent runs are created with an `original_attempt_run_id` of the
|
|
63
63
|
original attempt’s ID and an incrementing `attempt_number`. Runs are retried only until they
|
|
64
64
|
succeed, and the maximum `attempt_number` is the same as the `max_retries` value for the job."""
|
|
65
65
|
|
|
@@ -115,6 +115,11 @@ class BaseRun:
|
|
|
115
115
|
job_parameters: Optional[List[JobParameter]] = None
|
|
116
116
|
"""Job-level parameters used in the run"""
|
|
117
117
|
|
|
118
|
+
job_run_id: Optional[int] = None
|
|
119
|
+
"""ID of the job run that this run belongs to. For legacy and single-task job runs the field is
|
|
120
|
+
populated with the job run ID. For task runs, the field is populated with the ID of the job run
|
|
121
|
+
that the task run belongs to."""
|
|
122
|
+
|
|
118
123
|
number_in_job: Optional[int] = None
|
|
119
124
|
"""A unique identifier for this job run. This is set to the same value as `run_id`."""
|
|
120
125
|
|
|
@@ -201,6 +206,7 @@ class BaseRun:
|
|
|
201
206
|
if self.job_clusters: body['job_clusters'] = [v.as_dict() for v in self.job_clusters]
|
|
202
207
|
if self.job_id is not None: body['job_id'] = self.job_id
|
|
203
208
|
if self.job_parameters: body['job_parameters'] = [v.as_dict() for v in self.job_parameters]
|
|
209
|
+
if self.job_run_id is not None: body['job_run_id'] = self.job_run_id
|
|
204
210
|
if self.number_in_job is not None: body['number_in_job'] = self.number_in_job
|
|
205
211
|
if self.original_attempt_run_id is not None:
|
|
206
212
|
body['original_attempt_run_id'] = self.original_attempt_run_id
|
|
@@ -236,6 +242,7 @@ class BaseRun:
|
|
|
236
242
|
job_clusters=_repeated_dict(d, 'job_clusters', JobCluster),
|
|
237
243
|
job_id=d.get('job_id', None),
|
|
238
244
|
job_parameters=_repeated_dict(d, 'job_parameters', JobParameter),
|
|
245
|
+
job_run_id=d.get('job_run_id', None),
|
|
239
246
|
number_in_job=d.get('number_in_job', None),
|
|
240
247
|
original_attempt_run_id=d.get('original_attempt_run_id', None),
|
|
241
248
|
overriding_parameters=_from_dict(d, 'overriding_parameters', RunParameters),
|
|
@@ -469,7 +476,7 @@ class Continuous:
|
|
|
469
476
|
|
|
470
477
|
@dataclass
|
|
471
478
|
class CreateJob:
|
|
472
|
-
access_control_list: Optional[List[
|
|
479
|
+
access_control_list: Optional[List[JobAccessControlRequest]] = None
|
|
473
480
|
"""List of permissions to set on the job."""
|
|
474
481
|
|
|
475
482
|
continuous: Optional[Continuous] = None
|
|
@@ -480,7 +487,7 @@ class CreateJob:
|
|
|
480
487
|
"""Deployment information for jobs managed by external sources."""
|
|
481
488
|
|
|
482
489
|
description: Optional[str] = None
|
|
483
|
-
"""An optional description for the job. The maximum length is
|
|
490
|
+
"""An optional description for the job. The maximum length is 27700 characters in UTF-8 encoding."""
|
|
484
491
|
|
|
485
492
|
edit_mode: Optional[JobEditMode] = None
|
|
486
493
|
"""Edit mode of the job.
|
|
@@ -603,7 +610,7 @@ class CreateJob:
|
|
|
603
610
|
@classmethod
|
|
604
611
|
def from_dict(cls, d: Dict[str, any]) -> CreateJob:
|
|
605
612
|
"""Deserializes the CreateJob from a dictionary."""
|
|
606
|
-
return cls(access_control_list=_repeated_dict(d, 'access_control_list',
|
|
613
|
+
return cls(access_control_list=_repeated_dict(d, 'access_control_list', JobAccessControlRequest),
|
|
607
614
|
continuous=_from_dict(d, 'continuous', Continuous),
|
|
608
615
|
deployment=_from_dict(d, 'deployment', JobDeployment),
|
|
609
616
|
description=d.get('description', None),
|
|
@@ -827,6 +834,96 @@ class DeleteRunResponse:
|
|
|
827
834
|
return cls()
|
|
828
835
|
|
|
829
836
|
|
|
837
|
+
@dataclass
|
|
838
|
+
class EnforcePolicyComplianceForJobResponseJobClusterSettingsChange:
|
|
839
|
+
"""Represents a change to the job cluster's settings that would be required for the job clusters to
|
|
840
|
+
become compliant with their policies."""
|
|
841
|
+
|
|
842
|
+
field: Optional[str] = None
|
|
843
|
+
"""The field where this change would be made, prepended with the job cluster key."""
|
|
844
|
+
|
|
845
|
+
new_value: Optional[str] = None
|
|
846
|
+
"""The new value of this field after enforcing policy compliance (either a number, a boolean, or a
|
|
847
|
+
string) converted to a string. This is intended to be read by a human. The typed new value of
|
|
848
|
+
this field can be retrieved by reading the settings field in the API response."""
|
|
849
|
+
|
|
850
|
+
previous_value: Optional[str] = None
|
|
851
|
+
"""The previous value of this field before enforcing policy compliance (either a number, a boolean,
|
|
852
|
+
or a string) converted to a string. This is intended to be read by a human. The type of the
|
|
853
|
+
field can be retrieved by reading the settings field in the API response."""
|
|
854
|
+
|
|
855
|
+
def as_dict(self) -> dict:
|
|
856
|
+
"""Serializes the EnforcePolicyComplianceForJobResponseJobClusterSettingsChange into a dictionary suitable for use as a JSON request body."""
|
|
857
|
+
body = {}
|
|
858
|
+
if self.field is not None: body['field'] = self.field
|
|
859
|
+
if self.new_value is not None: body['new_value'] = self.new_value
|
|
860
|
+
if self.previous_value is not None: body['previous_value'] = self.previous_value
|
|
861
|
+
return body
|
|
862
|
+
|
|
863
|
+
@classmethod
|
|
864
|
+
def from_dict(cls, d: Dict[str, any]) -> EnforcePolicyComplianceForJobResponseJobClusterSettingsChange:
|
|
865
|
+
"""Deserializes the EnforcePolicyComplianceForJobResponseJobClusterSettingsChange from a dictionary."""
|
|
866
|
+
return cls(field=d.get('field', None),
|
|
867
|
+
new_value=d.get('new_value', None),
|
|
868
|
+
previous_value=d.get('previous_value', None))
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
@dataclass
|
|
872
|
+
class EnforcePolicyComplianceRequest:
|
|
873
|
+
job_id: int
|
|
874
|
+
"""The ID of the job you want to enforce policy compliance on."""
|
|
875
|
+
|
|
876
|
+
validate_only: Optional[bool] = None
|
|
877
|
+
"""If set, previews changes made to the job to comply with its policy, but does not update the job."""
|
|
878
|
+
|
|
879
|
+
def as_dict(self) -> dict:
|
|
880
|
+
"""Serializes the EnforcePolicyComplianceRequest into a dictionary suitable for use as a JSON request body."""
|
|
881
|
+
body = {}
|
|
882
|
+
if self.job_id is not None: body['job_id'] = self.job_id
|
|
883
|
+
if self.validate_only is not None: body['validate_only'] = self.validate_only
|
|
884
|
+
return body
|
|
885
|
+
|
|
886
|
+
@classmethod
|
|
887
|
+
def from_dict(cls, d: Dict[str, any]) -> EnforcePolicyComplianceRequest:
|
|
888
|
+
"""Deserializes the EnforcePolicyComplianceRequest from a dictionary."""
|
|
889
|
+
return cls(job_id=d.get('job_id', None), validate_only=d.get('validate_only', None))
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
@dataclass
|
|
893
|
+
class EnforcePolicyComplianceResponse:
|
|
894
|
+
has_changes: Optional[bool] = None
|
|
895
|
+
"""Whether any changes have been made to the job cluster settings for the job to become compliant
|
|
896
|
+
with its policies."""
|
|
897
|
+
|
|
898
|
+
job_cluster_changes: Optional[List[EnforcePolicyComplianceForJobResponseJobClusterSettingsChange]] = None
|
|
899
|
+
"""A list of job cluster changes that have been made to the job’s cluster settings in order for
|
|
900
|
+
all job clusters to become compliant with their policies."""
|
|
901
|
+
|
|
902
|
+
settings: Optional[JobSettings] = None
|
|
903
|
+
"""Updated job settings after policy enforcement. Policy enforcement only applies to job clusters
|
|
904
|
+
that are created when running the job (which are specified in new_cluster) and does not apply to
|
|
905
|
+
existing all-purpose clusters. Updated job settings are derived by applying policy default
|
|
906
|
+
values to the existing job clusters in order to satisfy policy requirements."""
|
|
907
|
+
|
|
908
|
+
def as_dict(self) -> dict:
|
|
909
|
+
"""Serializes the EnforcePolicyComplianceResponse into a dictionary suitable for use as a JSON request body."""
|
|
910
|
+
body = {}
|
|
911
|
+
if self.has_changes is not None: body['has_changes'] = self.has_changes
|
|
912
|
+
if self.job_cluster_changes:
|
|
913
|
+
body['job_cluster_changes'] = [v.as_dict() for v in self.job_cluster_changes]
|
|
914
|
+
if self.settings: body['settings'] = self.settings.as_dict()
|
|
915
|
+
return body
|
|
916
|
+
|
|
917
|
+
@classmethod
|
|
918
|
+
def from_dict(cls, d: Dict[str, any]) -> EnforcePolicyComplianceResponse:
|
|
919
|
+
"""Deserializes the EnforcePolicyComplianceResponse from a dictionary."""
|
|
920
|
+
return cls(has_changes=d.get('has_changes', None),
|
|
921
|
+
job_cluster_changes=_repeated_dict(
|
|
922
|
+
d, 'job_cluster_changes',
|
|
923
|
+
EnforcePolicyComplianceForJobResponseJobClusterSettingsChange),
|
|
924
|
+
settings=_from_dict(d, 'settings', JobSettings))
|
|
925
|
+
|
|
926
|
+
|
|
830
927
|
@dataclass
|
|
831
928
|
class ExportRunOutput:
|
|
832
929
|
"""Run was exported successfully."""
|
|
@@ -914,7 +1011,8 @@ class ForEachTask:
|
|
|
914
1011
|
"""Configuration for the task that will be run for each element in the array"""
|
|
915
1012
|
|
|
916
1013
|
concurrency: Optional[int] = None
|
|
917
|
-
"""
|
|
1014
|
+
"""An optional maximum allowed number of concurrent runs of the task. Set this value if you want to
|
|
1015
|
+
be able to execute multiple runs of the task concurrently."""
|
|
918
1016
|
|
|
919
1017
|
def as_dict(self) -> dict:
|
|
920
1018
|
"""Serializes the ForEachTask into a dictionary suitable for use as a JSON request body."""
|
|
@@ -1024,6 +1122,32 @@ class GetJobPermissionLevelsResponse:
|
|
|
1024
1122
|
return cls(permission_levels=_repeated_dict(d, 'permission_levels', JobPermissionsDescription))
|
|
1025
1123
|
|
|
1026
1124
|
|
|
1125
|
+
@dataclass
|
|
1126
|
+
class GetPolicyComplianceResponse:
|
|
1127
|
+
is_compliant: Optional[bool] = None
|
|
1128
|
+
"""Whether the job is compliant with its policies or not. Jobs could be out of compliance if a
|
|
1129
|
+
policy they are using was updated after the job was last edited and some of its job clusters no
|
|
1130
|
+
longer comply with their updated policies."""
|
|
1131
|
+
|
|
1132
|
+
violations: Optional[Dict[str, str]] = None
|
|
1133
|
+
"""An object containing key-value mappings representing the first 200 policy validation errors. The
|
|
1134
|
+
keys indicate the path where the policy validation error is occurring. An identifier for the job
|
|
1135
|
+
cluster is prepended to the path. The values indicate an error message describing the policy
|
|
1136
|
+
validation error."""
|
|
1137
|
+
|
|
1138
|
+
def as_dict(self) -> dict:
|
|
1139
|
+
"""Serializes the GetPolicyComplianceResponse into a dictionary suitable for use as a JSON request body."""
|
|
1140
|
+
body = {}
|
|
1141
|
+
if self.is_compliant is not None: body['is_compliant'] = self.is_compliant
|
|
1142
|
+
if self.violations: body['violations'] = self.violations
|
|
1143
|
+
return body
|
|
1144
|
+
|
|
1145
|
+
@classmethod
|
|
1146
|
+
def from_dict(cls, d: Dict[str, any]) -> GetPolicyComplianceResponse:
|
|
1147
|
+
"""Deserializes the GetPolicyComplianceResponse from a dictionary."""
|
|
1148
|
+
return cls(is_compliant=d.get('is_compliant', None), violations=d.get('violations', None))
|
|
1149
|
+
|
|
1150
|
+
|
|
1027
1151
|
class GitProvider(Enum):
|
|
1028
1152
|
|
|
1029
1153
|
AWS_CODE_COMMIT = 'awsCodeCommit'
|
|
@@ -1260,6 +1384,36 @@ class JobCluster:
|
|
|
1260
1384
|
new_cluster=_from_dict(d, 'new_cluster', compute.ClusterSpec))
|
|
1261
1385
|
|
|
1262
1386
|
|
|
1387
|
+
@dataclass
|
|
1388
|
+
class JobCompliance:
|
|
1389
|
+
job_id: int
|
|
1390
|
+
"""Canonical unique identifier for a job."""
|
|
1391
|
+
|
|
1392
|
+
is_compliant: Optional[bool] = None
|
|
1393
|
+
"""Whether this job is in compliance with the latest version of its policy."""
|
|
1394
|
+
|
|
1395
|
+
violations: Optional[Dict[str, str]] = None
|
|
1396
|
+
"""An object containing key-value mappings representing the first 200 policy validation errors. The
|
|
1397
|
+
keys indicate the path where the policy validation error is occurring. An identifier for the job
|
|
1398
|
+
cluster is prepended to the path. The values indicate an error message describing the policy
|
|
1399
|
+
validation error."""
|
|
1400
|
+
|
|
1401
|
+
def as_dict(self) -> dict:
|
|
1402
|
+
"""Serializes the JobCompliance into a dictionary suitable for use as a JSON request body."""
|
|
1403
|
+
body = {}
|
|
1404
|
+
if self.is_compliant is not None: body['is_compliant'] = self.is_compliant
|
|
1405
|
+
if self.job_id is not None: body['job_id'] = self.job_id
|
|
1406
|
+
if self.violations: body['violations'] = self.violations
|
|
1407
|
+
return body
|
|
1408
|
+
|
|
1409
|
+
@classmethod
|
|
1410
|
+
def from_dict(cls, d: Dict[str, any]) -> JobCompliance:
|
|
1411
|
+
"""Deserializes the JobCompliance from a dictionary."""
|
|
1412
|
+
return cls(is_compliant=d.get('is_compliant', None),
|
|
1413
|
+
job_id=d.get('job_id', None),
|
|
1414
|
+
violations=d.get('violations', None))
|
|
1415
|
+
|
|
1416
|
+
|
|
1263
1417
|
@dataclass
|
|
1264
1418
|
class JobDeployment:
|
|
1265
1419
|
kind: JobDeploymentKind
|
|
@@ -1601,7 +1755,7 @@ class JobSettings:
|
|
|
1601
1755
|
"""Deployment information for jobs managed by external sources."""
|
|
1602
1756
|
|
|
1603
1757
|
description: Optional[str] = None
|
|
1604
|
-
"""An optional description for the job. The maximum length is
|
|
1758
|
+
"""An optional description for the job. The maximum length is 27700 characters in UTF-8 encoding."""
|
|
1605
1759
|
|
|
1606
1760
|
edit_mode: Optional[JobEditMode] = None
|
|
1607
1761
|
"""Edit mode of the job.
|
|
@@ -1874,6 +2028,35 @@ class JobsHealthRules:
|
|
|
1874
2028
|
return cls(rules=_repeated_dict(d, 'rules', JobsHealthRule))
|
|
1875
2029
|
|
|
1876
2030
|
|
|
2031
|
+
@dataclass
|
|
2032
|
+
class ListJobComplianceForPolicyResponse:
|
|
2033
|
+
jobs: Optional[List[JobCompliance]] = None
|
|
2034
|
+
"""A list of jobs and their policy compliance statuses."""
|
|
2035
|
+
|
|
2036
|
+
next_page_token: Optional[str] = None
|
|
2037
|
+
"""This field represents the pagination token to retrieve the next page of results. If this field
|
|
2038
|
+
is not in the response, it means no further results for the request."""
|
|
2039
|
+
|
|
2040
|
+
prev_page_token: Optional[str] = None
|
|
2041
|
+
"""This field represents the pagination token to retrieve the previous page of results. If this
|
|
2042
|
+
field is not in the response, it means no further results for the request."""
|
|
2043
|
+
|
|
2044
|
+
def as_dict(self) -> dict:
|
|
2045
|
+
"""Serializes the ListJobComplianceForPolicyResponse into a dictionary suitable for use as a JSON request body."""
|
|
2046
|
+
body = {}
|
|
2047
|
+
if self.jobs: body['jobs'] = [v.as_dict() for v in self.jobs]
|
|
2048
|
+
if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
|
|
2049
|
+
if self.prev_page_token is not None: body['prev_page_token'] = self.prev_page_token
|
|
2050
|
+
return body
|
|
2051
|
+
|
|
2052
|
+
@classmethod
|
|
2053
|
+
def from_dict(cls, d: Dict[str, any]) -> ListJobComplianceForPolicyResponse:
|
|
2054
|
+
"""Deserializes the ListJobComplianceForPolicyResponse from a dictionary."""
|
|
2055
|
+
return cls(jobs=_repeated_dict(d, 'jobs', JobCompliance),
|
|
2056
|
+
next_page_token=d.get('next_page_token', None),
|
|
2057
|
+
prev_page_token=d.get('prev_page_token', None))
|
|
2058
|
+
|
|
2059
|
+
|
|
1877
2060
|
@dataclass
|
|
1878
2061
|
class ListJobsResponse:
|
|
1879
2062
|
"""List of jobs was retrieved successfully."""
|
|
@@ -2055,7 +2238,6 @@ class PeriodicTriggerConfigurationTimeUnit(Enum):
|
|
|
2055
2238
|
|
|
2056
2239
|
DAYS = 'DAYS'
|
|
2057
2240
|
HOURS = 'HOURS'
|
|
2058
|
-
TIME_UNIT_UNSPECIFIED = 'TIME_UNIT_UNSPECIFIED'
|
|
2059
2241
|
WEEKS = 'WEEKS'
|
|
2060
2242
|
|
|
2061
2243
|
|
|
@@ -2569,8 +2751,8 @@ class Run:
|
|
|
2569
2751
|
|
|
2570
2752
|
attempt_number: Optional[int] = None
|
|
2571
2753
|
"""The sequence number of this run attempt for a triggered job run. The initial attempt of a run
|
|
2572
|
-
has an attempt_number of 0
|
|
2573
|
-
(`max_retries`
|
|
2754
|
+
has an attempt_number of 0. If the initial run attempt fails, and the job has a retry policy
|
|
2755
|
+
(`max_retries` > 0), subsequent runs are created with an `original_attempt_run_id` of the
|
|
2574
2756
|
original attempt’s ID and an incrementing `attempt_number`. Runs are retried only until they
|
|
2575
2757
|
succeed, and the maximum `attempt_number` is the same as the `max_retries` value for the job."""
|
|
2576
2758
|
|
|
@@ -2615,6 +2797,9 @@ class Run:
|
|
|
2615
2797
|
Note: dbt and SQL File tasks support only version-controlled sources. If dbt or SQL File tasks
|
|
2616
2798
|
are used, `git_source` must be defined on the job."""
|
|
2617
2799
|
|
|
2800
|
+
iterations: Optional[List[RunTask]] = None
|
|
2801
|
+
"""Only populated by for-each iterations. The parent for-each task is located in tasks array."""
|
|
2802
|
+
|
|
2618
2803
|
job_clusters: Optional[List[JobCluster]] = None
|
|
2619
2804
|
"""A list of job cluster specifications that can be shared and reused by tasks of this job.
|
|
2620
2805
|
Libraries cannot be declared in a shared job cluster. You must declare dependent libraries in
|
|
@@ -2626,6 +2811,14 @@ class Run:
|
|
|
2626
2811
|
job_parameters: Optional[List[JobParameter]] = None
|
|
2627
2812
|
"""Job-level parameters used in the run"""
|
|
2628
2813
|
|
|
2814
|
+
job_run_id: Optional[int] = None
|
|
2815
|
+
"""ID of the job run that this run belongs to. For legacy and single-task job runs the field is
|
|
2816
|
+
populated with the job run ID. For task runs, the field is populated with the ID of the job run
|
|
2817
|
+
that the task run belongs to."""
|
|
2818
|
+
|
|
2819
|
+
next_page_token: Optional[str] = None
|
|
2820
|
+
"""A token that can be used to list the next page of sub-resources."""
|
|
2821
|
+
|
|
2629
2822
|
number_in_job: Optional[int] = None
|
|
2630
2823
|
"""A unique identifier for this job run. This is set to the same value as `run_id`."""
|
|
2631
2824
|
|
|
@@ -2636,6 +2829,9 @@ class Run:
|
|
|
2636
2829
|
overriding_parameters: Optional[RunParameters] = None
|
|
2637
2830
|
"""The parameters used for this run."""
|
|
2638
2831
|
|
|
2832
|
+
prev_page_token: Optional[str] = None
|
|
2833
|
+
"""A token that can be used to list the previous page of sub-resources."""
|
|
2834
|
+
|
|
2639
2835
|
queue_duration: Optional[int] = None
|
|
2640
2836
|
"""The time in milliseconds that the run has spent in the queue."""
|
|
2641
2837
|
|
|
@@ -2709,13 +2905,17 @@ class Run:
|
|
|
2709
2905
|
if self.end_time is not None: body['end_time'] = self.end_time
|
|
2710
2906
|
if self.execution_duration is not None: body['execution_duration'] = self.execution_duration
|
|
2711
2907
|
if self.git_source: body['git_source'] = self.git_source.as_dict()
|
|
2908
|
+
if self.iterations: body['iterations'] = [v.as_dict() for v in self.iterations]
|
|
2712
2909
|
if self.job_clusters: body['job_clusters'] = [v.as_dict() for v in self.job_clusters]
|
|
2713
2910
|
if self.job_id is not None: body['job_id'] = self.job_id
|
|
2714
2911
|
if self.job_parameters: body['job_parameters'] = [v.as_dict() for v in self.job_parameters]
|
|
2912
|
+
if self.job_run_id is not None: body['job_run_id'] = self.job_run_id
|
|
2913
|
+
if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
|
|
2715
2914
|
if self.number_in_job is not None: body['number_in_job'] = self.number_in_job
|
|
2716
2915
|
if self.original_attempt_run_id is not None:
|
|
2717
2916
|
body['original_attempt_run_id'] = self.original_attempt_run_id
|
|
2718
2917
|
if self.overriding_parameters: body['overriding_parameters'] = self.overriding_parameters.as_dict()
|
|
2918
|
+
if self.prev_page_token is not None: body['prev_page_token'] = self.prev_page_token
|
|
2719
2919
|
if self.queue_duration is not None: body['queue_duration'] = self.queue_duration
|
|
2720
2920
|
if self.repair_history: body['repair_history'] = [v.as_dict() for v in self.repair_history]
|
|
2721
2921
|
if self.run_duration is not None: body['run_duration'] = self.run_duration
|
|
@@ -2744,12 +2944,16 @@ class Run:
|
|
|
2744
2944
|
end_time=d.get('end_time', None),
|
|
2745
2945
|
execution_duration=d.get('execution_duration', None),
|
|
2746
2946
|
git_source=_from_dict(d, 'git_source', GitSource),
|
|
2947
|
+
iterations=_repeated_dict(d, 'iterations', RunTask),
|
|
2747
2948
|
job_clusters=_repeated_dict(d, 'job_clusters', JobCluster),
|
|
2748
2949
|
job_id=d.get('job_id', None),
|
|
2749
2950
|
job_parameters=_repeated_dict(d, 'job_parameters', JobParameter),
|
|
2951
|
+
job_run_id=d.get('job_run_id', None),
|
|
2952
|
+
next_page_token=d.get('next_page_token', None),
|
|
2750
2953
|
number_in_job=d.get('number_in_job', None),
|
|
2751
2954
|
original_attempt_run_id=d.get('original_attempt_run_id', None),
|
|
2752
2955
|
overriding_parameters=_from_dict(d, 'overriding_parameters', RunParameters),
|
|
2956
|
+
prev_page_token=d.get('prev_page_token', None),
|
|
2753
2957
|
queue_duration=d.get('queue_duration', None),
|
|
2754
2958
|
repair_history=_repeated_dict(d, 'repair_history', RepairHistoryItem),
|
|
2755
2959
|
run_duration=d.get('run_duration', None),
|
|
@@ -2818,7 +3022,8 @@ class RunForEachTask:
|
|
|
2818
3022
|
"""Configuration for the task that will be run for each element in the array"""
|
|
2819
3023
|
|
|
2820
3024
|
concurrency: Optional[int] = None
|
|
2821
|
-
"""
|
|
3025
|
+
"""An optional maximum allowed number of concurrent runs of the task. Set this value if you want to
|
|
3026
|
+
be able to execute multiple runs of the task concurrently."""
|
|
2822
3027
|
|
|
2823
3028
|
stats: Optional[ForEachStats] = None
|
|
2824
3029
|
"""Read only field. Populated for GetRun and ListRuns RPC calls and stores the execution stats of
|
|
@@ -3415,8 +3620,8 @@ class RunTask:
|
|
|
3415
3620
|
|
|
3416
3621
|
attempt_number: Optional[int] = None
|
|
3417
3622
|
"""The sequence number of this run attempt for a triggered job run. The initial attempt of a run
|
|
3418
|
-
has an attempt_number of 0
|
|
3419
|
-
(`max_retries`
|
|
3623
|
+
has an attempt_number of 0. If the initial run attempt fails, and the job has a retry policy
|
|
3624
|
+
(`max_retries` > 0), subsequent runs are created with an `original_attempt_run_id` of the
|
|
3420
3625
|
original attempt’s ID and an incrementing `attempt_number`. Runs are retried only until they
|
|
3421
3626
|
succeed, and the maximum `attempt_number` is the same as the `max_retries` value for the job."""
|
|
3422
3627
|
|
|
@@ -4188,7 +4393,7 @@ class SqlTaskSubscription:
|
|
|
4188
4393
|
|
|
4189
4394
|
@dataclass
|
|
4190
4395
|
class SubmitRun:
|
|
4191
|
-
access_control_list: Optional[List[
|
|
4396
|
+
access_control_list: Optional[List[JobAccessControlRequest]] = None
|
|
4192
4397
|
"""List of permissions to set on the job."""
|
|
4193
4398
|
|
|
4194
4399
|
email_notifications: Optional[JobEmailNotifications] = None
|
|
@@ -4268,7 +4473,7 @@ class SubmitRun:
|
|
|
4268
4473
|
@classmethod
|
|
4269
4474
|
def from_dict(cls, d: Dict[str, any]) -> SubmitRun:
|
|
4270
4475
|
"""Deserializes the SubmitRun from a dictionary."""
|
|
4271
|
-
return cls(access_control_list=_repeated_dict(d, 'access_control_list',
|
|
4476
|
+
return cls(access_control_list=_repeated_dict(d, 'access_control_list', JobAccessControlRequest),
|
|
4272
4477
|
email_notifications=_from_dict(d, 'email_notifications', JobEmailNotifications),
|
|
4273
4478
|
environments=_repeated_dict(d, 'environments', JobEnvironment),
|
|
4274
4479
|
git_source=_from_dict(d, 'git_source', GitSource),
|
|
@@ -5157,7 +5362,7 @@ class JobsAPI:
|
|
|
5157
5362
|
|
|
5158
5363
|
def create(self,
|
|
5159
5364
|
*,
|
|
5160
|
-
access_control_list: Optional[List[
|
|
5365
|
+
access_control_list: Optional[List[JobAccessControlRequest]] = None,
|
|
5161
5366
|
continuous: Optional[Continuous] = None,
|
|
5162
5367
|
deployment: Optional[JobDeployment] = None,
|
|
5163
5368
|
description: Optional[str] = None,
|
|
@@ -5184,7 +5389,7 @@ class JobsAPI:
|
|
|
5184
5389
|
|
|
5185
5390
|
Create a new job.
|
|
5186
5391
|
|
|
5187
|
-
:param access_control_list: List[:class:`
|
|
5392
|
+
:param access_control_list: List[:class:`JobAccessControlRequest`] (optional)
|
|
5188
5393
|
List of permissions to set on the job.
|
|
5189
5394
|
:param continuous: :class:`Continuous` (optional)
|
|
5190
5395
|
An optional continuous property for this job. The continuous property will ensure that there is
|
|
@@ -5192,7 +5397,7 @@ class JobsAPI:
|
|
|
5192
5397
|
:param deployment: :class:`JobDeployment` (optional)
|
|
5193
5398
|
Deployment information for jobs managed by external sources.
|
|
5194
5399
|
:param description: str (optional)
|
|
5195
|
-
An optional description for the job. The maximum length is
|
|
5400
|
+
An optional description for the job. The maximum length is 27700 characters in UTF-8 encoding.
|
|
5196
5401
|
:param edit_mode: :class:`JobEditMode` (optional)
|
|
5197
5402
|
Edit mode of the job.
|
|
5198
5403
|
|
|
@@ -5402,7 +5607,8 @@ class JobsAPI:
|
|
|
5402
5607
|
run_id: int,
|
|
5403
5608
|
*,
|
|
5404
5609
|
include_history: Optional[bool] = None,
|
|
5405
|
-
include_resolved_values: Optional[bool] = None
|
|
5610
|
+
include_resolved_values: Optional[bool] = None,
|
|
5611
|
+
page_token: Optional[str] = None) -> Run:
|
|
5406
5612
|
"""Get a single job run.
|
|
5407
5613
|
|
|
5408
5614
|
Retrieve the metadata of a run.
|
|
@@ -5413,6 +5619,9 @@ class JobsAPI:
|
|
|
5413
5619
|
Whether to include the repair history in the response.
|
|
5414
5620
|
:param include_resolved_values: bool (optional)
|
|
5415
5621
|
Whether to include resolved parameter values in the response.
|
|
5622
|
+
:param page_token: str (optional)
|
|
5623
|
+
To list the next page or the previous page of job tasks, set this field to the value of the
|
|
5624
|
+
`next_page_token` or `prev_page_token` returned in the GetJob response.
|
|
5416
5625
|
|
|
5417
5626
|
:returns: :class:`Run`
|
|
5418
5627
|
"""
|
|
@@ -5420,6 +5629,7 @@ class JobsAPI:
|
|
|
5420
5629
|
query = {}
|
|
5421
5630
|
if include_history is not None: query['include_history'] = include_history
|
|
5422
5631
|
if include_resolved_values is not None: query['include_resolved_values'] = include_resolved_values
|
|
5632
|
+
if page_token is not None: query['page_token'] = page_token
|
|
5423
5633
|
if run_id is not None: query['run_id'] = run_id
|
|
5424
5634
|
headers = {'Accept': 'application/json', }
|
|
5425
5635
|
|
|
@@ -5927,7 +6137,7 @@ class JobsAPI:
|
|
|
5927
6137
|
|
|
5928
6138
|
def submit(self,
|
|
5929
6139
|
*,
|
|
5930
|
-
access_control_list: Optional[List[
|
|
6140
|
+
access_control_list: Optional[List[JobAccessControlRequest]] = None,
|
|
5931
6141
|
email_notifications: Optional[JobEmailNotifications] = None,
|
|
5932
6142
|
environments: Optional[List[JobEnvironment]] = None,
|
|
5933
6143
|
git_source: Optional[GitSource] = None,
|
|
@@ -5946,7 +6156,7 @@ class JobsAPI:
|
|
|
5946
6156
|
Runs submitted using this endpoint don’t display in the UI. Use the `jobs/runs/get` API to check the
|
|
5947
6157
|
run state after the job is submitted.
|
|
5948
6158
|
|
|
5949
|
-
:param access_control_list: List[:class:`
|
|
6159
|
+
:param access_control_list: List[:class:`JobAccessControlRequest`] (optional)
|
|
5950
6160
|
List of permissions to set on the job.
|
|
5951
6161
|
:param email_notifications: :class:`JobEmailNotifications` (optional)
|
|
5952
6162
|
An optional set of email addresses notified when the run begins or completes.
|
|
@@ -6021,7 +6231,7 @@ class JobsAPI:
|
|
|
6021
6231
|
def submit_and_wait(
|
|
6022
6232
|
self,
|
|
6023
6233
|
*,
|
|
6024
|
-
access_control_list: Optional[List[
|
|
6234
|
+
access_control_list: Optional[List[JobAccessControlRequest]] = None,
|
|
6025
6235
|
email_notifications: Optional[JobEmailNotifications] = None,
|
|
6026
6236
|
environments: Optional[List[JobEnvironment]] = None,
|
|
6027
6237
|
git_source: Optional[GitSource] = None,
|
|
@@ -6108,3 +6318,102 @@ class JobsAPI:
|
|
|
6108
6318
|
|
|
6109
6319
|
res = self._api.do('PATCH', f'/api/2.0/permissions/jobs/{job_id}', body=body, headers=headers)
|
|
6110
6320
|
return JobPermissions.from_dict(res)
|
|
6321
|
+
|
|
6322
|
+
|
|
6323
|
+
class PolicyComplianceForJobsAPI:
|
|
6324
|
+
"""The compliance APIs allow you to view and manage the policy compliance status of jobs in your workspace.
|
|
6325
|
+
This API currently only supports compliance controls for cluster policies.
|
|
6326
|
+
|
|
6327
|
+
A job is in compliance if its cluster configurations satisfy the rules of all their respective cluster
|
|
6328
|
+
policies. A job could be out of compliance if a cluster policy it uses was updated after the job was last
|
|
6329
|
+
edited. The job is considered out of compliance if any of its clusters no longer comply with their updated
|
|
6330
|
+
policies.
|
|
6331
|
+
|
|
6332
|
+
The get and list compliance APIs allow you to view the policy compliance status of a job. The enforce
|
|
6333
|
+
compliance API allows you to update a job so that it becomes compliant with all of its policies."""
|
|
6334
|
+
|
|
6335
|
+
def __init__(self, api_client):
|
|
6336
|
+
self._api = api_client
|
|
6337
|
+
|
|
6338
|
+
def enforce_compliance(self,
|
|
6339
|
+
job_id: int,
|
|
6340
|
+
*,
|
|
6341
|
+
validate_only: Optional[bool] = None) -> EnforcePolicyComplianceResponse:
|
|
6342
|
+
"""Enforce job policy compliance.
|
|
6343
|
+
|
|
6344
|
+
Updates a job so the job clusters that are created when running the job (specified in `new_cluster`)
|
|
6345
|
+
are compliant with the current versions of their respective cluster policies. All-purpose clusters
|
|
6346
|
+
used in the job will not be updated.
|
|
6347
|
+
|
|
6348
|
+
:param job_id: int
|
|
6349
|
+
The ID of the job you want to enforce policy compliance on.
|
|
6350
|
+
:param validate_only: bool (optional)
|
|
6351
|
+
If set, previews changes made to the job to comply with its policy, but does not update the job.
|
|
6352
|
+
|
|
6353
|
+
:returns: :class:`EnforcePolicyComplianceResponse`
|
|
6354
|
+
"""
|
|
6355
|
+
body = {}
|
|
6356
|
+
if job_id is not None: body['job_id'] = job_id
|
|
6357
|
+
if validate_only is not None: body['validate_only'] = validate_only
|
|
6358
|
+
headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
|
|
6359
|
+
|
|
6360
|
+
res = self._api.do('POST', '/api/2.0/policies/jobs/enforce-compliance', body=body, headers=headers)
|
|
6361
|
+
return EnforcePolicyComplianceResponse.from_dict(res)
|
|
6362
|
+
|
|
6363
|
+
def get_compliance(self, job_id: int) -> GetPolicyComplianceResponse:
|
|
6364
|
+
"""Get job policy compliance.
|
|
6365
|
+
|
|
6366
|
+
Returns the policy compliance status of a job. Jobs could be out of compliance if a cluster policy
|
|
6367
|
+
they use was updated after the job was last edited and some of its job clusters no longer comply with
|
|
6368
|
+
their updated policies.
|
|
6369
|
+
|
|
6370
|
+
:param job_id: int
|
|
6371
|
+
The ID of the job whose compliance status you are requesting.
|
|
6372
|
+
|
|
6373
|
+
:returns: :class:`GetPolicyComplianceResponse`
|
|
6374
|
+
"""
|
|
6375
|
+
|
|
6376
|
+
query = {}
|
|
6377
|
+
if job_id is not None: query['job_id'] = job_id
|
|
6378
|
+
headers = {'Accept': 'application/json', }
|
|
6379
|
+
|
|
6380
|
+
res = self._api.do('GET', '/api/2.0/policies/jobs/get-compliance', query=query, headers=headers)
|
|
6381
|
+
return GetPolicyComplianceResponse.from_dict(res)
|
|
6382
|
+
|
|
6383
|
+
def list_compliance(self,
|
|
6384
|
+
policy_id: str,
|
|
6385
|
+
*,
|
|
6386
|
+
page_size: Optional[int] = None,
|
|
6387
|
+
page_token: Optional[str] = None) -> Iterator[JobCompliance]:
|
|
6388
|
+
"""List job policy compliance.
|
|
6389
|
+
|
|
6390
|
+
Returns the policy compliance status of all jobs that use a given policy. Jobs could be out of
|
|
6391
|
+
compliance if a cluster policy they use was updated after the job was last edited and its job clusters
|
|
6392
|
+
no longer comply with the updated policy.
|
|
6393
|
+
|
|
6394
|
+
:param policy_id: str
|
|
6395
|
+
Canonical unique identifier for the cluster policy.
|
|
6396
|
+
:param page_size: int (optional)
|
|
6397
|
+
Use this field to specify the maximum number of results to be returned by the server. The server may
|
|
6398
|
+
further constrain the maximum number of results returned in a single page.
|
|
6399
|
+
:param page_token: str (optional)
|
|
6400
|
+
A page token that can be used to navigate to the next page or previous page as returned by
|
|
6401
|
+
`next_page_token` or `prev_page_token`.
|
|
6402
|
+
|
|
6403
|
+
:returns: Iterator over :class:`JobCompliance`
|
|
6404
|
+
"""
|
|
6405
|
+
|
|
6406
|
+
query = {}
|
|
6407
|
+
if page_size is not None: query['page_size'] = page_size
|
|
6408
|
+
if page_token is not None: query['page_token'] = page_token
|
|
6409
|
+
if policy_id is not None: query['policy_id'] = policy_id
|
|
6410
|
+
headers = {'Accept': 'application/json', }
|
|
6411
|
+
|
|
6412
|
+
while True:
|
|
6413
|
+
json = self._api.do('GET', '/api/2.0/policies/jobs/list-compliance', query=query, headers=headers)
|
|
6414
|
+
if 'jobs' in json:
|
|
6415
|
+
for v in json['jobs']:
|
|
6416
|
+
yield JobCompliance.from_dict(v)
|
|
6417
|
+
if 'next_page_token' not in json or not json['next_page_token']:
|
|
6418
|
+
return
|
|
6419
|
+
query['page_token'] = json['next_page_token']
|