Skip to content

Commit 03659b6

Browse files
authored
[Feature] Add databricks_query resource instead of databricks_sql_query (#4103)
## Changes <!-- Summary of your changes that are easy to understand --> This PR is built on top of #4051 which should be merged first. The new resource uses the new [Queries API](https://docs.databricks.com/api/workspace/queries/create) instead of the legacy one that will be deprecated. Since the new resource has a slightly different set of parameters, it was decided to create a new resource and deprecate the old one. This resource uses old TF SDK to be compatible with TF exporter (until #4050 is implemented). TODOs: - Need to discuss how to handle permissions - `sql_query` permissions look like working, but not sure if we should continue to use that API - Support in the exporter will be in a separate PR ## Tests <!-- How is this tested? Please see the checklist below and also describe any other relevant tests --> - [x] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [x] using Go SDK
1 parent df26499 commit 03659b6

File tree

14 files changed

+637
-43
lines changed

14 files changed

+637
-43
lines changed

docs/resources/alert.md

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ resource "databricks_directory" "shared_dir" {
1313
}
1414
1515
# This will be replaced with new databricks_query resource
16-
resource "databricks_sql_query" "this" {
17-
data_source_id = databricks_sql_endpoint.example.data_source_id
18-
name = "My Query Name"
19-
query = "SELECT 42 as value"
20-
parent = "folders/${databricks_directory.shared_dir.object_id}"
16+
resource "databricks_query" "this" {
17+
warehouse_id = databricks_sql_endpoint.example.id
18+
display_name = "My Query Name"
19+
query_text = "SELECT 42 as value"
20+
parent_path = databricks_directory.shared_dir.path
2121
}
2222
2323
resource "databricks_alert" "alert" {
24-
query_id = databricks_sql_query.this.id
24+
query_id = databricks_query.this.id
2525
display_name = "TF new alert"
2626
parent_path = databricks_directory.shared_dir.path
2727
condition {
@@ -77,7 +77,11 @@ In addition to all the arguments above, the following attributes are exported:
7777

7878
## Migrating from `databricks_sql_alert` resource
7979

80-
Under the hood, the new resource uses the same data as the `databricks_sql_alert`, but is exposed via a different API. This means that we can migrate existing alerts without recreating them. This operation is done in few steps:
80+
Under the hood, the new resource uses the same data as the `databricks_sql_alert`, but is exposed via a different API. This means that we can migrate existing alerts without recreating them.
81+
82+
-> It's also recommended to migrate to the `databricks_query` resource - see [databricks_query](query.md) for more details.
83+
84+
This operation is done in few steps:
8185

8286
* Record the ID of existing `databricks_sql_alert`, for example, by executing the `terraform state show databricks_sql_alert.alert` command.
8387
* Create the code for the new implementation by performing the following changes:
@@ -109,7 +113,7 @@ we'll have a new resource defined as:
109113

110114
```hcl
111115
resource "databricks_alert" "alert" {
112-
query_id = databricks_sql_query.this.id
116+
query_id = databricks_query.this.id
113117
display_name = "My Alert"
114118
parent_path = databricks_directory.shared_dir.path
115119
condition {
@@ -179,6 +183,20 @@ resource "databricks_permissions" "alert_usage" {
179183
}
180184
```
181185

186+
## Access Control
187+
188+
[databricks_permissions](permissions.md#sql-alert-usage) can control which groups or individual users can *Manage*, *Edit*, *Run* or *View* individual alerts.
189+
190+
```hcl
191+
resource "databricks_permissions" "alert_usage" {
192+
sql_alert_id = databricks_alert.alert.id
193+
access_control {
194+
group_name = "users"
195+
permission_level = "CAN_RUN"
196+
}
197+
}
198+
```
199+
182200
## Import
183201

184202
This resource can be imported using alert ID:
@@ -191,6 +209,6 @@ terraform import databricks_alert.this <alert-id>
191209

192210
The following resources are often used in the same context:
193211

194-
* [databricks_sql_query](sql_query.md) to manage Databricks SQL [Queries](https://docs.databricks.com/sql/user/queries/index.html).
195-
* [databricks_sql_endpoint](sql_endpoint.md) to manage Databricks SQL [Endpoints](https://docs.databricks.com/sql/admin/sql-endpoints.html).
212+
* [databricks_query](query.md) to manage [Databricks SQL Queries](https://docs.databricks.com/sql/user/queries/index.html).
213+
* [databricks_sql_endpoint](sql_endpoint.md) to manage [Databricks SQL Endpoints](https://docs.databricks.com/sql/admin/sql-endpoints.html).
196214
* [databricks_directory](directory.md) to manage directories in [Databricks Workpace](https://docs.databricks.com/workspace/workspace-objects.html).

docs/resources/job.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,14 +224,14 @@ One of the `query`, `dashboard` or `alert` needs to be provided.
224224

225225
* `warehouse_id` - (Required) ID of the (the [databricks_sql_endpoint](sql_endpoint.md)) that will be used to execute the task. Only Serverless & Pro warehouses are supported right now.
226226
* `parameters` - (Optional) (Map) parameters to be used for each run of this task. The SQL alert task does not support custom parameters.
227-
* `query` - (Optional) block consisting of single string field: `query_id` - identifier of the Databricks SQL Query ([databricks_sql_query](sql_query.md)).
227+
* `query` - (Optional) block consisting of single string field: `query_id` - identifier of the Databricks Query ([databricks_query](query.md)).
228228
* `dashboard` - (Optional) block consisting of following fields:
229229
* `dashboard_id` - (Required) (String) identifier of the Databricks SQL Dashboard [databricks_sql_dashboard](sql_dashboard.md).
230230
* `subscriptions` - (Optional) a list of subscription blocks consisting out of one of the required fields: `user_name` for user emails or `destination_id` - for Alert destination's identifier.
231231
* `custom_subject` - (Optional) string specifying a custom subject of email sent.
232232
* `pause_subscriptions` - (Optional) flag that specifies if subscriptions are paused or not.
233233
* `alert` - (Optional) block consisting of following fields:
234-
* `alert_id` - (Required) (String) identifier of the Databricks SQL Alert.
234+
* `alert_id` - (Required) (String) identifier of the Databricks Alert ([databricks_alert](alert.md)).
235235
* `subscriptions` - (Optional) a list of subscription blocks consisting out of one of the required fields: `user_name` for user emails or `destination_id` - for Alert destination's identifier.
236236
* `pause_subscriptions` - (Optional) flag that specifies if subscriptions are paused or not.
237237
* `file` - (Optional) block consisting of single string fields:

docs/resources/query.md

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
---
2+
subcategory: "Databricks SQL"
3+
---
4+
# databricks_query Resource
5+
6+
This resource allows you to manage [Databricks SQL Queries](https://docs.databricks.com/en/sql/user/queries/index.html). It supersedes [databricks_sql_query](sql_query.md) resource - see migration guide below for more details.
7+
8+
## Example Usage
9+
10+
```hcl
11+
resource "databricks_directory" "shared_dir" {
12+
path = "/Shared/Queries"
13+
}
14+
15+
# This will be replaced with new databricks_query resource
16+
resource "databricks_query" "this" {
17+
warehouse_id = databricks_sql_endpoint.example.id
18+
display_name = "My Query Name"
19+
query_text = "SELECT 42 as value"
20+
parent_path = databricks_directory.shared_dir.path
21+
}
22+
```
23+
24+
## Argument Reference
25+
26+
The following arguments are available:
27+
28+
* `query_text` - (Required, String) Text of SQL query.
29+
* `display_name` - (Required, String) Name of the query.
30+
* `warehouse_id` - (Required, String) ID of a SQL warehouse which will be used to execute this query.
31+
* `parent_path` - (Optional, String) The path to a workspace folder containing the query. The default is the user's home folder. If changed, the query will be recreated.
32+
* `owner_user_name` - (Optional, String) Query owner's username.
33+
* `apply_auto_limit` - (Optional, Boolean) Whether to apply a 1000 row limit to the query result.
34+
* `catalog` - (Optional, String) Name of the catalog where this query will be executed.
35+
* `schema` - (Optional, String) Name of the schema where this query will be executed.
36+
* `description` - (Optional, String) General description that conveys additional information about this query such as usage notes.
37+
* `run_as_mode` - (Optional, String) Sets the "Run as" role for the object.
38+
* `tags` - (Optional, List of strings) Tags that will be added to the query.
39+
* `parameter` - (Optional, Block) Query parameter definition. Consists of following attributes (one of `*_value` is required):
40+
* `name` - (Required, String) Literal parameter marker that appears between double curly braces in the query text.
41+
* `title` - (Optional, String) Text displayed in the user-facing parameter widget in the UI.
42+
* `text_value` - (Block) Text parameter value. Consists of following attributes:
43+
* `value` - (Required, String) - actual text value.
44+
* `numeric_value` - (Block) Numeric parameter value. Consists of following attributes:
45+
* `value` - (Required, Double) - actual numeric value.
46+
* `date_value` - (Block) Date query parameter value. Consists of following attributes (Can only specify one of `dynamic_date_value` or `date_value`):
47+
* `date_value` - (String) Manually specified date-time value
48+
* `dynamic_date_value` - (String) Dynamic date-time value based on current date-time. Possible values are `NOW`, `YESTERDAY`.
49+
* `precision` - (Optional, String) Date-time precision to format the value into when the query is run. Possible values are `DAY_PRECISION`, `MINUTE_PRECISION`, `SECOND_PRECISION`. Defaults to `DAY_PRECISION` (`YYYY-MM-DD`).
50+
* `date_range_value` - (Block) Date-range query parameter value. Consists of following attributes (Can only specify one of `dynamic_date_range_value` or `date_range_value`):
51+
* `date_range_value` - (Block) Manually specified date-time range value. Consists of the following attributes:
52+
* `start` (Required, String) - begin of the date range.
53+
* `end` (Required, String) - end of the date range.
54+
* `dynamic_date_range_value` - (String) Dynamic date-time range value based on current date-time. Possible values are `TODAY`, `YESTERDAY`, `THIS_WEEK`, `THIS_MONTH`, `THIS_YEAR`, `LAST_WEEK`, `LAST_MONTH`, `LAST_YEAR`, `LAST_HOUR`, `LAST_8_HOURS`, `LAST_24_HOURS`, `LAST_7_DAYS`, `LAST_14_DAYS`, `LAST_30_DAYS`, `LAST_60_DAYS`, `LAST_90_DAYS`, `LAST_12_MONTHS`.
55+
* `start_day_of_week` - (Optional, Int) Specify what day that starts the week.
56+
* `precision` - (Optional, String) Date-time precision to format the value into when the query is run. Possible values are `DAY_PRECISION`, `MINUTE_PRECISION`, `SECOND_PRECISION`. Defaults to `DAY_PRECISION` (`YYYY-MM-DD`).
57+
* `enum_value` - (Block) Dropdown parameter value. Consists of following attributes:
58+
* `enum_options` - (String) List of valid query parameter values, newline delimited.
59+
* `values` - (Array of strings) List of selected query parameter values.
60+
* `multi_values_options` - (Optional, Block) If specified, allows multiple values to be selected for this parameter. Consists of following attributes:
61+
* `prefix` - (Optional, String) Character that prefixes each selected parameter value.
62+
* `separator` - (Optional, String) Character that separates each selected parameter value. Defaults to a comma.
63+
* `suffix` - (Optional, String) Character that suffixes each selected parameter value.
64+
* `query_backed_value` - (Block) Query-based dropdown parameter value. Consists of following attributes:
65+
* `query_id` - (Required, String) ID of the query that provides the parameter values.
66+
* `values` - (Array of strings) List of selected query parameter values.
67+
* `multi_values_options` - (Optional, Block) If specified, allows multiple values to be selected for this parameter. Consists of following attributes:
68+
* `prefix` - (Optional, String) Character that prefixes each selected parameter value.
69+
* `separator` - (Optional, String) Character that separates each selected parameter value. Defaults to a comma.
70+
* `suffix` - (Optional, String) Character that suffixes each selected parameter value.
71+
72+
## Attribute Reference
73+
74+
In addition to all the arguments above, the following attributes are exported:
75+
76+
* `id` - unique ID of the created Query.
77+
* `lifecycle_state` - The workspace state of the query. Used for tracking trashed status. (Possible values are `ACTIVE` or `TRASHED`).
78+
* `last_modifier_user_name` - Username of the user who last saved changes to this query.
79+
* `create_time` - The timestamp string indicating when the query was created.
80+
* `update_time` - The timestamp string indicating when the query was updated.
81+
82+
## Migrating from `databricks_sql_query` resource
83+
84+
Under the hood, the new resource uses the same data as the `databricks_sql_query`, but exposed via different API. This means that we can migrate existing queries without recreating them. This operation is done in few steps:
85+
86+
* Record the ID of existing `databricks_sql_query`, for example, by executing the `terraform state show databricks_sql_query.query` command.
87+
* Create the code for the new implementation performing following changes:
88+
* the `name` attribute is now named `display_name`
89+
* the `parent` (if exists) is renamed to `parent_path` attribute, and should be converted from `folders/object_id` to the actual path.
90+
* Blocks that specify values in the `parameter` block were renamed (see above).
91+
92+
For example, if we have the original `databricks_sql_query` defined as:
93+
94+
```hcl
95+
resource "databricks_sql_query" "query" {
96+
data_source_id = databricks_sql_endpoint.example.data_source_id
97+
query = "select 42 as value"
98+
name = "My Query"
99+
parent = "folders/${databricks_directory.shared_dir.object_id}"
100+
101+
parameter {
102+
name = "p1"
103+
title = "Title for p1"
104+
text {
105+
value = "default"
106+
}
107+
}
108+
}
109+
```
110+
111+
we'll have a new resource defined as:
112+
113+
```hcl
114+
resource "databricks_query" "query" {
115+
warehouse_id = databricks_sql_endpoint.example.id
116+
query_text = "select 42 as value"
117+
display_name = "My Query"
118+
parent_path = databricks_directory.shared_dir.path
119+
120+
parameter {
121+
name = "p1"
122+
title = "Title for p1"
123+
text_value {
124+
value = "default"
125+
}
126+
}
127+
}
128+
```
129+
130+
### For Terraform version >= 1.7.0
131+
132+
Terraform 1.7 introduced the [removed](https://developer.hashicorp.com/terraform/language/resources/syntax#removing-resources) block in addition to the [import](https://developer.hashicorp.com/terraform/language/import) block introduced in Terraform 1.5. Together they make import and removal of resources easier, avoiding manual execution of `terraform import` and `terraform state rm` commands.
133+
134+
So with Terraform 1.7+, the migration looks as the following:
135+
136+
* remove the old query definition and replace it with the new one.
137+
* Adjust references, like, `databricks_permissions`.
138+
* Add `import` and `removed` blocks like this:
139+
140+
```hcl
141+
import {
142+
to = databricks_query.query
143+
id = "<query-id>"
144+
}
145+
146+
removed {
147+
from = databricks_sql_query.query
148+
149+
lifecycle {
150+
destroy = false
151+
}
152+
}
153+
```
154+
155+
* Run the `terraform plan` command to check possible changes, such as value type change, etc.
156+
* Run the `terraform apply` command to apply changes.
157+
* Remove the `import` and `removed` blocks from the code.
158+
159+
### For Terraform version < 1.7.0
160+
161+
* Remove the old query definition and replace it with the new one.
162+
* Remove the old resource from the state with the `terraform state rm databricks_sql_query.query` command.
163+
* Import new resource with the `terraform import databricks_query.query <query-id>` command.
164+
* Adjust references, like, `databricks_permissions`.
165+
* Run the `terraform plan` command to check possible changes, such as value type change, etc.
166+
167+
## Access Control
168+
169+
[databricks_permissions](permissions.md#sql-query-usage) can control which groups or individual users can *Manage*, *Edit*, *Run* or *View* individual queries.
170+
171+
```hcl
172+
resource "databricks_permissions" "query_usage" {
173+
sql_query_id = databricks_query.query.id
174+
access_control {
175+
group_name = "users"
176+
permission_level = "CAN_RUN"
177+
}
178+
}
179+
```
180+
181+
## Import
182+
183+
This resource can be imported using query ID:
184+
185+
```bash
186+
terraform import databricks_query.this <query-id>
187+
```
188+
189+
## Related Resources
190+
191+
The following resources are often used in the same context:
192+
193+
* [databricks_alert](alert.md) to manage [Databricks SQL Alerts](https://docs.databricks.com/en/sql/user/alerts/index.html).
194+
* [databricks_sql_endpoint](sql_endpoint.md) to manage [Databricks SQL Endpoints](https://docs.databricks.com/sql/admin/sql-endpoints.html).
195+
* [databricks_directory](directory.md) to manage directories in [Databricks Workpace](https://docs.databricks.com/workspace/workspace-objects.html).

internal/acceptance/alert_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ import (
77
func TestAccAlert(t *testing.T) {
88
WorkspaceLevel(t, Step{
99
Template: `
10-
resource "databricks_sql_query" "this" {
11-
data_source_id = "{env.TEST_DEFAULT_WAREHOUSE_DATASOURCE_ID}"
12-
name = "tf-{var.RANDOM}"
13-
query = "SELECT 1 AS p1, 2 as p2"
10+
resource "databricks_query" "this" {
11+
warehouse_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}"
12+
display_name = "tf-{var.RANDOM}"
13+
query_text = "SELECT 1 AS p1, 2 as p2"
1414
}
1515
1616
resource "databricks_alert" "alert" {
17-
query_id = databricks_sql_query.this.id
17+
query_id = databricks_query.this.id
1818
display_name = "tf-alert-{var.RANDOM}"
1919
condition {
2020
op = "EQUAL"
@@ -33,14 +33,14 @@ func TestAccAlert(t *testing.T) {
3333
`,
3434
}, Step{
3535
Template: `
36-
resource "databricks_sql_query" "this" {
37-
data_source_id = "{env.TEST_DEFAULT_WAREHOUSE_DATASOURCE_ID}"
38-
name = "tf-{var.RANDOM}"
39-
query = "SELECT 1 AS p1, 2 as p2"
36+
resource "databricks_query" "this" {
37+
warehouse_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}"
38+
display_name = "tf-{var.RANDOM}"
39+
query_text = "SELECT 1 AS p1, 2 as p2"
4040
}
4141
4242
resource "databricks_alert" "alert" {
43-
query_id = databricks_sql_query.this.id
43+
query_id = databricks_query.this.id
4444
display_name = "tf-alert-{var.RANDOM}"
4545
condition {
4646
op = "GREATER_THAN"

internal/acceptance/permissions_test.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -841,20 +841,20 @@ func TestAccPermissions_ServingEndpoint(t *testing.T) {
841841
func TestAccPermissions_Alert(t *testing.T) {
842842
loadDebugEnvIfRunsFromIDE(t, "workspace")
843843
alertTemplate := `
844-
resource "databricks_sql_query" "this" {
845-
name = "{var.STICKY_RANDOM}-query"
846-
query = "SELECT 1 AS p1, 2 as p2"
847-
data_source_id = "{env.TEST_DEFAULT_WAREHOUSE_DATASOURCE_ID}"
844+
resource "databricks_query" "this" {
845+
display_name = "{var.STICKY_RANDOM}-query"
846+
query_text = "SELECT 1 AS p1, 2 as p2"
847+
warehouse_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}"
848848
}
849849
850850
resource "databricks_alert" "this" {
851-
query_id = databricks_sql_query.this.id
851+
query_id = databricks_query.this.id
852852
display_name = "{var.STICKY_RANDOM}-alert"
853853
condition {
854854
op = "GREATER_THAN"
855855
operand {
856856
column {
857-
name = "value"
857+
name = "p1"
858858
}
859859
}
860860
threshold {
@@ -876,3 +876,23 @@ func TestAccPermissions_Alert(t *testing.T) {
876876
ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for alert, allowed levels: CAN_MANAGE"),
877877
})
878878
}
879+
880+
func TestAccPermissions_Query(t *testing.T) {
881+
loadDebugEnvIfRunsFromIDE(t, "workspace")
882+
queryTemplate := `
883+
resource "databricks_query" "this" {
884+
display_name = "{var.STICKY_RANDOM}-query"
885+
query_text = "SELECT 1 AS p1, 2 as p2"
886+
warehouse_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}"
887+
}`
888+
WorkspaceLevel(t, Step{
889+
Template: queryTemplate + makePermissionsTestStage("sql_query_id", "databricks_query.this.id", groupPermissions("CAN_VIEW")),
890+
}, Step{
891+
Template: queryTemplate + makePermissionsTestStage("sql_query_id", "databricks_query.this.id",
892+
currentPrincipalPermission(t, "CAN_MANAGE"), groupPermissions("CAN_VIEW", "CAN_EDIT", "CAN_RUN", "CAN_MANAGE")),
893+
}, Step{
894+
Template: queryTemplate + makePermissionsTestStage("sql_query_id", "databricks_query.this.id",
895+
currentPrincipalPermission(t, "CAN_VIEW"), groupPermissions("CAN_VIEW", "CAN_EDIT", "CAN_RUN", "CAN_MANAGE")),
896+
ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for query, allowed levels: CAN_MANAGE"),
897+
})
898+
}

0 commit comments

Comments
 (0)