-
Notifications
You must be signed in to change notification settings - Fork 427
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add unsafe_execute resource (#2225)
* add unsafe exec resource * Rename resource and make the basic tests pass * Simplify tests setup * Rename resource args * Fix checking db existence * Add random part to id * Rename migration * Remove unnecessary config param * Remove duplicated checks * Extract function to generate capitalized name * Test escaped identifier * Test unsafe execute with grants * Add TODO * Add test with HCL for_each * Fix before pushing * Update docs with warning * Update example usage in docs * Add negative tests * Add read (WIP) * Pass test without query * Add test for query removed * Move unsafe client and implementation to SDK * Fix query unsafe * Update docs and change query behavior * Update docs * Update logs * Fix test --------- Co-authored-by: Jan Cieślak <jan.cieslak@snowflake.com>
- Loading branch information
1 parent
c60db80
commit 196134c
Showing
15 changed files
with
1,349 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
--- | ||
# generated by https://github.com/hashicorp/terraform-plugin-docs | ||
page_title: "snowflake_unsafe_execute Resource - terraform-provider-snowflake" | ||
subcategory: "" | ||
description: |- | ||
Experimental resource used for testing purposes only. Allows to execute ANY SQL statement. | ||
--- | ||
|
||
# snowflake_unsafe_execute (Resource) | ||
|
||
!> **Warning** This is a dangerous resource that allows executing **ANY** SQL statement. It may destroy resources if used incorrectly. It may behave incorrectly combined with other resources. Will be deleted in the upcoming versions. Use at your own risk. | ||
|
||
~> **Note** It can be theoretically used to manage resource that are not supported by the provider. This is risky and may brake other resources if used incorrectly. | ||
|
||
~> **Note** Use `query` parameter with caution. It will fetch **ALL** the results returned by the query provided. Try to limit the number of results by writing query with filters. Query failure does not stop resource creation; it simply results in `query_results` being empty. | ||
|
||
Experimental resource used for testing purposes only. Allows to execute ANY SQL statement. | ||
|
||
## Example Usage | ||
|
||
```terraform | ||
################################## | ||
### simple use cases | ||
################################## | ||
# create and destroy resource | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
} | ||
# create and destroy resource using qualified name | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE \"abc\"" | ||
revert = "DROP DATABASE \"abc\"" | ||
} | ||
# with query | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
query = "SHOW DATABASES LIKE '%ABC%'" | ||
} | ||
################################## | ||
### grants example | ||
################################## | ||
# grant and revoke privilege USAGE to ROLE on database | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "GRANT USAGE ON DATABASE ABC TO ROLE XYZ" | ||
revert = "REVOKE USAGE ON DATABASE ABC FROM ROLE XYZ" | ||
} | ||
# grant and revoke with for_each | ||
variable "database_grants" { | ||
type = list(object({ | ||
database_name = string | ||
role_id = string | ||
privileges = list(string) | ||
})) | ||
} | ||
resource "snowflake_unsafe_execute" "test" { | ||
for_each = { for index, db_grant in var.database_grants : index => db_grant } | ||
execute = "GRANT ${join(",", each.value.privileges)} ON DATABASE ${each.value.database_name} TO ROLE ${each.value.role_id}" | ||
revert = "REVOKE ${join(",", each.value.privileges)} ON DATABASE ${each.value.database_name} FROM ROLE ${each.value.role_id}" | ||
} | ||
################################## | ||
### fixing bad configuration | ||
################################## | ||
# bad revert - simple | ||
# 1 - resource created with a bad revert; it is constructed, revert is not validated before destroy happens | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "SELECT 1" | ||
} | ||
# 2 - fix the revert first; resource won't be recreated | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
} | ||
# bad revert - complex (we assume that the problem is spotted after trying to change the execute) | ||
# 1 - resource created with a bad revert; it is constructed, revert is not validated before destroy happens | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "SELECT 1" | ||
} | ||
# 2 - try to create different database; it will fail on bad destroy | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE XYZ" | ||
revert = "SELECT 1" | ||
} | ||
# 3 - fix the revert first | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
} | ||
# 4 - create different database updating revert also | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE XYZ" | ||
revert = "DROP DATABASE XYZ" | ||
} | ||
# bad query | ||
# 1 - resource will be created; query_results will be empty | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
query = "bad query" | ||
} | ||
# 2 - fix the query; query_results will be calculated; resource won't be recreated | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
query = "SHOW DATABASES LIKE '%ABC%'" | ||
} | ||
``` | ||
|
||
<!-- schema generated by tfplugindocs --> | ||
## Schema | ||
|
||
### Required | ||
|
||
- `execute` (String) SQL statement to execute. Forces recreation of resource on change. | ||
- `revert` (String) SQL statement to revert the execute statement. Invoked when resource is being destroyed. | ||
|
||
### Optional | ||
|
||
- `query` (String) Optional SQL statement to do a read. Invoked after creation and every time it is changed. | ||
|
||
### Read-Only | ||
|
||
- `id` (String) The ID of this resource. | ||
- `query_results` (List of Map of String) List of key-value maps (text to text) retrieved after executing read query. Will be empty if the query results in an error. |
104 changes: 104 additions & 0 deletions
104
examples/resources/snowflake_unsafe_execute/resource.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
################################## | ||
### simple use cases | ||
################################## | ||
|
||
# create and destroy resource | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
} | ||
|
||
# create and destroy resource using qualified name | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE \"abc\"" | ||
revert = "DROP DATABASE \"abc\"" | ||
} | ||
|
||
# with query | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
query = "SHOW DATABASES LIKE '%ABC%'" | ||
} | ||
|
||
################################## | ||
### grants example | ||
################################## | ||
|
||
# grant and revoke privilege USAGE to ROLE on database | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "GRANT USAGE ON DATABASE ABC TO ROLE XYZ" | ||
revert = "REVOKE USAGE ON DATABASE ABC FROM ROLE XYZ" | ||
} | ||
|
||
# grant and revoke with for_each | ||
variable "database_grants" { | ||
type = list(object({ | ||
database_name = string | ||
role_id = string | ||
privileges = list(string) | ||
})) | ||
} | ||
|
||
resource "snowflake_unsafe_execute" "test" { | ||
for_each = { for index, db_grant in var.database_grants : index => db_grant } | ||
execute = "GRANT ${join(",", each.value.privileges)} ON DATABASE ${each.value.database_name} TO ROLE ${each.value.role_id}" | ||
revert = "REVOKE ${join(",", each.value.privileges)} ON DATABASE ${each.value.database_name} FROM ROLE ${each.value.role_id}" | ||
} | ||
|
||
################################## | ||
### fixing bad configuration | ||
################################## | ||
|
||
# bad revert - simple | ||
# 1 - resource created with a bad revert; it is constructed, revert is not validated before destroy happens | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "SELECT 1" | ||
} | ||
|
||
# 2 - fix the revert first; resource won't be recreated | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
} | ||
|
||
# bad revert - complex (we assume that the problem is spotted after trying to change the execute) | ||
# 1 - resource created with a bad revert; it is constructed, revert is not validated before destroy happens | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "SELECT 1" | ||
} | ||
|
||
# 2 - try to create different database; it will fail on bad destroy | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE XYZ" | ||
revert = "SELECT 1" | ||
} | ||
|
||
# 3 - fix the revert first | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
} | ||
|
||
# 4 - create different database updating revert also | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE XYZ" | ||
revert = "DROP DATABASE XYZ" | ||
} | ||
|
||
# bad query | ||
# 1 - resource will be created; query_results will be empty | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
query = "bad query" | ||
} | ||
|
||
# 2 - fix the query; query_results will be calculated; resource won't be recreated | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = "CREATE DATABASE ABC" | ||
revert = "DROP DATABASE ABC" | ||
query = "SHOW DATABASES LIKE '%ABC%'" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 4 additions & 0 deletions
4
pkg/resources/testdata/TestAcc_UnsafeExecute_commonSetup/test.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = var.execute | ||
revert = var.revert | ||
} |
7 changes: 7 additions & 0 deletions
7
pkg/resources/testdata/TestAcc_UnsafeExecute_commonSetup/variables.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
variable "execute" { | ||
type = string | ||
} | ||
|
||
variable "revert" { | ||
type = string | ||
} |
5 changes: 5 additions & 0 deletions
5
pkg/resources/testdata/TestAcc_UnsafeExecute_grantsComplex/test.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
resource "snowflake_unsafe_execute" "test" { | ||
for_each = { for index, db_grant in var.database_grants : index => db_grant } | ||
execute = "GRANT ${join(",", each.value.privileges)} ON DATABASE ${each.value.database_name} TO ROLE ${each.value.role_id}" | ||
revert = "REVOKE ${join(",", each.value.privileges)} ON DATABASE ${each.value.database_name} FROM ROLE ${each.value.role_id}" | ||
} |
7 changes: 7 additions & 0 deletions
7
pkg/resources/testdata/TestAcc_UnsafeExecute_grantsComplex/variables.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
variable "database_grants" { | ||
type = list(object({ | ||
database_name = string | ||
role_id = string | ||
privileges = list(string) | ||
})) | ||
} |
5 changes: 5 additions & 0 deletions
5
pkg/resources/testdata/TestAcc_UnsafeExecute_withRead/test.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
resource "snowflake_unsafe_execute" "test" { | ||
execute = var.execute | ||
revert = var.revert | ||
query = var.query | ||
} |
11 changes: 11 additions & 0 deletions
11
pkg/resources/testdata/TestAcc_UnsafeExecute_withRead/variables.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
variable "execute" { | ||
type = string | ||
} | ||
|
||
variable "revert" { | ||
type = string | ||
} | ||
|
||
variable "query" { | ||
type = string | ||
} |
Oops, something went wrong.