Skip to content

Commit

Permalink
feat: Warehouse redesign part3 (#2890)
Browse files Browse the repository at this point in the history
Warehouses redesign part2 (continuation of
#2887):
- add datasource
- handle error for show warehouse

Still missing (next PR):
- encapsulate 3-value boolean logic
- extract and generalize part of read logic
  • Loading branch information
sfc-gh-asawicki committed Jun 27, 2024
1 parent 1aaf417 commit 873a1ed
Show file tree
Hide file tree
Showing 18 changed files with 599 additions and 92 deletions.
8 changes: 8 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ To easily handle three-value logic (true, false, unknown) in provider's configs,
#### *(note)* `resource_monitor` validation and diff suppression
`resource_monitor` is an identifier and handling logic may be still slightly changed as part of https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/ROADMAP.md#identifiers-rework. It should be handled automatically (without needed manual actions on user side), though, but it is not guaranteed.

#### *(behavior change)* snowflake_databases datasource
- Added `like` field to enable warehouse filtering
- Added missing fields returned by SHOW WAREHOUSES and enclosed its output in `show_output` field.
- Added outputs from **DESC WAREHOUSE** and **SHOW PARAMETERS IN WAREHOUSE** (they can be turned off by declaring `with_describe = false` and `with_parameters = false`, **they're turned on by default**).
The additional parameters call **DESC WAREHOUSE** (with `with_describe` turned on) and **SHOW PARAMETERS IN WAREHOUSE** (with `with_parameters` turned on) **per warehouse** returned by **SHOW WAREHOUSES**.
The outputs of both commands are held in `warehouses` entry, where **DESC WAREHOUSE** is saved in the `describe_output` field, and **SHOW PARAMETERS IN WAREHOUSE** in the `parameters` field.
It's important to limit the records and calls to Snowflake to the minimum. That's why we recommend assessing which information you need from the data source and then providing strong filters and turning off additional fields for better plan performance.

### new database resources
As part of the [preparation for v1](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/ROADMAP.md#preparing-essential-ga-objects-for-the-provider-v1), we split up the database resource into multiple ones:
- Standard database - can be used as `snowflake_database` (replaces the old one and is used to create databases with optional ability to become a primary database ready for replication)
Expand Down
10 changes: 5 additions & 5 deletions docs/data-sources/databases.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
page_title: "snowflake_databases Data Source - terraform-provider-snowflake"
subcategory: ""
description: |-
Datasource used to get details of filtered databases. Filtering is aligned with the current possibilities for SHOW DATABASES (https://docs.snowflake.com/en/sql-reference/sql/show-databases) query (`like`, 'starts_with', and `limit` are all supported. The results of SHOW, DESCRIBE, and SHOW PARAMETERS IN are encapsulated in one output collection.
---

# snowflake_databases (Data Source)


Datasource used to get details of filtered databases. Filtering is aligned with the current possibilities for [SHOW DATABASES]((https://docs.snowflake.com/en/sql-reference/sql/show-databases) query (`like`, 'starts_with', and `limit` are all supported). The results of SHOW, DESCRIBE, and SHOW PARAMETERS IN are encapsulated in one output collection.

## Example Usage

Expand Down Expand Up @@ -81,8 +81,8 @@ check "database_check" {
}
assert {
condition = length(data.snowflake_databases.test.databases) == 1
error_message = "Databases filtered by '${data.snowflake_databases.test.like}' returned ${length(data.snowflake_databases.test.databases)} databases where one was expected"
condition = length(data.snowflake_databases.assert_with_check_block.databases) == 1
error_message = "Databases filtered by '${data.snowflake_databases.assert_with_check_block.like}' returned ${length(data.snowflake_databases.assert_with_check_block.databases)} databases where one was expected"
}
}
```
Expand All @@ -100,7 +100,7 @@ check "database_check" {

### Read-Only

- `databases` (List of Object) Holds the output of SHOW DATABASES. (see [below for nested schema](#nestedatt--databases))
- `databases` (List of Object) Holds the aggregated output of all database details queries. (see [below for nested schema](#nestedatt--databases))
- `id` (String) The ID of this resource.

<a id="nestedblock--limit"></a>
Expand Down
159 changes: 155 additions & 4 deletions docs/data-sources/warehouses.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,187 @@
page_title: "snowflake_warehouses Data Source - terraform-provider-snowflake"
subcategory: ""
description: |-
Datasource used to get details of filtered warehouses. Filtering is aligned with the current possibilities for [SHOW WAREHOUSES]((https://docs.snowflake.com/en/sql-reference/sql/show-warehouses) query (only like is supported). The results of SHOW, DESCRIBE, and SHOW PARAMETERS IN are encapsulated in one output collection.
---

# snowflake_warehouses (Data Source)


Datasource used to get details of filtered warehouses. Filtering is aligned with the current possibilities for [SHOW WAREHOUSES]((https://docs.snowflake.com/en/sql-reference/sql/show-warehouses) query (only `like` is supported). The results of SHOW, DESCRIBE, and SHOW PARAMETERS IN are encapsulated in one output collection.

## Example Usage

```terraform
data "snowflake_warehouses" "current" {
# Simple usage
data "snowflake_warehouses" "simple" {
}
output "simple_output" {
value = data.snowflake_warehouses.simple.warehouses
}
# Filtering (like)
data "snowflake_warehouses" "like" {
like = "warehouse-name"
}
output "like_output" {
value = data.snowflake_warehouses.like.warehouses
}
# Filtering by prefix (like)
data "snowflake_warehouses" "like_prefix" {
like = "prefix%"
}
output "like_prefix_output" {
value = data.snowflake_warehouses.like_prefix.warehouses
}
# Without additional data (to limit the number of calls make for every found warehouse)
data "snowflake_warehouses" "only_show" {
# with_describe is turned on by default and it calls DESCRIBE WAREHOUSE for every warehouse found and attaches its output to warehouses.*.describe_output field
with_describe = false
# with_parameters is turned on by default and it calls SHOW PARAMETERS FOR WAREHOUSE for every warehouse found and attaches its output to warehouses.*.parameters field
with_parameters = false
}
output "only_show_output" {
value = data.snowflake_warehouses.only_show.warehouses
}
# Ensure the number of warehouses is equal to at least one element (with the use of postcondition)
data "snowflake_warehouses" "assert_with_postcondition" {
like = "warehouse-name%"
lifecycle {
postcondition {
condition = length(self.warehouses) > 0
error_message = "there should be at least one warehouse"
}
}
}
# Ensure the number of warehouses is equal to at exactly one element (with the use of check block)
check "warehouse_check" {
data "snowflake_warehouses" "assert_with_check_block" {
like = "warehouse-name"
}
assert {
condition = length(data.snowflake_warehouses.assert_with_check_block.warehouses) == 1
error_message = "warehouses filtered by '${data.snowflake_warehouses.assert_with_check_block.like}' returned ${length(data.snowflake_warehouses.assert_with_check_block.warehouses)} warehouses where one was expected"
}
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Optional

- `like` (String) Filters the output with **case-insensitive** pattern, with support for SQL wildcard characters (`%` and `_`).
- `with_describe` (Boolean) Runs DESC WAREHOUSE for each warehouse returned by SHOW WAREHOUSES. The output of describe is saved to the description field. By default this value is set to true.
- `with_parameters` (Boolean) Runs SHOW PARAMETERS FOR WAREHOUSE for each warehouse returned by SHOW WAREHOUSES. The output of describe is saved to the parameters field as a map. By default this value is set to true.

### Read-Only

- `id` (String) The ID of this resource.
- `warehouses` (List of Object) The warehouses in the database (see [below for nested schema](#nestedatt--warehouses))
- `warehouses` (List of Object) Holds the aggregated output of all warehouse details queries. (see [below for nested schema](#nestedatt--warehouses))

<a id="nestedatt--warehouses"></a>
### Nested Schema for `warehouses`

Read-Only:

- `describe_output` (List of Object) (see [below for nested schema](#nestedobjatt--warehouses--describe_output))
- `parameters` (List of Object) (see [below for nested schema](#nestedobjatt--warehouses--parameters))
- `show_output` (List of Object) (see [below for nested schema](#nestedobjatt--warehouses--show_output))

<a id="nestedobjatt--warehouses--describe_output"></a>
### Nested Schema for `warehouses.describe_output`

Read-Only:

- `created_on` (String)
- `kind` (String)
- `name` (String)


<a id="nestedobjatt--warehouses--parameters"></a>
### Nested Schema for `warehouses.parameters`

Read-Only:

- `max_concurrency_level` (List of Object) (see [below for nested schema](#nestedobjatt--warehouses--parameters--max_concurrency_level))
- `statement_queued_timeout_in_seconds` (List of Object) (see [below for nested schema](#nestedobjatt--warehouses--parameters--statement_queued_timeout_in_seconds))
- `statement_timeout_in_seconds` (List of Object) (see [below for nested schema](#nestedobjatt--warehouses--parameters--statement_timeout_in_seconds))

<a id="nestedobjatt--warehouses--parameters--max_concurrency_level"></a>
### Nested Schema for `warehouses.parameters.max_concurrency_level`

Read-Only:

- `default` (String)
- `description` (String)
- `key` (String)
- `level` (String)
- `value` (String)


<a id="nestedobjatt--warehouses--parameters--statement_queued_timeout_in_seconds"></a>
### Nested Schema for `warehouses.parameters.statement_queued_timeout_in_seconds`

Read-Only:

- `default` (String)
- `description` (String)
- `key` (String)
- `level` (String)
- `value` (String)


<a id="nestedobjatt--warehouses--parameters--statement_timeout_in_seconds"></a>
### Nested Schema for `warehouses.parameters.statement_timeout_in_seconds`

Read-Only:

- `default` (String)
- `description` (String)
- `key` (String)
- `level` (String)
- `value` (String)



<a id="nestedobjatt--warehouses--show_output"></a>
### Nested Schema for `warehouses.show_output`

Read-Only:

- `auto_resume` (Boolean)
- `auto_suspend` (Number)
- `available` (Number)
- `comment` (String)
- `created_on` (String)
- `enable_query_acceleration` (Boolean)
- `is_current` (Boolean)
- `is_default` (Boolean)
- `max_cluster_count` (Number)
- `min_cluster_count` (Number)
- `name` (String)
- `other` (Number)
- `owner` (String)
- `owner_role_type` (String)
- `provisioning` (Number)
- `query_acceleration_max_scale_factor` (Number)
- `queued` (Number)
- `quiescing` (Number)
- `resource_monitor` (String)
- `resumed_on` (String)
- `running` (Number)
- `scaling_policy` (String)
- `size` (String)
- `started_clusters` (Number)
- `state` (String)
- `type` (String)
- `updated_on` (String)
4 changes: 2 additions & 2 deletions examples/data-sources/snowflake_databases/data-source.tf
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ check "database_check" {
}

assert {
condition = length(data.snowflake_databases.test.databases) == 1
error_message = "Databases filtered by '${data.snowflake_databases.test.like}' returned ${length(data.snowflake_databases.test.databases)} databases where one was expected"
condition = length(data.snowflake_databases.assert_with_check_block.databases) == 1
error_message = "Databases filtered by '${data.snowflake_databases.assert_with_check_block.like}' returned ${length(data.snowflake_databases.assert_with_check_block.databases)} databases where one was expected"
}
}
63 changes: 61 additions & 2 deletions examples/data-sources/snowflake_warehouses/data-source.tf
Original file line number Diff line number Diff line change
@@ -1,2 +1,61 @@
data "snowflake_warehouses" "current" {
}
# Simple usage
data "snowflake_warehouses" "simple" {
}

output "simple_output" {
value = data.snowflake_warehouses.simple.warehouses
}

# Filtering (like)
data "snowflake_warehouses" "like" {
like = "warehouse-name"
}

output "like_output" {
value = data.snowflake_warehouses.like.warehouses
}

# Filtering by prefix (like)
data "snowflake_warehouses" "like_prefix" {
like = "prefix%"
}

output "like_prefix_output" {
value = data.snowflake_warehouses.like_prefix.warehouses
}

# Without additional data (to limit the number of calls make for every found warehouse)
data "snowflake_warehouses" "only_show" {
# with_describe is turned on by default and it calls DESCRIBE WAREHOUSE for every warehouse found and attaches its output to warehouses.*.describe_output field
with_describe = false

# with_parameters is turned on by default and it calls SHOW PARAMETERS FOR WAREHOUSE for every warehouse found and attaches its output to warehouses.*.parameters field
with_parameters = false
}

output "only_show_output" {
value = data.snowflake_warehouses.only_show.warehouses
}

# Ensure the number of warehouses is equal to at least one element (with the use of postcondition)
data "snowflake_warehouses" "assert_with_postcondition" {
like = "warehouse-name%"
lifecycle {
postcondition {
condition = length(self.warehouses) > 0
error_message = "there should be at least one warehouse"
}
}
}

# Ensure the number of warehouses is equal to at exactly one element (with the use of check block)
check "warehouse_check" {
data "snowflake_warehouses" "assert_with_check_block" {
like = "warehouse-name"
}

assert {
condition = length(data.snowflake_warehouses.assert_with_check_block.warehouses) == 1
error_message = "warehouses filtered by '${data.snowflake_warehouses.assert_with_check_block.like}' returned ${length(data.snowflake_warehouses.assert_with_check_block.warehouses)} warehouses where one was expected"
}
}
3 changes: 2 additions & 1 deletion pkg/datasources/databases.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ var databasesSchema = map[string]*schema.Schema{
"databases": {
Type: schema.TypeList,
Computed: true,
Description: "Holds the output of SHOW DATABASES.",
Description: "Holds the aggregated output of all database details queries.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"show_output": {
Expand Down Expand Up @@ -95,6 +95,7 @@ func Databases() *schema.Resource {
return &schema.Resource{
ReadContext: ReadDatabases,
Schema: databasesSchema,
Description: "Datasource used to get details of filtered databases. Filtering is aligned with the current possibilities for [SHOW DATABASES]((https://docs.snowflake.com/en/sql-reference/sql/show-databases) query (`like`, 'starts_with', and `limit` are all supported). The results of SHOW, DESCRIBE, and SHOW PARAMETERS IN are encapsulated in one output collection.",
}
}

Expand Down
15 changes: 7 additions & 8 deletions pkg/datasources/databases_acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ import (
"regexp"
"testing"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources"
"github.com/hashicorp/terraform-plugin-testing/config"

acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/testenvs"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources"
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/tfversion"
)

func TestAcc_Databases_Complete(t *testing.T) {
_ = testenvs.GetOrSkipTest(t, testenvs.ConfigureClientOnce)
databaseName := acc.TestClient().Ids.Alpha()
comment := random.Comment()

Expand All @@ -42,8 +43,7 @@ func TestAcc_Databases_Complete(t *testing.T) {
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.kind", "STANDARD"),
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.transient", "false"),
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.is_default", "false"),
// Commenting as this value depends on the currently used database, which is different when running as a single test and multiple tests (e.g., on CI)
// resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.is_current", "true"),
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.is_current", "true"),
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.origin", ""),
resource.TestCheckResourceAttrSet("data.snowflake_databases.test", "databases.0.show_output.0.owner"),
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.comment", comment),
Expand Down Expand Up @@ -85,8 +85,7 @@ func TestAcc_Databases_Complete(t *testing.T) {
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.kind", "STANDARD"),
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.transient", "false"),
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.is_default", "false"),
// Commenting for the same reason as above
// resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.is_current", "false"),
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.is_current", "true"),
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.origin", ""),
resource.TestCheckResourceAttrSet("data.snowflake_databases.test", "databases.0.show_output.0.owner"),
resource.TestCheckResourceAttr("data.snowflake_databases.test", "databases.0.show_output.0.comment", comment),
Expand All @@ -104,7 +103,7 @@ func TestAcc_Databases_Complete(t *testing.T) {
}

func TestAcc_Databases_DifferentFiltering(t *testing.T) {
prefix := random.String()
prefix := random.AlphaN(4)
idOne := acc.TestClient().Ids.RandomAccountObjectIdentifierWithPrefix(prefix)
idTwo := acc.TestClient().Ids.RandomAccountObjectIdentifierWithPrefix(prefix)
idThree := acc.TestClient().Ids.RandomAccountObjectIdentifier()
Expand Down
Loading

0 comments on commit 873a1ed

Please sign in to comment.