From 24f01bca0328fdccde1d97651a21c9bf514eaec8 Mon Sep 17 00:00:00 2001 From: Jakub Michalak Date: Thu, 12 Dec 2024 21:20:31 +0100 Subject: [PATCH] chore: Remove remaining deprecated features (#3268) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - remove remaining deprecated resources, data sources, and fields - update the docs with new examples and references - update the provider version in `tracking` package - minor updates in the docs - update lists in `v1-preparations` directory ## Test Plan * [ ] acceptance tests * [ ] … ## References --------- Co-authored-by: snowflake-release-please[bot] <105954990+snowflake-release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 46 + CREATING_ISSUES.md | 6 +- MIGRATION_GUIDE.md | 77 +- docs/data-sources/accounts.md | 2 - docs/data-sources/roles.md | 104 --- docs/guides/identifiers.md | 2 +- docs/index.md | 10 +- docs/resources/function.md | 140 --- docs/resources/procedure.md | 101 --- docs/resources/tag_association.md | 1 - docs/resources/unsafe_execute.md | 147 ---- examples/additional/deprecated_datasources.MD | 3 +- examples/additional/deprecated_resources.MD | 5 +- .../snowflake_roles/data-source.tf | 48 -- .../resources/snowflake_function/import.sh | 2 - .../resources/snowflake_function/resource.tf | 73 -- .../resources/snowflake_procedure/import.sh | 2 - .../resources/snowflake_procedure/resource.tf | 34 - .../snowflake_unsafe_execute/resource.tf | 104 --- pkg/acceptance/check_destroy.go | 12 +- pkg/datasources/roles.go | 101 --- pkg/datasources/roles_acceptance_test.go | 107 --- .../TestAcc_Procedures/complete/test.tf | 8 +- .../testdata/TestAcc_Roles_Complete/1/test.tf | 23 - .../TestAcc_Roles_Complete/1/variables.tf | 19 - .../testdata/TestAcc_Roles_Complete/2/test.tf | 3 - pkg/internal/tracking/context.go | 2 +- pkg/provider/datasources/datasources.go | 2 - pkg/provider/provider.go | 6 +- pkg/provider/resources/resources.go | 3 - pkg/resources/execute.go | 2 +- pkg/resources/function.go | 790 ----------------- pkg/resources/function_acceptance_test.go | 451 ---------- pkg/resources/function_state_upgraders.go | 63 -- pkg/resources/procedure.go | 804 ------------------ pkg/resources/procedure_acceptance_test.go | 583 ------------- pkg/resources/procedure_state_upgraders.go | 63 -- pkg/resources/tag_association.go | 7 - .../testdata/TestAcc_Function/complex/test.tf | 25 - .../TestAcc_Function/complex/variables.tf | 15 - .../testdata/TestAcc_Function/java/test.tf | 22 - .../TestAcc_Function/java/variables.tf | 15 - .../TestAcc_Function/javascript/test.tf | 25 - .../TestAcc_Function/javascript/variables.tf | 15 - .../testdata/TestAcc_Function/python/test.tf | 20 - .../TestAcc_Function/python/variables.tf | 15 - .../testdata/TestAcc_Function/scala/test.tf | 23 - .../TestAcc_Function/scala/variables.tf | 15 - .../testdata/TestAcc_Function/sql/test.tf | 17 - .../TestAcc_Function/sql/variables.tf | 15 - .../OnObject_Procedure_ToAccountRole/test.tf | 5 +- .../OnObject_Procedure_ToDatabaseRole/test.tf | 7 +- .../TestAcc_Procedure/complex/test.tf | 22 - .../TestAcc_Procedure/complex/variables.tf | 19 - .../testdata/TestAcc_Procedure/java/test.tf | 30 - .../TestAcc_Procedure/java/variables.tf | 19 - .../TestAcc_Procedure/javascript/test.tf | 12 - .../TestAcc_Procedure/javascript/variables.tf | 19 - .../testdata/TestAcc_Procedure/python/test.tf | 26 - .../TestAcc_Procedure/python/variables.tf | 19 - .../testdata/TestAcc_Procedure/scala/test.tf | 31 - .../TestAcc_Procedure/scala/variables.tf | 19 - .../testdata/TestAcc_Procedure/sql/test.tf | 19 - .../TestAcc_Procedure/sql/variables.tf | 19 - pkg/resources/unsafe_execute.go | 12 - .../{roles.md.tmpl => accounts.md.tmpl} | 3 - templates/guides/identifiers.md.tmpl | 2 +- templates/resources/unsafe_execute.md.tmpl | 40 - v1-preparations/GENERAL_TOPICS.md | 2 +- .../LIST_OF_PREVIEW_FEATURES_FOR_V1.md | 126 +-- .../LIST_OF_REMOVED_RESOURCES_FOR_V1.md | 10 +- .../LIST_OF_STABLE_RESOURCES_FOR_V1.md | 154 ++-- 72 files changed, 249 insertions(+), 4544 deletions(-) delete mode 100644 docs/data-sources/roles.md delete mode 100644 docs/resources/function.md delete mode 100644 docs/resources/procedure.md delete mode 100644 docs/resources/unsafe_execute.md delete mode 100644 examples/data-sources/snowflake_roles/data-source.tf delete mode 100644 examples/resources/snowflake_function/import.sh delete mode 100644 examples/resources/snowflake_function/resource.tf delete mode 100644 examples/resources/snowflake_procedure/import.sh delete mode 100644 examples/resources/snowflake_procedure/resource.tf delete mode 100644 examples/resources/snowflake_unsafe_execute/resource.tf delete mode 100644 pkg/datasources/roles.go delete mode 100644 pkg/datasources/roles_acceptance_test.go delete mode 100644 pkg/datasources/testdata/TestAcc_Roles_Complete/1/test.tf delete mode 100644 pkg/datasources/testdata/TestAcc_Roles_Complete/1/variables.tf delete mode 100644 pkg/datasources/testdata/TestAcc_Roles_Complete/2/test.tf delete mode 100644 pkg/resources/function.go delete mode 100644 pkg/resources/function_acceptance_test.go delete mode 100644 pkg/resources/function_state_upgraders.go delete mode 100644 pkg/resources/procedure.go delete mode 100644 pkg/resources/procedure_acceptance_test.go delete mode 100644 pkg/resources/procedure_state_upgraders.go delete mode 100644 pkg/resources/testdata/TestAcc_Function/complex/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Function/complex/variables.tf delete mode 100644 pkg/resources/testdata/TestAcc_Function/java/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Function/java/variables.tf delete mode 100644 pkg/resources/testdata/TestAcc_Function/javascript/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Function/javascript/variables.tf delete mode 100644 pkg/resources/testdata/TestAcc_Function/python/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Function/python/variables.tf delete mode 100644 pkg/resources/testdata/TestAcc_Function/scala/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Function/scala/variables.tf delete mode 100644 pkg/resources/testdata/TestAcc_Function/sql/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Function/sql/variables.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/complex/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/complex/variables.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/java/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/java/variables.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/javascript/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/javascript/variables.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/python/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/python/variables.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/scala/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/scala/variables.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/sql/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Procedure/sql/variables.tf delete mode 100644 pkg/resources/unsafe_execute.go rename templates/data-sources/{roles.md.tmpl => accounts.md.tmpl} (78%) delete mode 100644 templates/resources/unsafe_execute.md.tmpl diff --git a/CHANGELOG.md b/CHANGELOG.md index 233351f618..ae66222e55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,51 @@ # Changelog +## [0.100.0](https://github.com/Snowflake-Labs/terraform-provider-snowflake/compare/v0.99.0...v0.100.0) (2024-12-12) + + +### 🎉 **What's new:** + +* Account v1 readiness ([#3236](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3236)) ([5df33a8](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/5df33a8c1abe38c29124bac1e03727202c556347)) +* Account v1 readiness generated files ([#3242](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3242)) ([3df59dd](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/3df59dd51b53acae9155b732811cfda56d7f20b8)) +* Account v1 readiness resource ([#3252](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3252)) ([8f5698d](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/8f5698dbce3325461d572c4029ef2dbc364e819b)) +* Add a new account roles data source ([#3257](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3257)) ([b3d6b9e](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/b3d6b9e5b4f327b186161f50dc9ac732d199fb19)) +* Add account data source ([#3261](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3261)) ([6087fc9](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/6087fc9fdb2467e022ec7489137e7f5a5fe1ff25)) +* Add all other functions and procedures implementations ([#3275](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3275)) ([7a6f68d](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/7a6f68df2fb0a0a4696a5442569344039a839c27)) +* Basic functions implementation ([#3269](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3269)) ([6d4a103](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/6d4a10364276e92fa791eaa022c3bd7bce16228d)) +* Basic procedures implementation ([#3271](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3271)) ([933335f](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/933335f56d1e53bf3e95d1f552672f35425b4878)) +* Docs, test, and missing parameter ([#3280](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3280)) ([10517f3](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/10517f337c6b22d5f7f2a4f6c747b6fd2d2f47e9)) +* Functions and procedures schemas and generated sources ([#3262](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3262)) ([9b70f87](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/9b70f872ca799126bc2051b4ed70160f868ac267)) +* Functions sdk update ([#3254](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3254)) ([fc1eace](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/fc1eace306e8d919c3349d56480fa3386ca664af)) +* Handle missing fields in function and procedure ([#3273](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3273)) ([53e7a0a](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/53e7a0aea3350e9e03a804d67e7df796f15bff3a)) +* Procedures schemas and generated sources ([#3263](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3263)) ([211ad46](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/211ad46223f1bdf03b20cc7a06110bfce18a967e)) +* Procedures sdk update ([#3255](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3255)) ([682606a](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/682606adea5e40befa7e599ced5aa7dc8570f80a)) +* Rework account parameter resource ([#3264](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3264)) ([15aa9c2](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/15aa9c2c94d80ae1d299a333b8035e38de6a6dfc)) +* Rework data types ([#3244](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3244)) ([05ada91](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/05ada917414ea7c574be3974c7de4f09535961fd)) +* support table data type ([#3274](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3274)) ([13401d5](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/13401d5fff320eedcf40eed7c0831154cc6cc13a)) +* Tag association v1 readiness ([#3210](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3210)) ([04f6d54](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/04f6d54a83cf4e9ea4b292087eefa056114eb5b5)) +* Test imports and small fixes ([#3276](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3276)) ([a712195](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/a7121952892847f61e24e7a7a4fe78c38a450985)) +* Unsafe execute v1 readiness ([#3266](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3266)) ([c4f1e8f](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/c4f1e8fd55150e40d8a556580016ff83fe65bdaf)) +* Use new data types in sql builder for functions and procedures ([#3247](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3247)) ([69f677a](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/69f677a6f86faa79cdece4d422eb61284c1599a6)) + + +### 🔧 **Misc** + +* Add ShowByID filtering generation ([#3227](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3227)) ([548ec42](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/548ec42ae7bcb8daa038de4cb2f81ced9c028f2d)) +* Adress small task-related todos ([#3243](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3243)) ([40de9ae](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/40de9ae93796afbc3091aa2fbb2c5dfba71f911c)) +* Apply masking ([#3234](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3234)) ([c209a8a](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/c209a8ae6c15fa9515e933d18add962070b60257)) +* fix missing references in toOpts and changes with newlines ([#3240](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3240)) ([246547f](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/246547f8eb13118a325881630f33433b3f5d8f0a)) +* function tests ([#3279](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3279)) ([5af6efb](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/5af6efb08c479edbaea54f87f79672c802edcc86)) +* Improve config builders ([#3207](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3207)) ([425787c](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/425787c5938e88895af1157f505889611bdef398)) +* Revert to proper env ([#3238](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3238)) ([5d4ed3b](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/5d4ed3bc233a77196f01351d9c972bb56730298e)) +* Use service user for ci ([#3228](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3228)) ([2fb50d7](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/2fb50d7b5beb1f361d3c761b344bab3216f6ea59)) + + +### 🐛 **Bug fixes:** + +* Make blocked_roles_field optional in OAuth security integrations ([#3267](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3267)) ([7197b57](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/7197b57c5dd75be34fc77eb82aabbd091074b809)) +* Minor fixes ([#3231](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3231)) ([1863bf6](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/1863bf697f05177f27c351c0687c4bee24fe2c1b)) +* Minor fixes 2 ([#3230](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/3230)) ([73b7e74](https://github.com/Snowflake-Labs/terraform-provider-snowflake/commit/73b7e74bf44b1ae6ddc78cac752f2b7febb836cd)) + ## [0.99.0](https://github.com/Snowflake-Labs/terraform-provider-snowflake/compare/v0.98.0...v0.99.0) (2024-11-26) diff --git a/CREATING_ISSUES.md b/CREATING_ISSUES.md index 87d00a1a92..274d61662c 100644 --- a/CREATING_ISSUES.md +++ b/CREATING_ISSUES.md @@ -181,7 +181,7 @@ resource "snowflake_grant_privileges_to_account_role" "grant_on_procedure" { account_role_name = snowflake_account_role.name on_schema_object { object_type = "PROCEDURE" - object_name = "\"${snowflake_database.database.name}\".\"${snowflake_schema.schema.name}\".\"${snowflake_procedure.procedure.name}\"" + object_name = "\"${snowflake_database.database.name}\".\"${snowflake_schema.schema.name}\".\"${snowflake_procedure_sql.procedure.name}\"" } } ``` @@ -202,7 +202,7 @@ resource "snowflake_grant_privileges_to_account_role" "grant_on_procedure" { account_role_name = snowflake_account_role.name on_schema_object { object_type = "PROCEDURE" - object_name = "\"${snowflake_database.database.name}\".\"${snowflake_schema.schema.name}\".\"${snowflake_procedure.procedure.name}\"(NUMBER, VARCHAR)" + object_name = "\"${snowflake_database.database.name}\".\"${snowflake_schema.schema.name}\".\"${snowflake_procedure_sql.procedure.name}\"(NUMBER, VARCHAR)" } } ``` @@ -215,7 +215,7 @@ resource "snowflake_grant_privileges_to_account_role" "grant_on_procedure" { account_role_name = snowflake_account_role.name on_schema_object { object_type = "PROCEDURE" - object_name = snowflake_procedure.procedure_name.fully_qualified_name + object_name = snowflake_procedure_sql.procedure_name.fully_qualified_name } } ``` diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 1973ca9ac3..3ecf522a66 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -7,7 +7,7 @@ across different versions. > [!TIP] > We highly recommend upgrading the versions one by one instead of bulk upgrades. -## v0.99.0 ➞ v1.0.0 +## v0.100.0 ➞ v1.0.0 ### Preview features flag All of the preview features objects are now disabled by default. This includes: @@ -72,34 +72,39 @@ provider "snowflake" { ### Removed deprecated objects All of the deprecated objects are removed from v1 release. This includes: - - Resources - - `snowflake_database_old` - - `snowflake_role` - - `snowflake_oauth_integration` - - `snowflake_saml_integration` + - `snowflake_database_old` - see [migration guide](#new-feature-new-database-resources) + - `snowflake_role` - see [migration guide](#new-feature-new-snowflake_account_role-resource) + - `snowflake_oauth_integration` - see [migration guide](#new-feature-snowflake_oauth_integration_for_custom_clients-and-snowflake_oauth_integration_for_partner_applications-resources) + - `snowflake_saml_integration` - see [migration guide](#new-feature-snowflake_saml2_integration-resource) - `snowflake_session_parameter` - - `snowflake_stream` - - `snowflake_tag_masking_policy_association` + - `snowflake_stream` - see [migration guide](#new-feature-snowflake_stream_on_directory_table-and-snowflake_stream_on_view-resource) + - `snowflake_tag_masking_policy_association` - see [migration guide](#snowflake_tag_masking_policy_association-deprecation) + - `snowflake_function` + - `snowflake_procedure` + - `snowflake_unsafe_execute` - see [migration guide](#unsafe_execute-resource-deprecation--new-execute-resource) - Data sources - - `snowflake_role` + - `snowflake_role` - see [migration guide](#snowflake_role-data-source-deprecation) + - `snowflake_roles` - see [migration guide](#new-feature-account-role-data-source) - Fields in the provider configuration: - - `account` - - `oauth_access_token` - - `oauth_client_id` - - `oauth_client_secret` - - `oauth_endpoint` - - `oauth_redirect_url` - - `oauth_refresh_token` - - `private_key_path` - - `region` - - `session_params` - - `username` + - `account` - see [migration guide](#behavior-change-deprecated-fields) + - OAuth related fields - see [migration guide](#structural-change-oauth-api): + - `oauth_access_token` + - `oauth_client_id` + - `oauth_client_secret` + - `oauth_endpoint` + - `oauth_redirect_url` + - `oauth_refresh_token` + - `browser_auth` + - `private_key_path` - see [migration guide](#private_key_path-deprecation) + - `region` - see [migration guide](#remove-redundant-information-region) + - `session_params` - see [migration guide](#rename-session_params--params) + - `username` - see [migration guide](#rename-username--user) +- Fields in `tag` resource: + - `object_name` Additionally, `JWT` value is no longer available for `authenticator` field in the provider configuration. - - ## v0.99.0 ➞ v0.100.0 ### *(preview feature/deprecation)* Function and procedure resources @@ -1389,21 +1394,6 @@ Changes: - `pattern` was renamed to `like` - output of SHOW is enclosed in `show_output`, so before, e.g. `roles.0.comment` is now `roles.0.show_output.0.comment` -### *(new feature)* new snowflake_account_role resource - -Already existing `snowflake_role` was deprecated in favor of the new `snowflake_account_role`. The old resource got upgraded to -have the same features as the new one. The only difference is the deprecation message on the old resource. - -New fields: -- added `show_output` field that holds the response from SHOW ROLES. Remember that the field will be only recomputed if one of the fields (`name` or `comment`) are changed. - -### *(breaking change)* refactored snowflake_roles data source - -Changes: -- New `in_class` filtering option to filter out roles by class name, e.g. `in_class = "SNOWFLAKE.CORE.BUDGET"` -- `pattern` was renamed to `like` -- output of SHOW is enclosed in `show_output`, so before, e.g. `roles.0.comment` is now `roles.0.show_output.0.comment` - ### *(new feature)* snowflake_streamlit resource Added a new resource for managing streamlits. See reference [docs](https://docs.snowflake.com/en/sql-reference/sql/create-streamlit). In this resource, we decided to split `ROOT_LOCATION` in Snowflake to two fields: `stage` representing stage fully qualified name and `directory_location` containing a path within this stage to root location. @@ -1759,6 +1749,11 @@ The `ForceNew` field was removed in favor of in-place Update for `name` paramete So from now, these objects won't be re-created when the `name` changes, but instead only the name will be updated with `ALTER .. RENAME TO` statements. ## v0.87.0 ➞ v0.88.0 + +### snowflake_role data source deprecation + +Already existing `snowflake_role` was deprecated in favor of the new `snowflake_roles`. You can have a similar behavior like before by specifying `pattern` field. Please adjust your Terraform configurations. + ### snowflake_procedure resource changes #### *(behavior change)* Execute as validation added From now on, the `snowflake_procedure`'s `execute_as` parameter allows only two values: OWNER and CALLER (case-insensitive). Setting other values earlier resulted in falling back to the Snowflake default (currently OWNER) and creating a permadiff. @@ -1961,7 +1956,7 @@ were already available in Golang Snowflake driver. This lead to several attribut We will focus on the deprecated ones and show you how to adapt your current configuration to the new changes. #### *(rename)* username ➞ user - +Provider field `username` were renamed to `user`. Adjust your provider configuration like below: ```terraform provider "snowflake" { # before @@ -1973,6 +1968,7 @@ provider "snowflake" { ``` #### *(structural change)* OAuth API +Provider fields regarding Oauth were renamed and nested. Adjust your provider configuration like below: ```terraform provider "snowflake" { @@ -2014,7 +2010,8 @@ provider "snowflake" { } ``` -#### *(todo)* private key path +#### private_key_path deprecation +Provider field `private_key_path` is now deprecated in favor of `private_key` and `file` Terraform function (see [docs](https://developer.hashicorp.com/terraform/language/functions/file)). Adjust your provider configuration like below: ```terraform provider "snowflake" { @@ -2027,7 +2024,7 @@ provider "snowflake" { ``` #### *(rename)* session_params ➞ params - +Provider field `session_params` were renamed to `params`. Adjust your provider configuration like below: ```terraform provider "snowflake" { # before diff --git a/docs/data-sources/accounts.md b/docs/data-sources/accounts.md index 9f19e5e9cb..f378741edd 100644 --- a/docs/data-sources/accounts.md +++ b/docs/data-sources/accounts.md @@ -5,8 +5,6 @@ description: |- Data source used to get details of filtered accounts. Filtering is aligned with the current possibilities for SHOW ACCOUNTS https://docs.snowflake.com/en/sql-reference/sql/show-accounts query. The results of SHOW are encapsulated in one output collection accounts. --- -!> **Caution: Preview Feature** This feature is considered a preview feature in the provider, regardless of the state of the resource in Snowflake. We do not guarantee its stability. It will be reworked and marked as a stable feature in future releases. Breaking changes are expected, even without bumping the major version. To use this feature, add the relevant feature name to `preview_features_enabled field` in the [provider configuration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs#schema). Please always refer to the [Getting Help](https://github.com/Snowflake-Labs/terraform-provider-snowflake?tab=readme-ov-file#getting-help) section in our Github repo to best determine how to get help for your questions. - # snowflake_accounts (Data Source) Data source used to get details of filtered accounts. Filtering is aligned with the current possibilities for [SHOW ACCOUNTS](https://docs.snowflake.com/en/sql-reference/sql/show-accounts) query. The results of SHOW are encapsulated in one output collection `accounts`. diff --git a/docs/data-sources/roles.md b/docs/data-sources/roles.md deleted file mode 100644 index 44d8615423..0000000000 --- a/docs/data-sources/roles.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -page_title: "snowflake_roles Data Source - terraform-provider-snowflake" -subcategory: "" -description: |- - Data source used to get details of filtered roles. Filtering is aligned with the current possibilities for SHOW ROLES https://docs.snowflake.com/en/sql-reference/sql/show-roles query (like and in_class are all supported). The results of SHOW are encapsulated in one output collection. ---- - - --> **Note** Fields `STARTS WITH` and `LIMIT` are currently missing. They will be added in the future. - -# snowflake_roles (Data Source) - -~> **Deprecation** This resource is deprecated and will be removed in a future major version release. Please use [snowflake_account_roles](./account_roles) instead. - -Data source used to get details of filtered roles. Filtering is aligned with the current possibilities for [SHOW ROLES](https://docs.snowflake.com/en/sql-reference/sql/show-roles) query (`like` and `in_class` are all supported). The results of SHOW are encapsulated in one output collection. - -## Example Usage - -```terraform -# Simple usage -data "snowflake_roles" "simple" { -} - -output "simple_output" { - value = data.snowflake_roles.simple.roles -} - -# Filtering (like) -data "snowflake_roles" "like" { - like = "role-name" -} - -output "like_output" { - value = data.snowflake_roles.like.roles -} - -# Filtering (in class) -data "snowflake_roles" "in_class" { - in_class = "SNOWFLAKE.CORE.BUDGET" -} - -output "in_class_output" { - value = data.snowflake_roles.in_class.roles -} - -# Ensure the number of roles is equal to at least one element (with the use of postcondition) -data "snowflake_roles" "assert_with_postcondition" { - like = "role-name-%" - lifecycle { - postcondition { - condition = length(self.roles) > 0 - error_message = "there should be at least one role" - } - } -} - -# Ensure the number of roles is equal to at exactly one element (with the use of check block) -check "role_check" { - data "snowflake_roles" "assert_with_check_block" { - like = "role-name" - } - - assert { - condition = length(data.snowflake_roles.assert_with_check_block.roles) == 1 - error_message = "Roles filtered by '${data.snowflake_roles.assert_with_check_block.like}' returned ${length(data.snowflake_roles.assert_with_check_block.roles)} roles where one was expected" - } -} -``` - - -## Schema - -### Optional - -- `in_class` (String) Filters the SHOW GRANTS output by class name. -- `like` (String) Filters the output with **case-insensitive** pattern, with support for SQL wildcard characters (`%` and `_`). - -### Read-Only - -- `id` (String) The ID of this resource. -- `roles` (List of Object) Holds the aggregated output of all role details queries. (see [below for nested schema](#nestedatt--roles)) - - -### Nested Schema for `roles` - -Read-Only: - -- `show_output` (List of Object) (see [below for nested schema](#nestedobjatt--roles--show_output)) - - -### Nested Schema for `roles.show_output` - -Read-Only: - -- `assigned_to_users` (Number) -- `comment` (String) -- `created_on` (String) -- `granted_roles` (Number) -- `granted_to_roles` (Number) -- `is_current` (Boolean) -- `is_default` (Boolean) -- `is_inherited` (Boolean) -- `name` (String) -- `owner` (String) diff --git a/docs/guides/identifiers.md b/docs/guides/identifiers.md index 0af6936acf..e8ddac899a 100644 --- a/docs/guides/identifiers.md +++ b/docs/guides/identifiers.md @@ -15,7 +15,7 @@ For example, instead of writing ``` object_name = “\”${snowflake_table.database}\”.\”${snowflake_table.schema}\”.\”${snowflake_table.name}\”” # for procedures -object_name = “\”${snowflake_procedure.database}\”.\”${snowflake_procedure.schema}\”.\”${snowflake_procedure.name}\"(NUMBER, VARCHAR)” +object_name = “\”${snowflake_procedure_sql.database}\”.\”${snowflake_procedure_sql.schema}\”.\”${snowflake_procedure_sql.name}\"(NUMBER, VARCHAR)” ``` now we can write diff --git a/docs/index.md b/docs/index.md index fad1f2be7d..b5d8c76acb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -95,7 +95,7 @@ provider "snowflake" { - `params` (Map of String) Sets other connection (i.e. session) parameters. [Parameters](https://docs.snowflake.com/en/sql-reference/parameters). This field can not be set with environmental variables. - `passcode` (String) Specifies the passcode provided by Duo when using multi-factor authentication (MFA) for login. Can also be sourced from the `SNOWFLAKE_PASSCODE` environment variable. - `passcode_in_password` (Boolean) False by default. Set to true if the MFA passcode is embedded to the configured password. Can also be sourced from the `SNOWFLAKE_PASSCODE_IN_PASSWORD` environment variable. -- `password` (String, Sensitive) Password for user + password auth. Cannot be used with `browser_auth` or `private_key_path`. Can also be sourced from the `SNOWFLAKE_PASSWORD` environment variable. +- `password` (String, Sensitive) Password for user + password auth. Cannot be used with `private_key` and `private_key_passphrase`. Can also be sourced from the `SNOWFLAKE_PASSWORD` environment variable. - `port` (Number) Specifies a custom port value used by the driver for privatelink connections. Can also be sourced from the `SNOWFLAKE_PORT` environment variable. - `preview_features_enabled` (Set of String) A list of preview features that are handled by the provider. See [preview features list](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/v1-preparations/LIST_OF_PREVIEW_FEATURES_FOR_V1.md). Preview features may have breaking changes in future releases, even without raising the major version. This field can not be set with environmental variables. Valid options are: `snowflake_current_account_datasource` | `snowflake_account_authentication_policy_attachment_resource` | `snowflake_account_password_policy_attachment_resource` | `snowflake_alert_resource` | `snowflake_alerts_datasource` | `snowflake_api_integration_resource` | `snowflake_authentication_policy_resource` | `snowflake_cortex_search_service_resource` | `snowflake_cortex_search_services_datasource` | `snowflake_database_datasource` | `snowflake_database_role_datasource` | `snowflake_dynamic_table_resource` | `snowflake_dynamic_tables_datasource` | `snowflake_external_function_resource` | `snowflake_external_functions_datasource` | `snowflake_external_table_resource` | `snowflake_external_tables_datasource` | `snowflake_external_volume_resource` | `snowflake_failover_group_resource` | `snowflake_failover_groups_datasource` | `snowflake_file_format_resource` | `snowflake_file_formats_datasource` | `snowflake_managed_account_resource` | `snowflake_materialized_view_resource` | `snowflake_materialized_views_datasource` | `snowflake_network_policy_attachment_resource` | `snowflake_network_rule_resource` | `snowflake_email_notification_integration_resource` | `snowflake_notification_integration_resource` | `snowflake_object_parameter_resource` | `snowflake_password_policy_resource` | `snowflake_pipe_resource` | `snowflake_pipes_datasource` | `snowflake_current_role_datasource` | `snowflake_sequence_resource` | `snowflake_sequences_datasource` | `snowflake_share_resource` | `snowflake_shares_datasource` | `snowflake_parameters_datasource` | `snowflake_stage_resource` | `snowflake_stages_datasource` | `snowflake_storage_integration_resource` | `snowflake_storage_integrations_datasource` | `snowflake_system_generate_scim_access_token_datasource` | `snowflake_system_get_aws_sns_iam_policy_datasource` | `snowflake_system_get_privatelink_config_datasource` | `snowflake_system_get_snowflake_platform_info_datasource` | `snowflake_table_column_masking_policy_application_resource` | `snowflake_table_constraint_resource` | `snowflake_user_authentication_policy_attachment_resource` | `snowflake_user_public_keys_resource` | `snowflake_user_password_policy_attachment_resource`. - `private_key` (String, Sensitive) Private Key for username+private-key auth. Cannot be used with `password`. Can also be sourced from the `SNOWFLAKE_PRIVATE_KEY` environment variable. @@ -349,13 +349,5 @@ provider "snowflake" { ``` - ## Currently deprecated resources - -- [snowflake_function](./docs/resources/function) -- [snowflake_procedure](./docs/resources/procedure) -- [snowflake_unsafe_execute](./docs/resources/unsafe_execute) - use [snowflake_execute](./docs/resources/execute) instead - ## Currently deprecated data sources - -- [snowflake_roles](./docs/data-sources/roles) - use [snowflake_account_roles](./docs/data-sources/account_roles) instead diff --git a/docs/resources/function.md b/docs/resources/function.md deleted file mode 100644 index 9511de1dce..0000000000 --- a/docs/resources/function.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -page_title: "snowflake_function Resource - terraform-provider-snowflake" -subcategory: "" -description: |- - ---- - -!> **Caution: Preview Feature** This feature is considered a preview feature in the provider, regardless of the state of the resource in Snowflake. We do not guarantee its stability. It will be reworked and marked as a stable feature in future releases. Breaking changes are expected, even without bumping the major version. To use this feature, add the relevant feature name to `preview_features_enabled field` in the [provider configuration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs#schema). Please always refer to the [Getting Help](https://github.com/Snowflake-Labs/terraform-provider-snowflake?tab=readme-ov-file#getting-help) section in our Github repo to best determine how to get help for your questions. - -# snowflake_function (Resource) - -~> **Deprecation** This resource is deprecated and will be removed in a future major version release. Please use snowflake_function_java, snowflake_function_javascript, snowflake_function_python, snowflake_function_scala, and snowflake_function_sql instead. - -## Example Usage - -```terraform -// Provider configuration -provider "snowflake" { - region = "REGION" // Default is "us-west-2" - username = "USERNAME" - account = "ACCOUNT" - password = "PASSWORD" - role = "MY_ROLE" - warehouse = "MY_WH" // Optional attribute, some resources (e.g. Python UDFs)' require a warehouse to create and can also be set optionally from the `SNOWFLAKE_WAREHOUSE` environment variable -} - -// Create database -resource "snowflake_database" "db" { - name = "MY_DB" - data_retention_days = 1 -} - -// Create schema -resource "snowflake_schema" "schema" { - database = snowflake_database.db.name - name = "MY_SCHEMA" - data_retention_days = 1 -} - -// Example for Java language -resource "snowflake_function" "test_funct_java" { - name = "my_java_func" - database = "MY_DB" - schema = "MY_SCHEMA" - arguments { - name = "arg1" - type = "number" - } - comment = "Example for java language" - return_type = "varchar" - language = "java" - handler = "CoolFunc.test" - statement = "class CoolFunc {public static String test(int n) {return \"hello!\";}}" -} - -// Example for Python language -resource "snowflake_function" "python_test" { - name = "MY_PYTHON_FUNC" - database = "MY_DB" - schema = "MY_SCHEMA" - arguments { - name = "arg1" - type = "number" - } - comment = "Example for Python language" - return_type = "NUMBER(38,0)" - null_input_behavior = "CALLED ON NULL INPUT" - return_behavior = "VOLATILE" - language = "python" - runtime_version = "3.8" - handler = "add_py" - statement = "def add_py(i): return i+1" -} - -// Example SQL language -resource "snowflake_function" "sql_test" { - name = "MY_SQL_FUNC" - database = "MY_DB" - schema = "MY_SCHEMA" - arguments { - name = "arg1" - type = "number" - } - comment = "Example for SQL language" - return_type = "NUMBER(38,0)" - null_input_behavior = "CALLED ON NULL INPUT" - return_behavior = "VOLATILE" - statement = "select arg1 + 1" -} -``` - --> **Note** Instead of using fully_qualified_name, you can reference objects managed outside Terraform by constructing a correct ID, consult [identifiers guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/identifiers#new-computed-fully-qualified-name-field-in-resources). - - - -## Schema - -### Required - -- `database` (String) The database in which to create the function. Don't use the | character. -- `name` (String) Specifies the identifier for the function; does not have to be unique for the schema in which the function is created. Don't use the | character. -- `return_type` (String) The return type of the function -- `schema` (String) The schema in which to create the function. Don't use the | character. -- `statement` (String) Specifies the javascript / java / scala / sql / python code used to create the function. - -### Optional - -- `arguments` (Block List) List of the arguments for the function (see [below for nested schema](#nestedblock--arguments)) -- `comment` (String) Specifies a comment for the function. -- `handler` (String) The handler method for Java / Python function. -- `imports` (List of String) Imports for Java / Python functions. For Java this a list of jar files, for Python this is a list of Python files. -- `is_secure` (Boolean) Specifies that the function is secure. -- `language` (String) Specifies the language of the stored function code. -- `null_input_behavior` (String) Specifies the behavior of the function when called with null inputs. -- `packages` (List of String) List of package imports to use for Java / Python functions. For Java, package imports should be of the form: package_name:version_number, where package_name is snowflake_domain:package. For Python use it should be: ('numpy','pandas','xgboost==1.5.0'). -- `return_behavior` (String) Specifies the behavior of the function when returning results -- `runtime_version` (String) Required for Python functions. Specifies Python runtime version. -- `target_path` (String) The target path for the Java / Python functions. For Java, it is the path of compiled jar files and for the Python it is the path of the Python files. - -### Read-Only - -- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution). -- `id` (String) The ID of this resource. - - -### Nested Schema for `arguments` - -Required: - -- `name` (String) The argument name -- `type` (String) The argument type - -## Import - -Import is supported using the following syntax: - -```shell -# format is ..() -terraform import snowflake_function.example 'dbName.schemaName.functionName(varchar, varchar, varchar)' -``` diff --git a/docs/resources/procedure.md b/docs/resources/procedure.md deleted file mode 100644 index 3f85c71c33..0000000000 --- a/docs/resources/procedure.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -page_title: "snowflake_procedure Resource - terraform-provider-snowflake" -subcategory: "" -description: |- - ---- - -!> **Caution: Preview Feature** This feature is considered a preview feature in the provider, regardless of the state of the resource in Snowflake. We do not guarantee its stability. It will be reworked and marked as a stable feature in future releases. Breaking changes are expected, even without bumping the major version. To use this feature, add the relevant feature name to `preview_features_enabled field` in the [provider configuration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs#schema). Please always refer to the [Getting Help](https://github.com/Snowflake-Labs/terraform-provider-snowflake?tab=readme-ov-file#getting-help) section in our Github repo to best determine how to get help for your questions. - -# snowflake_procedure (Resource) - -~> **Deprecation** This resource is deprecated and will be removed in a future major version release. Please use snowflake_procedure_java, snowflake_procedure_javascript, snowflake_procedure_python, snowflake_procedure_scala, and snowflake_procedure_sql instead. - -## Example Usage - -```terraform -resource "snowflake_database" "db" { - name = "MYDB" - data_retention_days = 1 -} - -resource "snowflake_schema" "schema" { - database = snowflake_database.db.name - name = "MYSCHEMA" - data_retention_days = 1 -} - -resource "snowflake_procedure" "proc" { - name = "SAMPLEPROC" - database = snowflake_database.db.name - schema = snowflake_schema.schema.name - language = "JAVASCRIPT" - arguments { - name = "arg1" - type = "varchar" - } - arguments { - name = "arg2" - type = "DATE" - } - comment = "Procedure with 2 arguments" - return_type = "VARCHAR" - execute_as = "CALLER" - return_behavior = "IMMUTABLE" - null_input_behavior = "RETURNS NULL ON NULL INPUT" - statement = < **Note** Instead of using fully_qualified_name, you can reference objects managed outside Terraform by constructing a correct ID, consult [identifiers guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/identifiers#new-computed-fully-qualified-name-field-in-resources). - - - -## Schema - -### Required - -- `database` (String) The database in which to create the procedure. Don't use the | character. -- `name` (String) Specifies the identifier for the procedure; does not have to be unique for the schema in which the procedure is created. Don't use the | character. -- `return_type` (String) The return type of the procedure -- `schema` (String) The schema in which to create the procedure. Don't use the | character. -- `statement` (String) Specifies the code used to create the procedure. - -### Optional - -- `arguments` (Block List) List of the arguments for the procedure (see [below for nested schema](#nestedblock--arguments)) -- `comment` (String) Specifies a comment for the procedure. -- `execute_as` (String) Sets execution context. Allowed values are CALLER and OWNER (consult a proper section in the [docs](https://docs.snowflake.com/en/sql-reference/sql/create-procedure#id1)). For more information see [caller's rights and owner's rights](https://docs.snowflake.com/en/developer-guide/stored-procedure/stored-procedures-rights). -- `handler` (String) The handler method for Java / Python procedures. -- `imports` (List of String) Imports for Java / Python procedures. For Java this a list of jar files, for Python this is a list of Python files. -- `language` (String) Specifies the language of the stored procedure code. -- `null_input_behavior` (String) Specifies the behavior of the procedure when called with null inputs. -- `packages` (List of String) List of package imports to use for Java / Python procedures. For Java, package imports should be of the form: package_name:version_number, where package_name is snowflake_domain:package. For Python use it should be: ('numpy','pandas','xgboost==1.5.0'). -- `return_behavior` (String, Deprecated) Specifies the behavior of the function when returning results -- `runtime_version` (String) Required for Python procedures. Specifies Python runtime version. -- `secure` (Boolean) Specifies that the procedure is secure. For more information about secure procedures, see Protecting Sensitive Information with Secure UDFs and Stored Procedures. - -### Read-Only - -- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution). -- `id` (String) The ID of this resource. - - -### Nested Schema for `arguments` - -Required: - -- `name` (String) The argument name -- `type` (String) The argument type - -## Import - -Import is supported using the following syntax: - -```shell -# format is ..() -terraform import snowflake_procedure.example 'dbName.schemaName.procedureName(varchar, varchar, varchar)' -``` diff --git a/docs/resources/tag_association.md b/docs/resources/tag_association.md index 35b0d44db6..05a3b9b045 100644 --- a/docs/resources/tag_association.md +++ b/docs/resources/tag_association.md @@ -92,7 +92,6 @@ resource "snowflake_tag_association" "account_association" { ### Optional -- `object_name` (String, Deprecated) Specifies the object identifier for the tag association. - `skip_validation` (Boolean) If true, skips validation of the tag association. - `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) diff --git a/docs/resources/unsafe_execute.md b/docs/resources/unsafe_execute.md deleted file mode 100644 index 3ac9e7c7b6..0000000000 --- a/docs/resources/unsafe_execute.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "snowflake_unsafe_execute Resource - terraform-provider-snowflake" -subcategory: "" -description: |- - Experimental resource allowing execution of ANY SQL statement. It may destroy resources if used incorrectly. It may behave incorrectly combined with other resources. Use at your own risk. ---- - -# 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. 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. - -~> **Deprecation** This resource is deprecated and will be removed in a future major version release. Please use [snowflake_execute](./execute) instead. - -Experimental resource allowing execution of ANY SQL statement. It may destroy resources if used incorrectly. It may behave incorrectly combined with other resources. Use at your own risk. - -## 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%'" -} -``` --> **Note** Instead of using fully_qualified_name, you can reference objects managed outside Terraform by constructing a correct ID, consult [identifiers guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/identifiers#new-computed-fully-qualified-name-field-in-resources). - - - -## 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 on every resource refresh 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. diff --git a/examples/additional/deprecated_datasources.MD b/examples/additional/deprecated_datasources.MD index 6e29a34e49..393ab71209 100644 --- a/examples/additional/deprecated_datasources.MD +++ b/examples/additional/deprecated_datasources.MD @@ -1,4 +1,3 @@ - ## Currently deprecated data sources -- [snowflake_roles](./docs/data-sources/roles) - use [snowflake_account_roles](./docs/data-sources/account_roles) instead + diff --git a/examples/additional/deprecated_resources.MD b/examples/additional/deprecated_resources.MD index 78735c7f69..3b52465691 100644 --- a/examples/additional/deprecated_resources.MD +++ b/examples/additional/deprecated_resources.MD @@ -1,6 +1,3 @@ - ## Currently deprecated resources -- [snowflake_function](./docs/resources/function) -- [snowflake_procedure](./docs/resources/procedure) -- [snowflake_unsafe_execute](./docs/resources/unsafe_execute) - use [snowflake_execute](./docs/resources/execute) instead + diff --git a/examples/data-sources/snowflake_roles/data-source.tf b/examples/data-sources/snowflake_roles/data-source.tf deleted file mode 100644 index 24ed09708b..0000000000 --- a/examples/data-sources/snowflake_roles/data-source.tf +++ /dev/null @@ -1,48 +0,0 @@ -# Simple usage -data "snowflake_roles" "simple" { -} - -output "simple_output" { - value = data.snowflake_roles.simple.roles -} - -# Filtering (like) -data "snowflake_roles" "like" { - like = "role-name" -} - -output "like_output" { - value = data.snowflake_roles.like.roles -} - -# Filtering (in class) -data "snowflake_roles" "in_class" { - in_class = "SNOWFLAKE.CORE.BUDGET" -} - -output "in_class_output" { - value = data.snowflake_roles.in_class.roles -} - -# Ensure the number of roles is equal to at least one element (with the use of postcondition) -data "snowflake_roles" "assert_with_postcondition" { - like = "role-name-%" - lifecycle { - postcondition { - condition = length(self.roles) > 0 - error_message = "there should be at least one role" - } - } -} - -# Ensure the number of roles is equal to at exactly one element (with the use of check block) -check "role_check" { - data "snowflake_roles" "assert_with_check_block" { - like = "role-name" - } - - assert { - condition = length(data.snowflake_roles.assert_with_check_block.roles) == 1 - error_message = "Roles filtered by '${data.snowflake_roles.assert_with_check_block.like}' returned ${length(data.snowflake_roles.assert_with_check_block.roles)} roles where one was expected" - } -} diff --git a/examples/resources/snowflake_function/import.sh b/examples/resources/snowflake_function/import.sh deleted file mode 100644 index 62c2ca5681..0000000000 --- a/examples/resources/snowflake_function/import.sh +++ /dev/null @@ -1,2 +0,0 @@ -# format is ..() -terraform import snowflake_function.example 'dbName.schemaName.functionName(varchar, varchar, varchar)' diff --git a/examples/resources/snowflake_function/resource.tf b/examples/resources/snowflake_function/resource.tf deleted file mode 100644 index 2e5c03a00f..0000000000 --- a/examples/resources/snowflake_function/resource.tf +++ /dev/null @@ -1,73 +0,0 @@ -// Provider configuration -provider "snowflake" { - region = "REGION" // Default is "us-west-2" - username = "USERNAME" - account = "ACCOUNT" - password = "PASSWORD" - role = "MY_ROLE" - warehouse = "MY_WH" // Optional attribute, some resources (e.g. Python UDFs)' require a warehouse to create and can also be set optionally from the `SNOWFLAKE_WAREHOUSE` environment variable -} - -// Create database -resource "snowflake_database" "db" { - name = "MY_DB" - data_retention_days = 1 -} - -// Create schema -resource "snowflake_schema" "schema" { - database = snowflake_database.db.name - name = "MY_SCHEMA" - data_retention_days = 1 -} - -// Example for Java language -resource "snowflake_function" "test_funct_java" { - name = "my_java_func" - database = "MY_DB" - schema = "MY_SCHEMA" - arguments { - name = "arg1" - type = "number" - } - comment = "Example for java language" - return_type = "varchar" - language = "java" - handler = "CoolFunc.test" - statement = "class CoolFunc {public static String test(int n) {return \"hello!\";}}" -} - -// Example for Python language -resource "snowflake_function" "python_test" { - name = "MY_PYTHON_FUNC" - database = "MY_DB" - schema = "MY_SCHEMA" - arguments { - name = "arg1" - type = "number" - } - comment = "Example for Python language" - return_type = "NUMBER(38,0)" - null_input_behavior = "CALLED ON NULL INPUT" - return_behavior = "VOLATILE" - language = "python" - runtime_version = "3.8" - handler = "add_py" - statement = "def add_py(i): return i+1" -} - -// Example SQL language -resource "snowflake_function" "sql_test" { - name = "MY_SQL_FUNC" - database = "MY_DB" - schema = "MY_SCHEMA" - arguments { - name = "arg1" - type = "number" - } - comment = "Example for SQL language" - return_type = "NUMBER(38,0)" - null_input_behavior = "CALLED ON NULL INPUT" - return_behavior = "VOLATILE" - statement = "select arg1 + 1" -} diff --git a/examples/resources/snowflake_procedure/import.sh b/examples/resources/snowflake_procedure/import.sh deleted file mode 100644 index 9ba6623768..0000000000 --- a/examples/resources/snowflake_procedure/import.sh +++ /dev/null @@ -1,2 +0,0 @@ -# format is ..() -terraform import snowflake_procedure.example 'dbName.schemaName.procedureName(varchar, varchar, varchar)' diff --git a/examples/resources/snowflake_procedure/resource.tf b/examples/resources/snowflake_procedure/resource.tf deleted file mode 100644 index 210a395897..0000000000 --- a/examples/resources/snowflake_procedure/resource.tf +++ /dev/null @@ -1,34 +0,0 @@ -resource "snowflake_database" "db" { - name = "MYDB" - data_retention_days = 1 -} - -resource "snowflake_schema" "schema" { - database = snowflake_database.db.name - name = "MYSCHEMA" - data_retention_days = 1 -} - -resource "snowflake_procedure" "proc" { - name = "SAMPLEPROC" - database = snowflake_database.db.name - schema = snowflake_schema.schema.name - language = "JAVASCRIPT" - arguments { - name = "arg1" - type = "varchar" - } - arguments { - name = "arg2" - type = "DATE" - } - comment = "Procedure with 2 arguments" - return_type = "VARCHAR" - execute_as = "CALLER" - return_behavior = "IMMUTABLE" - null_input_behavior = "RETURNS NULL ON NULL INPUT" - statement = < 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%'" -} diff --git a/pkg/acceptance/check_destroy.go b/pkg/acceptance/check_destroy.go index 0de18402be..a6b918224d 100644 --- a/pkg/acceptance/check_destroy.go +++ b/pkg/acceptance/check_destroy.go @@ -67,15 +67,13 @@ func decodeSnowflakeId(rs *terraform.ResourceState, resource resources.Resource) switch resource { case resources.ExternalFunction: return sdk.NewSchemaObjectIdentifierFromFullyQualifiedName(rs.Primary.ID), nil - case resources.Function, - resources.FunctionJava, + case resources.FunctionJava, resources.FunctionJavascript, resources.FunctionPython, resources.FunctionScala, resources.FunctionSql: return sdk.ParseSchemaObjectIdentifierWithArguments(rs.Primary.ID) - case resources.Procedure, - resources.ProcedureJava, + case resources.ProcedureJava, resources.ProcedureJavascript, resources.ProcedurePython, resources.ProcedureScala, @@ -149,9 +147,6 @@ var showByIdFunctions = map[resources.Resource]showByIdFunc{ resources.FileFormat: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.FileFormats.ShowByID) }, - resources.Function: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { - return runShowById(ctx, id, client.Functions.ShowByID) - }, resources.FunctionJava: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.Functions.ShowByID) }, @@ -200,9 +195,6 @@ var showByIdFunctions = map[resources.Resource]showByIdFunc{ resources.Pipe: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.Pipes.ShowByID) }, - resources.Procedure: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { - return runShowById(ctx, id, client.Procedures.ShowByID) - }, resources.ProcedureJava: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.Procedures.ShowByID) }, diff --git a/pkg/datasources/roles.go b/pkg/datasources/roles.go deleted file mode 100644 index 597702a637..0000000000 --- a/pkg/datasources/roles.go +++ /dev/null @@ -1,101 +0,0 @@ -package datasources - -import ( - "context" - "fmt" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/datasources" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/resources" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -var rolesSchema = map[string]*schema.Schema{ - "like": { - Type: schema.TypeString, - Optional: true, - Description: "Filters the output with **case-insensitive** pattern, with support for SQL wildcard characters (`%` and `_`).", - }, - "in_class": { - Type: schema.TypeString, - Optional: true, - ValidateDiagFunc: resources.IsValidIdentifier[sdk.SchemaObjectIdentifier](), - Description: "Filters the SHOW GRANTS output by class name.", - }, - "roles": { - Type: schema.TypeList, - Computed: true, - Description: "Holds the aggregated output of all role details queries.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - resources.ShowOutputAttributeName: { - Type: schema.TypeList, - Computed: true, - Description: "Holds the output of SHOW ROLES.", - Elem: &schema.Resource{ - Schema: schemas.ShowRoleSchema, - }, - }, - }, - }, - }, -} - -func Roles() *schema.Resource { - return &schema.Resource{ - ReadContext: TrackingReadWrapper(datasources.Roles, ReadRoles), - Schema: rolesSchema, - DeprecationMessage: "This resource is deprecated and will be removed in a future major version release. Please use snowflake_account_roles instead.", - Description: "Data source used to get details of filtered roles. Filtering is aligned with the current possibilities for [SHOW ROLES](https://docs.snowflake.com/en/sql-reference/sql/show-roles) query (`like` and `in_class` are all supported). The results of SHOW are encapsulated in one output collection.", - } -} - -func ReadRoles(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - client := meta.(*provider.Context).Client - - req := sdk.NewShowRoleRequest() - - if likePattern, ok := d.GetOk("like"); ok { - req.WithLike(sdk.NewLikeRequest(likePattern.(string))) - } - - if className, ok := d.GetOk("in_class"); ok { - req.WithInClass(sdk.RolesInClass{ - Class: sdk.NewSchemaObjectIdentifierFromFullyQualifiedName(className.(string)), - }) - } - - roles, err := client.Roles.Show(ctx, req) - if err != nil { - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to show roles", - Detail: fmt.Sprintf("Error: %s", err), - }, - } - } - - d.SetId("roles_read") - - flattenedRoles := make([]map[string]any, len(roles)) - for i, role := range roles { - role := role - flattenedRoles[i] = map[string]any{ - resources.ShowOutputAttributeName: []map[string]any{schemas.RoleToSchema(&role)}, - } - } - - err = d.Set("roles", flattenedRoles) - if err != nil { - return diag.FromErr(err) - } - - return nil -} diff --git a/pkg/datasources/roles_acceptance_test.go b/pkg/datasources/roles_acceptance_test.go deleted file mode 100644 index 35623e2ec0..0000000000 --- a/pkg/datasources/roles_acceptance_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package datasources_test - -import ( - "fmt" - "strconv" - "testing" - - acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" - "github.com/hashicorp/terraform-plugin-testing/config" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/terraform" - "github.com/hashicorp/terraform-plugin-testing/tfversion" -) - -func TestAcc_Roles_Complete(t *testing.T) { - accountRoleNamePrefix := random.AlphaN(10) - accountRoleName1 := acc.TestClient().Ids.AlphaWithPrefix(accountRoleNamePrefix + "1") - accountRoleName2 := acc.TestClient().Ids.AlphaWithPrefix(accountRoleNamePrefix + "2") - accountRoleName3 := acc.TestClient().Ids.Alpha() - comment := random.Comment() - - likeVariables := config.Variables{ - "account_role_name_1": config.StringVariable(accountRoleName1), - "account_role_name_2": config.StringVariable(accountRoleName2), - "account_role_name_3": config.StringVariable(accountRoleName3), - "comment": config.StringVariable(comment), - "like": config.StringVariable(accountRoleNamePrefix + "%"), - } - - resource.Test(t, resource.TestCase{ - ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, - PreCheck: func() { acc.TestAccPreCheck(t) }, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - Steps: []resource.TestStep{ - { - ConfigDirectory: config.TestStepDirectory(), - ConfigVariables: likeVariables, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("data.snowflake_roles.test", "roles.#", "2"), - // containsRole(accountRoleName1, comment), - // containsRole(accountRoleName2, comment), - doesntContainRole(accountRoleName3, comment), - ), - }, - { - ConfigDirectory: config.TestStepDirectory(), - ConfigVariables: config.Variables{}, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrWith("data.snowflake_roles.test", "roles.#", func(value string) error { - numberOfRoles, err := strconv.ParseInt(value, 10, 8) - if err != nil { - return err - } - - if numberOfRoles == 0 { - return fmt.Errorf("expected roles to be non-empty") - } - - return nil - }), - ), - }, - }, - }) -} - -func doesntContainRole(name string, comment string) func(s *terraform.State) error { - return func(state *terraform.State) error { - err := containsRole(name, comment)(state) - if err != nil && err.Error() == fmt.Sprintf("role %s not found", name) { - return nil - } - return fmt.Errorf("expected %s not to be present", name) - } -} - -func containsRole(name string, comment string) func(s *terraform.State) error { - return func(s *terraform.State) error { - for _, rs := range s.RootModule().Resources { - if rs.Type != "snowflake_roles" { - continue - } - - iter, err := strconv.ParseInt(rs.Primary.Attributes["roles.#"], 10, 32) - if err != nil { - return err - } - - for i := 0; i < int(iter); i++ { - if rs.Primary.Attributes[fmt.Sprintf("roles.%d.show_output.0.name", i)] == name { - actualComment := rs.Primary.Attributes[fmt.Sprintf("roles.%d.show_output.0.comment", i)] - if actualComment != comment { - return fmt.Errorf("expected comment: %s, but got: %s", comment, actualComment) - } - - return nil - } - } - } - - return fmt.Errorf("role %s not found", name) - } -} diff --git a/pkg/datasources/testdata/TestAcc_Procedures/complete/test.tf b/pkg/datasources/testdata/TestAcc_Procedures/complete/test.tf index 33ffb62f1d..b91ba271a9 100644 --- a/pkg/datasources/testdata/TestAcc_Procedures/complete/test.tf +++ b/pkg/datasources/testdata/TestAcc_Procedures/complete/test.tf @@ -14,18 +14,17 @@ variable "schema" { type = string } -resource "snowflake_procedure" "test_proc_one" { +resource "snowflake_procedure_javascript" "test_proc_one" { name = var.proc_name_one database = var.database schema = var.schema return_type = "VARCHAR" - language = "JAVASCRIPT" statement = <<-EOF return "Hi" EOF } -resource "snowflake_procedure" "test_proc_two" { +resource "snowflake_procedure_javascript" "test_proc_two" { name = var.proc_name_two database = var.database schema = var.schema @@ -35,7 +34,6 @@ resource "snowflake_procedure" "test_proc_two" { } comment = "Terraform acceptance test" return_type = "varchar" - language = "JAVASCRIPT" statement = <<-EOF var X=1 return X @@ -45,5 +43,5 @@ resource "snowflake_procedure" "test_proc_two" { data "snowflake_procedures" "procedures" { database = var.database schema = var.schema - depends_on = [snowflake_procedure.test_proc_one, snowflake_procedure.test_proc_two] + depends_on = [snowflake_procedure_javascript.test_proc_one, snowflake_procedure_javascript.test_proc_two] } diff --git a/pkg/datasources/testdata/TestAcc_Roles_Complete/1/test.tf b/pkg/datasources/testdata/TestAcc_Roles_Complete/1/test.tf deleted file mode 100644 index ecef265a1c..0000000000 --- a/pkg/datasources/testdata/TestAcc_Roles_Complete/1/test.tf +++ /dev/null @@ -1,23 +0,0 @@ -resource "snowflake_account_role" "test1" { - name = var.account_role_name_1 - comment = var.comment -} - -resource "snowflake_account_role" "test2" { - name = var.account_role_name_2 - comment = var.comment -} - -resource "snowflake_account_role" "test3" { - name = var.account_role_name_3 - comment = var.comment -} - -data "snowflake_roles" "test" { - depends_on = [ - snowflake_account_role.test1, - snowflake_account_role.test2, - snowflake_account_role.test3, - ] - like = var.like -} diff --git a/pkg/datasources/testdata/TestAcc_Roles_Complete/1/variables.tf b/pkg/datasources/testdata/TestAcc_Roles_Complete/1/variables.tf deleted file mode 100644 index fcd75c445f..0000000000 --- a/pkg/datasources/testdata/TestAcc_Roles_Complete/1/variables.tf +++ /dev/null @@ -1,19 +0,0 @@ -variable "account_role_name_1" { - type = string -} - -variable "account_role_name_2" { - type = string -} - -variable "account_role_name_3" { - type = string -} - -variable "comment" { - type = string -} - -variable "like" { - type = string -} diff --git a/pkg/datasources/testdata/TestAcc_Roles_Complete/2/test.tf b/pkg/datasources/testdata/TestAcc_Roles_Complete/2/test.tf deleted file mode 100644 index 371634b3d1..0000000000 --- a/pkg/datasources/testdata/TestAcc_Roles_Complete/2/test.tf +++ /dev/null @@ -1,3 +0,0 @@ -data "snowflake_roles" "test" { - in_class = "SNOWFLAKE.CORE.BUDGET" -} diff --git a/pkg/internal/tracking/context.go b/pkg/internal/tracking/context.go index 213dce13c7..412ff9eb77 100644 --- a/pkg/internal/tracking/context.go +++ b/pkg/internal/tracking/context.go @@ -10,7 +10,7 @@ import ( const ( CurrentSchemaVersion string = "1" - ProviderVersion string = "v1.0.0-rc1" // TODO(SNOW-1814934): Currently hardcoded, make it computed + ProviderVersion string = "v1.0.0" // TODO(SNOW-1814934): Currently hardcoded, make it computed MetadataPrefix string = "terraform_provider_usage_tracking" ) diff --git a/pkg/provider/datasources/datasources.go b/pkg/provider/datasources/datasources.go index c31b954a22..5edf2f8ca8 100644 --- a/pkg/provider/datasources/datasources.go +++ b/pkg/provider/datasources/datasources.go @@ -28,8 +28,6 @@ const ( Pipes datasource = "snowflake_pipes" Procedures datasource = "snowflake_procedures" ResourceMonitors datasource = "snowflake_resource_monitors" - Role datasource = "snowflake_role" - Roles datasource = "snowflake_roles" RowAccessPolicies datasource = "snowflake_row_access_policies" Schemas datasource = "snowflake_schemas" Secrets datasource = "snowflake_secrets" diff --git a/pkg/provider/provider.go b/pkg/provider/provider.go index d3ef21f5f5..1664c48f52 100644 --- a/pkg/provider/provider.go +++ b/pkg/provider/provider.go @@ -72,7 +72,7 @@ func Provider() *schema.Provider { }, "password": { Type: schema.TypeString, - Description: envNameFieldDescription("Password for user + password auth. Cannot be used with `browser_auth` or `private_key_path`.", snowflakeenvs.Password), + Description: envNameFieldDescription("Password for user + password auth. Cannot be used with `private_key` and `private_key_passphrase`.", snowflakeenvs.Password), Optional: true, Sensitive: true, DefaultFunc: schema.EnvDefaultFunc(snowflakeenvs.Password, nil), @@ -399,7 +399,6 @@ func getResources() map[string]*schema.Resource { "snowflake_external_volume": resources.ExternalVolume(), "snowflake_failover_group": resources.FailoverGroup(), "snowflake_file_format": resources.FileFormat(), - "snowflake_function": resources.Function(), "snowflake_function_java": resources.FunctionJava(), "snowflake_function_javascript": resources.FunctionJavascript(), "snowflake_function_python": resources.FunctionPython(), @@ -426,7 +425,6 @@ func getResources() map[string]*schema.Resource { "snowflake_password_policy": resources.PasswordPolicy(), "snowflake_pipe": resources.Pipe(), "snowflake_primary_connection": resources.PrimaryConnection(), - "snowflake_procedure": resources.Procedure(), "snowflake_procedure_java": resources.ProcedureJava(), "snowflake_procedure_javascript": resources.ProcedureJavascript(), "snowflake_procedure_python": resources.ProcedurePython(), @@ -460,7 +458,6 @@ func getResources() map[string]*schema.Resource { "snowflake_tag": resources.Tag(), "snowflake_tag_association": resources.TagAssociation(), "snowflake_task": resources.Task(), - "snowflake_unsafe_execute": resources.UnsafeExecute(), "snowflake_user": resources.User(), "snowflake_user_authentication_policy_attachment": resources.UserAuthenticationPolicyAttachment(), "snowflake_user_password_policy_attachment": resources.UserPasswordPolicyAttachment(), @@ -503,7 +500,6 @@ func getDataSources() map[string]*schema.Resource { "snowflake_pipes": datasources.Pipes(), "snowflake_procedures": datasources.Procedures(), "snowflake_resource_monitors": datasources.ResourceMonitors(), - "snowflake_roles": datasources.Roles(), "snowflake_row_access_policies": datasources.RowAccessPolicies(), "snowflake_schemas": datasources.Schemas(), "snowflake_secrets": datasources.Secrets(), diff --git a/pkg/provider/resources/resources.go b/pkg/provider/resources/resources.go index 3f042d1246..b6739b9604 100644 --- a/pkg/provider/resources/resources.go +++ b/pkg/provider/resources/resources.go @@ -33,7 +33,6 @@ const ( GrantPrivilegesToAccountRole resource = "snowflake_grant_privileges_to_account_role" GrantPrivilegesToDatabaseRole resource = "snowflake_grant_privileges_to_database_role" GrantPrivilegesToShare resource = "snowflake_grant_privileges_to_share" - Function resource = "snowflake_function" FunctionJava resource = "snowflake_function_java" FunctionJavascript resource = "snowflake_function_javascript" FunctionPython resource = "snowflake_function_python" @@ -54,7 +53,6 @@ const ( PasswordPolicy resource = "snowflake_password_policy" Pipe resource = "snowflake_pipe" PrimaryConnection resource = "snowflake_primary_connection" - Procedure resource = "snowflake_procedure" ProcedureJava resource = "snowflake_procedure_java" ProcedureJavascript resource = "snowflake_procedure_javascript" ProcedurePython resource = "snowflake_procedure_python" @@ -91,7 +89,6 @@ const ( TagAssociation resource = "snowflake_tag_association" TagMaskingPolicyAssociation resource = "snowflake_tag_masking_policy_association" Task resource = "snowflake_task" - UnsafeExecute resource = "snowflake_unsafe_execute" User resource = "snowflake_user" UserAuthenticationPolicyAttachment resource = "snowflake_user_authentication_policy_attachment" UserPasswordPolicyAttachment resource = "snowflake_user_password_policy_attachment" diff --git a/pkg/resources/execute.go b/pkg/resources/execute.go index 6ad9b189cd..acd5c26926 100644 --- a/pkg/resources/execute.go +++ b/pkg/resources/execute.go @@ -61,7 +61,7 @@ func Execute() *schema.Resource { Description: "Resource allowing execution of ANY SQL statement.", - CustomizeDiff: TrackingCustomDiffWrapper(resources.UnsafeExecute, customdiff.All( + CustomizeDiff: TrackingCustomDiffWrapper(resources.Execute, customdiff.All( customdiff.ForceNewIfChange("execute", func(ctx context.Context, oldValue, newValue, meta any) bool { return oldValue != "" }), diff --git a/pkg/resources/function.go b/pkg/resources/function.go deleted file mode 100644 index 663dcf5693..0000000000 --- a/pkg/resources/function.go +++ /dev/null @@ -1,790 +0,0 @@ -package resources - -import ( - "context" - "fmt" - "log" - "regexp" - "strings" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/datatypes" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/snowflake" - "github.com/hashicorp/go-cty/cty" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" -) - -var languages = []string{"javascript", "scala", "java", "sql", "python"} - -var functionSchema = map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - Description: "Specifies the identifier for the function; does not have to be unique for the schema in which the function is created. Don't use the | character.", - }, - "database": { - Type: schema.TypeString, - Required: true, - Description: "The database in which to create the function. Don't use the | character.", - ForceNew: true, - }, - "schema": { - Type: schema.TypeString, - Required: true, - Description: "The schema in which to create the function. Don't use the | character.", - ForceNew: true, - }, - "arguments": { - Type: schema.TypeList, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - // Suppress the diff shown if the values are equal when both compared in lower case. - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return strings.EqualFold(old, new) - }, - Description: "The argument name", - }, - // TODO(SNOW-1596962): Fully support VECTOR data type sdk.ParseFunctionArgumentsFromString could be a base for another function that takes argument names into consideration. - "type": { - Type: schema.TypeString, - Required: true, - // Suppress the diff shown if the values are equal when both compared in lower case. - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return strings.EqualFold(old, new) - }, - Description: "The argument type", - }, - }, - }, - Optional: true, - Description: "List of the arguments for the function", - ForceNew: true, - }, - "return_type": { - Type: schema.TypeString, - Description: "The return type of the function", - // Suppress the diff shown if the values are equal when both compared in lower case. - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return strings.EqualFold(old, new) - }, - Required: true, - ForceNew: true, - }, - "statement": { - Type: schema.TypeString, - Required: true, - Description: "Specifies the javascript / java / scala / sql / python code used to create the function.", - ForceNew: true, - DiffSuppressFunc: DiffSuppressStatement, - }, - "language": { - Type: schema.TypeString, - Optional: true, - Default: "SQL", - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return strings.EqualFold(old, new) - }, - ValidateFunc: validation.StringInSlice(languages, true), - Description: "Specifies the language of the stored function code.", - }, - "null_input_behavior": { - Type: schema.TypeString, - Optional: true, - Default: "CALLED ON NULL INPUT", - ForceNew: true, - // We do not use STRICT, because Snowflake then in the Read phase returns RETURNS NULL ON NULL INPUT - ValidateFunc: validation.StringInSlice([]string{"CALLED ON NULL INPUT", "RETURNS NULL ON NULL INPUT"}, false), - Description: "Specifies the behavior of the function when called with null inputs.", - }, - "return_behavior": { - Type: schema.TypeString, - Optional: true, - Default: "VOLATILE", - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"VOLATILE", "IMMUTABLE"}, false), - Description: "Specifies the behavior of the function when returning results", - }, - "is_secure": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Description: "Specifies that the function is secure.", - }, - "comment": { - Type: schema.TypeString, - Optional: true, - Default: "user-defined function", - Description: "Specifies a comment for the function.", - }, - "runtime_version": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: "Required for Python functions. Specifies Python runtime version.", - }, - "packages": { - Type: schema.TypeList, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - Optional: true, - ForceNew: true, - Description: "List of package imports to use for Java / Python functions. For Java, package imports should be of the form: package_name:version_number, where package_name is snowflake_domain:package. For Python use it should be: ('numpy','pandas','xgboost==1.5.0').", - }, - "imports": { - Type: schema.TypeList, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - Optional: true, - ForceNew: true, - Description: "Imports for Java / Python functions. For Java this a list of jar files, for Python this is a list of Python files.", - }, - "handler": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: "The handler method for Java / Python function.", - }, - "target_path": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: "The target path for the Java / Python functions. For Java, it is the path of compiled jar files and for the Python it is the path of the Python files.", - }, - FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, -} - -func Function() *schema.Resource { - return &schema.Resource{ - SchemaVersion: 2, - - CreateContext: TrackingCreateWrapper(resources.Function, CreateContextFunction), - ReadContext: TrackingReadWrapper(resources.Function, ReadContextFunction), - UpdateContext: TrackingUpdateWrapper(resources.Function, UpdateContextFunction), - DeleteContext: TrackingDeleteWrapper(resources.Function, DeleteFunction), - - DeprecationMessage: "This resource is deprecated and will be removed in a future major version release. Please use snowflake_function_java, snowflake_function_javascript, snowflake_function_python, snowflake_function_scala, and snowflake_function_sql instead.", - - CustomizeDiff: TrackingCustomDiffWrapper(resources.Function, customdiff.All( - // TODO(SNOW-1348103): add `arguments` to ComputedIfAnyAttributeChanged. This can't be done now because this function compares values without diff suppress. - ComputedIfAnyAttributeChanged(functionSchema, FullyQualifiedNameAttributeName, "name"), - )), - - Schema: functionSchema, - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - - StateUpgraders: []schema.StateUpgrader{ - { - Version: 0, - // setting type to cty.EmptyObject is a bit hacky here but following https://developer.hashicorp.com/terraform/plugin/framework/migrating/resources/state-upgrade#sdkv2-1 would require lots of repetitive code; this should work with cty.EmptyObject - Type: cty.EmptyObject, - Upgrade: v085FunctionIdStateUpgrader, - }, - { - Version: 1, - // setting type to cty.EmptyObject is a bit hacky here but following https://developer.hashicorp.com/terraform/plugin/framework/migrating/resources/state-upgrade#sdkv2-1 would require lots of repetitive code; this should work with cty.EmptyObject - Type: cty.EmptyObject, - Upgrade: v0941ResourceIdentifierWithArguments, - }, - }, - } -} - -func CreateContextFunction(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - lang := strings.ToUpper(d.Get("language").(string)) - switch lang { - case "JAVA": - return createJavaFunction(ctx, d, meta) - case "JAVASCRIPT": - return createJavascriptFunction(ctx, d, meta) - case "PYTHON": - return createPythonFunction(ctx, d, meta) - case "SCALA": - return createScalaFunction(ctx, d, meta) - case "", "SQL": // SQL if language is not set - return createSQLFunction(ctx, d, meta) - default: - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Invalid language", - Detail: fmt.Sprintf("Language %s is not supported", lang), - }, - } - } -} - -func createJavaFunction(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*provider.Context).Client - name := d.Get("name").(string) - sc := d.Get("schema").(string) - database := d.Get("database").(string) - id := sdk.NewSchemaObjectIdentifier(database, sc, name) - - // Set required - returns, diags := parseFunctionReturnsRequest(d.Get("return_type").(string)) - if diags != nil { - return diags - } - handler := d.Get("handler").(string) - // create request with required - request := sdk.NewCreateForJavaFunctionRequest(id, *returns, handler) - functionDefinition := d.Get("statement").(string) - request.WithFunctionDefinitionWrapped(functionDefinition) - - // Set optionals - if v, ok := d.GetOk("is_secure"); ok { - request.WithSecure(v.(bool)) - } - arguments, diags := parseFunctionArguments(d) - if diags != nil { - return diags - } - if len(arguments) > 0 { - request.WithArguments(arguments) - } - if v, ok := d.GetOk("null_input_behavior"); ok { - request.WithNullInputBehavior(sdk.NullInputBehavior(v.(string))) - } - if v, ok := d.GetOk("return_behavior"); ok { - request.WithReturnResultsBehavior(sdk.ReturnResultsBehavior(v.(string))) - } - if v, ok := d.GetOk("runtime_version"); ok { - request.WithRuntimeVersion(v.(string)) - } - if v, ok := d.GetOk("comment"); ok { - request.WithComment(v.(string)) - } - if _, ok := d.GetOk("imports"); ok { - var imports []sdk.FunctionImportRequest - for _, item := range d.Get("imports").([]interface{}) { - imports = append(imports, *sdk.NewFunctionImportRequest().WithImport(item.(string))) - } - request.WithImports(imports) - } - if _, ok := d.GetOk("packages"); ok { - var packages []sdk.FunctionPackageRequest - for _, item := range d.Get("packages").([]interface{}) { - packages = append(packages, *sdk.NewFunctionPackageRequest().WithPackage(item.(string))) - } - request.WithPackages(packages) - } - if v, ok := d.GetOk("target_path"); ok { - request.WithTargetPath(v.(string)) - } - - if err := client.Functions.CreateForJava(ctx, request); err != nil { - return diag.FromErr(err) - } - argumentTypes := make([]sdk.DataType, 0, len(arguments)) - for _, item := range arguments { - argumentTypes = append(argumentTypes, item.ArgDataTypeOld) - } - nid := sdk.NewSchemaObjectIdentifierWithArguments(database, sc, name, argumentTypes...) - d.SetId(nid.FullyQualifiedName()) - return ReadContextFunction(ctx, d, meta) -} - -func createScalaFunction(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*provider.Context).Client - name := d.Get("name").(string) - sc := d.Get("schema").(string) - database := d.Get("database").(string) - id := sdk.NewSchemaObjectIdentifier(database, sc, name) - - // Set required - returnType := d.Get("return_type").(string) - returnDataType, diags := convertFunctionDataType(returnType) - if diags != nil { - return diags - } - functionDefinition := d.Get("statement").(string) - handler := d.Get("handler").(string) - var runtimeVersion string - if v, ok := d.GetOk("runtime_version"); ok { - runtimeVersion = v.(string) - } else { - return diag.Errorf("Runtime version is required for Scala function") - } - - // create request with required - request := sdk.NewCreateForScalaFunctionRequest(id, nil, handler, runtimeVersion).WithResultDataTypeOld(sdk.LegacyDataTypeFrom(returnDataType)) - request.WithFunctionDefinitionWrapped(functionDefinition) - - // Set optionals - if v, ok := d.GetOk("is_secure"); ok { - request.WithSecure(v.(bool)) - } - arguments, diags := parseFunctionArguments(d) - if diags != nil { - return diags - } - if len(arguments) > 0 { - request.WithArguments(arguments) - } - if v, ok := d.GetOk("null_input_behavior"); ok { - request.WithNullInputBehavior(sdk.NullInputBehavior(v.(string))) - } - if v, ok := d.GetOk("return_behavior"); ok { - request.WithReturnResultsBehavior(sdk.ReturnResultsBehavior(v.(string))) - } - if v, ok := d.GetOk("comment"); ok { - request.WithComment(v.(string)) - } - if _, ok := d.GetOk("imports"); ok { - var imports []sdk.FunctionImportRequest - for _, item := range d.Get("imports").([]interface{}) { - imports = append(imports, *sdk.NewFunctionImportRequest().WithImport(item.(string))) - } - request.WithImports(imports) - } - if _, ok := d.GetOk("packages"); ok { - var packages []sdk.FunctionPackageRequest - for _, item := range d.Get("packages").([]interface{}) { - packages = append(packages, *sdk.NewFunctionPackageRequest().WithPackage(item.(string))) - } - request.WithPackages(packages) - } - if v, ok := d.GetOk("target_path"); ok { - request.WithTargetPath(v.(string)) - } - - if err := client.Functions.CreateForScala(ctx, request); err != nil { - return diag.FromErr(err) - } - argumentTypes := make([]sdk.DataType, 0, len(arguments)) - for _, item := range arguments { - argumentTypes = append(argumentTypes, item.ArgDataTypeOld) - } - nid := sdk.NewSchemaObjectIdentifierWithArguments(database, sc, name, argumentTypes...) - d.SetId(nid.FullyQualifiedName()) - return ReadContextFunction(ctx, d, meta) -} - -func createSQLFunction(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*provider.Context).Client - name := d.Get("name").(string) - sc := d.Get("schema").(string) - database := d.Get("database").(string) - id := sdk.NewSchemaObjectIdentifier(database, sc, name) - - // Set required - returns, diags := parseFunctionReturnsRequest(d.Get("return_type").(string)) - if diags != nil { - return diags - } - functionDefinition := d.Get("statement").(string) - // create request with required - request := sdk.NewCreateForSQLFunctionRequestDefinitionWrapped(id, *returns, functionDefinition) - - // Set optionals - if v, ok := d.GetOk("is_secure"); ok { - request.WithSecure(v.(bool)) - } - arguments, diags := parseFunctionArguments(d) - if diags != nil { - return diags - } - if len(arguments) > 0 { - request.WithArguments(arguments) - } - if v, ok := d.GetOk("return_behavior"); ok { - request.WithReturnResultsBehavior(sdk.ReturnResultsBehavior(v.(string))) - } - if v, ok := d.GetOk("comment"); ok { - request.WithComment(v.(string)) - } - - if err := client.Functions.CreateForSQL(ctx, request); err != nil { - return diag.FromErr(err) - } - argumentTypes := make([]sdk.DataType, 0, len(arguments)) - for _, item := range arguments { - argumentTypes = append(argumentTypes, item.ArgDataTypeOld) - } - nid := sdk.NewSchemaObjectIdentifierWithArguments(database, sc, name, argumentTypes...) - d.SetId(nid.FullyQualifiedName()) - return ReadContextFunction(ctx, d, meta) -} - -func createPythonFunction(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*provider.Context).Client - name := d.Get("name").(string) - sc := d.Get("schema").(string) - database := d.Get("database").(string) - id := sdk.NewSchemaObjectIdentifier(database, sc, name) - - // Set required - returns, diags := parseFunctionReturnsRequest(d.Get("return_type").(string)) - if diags != nil { - return diags - } - functionDefinition := d.Get("statement").(string) - version := d.Get("runtime_version").(string) - handler := d.Get("handler").(string) - // create request with required - request := sdk.NewCreateForPythonFunctionRequest(id, *returns, version, handler) - request.WithFunctionDefinitionWrapped(functionDefinition) - - // Set optionals - if v, ok := d.GetOk("is_secure"); ok { - request.WithSecure(v.(bool)) - } - arguments, diags := parseFunctionArguments(d) - if diags != nil { - return diags - } - if len(arguments) > 0 { - request.WithArguments(arguments) - } - if v, ok := d.GetOk("null_input_behavior"); ok { - request.WithNullInputBehavior(sdk.NullInputBehavior(v.(string))) - } - if v, ok := d.GetOk("return_behavior"); ok { - request.WithReturnResultsBehavior(sdk.ReturnResultsBehavior(v.(string))) - } - - if v, ok := d.GetOk("comment"); ok { - request.WithComment(v.(string)) - } - if _, ok := d.GetOk("imports"); ok { - var imports []sdk.FunctionImportRequest - for _, item := range d.Get("imports").([]interface{}) { - imports = append(imports, *sdk.NewFunctionImportRequest().WithImport(item.(string))) - } - request.WithImports(imports) - } - if _, ok := d.GetOk("packages"); ok { - var packages []sdk.FunctionPackageRequest - for _, item := range d.Get("packages").([]interface{}) { - packages = append(packages, *sdk.NewFunctionPackageRequest().WithPackage(item.(string))) - } - request.WithPackages(packages) - } - - if err := client.Functions.CreateForPython(ctx, request); err != nil { - return diag.FromErr(err) - } - argumentTypes := make([]sdk.DataType, 0, len(arguments)) - for _, item := range arguments { - argumentTypes = append(argumentTypes, item.ArgDataTypeOld) - } - nid := sdk.NewSchemaObjectIdentifierWithArguments(database, sc, name, argumentTypes...) - d.SetId(nid.FullyQualifiedName()) - return ReadContextFunction(ctx, d, meta) -} - -func createJavascriptFunction(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*provider.Context).Client - name := d.Get("name").(string) - sc := d.Get("schema").(string) - database := d.Get("database").(string) - id := sdk.NewSchemaObjectIdentifier(database, sc, name) - - // Set required - returns, diags := parseFunctionReturnsRequest(d.Get("return_type").(string)) - if diags != nil { - return diags - } - functionDefinition := d.Get("statement").(string) - // create request with required - request := sdk.NewCreateForJavascriptFunctionRequestDefinitionWrapped(id, *returns, functionDefinition) - - // Set optionals - if v, ok := d.GetOk("is_secure"); ok { - request.WithSecure(v.(bool)) - } - arguments, diags := parseFunctionArguments(d) - if diags != nil { - return diags - } - if len(arguments) > 0 { - request.WithArguments(arguments) - } - if v, ok := d.GetOk("null_input_behavior"); ok { - request.WithNullInputBehavior(sdk.NullInputBehavior(v.(string))) - } - if v, ok := d.GetOk("return_behavior"); ok { - request.WithReturnResultsBehavior(sdk.ReturnResultsBehavior(v.(string))) - } - if v, ok := d.GetOk("comment"); ok { - request.WithComment(v.(string)) - } - - if err := client.Functions.CreateForJavascript(ctx, request); err != nil { - return diag.FromErr(err) - } - argumentTypes := make([]sdk.DataType, 0, len(arguments)) - for _, item := range arguments { - argumentTypes = append(argumentTypes, item.ArgDataTypeOld) - } - nid := sdk.NewSchemaObjectIdentifierWithArguments(database, sc, name, argumentTypes...) - d.SetId(nid.FullyQualifiedName()) - return ReadContextFunction(ctx, d, meta) -} - -func ReadContextFunction(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - diags := diag.Diagnostics{} - client := meta.(*provider.Context).Client - - id, err := sdk.ParseSchemaObjectIdentifierWithArguments(d.Id()) - if err != nil { - return diag.FromErr(err) - } - if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { - return diag.FromErr(err) - } - if err := d.Set("name", id.Name()); err != nil { - return diag.FromErr(err) - } - if err := d.Set("database", id.DatabaseName()); err != nil { - return diag.FromErr(err) - } - if err := d.Set("schema", id.SchemaName()); err != nil { - return diag.FromErr(err) - } - - arguments := d.Get("arguments").([]interface{}) - argumentTypes := make([]string, len(arguments)) - for i, arg := range arguments { - argumentTypes[i] = arg.(map[string]interface{})["type"].(string) - } - functionDetails, err := client.Functions.Describe(ctx, id) - if err != nil { - // if function is not found then mark resource to be removed from state file during apply or refresh - d.SetId("") - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Warning, - Summary: "Describe function failed.", - Detail: "See our document on design decisions for functions: ", - }, - } - } - for _, desc := range functionDetails { - if desc.Value == nil { - continue - } - switch desc.Property { - case "signature": - // Format in Snowflake DB is: (argName argType, argName argType, ...) - value := strings.ReplaceAll(strings.ReplaceAll(*desc.Value, "(", ""), ")", "") - if value != "" { // Do nothing for functions without arguments - pairs := strings.Split(value, ", ") - - var arguments []interface{} - for _, pair := range pairs { - item := strings.Split(pair, " ") - argument := map[string]interface{}{} - argument["name"] = item[0] - argument["type"] = item[1] - arguments = append(arguments, argument) - } - if err := d.Set("arguments", arguments); err != nil { - diag.FromErr(err) - } - } - case "null handling": - if err := d.Set("null_input_behavior", *desc.Value); err != nil { - diag.FromErr(err) - } - case "volatility": - if err := d.Set("return_behavior", *desc.Value); err != nil { - diag.FromErr(err) - } - case "body": - if err := d.Set("statement", *desc.Value); err != nil { - diag.FromErr(err) - } - case "returns": - // Format in Snowflake DB is returnType() - re := regexp.MustCompile(`^(.*)\([0-9]*\)$`) - rt := *desc.Value - match := re.FindStringSubmatch(rt) - if match != nil { - rt = match[1] - } - if err := d.Set("return_type", rt); err != nil { - diag.FromErr(err) - } - case "language": - if snowflake.Contains(languages, strings.ToLower(*desc.Value)) { - if err := d.Set("language", *desc.Value); err != nil { - diag.FromErr(err) - } - } else { - log.Printf("[INFO] Unexpected language for function %v returned from Snowflake", *desc.Value) - } - case "packages": - value := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(*desc.Value, "[", ""), "]", ""), "'", "") - if value != "" { // Do nothing for Java / Python functions without packages - packages := strings.Split(value, ",") - if err := d.Set("packages", packages); err != nil { - diag.FromErr(err) - } - } - case "imports": - value := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(*desc.Value, "[", ""), "]", ""), "'", "") - if value != "" { // Do nothing for Java functions without imports - imports := strings.Split(value, ",") - if err := d.Set("imports", imports); err != nil { - diag.FromErr(err) - } - } - case "handler": - if err := d.Set("handler", *desc.Value); err != nil { - diag.FromErr(err) - } - case "target_path": - if err := d.Set("target_path", *desc.Value); err != nil { - diag.FromErr(err) - } - case "runtime_version": - if err := d.Set("runtime_version", *desc.Value); err != nil { - diag.FromErr(err) - } - default: - log.Printf("[INFO] Unexpected function property %v returned from Snowflake with value %v", desc.Property, *desc.Value) - } - } - - function, err := client.Functions.ShowByID(ctx, id) - if err != nil { - return diag.FromErr(err) - } - - if err := d.Set("is_secure", function.IsSecure); err != nil { - return diag.FromErr(err) - } - - if err := d.Set("comment", function.Description); err != nil { - return diag.FromErr(err) - } - - return diags -} - -func UpdateContextFunction(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*provider.Context).Client - - id, err := sdk.ParseSchemaObjectIdentifierWithArguments(d.Id()) - if err != nil { - return diag.FromErr(err) - } - if d.HasChange("name") { - name := d.Get("name").(string) - newId := sdk.NewSchemaObjectIdentifierWithArguments(id.DatabaseName(), id.SchemaName(), name, id.ArgumentDataTypes()...) - - if err := client.Functions.Alter(ctx, sdk.NewAlterFunctionRequest(id).WithRenameTo(newId.SchemaObjectId())); err != nil { - return diag.FromErr(err) - } - - d.SetId(newId.FullyQualifiedName()) - id = newId - } - - if d.HasChange("is_secure") { - secure := d.Get("is_secure") - if secure.(bool) { - if err := client.Functions.Alter(ctx, sdk.NewAlterFunctionRequest(id).WithSetSecure(true)); err != nil { - return diag.FromErr(err) - } - } else { - if err := client.Functions.Alter(ctx, sdk.NewAlterFunctionRequest(id).WithUnsetSecure(true)); err != nil { - return diag.FromErr(err) - } - } - } - - if d.HasChange("comment") { - comment := d.Get("comment") - if comment != "" { - if err := client.Functions.Alter(ctx, sdk.NewAlterFunctionRequest(id).WithSet(*sdk.NewFunctionSetRequest().WithComment(comment.(string)))); err != nil { - return diag.FromErr(err) - } - } else { - if err := client.Functions.Alter(ctx, sdk.NewAlterFunctionRequest(id).WithUnset(*sdk.NewFunctionUnsetRequest().WithComment(true))); err != nil { - return diag.FromErr(err) - } - } - } - - return ReadContextFunction(ctx, d, meta) -} - -func parseFunctionArguments(d *schema.ResourceData) ([]sdk.FunctionArgumentRequest, diag.Diagnostics) { - args := make([]sdk.FunctionArgumentRequest, 0) - if v, ok := d.GetOk("arguments"); ok { - for _, arg := range v.([]interface{}) { - argName := arg.(map[string]interface{})["name"].(string) - argType := arg.(map[string]interface{})["type"].(string) - argDataType, diags := convertFunctionDataType(argType) - if diags != nil { - return nil, diags - } - args = append(args, sdk.FunctionArgumentRequest{ArgName: argName, ArgDataTypeOld: sdk.LegacyDataTypeFrom(argDataType)}) - } - } - return args, nil -} - -func convertFunctionDataType(s string) (datatypes.DataType, diag.Diagnostics) { - dataType, err := datatypes.ParseDataType(s) - if err != nil { - return nil, diag.FromErr(err) - } - return dataType, nil -} - -func convertFunctionColumns(s string) ([]sdk.FunctionColumn, diag.Diagnostics) { - pattern := regexp.MustCompile(`(\w+)\s+(\w+)`) - matches := pattern.FindAllStringSubmatch(s, -1) - var columns []sdk.FunctionColumn - for _, match := range matches { - if len(match) == 3 { - dataType, err := datatypes.ParseDataType(match[2]) - if err != nil { - return nil, diag.FromErr(err) - } - columns = append(columns, sdk.FunctionColumn{ - ColumnName: match[1], - ColumnDataTypeOld: sdk.LegacyDataTypeFrom(dataType), - }) - } - } - return columns, nil -} - -func parseFunctionReturnsRequest(s string) (*sdk.FunctionReturnsRequest, diag.Diagnostics) { - returns := sdk.NewFunctionReturnsRequest() - if strings.HasPrefix(strings.ToLower(s), "table") { - columns, diags := convertFunctionColumns(s) - if diags != nil { - return nil, diags - } - var cr []sdk.FunctionColumnRequest - for _, item := range columns { - cr = append(cr, *sdk.NewFunctionColumnRequest(item.ColumnName, nil).WithColumnDataTypeOld(item.ColumnDataTypeOld)) - } - returns.WithTable(*sdk.NewFunctionReturnsTableRequest().WithColumns(cr)) - } else { - returnDataType, diags := convertFunctionDataType(s) - if diags != nil { - return nil, diags - } - returns.WithResultDataType(*sdk.NewFunctionReturnsResultDataTypeRequest(nil).WithResultDataTypeOld(sdk.LegacyDataTypeFrom(returnDataType))) - } - return returns, nil -} diff --git a/pkg/resources/function_acceptance_test.go b/pkg/resources/function_acceptance_test.go deleted file mode 100644 index df8bb28014..0000000000 --- a/pkg/resources/function_acceptance_test.go +++ /dev/null @@ -1,451 +0,0 @@ -package resources_test - -import ( - "fmt" - "strings" - "testing" - - 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/provider/resources" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" - "github.com/hashicorp/terraform-plugin-testing/config" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/plancheck" - "github.com/hashicorp/terraform-plugin-testing/tfversion" -) - -func testAccFunction(t *testing.T, configDirectory string) { - t.Helper() - - name := acc.TestClient().Ids.Alpha() - resourceName := "snowflake_function.f" - m := func() map[string]config.Variable { - return map[string]config.Variable{ - "name": config.StringVariable(name), - "database": config.StringVariable(acc.TestDatabaseName), - "schema": config.StringVariable(acc.TestSchemaName), - "comment": config.StringVariable("Terraform acceptance test"), - } - } - variableSet2 := m() - variableSet2["comment"] = config.StringVariable("Terraform acceptance test - updated") - - ignoreDuringImport := []string{"null_input_behavior"} - if strings.Contains(configDirectory, "/sql") { - ignoreDuringImport = append(ignoreDuringImport, "return_behavior") - } - - resource.Test(t, resource.TestCase{ - ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, - PreCheck: func() { acc.TestAccPreCheck(t) }, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - CheckDestroy: acc.CheckDestroy(t, resources.Function), - Steps: []resource.TestStep{ - { - ConfigDirectory: acc.ConfigurationDirectory(configDirectory), - ConfigVariables: m(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test"), - - // computed attributes - resource.TestCheckResourceAttrSet(resourceName, "return_type"), - resource.TestCheckResourceAttrSet(resourceName, "statement"), - resource.TestCheckResourceAttrSet(resourceName, "is_secure"), - ), - }, - - // test - change comment - { - ConfigDirectory: acc.ConfigurationDirectory(configDirectory), - ConfigVariables: variableSet2, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test - updated"), - ), - }, - - // test - import - { - ConfigDirectory: acc.ConfigurationDirectory(configDirectory), - ConfigVariables: variableSet2, - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: ignoreDuringImport, - }, - }, - }) -} - -func TestAcc_Function_Javascript(t *testing.T) { - testAccFunction(t, "TestAcc_Function/javascript") -} - -func TestAcc_Function_SQL(t *testing.T) { - testAccFunction(t, "TestAcc_Function/sql") -} - -func TestAcc_Function_Java(t *testing.T) { - testAccFunction(t, "TestAcc_Function/java") -} - -func TestAcc_Function_Scala(t *testing.T) { - testAccFunction(t, "TestAcc_Function/scala") -} - -/* - Error: 391528 (42601): SQL compilation error: An active warehouse is required for creating Python UDFs. -func TestAcc_Function_Python(t *testing.T) { - testAccFunction(t, "TestAcc_Function/python") -} -*/ - -func TestAcc_Function_complex(t *testing.T) { - name := acc.TestClient().Ids.Alpha() - resourceName := "snowflake_function.f" - m := func() map[string]config.Variable { - return map[string]config.Variable{ - "name": config.StringVariable(name), - "database": config.StringVariable(acc.TestDatabaseName), - "schema": config.StringVariable(acc.TestSchemaName), - "comment": config.StringVariable("Terraform acceptance test"), - } - } - variableSet2 := m() - variableSet2["comment"] = config.StringVariable("Terraform acceptance test - updated") - - statement := "\t\tif (D <= 0) {\n\t\t\treturn 1;\n\t\t} else {\n\t\t\tvar result = 1;\n\t\t\tfor (var i = 2; i <= D; i++) {\n\t\t\t\tresult = result * i;\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n" - resource.Test(t, resource.TestCase{ - ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, - PreCheck: func() { acc.TestAccPreCheck(t) }, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - CheckDestroy: acc.CheckDestroy(t, resources.Function), - Steps: []resource.TestStep{ - { - ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Function/complex"), - ConfigVariables: m(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test"), - resource.TestCheckResourceAttr(resourceName, "statement", statement), - resource.TestCheckResourceAttr(resourceName, "arguments.#", "1"), - resource.TestCheckResourceAttr(resourceName, "arguments.0.name", "d"), - resource.TestCheckResourceAttr(resourceName, "arguments.0.type", "FLOAT"), - resource.TestCheckResourceAttr(resourceName, "return_behavior", "VOLATILE"), - resource.TestCheckResourceAttr(resourceName, "return_type", "FLOAT"), - resource.TestCheckResourceAttr(resourceName, "language", "JAVASCRIPT"), - resource.TestCheckResourceAttr(resourceName, "null_input_behavior", "CALLED ON NULL INPUT"), - - // computed attributes - resource.TestCheckResourceAttrSet(resourceName, "return_type"), - resource.TestCheckResourceAttrSet(resourceName, "statement"), - resource.TestCheckResourceAttrSet(resourceName, "is_secure"), - ), - }, - - // test - change comment - { - ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Function/complex"), - ConfigVariables: variableSet2, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test - updated"), - ), - }, - - // test - import - { - ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Function/complex"), - ConfigVariables: variableSet2, - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "language", - }, - }, - }, - }) -} - -// proves issue https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2490 -func TestAcc_Function_migrateFromVersion085(t *testing.T) { - id := acc.TestClient().Ids.RandomSchemaObjectIdentifierWithArguments(sdk.DataTypeVARCHAR) - name := id.Name() - comment := random.Comment() - resourceName := "snowflake_function.f" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { acc.TestAccPreCheck(t) }, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - CheckDestroy: acc.CheckDestroy(t, resources.Function), - - // Using the string config because of the validation in teststep_validate.go: - // teststep.Config.HasConfigurationFiles() returns true both for ConfigFile and ConfigDirectory. - // It returns false for Config. I don't understand why they have such a validation, but we will work around it later. - // Added as subtask SNOW-1057066 to SNOW-926148. - Steps: []resource.TestStep{ - { - PreConfig: func() { acc.SetV097CompatibleConfigPathEnv(t) }, - ExternalProviders: map[string]resource.ExternalProvider{ - "snowflake": { - VersionConstraint: "=0.85.0", - Source: "Snowflake-Labs/snowflake", - }, - }, - Config: functionConfig(acc.TestDatabaseName, acc.TestSchemaName, name, comment), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "id", fmt.Sprintf("%s|%s|%s|VARCHAR", acc.TestDatabaseName, acc.TestSchemaName, name)), - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - ), - }, - { - ExternalProviders: map[string]resource.ExternalProvider{ - "snowflake": { - VersionConstraint: "=0.94.1", - Source: "Snowflake-Labs/snowflake", - }, - }, - Config: functionConfig(acc.TestDatabaseName, acc.TestSchemaName, name, comment), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "id", id.FullyQualifiedName()), - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - ), - }, - }, - }) -} - -func TestAcc_Function_Rename(t *testing.T) { - oldId := acc.TestClient().Ids.RandomSchemaObjectIdentifierWithArguments(sdk.DataTypeVARCHAR) - newId := acc.TestClient().Ids.RandomSchemaObjectIdentifierWithArguments(sdk.DataTypeVARCHAR) - comment := random.Comment() - newComment := random.Comment() - resourceName := "snowflake_function.f" - - resource.Test(t, resource.TestCase{ - ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, - PreCheck: func() { acc.TestAccPreCheck(t) }, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - CheckDestroy: acc.CheckDestroy(t, resources.Function), - Steps: []resource.TestStep{ - { - Config: functionConfig(acc.TestDatabaseName, acc.TestSchemaName, oldId.Name(), comment), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", oldId.Name()), - resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", oldId.FullyQualifiedName()), - resource.TestCheckResourceAttr(resourceName, "comment", comment), - ), - }, - { - Config: functionConfig(acc.TestDatabaseName, acc.TestSchemaName, newId.Name(), newComment), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", newId.Name()), - resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", newId.FullyQualifiedName()), - resource.TestCheckResourceAttr(resourceName, "comment", newComment), - ), - ConfigPlanChecks: resource.ConfigPlanChecks{ - PreApply: []plancheck.PlanCheck{ - plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), - }, - PostApplyPostRefresh: []plancheck.PlanCheck{ - plancheck.ExpectEmptyPlan(), - }, - }, - }, - }, - }) -} - -func functionConfig(database string, schema string, name string, comment string) string { - return fmt.Sprintf(` -resource "snowflake_function" "f" { - database = "%[1]s" - schema = "%[2]s" - name = "%[3]s" - comment = "%[4]s" - return_type = "VARCHAR" - return_behavior = "IMMUTABLE" - statement = "SELECT PARAM" - - arguments { - name = "PARAM" - type = "VARCHAR" - } -} -`, database, schema, name, comment) -} - -// TODO [SNOW-1348103]: do not trim the data type (e.g. NUMBER(10, 2) -> NUMBER loses the information as shown in this test); finish the test -// proves https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2735 -func TestAcc_Function_gh2735(t *testing.T) { - t.Skipf("Will be fixed with functions redesign in SNOW-1348103") - name := acc.TestClient().Ids.Alpha() - resourceName := "snowflake_function.f" - - resource.Test(t, resource.TestCase{ - ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, - PreCheck: func() { acc.TestAccPreCheck(t) }, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - CheckDestroy: acc.CheckDestroy(t, resources.Function), - Steps: []resource.TestStep{ - { - Config: functionConfigGh2735(acc.TestDatabaseName, acc.TestSchemaName, name), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), - ), - }, - }, - }) -} - -func functionConfigGh2735(database string, schema string, name string) string { - return fmt.Sprintf(` -resource "snowflake_function" "f" { - database = "%[1]s" - schema = "%[2]s" - name = "%[3]s" - return_type = "TABLE (NUM1 NUMBER, NUM2 NUMBER(10,2))" - - statement = < 0 { - req.WithArguments(args) - } - - // read optional params - if v, ok := d.GetOk("execute_as"); ok { - if strings.ToUpper(v.(string)) == "OWNER" { - req.WithExecuteAs(sdk.ExecuteAsOwner) - } else if strings.ToUpper(v.(string)) == "CALLER" { - req.WithExecuteAs(sdk.ExecuteAsCaller) - } - } - if v, ok := d.GetOk("comment"); ok { - req.WithComment(v.(string)) - } - if v, ok := d.GetOk("secure"); ok { - req.WithSecure(v.(bool)) - } - if _, ok := d.GetOk("imports"); ok { - var imports []sdk.ProcedureImportRequest - for _, item := range d.Get("imports").([]interface{}) { - imports = append(imports, *sdk.NewProcedureImportRequest(item.(string))) - } - req.WithImports(imports) - } - - if err := client.Procedures.CreateForJava(ctx, req); err != nil { - return diag.FromErr(err) - } - d.SetId(id.FullyQualifiedName()) - return ReadContextProcedure(ctx, d, meta) -} - -func createJavaScriptProcedure(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*provider.Context).Client - name := d.Get("name").(string) - sc := d.Get("schema").(string) - database := d.Get("database").(string) - args, diags := getProcedureArguments(d) - if diags != nil { - return diags - } - argDataTypes := make([]sdk.DataType, len(args)) - for i, arg := range args { - argDataTypes[i] = arg.ArgDataTypeOld - } - id := sdk.NewSchemaObjectIdentifierWithArguments(database, sc, name, argDataTypes...) - - returnType := d.Get("return_type").(string) - returnDataType, diags := convertProcedureDataType(returnType) - if diags != nil { - return diags - } - procedureDefinition := d.Get("statement").(string) - req := sdk.NewCreateForJavaScriptProcedureRequestDefinitionWrapped(id.SchemaObjectId(), nil, procedureDefinition).WithResultDataTypeOld(sdk.LegacyDataTypeFrom(returnDataType)) - if len(args) > 0 { - req.WithArguments(args) - } - - // read optional params - if v, ok := d.GetOk("execute_as"); ok { - if strings.ToUpper(v.(string)) == "OWNER" { - req.WithExecuteAs(sdk.ExecuteAsOwner) - } else if strings.ToUpper(v.(string)) == "CALLER" { - req.WithExecuteAs(sdk.ExecuteAsCaller) - } - } - if v, ok := d.GetOk("null_input_behavior"); ok { - req.WithNullInputBehavior(sdk.NullInputBehavior(v.(string))) - } - if v, ok := d.GetOk("comment"); ok { - req.WithComment(v.(string)) - } - if v, ok := d.GetOk("secure"); ok { - req.WithSecure(v.(bool)) - } - - if err := client.Procedures.CreateForJavaScript(ctx, req); err != nil { - return diag.FromErr(err) - } - d.SetId(id.FullyQualifiedName()) - return ReadContextProcedure(ctx, d, meta) -} - -func createScalaProcedure(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*provider.Context).Client - name := d.Get("name").(string) - sc := d.Get("schema").(string) - database := d.Get("database").(string) - args, diags := getProcedureArguments(d) - if diags != nil { - return diags - } - argDataTypes := make([]sdk.DataType, len(args)) - for i, arg := range args { - argDataTypes[i] = arg.ArgDataTypeOld - } - id := sdk.NewSchemaObjectIdentifierWithArguments(database, sc, name, argDataTypes...) - - returns, diags := parseProcedureReturnsRequest(d.Get("return_type").(string)) - if diags != nil { - return diags - } - procedureDefinition := d.Get("statement").(string) - runtimeVersion := d.Get("runtime_version").(string) - packages := make([]sdk.ProcedurePackageRequest, 0) - for _, item := range d.Get("packages").([]interface{}) { - packages = append(packages, *sdk.NewProcedurePackageRequest(item.(string))) - } - handler := d.Get("handler").(string) - req := sdk.NewCreateForScalaProcedureRequest(id.SchemaObjectId(), *returns, runtimeVersion, packages, handler) - req.WithProcedureDefinitionWrapped(procedureDefinition) - if len(args) > 0 { - req.WithArguments(args) - } - - // read optional params - if v, ok := d.GetOk("execute_as"); ok { - if strings.ToUpper(v.(string)) == "OWNER" { - req.WithExecuteAs(sdk.ExecuteAsOwner) - } else if strings.ToUpper(v.(string)) == "CALLER" { - req.WithExecuteAs(sdk.ExecuteAsCaller) - } - } - if v, ok := d.GetOk("comment"); ok { - req.WithComment(v.(string)) - } - if v, ok := d.GetOk("secure"); ok { - req.WithSecure(v.(bool)) - } - if _, ok := d.GetOk("imports"); ok { - var imports []sdk.ProcedureImportRequest - for _, item := range d.Get("imports").([]interface{}) { - imports = append(imports, *sdk.NewProcedureImportRequest(item.(string))) - } - req.WithImports(imports) - } - - if err := client.Procedures.CreateForScala(ctx, req); err != nil { - return diag.FromErr(err) - } - d.SetId(id.FullyQualifiedName()) - return ReadContextProcedure(ctx, d, meta) -} - -func createSQLProcedure(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*provider.Context).Client - name := d.Get("name").(string) - sc := d.Get("schema").(string) - database := d.Get("database").(string) - args, diags := getProcedureArguments(d) - if diags != nil { - return diags - } - argDataTypes := make([]sdk.DataType, len(args)) - for i, arg := range args { - argDataTypes[i] = arg.ArgDataTypeOld - } - id := sdk.NewSchemaObjectIdentifierWithArguments(database, sc, name, argDataTypes...) - - returns, diags := parseProcedureSQLReturnsRequest(d.Get("return_type").(string)) - if diags != nil { - return diags - } - procedureDefinition := d.Get("statement").(string) - req := sdk.NewCreateForSQLProcedureRequestDefinitionWrapped(id.SchemaObjectId(), *returns, procedureDefinition) - if len(args) > 0 { - req.WithArguments(args) - } - - // read optional params - if v, ok := d.GetOk("execute_as"); ok { - if strings.ToUpper(v.(string)) == "OWNER" { - req.WithExecuteAs(sdk.ExecuteAsOwner) - } else if strings.ToUpper(v.(string)) == "CALLER" { - req.WithExecuteAs(sdk.ExecuteAsCaller) - } - } - if v, ok := d.GetOk("null_input_behavior"); ok { - req.WithNullInputBehavior(sdk.NullInputBehavior(v.(string))) - } - if v, ok := d.GetOk("comment"); ok { - req.WithComment(v.(string)) - } - if v, ok := d.GetOk("secure"); ok { - req.WithSecure(v.(bool)) - } - - if err := client.Procedures.CreateForSQL(ctx, req); err != nil { - return diag.FromErr(err) - } - d.SetId(id.FullyQualifiedName()) - return ReadContextProcedure(ctx, d, meta) -} - -func createPythonProcedure(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*provider.Context).Client - name := d.Get("name").(string) - sc := d.Get("schema").(string) - database := d.Get("database").(string) - args, diags := getProcedureArguments(d) - if diags != nil { - return diags - } - argDataTypes := make([]sdk.DataType, len(args)) - for i, arg := range args { - argDataTypes[i] = arg.ArgDataTypeOld - } - id := sdk.NewSchemaObjectIdentifierWithArguments(database, sc, name, argDataTypes...) - - returns, diags := parseProcedureReturnsRequest(d.Get("return_type").(string)) - if diags != nil { - return diags - } - procedureDefinition := d.Get("statement").(string) - runtimeVersion := d.Get("runtime_version").(string) - packages := make([]sdk.ProcedurePackageRequest, 0) - for _, item := range d.Get("packages").([]interface{}) { - packages = append(packages, *sdk.NewProcedurePackageRequest(item.(string))) - } - handler := d.Get("handler").(string) - req := sdk.NewCreateForPythonProcedureRequest(id.SchemaObjectId(), *returns, runtimeVersion, packages, handler) - req.WithProcedureDefinitionWrapped(procedureDefinition) - if len(args) > 0 { - req.WithArguments(args) - } - - // read optional params - if v, ok := d.GetOk("execute_as"); ok { - if strings.ToUpper(v.(string)) == "OWNER" { - req.WithExecuteAs(sdk.ExecuteAsOwner) - } else if strings.ToUpper(v.(string)) == "CALLER" { - req.WithExecuteAs(sdk.ExecuteAsCaller) - } - } - - // [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ] does not work for java, scala or python - // posted in docs-discuss channel, either docs need to be updated to reflect reality or this feature needs to be added - // https://snowflake.slack.com/archives/C6380540P/p1707511734666249 - // if v, ok := d.GetOk("null_input_behavior"); ok { - // req.WithNullInputBehavior(sdk.Pointer(sdk.NullInputBehavior(v.(string)))) - // } - - if v, ok := d.GetOk("comment"); ok { - req.WithComment(v.(string)) - } - if v, ok := d.GetOk("secure"); ok { - req.WithSecure(v.(bool)) - } - if _, ok := d.GetOk("imports"); ok { - var imports []sdk.ProcedureImportRequest - for _, item := range d.Get("imports").([]interface{}) { - imports = append(imports, *sdk.NewProcedureImportRequest(item.(string))) - } - req.WithImports(imports) - } - - if err := client.Procedures.CreateForPython(ctx, req); err != nil { - return diag.FromErr(err) - } - d.SetId(id.FullyQualifiedName()) - return ReadContextProcedure(ctx, d, meta) -} - -func ReadContextProcedure(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - diags := diag.Diagnostics{} - client := meta.(*provider.Context).Client - - id, err := sdk.ParseSchemaObjectIdentifierWithArguments(d.Id()) - if err != nil { - return diag.FromErr(err) - } - if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { - return diag.FromErr(err) - } - if err := d.Set("name", id.Name()); err != nil { - return diag.FromErr(err) - } - if err := d.Set("database", id.DatabaseName()); err != nil { - return diag.FromErr(err) - } - if err := d.Set("schema", id.SchemaName()); err != nil { - return diag.FromErr(err) - } - args := d.Get("arguments").([]interface{}) - argTypes := make([]string, len(args)) - for i, arg := range args { - argTypes[i] = arg.(map[string]interface{})["type"].(string) - } - procedureDetails, err := client.Procedures.Describe(ctx, id) - if err != nil { - // if procedure is not found then mark resource to be removed from state file during apply or refresh - d.SetId("") - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Warning, - Summary: "Describe procedure failed.", - Detail: fmt.Sprintf("Describe procedure failed: %v", err), - }, - } - } - for _, desc := range procedureDetails { - if desc.Value == nil { - continue - } - switch desc.Property { - case "signature": - // Format in Snowflake DB is: (argName argType, argName argType, ...) - args := strings.ReplaceAll(strings.ReplaceAll(*desc.Value, "(", ""), ")", "") - - if args != "" { // Do nothing for functions without arguments - argPairs := strings.Split(args, ", ") - var args []any - - for _, argPair := range argPairs { - argItem := strings.Split(argPair, " ") - - arg := map[string]interface{}{} - arg["name"] = argItem[0] - arg["type"] = argItem[1] - args = append(args, arg) - } - - if err := d.Set("arguments", args); err != nil { - return diag.FromErr(err) - } - } - case "null handling": - if err := d.Set("null_input_behavior", *desc.Value); err != nil { - return diag.FromErr(err) - } - case "body": - if err := d.Set("statement", *desc.Value); err != nil { - return diag.FromErr(err) - } - case "execute as": - if err := d.Set("execute_as", *desc.Value); err != nil { - return diag.FromErr(err) - } - case "returns": - if err := d.Set("return_type", *desc.Value); err != nil { - return diag.FromErr(err) - } - case "language": - if err := d.Set("language", *desc.Value); err != nil { - return diag.FromErr(err) - } - case "runtime_version": - if err := d.Set("runtime_version", *desc.Value); err != nil { - return diag.FromErr(err) - } - case "packages": - packagesString := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(*desc.Value, "[", ""), "]", ""), "'", "") - if packagesString != "" { // Do nothing for Java / Python functions without packages - packages := strings.Split(packagesString, ",") - if err := d.Set("packages", packages); err != nil { - return diag.FromErr(err) - } - } - case "imports": - importsString := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(*desc.Value, "[", ""), "]", ""), "'", ""), " ", "") - if importsString != "" { // Do nothing for Java functions without imports - imports := strings.Split(importsString, ",") - if err := d.Set("imports", imports); err != nil { - return diag.FromErr(err) - } - } - case "handler": - if err := d.Set("handler", *desc.Value); err != nil { - return diag.FromErr(err) - } - case "volatility": - if err := d.Set("return_behavior", *desc.Value); err != nil { - return diag.FromErr(err) - } - default: - log.Printf("[INFO] Unexpected procedure property %v returned from Snowflake with value %v", desc.Property, *desc.Value) - } - } - - procedure, err := client.Procedures.ShowByID(ctx, id) - if err != nil { - return diag.FromErr(err) - } - - if err := d.Set("secure", procedure.IsSecure); err != nil { - return diag.FromErr(err) - } - - if err := d.Set("comment", procedure.Description); err != nil { - return diag.FromErr(err) - } - - return diags -} - -func UpdateContextProcedure(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - client := meta.(*provider.Context).Client - - id, err := sdk.ParseSchemaObjectIdentifierWithArguments(d.Id()) - if err != nil { - return diag.FromErr(err) - } - - if d.HasChange("name") { - newId := sdk.NewSchemaObjectIdentifier(id.DatabaseName(), id.SchemaName(), d.Get("name").(string)) - newIdWithArguments := sdk.NewSchemaObjectIdentifierWithArguments(id.DatabaseName(), id.SchemaName(), d.Get("name").(string), id.ArgumentDataTypes()...) - - err := client.Procedures.Alter(ctx, sdk.NewAlterProcedureRequest(id).WithRenameTo(newId.WithoutArguments())) - if err != nil { - return diag.FromErr(err) - } - - d.SetId(newIdWithArguments.FullyQualifiedName()) - id = newIdWithArguments - } - - if d.HasChange("comment") { - comment := d.Get("comment") - if comment != "" { - if err := client.Procedures.Alter(ctx, sdk.NewAlterProcedureRequest(id).WithSet(*sdk.NewProcedureSetRequest().WithComment(comment.(string)))); err != nil { - return diag.FromErr(err) - } - } else { - if err := client.Procedures.Alter(ctx, sdk.NewAlterProcedureRequest(id).WithUnset(*sdk.NewProcedureUnsetRequest().WithComment(true))); err != nil { - return diag.FromErr(err) - } - } - } - - if d.HasChange("execute_as") { - req := sdk.NewAlterProcedureRequest(id) - executeAs := d.Get("execute_as").(string) - if strings.ToUpper(executeAs) == "OWNER" { - req.WithExecuteAs(sdk.ExecuteAsOwner) - } else if strings.ToUpper(executeAs) == "CALLER" { - req.WithExecuteAs(sdk.ExecuteAsCaller) - } - if err := client.Procedures.Alter(ctx, req); err != nil { - return diag.FromErr(err) - } - } - - return ReadContextProcedure(ctx, d, meta) -} - -func getProcedureArguments(d *schema.ResourceData) ([]sdk.ProcedureArgumentRequest, diag.Diagnostics) { - args := make([]sdk.ProcedureArgumentRequest, 0) - if v, ok := d.GetOk("arguments"); ok { - for _, arg := range v.([]interface{}) { - argName := arg.(map[string]interface{})["name"].(string) - argType := arg.(map[string]interface{})["type"].(string) - argDataType, diags := convertProcedureDataType(argType) - if diags != nil { - return nil, diags - } - args = append(args, sdk.ProcedureArgumentRequest{ArgName: argName, ArgDataTypeOld: sdk.LegacyDataTypeFrom(argDataType)}) - } - } - return args, nil -} - -func convertProcedureDataType(s string) (datatypes.DataType, diag.Diagnostics) { - dataType, err := datatypes.ParseDataType(s) - if err != nil { - return nil, diag.FromErr(err) - } - return dataType, nil -} - -func convertProcedureColumns(s string) ([]sdk.ProcedureColumn, diag.Diagnostics) { - pattern := regexp.MustCompile(`(\w+)\s+(\w+)`) - matches := pattern.FindAllStringSubmatch(s, -1) - var columns []sdk.ProcedureColumn - for _, match := range matches { - if len(match) == 3 { - dataType, err := datatypes.ParseDataType(match[2]) - if err != nil { - return nil, diag.FromErr(err) - } - columns = append(columns, sdk.ProcedureColumn{ - ColumnName: match[1], - ColumnDataTypeOld: sdk.LegacyDataTypeFrom(dataType), - }) - } - } - return columns, nil -} - -func parseProcedureReturnsRequest(s string) (*sdk.ProcedureReturnsRequest, diag.Diagnostics) { - returns := sdk.NewProcedureReturnsRequest() - if strings.HasPrefix(strings.ToLower(s), "table") { - columns, diags := convertProcedureColumns(s) - if diags != nil { - return nil, diags - } - var cr []sdk.ProcedureColumnRequest - for _, item := range columns { - cr = append(cr, *sdk.NewProcedureColumnRequest(item.ColumnName, nil).WithColumnDataTypeOld(item.ColumnDataTypeOld)) - } - returns.WithTable(*sdk.NewProcedureReturnsTableRequest().WithColumns(cr)) - } else { - returnDataType, diags := convertProcedureDataType(s) - if diags != nil { - return nil, diags - } - returns.WithResultDataType(*sdk.NewProcedureReturnsResultDataTypeRequest(nil).WithResultDataTypeOld(sdk.LegacyDataTypeFrom(returnDataType))) - } - return returns, nil -} - -func parseProcedureSQLReturnsRequest(s string) (*sdk.ProcedureSQLReturnsRequest, diag.Diagnostics) { - returns := sdk.NewProcedureSQLReturnsRequest() - if strings.HasPrefix(strings.ToLower(s), "table") { - columns, diags := convertProcedureColumns(s) - if diags != nil { - return nil, diags - } - var cr []sdk.ProcedureColumnRequest - for _, item := range columns { - cr = append(cr, *sdk.NewProcedureColumnRequest(item.ColumnName, nil).WithColumnDataTypeOld(item.ColumnDataTypeOld)) - } - returns.WithTable(*sdk.NewProcedureReturnsTableRequest().WithColumns(cr)) - } else { - returnDataType, diags := convertProcedureDataType(s) - if diags != nil { - return nil, diags - } - returns.WithResultDataType(*sdk.NewProcedureReturnsResultDataTypeRequest(nil).WithResultDataTypeOld(sdk.LegacyDataTypeFrom(returnDataType))) - } - return returns, nil -} diff --git a/pkg/resources/procedure_acceptance_test.go b/pkg/resources/procedure_acceptance_test.go deleted file mode 100644 index 1039ebc459..0000000000 --- a/pkg/resources/procedure_acceptance_test.go +++ /dev/null @@ -1,583 +0,0 @@ -package resources_test - -import ( - "fmt" - "strings" - "testing" - - acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" - "github.com/hashicorp/terraform-plugin-testing/config" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/plancheck" - "github.com/hashicorp/terraform-plugin-testing/tfversion" -) - -func testAccProcedure(t *testing.T, configDirectory string, args ...sdk.DataType) { - t.Helper() - - oldId := acc.TestClient().Ids.RandomSchemaObjectIdentifierWithArguments(args...) - newId := acc.TestClient().Ids.RandomSchemaObjectIdentifierWithArguments(args...) - - resourceName := "snowflake_procedure.p" - m := func() map[string]config.Variable { - return map[string]config.Variable{ - "name": config.StringVariable(oldId.Name()), - "database": config.StringVariable(acc.TestDatabaseName), - "schema": config.StringVariable(acc.TestSchemaName), - "comment": config.StringVariable("Terraform acceptance test"), - "execute_as": config.StringVariable("CALLER"), - } - } - variableSet2 := m() - variableSet2["name"] = config.StringVariable(newId.Name()) - variableSet2["comment"] = config.StringVariable("Terraform acceptance test - updated") - variableSet2["execute_as"] = config.StringVariable("OWNER") - - ignoreDuringImport := []string{"null_input_behavior"} - if strings.Contains(configDirectory, "/sql") { - ignoreDuringImport = append(ignoreDuringImport, "return_behavior") - } - - resource.Test(t, resource.TestCase{ - ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, - PreCheck: func() { acc.TestAccPreCheck(t) }, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - CheckDestroy: acc.CheckDestroy(t, resources.Procedure), - Steps: []resource.TestStep{ - { - ConfigDirectory: acc.ConfigurationDirectory(configDirectory), - ConfigVariables: m(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", oldId.Name()), - resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", oldId.FullyQualifiedName()), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test"), - resource.TestCheckResourceAttr(resourceName, "return_behavior", "VOLATILE"), - resource.TestCheckResourceAttr(resourceName, "execute_as", "CALLER"), - - // computed attributes - resource.TestCheckResourceAttrSet(resourceName, "return_type"), - resource.TestCheckResourceAttrSet(resourceName, "statement"), - resource.TestCheckResourceAttrSet(resourceName, "secure"), - ), - }, - - // test - rename + change comment and caller (proves https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2642) - { - ConfigDirectory: acc.ConfigurationDirectory(configDirectory), - ConfigVariables: variableSet2, - ConfigPlanChecks: resource.ConfigPlanChecks{ - PreApply: []plancheck.PlanCheck{ - plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), - }, - }, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", newId.Name()), - resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", newId.FullyQualifiedName()), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test - updated"), - resource.TestCheckResourceAttr(resourceName, "execute_as", "OWNER"), - ), - }, - - // test - import - { - ConfigDirectory: acc.ConfigurationDirectory(configDirectory), - ConfigVariables: variableSet2, - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: ignoreDuringImport, - }, - }, - }) -} - -func TestAcc_Procedure_SQL(t *testing.T) { - testAccProcedure(t, "TestAcc_Procedure/sql", sdk.DataTypeVARCHAR) -} - -/* -Error: 391531 (42601): SQL compilation error: An active warehouse is required for creating Python stored procedures. -func TestAcc_Procedure_Python(t *testing.T) { - testAccProcedure(t, "TestAcc_Procedure/python") -} -*/ - -func TestAcc_Procedure_Javascript(t *testing.T) { - testAccProcedure(t, "TestAcc_Procedure/javascript") -} - -func TestAcc_Procedure_Java(t *testing.T) { - testAccProcedure(t, "TestAcc_Procedure/java", sdk.DataTypeVARCHAR, sdk.DataTypeVARCHAR) -} - -func TestAcc_Procedure_Scala(t *testing.T) { - testAccProcedure(t, "TestAcc_Procedure/scala", sdk.DataTypeVARCHAR, sdk.DataTypeVARCHAR) -} - -func TestAcc_Procedure_complex(t *testing.T) { - name := acc.TestClient().Ids.Alpha() - resourceName := "snowflake_procedure.p" - m := func() map[string]config.Variable { - return map[string]config.Variable{ - "name": config.StringVariable(name), - "database": config.StringVariable(acc.TestDatabaseName), - "schema": config.StringVariable(acc.TestSchemaName), - "comment": config.StringVariable("Terraform acceptance test"), - "execute_as": config.StringVariable("CALLER"), - } - } - variableSet2 := m() - variableSet2["comment"] = config.StringVariable("Terraform acceptance test - updated") - - statement := "var x = 1\nreturn x\n" - resource.Test(t, resource.TestCase{ - ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, - PreCheck: func() { acc.TestAccPreCheck(t) }, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - CheckDestroy: acc.CheckDestroy(t, resources.Procedure), - Steps: []resource.TestStep{ - { - ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Procedure/complex"), - ConfigVariables: m(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test"), - resource.TestCheckResourceAttr(resourceName, "statement", statement), - resource.TestCheckResourceAttr(resourceName, "execute_as", "CALLER"), - resource.TestCheckResourceAttr(resourceName, "arguments.#", "2"), - resource.TestCheckResourceAttr(resourceName, "arguments.0.name", "arg1"), - resource.TestCheckResourceAttr(resourceName, "arguments.0.type", "VARCHAR"), - resource.TestCheckResourceAttr(resourceName, "arguments.1.name", "arg2"), - resource.TestCheckResourceAttr(resourceName, "arguments.1.type", "DATE"), - resource.TestCheckResourceAttr(resourceName, "null_input_behavior", "RETURNS NULL ON NULL INPUT"), - - // computed attributes - resource.TestCheckResourceAttrSet(resourceName, "return_type"), - resource.TestCheckResourceAttrSet(resourceName, "statement"), - resource.TestCheckResourceAttrSet(resourceName, "execute_as"), - resource.TestCheckResourceAttrSet(resourceName, "secure"), - ), - }, - - // test - change comment - { - ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Procedure/complex"), - ConfigVariables: variableSet2, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test - updated"), - ), - }, - - // test - import - { - ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Procedure/complex"), - ConfigVariables: variableSet2, - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "return_behavior", - }, - }, - }, - }) -} - -func TestAcc_Procedure_migrateFromVersion085(t *testing.T) { - id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() - name := id.Name() - resourceName := "snowflake_procedure.p" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { acc.TestAccPreCheck(t) }, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - CheckDestroy: acc.CheckDestroy(t, resources.Procedure), - - Steps: []resource.TestStep{ - { - PreConfig: func() { acc.SetV097CompatibleConfigPathEnv(t) }, - ExternalProviders: map[string]resource.ExternalProvider{ - "snowflake": { - VersionConstraint: "=0.85.0", - Source: "Snowflake-Labs/snowflake", - }, - }, - Config: procedureConfig(acc.TestDatabaseName, acc.TestSchemaName, name), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "id", fmt.Sprintf("%s|%s|%s|", acc.TestDatabaseName, acc.TestSchemaName, name)), - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - ), - }, - { - ExternalProviders: map[string]resource.ExternalProvider{ - "snowflake": { - VersionConstraint: "=0.94.1", - Source: "Snowflake-Labs/snowflake", - }, - }, - Config: procedureConfig(acc.TestDatabaseName, acc.TestSchemaName, name), - ConfigPlanChecks: resource.ConfigPlanChecks{ - PreApply: []plancheck.PlanCheck{plancheck.ExpectEmptyPlan()}, - }, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "id", id.FullyQualifiedName()), - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - ), - }, - }, - }) -} - -func procedureConfig(database string, schema string, name string) string { - return fmt.Sprintf(` -resource "snowflake_procedure" "p" { - database = "%[1]s" - schema = "%[2]s" - name = "%[3]s" - language = "JAVASCRIPT" - return_type = "VARCHAR" - statement = < --> **Note** Fields `STARTS WITH` and `LIMIT` are currently missing. They will be added in the future. - # {{.Name}} ({{.Type}}) {{ .Description | trimspace }} diff --git a/templates/guides/identifiers.md.tmpl b/templates/guides/identifiers.md.tmpl index 0af6936acf..e8ddac899a 100644 --- a/templates/guides/identifiers.md.tmpl +++ b/templates/guides/identifiers.md.tmpl @@ -15,7 +15,7 @@ For example, instead of writing ``` object_name = “\”${snowflake_table.database}\”.\”${snowflake_table.schema}\”.\”${snowflake_table.name}\”” # for procedures -object_name = “\”${snowflake_procedure.database}\”.\”${snowflake_procedure.schema}\”.\”${snowflake_procedure.name}\"(NUMBER, VARCHAR)” +object_name = “\”${snowflake_procedure_sql.database}\”.\”${snowflake_procedure_sql.schema}\”.\”${snowflake_procedure_sql.name}\"(NUMBER, VARCHAR)” ``` now we can write diff --git a/templates/resources/unsafe_execute.md.tmpl b/templates/resources/unsafe_execute.md.tmpl deleted file mode 100644 index 80794cba89..0000000000 --- a/templates/resources/unsafe_execute.md.tmpl +++ /dev/null @@ -1,40 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" -subcategory: "" -description: |- -{{ if gt (len (split .Description "")) 1 -}} -{{ index (split .Description "") 1 | plainmarkdown | trimspace | prefixlines " " }} -{{- else -}} -{{ .Description | plainmarkdown | trimspace | prefixlines " " }} -{{- end }} ---- - -# {{.Name}} ({{.Type}}) - -!> **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. 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. - -{{ .Description | trimspace }} - -{{ if .HasExample -}} -## Example Usage - -{{ tffile (printf "examples/resources/%s/resource.tf" .Name)}} --> **Note** Instead of using fully_qualified_name, you can reference objects managed outside Terraform by constructing a correct ID, consult [identifiers guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/identifiers#new-computed-fully-qualified-name-field-in-resources). - - -{{- end }} - -{{ .SchemaMarkdown | trimspace }} -{{- if .HasImport }} - -## Import - -Import is supported using the following syntax: - -{{ codefile "shell" (printf "examples/resources/%s/import.sh" .Name)}} -{{- end }} diff --git a/v1-preparations/GENERAL_TOPICS.md b/v1-preparations/GENERAL_TOPICS.md index 6370c637ee..1e8a3ed6d6 100644 --- a/v1-preparations/GENERAL_TOPICS.md +++ b/v1-preparations/GENERAL_TOPICS.md @@ -2,4 +2,4 @@ This is a (unfinished) list of additional topics, not being a part of the partic - object cloning: [#2211](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2211) - error handling improvements: [#2188](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2188), [#2091](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2091), [#1823](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1823) - generic function datasource/resource: [#2630](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2630), [#1630](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1630) -- open tofu: [#2939](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2939) \ No newline at end of file +- OpenTofu support: [#2939](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2939) diff --git a/v1-preparations/LIST_OF_PREVIEW_FEATURES_FOR_V1.md b/v1-preparations/LIST_OF_PREVIEW_FEATURES_FOR_V1.md index 2a58d9a9c7..93164a2c18 100644 --- a/v1-preparations/LIST_OF_PREVIEW_FEATURES_FOR_V1.md +++ b/v1-preparations/LIST_OF_PREVIEW_FEATURES_FOR_V1.md @@ -1,57 +1,71 @@ -[Preview features](../ROADMAP.md#preview-resourcesdatasources) for the V1: +# List of preview resources and data sources that are available in V1 -* [snowflake_current_account](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/current_account) (datasource) -* [snowflake_account_password_policy_attachment](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/account_password_policy_attachment) -* [snowflake_account_authentication_policy_attachment](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/account_authentication_policy_attachment) -* [snowflake_alert](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/alert) -* [snowflake_alerts](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/alerts) (datasource) -* [snowflake_authentication_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/authentication_policy) -* [snowflake_api_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/api_integration) -* [snowflake_cortex_search_service](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/cortex_search_service) -* [snowflake_cortex_search_services](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/cortex_search_services) (datasource) -* [snowflake_current_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/current_role) (datasource) -* [snowflake_database](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/database) (datasource) -* [snowflake_database_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/database_role) (datasource) -* [snowflake_dynamic_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/dynamic_table) -* [snowflake_dynamic_tables](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/dynamic_tables) (datasource) -* [snowflake_external_function](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/external_function) -* [snowflake_external_functions](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/external_functions) (datasource) -* [snowflake_external_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/external_table) -* [snowflake_external_tables](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/external_tables) (datasource) -* [snowflake_external_volume](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/external_volume) -* [snowflake_failover_group](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/failover_group) -* [snowflake_failover_groups](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/failover_groups) (datasource) -* [snowflake_file_format](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/file_format) -* [snowflake_file_formats](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/file_formats) (datasource) -* [snowflake_managed_account](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/managed_account) -* [snowflake_materialized_view](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/materialized_view) -* [snowflake_materialized_views](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/materialized_views) (datasource) -* [snowflake_network_policy_attachment](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/network_policy_attachment) -* [snowflake_network_rule](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/network_rule) -* [snowflake_email_notification_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/email_notification_integration) -* [snowflake_notification_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/notification_integration) -* [snowflake_object_parameter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/object_parameter) -* [snowflake_password_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/password_policy) -* [snowflake_pipe](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/pipe) -* [snowflake_pipes](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/pipes) (datasource) -* [snowflake_sequence](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/sequence) -* [snowflake_sequences](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/sequences) (datasource) -* [snowflake_share](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/share) -* [snowflake_shares](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/shares) (datasource) -* [snowflake_object_parameter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/object_parameter) -* [snowflake_parameters](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/parameters) (datasource) -* [snowflake_stage](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/stage) -* [snowflake_stages](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/stages) (datasource) -* [snowflake_storage_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/storage_integration) -* [snowflake_storage_integrations](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/storage_integrations) (datasource) -* [snowflake_system_generate_scim_access_token](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/system_generate_scim_access_token) (datasource) -* [snowflake_system_get_aws_sns_iam_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/system_get_aws_sns_iam_policy) (datasource) -* [snowflake_system_get_privatelink_config](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/system_get_privatelink_config) (datasource) -* [snowflake_system_get_snowflake_platform_info](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/data-sources/system_get_snowflake_platform_info) (datasource) -* [snowflake_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/table) -* [snowflake_tables](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/tables) (datasource) -* [snowflake_table_column_masking_policy_application](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/table_column_masking_policy_application) -* [snowflake_table_constraint](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/table_constraint) (undecided - may be deleted instead) -* [snowflake_user_public_keys](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/user_public_keys) -* [snowflake_user_password_policy_attachment](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/user_password_policy_attachment) -* [snowflake_user_authentication_policy_attachment](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/snowflake_user_authentication_policy_attachment) +[Preview features](../ROADMAP.md#preview-resourcesdata sources) for the V1: + +* [snowflake_current_account](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/current_account) (data source) +* [snowflake_account_password_policy_attachment](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/account_password_policy_attachment) +* [snowflake_account_authentication_policy_attachment](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/account_authentication_policy_attachment) +* [snowflake_alert](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/alert) +* [snowflake_alerts](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/alerts) (datasource) +* [snowflake_api_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/api_integration) +* [snowflake_authentication_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/authentication_policy) +* [snowflake_cortex_search_service](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/cortex_search_service) +* [snowflake_cortex_search_services](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/cortex_search_services) (data source) +* [snowflake_current_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/current_role) (data source) +* [snowflake_database](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/database) (data source) +* [snowflake_database_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/database_role) (data source) +* [snowflake_dynamic_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/dynamic_table) +* [snowflake_dynamic_tables](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/dynamic_tables) (data source) +* [snowflake_external_function](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/external_function) +* [snowflake_external_functions](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/external_functions) (data source) +* [snowflake_external_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/external_table) +* [snowflake_external_tables](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/external_tables) (data source) +* [snowflake_external_volume](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/external_volume) +* [snowflake_failover_group](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/failover_group) +* [snowflake_failover_groups](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/failover_groups) (data source) +* [snowflake_file_format](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/file_format) +* [snowflake_file_formats](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/file_formats) (data source) +* [snowflake_function_java](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/function_java) +* [snowflake_function_javascript](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/function_javascript) +* [snowflake_function_python](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/function_python) +* [snowflake_function_scala](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/function_scala) +* [snowflake_function_sql](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/function_sql) +* [snowflake_functions](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/functions) (data source) +* [snowflake_managed_account](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/managed_account) +* [snowflake_materialized_view](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/materialized_view) +* [snowflake_materialized_views](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/materialized_views) (data source) +* [snowflake_network_policy_attachment](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/network_policy_attachment) +* [snowflake_network_rule](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/network_rule) +* [snowflake_email_notification_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/email_notification_integration) +* [snowflake_notification_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/notification_integration) +* [snowflake_object_parameter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/object_parameter) +* [snowflake_password_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/password_policy) +* [snowflake_pipe](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/pipe) +* [snowflake_pipes](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/pipes) (data source) +* [snowflake_procedure_java](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/procedure_java) +* [snowflake_procedure_javascript](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/procedure_javascript) +* [snowflake_procedure_python](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/procedure_python) +* [snowflake_procedure_scala](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/procedure_scala) +* [snowflake_procedure_sql](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/procedure_sql) +* [snowflake_procedures](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/procedures) (data source) +* [snowflake_sequence](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/sequence) +* [snowflake_sequences](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/sequences) (data source) +* [snowflake_share](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/share) +* [snowflake_shares](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/shares) (data source) +* [snowflake_object_parameter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/object_parameter) +* [snowflake_parameters](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/parameters) (data source) +* [snowflake_stage](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/stage) +* [snowflake_stages](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/stages) (data source) +* [snowflake_storage_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/storage_integration) +* [snowflake_storage_integrations](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/storage_integrations) (data source) +* [snowflake_system_generate_scim_access_token](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/system_generate_scim_access_token) (data source) +* [snowflake_system_get_aws_sns_iam_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/system_get_aws_sns_iam_policy) (data source) +* [snowflake_system_get_privatelink_config](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/system_get_privatelink_config) (data source) +* [snowflake_system_get_snowflake_platform_info](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/system_get_snowflake_platform_info) (data source) +* [snowflake_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/table) +* [snowflake_tables](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/tables) (data source) +* [snowflake_table_column_masking_policy_application](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/table_column_masking_policy_application) +* [snowflake_table_constraint](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/table_constraint) (undecided - may be deleted instead) +* [snowflake_user_public_keys](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/user_public_keys) +* [snowflake_user_password_policy_attachment](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/user_password_policy_attachment) +* [snowflake_user_authentication_policy_attachment](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/snowflake_user_authentication_policy_attachment) diff --git a/v1-preparations/LIST_OF_REMOVED_RESOURCES_FOR_V1.md b/v1-preparations/LIST_OF_REMOVED_RESOURCES_FOR_V1.md index 645bb93568..77adbf8ce5 100644 --- a/v1-preparations/LIST_OF_REMOVED_RESOURCES_FOR_V1.md +++ b/v1-preparations/LIST_OF_REMOVED_RESOURCES_FOR_V1.md @@ -1,16 +1,14 @@ -Deprecated resources that are removed with the V1: +# List of deprecated resources and data sources that were removed with the V1 * [snowflake_database_old](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/database_old) * [snowflake_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/role) -* [snowflake_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/role) (datasource) +* [snowflake_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/role) (data source) +* [snowflake_roles](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/roles) (data source) * [snowflake_oauth_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/oauth_integration) * [snowflake_saml_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/saml_integration) * [snowflake_stream](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/stream) * [snowflake_tag_masking_policy_association](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/tag_masking_policy_association) * [snowflake_session_parameter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/session_parameter) - - -Deprecated resources that should be removed with the V1: * [snowflake_procedure](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/procedure) * [snowflake_function](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/function) -* [snowflake_unsafe_execute](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/unsafe_execute) - will be renamed +* [snowflake_unsafe_execute](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.97.0/docs/resources/unsafe_execute) diff --git a/v1-preparations/LIST_OF_STABLE_RESOURCES_FOR_V1.md b/v1-preparations/LIST_OF_STABLE_RESOURCES_FOR_V1.md index bb7a9d5426..ab1cfa6461 100644 --- a/v1-preparations/LIST_OF_STABLE_RESOURCES_FOR_V1.md +++ b/v1-preparations/LIST_OF_STABLE_RESOURCES_FOR_V1.md @@ -1,105 +1,91 @@ -We estimate the given list to be accurate, but it may be subject to small changes: +# List of stable resources and data sources available in V1 * Account - * [snowflake_account](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/account) - * [snowflake_accounts](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/accounts) (datasource) + * [snowflake_account](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/account) + * [snowflake_accounts](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/accounts) (data source) * Connection - * [snowflake_primary_connection](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/primary_connection) - * [snowflake_secondary_connection](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/secondary_connection) - * [snowflake_connections](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/connections) (datasource) + * [snowflake_primary_connection](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/primary_connection) + * [snowflake_secondary_connection](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/secondary_connection) + * [snowflake_connections](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/connections) (data source) * Database - * [snowflake_database](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/database) - * [snowflake_secondary_database](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/secondary_database) - * [snowflake_shared_database](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/shared_database) - * [snowflake_databases](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/databases) (datasource) + * [snowflake_database](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/database) + * [snowflake_secondary_database](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/secondary_database) + * [snowflake_shared_database](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/shared_database) + * [snowflake_databases](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/databases) (data source) * Database Role - * [snowflake_database_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/database_role) - * [snowflake_database_roles](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/database_roles) (datasource) -* Function (in progress) - * snowflake_function_java - * snowflake_function_javascript - * snowflake_function_python - * snowflake_function_scala - * snowflake_function_sql - * [snowflake_functions](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/functions) (datasource) + * [snowflake_database_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/database_role) + * [snowflake_database_roles](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/database_roles) (data source) * Grants - * [snowflake_grant_account_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/grant_account_role) - * [snowflake_grant_application_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/grant_application_role) - * [snowflake_grant_database_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/grant_database_role) - * [snowflake_grant_ownership](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/grant_ownership) - * [snowflake_grant_privileges_to_account_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/grant_privileges_to_account_role) - * [snowflake_grant_privileges_to_database_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/grant_privileges_to_database_role) - * [snowflake_grant_privileges_to_share](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/grant_privileges_to_share) - * [snowflake_grants](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/grants) (datasource) + * [snowflake_grant_account_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/grant_account_role) + * [snowflake_grant_application_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/grant_application_role) + * [snowflake_grant_database_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/grant_database_role) + * [snowflake_grant_ownership](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/grant_ownership) + * [snowflake_grant_privileges_to_account_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/grant_privileges_to_account_role) + * [snowflake_grant_privileges_to_database_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/grant_privileges_to_database_role) + * [snowflake_grant_privileges_to_share](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/grant_privileges_to_share) + * [snowflake_grants](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/grants) (data source) * Masking Policy - * [snowflake_masking_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/masking_policy) - * [snowflake_masking_policies](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/masking_policies) (datasource) + * [snowflake_masking_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/masking_policy) + * [snowflake_masking_policies](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/masking_policies) (data source) * Network Policy - * [snowflake_network_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/network_policy) - * [snowflake_network_policies](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/network_policies) (datasource) -* Procedure (in progress) - * snowflake_procedure_java - * snowflake_procedure_javascript - * snowflake_procedure_python - * snowflake_procedure_scala - * snowflake_procedure_sql - * [snowflake_procedures](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/procedures) (datasource) + * [snowflake_network_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/network_policy) + * [snowflake_network_policies](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/network_policies) (data source) * Resource Monitor - * [snowflake_resource_monitor](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/resource_monitor) - * [snowflake_resource_monitors](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/resource_monitors) (datasource) + * [snowflake_resource_monitor](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/resource_monitor) + * [snowflake_resource_monitors](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/resource_monitors) (data source) * Role - * [snowflake_account_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/account_role) - * [snowflake_roles](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/roles) (datasource) + * [snowflake_account_role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/account_role) + * [snowflake_account_roles](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/account_roles) (data source) * Row Access Policy - * [snowflake_row_access_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/row_access_policy) - * [snowflake_row_access_policies](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/row_access_policies) (datasource) + * [snowflake_row_access_policy](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/row_access_policy) + * [snowflake_row_access_policies](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/row_access_policies) (data source) * Schema - * [snowflake_schema](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/schema) - * [snowflake_schemas](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/schemas) (datasource) + * [snowflake_schema](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/schema) + * [snowflake_schemas](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/schemas) (data source) * Secret - * [snowflake_secret_with_client_credentials](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/secret_with_client_credentials) - * [snowflake_secret_with_authorization_code_grant](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/secret_with_authorization_code_grant) - * [snowflake_secret_with_basic_authentication](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/secret_with_basic_authentication) - * [snowflake_secret_with_generic_string](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/secret_with_generic_string) - * [snowflake_secrets](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/secrets) (datasource) + * [snowflake_secret_with_client_credentials](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/secret_with_client_credentials) + * [snowflake_secret_with_authorization_code_grant](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/secret_with_authorization_code_grant) + * [snowflake_secret_with_basic_authentication](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/secret_with_basic_authentication) + * [snowflake_secret_with_generic_string](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/secret_with_generic_string) + * [snowflake_secrets](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/secrets) (data source) * Security Integration - * [snowflake_api_authentication_integration_with_authorization_code_grant](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/api_authentication_integration_with_authorization_code_grant) - * [snowflake_api_authentication_integration_with_client_credentials](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/api_authentication_integration_with_client_credentials) - * [snowflake_api_authentication_integration_with_jwt_bearer](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/api_authentication_integration_with_jwt_bearer) - * [snowflake_external_oauth_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/external_oauth_integration) - * [snowflake_oauth_integration_for_custom_clients](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/oauth_integration_for_custom_clients) - * [snowflake_oauth_integration_for_partner_applications](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/oauth_integration_for_partner_applications) - * [snowflake_saml2_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/saml2_integration) - * [snowflake_scim_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/scim_integration) - * [snowflake_security_integrations](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/security_integrations) (datasource) -* Snowflake Parameters (in progress) - * [snowflake_account_parameter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/account_parameter) -* SQL Execute (in progress) - * \ (no name yet) + * [snowflake_api_authentication_integration_with_authorization_code_grant](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/api_authentication_integration_with_authorization_code_grant) + * [snowflake_api_authentication_integration_with_client_credentials](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/api_authentication_integration_with_client_credentials) + * [snowflake_api_authentication_integration_with_jwt_bearer](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/api_authentication_integration_with_jwt_bearer) + * [snowflake_external_oauth_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/external_oauth_integration) + * [snowflake_oauth_integration_for_custom_clients](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/oauth_integration_for_custom_clients) + * [snowflake_oauth_integration_for_partner_applications](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/oauth_integration_for_partner_applications) + * [snowflake_saml2_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/saml2_integration) + * [snowflake_scim_integration](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/scim_integration) + * [snowflake_security_integrations](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/security_integrations) (data source) +* Snowflake Parameters + * [snowflake_account_parameter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/account_parameter) +* SQL Execute + * [snowflake_execute](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/account_parameter) * Stream - * [snowflake_stream_on_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/stream_on_table) - * [snowflake_stream_on_external_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/stream_on_external_table) - * [snowflake_stream_on_directory_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/stream_on_directory_table) - * [snowflake_stream_on_view](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/stream_on_view) - * [snowflake_streams](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/streams) (datasource) + * [snowflake_stream_on_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/stream_on_table) + * [snowflake_stream_on_external_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/stream_on_external_table) + * [snowflake_stream_on_directory_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/stream_on_directory_table) + * [snowflake_stream_on_view](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/stream_on_view) + * [snowflake_streams](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/streams) (data source) * Streamlit - * [snowflake_streamlit](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/streamlit) - * [snowflake_streamlits](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/streamlits) (datasource) + * [snowflake_streamlit](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/streamlit) + * [snowflake_streamlits](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/streamlits) (data source) * Tag - * [snowflake_tag](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/tag) - * [snowflake_tag_association](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/tag_association) - * [snowflake_tags](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/tags) (datasource) + * [snowflake_tag](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/tag) + * [snowflake_tag_association](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/tag_association) + * [snowflake_tags](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/tags) (data source) * Task - * [snowflake_task](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/task) - * [snowflake_tasks](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/tasks) (datasource) + * [snowflake_task](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/task) + * [snowflake_tasks](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/tasks) (data source) * User - * [snowflake_user](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/user) - * [snowflake_service_user](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/service_user) - * [snowflake_legacy_service_user](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/legacy_service_user) - * [snowflake_users](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/users) (datasource) + * [snowflake_user](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/user) + * [snowflake_service_user](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/service_user) + * [snowflake_legacy_service_user](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/legacy_service_user) + * [snowflake_users](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/users) (data source) * View - * [snowflake_view](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/view) - * [snowflake_views](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/views) (datasource) + * [snowflake_view](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/view) + * [snowflake_views](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/views) (data source) * Warehouse - * [snowflake_warehouse](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/resources/warehouse) - * [snowflake_warehouse](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/0.98.0/docs/data-sources/warehouse) (datasource) + * [snowflake_warehouse](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/resources/warehouse) + * [snowflake_warehouse](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/1.0.0/docs/data-sources/warehouse) (data source)