databricks-sdk 0.28.0__py3-none-any.whl → 0.30.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 (31) hide show
  1. databricks/sdk/__init__.py +74 -22
  2. databricks/sdk/config.py +89 -48
  3. databricks/sdk/core.py +38 -9
  4. databricks/sdk/credentials_provider.py +134 -57
  5. databricks/sdk/data_plane.py +65 -0
  6. databricks/sdk/dbutils.py +81 -3
  7. databricks/sdk/mixins/files.py +12 -4
  8. databricks/sdk/oauth.py +8 -6
  9. databricks/sdk/service/apps.py +977 -0
  10. databricks/sdk/service/billing.py +602 -218
  11. databricks/sdk/service/catalog.py +263 -62
  12. databricks/sdk/service/compute.py +515 -94
  13. databricks/sdk/service/dashboards.py +1310 -2
  14. databricks/sdk/service/iam.py +99 -88
  15. databricks/sdk/service/jobs.py +159 -166
  16. databricks/sdk/service/marketplace.py +74 -58
  17. databricks/sdk/service/oauth2.py +149 -70
  18. databricks/sdk/service/pipelines.py +73 -53
  19. databricks/sdk/service/serving.py +332 -694
  20. databricks/sdk/service/settings.py +424 -4
  21. databricks/sdk/service/sharing.py +235 -26
  22. databricks/sdk/service/sql.py +2484 -553
  23. databricks/sdk/service/vectorsearch.py +75 -0
  24. databricks/sdk/useragent.py +144 -0
  25. databricks/sdk/version.py +1 -1
  26. {databricks_sdk-0.28.0.dist-info → databricks_sdk-0.30.0.dist-info}/METADATA +37 -16
  27. {databricks_sdk-0.28.0.dist-info → databricks_sdk-0.30.0.dist-info}/RECORD +31 -28
  28. {databricks_sdk-0.28.0.dist-info → databricks_sdk-0.30.0.dist-info}/WHEEL +1 -1
  29. {databricks_sdk-0.28.0.dist-info → databricks_sdk-0.30.0.dist-info}/LICENSE +0 -0
  30. {databricks_sdk-0.28.0.dist-info → databricks_sdk-0.30.0.dist-info}/NOTICE +0 -0
  31. {databricks_sdk-0.28.0.dist-info → databricks_sdk-0.30.0.dist-info}/top_level.txt +0 -0
@@ -15,204 +15,412 @@ _LOG = logging.getLogger('databricks.sdk')
15
15
 
16
16
 
17
17
  @dataclass
18
- class Budget:
19
- """Budget configuration to be created."""
18
+ class ActionConfiguration:
19
+ action_configuration_id: Optional[str] = None
20
+ """Databricks action configuration ID."""
20
21
 
21
- name: str
22
- """Human-readable name of the budget."""
22
+ action_type: Optional[ActionConfigurationType] = None
23
+ """The type of the action."""
23
24
 
24
- period: str
25
- """Period length in years, months, weeks and/or days. Examples: `1 month`, `30 days`, `1 year, 2
26
- months, 1 week, 2 days`"""
25
+ target: Optional[str] = None
26
+ """Target for the action. For example, an email address."""
27
27
 
28
- start_date: str
29
- """Start date of the budget period calculation."""
28
+ def as_dict(self) -> dict:
29
+ """Serializes the ActionConfiguration into a dictionary suitable for use as a JSON request body."""
30
+ body = {}
31
+ if self.action_configuration_id is not None:
32
+ body['action_configuration_id'] = self.action_configuration_id
33
+ if self.action_type is not None: body['action_type'] = self.action_type.value
34
+ if self.target is not None: body['target'] = self.target
35
+ return body
30
36
 
31
- target_amount: str
32
- """Target amount of the budget per period in USD."""
37
+ @classmethod
38
+ def from_dict(cls, d: Dict[str, any]) -> ActionConfiguration:
39
+ """Deserializes the ActionConfiguration from a dictionary."""
40
+ return cls(action_configuration_id=d.get('action_configuration_id', None),
41
+ action_type=_enum(d, 'action_type', ActionConfigurationType),
42
+ target=d.get('target', None))
33
43
 
34
- filter: str
35
- """SQL-like filter expression with workspaceId, SKU and tag. Usage in your account that matches
36
- this expression will be counted in this budget.
37
-
38
- Supported properties on left-hand side of comparison: * `workspaceId` - the ID of the workspace
39
- * `sku` - SKU of the cluster, e.g. `STANDARD_ALL_PURPOSE_COMPUTE` * `tag.tagName`, `tag.'tag
40
- name'` - tag of the cluster
41
-
42
- Supported comparison operators: * `=` - equal * `!=` - not equal
43
-
44
- Supported logical operators: `AND`, `OR`.
45
-
46
- Examples: * `workspaceId=123 OR (sku='STANDARD_ALL_PURPOSE_COMPUTE' AND tag.'my tag'='my
47
- value')` * `workspaceId!=456` * `sku='STANDARD_ALL_PURPOSE_COMPUTE' OR
48
- sku='PREMIUM_ALL_PURPOSE_COMPUTE'` * `tag.name1='value1' AND tag.name2='value2'`"""
49
44
 
50
- alerts: Optional[List[BudgetAlert]] = None
45
+ class ActionConfigurationType(Enum):
46
+
47
+ EMAIL_NOTIFICATION = 'EMAIL_NOTIFICATION'
48
+
49
+
50
+ @dataclass
51
+ class AlertConfiguration:
52
+ action_configurations: Optional[List[ActionConfiguration]] = None
53
+ """Configured actions for this alert. These define what happens when an alert enters a triggered
54
+ state."""
55
+
56
+ alert_configuration_id: Optional[str] = None
57
+ """Databricks alert configuration ID."""
58
+
59
+ quantity_threshold: Optional[str] = None
60
+ """The threshold for the budget alert to determine if it is in a triggered state. The number is
61
+ evaluated based on `quantity_type`."""
62
+
63
+ quantity_type: Optional[AlertConfigurationQuantityType] = None
64
+ """The way to calculate cost for this budget alert. This is what `quantity_threshold` is measured
65
+ in."""
66
+
67
+ time_period: Optional[AlertConfigurationTimePeriod] = None
68
+ """The time window of usage data for the budget."""
51
69
 
52
- end_date: Optional[str] = None
53
- """Optional end date of the budget."""
70
+ trigger_type: Optional[AlertConfigurationTriggerType] = None
71
+ """The evaluation method to determine when this budget alert is in a triggered state."""
54
72
 
55
73
  def as_dict(self) -> dict:
56
- """Serializes the Budget into a dictionary suitable for use as a JSON request body."""
74
+ """Serializes the AlertConfiguration into a dictionary suitable for use as a JSON request body."""
57
75
  body = {}
58
- if self.alerts: body['alerts'] = [v.as_dict() for v in self.alerts]
59
- if self.end_date is not None: body['end_date'] = self.end_date
60
- if self.filter is not None: body['filter'] = self.filter
61
- if self.name is not None: body['name'] = self.name
62
- if self.period is not None: body['period'] = self.period
63
- if self.start_date is not None: body['start_date'] = self.start_date
64
- if self.target_amount is not None: body['target_amount'] = self.target_amount
76
+ if self.action_configurations:
77
+ body['action_configurations'] = [v.as_dict() for v in self.action_configurations]
78
+ if self.alert_configuration_id is not None:
79
+ body['alert_configuration_id'] = self.alert_configuration_id
80
+ if self.quantity_threshold is not None: body['quantity_threshold'] = self.quantity_threshold
81
+ if self.quantity_type is not None: body['quantity_type'] = self.quantity_type.value
82
+ if self.time_period is not None: body['time_period'] = self.time_period.value
83
+ if self.trigger_type is not None: body['trigger_type'] = self.trigger_type.value
65
84
  return body
66
85
 
67
86
  @classmethod
68
- def from_dict(cls, d: Dict[str, any]) -> Budget:
69
- """Deserializes the Budget from a dictionary."""
70
- return cls(alerts=_repeated_dict(d, 'alerts', BudgetAlert),
71
- end_date=d.get('end_date', None),
72
- filter=d.get('filter', None),
73
- name=d.get('name', None),
74
- period=d.get('period', None),
75
- start_date=d.get('start_date', None),
76
- target_amount=d.get('target_amount', None))
87
+ def from_dict(cls, d: Dict[str, any]) -> AlertConfiguration:
88
+ """Deserializes the AlertConfiguration from a dictionary."""
89
+ return cls(action_configurations=_repeated_dict(d, 'action_configurations', ActionConfiguration),
90
+ alert_configuration_id=d.get('alert_configuration_id', None),
91
+ quantity_threshold=d.get('quantity_threshold', None),
92
+ quantity_type=_enum(d, 'quantity_type', AlertConfigurationQuantityType),
93
+ time_period=_enum(d, 'time_period', AlertConfigurationTimePeriod),
94
+ trigger_type=_enum(d, 'trigger_type', AlertConfigurationTriggerType))
95
+
96
+
97
+ class AlertConfigurationQuantityType(Enum):
98
+
99
+ LIST_PRICE_DOLLARS_USD = 'LIST_PRICE_DOLLARS_USD'
100
+
101
+
102
+ class AlertConfigurationTimePeriod(Enum):
103
+
104
+ MONTH = 'MONTH'
105
+
106
+
107
+ class AlertConfigurationTriggerType(Enum):
108
+
109
+ CUMULATIVE_SPENDING_EXCEEDED = 'CUMULATIVE_SPENDING_EXCEEDED'
77
110
 
78
111
 
79
112
  @dataclass
80
- class BudgetAlert:
81
- email_notifications: Optional[List[str]] = None
82
- """List of email addresses to be notified when budget percentage is exceeded in the given period."""
113
+ class BudgetConfiguration:
114
+ account_id: Optional[str] = None
115
+ """Databricks account ID."""
116
+
117
+ alert_configurations: Optional[List[AlertConfiguration]] = None
118
+ """Alerts to configure when this budget is in a triggered state. Budgets must have exactly one
119
+ alert configuration."""
120
+
121
+ budget_configuration_id: Optional[str] = None
122
+ """Databricks budget configuration ID."""
123
+
124
+ create_time: Optional[int] = None
125
+ """Creation time of this budget configuration."""
126
+
127
+ display_name: Optional[str] = None
128
+ """Human-readable name of budget configuration. Max Length: 128"""
129
+
130
+ filter: Optional[BudgetConfigurationFilter] = None
131
+ """Configured filters for this budget. These are applied to your account's usage to limit the scope
132
+ of what is considered for this budget. Leave empty to include all usage for this account. All
133
+ provided filters must be matched for usage to be included."""
83
134
 
84
- min_percentage: Optional[int] = None
85
- """Percentage of the target amount used in the currect period that will trigger a notification."""
135
+ update_time: Optional[int] = None
136
+ """Update time of this budget configuration."""
86
137
 
87
138
  def as_dict(self) -> dict:
88
- """Serializes the BudgetAlert into a dictionary suitable for use as a JSON request body."""
139
+ """Serializes the BudgetConfiguration into a dictionary suitable for use as a JSON request body."""
89
140
  body = {}
90
- if self.email_notifications: body['email_notifications'] = [v for v in self.email_notifications]
91
- if self.min_percentage is not None: body['min_percentage'] = self.min_percentage
141
+ if self.account_id is not None: body['account_id'] = self.account_id
142
+ if self.alert_configurations:
143
+ body['alert_configurations'] = [v.as_dict() for v in self.alert_configurations]
144
+ if self.budget_configuration_id is not None:
145
+ body['budget_configuration_id'] = self.budget_configuration_id
146
+ if self.create_time is not None: body['create_time'] = self.create_time
147
+ if self.display_name is not None: body['display_name'] = self.display_name
148
+ if self.filter: body['filter'] = self.filter.as_dict()
149
+ if self.update_time is not None: body['update_time'] = self.update_time
92
150
  return body
93
151
 
94
152
  @classmethod
95
- def from_dict(cls, d: Dict[str, any]) -> BudgetAlert:
96
- """Deserializes the BudgetAlert from a dictionary."""
97
- return cls(email_notifications=d.get('email_notifications', None),
98
- min_percentage=d.get('min_percentage', None))
153
+ def from_dict(cls, d: Dict[str, any]) -> BudgetConfiguration:
154
+ """Deserializes the BudgetConfiguration from a dictionary."""
155
+ return cls(account_id=d.get('account_id', None),
156
+ alert_configurations=_repeated_dict(d, 'alert_configurations', AlertConfiguration),
157
+ budget_configuration_id=d.get('budget_configuration_id', None),
158
+ create_time=d.get('create_time', None),
159
+ display_name=d.get('display_name', None),
160
+ filter=_from_dict(d, 'filter', BudgetConfigurationFilter),
161
+ update_time=d.get('update_time', None))
99
162
 
100
163
 
101
164
  @dataclass
102
- class BudgetList:
103
- """List of budgets."""
165
+ class BudgetConfigurationFilter:
166
+ tags: Optional[List[BudgetConfigurationFilterTagClause]] = None
167
+ """A list of tag keys and values that will limit the budget to usage that includes those specific
168
+ custom tags. Tags are case-sensitive and should be entered exactly as they appear in your usage
169
+ data."""
104
170
 
105
- budgets: Optional[List[BudgetWithStatus]] = None
171
+ workspace_id: Optional[BudgetConfigurationFilterWorkspaceIdClause] = None
172
+ """If provided, usage must match with the provided Databricks workspace IDs."""
106
173
 
107
174
  def as_dict(self) -> dict:
108
- """Serializes the BudgetList into a dictionary suitable for use as a JSON request body."""
175
+ """Serializes the BudgetConfigurationFilter into a dictionary suitable for use as a JSON request body."""
109
176
  body = {}
110
- if self.budgets: body['budgets'] = [v.as_dict() for v in self.budgets]
177
+ if self.tags: body['tags'] = [v.as_dict() for v in self.tags]
178
+ if self.workspace_id: body['workspace_id'] = self.workspace_id.as_dict()
111
179
  return body
112
180
 
113
181
  @classmethod
114
- def from_dict(cls, d: Dict[str, any]) -> BudgetList:
115
- """Deserializes the BudgetList from a dictionary."""
116
- return cls(budgets=_repeated_dict(d, 'budgets', BudgetWithStatus))
182
+ def from_dict(cls, d: Dict[str, any]) -> BudgetConfigurationFilter:
183
+ """Deserializes the BudgetConfigurationFilter from a dictionary."""
184
+ return cls(tags=_repeated_dict(d, 'tags', BudgetConfigurationFilterTagClause),
185
+ workspace_id=_from_dict(d, 'workspace_id', BudgetConfigurationFilterWorkspaceIdClause))
117
186
 
118
187
 
119
188
  @dataclass
120
- class BudgetWithStatus:
121
- """Budget configuration with daily status."""
189
+ class BudgetConfigurationFilterClause:
190
+ operator: Optional[BudgetConfigurationFilterOperator] = None
122
191
 
123
- alerts: Optional[List[BudgetAlert]] = None
192
+ values: Optional[List[str]] = None
124
193
 
125
- budget_id: Optional[str] = None
194
+ def as_dict(self) -> dict:
195
+ """Serializes the BudgetConfigurationFilterClause into a dictionary suitable for use as a JSON request body."""
196
+ body = {}
197
+ if self.operator is not None: body['operator'] = self.operator.value
198
+ if self.values: body['values'] = [v for v in self.values]
199
+ return body
126
200
 
127
- creation_time: Optional[str] = None
201
+ @classmethod
202
+ def from_dict(cls, d: Dict[str, any]) -> BudgetConfigurationFilterClause:
203
+ """Deserializes the BudgetConfigurationFilterClause from a dictionary."""
204
+ return cls(operator=_enum(d, 'operator', BudgetConfigurationFilterOperator),
205
+ values=d.get('values', None))
128
206
 
129
- end_date: Optional[str] = None
130
- """Optional end date of the budget."""
131
207
 
132
- filter: Optional[str] = None
133
- """SQL-like filter expression with workspaceId, SKU and tag. Usage in your account that matches
134
- this expression will be counted in this budget.
135
-
136
- Supported properties on left-hand side of comparison: * `workspaceId` - the ID of the workspace
137
- * `sku` - SKU of the cluster, e.g. `STANDARD_ALL_PURPOSE_COMPUTE` * `tag.tagName`, `tag.'tag
138
- name'` - tag of the cluster
139
-
140
- Supported comparison operators: * `=` - equal * `!=` - not equal
141
-
142
- Supported logical operators: `AND`, `OR`.
143
-
144
- Examples: * `workspaceId=123 OR (sku='STANDARD_ALL_PURPOSE_COMPUTE' AND tag.'my tag'='my
145
- value')` * `workspaceId!=456` * `sku='STANDARD_ALL_PURPOSE_COMPUTE' OR
146
- sku='PREMIUM_ALL_PURPOSE_COMPUTE'` * `tag.name1='value1' AND tag.name2='value2'`"""
208
+ class BudgetConfigurationFilterOperator(Enum):
147
209
 
148
- name: Optional[str] = None
149
- """Human-readable name of the budget."""
210
+ IN = 'IN'
150
211
 
151
- period: Optional[str] = None
152
- """Period length in years, months, weeks and/or days. Examples: `1 month`, `30 days`, `1 year, 2
153
- months, 1 week, 2 days`"""
154
212
 
155
- start_date: Optional[str] = None
156
- """Start date of the budget period calculation."""
213
+ @dataclass
214
+ class BudgetConfigurationFilterTagClause:
215
+ key: Optional[str] = None
157
216
 
158
- status_daily: Optional[List[BudgetWithStatusStatusDailyItem]] = None
159
- """Amount used in the budget for each day (noncumulative)."""
217
+ value: Optional[BudgetConfigurationFilterClause] = None
160
218
 
161
- target_amount: Optional[str] = None
162
- """Target amount of the budget per period in USD."""
219
+ def as_dict(self) -> dict:
220
+ """Serializes the BudgetConfigurationFilterTagClause into a dictionary suitable for use as a JSON request body."""
221
+ body = {}
222
+ if self.key is not None: body['key'] = self.key
223
+ if self.value: body['value'] = self.value.as_dict()
224
+ return body
225
+
226
+ @classmethod
227
+ def from_dict(cls, d: Dict[str, any]) -> BudgetConfigurationFilterTagClause:
228
+ """Deserializes the BudgetConfigurationFilterTagClause from a dictionary."""
229
+ return cls(key=d.get('key', None), value=_from_dict(d, 'value', BudgetConfigurationFilterClause))
230
+
231
+
232
+ @dataclass
233
+ class BudgetConfigurationFilterWorkspaceIdClause:
234
+ operator: Optional[BudgetConfigurationFilterOperator] = None
163
235
 
164
- update_time: Optional[str] = None
236
+ values: Optional[List[int]] = None
165
237
 
166
238
  def as_dict(self) -> dict:
167
- """Serializes the BudgetWithStatus into a dictionary suitable for use as a JSON request body."""
239
+ """Serializes the BudgetConfigurationFilterWorkspaceIdClause into a dictionary suitable for use as a JSON request body."""
168
240
  body = {}
169
- if self.alerts: body['alerts'] = [v.as_dict() for v in self.alerts]
170
- if self.budget_id is not None: body['budget_id'] = self.budget_id
171
- if self.creation_time is not None: body['creation_time'] = self.creation_time
172
- if self.end_date is not None: body['end_date'] = self.end_date
173
- if self.filter is not None: body['filter'] = self.filter
174
- if self.name is not None: body['name'] = self.name
175
- if self.period is not None: body['period'] = self.period
176
- if self.start_date is not None: body['start_date'] = self.start_date
177
- if self.status_daily: body['status_daily'] = [v.as_dict() for v in self.status_daily]
178
- if self.target_amount is not None: body['target_amount'] = self.target_amount
179
- if self.update_time is not None: body['update_time'] = self.update_time
241
+ if self.operator is not None: body['operator'] = self.operator.value
242
+ if self.values: body['values'] = [v for v in self.values]
180
243
  return body
181
244
 
182
245
  @classmethod
183
- def from_dict(cls, d: Dict[str, any]) -> BudgetWithStatus:
184
- """Deserializes the BudgetWithStatus from a dictionary."""
185
- return cls(alerts=_repeated_dict(d, 'alerts', BudgetAlert),
186
- budget_id=d.get('budget_id', None),
187
- creation_time=d.get('creation_time', None),
188
- end_date=d.get('end_date', None),
189
- filter=d.get('filter', None),
190
- name=d.get('name', None),
191
- period=d.get('period', None),
192
- start_date=d.get('start_date', None),
193
- status_daily=_repeated_dict(d, 'status_daily', BudgetWithStatusStatusDailyItem),
194
- target_amount=d.get('target_amount', None),
195
- update_time=d.get('update_time', None))
246
+ def from_dict(cls, d: Dict[str, any]) -> BudgetConfigurationFilterWorkspaceIdClause:
247
+ """Deserializes the BudgetConfigurationFilterWorkspaceIdClause from a dictionary."""
248
+ return cls(operator=_enum(d, 'operator', BudgetConfigurationFilterOperator),
249
+ values=d.get('values', None))
250
+
251
+
252
+ @dataclass
253
+ class CreateBillingUsageDashboardRequest:
254
+ dashboard_type: Optional[UsageDashboardType] = None
255
+ """Workspace level usage dashboard shows usage data for the specified workspace ID. Global level
256
+ usage dashboard shows usage data for all workspaces in the account."""
257
+
258
+ workspace_id: Optional[int] = None
259
+ """The workspace ID of the workspace in which the usage dashboard is created."""
260
+
261
+ def as_dict(self) -> dict:
262
+ """Serializes the CreateBillingUsageDashboardRequest into a dictionary suitable for use as a JSON request body."""
263
+ body = {}
264
+ if self.dashboard_type is not None: body['dashboard_type'] = self.dashboard_type.value
265
+ if self.workspace_id is not None: body['workspace_id'] = self.workspace_id
266
+ return body
267
+
268
+ @classmethod
269
+ def from_dict(cls, d: Dict[str, any]) -> CreateBillingUsageDashboardRequest:
270
+ """Deserializes the CreateBillingUsageDashboardRequest from a dictionary."""
271
+ return cls(dashboard_type=_enum(d, 'dashboard_type', UsageDashboardType),
272
+ workspace_id=d.get('workspace_id', None))
273
+
274
+
275
+ @dataclass
276
+ class CreateBillingUsageDashboardResponse:
277
+ dashboard_id: Optional[str] = None
278
+ """The unique id of the usage dashboard."""
279
+
280
+ def as_dict(self) -> dict:
281
+ """Serializes the CreateBillingUsageDashboardResponse into a dictionary suitable for use as a JSON request body."""
282
+ body = {}
283
+ if self.dashboard_id is not None: body['dashboard_id'] = self.dashboard_id
284
+ return body
285
+
286
+ @classmethod
287
+ def from_dict(cls, d: Dict[str, any]) -> CreateBillingUsageDashboardResponse:
288
+ """Deserializes the CreateBillingUsageDashboardResponse from a dictionary."""
289
+ return cls(dashboard_id=d.get('dashboard_id', None))
290
+
291
+
292
+ @dataclass
293
+ class CreateBudgetConfigurationBudget:
294
+ account_id: Optional[str] = None
295
+ """Databricks account ID."""
296
+
297
+ alert_configurations: Optional[List[CreateBudgetConfigurationBudgetAlertConfigurations]] = None
298
+ """Alerts to configure when this budget is in a triggered state. Budgets must have exactly one
299
+ alert configuration."""
300
+
301
+ display_name: Optional[str] = None
302
+ """Human-readable name of budget configuration. Max Length: 128"""
303
+
304
+ filter: Optional[BudgetConfigurationFilter] = None
305
+ """Configured filters for this budget. These are applied to your account's usage to limit the scope
306
+ of what is considered for this budget. Leave empty to include all usage for this account. All
307
+ provided filters must be matched for usage to be included."""
308
+
309
+ def as_dict(self) -> dict:
310
+ """Serializes the CreateBudgetConfigurationBudget into a dictionary suitable for use as a JSON request body."""
311
+ body = {}
312
+ if self.account_id is not None: body['account_id'] = self.account_id
313
+ if self.alert_configurations:
314
+ body['alert_configurations'] = [v.as_dict() for v in self.alert_configurations]
315
+ if self.display_name is not None: body['display_name'] = self.display_name
316
+ if self.filter: body['filter'] = self.filter.as_dict()
317
+ return body
318
+
319
+ @classmethod
320
+ def from_dict(cls, d: Dict[str, any]) -> CreateBudgetConfigurationBudget:
321
+ """Deserializes the CreateBudgetConfigurationBudget from a dictionary."""
322
+ return cls(account_id=d.get('account_id', None),
323
+ alert_configurations=_repeated_dict(d, 'alert_configurations',
324
+ CreateBudgetConfigurationBudgetAlertConfigurations),
325
+ display_name=d.get('display_name', None),
326
+ filter=_from_dict(d, 'filter', BudgetConfigurationFilter))
327
+
328
+
329
+ @dataclass
330
+ class CreateBudgetConfigurationBudgetActionConfigurations:
331
+ action_type: Optional[ActionConfigurationType] = None
332
+ """The type of the action."""
333
+
334
+ target: Optional[str] = None
335
+ """Target for the action. For example, an email address."""
336
+
337
+ def as_dict(self) -> dict:
338
+ """Serializes the CreateBudgetConfigurationBudgetActionConfigurations into a dictionary suitable for use as a JSON request body."""
339
+ body = {}
340
+ if self.action_type is not None: body['action_type'] = self.action_type.value
341
+ if self.target is not None: body['target'] = self.target
342
+ return body
343
+
344
+ @classmethod
345
+ def from_dict(cls, d: Dict[str, any]) -> CreateBudgetConfigurationBudgetActionConfigurations:
346
+ """Deserializes the CreateBudgetConfigurationBudgetActionConfigurations from a dictionary."""
347
+ return cls(action_type=_enum(d, 'action_type', ActionConfigurationType), target=d.get('target', None))
196
348
 
197
349
 
198
350
  @dataclass
199
- class BudgetWithStatusStatusDailyItem:
200
- amount: Optional[str] = None
201
- """Amount used in this day in USD."""
351
+ class CreateBudgetConfigurationBudgetAlertConfigurations:
352
+ action_configurations: Optional[List[CreateBudgetConfigurationBudgetActionConfigurations]] = None
353
+ """Configured actions for this alert. These define what happens when an alert enters a triggered
354
+ state."""
355
+
356
+ quantity_threshold: Optional[str] = None
357
+ """The threshold for the budget alert to determine if it is in a triggered state. The number is
358
+ evaluated based on `quantity_type`."""
202
359
 
203
- date: Optional[str] = None
360
+ quantity_type: Optional[AlertConfigurationQuantityType] = None
361
+ """The way to calculate cost for this budget alert. This is what `quantity_threshold` is measured
362
+ in."""
363
+
364
+ time_period: Optional[AlertConfigurationTimePeriod] = None
365
+ """The time window of usage data for the budget."""
366
+
367
+ trigger_type: Optional[AlertConfigurationTriggerType] = None
368
+ """The evaluation method to determine when this budget alert is in a triggered state."""
204
369
 
205
370
  def as_dict(self) -> dict:
206
- """Serializes the BudgetWithStatusStatusDailyItem into a dictionary suitable for use as a JSON request body."""
371
+ """Serializes the CreateBudgetConfigurationBudgetAlertConfigurations into a dictionary suitable for use as a JSON request body."""
207
372
  body = {}
208
- if self.amount is not None: body['amount'] = self.amount
209
- if self.date is not None: body['date'] = self.date
373
+ if self.action_configurations:
374
+ body['action_configurations'] = [v.as_dict() for v in self.action_configurations]
375
+ if self.quantity_threshold is not None: body['quantity_threshold'] = self.quantity_threshold
376
+ if self.quantity_type is not None: body['quantity_type'] = self.quantity_type.value
377
+ if self.time_period is not None: body['time_period'] = self.time_period.value
378
+ if self.trigger_type is not None: body['trigger_type'] = self.trigger_type.value
210
379
  return body
211
380
 
212
381
  @classmethod
213
- def from_dict(cls, d: Dict[str, any]) -> BudgetWithStatusStatusDailyItem:
214
- """Deserializes the BudgetWithStatusStatusDailyItem from a dictionary."""
215
- return cls(amount=d.get('amount', None), date=d.get('date', None))
382
+ def from_dict(cls, d: Dict[str, any]) -> CreateBudgetConfigurationBudgetAlertConfigurations:
383
+ """Deserializes the CreateBudgetConfigurationBudgetAlertConfigurations from a dictionary."""
384
+ return cls(action_configurations=_repeated_dict(d, 'action_configurations',
385
+ CreateBudgetConfigurationBudgetActionConfigurations),
386
+ quantity_threshold=d.get('quantity_threshold', None),
387
+ quantity_type=_enum(d, 'quantity_type', AlertConfigurationQuantityType),
388
+ time_period=_enum(d, 'time_period', AlertConfigurationTimePeriod),
389
+ trigger_type=_enum(d, 'trigger_type', AlertConfigurationTriggerType))
390
+
391
+
392
+ @dataclass
393
+ class CreateBudgetConfigurationRequest:
394
+ budget: CreateBudgetConfigurationBudget
395
+ """Properties of the new budget configuration."""
396
+
397
+ def as_dict(self) -> dict:
398
+ """Serializes the CreateBudgetConfigurationRequest into a dictionary suitable for use as a JSON request body."""
399
+ body = {}
400
+ if self.budget: body['budget'] = self.budget.as_dict()
401
+ return body
402
+
403
+ @classmethod
404
+ def from_dict(cls, d: Dict[str, any]) -> CreateBudgetConfigurationRequest:
405
+ """Deserializes the CreateBudgetConfigurationRequest from a dictionary."""
406
+ return cls(budget=_from_dict(d, 'budget', CreateBudgetConfigurationBudget))
407
+
408
+
409
+ @dataclass
410
+ class CreateBudgetConfigurationResponse:
411
+ budget: Optional[BudgetConfiguration] = None
412
+ """The created budget configuration."""
413
+
414
+ def as_dict(self) -> dict:
415
+ """Serializes the CreateBudgetConfigurationResponse into a dictionary suitable for use as a JSON request body."""
416
+ body = {}
417
+ if self.budget: body['budget'] = self.budget.as_dict()
418
+ return body
419
+
420
+ @classmethod
421
+ def from_dict(cls, d: Dict[str, any]) -> CreateBudgetConfigurationResponse:
422
+ """Deserializes the CreateBudgetConfigurationResponse from a dictionary."""
423
+ return cls(budget=_from_dict(d, 'budget', BudgetConfiguration))
216
424
 
217
425
 
218
426
  @dataclass
@@ -316,16 +524,16 @@ class CreateLogDeliveryConfigurationParams:
316
524
 
317
525
 
318
526
  @dataclass
319
- class DeleteResponse:
527
+ class DeleteBudgetConfigurationResponse:
320
528
 
321
529
  def as_dict(self) -> dict:
322
- """Serializes the DeleteResponse into a dictionary suitable for use as a JSON request body."""
530
+ """Serializes the DeleteBudgetConfigurationResponse into a dictionary suitable for use as a JSON request body."""
323
531
  body = {}
324
532
  return body
325
533
 
326
534
  @classmethod
327
- def from_dict(cls, d: Dict[str, any]) -> DeleteResponse:
328
- """Deserializes the DeleteResponse from a dictionary."""
535
+ def from_dict(cls, d: Dict[str, any]) -> DeleteBudgetConfigurationResponse:
536
+ """Deserializes the DeleteBudgetConfigurationResponse from a dictionary."""
329
537
  return cls()
330
538
 
331
539
 
@@ -361,6 +569,65 @@ class DownloadResponse:
361
569
  return cls(contents=d.get('contents', None))
362
570
 
363
571
 
572
+ @dataclass
573
+ class GetBillingUsageDashboardResponse:
574
+ dashboard_id: Optional[str] = None
575
+ """The unique id of the usage dashboard."""
576
+
577
+ dashboard_url: Optional[str] = None
578
+ """The URL of the usage dashboard."""
579
+
580
+ def as_dict(self) -> dict:
581
+ """Serializes the GetBillingUsageDashboardResponse into a dictionary suitable for use as a JSON request body."""
582
+ body = {}
583
+ if self.dashboard_id is not None: body['dashboard_id'] = self.dashboard_id
584
+ if self.dashboard_url is not None: body['dashboard_url'] = self.dashboard_url
585
+ return body
586
+
587
+ @classmethod
588
+ def from_dict(cls, d: Dict[str, any]) -> GetBillingUsageDashboardResponse:
589
+ """Deserializes the GetBillingUsageDashboardResponse from a dictionary."""
590
+ return cls(dashboard_id=d.get('dashboard_id', None), dashboard_url=d.get('dashboard_url', None))
591
+
592
+
593
+ @dataclass
594
+ class GetBudgetConfigurationResponse:
595
+ budget: Optional[BudgetConfiguration] = None
596
+
597
+ def as_dict(self) -> dict:
598
+ """Serializes the GetBudgetConfigurationResponse into a dictionary suitable for use as a JSON request body."""
599
+ body = {}
600
+ if self.budget: body['budget'] = self.budget.as_dict()
601
+ return body
602
+
603
+ @classmethod
604
+ def from_dict(cls, d: Dict[str, any]) -> GetBudgetConfigurationResponse:
605
+ """Deserializes the GetBudgetConfigurationResponse from a dictionary."""
606
+ return cls(budget=_from_dict(d, 'budget', BudgetConfiguration))
607
+
608
+
609
+ @dataclass
610
+ class ListBudgetConfigurationsResponse:
611
+ budgets: Optional[List[BudgetConfiguration]] = None
612
+
613
+ next_page_token: Optional[str] = None
614
+ """Token which can be sent as `page_token` to retrieve the next page of results. If this field is
615
+ omitted, there are no subsequent budgets."""
616
+
617
+ def as_dict(self) -> dict:
618
+ """Serializes the ListBudgetConfigurationsResponse into a dictionary suitable for use as a JSON request body."""
619
+ body = {}
620
+ if self.budgets: body['budgets'] = [v.as_dict() for v in self.budgets]
621
+ if self.next_page_token is not None: body['next_page_token'] = self.next_page_token
622
+ return body
623
+
624
+ @classmethod
625
+ def from_dict(cls, d: Dict[str, any]) -> ListBudgetConfigurationsResponse:
626
+ """Deserializes the ListBudgetConfigurationsResponse from a dictionary."""
627
+ return cls(budgets=_repeated_dict(d, 'budgets', BudgetConfiguration),
628
+ next_page_token=d.get('next_page_token', None))
629
+
630
+
364
631
  class LogDeliveryConfigStatus(Enum):
365
632
  """Status of log delivery configuration. Set to `ENABLED` (enabled) or `DISABLED` (disabled).
366
633
  Defaults to `ENABLED`. You can [enable or disable the
@@ -586,81 +853,116 @@ class PatchStatusResponse:
586
853
 
587
854
 
588
855
  @dataclass
589
- class UpdateLogDeliveryConfigurationStatusRequest:
590
- status: LogDeliveryConfigStatus
591
- """Status of log delivery configuration. Set to `ENABLED` (enabled) or `DISABLED` (disabled).
592
- Defaults to `ENABLED`. You can [enable or disable the
593
- configuration](#operation/patch-log-delivery-config-status) later. Deletion of a configuration
594
- is not supported, so disable a log delivery configuration that is no longer needed."""
856
+ class UpdateBudgetConfigurationBudget:
857
+ account_id: Optional[str] = None
858
+ """Databricks account ID."""
595
859
 
596
- log_delivery_configuration_id: Optional[str] = None
597
- """Databricks log delivery configuration ID"""
860
+ alert_configurations: Optional[List[AlertConfiguration]] = None
861
+ """Alerts to configure when this budget is in a triggered state. Budgets must have exactly one
862
+ alert configuration."""
863
+
864
+ budget_configuration_id: Optional[str] = None
865
+ """Databricks budget configuration ID."""
866
+
867
+ display_name: Optional[str] = None
868
+ """Human-readable name of budget configuration. Max Length: 128"""
869
+
870
+ filter: Optional[BudgetConfigurationFilter] = None
871
+ """Configured filters for this budget. These are applied to your account's usage to limit the scope
872
+ of what is considered for this budget. Leave empty to include all usage for this account. All
873
+ provided filters must be matched for usage to be included."""
598
874
 
599
875
  def as_dict(self) -> dict:
600
- """Serializes the UpdateLogDeliveryConfigurationStatusRequest into a dictionary suitable for use as a JSON request body."""
876
+ """Serializes the UpdateBudgetConfigurationBudget into a dictionary suitable for use as a JSON request body."""
601
877
  body = {}
602
- if self.log_delivery_configuration_id is not None:
603
- body['log_delivery_configuration_id'] = self.log_delivery_configuration_id
604
- if self.status is not None: body['status'] = self.status.value
878
+ if self.account_id is not None: body['account_id'] = self.account_id
879
+ if self.alert_configurations:
880
+ body['alert_configurations'] = [v.as_dict() for v in self.alert_configurations]
881
+ if self.budget_configuration_id is not None:
882
+ body['budget_configuration_id'] = self.budget_configuration_id
883
+ if self.display_name is not None: body['display_name'] = self.display_name
884
+ if self.filter: body['filter'] = self.filter.as_dict()
605
885
  return body
606
886
 
607
887
  @classmethod
608
- def from_dict(cls, d: Dict[str, any]) -> UpdateLogDeliveryConfigurationStatusRequest:
609
- """Deserializes the UpdateLogDeliveryConfigurationStatusRequest from a dictionary."""
610
- return cls(log_delivery_configuration_id=d.get('log_delivery_configuration_id', None),
611
- status=_enum(d, 'status', LogDeliveryConfigStatus))
888
+ def from_dict(cls, d: Dict[str, any]) -> UpdateBudgetConfigurationBudget:
889
+ """Deserializes the UpdateBudgetConfigurationBudget from a dictionary."""
890
+ return cls(account_id=d.get('account_id', None),
891
+ alert_configurations=_repeated_dict(d, 'alert_configurations', AlertConfiguration),
892
+ budget_configuration_id=d.get('budget_configuration_id', None),
893
+ display_name=d.get('display_name', None),
894
+ filter=_from_dict(d, 'filter', BudgetConfigurationFilter))
612
895
 
613
896
 
614
897
  @dataclass
615
- class UpdateResponse:
898
+ class UpdateBudgetConfigurationRequest:
899
+ budget: UpdateBudgetConfigurationBudget
900
+ """The updated budget. This will overwrite the budget specified by the budget ID."""
901
+
902
+ budget_id: Optional[str] = None
903
+ """The Databricks budget configuration ID."""
616
904
 
617
905
  def as_dict(self) -> dict:
618
- """Serializes the UpdateResponse into a dictionary suitable for use as a JSON request body."""
906
+ """Serializes the UpdateBudgetConfigurationRequest into a dictionary suitable for use as a JSON request body."""
619
907
  body = {}
908
+ if self.budget: body['budget'] = self.budget.as_dict()
909
+ if self.budget_id is not None: body['budget_id'] = self.budget_id
620
910
  return body
621
911
 
622
912
  @classmethod
623
- def from_dict(cls, d: Dict[str, any]) -> UpdateResponse:
624
- """Deserializes the UpdateResponse from a dictionary."""
625
- return cls()
913
+ def from_dict(cls, d: Dict[str, any]) -> UpdateBudgetConfigurationRequest:
914
+ """Deserializes the UpdateBudgetConfigurationRequest from a dictionary."""
915
+ return cls(budget=_from_dict(d, 'budget', UpdateBudgetConfigurationBudget),
916
+ budget_id=d.get('budget_id', None))
626
917
 
627
918
 
628
919
  @dataclass
629
- class WrappedBudget:
630
- budget: Budget
631
- """Budget configuration to be created."""
632
-
633
- budget_id: Optional[str] = None
634
- """Budget ID"""
920
+ class UpdateBudgetConfigurationResponse:
921
+ budget: Optional[BudgetConfiguration] = None
922
+ """The updated budget."""
635
923
 
636
924
  def as_dict(self) -> dict:
637
- """Serializes the WrappedBudget into a dictionary suitable for use as a JSON request body."""
925
+ """Serializes the UpdateBudgetConfigurationResponse into a dictionary suitable for use as a JSON request body."""
638
926
  body = {}
639
927
  if self.budget: body['budget'] = self.budget.as_dict()
640
- if self.budget_id is not None: body['budget_id'] = self.budget_id
641
928
  return body
642
929
 
643
930
  @classmethod
644
- def from_dict(cls, d: Dict[str, any]) -> WrappedBudget:
645
- """Deserializes the WrappedBudget from a dictionary."""
646
- return cls(budget=_from_dict(d, 'budget', Budget), budget_id=d.get('budget_id', None))
931
+ def from_dict(cls, d: Dict[str, any]) -> UpdateBudgetConfigurationResponse:
932
+ """Deserializes the UpdateBudgetConfigurationResponse from a dictionary."""
933
+ return cls(budget=_from_dict(d, 'budget', BudgetConfiguration))
647
934
 
648
935
 
649
936
  @dataclass
650
- class WrappedBudgetWithStatus:
651
- budget: BudgetWithStatus
652
- """Budget configuration with daily status."""
937
+ class UpdateLogDeliveryConfigurationStatusRequest:
938
+ status: LogDeliveryConfigStatus
939
+ """Status of log delivery configuration. Set to `ENABLED` (enabled) or `DISABLED` (disabled).
940
+ Defaults to `ENABLED`. You can [enable or disable the
941
+ configuration](#operation/patch-log-delivery-config-status) later. Deletion of a configuration
942
+ is not supported, so disable a log delivery configuration that is no longer needed."""
943
+
944
+ log_delivery_configuration_id: Optional[str] = None
945
+ """Databricks log delivery configuration ID"""
653
946
 
654
947
  def as_dict(self) -> dict:
655
- """Serializes the WrappedBudgetWithStatus into a dictionary suitable for use as a JSON request body."""
948
+ """Serializes the UpdateLogDeliveryConfigurationStatusRequest into a dictionary suitable for use as a JSON request body."""
656
949
  body = {}
657
- if self.budget: body['budget'] = self.budget.as_dict()
950
+ if self.log_delivery_configuration_id is not None:
951
+ body['log_delivery_configuration_id'] = self.log_delivery_configuration_id
952
+ if self.status is not None: body['status'] = self.status.value
658
953
  return body
659
954
 
660
955
  @classmethod
661
- def from_dict(cls, d: Dict[str, any]) -> WrappedBudgetWithStatus:
662
- """Deserializes the WrappedBudgetWithStatus from a dictionary."""
663
- return cls(budget=_from_dict(d, 'budget', BudgetWithStatus))
956
+ def from_dict(cls, d: Dict[str, any]) -> UpdateLogDeliveryConfigurationStatusRequest:
957
+ """Deserializes the UpdateLogDeliveryConfigurationStatusRequest from a dictionary."""
958
+ return cls(log_delivery_configuration_id=d.get('log_delivery_configuration_id', None),
959
+ status=_enum(d, 'status', LogDeliveryConfigStatus))
960
+
961
+
962
+ class UsageDashboardType(Enum):
963
+
964
+ USAGE_DASHBOARD_TYPE_GLOBAL = 'USAGE_DASHBOARD_TYPE_GLOBAL'
965
+ USAGE_DASHBOARD_TYPE_WORKSPACE = 'USAGE_DASHBOARD_TYPE_WORKSPACE'
664
966
 
665
967
 
666
968
  @dataclass
@@ -767,39 +1069,42 @@ class BillableUsageAPI:
767
1069
 
768
1070
 
769
1071
  class BudgetsAPI:
770
- """These APIs manage budget configuration including notifications for exceeding a budget for a period. They
771
- can also retrieve the status of each budget."""
1072
+ """These APIs manage budget configurations for this account. Budgets enable you to monitor usage across your
1073
+ account. You can set up budgets to either track account-wide spending, or apply filters to track the
1074
+ spending of specific teams, projects, or workspaces."""
772
1075
 
773
1076
  def __init__(self, api_client):
774
1077
  self._api = api_client
775
1078
 
776
- def create(self, budget: Budget) -> WrappedBudgetWithStatus:
777
- """Create a new budget.
1079
+ def create(self, budget: CreateBudgetConfigurationBudget) -> CreateBudgetConfigurationResponse:
1080
+ """Create new budget.
778
1081
 
779
- Creates a new budget in the specified account.
1082
+ Create a new budget configuration for an account. For full details, see
1083
+ https://docs.databricks.com/en/admin/account-settings/budgets.html.
780
1084
 
781
- :param budget: :class:`Budget`
782
- Budget configuration to be created.
1085
+ :param budget: :class:`CreateBudgetConfigurationBudget`
1086
+ Properties of the new budget configuration.
783
1087
 
784
- :returns: :class:`WrappedBudgetWithStatus`
1088
+ :returns: :class:`CreateBudgetConfigurationResponse`
785
1089
  """
786
1090
  body = {}
787
1091
  if budget is not None: body['budget'] = budget.as_dict()
788
1092
  headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
789
1093
 
790
1094
  res = self._api.do('POST',
791
- f'/api/2.0/accounts/{self._api.account_id}/budget',
1095
+ f'/api/2.1/accounts/{self._api.account_id}/budgets',
792
1096
  body=body,
793
1097
  headers=headers)
794
- return WrappedBudgetWithStatus.from_dict(res)
1098
+ return CreateBudgetConfigurationResponse.from_dict(res)
795
1099
 
796
1100
  def delete(self, budget_id: str):
797
1101
  """Delete budget.
798
1102
 
799
- Deletes the budget specified by its UUID.
1103
+ Deletes a budget configuration for an account. Both account and budget configuration are specified by
1104
+ ID. This cannot be undone.
800
1105
 
801
1106
  :param budget_id: str
802
- Budget ID
1107
+ The Databricks budget configuration ID.
803
1108
 
804
1109
 
805
1110
  """
@@ -807,63 +1112,78 @@ class BudgetsAPI:
807
1112
  headers = {'Accept': 'application/json', }
808
1113
 
809
1114
  self._api.do('DELETE',
810
- f'/api/2.0/accounts/{self._api.account_id}/budget/{budget_id}',
1115
+ f'/api/2.1/accounts/{self._api.account_id}/budgets/{budget_id}',
811
1116
  headers=headers)
812
1117
 
813
- def get(self, budget_id: str) -> WrappedBudgetWithStatus:
814
- """Get budget and its status.
1118
+ def get(self, budget_id: str) -> GetBudgetConfigurationResponse:
1119
+ """Get budget.
815
1120
 
816
- Gets the budget specified by its UUID, including noncumulative status for each day that the budget is
817
- configured to include.
1121
+ Gets a budget configuration for an account. Both account and budget configuration are specified by ID.
818
1122
 
819
1123
  :param budget_id: str
820
- Budget ID
1124
+ The Databricks budget configuration ID.
821
1125
 
822
- :returns: :class:`WrappedBudgetWithStatus`
1126
+ :returns: :class:`GetBudgetConfigurationResponse`
823
1127
  """
824
1128
 
825
1129
  headers = {'Accept': 'application/json', }
826
1130
 
827
1131
  res = self._api.do('GET',
828
- f'/api/2.0/accounts/{self._api.account_id}/budget/{budget_id}',
1132
+ f'/api/2.1/accounts/{self._api.account_id}/budgets/{budget_id}',
829
1133
  headers=headers)
830
- return WrappedBudgetWithStatus.from_dict(res)
1134
+ return GetBudgetConfigurationResponse.from_dict(res)
831
1135
 
832
- def list(self) -> Iterator[BudgetWithStatus]:
1136
+ def list(self, *, page_token: Optional[str] = None) -> Iterator[BudgetConfiguration]:
833
1137
  """Get all budgets.
834
1138
 
835
- Gets all budgets associated with this account, including noncumulative status for each day that the
836
- budget is configured to include.
1139
+ Gets all budgets associated with this account.
1140
+
1141
+ :param page_token: str (optional)
1142
+ A page token received from a previous get all budget configurations call. This token can be used to
1143
+ retrieve the subsequent page. Requests first page if absent.
837
1144
 
838
- :returns: Iterator over :class:`BudgetWithStatus`
1145
+ :returns: Iterator over :class:`BudgetConfiguration`
839
1146
  """
840
1147
 
1148
+ query = {}
1149
+ if page_token is not None: query['page_token'] = page_token
841
1150
  headers = {'Accept': 'application/json', }
842
1151
 
843
- json = self._api.do('GET', f'/api/2.0/accounts/{self._api.account_id}/budget', headers=headers)
844
- parsed = BudgetList.from_dict(json).budgets
845
- return parsed if parsed is not None else []
846
-
847
- def update(self, budget_id: str, budget: Budget):
1152
+ while True:
1153
+ json = self._api.do('GET',
1154
+ f'/api/2.1/accounts/{self._api.account_id}/budgets',
1155
+ query=query,
1156
+ headers=headers)
1157
+ if 'budgets' in json:
1158
+ for v in json['budgets']:
1159
+ yield BudgetConfiguration.from_dict(v)
1160
+ if 'next_page_token' not in json or not json['next_page_token']:
1161
+ return
1162
+ query['page_token'] = json['next_page_token']
1163
+
1164
+ def update(self, budget_id: str,
1165
+ budget: UpdateBudgetConfigurationBudget) -> UpdateBudgetConfigurationResponse:
848
1166
  """Modify budget.
849
1167
 
850
- Modifies a budget in this account. Budget properties are completely overwritten.
1168
+ Updates a budget configuration for an account. Both account and budget configuration are specified by
1169
+ ID.
851
1170
 
852
1171
  :param budget_id: str
853
- Budget ID
854
- :param budget: :class:`Budget`
855
- Budget configuration to be created.
856
-
1172
+ The Databricks budget configuration ID.
1173
+ :param budget: :class:`UpdateBudgetConfigurationBudget`
1174
+ The updated budget. This will overwrite the budget specified by the budget ID.
857
1175
 
1176
+ :returns: :class:`UpdateBudgetConfigurationResponse`
858
1177
  """
859
1178
  body = {}
860
1179
  if budget is not None: body['budget'] = budget.as_dict()
861
1180
  headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
862
1181
 
863
- self._api.do('PATCH',
864
- f'/api/2.0/accounts/{self._api.account_id}/budget/{budget_id}',
865
- body=body,
866
- headers=headers)
1182
+ res = self._api.do('PUT',
1183
+ f'/api/2.1/accounts/{self._api.account_id}/budgets/{budget_id}',
1184
+ body=body,
1185
+ headers=headers)
1186
+ return UpdateBudgetConfigurationResponse.from_dict(res)
867
1187
 
868
1188
 
869
1189
  class LogDeliveryAPI:
@@ -1037,3 +1357,67 @@ class LogDeliveryAPI:
1037
1357
  f'/api/2.0/accounts/{self._api.account_id}/log-delivery/{log_delivery_configuration_id}',
1038
1358
  body=body,
1039
1359
  headers=headers)
1360
+
1361
+
1362
+ class UsageDashboardsAPI:
1363
+ """These APIs manage usage dashboards for this account. Usage dashboards enable you to gain insights into
1364
+ your usage with pre-built dashboards: visualize breakdowns, analyze tag attributions, and identify cost
1365
+ drivers."""
1366
+
1367
+ def __init__(self, api_client):
1368
+ self._api = api_client
1369
+
1370
+ def create(self,
1371
+ *,
1372
+ dashboard_type: Optional[UsageDashboardType] = None,
1373
+ workspace_id: Optional[int] = None) -> CreateBillingUsageDashboardResponse:
1374
+ """Create new usage dashboard.
1375
+
1376
+ Create a usage dashboard specified by workspaceId, accountId, and dashboard type.
1377
+
1378
+ :param dashboard_type: :class:`UsageDashboardType` (optional)
1379
+ Workspace level usage dashboard shows usage data for the specified workspace ID. Global level usage
1380
+ dashboard shows usage data for all workspaces in the account.
1381
+ :param workspace_id: int (optional)
1382
+ The workspace ID of the workspace in which the usage dashboard is created.
1383
+
1384
+ :returns: :class:`CreateBillingUsageDashboardResponse`
1385
+ """
1386
+ body = {}
1387
+ if dashboard_type is not None: body['dashboard_type'] = dashboard_type.value
1388
+ if workspace_id is not None: body['workspace_id'] = workspace_id
1389
+ headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
1390
+
1391
+ res = self._api.do('POST',
1392
+ f'/api/2.0/accounts/{self._api.account_id}/dashboard',
1393
+ body=body,
1394
+ headers=headers)
1395
+ return CreateBillingUsageDashboardResponse.from_dict(res)
1396
+
1397
+ def get(self,
1398
+ *,
1399
+ dashboard_type: Optional[UsageDashboardType] = None,
1400
+ workspace_id: Optional[int] = None) -> GetBillingUsageDashboardResponse:
1401
+ """Get usage dashboard.
1402
+
1403
+ Get a usage dashboard specified by workspaceId, accountId, and dashboard type.
1404
+
1405
+ :param dashboard_type: :class:`UsageDashboardType` (optional)
1406
+ Workspace level usage dashboard shows usage data for the specified workspace ID. Global level usage
1407
+ dashboard shows usage data for all workspaces in the account.
1408
+ :param workspace_id: int (optional)
1409
+ The workspace ID of the workspace in which the usage dashboard is created.
1410
+
1411
+ :returns: :class:`GetBillingUsageDashboardResponse`
1412
+ """
1413
+
1414
+ query = {}
1415
+ if dashboard_type is not None: query['dashboard_type'] = dashboard_type.value
1416
+ if workspace_id is not None: query['workspace_id'] = workspace_id
1417
+ headers = {'Accept': 'application/json', }
1418
+
1419
+ res = self._api.do('GET',
1420
+ f'/api/2.0/accounts/{self._api.account_id}/dashboard',
1421
+ query=query,
1422
+ headers=headers)
1423
+ return GetBillingUsageDashboardResponse.from_dict(res)