Skip to content

Commit

Permalink
Added databricks_sql_alert resource (#2047)
Browse files Browse the repository at this point in the history
  • Loading branch information
kartikgupta-db authored Mar 14, 2023
1 parent a0921ab commit cf8cc0f
Show file tree
Hide file tree
Showing 4 changed files with 250 additions and 0 deletions.
61 changes: 61 additions & 0 deletions docs/resources/sql_alert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
subcategory: "Databricks SQL"
---
# databricks_sql_alert Resource

This resource allows you to manage [Databricks SQL Alerts](https://docs.databricks.com/sql/user/queries/index.html).

**Note:** To manage [SQLA resources](https://docs.databricks.com/sql/get-started/concepts.html) you must have `databricks_sql_access` on your [databricks_group](group.md#databricks_sql_access) or [databricks_user](user.md#databricks_sql_access).

## Example Usage

```hcl
resource "databricks_directory" "shared_dir" {
path = "/Shared/Queries"
}
resource "databricks_sql_query" "this" {
data_source_id = databricks_sql_endpoint.example.data_source_id
name = "My Query Name"
query = "SELECT 1 AS p1, 2 as p2"
parent = "folders/${databricks_directory.shared_dir.object_id}"
}
resource "databricks_sql_alert" "alert" {
query_id = databricks_sql_query.this.id
name = "My Alert"
parent = "folders/${databricks_directory.shared_dir.object_id}"
rearm = 1
options {
column = "p1"
op = "=="
value = "2"
muted = false
}
}
```

## Argument Reference

The following arguments are available:

* `query_id` - (Required, String) ID of the query evaluated by the alert.
* `name` - (Required, String) Name of the alert.
* `options` - (Required) Alert configuration options.
* `column` - (Required, String) Name of column in the query result to compare in alert evaluation.
* `op` - (Required, String Enum) Operator used to compare in alert evaluation. (Enum: `>`, `>=`, `<`, `<=`, `==`, `!=`)
* `value` - (Required, String) Value used to compare in alert evaluation.
* `muted` - (Optional, bool) Whether or not the alert is muted. If an alert is muted, it will not notify users and alert destinations when triggered.
* `custom_subject` - (Optional, String) Custom subject of alert notification, if it exists. This includes email subject, Slack notification header, etc. See [Alerts API reference](https://docs.databricks.com/sql/user/alerts/index.html) for custom templating instructions.
* `custom_body` - (Optional, String) Custom body of alert notification, if it exists. See [Alerts API reference](https://docs.databricks.com/sql/user/alerts/index.html) for custom templating instructions.
* `parent` - (Optional, String) The identifier of the workspace folder containing the alert. The default is ther user's home folder. The folder identifier is formatted as `folder/<folder_id>`.
* `rearm` - (Optional, Integer) Number of seconds after being triggered before the alert rearms itself and can be triggered again. If not defined, alert will never be triggered again.

## Related Resources

The following resources are often used in the same context:

* [End to end workspace management](../guides/workspace-management.md) guide.
* [databricks_sql_query](sql_query.md) to manage Databricks SQL [Queries](https://docs.databricks.com/sql/user/queries/index.html).
* [databricks_sql_endpoint](sql_endpoint.md) to manage Databricks SQL [Endpoints](https://docs.databricks.com/sql/admin/sql-endpoints.html).
* [databricks_directory](directory.md) to manage directories in [Databricks Workpace](https://docs.databricks.com/workspace/workspace-objects.html).
45 changes: 45 additions & 0 deletions internal/acceptance/sql_alert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package acceptance

import (
"testing"
)

func TestAccAlert(t *testing.T) {
workspaceLevel(t, step{
Template: `
resource "databricks_sql_query" "this" {
data_source_id = "{env.TEST_DEFAULT_WAREHOUSE_DATASOURCE_ID}"
name = "tf-{var.RANDOM}"
query = "SELECT 1 AS p1, 2 as p2"
}
resource "databricks_sql_alert" "alert" {
query_id = databricks_sql_query.this.id
name = "tf-alert-{var.RANDOM}"
options {
column = "p1"
op = "=="
value = "2"
muted = false
}
}`,
}, step{
Template: `
resource "databricks_sql_query" "this" {
data_source_id = "{env.TEST_DEFAULT_WAREHOUSE_DATASOURCE_ID}"
name = "tf-{var.RANDOM}"
query = "SELECT 1 AS p1, 2 as p2"
}
resource "databricks_sql_alert" "alert" {
query_id = databricks_sql_query.this.id
name = "tf-alert-{var.RANDOM}"
options {
column = "p1"
op = ">="
value = "2"
muted = false
}
}`,
})
}
1 change: 1 addition & 0 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ func DatabricksProvider() *schema.Provider {
"databricks_sql_global_config": sql.ResourceSqlGlobalConfig(),
"databricks_sql_permissions": access.ResourceSqlPermissions(),
"databricks_sql_query": sql.ResourceSqlQuery(),
"databricks_sql_alert": sql.ResourceSqlAlert(),
"databricks_sql_visualization": sql.ResourceSqlVisualization(),
"databricks_sql_widget": sql.ResourceSqlWidget(),
"databricks_storage_credential": catalog.ResourceStorageCredential(),
Expand Down
143 changes: 143 additions & 0 deletions sql/resource_sql_alerts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package sql

import (
"context"

"github.com/databricks/databricks-sdk-go/service/sql"
"github.com/databricks/terraform-provider-databricks/common"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

type AlertOptions struct {
Column string `json:"column"`
Op string `json:"op"`
Value string `json:"value"`
Muted bool `json:"muted,omitempty"`
CustomBody string `json:"custom_body,omitempty"`
CustomSubject string `json:"custom_subject,omitempty"`
}

type AlertEntity struct {
Name string `json:"name"`
QueryId string `json:"query_id"`
Rearm int `json:"rearm,omitempty"`
Options *AlertOptions `json:"options"`
Parent string `json:"parent,omitempty" tf:"suppress_diff,force_new"`
}

func (a *AlertEntity) toCreateAlertApiObject(s map[string]*schema.Schema, data *schema.ResourceData) (sql.CreateAlert, error) {
common.DataToStructPointer(data, s, a)

var ca sql.CreateAlert
ca.Name = a.Name
ca.Parent = a.Parent
ca.QueryId = a.QueryId
ca.Rearm = a.Rearm
ca.Options = sql.AlertOptions{
Column: a.Options.Column,
CustomBody: a.Options.CustomBody,
CustomSubject: a.Options.CustomSubject,
Muted: a.Options.Muted,
Op: a.Options.Op,
Value: a.Options.Value,
}

return ca, nil
}

func (a *AlertEntity) toEditAlertApiObject(s map[string]*schema.Schema, data *schema.ResourceData) (sql.EditAlert, error) {
common.DataToStructPointer(data, s, a)

return sql.EditAlert{
AlertId: data.Id(),
Name: a.Name,
Options: sql.AlertOptions{
Column: a.Options.Column,
CustomBody: a.Options.CustomBody,
CustomSubject: a.Options.CustomSubject,
Muted: a.Options.Muted,
Op: a.Options.Op,
Value: a.Options.Value,
},
QueryId: a.QueryId,
Rearm: a.Rearm,
}, nil
}

func (a *AlertEntity) fromAPIObject(apiAlert *sql.Alert, s map[string]*schema.Schema, data *schema.ResourceData) error {
a.Name = apiAlert.Name
a.Parent = apiAlert.Parent
a.QueryId = apiAlert.Query.Id
a.Rearm = apiAlert.Rearm
a.Options = &AlertOptions{
Column: apiAlert.Options.Column,
Op: apiAlert.Options.Op,
Value: apiAlert.Options.Value,
Muted: apiAlert.Options.Muted,
CustomBody: apiAlert.Options.CustomBody,
CustomSubject: apiAlert.Options.CustomSubject,
}

return common.StructToData(a, s, data)
}

func ResourceSqlAlert() *schema.Resource {
s := common.StructToSchema(AlertEntity{}, func(m map[string]*schema.Schema) map[string]*schema.Schema {
options := m["options"].Elem.(*schema.Resource)
options.Schema["op"].ValidateFunc = validation.StringInSlice([]string{">", ">=", "<", "<=", "==", "!="}, true)
return m
})

return common.Resource{
Create: func(ctx context.Context, data *schema.ResourceData, c *common.DatabricksClient) error {
w, err := c.WorkspaceClient()
if err != nil {
return err
}
var a AlertEntity
ca, err := a.toCreateAlertApiObject(s, data)
if err != nil {
return err
}
apiAlert, err := w.Alerts.Create(ctx, ca)
if err != nil {
return err
}
data.SetId(apiAlert.Id)
return nil
},
Read: func(ctx context.Context, data *schema.ResourceData, c *common.DatabricksClient) error {
w, err := c.WorkspaceClient()
if err != nil {
return err
}
apiAlert, err := w.Alerts.GetByAlertId(ctx, data.Id())
if err != nil {
return err
}
var a AlertEntity
return a.fromAPIObject(apiAlert, s, data)
},
Update: func(ctx context.Context, data *schema.ResourceData, c *common.DatabricksClient) error {
w, err := c.WorkspaceClient()
if err != nil {
return err
}
var a AlertEntity
ca, err := a.toEditAlertApiObject(s, data)
if err != nil {
return err
}
return w.Alerts.Update(ctx, ca)
},
Delete: func(ctx context.Context, data *schema.ResourceData, c *common.DatabricksClient) error {
w, err := c.WorkspaceClient()
if err != nil {
return err
}
return w.Alerts.DeleteByAlertId(ctx, data.Id())
},
Schema: s,
}.ToResource()
}

0 comments on commit cf8cc0f

Please sign in to comment.