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.

Files changed (30) hide show
  1. databricks/sdk/__init__.py +89 -21
  2. databricks/sdk/config.py +61 -75
  3. databricks/sdk/core.py +16 -9
  4. databricks/sdk/credentials_provider.py +15 -15
  5. databricks/sdk/data_plane.py +65 -0
  6. databricks/sdk/errors/overrides.py +8 -0
  7. databricks/sdk/errors/platform.py +5 -0
  8. databricks/sdk/mixins/files.py +12 -4
  9. databricks/sdk/service/apps.py +977 -0
  10. databricks/sdk/service/billing.py +602 -218
  11. databricks/sdk/service/catalog.py +324 -34
  12. databricks/sdk/service/compute.py +766 -81
  13. databricks/sdk/service/dashboards.py +628 -18
  14. databricks/sdk/service/iam.py +99 -88
  15. databricks/sdk/service/jobs.py +332 -23
  16. databricks/sdk/service/marketplace.py +2 -122
  17. databricks/sdk/service/oauth2.py +127 -70
  18. databricks/sdk/service/pipelines.py +72 -52
  19. databricks/sdk/service/serving.py +303 -750
  20. databricks/sdk/service/settings.py +423 -4
  21. databricks/sdk/service/sharing.py +235 -25
  22. databricks/sdk/service/sql.py +2328 -544
  23. databricks/sdk/useragent.py +151 -0
  24. databricks/sdk/version.py +1 -1
  25. {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/METADATA +36 -16
  26. {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/RECORD +30 -27
  27. {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/WHEEL +1 -1
  28. {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/LICENSE +0 -0
  29. {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/NOTICE +0 -0
  30. {databricks_sdk-0.29.0.dist-info → databricks_sdk-0.31.0.dist-info}/top_level.txt +0 -0
@@ -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, iam
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\. 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
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[iam.AccessControlRequest]] = None
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 1024 characters in UTF-8 encoding."""
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', iam.AccessControlRequest),
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
- """Controls the number of active iterations task runs. Default is 20, maximum allowed is 100."""
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 1024 characters in UTF-8 encoding."""
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\. If the initial run attempt fails, and the job has a retry policy
2573
- (`max_retries` \> 0), subsequent runs are created with an `original_attempt_run_id` of the
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
- """Controls the number of active iterations task runs. Default is 20, maximum allowed is 100."""
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\. If the initial run attempt fails, and the job has a retry policy
3419
- (`max_retries` \> 0), subsequent runs are created with an `original_attempt_run_id` of the
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[iam.AccessControlRequest]] = None
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', iam.AccessControlRequest),
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[iam.AccessControlRequest]] = None,
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:`AccessControlRequest`] (optional)
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 1024 characters in UTF-8 encoding.
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) -> Run:
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[iam.AccessControlRequest]] = None,
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:`AccessControlRequest`] (optional)
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[iam.AccessControlRequest]] = None,
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']