From 77b3bf0c9998c05a30951730439f8b03a2e418ac Mon Sep 17 00:00:00 2001 From: Jakub Michalak Date: Wed, 20 Nov 2024 11:54:09 +0100 Subject: [PATCH] feat: Tag resource v1 (#3197) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rework tag resource for v1 - generate asserts and models - deprecate snowflake_tag_masking_policy_association - extract a parser for extracting schema object identifier list ## Test Plan * [x] acceptance tests * [ ] … ## References https://docs.snowflake.com/en/sql-reference/sql/create-tag https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1806 https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1443 https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1394 ## TODO - tag data source - tag association resource - asserting that ALTER MASKING POLICY [ IF EXISTS ] SET TAG doesn't alter the tag and vice-versa - we already unset masking policies from the tags on the tag part, but we're missing this on masking policies part - add acc tests, too --- MIGRATION_GUIDE.md | 24 ++ docs/index.md | 1 + docs/resources/account_role.md | 2 +- ...tegration_with_authorization_code_grant.md | 2 +- ...ion_integration_with_client_credentials.md | 2 +- ...hentication_integration_with_jwt_bearer.md | 2 +- docs/resources/authentication_policy.md | 6 +- docs/resources/database.md | 2 +- docs/resources/database_role.md | 4 +- docs/resources/external_oauth_integration.md | 2 +- docs/resources/external_volume.md | 4 +- docs/resources/legacy_service_user.md | 2 +- docs/resources/masking_policy.md | 6 +- docs/resources/network_policy.md | 2 +- .../oauth_integration_for_custom_clients.md | 2 +- ...th_integration_for_partner_applications.md | 2 +- docs/resources/primary_connection.md | 2 +- docs/resources/resource_monitor.md | 2 +- docs/resources/role.md | 2 +- docs/resources/row_access_policy.md | 6 +- docs/resources/saml2_integration.md | 2 +- docs/resources/scim_integration.md | 2 +- docs/resources/secondary_connection.md | 2 +- docs/resources/secondary_database.md | 2 +- .../secret_with_authorization_code_grant.md | 6 +- .../secret_with_basic_authentication.md | 6 +- .../secret_with_client_credentials.md | 6 +- docs/resources/secret_with_generic_string.md | 6 +- docs/resources/service_user.md | 2 +- docs/resources/shared_database.md | 2 +- docs/resources/stream_on_directory_table.md | 8 +- docs/resources/stream_on_external_table.md | 8 +- docs/resources/stream_on_table.md | 8 +- docs/resources/stream_on_view.md | 8 +- docs/resources/tag.md | 57 ++- .../tag_masking_policy_association.md | 2 + docs/resources/user.md | 2 +- docs/resources/view.md | 6 +- docs/resources/warehouse.md | 2 +- examples/additional/deprecated_resources.MD | 1 + examples/resources/snowflake_tag/import.sh | 3 +- examples/resources/snowflake_tag/resource.tf | 23 +- .../resourceassert/gen/resource_schema_def.go | 4 + .../assert/resourceassert/tag_resource_ext.go | 17 + .../assert/resourceassert/tag_resource_gen.go | 107 +++++ .../tag_show_output_ext.go | 26 ++ .../tag_show_output_gen.go | 5 - .../config/model/tag_model_ext.go | 26 ++ .../config/model/tag_model_gen.go | 123 ++++++ pkg/acceptance/helpers/tag_client.go | 7 + pkg/provider/resources/resources.go | 1 + pkg/resources/doc_helpers.go | 2 +- pkg/resources/helpers.go | 14 + pkg/resources/network_policy.go | 22 +- pkg/resources/tag.go | 251 ++++++++--- pkg/resources/tag_acceptance_test.go | 401 +++++++++++++++--- .../tag_association_acceptance_test.go | 39 +- .../tag_masking_policy_association.go | 4 +- ...king_policy_association_acceptance_test.go | 24 +- .../testdata/TestAcc_Tag/basic/test.tf | 7 - .../testdata/TestAcc_Tag/basic/variables.tf | 19 - .../basic/test.tf | 12 +- pkg/schemas/tag_gen.go | 4 +- ...urity_integrations_gen_integration_test.go | 2 +- templates/resources/tag.md.tmpl | 35 ++ 65 files changed, 1087 insertions(+), 306 deletions(-) create mode 100644 pkg/acceptance/bettertestspoc/assert/resourceassert/tag_resource_ext.go create mode 100644 pkg/acceptance/bettertestspoc/assert/resourceassert/tag_resource_gen.go create mode 100644 pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/tag_show_output_ext.go create mode 100644 pkg/acceptance/bettertestspoc/config/model/tag_model_ext.go create mode 100644 pkg/acceptance/bettertestspoc/config/model/tag_model_gen.go delete mode 100644 pkg/resources/testdata/TestAcc_Tag/basic/test.tf delete mode 100644 pkg/resources/testdata/TestAcc_Tag/basic/variables.tf create mode 100644 templates/resources/tag.md.tmpl diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 44079dfc95..2c75e172d8 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -7,6 +7,30 @@ across different versions. > [!TIP] > We highly recommend upgrading the versions one by one instead of bulk upgrades. +## v0.98.0 ➞ v0.99.0 + +### snowflake_tag_masking_policy_association deprecation +`snowflake_tag_masking_policy_association` is now deprecated in favor of `snowflake_tag` with a new `masking_policy` field. It will be removed with the v1 release. Please adjust your configuration files. + +### snowflake_tag resource changes +New fields: + - `masking_policies` field that holds the associated masking policies. + - `show_output` field that holds the response from SHOW TAGS. + +#### *(breaking change)* Changed fields in snowflake_masking_policy resource +Changed fields: + - `name` is now not marked as ForceNew. When this value is changed, the resource is renamed with `ALTER TAG`, instead of being recreated. + - `allowed_values` type was changed from list to set. This causes different ordering to be ignored. +State will be migrated automatically. + +#### *(breaking change)* Identifiers related changes +During [identifiers rework](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/ROADMAP.md#identifiers-rework) we decided to +migrate resource ids from pipe-separated to regular Snowflake identifiers (e.g. `|` -> `"".""`). Importing resources also needs to be adjusted (see [example](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/tag#import)). + +Also, we added diff suppress function that prevents Terraform from showing differences, when only quoting is different. + +No change is required, the state will be migrated automatically. + ## v0.97.0 ➞ v0.98.0 ### *(new feature)* snowflake_connections datasource diff --git a/docs/index.md b/docs/index.md index b0e0a17a04..518af87d7c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -366,6 +366,7 @@ provider "snowflake" { - [snowflake_role](./docs/resources/role) - use [snowflake_account_role](./docs/resources/account_role) instead - [snowflake_saml_integration](./docs/resources/saml_integration) - use [snowflake_saml2_integration](./docs/resources/saml2_integration) instead - [snowflake_stream](./docs/resources/stream) +- [snowflake_tag_masking_policy_association](./docs/resources/tag_masking_policy_association) ## Currently deprecated datasources diff --git a/docs/resources/account_role.md b/docs/resources/account_role.md index 1d5a3eec4e..e5c9a7068f 100644 --- a/docs/resources/account_role.md +++ b/docs/resources/account_role.md @@ -33,7 +33,7 @@ resource "snowflake_account_role" "complete" { ### Required -- `name` (String) Identifier for the role; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Identifier for the role; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/api_authentication_integration_with_authorization_code_grant.md b/docs/resources/api_authentication_integration_with_authorization_code_grant.md index af2ad46347..7ff4240139 100644 --- a/docs/resources/api_authentication_integration_with_authorization_code_grant.md +++ b/docs/resources/api_authentication_integration_with_authorization_code_grant.md @@ -45,7 +45,7 @@ resource "snowflake_api_authentication_integration_with_authorization_code_grant ### Required - `enabled` (Boolean) Specifies whether this security integration is enabled or disabled. -- `name` (String) Specifies the identifier (i.e. name) for the integration. This value must be unique in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Specifies the identifier (i.e. name) for the integration. This value must be unique in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `oauth_client_id` (String) Specifies the client ID for the OAuth application in the external service. - `oauth_client_secret` (String) Specifies the client secret for the OAuth application in the ServiceNow instance from the previous step. The connector uses this to request an access token from the ServiceNow instance. diff --git a/docs/resources/api_authentication_integration_with_client_credentials.md b/docs/resources/api_authentication_integration_with_client_credentials.md index 3813877b62..098bdf6ce8 100644 --- a/docs/resources/api_authentication_integration_with_client_credentials.md +++ b/docs/resources/api_authentication_integration_with_client_credentials.md @@ -43,7 +43,7 @@ resource "snowflake_api_authentication_integration_with_client_credentials" "tes ### Required - `enabled` (Boolean) Specifies whether this security integration is enabled or disabled. -- `name` (String) Specifies the identifier (i.e. name) for the integration. This value must be unique in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Specifies the identifier (i.e. name) for the integration. This value must be unique in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `oauth_client_id` (String) Specifies the client ID for the OAuth application in the external service. - `oauth_client_secret` (String) Specifies the client secret for the OAuth application in the ServiceNow instance from the previous step. The connector uses this to request an access token from the ServiceNow instance. diff --git a/docs/resources/api_authentication_integration_with_jwt_bearer.md b/docs/resources/api_authentication_integration_with_jwt_bearer.md index 9b2024cbd4..c4cdee9bdf 100644 --- a/docs/resources/api_authentication_integration_with_jwt_bearer.md +++ b/docs/resources/api_authentication_integration_with_jwt_bearer.md @@ -46,7 +46,7 @@ resource "snowflake_api_authentication_integration_with_jwt_bearer" "test" { ### Required - `enabled` (Boolean) Specifies whether this security integration is enabled or disabled. -- `name` (String) Specifies the identifier (i.e. name) for the integration. This value must be unique in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Specifies the identifier (i.e. name) for the integration. This value must be unique in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `oauth_assertion_issuer` (String) - `oauth_client_id` (String) Specifies the client ID for the OAuth application in the external service. - `oauth_client_secret` (String) Specifies the client secret for the OAuth application in the ServiceNow instance from the previous step. The connector uses this to request an access token from the ServiceNow instance. diff --git a/docs/resources/authentication_policy.md b/docs/resources/authentication_policy.md index 99b64f0cfe..e53ccb42ca 100644 --- a/docs/resources/authentication_policy.md +++ b/docs/resources/authentication_policy.md @@ -41,9 +41,9 @@ resource "snowflake_authentication_policy" "complete" { ### Required -- `database` (String) The database in which to create the authentication policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) Specifies the identifier for the authentication policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `schema` (String) The schema in which to create the authentication policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the authentication policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) Specifies the identifier for the authentication policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `schema` (String) The schema in which to create the authentication policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/database.md b/docs/resources/database.md index a8a1596e1c..998d9ca232 100644 --- a/docs/resources/database.md +++ b/docs/resources/database.md @@ -84,7 +84,7 @@ resource "snowflake_database" "primary" { ### Required -- `name` (String) Specifies the identifier for the database; must be unique for your account. As a best practice for [Database Replication and Failover](https://docs.snowflake.com/en/user-guide/db-replication-intro), it is recommended to give each secondary database the same name as its primary database. This practice supports referencing fully-qualified objects (i.e. '..') by other objects in the same database, such as querying a fully-qualified table name in a view. If a secondary database has a different name from the primary database, then these object references would break in the secondary database. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Specifies the identifier for the database; must be unique for your account. As a best practice for [Database Replication and Failover](https://docs.snowflake.com/en/user-guide/db-replication-intro), it is recommended to give each secondary database the same name as its primary database. This practice supports referencing fully-qualified objects (i.e. '..') by other objects in the same database, such as querying a fully-qualified table name in a view. If a secondary database has a different name from the primary database, then these object references would break in the secondary database. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/database_role.md b/docs/resources/database_role.md index 0774975d4b..f0097ccb89 100644 --- a/docs/resources/database_role.md +++ b/docs/resources/database_role.md @@ -32,8 +32,8 @@ resource "snowflake_database_role" "test_database_role" { ### Required -- `database` (String) The database in which to create the database role. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) Specifies the identifier for the database role. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the database role. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) Specifies the identifier for the database role. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/external_oauth_integration.md b/docs/resources/external_oauth_integration.md index b76fc63e59..2d6473cfd9 100644 --- a/docs/resources/external_oauth_integration.md +++ b/docs/resources/external_oauth_integration.md @@ -70,7 +70,7 @@ resource "snowflake_external_oauth_integration" "test" { - `external_oauth_snowflake_user_mapping_attribute` (String) Indicates which Snowflake user record attribute should be used to map the access token to a Snowflake user record. Valid values are (case-insensitive): `LOGIN_NAME` | `EMAIL_ADDRESS`. - `external_oauth_token_user_mapping_claim` (Set of String) Specifies the access token claim or claims that can be used to map the access token to a Snowflake user record. If removed from the config, the resource is recreated. - `external_oauth_type` (String) Specifies the OAuth 2.0 authorization server to be Okta, Microsoft Azure AD, Ping Identity PingFederate, or a Custom OAuth 2.0 authorization server. Valid values are (case-insensitive): `OKTA` | `AZURE` | `PING_FEDERATE` | `CUSTOM`. -- `name` (String) Specifies the name of the External Oath integration. This name follows the rules for Object Identifiers. The name should be unique among security integrations in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Specifies the name of the External Oath integration. This name follows the rules for Object Identifiers. The name should be unique among security integrations in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/external_volume.md b/docs/resources/external_volume.md index 5c5a0f8cca..249d2a60f4 100644 --- a/docs/resources/external_volume.md +++ b/docs/resources/external_volume.md @@ -16,7 +16,7 @@ Resource used to manage external volume objects. For more information, check [ex ### Required -- `name` (String) Identifier for the external volume; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Identifier for the external volume; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `storage_location` (Block List, Min: 1) List of named cloud storage locations in different regions and, optionally, cloud platforms. Minimum 1 required. The order of the list is important as it impacts the active storage location, and updates will be triggered if it changes. Note that not all parameter combinations are valid as they depend on the given storage_provider. Consult [the docs](https://docs.snowflake.com/en/sql-reference/sql/create-external-volume#cloud-provider-parameters-cloudproviderparams) for more details on this. (see [below for nested schema](#nestedblock--storage_location)) ### Optional @@ -37,7 +37,7 @@ Resource used to manage external volume objects. For more information, check [ex Required: - `storage_base_url` (String) Specifies the base URL for your cloud storage location. -- `storage_location_name` (String) Name of the storage location. Must be unique for the external volume. Do not use the name `terraform_provider_sentinel_storage_location` - this is reserved for the provider for performing update operations. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `storage_location_name` (String) Name of the storage location. Must be unique for the external volume. Do not use the name `terraform_provider_sentinel_storage_location` - this is reserved for the provider for performing update operations. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `storage_provider` (String) Specifies the cloud storage provider that stores your data files. Valid values are (case-insensitive): `GCS` | `AZURE` | `S3` | `S3GOV`. Optional: diff --git a/docs/resources/legacy_service_user.md b/docs/resources/legacy_service_user.md index 820ef8957a..57ef504370 100644 --- a/docs/resources/legacy_service_user.md +++ b/docs/resources/legacy_service_user.md @@ -123,7 +123,7 @@ resource "snowflake_legacy_service_user" "u" { ### Required -- `name` (String) Name of the user. Note that if you do not supply login_name this will be used as login_name. Check the [docs](https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#required-parameters). Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Name of the user. Note that if you do not supply login_name this will be used as login_name. Check the [docs](https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#required-parameters). Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/masking_policy.md b/docs/resources/masking_policy.md index 0806f24147..aa9bb89af4 100644 --- a/docs/resources/masking_policy.md +++ b/docs/resources/masking_policy.md @@ -86,10 +86,10 @@ EOF - `argument` (Block List, Min: 1) List of the arguments for the masking policy. The first column and its data type always indicate the column data type values to mask or tokenize in the subsequent policy conditions. Note that you can not specify a virtual column as the first column argument in a conditional masking policy. (see [below for nested schema](#nestedblock--argument)) - `body` (String) Specifies the SQL expression that transforms the data. To mitigate permadiff on this field, the provider replaces blank characters with a space. This can lead to false positives in cases where a change in case or run of whitespace is semantically significant. -- `database` (String) The database in which to create the masking policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) Specifies the identifier for the masking policy; must be unique for the database and schema in which the masking policy is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the masking policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) Specifies the identifier for the masking policy; must be unique for the database and schema in which the masking policy is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `return_data_type` (String) The return data type must match the input data type of the first column that is specified as an input column. For more information about data types, check [Snowflake docs](https://docs.snowflake.com/en/sql-reference/intro-summary-data-types). -- `schema` (String) The schema in which to create the masking policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `schema` (String) The schema in which to create the masking policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/network_policy.md b/docs/resources/network_policy.md index 706acad399..aaa3bc02c5 100644 --- a/docs/resources/network_policy.md +++ b/docs/resources/network_policy.md @@ -37,7 +37,7 @@ resource "snowflake_network_policy" "complete" { ### Required -- `name` (String) Specifies the identifier for the network policy; must be unique for the account in which the network policy is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Specifies the identifier for the network policy; must be unique for the account in which the network policy is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/oauth_integration_for_custom_clients.md b/docs/resources/oauth_integration_for_custom_clients.md index c6f427e7b3..2ed8b0521e 100644 --- a/docs/resources/oauth_integration_for_custom_clients.md +++ b/docs/resources/oauth_integration_for_custom_clients.md @@ -50,7 +50,7 @@ resource "snowflake_oauth_integration_for_custom_clients" "complete" { ### Required - `blocked_roles_list` (Set of String) A set of Snowflake roles that a user cannot explicitly consent to using after authenticating. -- `name` (String) Specifies the name of the OAuth integration. This name follows the rules for Object Identifiers. The name should be unique among security integrations in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Specifies the name of the OAuth integration. This name follows the rules for Object Identifiers. The name should be unique among security integrations in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `oauth_client_type` (String) Specifies the type of client being registered. Snowflake supports both confidential and public clients. Valid options are: `PUBLIC` | `CONFIDENTIAL`. - `oauth_redirect_uri` (String) Specifies the client URI. After a user is authenticated, the web browser is redirected to this URI. diff --git a/docs/resources/oauth_integration_for_partner_applications.md b/docs/resources/oauth_integration_for_partner_applications.md index ae75802d54..0d9f1c139e 100644 --- a/docs/resources/oauth_integration_for_partner_applications.md +++ b/docs/resources/oauth_integration_for_partner_applications.md @@ -43,7 +43,7 @@ resource "snowflake_oauth_integration_for_partner_applications" "test" { ### Required - `blocked_roles_list` (Set of String) A set of Snowflake roles that a user cannot explicitly consent to using after authenticating. -- `name` (String) Specifies the name of the OAuth integration. This name follows the rules for Object Identifiers. The name should be unique among security integrations in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Specifies the name of the OAuth integration. This name follows the rules for Object Identifiers. The name should be unique among security integrations in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `oauth_client` (String) Creates an OAuth interface between Snowflake and a partner application. Valid options are: `LOOKER` | `TABLEAU_DESKTOP` | `TABLEAU_SERVER`. ### Optional diff --git a/docs/resources/primary_connection.md b/docs/resources/primary_connection.md index 6227f4e338..27d726a362 100644 --- a/docs/resources/primary_connection.md +++ b/docs/resources/primary_connection.md @@ -43,7 +43,7 @@ and then import it as the `snowflake_secondary_connection`. ### Required -- `name` (String) String that specifies the identifier (i.e. name) for the connection. Must start with an alphabetic character and may only contain letters, decimal digits (0-9), and underscores (_). For a primary connection, the name must be unique across connection names and account names in the organization. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) String that specifies the identifier (i.e. name) for the connection. Must start with an alphabetic character and may only contain letters, decimal digits (0-9), and underscores (_). For a primary connection, the name must be unique across connection names and account names in the organization. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/resource_monitor.md b/docs/resources/resource_monitor.md index dea0fa29b3..03ade24eea 100644 --- a/docs/resources/resource_monitor.md +++ b/docs/resources/resource_monitor.md @@ -57,7 +57,7 @@ resource "snowflake_resource_monitor" "complete" { ### Required -- `name` (String) Identifier for the resource monitor; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Identifier for the resource monitor; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/role.md b/docs/resources/role.md index 4b20e2d2c3..cf79b2cdf3 100644 --- a/docs/resources/role.md +++ b/docs/resources/role.md @@ -34,7 +34,7 @@ resource "snowflake_role" "complete" { ### Required -- `name` (String) Identifier for the role; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Identifier for the role; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/row_access_policy.md b/docs/resources/row_access_policy.md index 3bd3afa7d3..1d1951dcb0 100644 --- a/docs/resources/row_access_policy.md +++ b/docs/resources/row_access_policy.md @@ -44,9 +44,9 @@ resource "snowflake_row_access_policy" "example_row_access_policy" { - `argument` (Block List, Min: 1) List of the arguments for the row access policy. A signature specifies a set of attributes that must be considered to determine whether the row is accessible. The attribute values come from the database object (e.g. table or view) to be protected by the row access policy. If any argument name or type is changed, the resource is recreated. (see [below for nested schema](#nestedblock--argument)) - `body` (String) Specifies the SQL expression. The expression can be any boolean-valued SQL expression. To mitigate permadiff on this field, the provider replaces blank characters with a space. This can lead to false positives in cases where a change in case or run of whitespace is semantically significant. -- `database` (String) The database in which to create the row access policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) Specifies the identifier for the row access policy; must be unique for the database and schema in which the row access policy is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `schema` (String) The schema in which to create the row access policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the row access policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) Specifies the identifier for the row access policy; must be unique for the database and schema in which the row access policy is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `schema` (String) The schema in which to create the row access policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/saml2_integration.md b/docs/resources/saml2_integration.md index 133eb33f4c..38e45dc4d8 100644 --- a/docs/resources/saml2_integration.md +++ b/docs/resources/saml2_integration.md @@ -53,7 +53,7 @@ resource "snowflake_saml2_integration" "test" { ### Required -- `name` (String) Specifies the name of the SAML2 integration. This name follows the rules for Object Identifiers. The name should be unique among security integrations in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Specifies the name of the SAML2 integration. This name follows the rules for Object Identifiers. The name should be unique among security integrations in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `saml2_issuer` (String) The string containing the IdP EntityID / Issuer. - `saml2_provider` (String) The string describing the IdP. Valid options are: `OKTA` | `ADFS` | `CUSTOM`. - `saml2_sso_url` (String) The string containing the IdP SSO URL, where the user should be redirected by Snowflake (the Service Provider) with a SAML AuthnRequest message. diff --git a/docs/resources/scim_integration.md b/docs/resources/scim_integration.md index 19985cf3e1..c3e8ee35a9 100644 --- a/docs/resources/scim_integration.md +++ b/docs/resources/scim_integration.md @@ -41,7 +41,7 @@ resource "snowflake_scim_integration" "test" { ### Required - `enabled` (Boolean) Specify whether the security integration is enabled. -- `name` (String) String that specifies the identifier (i.e. name) for the integration; must be unique in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) String that specifies the identifier (i.e. name) for the integration; must be unique in your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `run_as_role` (String) Specify the SCIM role in Snowflake that owns any users and roles that are imported from the identity provider into Snowflake using SCIM. Provider assumes that the specified role is already provided. Valid options are: `OKTA_PROVISIONER` | `AAD_PROVISIONER` | `GENERIC_SCIM_PROVISIONER`. - `scim_client` (String) Specifies the client type for the scim integration. Valid options are: `OKTA` | `AZURE` | `GENERIC`. diff --git a/docs/resources/secondary_connection.md b/docs/resources/secondary_connection.md index c9b9ee9416..416e593392 100644 --- a/docs/resources/secondary_connection.md +++ b/docs/resources/secondary_connection.md @@ -43,7 +43,7 @@ and then import it as the `snowflake_primary_connection`. ### Required - `as_replica_of` (String) Specifies the identifier for a primary connection from which to create a replica (i.e. a secondary connection). -- `name` (String) String that specifies the identifier (i.e. name) for the connection. Must start with an alphabetic character and may only contain letters, decimal digits (0-9), and underscores (_). For a secondary connection, the name must match the name of its primary connection. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) String that specifies the identifier (i.e. name) for the connection. Must start with an alphabetic character and may only contain letters, decimal digits (0-9), and underscores (_). For a secondary connection, the name must match the name of its primary connection. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/secondary_database.md b/docs/resources/secondary_database.md index 8e3c22cd65..95fbaf8815 100644 --- a/docs/resources/secondary_database.md +++ b/docs/resources/secondary_database.md @@ -93,7 +93,7 @@ resource "snowflake_task" "refresh_secondary_database" { ### Required - `as_replica_of` (String) A fully qualified path to a database to create a replica from. A fully qualified path follows the format of `""."".""`. -- `name` (String) Specifies the identifier for the database; must be unique for your account. As a best practice for [Database Replication and Failover](https://docs.snowflake.com/en/user-guide/db-replication-intro), it is recommended to give each secondary database the same name as its primary database. This practice supports referencing fully-qualified objects (i.e. '..') by other objects in the same database, such as querying a fully-qualified table name in a view. If a secondary database has a different name from the primary database, then these object references would break in the secondary database. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Specifies the identifier for the database; must be unique for your account. As a best practice for [Database Replication and Failover](https://docs.snowflake.com/en/user-guide/db-replication-intro), it is recommended to give each secondary database the same name as its primary database. This practice supports referencing fully-qualified objects (i.e. '..') by other objects in the same database, such as querying a fully-qualified table name in a view. If a secondary database has a different name from the primary database, then these object references would break in the secondary database. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/secret_with_authorization_code_grant.md b/docs/resources/secret_with_authorization_code_grant.md index ff13b763fc..3217db19dc 100644 --- a/docs/resources/secret_with_authorization_code_grant.md +++ b/docs/resources/secret_with_authorization_code_grant.md @@ -44,11 +44,11 @@ resource "snowflake_secret_with_authorization_code_grant" "test" { ### Required - `api_authentication` (String) Specifies the name value of the Snowflake security integration that connects Snowflake to an external service. -- `database` (String) The database in which to create the secret Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) String that specifies the identifier (i.e. name) for the secret, must be unique in your schema. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the secret Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) String that specifies the identifier (i.e. name) for the secret, must be unique in your schema. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `oauth_refresh_token` (String, Sensitive) Specifies the token as a string that is used to obtain a new access token from the OAuth authorization server when the access token expires. External changes for this field won't be detected. In case you want to apply external changes, you can re-create the resource manually using "terraform taint". - `oauth_refresh_token_expiry_time` (String) Specifies the timestamp as a string when the OAuth refresh token expires. Accepted string formats: YYYY-MM-DD, YYYY-MM-DD HH:MI, YYYY-MM-DD HH:MI:SS, YYYY-MM-DD HH:MI -- `schema` (String) The schema in which to create the secret. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `schema` (String) The schema in which to create the secret. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/secret_with_basic_authentication.md b/docs/resources/secret_with_basic_authentication.md index e7078451d4..66d99164b3 100644 --- a/docs/resources/secret_with_basic_authentication.md +++ b/docs/resources/secret_with_basic_authentication.md @@ -41,10 +41,10 @@ resource "snowflake_secret_with_basic_authentication" "test" { ### Required -- `database` (String) The database in which to create the secret Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) String that specifies the identifier (i.e. name) for the secret, must be unique in your schema. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the secret Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) String that specifies the identifier (i.e. name) for the secret, must be unique in your schema. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `password` (String, Sensitive) Specifies the password value to store in the secret. External changes for this field won't be detected. In case you want to apply external changes, you can re-create the resource manually using "terraform taint". -- `schema` (String) The schema in which to create the secret. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `schema` (String) The schema in which to create the secret. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `username` (String, Sensitive) Specifies the username value to store in the secret. ### Optional diff --git a/docs/resources/secret_with_client_credentials.md b/docs/resources/secret_with_client_credentials.md index d827292373..0e5ad14903 100644 --- a/docs/resources/secret_with_client_credentials.md +++ b/docs/resources/secret_with_client_credentials.md @@ -42,10 +42,10 @@ resource "snowflake_secret_with_client_credentials" "test" { ### Required - `api_authentication` (String) Specifies the name value of the Snowflake security integration that connects Snowflake to an external service. -- `database` (String) The database in which to create the secret Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) String that specifies the identifier (i.e. name) for the secret, must be unique in your schema. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the secret Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) String that specifies the identifier (i.e. name) for the secret, must be unique in your schema. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `oauth_scopes` (Set of String) Specifies a list of scopes to use when making a request from the OAuth server by a role with USAGE on the integration during the OAuth client credentials flow. -- `schema` (String) The schema in which to create the secret. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `schema` (String) The schema in which to create the secret. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/secret_with_generic_string.md b/docs/resources/secret_with_generic_string.md index 3b1579c6ce..408e71592d 100644 --- a/docs/resources/secret_with_generic_string.md +++ b/docs/resources/secret_with_generic_string.md @@ -39,9 +39,9 @@ resource "snowflake_secret_with_generic_string" "test" { ### Required -- `database` (String) The database in which to create the secret Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) String that specifies the identifier (i.e. name) for the secret, must be unique in your schema. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `schema` (String) The schema in which to create the secret. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the secret Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) String that specifies the identifier (i.e. name) for the secret, must be unique in your schema. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `schema` (String) The schema in which to create the secret. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `secret_string` (String, Sensitive) Specifies the string to store in the secret. The string can be an API token or a string of sensitive value that can be used in the handler code of a UDF or stored procedure. For details, see [Creating and using an external access integration](https://docs.snowflake.com/en/developer-guide/external-network-access/creating-using-external-network-access). You should not use this property to store any kind of OAuth token; use one of the other secret types for your OAuth use cases. External changes for this field won't be detected. In case you want to apply external changes, you can re-create the resource manually using "terraform taint". ### Optional diff --git a/docs/resources/service_user.md b/docs/resources/service_user.md index dd74130322..eba0597df1 100644 --- a/docs/resources/service_user.md +++ b/docs/resources/service_user.md @@ -120,7 +120,7 @@ resource "snowflake_service_user" "u" { ### Required -- `name` (String) Name of the user. Note that if you do not supply login_name this will be used as login_name. Check the [docs](https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#required-parameters). Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Name of the user. Note that if you do not supply login_name this will be used as login_name. Check the [docs](https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#required-parameters). Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/shared_database.md b/docs/resources/shared_database.md index 09cf18a2fc..574ff4f28c 100644 --- a/docs/resources/shared_database.md +++ b/docs/resources/shared_database.md @@ -76,7 +76,7 @@ resource "snowflake_shared_database" "test" { ### Required - `from_share` (String) A fully qualified path to a share from which the database will be created. A fully qualified path follows the format of `""."".""`. -- `name` (String) Specifies the identifier for the database; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Specifies the identifier for the database; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/stream_on_directory_table.md b/docs/resources/stream_on_directory_table.md index ec6abfdb5e..1913610345 100644 --- a/docs/resources/stream_on_directory_table.md +++ b/docs/resources/stream_on_directory_table.md @@ -56,10 +56,10 @@ resource "snowflake_stream_on_directory_table" "stream" { ### Required -- `database` (String) The database in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) Specifies the identifier for the stream; must be unique for the database and schema in which the stream is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `schema` (String) The schema in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `stage` (String) Specifies an identifier for the stage the stream will monitor. Due to Snowflake limitations, the provider can not read the stage's database and schema. For stages, Snowflake returns only partially qualified name instead of fully qualified name. Please use stages located in the same schema as the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) Specifies the identifier for the stream; must be unique for the database and schema in which the stream is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `schema` (String) The schema in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `stage` (String) Specifies an identifier for the stage the stream will monitor. Due to Snowflake limitations, the provider can not read the stage's database and schema. For stages, Snowflake returns only partially qualified name instead of fully qualified name. Please use stages located in the same schema as the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/stream_on_external_table.md b/docs/resources/stream_on_external_table.md index e885a93a91..a01c1a93bc 100644 --- a/docs/resources/stream_on_external_table.md +++ b/docs/resources/stream_on_external_table.md @@ -70,10 +70,10 @@ resource "snowflake_stream_on_external_table" "stream" { ### Required -- `database` (String) The database in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `external_table` (String) Specifies an identifier for the external table the stream will monitor. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) Specifies the identifier for the stream; must be unique for the database and schema in which the stream is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `schema` (String) The schema in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `external_table` (String) Specifies an identifier for the external table the stream will monitor. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) Specifies the identifier for the stream; must be unique for the database and schema in which the stream is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `schema` (String) The schema in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/stream_on_table.md b/docs/resources/stream_on_table.md index 99ec11a4be..244f5b97a5 100644 --- a/docs/resources/stream_on_table.md +++ b/docs/resources/stream_on_table.md @@ -54,10 +54,10 @@ resource "snowflake_stream_on_table" "stream" { ### Required -- `database` (String) The database in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) Specifies the identifier for the stream; must be unique for the database and schema in which the stream is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `schema` (String) The schema in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `table` (String) Specifies an identifier for the table the stream will monitor. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) Specifies the identifier for the stream; must be unique for the database and schema in which the stream is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `schema` (String) The schema in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `table` (String) Specifies an identifier for the table the stream will monitor. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/stream_on_view.md b/docs/resources/stream_on_view.md index 6795301683..ea8c406eb4 100644 --- a/docs/resources/stream_on_view.md +++ b/docs/resources/stream_on_view.md @@ -58,10 +58,10 @@ resource "snowflake_stream_on_view" "stream" { ### Required -- `database` (String) The database in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) Specifies the identifier for the stream; must be unique for the database and schema in which the stream is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `schema` (String) The schema in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `view` (String) Specifies an identifier for the view the stream will monitor. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) Specifies the identifier for the stream; must be unique for the database and schema in which the stream is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `schema` (String) The schema in which to create the stream. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `view` (String) Specifies an identifier for the view the stream will monitor. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/tag.md b/docs/resources/tag.md index b2352e260c..0d8c2ba31c 100644 --- a/docs/resources/tag.md +++ b/docs/resources/tag.md @@ -2,33 +2,35 @@ page_title: "snowflake_tag Resource - terraform-provider-snowflake" subcategory: "" description: |- - + Resource used to manage tags. For more information, check tag documentation https://docs.snowflake.com/en/sql-reference/sql/create-tag. --- -# snowflake_tag (Resource) +!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v0980--v0990) to use it. +# snowflake_tag (Resource) +Resource used to manage tags. For more information, check [tag documentation](https://docs.snowflake.com/en/sql-reference/sql/create-tag). ## Example Usage ```terraform -resource "snowflake_database" "database" { - name = "database" -} - -resource "snowflake_schema" "schema" { - name = "schema" - database = snowflake_database.database.name +# basic resource +resource "snowflake_tag" "tag" { + name = "tag" + database = "database" + schema = "schema" } +# complete resource resource "snowflake_tag" "tag" { - name = "cost_center" - database = snowflake_database.database.name - schema = snowflake_schema.schema.name - allowed_values = ["finance", "engineering"] + name = "tag" + database = "database" + schema = "schema" + comment = "comment" + allowed_values = ["finance", "engineering", ""] + masking_policies = [snowfalke_masking_policy.masking_policy.fully_qualified_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). @@ -37,25 +39,40 @@ resource "snowflake_tag" "tag" { ### Required -- `database` (String) The database in which to create the tag. -- `name` (String) Specifies the identifier for the tag; must be unique for the database in which the tag is created. -- `schema` (String) The schema in which to create the tag. +- `database` (String) The database in which to create the tag. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) Specifies the identifier for the tag; must be unique for the database in which the tag is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `schema` (String) The schema in which to create the tag. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional -- `allowed_values` (List of String) List of allowed values for the tag. +- `allowed_values` (Set of String) Set of allowed values for the tag. - `comment` (String) Specifies a comment for the tag. +- `masking_policies` (Set of String) Set of masking policies for the tag. A tag can support one masking policy for each data type. If masking policies are assigned to the tag, before dropping the tag, the provider automatically unassigns them. ### 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. +- `show_output` (List of Object) Outputs the result of `SHOW TAGS` for the given tag. (see [below for nested schema](#nestedatt--show_output)) + + +### Nested Schema for `show_output` + +Read-Only: + +- `allowed_values` (Set of String) +- `comment` (String) +- `created_on` (String) +- `database_name` (String) +- `name` (String) +- `owner` (String) +- `owner_role_type` (String) +- `schema_name` (String) ## Import Import is supported using the following syntax: ```shell -# format is database name | schema name | tag name -terraform import snowflake_tag.example 'dbName|schemaName|tagName' +terraform import snowflake_tag.example '""."".""' ``` diff --git a/docs/resources/tag_masking_policy_association.md b/docs/resources/tag_masking_policy_association.md index 1b183e31f9..36d6c8943a 100644 --- a/docs/resources/tag_masking_policy_association.md +++ b/docs/resources/tag_masking_policy_association.md @@ -7,6 +7,8 @@ description: |- # snowflake_tag_masking_policy_association (Resource) +~> **Deprecation** This resource is deprecated and will be removed in a future major version release. Please use one of the new resources instead: `snowflake_tag` + Attach a masking policy to a tag. Requires a current warehouse to be set. Either with SNOWFLAKE_WAREHOUSE env variable or in current session. If no warehouse is provided, a temporary warehouse will be created. ## Example Usage diff --git a/docs/resources/user.md b/docs/resources/user.md index 688dd75359..0f542d36b9 100644 --- a/docs/resources/user.md +++ b/docs/resources/user.md @@ -128,7 +128,7 @@ resource "snowflake_user" "u" { ### Required -- `name` (String) Name of the user. Note that if you do not supply login_name this will be used as login_name. Check the [docs](https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#required-parameters). Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Name of the user. Note that if you do not supply login_name this will be used as login_name. Check the [docs](https://docs.snowflake.net/manuals/sql-reference/sql/create-user.html#required-parameters). Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/docs/resources/view.md b/docs/resources/view.md index 46a880bab0..4295f33051 100644 --- a/docs/resources/view.md +++ b/docs/resources/view.md @@ -91,9 +91,9 @@ SQL ### Required -- `database` (String) The database in which to create the view. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `name` (String) Specifies the identifier for the view; must be unique for the schema in which the view is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` -- `schema` (String) The schema in which to create the view. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `database` (String) The database in which to create the view. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `name` (String) Specifies the identifier for the view; must be unique for the schema in which the view is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` +- `schema` (String) The schema in which to create the view. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` - `statement` (String) Specifies the query used to create the view. ### Optional diff --git a/docs/resources/warehouse.md b/docs/resources/warehouse.md index 3a440710bd..af0fbe914d 100644 --- a/docs/resources/warehouse.md +++ b/docs/resources/warehouse.md @@ -28,7 +28,7 @@ resource "snowflake_warehouse" "warehouse" { ### Required -- `name` (String) Identifier for the virtual warehouse; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"` +- `name` (String) Identifier for the virtual warehouse; must be unique for your account. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `"` ### Optional diff --git a/examples/additional/deprecated_resources.MD b/examples/additional/deprecated_resources.MD index 1c5fb01acb..557f4af44a 100644 --- a/examples/additional/deprecated_resources.MD +++ b/examples/additional/deprecated_resources.MD @@ -5,3 +5,4 @@ - [snowflake_role](./docs/resources/role) - use [snowflake_account_role](./docs/resources/account_role) instead - [snowflake_saml_integration](./docs/resources/saml_integration) - use [snowflake_saml2_integration](./docs/resources/saml2_integration) instead - [snowflake_stream](./docs/resources/stream) +- [snowflake_tag_masking_policy_association](./docs/resources/tag_masking_policy_association) diff --git a/examples/resources/snowflake_tag/import.sh b/examples/resources/snowflake_tag/import.sh index 0c75224ed4..784e71109b 100644 --- a/examples/resources/snowflake_tag/import.sh +++ b/examples/resources/snowflake_tag/import.sh @@ -1,2 +1 @@ -# format is database name | schema name | tag name -terraform import snowflake_tag.example 'dbName|schemaName|tagName' \ No newline at end of file +terraform import snowflake_tag.example '""."".""' diff --git a/examples/resources/snowflake_tag/resource.tf b/examples/resources/snowflake_tag/resource.tf index 465cd6741d..9c99ab0503 100644 --- a/examples/resources/snowflake_tag/resource.tf +++ b/examples/resources/snowflake_tag/resource.tf @@ -1,15 +1,16 @@ -resource "snowflake_database" "database" { - name = "database" -} - -resource "snowflake_schema" "schema" { - name = "schema" - database = snowflake_database.database.name +# basic resource +resource "snowflake_tag" "tag" { + name = "tag" + database = "database" + schema = "schema" } +# complete resource resource "snowflake_tag" "tag" { - name = "cost_center" - database = snowflake_database.database.name - schema = snowflake_schema.schema.name - allowed_values = ["finance", "engineering"] + name = "tag" + database = "database" + schema = "schema" + comment = "comment" + allowed_values = ["finance", "engineering", ""] + masking_policies = [snowfalke_masking_policy.masking_policy.fully_qualified_name] } diff --git a/pkg/acceptance/bettertestspoc/assert/resourceassert/gen/resource_schema_def.go b/pkg/acceptance/bettertestspoc/assert/resourceassert/gen/resource_schema_def.go index 692552496c..144b0d5975 100644 --- a/pkg/acceptance/bettertestspoc/assert/resourceassert/gen/resource_schema_def.go +++ b/pkg/acceptance/bettertestspoc/assert/resourceassert/gen/resource_schema_def.go @@ -105,4 +105,8 @@ var allResourceSchemaDefs = []ResourceSchemaDef{ name: "SecondaryConnection", schema: resources.SecondaryConnection().Schema, }, + { + name: "Tag", + schema: resources.Tag().Schema, + }, } diff --git a/pkg/acceptance/bettertestspoc/assert/resourceassert/tag_resource_ext.go b/pkg/acceptance/bettertestspoc/assert/resourceassert/tag_resource_ext.go new file mode 100644 index 0000000000..d9ee8d7190 --- /dev/null +++ b/pkg/acceptance/bettertestspoc/assert/resourceassert/tag_resource_ext.go @@ -0,0 +1,17 @@ +package resourceassert + +import ( + "fmt" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" +) + +func (t *TagResourceAssert) HasMaskingPoliciesLength(len int) *TagResourceAssert { + t.AddAssertion(assert.ValueSet("masking_policies.#", fmt.Sprintf("%d", len))) + return t +} + +func (t *TagResourceAssert) HasAllowedValuesLength(len int) *TagResourceAssert { + t.AddAssertion(assert.ValueSet("allowed_values.#", fmt.Sprintf("%d", len))) + return t +} diff --git a/pkg/acceptance/bettertestspoc/assert/resourceassert/tag_resource_gen.go b/pkg/acceptance/bettertestspoc/assert/resourceassert/tag_resource_gen.go new file mode 100644 index 0000000000..27102d9656 --- /dev/null +++ b/pkg/acceptance/bettertestspoc/assert/resourceassert/tag_resource_gen.go @@ -0,0 +1,107 @@ +// Code generated by assertions generator; DO NOT EDIT. + +package resourceassert + +import ( + "testing" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" +) + +type TagResourceAssert struct { + *assert.ResourceAssert +} + +func TagResource(t *testing.T, name string) *TagResourceAssert { + t.Helper() + + return &TagResourceAssert{ + ResourceAssert: assert.NewResourceAssert(name, "resource"), + } +} + +func ImportedTagResource(t *testing.T, id string) *TagResourceAssert { + t.Helper() + + return &TagResourceAssert{ + ResourceAssert: assert.NewImportedResourceAssert(id, "imported resource"), + } +} + +/////////////////////////////////// +// Attribute value string checks // +/////////////////////////////////// + +func (t *TagResourceAssert) HasAllowedValuesString(expected string) *TagResourceAssert { + t.AddAssertion(assert.ValueSet("allowed_values", expected)) + return t +} + +func (t *TagResourceAssert) HasCommentString(expected string) *TagResourceAssert { + t.AddAssertion(assert.ValueSet("comment", expected)) + return t +} + +func (t *TagResourceAssert) HasDatabaseString(expected string) *TagResourceAssert { + t.AddAssertion(assert.ValueSet("database", expected)) + return t +} + +func (t *TagResourceAssert) HasFullyQualifiedNameString(expected string) *TagResourceAssert { + t.AddAssertion(assert.ValueSet("fully_qualified_name", expected)) + return t +} + +func (t *TagResourceAssert) HasMaskingPolicyString(expected string) *TagResourceAssert { + t.AddAssertion(assert.ValueSet("masking_policy", expected)) + return t +} + +func (t *TagResourceAssert) HasNameString(expected string) *TagResourceAssert { + t.AddAssertion(assert.ValueSet("name", expected)) + return t +} + +func (t *TagResourceAssert) HasSchemaString(expected string) *TagResourceAssert { + t.AddAssertion(assert.ValueSet("schema", expected)) + return t +} + +//////////////////////////// +// Attribute empty checks // +//////////////////////////// + +func (t *TagResourceAssert) HasNoAllowedValues() *TagResourceAssert { + t.AddAssertion(assert.ValueNotSet("allowed_values")) + return t +} + +func (t *TagResourceAssert) HasNoComment() *TagResourceAssert { + t.AddAssertion(assert.ValueNotSet("comment")) + return t +} + +func (t *TagResourceAssert) HasNoDatabase() *TagResourceAssert { + t.AddAssertion(assert.ValueNotSet("database")) + return t +} + +func (t *TagResourceAssert) HasNoFullyQualifiedName() *TagResourceAssert { + t.AddAssertion(assert.ValueNotSet("fully_qualified_name")) + return t +} + +func (t *TagResourceAssert) HasNoMaskingPolicies() *TagResourceAssert { + t.AddAssertion(assert.ValueNotSet("masking_policies")) + return t +} + +func (t *TagResourceAssert) HasNoName() *TagResourceAssert { + t.AddAssertion(assert.ValueNotSet("name")) + return t +} + +func (t *TagResourceAssert) HasNoSchema() *TagResourceAssert { + t.AddAssertion(assert.ValueNotSet("schema")) + return t +} diff --git a/pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/tag_show_output_ext.go b/pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/tag_show_output_ext.go new file mode 100644 index 0000000000..9fb4de087b --- /dev/null +++ b/pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/tag_show_output_ext.go @@ -0,0 +1,26 @@ +package resourceshowoutputassert + +import ( + "fmt" + "strconv" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" +) + +func (s *TagShowOutputAssert) HasCreatedOnNotEmpty() *TagShowOutputAssert { + s.AddAssertion(assert.ResourceShowOutputValuePresent("created_on")) + return s +} + +func (s *TagShowOutputAssert) HasAllowedValues(expected ...string) *TagShowOutputAssert { + s.AddAssertion(assert.ResourceShowOutputValueSet("allowed_values.#", strconv.FormatInt(int64(len(expected)), 10))) + for i := range expected { + s.AddAssertion(assert.ResourceShowOutputValueSet(fmt.Sprintf("allowed_values.%d", i), expected[i])) + } + return s +} + +func (s *TagShowOutputAssert) HasNoAllowedValues(expected ...string) *TagShowOutputAssert { + s.AddAssertion(assert.ResourceShowOutputValueSet("allowed_values.#", "0")) + return s +} diff --git a/pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/tag_show_output_gen.go b/pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/tag_show_output_gen.go index 486e08488c..fbf79c735f 100644 --- a/pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/tag_show_output_gen.go +++ b/pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert/tag_show_output_gen.go @@ -71,11 +71,6 @@ func (t *TagShowOutputAssert) HasComment(expected string) *TagShowOutputAssert { return t } -// func (t *TagShowOutputAssert) HasAllowedValues(expected []string) *TagShowOutputAssert { -// t.AddAssertion(assert.ResourceShowOutputValueSet("allowed_values", expected)) -// return t -// } - func (t *TagShowOutputAssert) HasOwnerRoleType(expected string) *TagShowOutputAssert { t.AddAssertion(assert.ResourceShowOutputValueSet("owner_role_type", expected)) return t diff --git a/pkg/acceptance/bettertestspoc/config/model/tag_model_ext.go b/pkg/acceptance/bettertestspoc/config/model/tag_model_ext.go new file mode 100644 index 0000000000..81fd60aa63 --- /dev/null +++ b/pkg/acceptance/bettertestspoc/config/model/tag_model_ext.go @@ -0,0 +1,26 @@ +package model + +import ( + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + tfconfig "github.com/hashicorp/terraform-plugin-testing/config" +) + +func (t *TagModel) WithAllowedValues(allowedValues ...string) *TagModel { + allowedValuesStringVariables := make([]tfconfig.Variable, len(allowedValues)) + for i, v := range allowedValues { + allowedValuesStringVariables[i] = tfconfig.StringVariable(v) + } + + t.AllowedValues = tfconfig.SetVariable(allowedValuesStringVariables...) + return t +} + +func (t *TagModel) WithMaskingPolicies(maskingPolicies ...sdk.SchemaObjectIdentifier) *TagModel { + maskingPoliciesStringVariables := make([]tfconfig.Variable, len(maskingPolicies)) + for i, v := range maskingPolicies { + maskingPoliciesStringVariables[i] = tfconfig.StringVariable(v.FullyQualifiedName()) + } + + t.MaskingPolicies = tfconfig.SetVariable(maskingPoliciesStringVariables...) + return t +} diff --git a/pkg/acceptance/bettertestspoc/config/model/tag_model_gen.go b/pkg/acceptance/bettertestspoc/config/model/tag_model_gen.go new file mode 100644 index 0000000000..91b5bb9eff --- /dev/null +++ b/pkg/acceptance/bettertestspoc/config/model/tag_model_gen.go @@ -0,0 +1,123 @@ +// Code generated by config model builder generator; DO NOT EDIT. + +package model + +import ( + tfconfig "github.com/hashicorp/terraform-plugin-testing/config" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/config" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" +) + +type TagModel struct { + AllowedValues tfconfig.Variable `json:"allowed_values,omitempty"` + Comment tfconfig.Variable `json:"comment,omitempty"` + Database tfconfig.Variable `json:"database,omitempty"` + FullyQualifiedName tfconfig.Variable `json:"fully_qualified_name,omitempty"` + MaskingPolicies tfconfig.Variable `json:"masking_policies,omitempty"` + Name tfconfig.Variable `json:"name,omitempty"` + Schema tfconfig.Variable `json:"schema,omitempty"` + + *config.ResourceModelMeta +} + +///////////////////////////////////////////////// +// Basic builders (resource name and required) // +///////////////////////////////////////////////// + +func Tag( + resourceName string, + database string, + name string, + schema string, +) *TagModel { + t := &TagModel{ResourceModelMeta: config.Meta(resourceName, resources.Tag)} + t.WithDatabase(database) + t.WithName(name) + t.WithSchema(schema) + return t +} + +func TagWithDefaultMeta( + database string, + name string, + schema string, +) *TagModel { + t := &TagModel{ResourceModelMeta: config.DefaultMeta(resources.Tag)} + t.WithDatabase(database) + t.WithName(name) + t.WithSchema(schema) + return t +} + +///////////////////////////////// +// below all the proper values // +///////////////////////////////// + +// allowed_values attribute type is not yet supported, so WithAllowedValues can't be generated + +func (t *TagModel) WithComment(comment string) *TagModel { + t.Comment = tfconfig.StringVariable(comment) + return t +} + +func (t *TagModel) WithDatabase(database string) *TagModel { + t.Database = tfconfig.StringVariable(database) + return t +} + +func (t *TagModel) WithFullyQualifiedName(fullyQualifiedName string) *TagModel { + t.FullyQualifiedName = tfconfig.StringVariable(fullyQualifiedName) + return t +} + +// masking_policy attribute type is not yet supported, so WithMaskingPolicy can't be generated + +func (t *TagModel) WithName(name string) *TagModel { + t.Name = tfconfig.StringVariable(name) + return t +} + +func (t *TagModel) WithSchema(schema string) *TagModel { + t.Schema = tfconfig.StringVariable(schema) + return t +} + +////////////////////////////////////////// +// below it's possible to set any value // +////////////////////////////////////////// + +func (t *TagModel) WithAllowedValuesValue(value tfconfig.Variable) *TagModel { + t.AllowedValues = value + return t +} + +func (t *TagModel) WithCommentValue(value tfconfig.Variable) *TagModel { + t.Comment = value + return t +} + +func (t *TagModel) WithDatabaseValue(value tfconfig.Variable) *TagModel { + t.Database = value + return t +} + +func (t *TagModel) WithFullyQualifiedNameValue(value tfconfig.Variable) *TagModel { + t.FullyQualifiedName = value + return t +} + +func (t *TagModel) WithMaskingPoliciesValue(value tfconfig.Variable) *TagModel { + t.MaskingPolicies = value + return t +} + +func (t *TagModel) WithNameValue(value tfconfig.Variable) *TagModel { + t.Name = value + return t +} + +func (t *TagModel) WithSchemaValue(value tfconfig.Variable) *TagModel { + t.Schema = value + return t +} diff --git a/pkg/acceptance/helpers/tag_client.go b/pkg/acceptance/helpers/tag_client.go index ee2f01d46a..90d7cbcb8b 100644 --- a/pkg/acceptance/helpers/tag_client.go +++ b/pkg/acceptance/helpers/tag_client.go @@ -52,6 +52,13 @@ func (c *TagClient) CreateWithRequest(t *testing.T, req *sdk.CreateTagRequest) ( return tag, c.DropTagFunc(t, req.GetName()) } +func (c *TagClient) Alter(t *testing.T, req *sdk.AlterTagRequest) { + t.Helper() + ctx := context.Background() + err := c.client().Alter(ctx, req) + require.NoError(t, err) +} + func (c *TagClient) DropTagFunc(t *testing.T, id sdk.SchemaObjectIdentifier) func() { t.Helper() ctx := context.Background() diff --git a/pkg/provider/resources/resources.go b/pkg/provider/resources/resources.go index 9437469ef9..05757d5967 100644 --- a/pkg/provider/resources/resources.go +++ b/pkg/provider/resources/resources.go @@ -63,6 +63,7 @@ const ( Streamlit resource = "snowflake_streamlit" Table resource = "snowflake_table" Tag resource = "snowflake_tag" + TagAssociation resource = "snowflake_tag_association" Task resource = "snowflake_task" User resource = "snowflake_user" View resource = "snowflake_view" diff --git a/pkg/resources/doc_helpers.go b/pkg/resources/doc_helpers.go index 8476ed050b..eec39dcf4a 100644 --- a/pkg/resources/doc_helpers.go +++ b/pkg/resources/doc_helpers.go @@ -32,7 +32,7 @@ func withPrivilegedRolesDescription(description, paramName string) string { } func blocklistedCharactersFieldDescription(description string) string { - return fmt.Sprintf(`%s Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: %s`, description, characterList([]rune{'|', '.', '(', ')', '"'})) + return fmt.Sprintf(`%s Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: %s`, description, characterList([]rune{'|', '.', '"'})) } func diffSuppressStatementFieldDescription(description string) string { diff --git a/pkg/resources/helpers.go b/pkg/resources/helpers.go index a7c78d2532..3c47984e7e 100644 --- a/pkg/resources/helpers.go +++ b/pkg/resources/helpers.go @@ -330,3 +330,17 @@ func ListDiff[T comparable](beforeList []T, afterList []T) (added []T, removed [ return added, removed } + +// parseSchemaObjectIdentifierSet is a helper function to parse a given schema object identifier list from ResourceData. +func parseSchemaObjectIdentifierSet(v any) ([]sdk.SchemaObjectIdentifier, error) { + idsRaw := expandStringList(v.(*schema.Set).List()) + ids := make([]sdk.SchemaObjectIdentifier, len(idsRaw)) + for i, idRaw := range idsRaw { + id, err := sdk.ParseSchemaObjectIdentifier(idRaw) + if err != nil { + return nil, err + } + ids[i] = id + } + return ids, nil +} diff --git a/pkg/resources/network_policy.go b/pkg/resources/network_policy.go index 7b590ce169..981107abb0 100644 --- a/pkg/resources/network_policy.go +++ b/pkg/resources/network_policy.go @@ -138,7 +138,7 @@ func CreateContextNetworkPolicy(ctx context.Context, d *schema.ResourceData, met } if v, ok := d.GetOk("allowed_network_rule_list"); ok { - allowedNetworkRuleList, err := parseNetworkRulesList(v) + allowedNetworkRuleList, err := parseSchemaObjectIdentifierSet(v) if err != nil { return diag.FromErr(err) } @@ -146,7 +146,7 @@ func CreateContextNetworkPolicy(ctx context.Context, d *schema.ResourceData, met } if v, ok := d.GetOk("blocked_network_rule_list"); ok { - blockedNetworkRuleList, err := parseNetworkRulesList(v) + blockedNetworkRuleList, err := parseSchemaObjectIdentifierSet(v) if err != nil { return diag.FromErr(err) } @@ -315,7 +315,7 @@ func UpdateContextNetworkPolicy(ctx context.Context, d *schema.ResourceData, met if d.HasChange("allowed_network_rule_list") { if v, ok := d.GetOk("allowed_network_rule_list"); ok { - allowedNetworkRuleList, err := parseNetworkRulesList(v) + allowedNetworkRuleList, err := parseSchemaObjectIdentifierSet(v) if err != nil { return diag.FromErr(err) } @@ -327,7 +327,7 @@ func UpdateContextNetworkPolicy(ctx context.Context, d *schema.ResourceData, met if d.HasChange("blocked_network_rule_list") { if v, ok := d.GetOk("blocked_network_rule_list"); ok { - blockedNetworkRuleList, err := parseNetworkRulesList(v) + blockedNetworkRuleList, err := parseSchemaObjectIdentifierSet(v) if err != nil { return diag.FromErr(err) } @@ -399,17 +399,3 @@ func parseIPList(v interface{}) []sdk.IPRequest { } return ipRequests } - -// parseNetworkRulesList is a helper function to parse a given network rule list from ResourceData. -func parseNetworkRulesList(v interface{}) ([]sdk.SchemaObjectIdentifier, error) { - networkRules := expandStringList(v.(*schema.Set).List()) - networkRuleIdentifiers := make([]sdk.SchemaObjectIdentifier, len(networkRules)) - for i, networkRuleFullyQualifiedName := range networkRules { - networkRuleId, err := sdk.ParseSchemaObjectIdentifier(networkRuleFullyQualifiedName) - if err != nil { - return nil, err - } - networkRuleIdentifiers[i] = networkRuleId - } - return networkRuleIdentifiers, nil -} diff --git a/pkg/resources/tag.go b/pkg/resources/tag.go index 08f50c8116..39ba4e9990 100644 --- a/pkg/resources/tag.go +++ b/pkg/resources/tag.go @@ -2,10 +2,13 @@ package resources import ( "context" + "errors" "fmt" - "slices" + "log" + "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/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" @@ -16,22 +19,24 @@ import ( var tagSchema = map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Required: true, - Description: "Specifies the identifier for the tag; must be unique for the database in which the tag is created.", - ForceNew: true, + Type: schema.TypeString, + Required: true, + Description: blocklistedCharactersFieldDescription("Specifies the identifier for the tag; must be unique for the database in which the tag is created."), + DiffSuppressFunc: suppressIdentifierQuoting, }, "database": { - Type: schema.TypeString, - Required: true, - Description: "The database in which to create the tag.", - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: blocklistedCharactersFieldDescription("The database in which to create the tag."), + DiffSuppressFunc: suppressIdentifierQuoting, }, "schema": { - Type: schema.TypeString, - Required: true, - Description: "The schema in which to create the tag.", - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: blocklistedCharactersFieldDescription("The schema in which to create the tag."), + DiffSuppressFunc: suppressIdentifierQuoting, }, "comment": { Type: schema.TypeString, @@ -39,12 +44,30 @@ var tagSchema = map[string]*schema.Schema{ Description: "Specifies a comment for the tag.", }, "allowed_values": { - Type: schema.TypeList, + Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, - Description: "List of allowed values for the tag.", + Description: "Set of allowed values for the tag.", + }, + "masking_policies": { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: IsValidIdentifier[sdk.SchemaObjectIdentifier](), + }, + Optional: true, + DiffSuppressFunc: NormalizeAndCompareIdentifiersInSet("masking_policies"), + Description: "Set of masking policies for the tag. A tag can support one masking policy for each data type. If masking policies are assigned to the tag, before dropping the tag, the provider automatically unassigns them.", }, FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, + ShowOutputAttributeName: { + Type: schema.TypeList, + Computed: true, + Description: "Outputs the result of `SHOW TAGS` for the given tag.", + Elem: &schema.Resource{ + Schema: schemas.ShowTagSchema, + }, + }, } // TODO(SNOW-1348114, SNOW-1348110, SNOW-1348355, SNOW-1348353): remove after rework of external table, materialized view, stage and table @@ -83,14 +106,31 @@ var tagReferenceSchema = &schema.Schema{ // Schema returns a pointer to the resource representing a schema. func Tag() *schema.Resource { return &schema.Resource{ + SchemaVersion: 1, + CreateContext: CreateContextTag, ReadContext: ReadContextTag, UpdateContext: UpdateContextTag, DeleteContext: DeleteContextTag, + Description: "Resource used to manage tags. For more information, check [tag documentation](https://docs.snowflake.com/en/sql-reference/sql/create-tag).", + + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(tagSchema, ShowOutputAttributeName, "name", "comment", "allowed_values"), + ComputedIfAnyAttributeChanged(tagSchema, FullyQualifiedNameAttributeName, "name"), + ), Schema: tagSchema, Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, + StateContext: ImportName[sdk.SchemaObjectIdentifier], + }, + + 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: migratePipeSeparatedObjectIdentifierResourceIdToFullyQualifiedName, + }, }, } } @@ -98,57 +138,98 @@ func Tag() *schema.Resource { func CreateContextTag(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { client := meta.(*provider.Context).Client name := d.Get("name").(string) - schema := d.Get("schema").(string) + schemaName := d.Get("schema").(string) database := d.Get("database").(string) - id := sdk.NewSchemaObjectIdentifier(database, schema, name) + id := sdk.NewSchemaObjectIdentifier(database, schemaName, name) request := sdk.NewCreateTagRequest(id) if v, ok := d.GetOk("comment"); ok { request.WithComment(sdk.String(v.(string))) } if v, ok := d.GetOk("allowed_values"); ok { - request.WithAllowedValues(expandStringListAllowEmpty(v.([]any))) + request.WithAllowedValues(expandStringListAllowEmpty(v.(*schema.Set).List())) } if err := client.Tags.Create(ctx, request); err != nil { return diag.FromErr(err) } - d.SetId(helpers.EncodeSnowflakeID(id)) + d.SetId(helpers.EncodeResourceIdentifier(id)) + if v, ok := d.GetOk("masking_policies"); ok { + ids, err := parseSchemaObjectIdentifierSet(v) + if err != nil { + return diag.FromErr(err) + } + err = client.Tags.Alter(ctx, sdk.NewAlterTagRequest(id).WithSet(sdk.NewTagSetRequest().WithMaskingPolicies(ids))) + if err != nil { + return diag.FromErr(fmt.Errorf("error setting masking policies in tag %v err = %w", id.Name(), err)) + } + } return ReadContextTag(ctx, d, meta) } func ReadContextTag(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - diags := diag.Diagnostics{} client := meta.(*provider.Context).Client - id := helpers.DecodeSnowflakeID(d.Id()).(sdk.SchemaObjectIdentifier) - - tag, err := client.Tags.ShowByID(ctx, id) + id, err := sdk.ParseSchemaObjectIdentifier(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", tag.Name); err != nil { - return diag.FromErr(err) - } - if err := d.Set("database", tag.DatabaseName); err != nil { - return diag.FromErr(err) - } - if err := d.Set("schema", tag.SchemaName); err != nil { - return diag.FromErr(err) - } - if err := d.Set("comment", tag.Comment); err != nil { + + tag, err := client.Tags.ShowByID(ctx, id) + if err != nil { + if errors.Is(err, sdk.ErrObjectNotFound) { + d.SetId("") + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Warning, + Summary: "Failed to query tag. Marking the resource as removed.", + Detail: fmt.Sprintf("Tag: %s, Err: %s", id.FullyQualifiedName(), err), + }, + } + } return diag.FromErr(err) } - if err := d.Set("allowed_values", tag.AllowedValues); err != nil { - return diag.FromErr(err) + errs := errors.Join( + d.Set("name", tag.Name), + d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()), + d.Set(ShowOutputAttributeName, []map[string]any{schemas.TagToSchema(tag)}), + d.Set("comment", tag.Comment), + d.Set("allowed_values", tag.AllowedValues), + func() error { + policyRefs, err := client.PolicyReferences.GetForEntity(ctx, sdk.NewGetForEntityPolicyReferenceRequest(id, sdk.PolicyEntityDomainTag)) + if err != nil { + return (fmt.Errorf("getting policy references for view: %w", err)) + } + policyIds := make([]string, 0, len(policyRefs)) + for _, p := range policyRefs { + if p.PolicyKind == sdk.PolicyKindMaskingPolicy { + policyId := sdk.NewSchemaObjectIdentifier(*p.PolicyDb, *p.PolicySchema, p.PolicyName) + policyIds = append(policyIds, policyId.FullyQualifiedName()) + } + } + return d.Set("masking_policies", policyIds) + }(), + ) + if errs != nil { + return diag.FromErr(errs) } - return diags + return nil } func UpdateContextTag(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { client := meta.(*provider.Context).Client - id := helpers.DecodeSnowflakeID(d.Id()).(sdk.SchemaObjectIdentifier) + id, err := sdk.ParseSchemaObjectIdentifier(d.Id()) + if err != nil { + return diag.FromErr(err) + } + if d.HasChange("name") { + newId := sdk.NewSchemaObjectIdentifierInSchema(id.SchemaId(), d.Get("name").(string)) + + err := client.Tags.Alter(ctx, sdk.NewAlterTagRequest(id).WithRename(newId)) + if err != nil { + return diag.FromErr(fmt.Errorf("error renaming tag %v err = %w", d.Id(), err)) + } + d.SetId(helpers.EncodeResourceIdentifier(newId)) + id = newId + } if d.HasChange("comment") { comment, ok := d.GetOk("comment") if ok { @@ -165,30 +246,56 @@ func UpdateContextTag(ctx context.Context, d *schema.ResourceData, meta any) dia } if d.HasChange("allowed_values") { o, n := d.GetChange("allowed_values") - oldAllowedValues := expandStringListAllowEmpty(o.([]any)) - newAllowedValues := expandStringListAllowEmpty(n.([]any)) - var allowedValuesToAdd, allowedValuesToRemove []string + oldAllowedValues := expandStringListAllowEmpty(o.(*schema.Set).List()) + newAllowedValues := expandStringListAllowEmpty(n.(*schema.Set).List()) + + addedItems, removedItems := ListDiff(oldAllowedValues, newAllowedValues) + + if len(addedItems) > 0 { + if err := client.Tags.Alter(ctx, sdk.NewAlterTagRequest(id).WithAdd(addedItems)); err != nil { + return diag.FromErr(err) + } + } + + if len(removedItems) > 0 { + if err := client.Tags.Alter(ctx, sdk.NewAlterTagRequest(id).WithDrop(removedItems)); err != nil { + return diag.FromErr(err) + } + } + } + if d.HasChange("masking_policies") { + o, n := d.GetChange("masking_policies") + oldAllowedValues := expandStringList(o.(*schema.Set).List()) + newAllowedValues := expandStringList(n.(*schema.Set).List()) + + addedItems, removedItems := ListDiff(oldAllowedValues, newAllowedValues) - for _, oldAllowedValue := range oldAllowedValues { - if !slices.Contains(newAllowedValues, oldAllowedValue) { - allowedValuesToRemove = append(allowedValuesToRemove, oldAllowedValue) + removedids := make([]sdk.SchemaObjectIdentifier, len(removedItems)) + for i, idRaw := range removedItems { + id, err := sdk.ParseSchemaObjectIdentifier(idRaw) + if err != nil { + return diag.FromErr(err) } + removedids[i] = id } - for _, newAllowedValue := range newAllowedValues { - if !slices.Contains(oldAllowedValues, newAllowedValue) { - allowedValuesToAdd = append(allowedValuesToAdd, newAllowedValue) + addedids := make([]sdk.SchemaObjectIdentifier, len(addedItems)) + for i, idRaw := range addedItems { + id, err := sdk.ParseSchemaObjectIdentifier(idRaw) + if err != nil { + return diag.FromErr(err) } + addedids[i] = id } - if len(allowedValuesToAdd) > 0 { - if err := client.Tags.Alter(ctx, sdk.NewAlterTagRequest(id).WithAdd(allowedValuesToAdd)); err != nil { + if len(removedItems) > 0 { + if err := client.Tags.Alter(ctx, sdk.NewAlterTagRequest(id).WithUnset(sdk.NewTagUnsetRequest().WithMaskingPolicies(removedids))); err != nil { return diag.FromErr(err) } } - if len(allowedValuesToRemove) > 0 { - if err := client.Tags.Alter(ctx, sdk.NewAlterTagRequest(id).WithDrop(allowedValuesToRemove)); err != nil { + if len(addedItems) > 0 { + if err := client.Tags.Alter(ctx, sdk.NewAlterTagRequest(id).WithSet(sdk.NewTagSetRequest().WithMaskingPolicies(addedids))); err != nil { return diag.FromErr(err) } } @@ -198,21 +305,31 @@ func UpdateContextTag(ctx context.Context, d *schema.ResourceData, meta any) dia func DeleteContextTag(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { client := meta.(*provider.Context).Client - id := helpers.DecodeSnowflakeID(d.Id()).(sdk.SchemaObjectIdentifier) - if err := client.Tags.Drop(ctx, sdk.NewDropTagRequest(id)); err != nil { + id, err := sdk.ParseSchemaObjectIdentifier(d.Id()) + if err != nil { + return diag.FromErr(err) + } + // before dropping the resource, all policies must be unset + policyRefs, err := client.PolicyReferences.GetForEntity(ctx, sdk.NewGetForEntityPolicyReferenceRequest(id, sdk.PolicyEntityDomainTag)) + if err != nil { + return diag.FromErr(fmt.Errorf("getting policy references for view: %w", err)) + } + removedPolicies := make([]sdk.SchemaObjectIdentifier, 0, len(policyRefs)) + for _, p := range policyRefs { + if p.PolicyKind == sdk.PolicyKindMaskingPolicy { + policyName := sdk.NewSchemaObjectIdentifier(*p.PolicyDb, *p.PolicySchema, p.PolicyName) + removedPolicies = append(removedPolicies, policyName) + } + } + if len(removedPolicies) > 0 { + log.Printf("[DEBUG] unsetting masking policies before dropping tag: %s\n", id.FullyQualifiedName()) + if err := client.Tags.Alter(ctx, sdk.NewAlterTagRequest(id).WithUnset(sdk.NewTagUnsetRequest().WithMaskingPolicies(removedPolicies))); err != nil { + return diag.FromErr(err) + } + } + if err := client.Tags.Drop(ctx, sdk.NewDropTagRequest(id).WithIfExists(true)); err != nil { return diag.FromErr(err) } d.SetId("") return nil } - -// Returns the slice of strings for inputed allowed values. -func expandAllowedValues(avChangeSet any) []string { - avList := avChangeSet.([]any) - newAvs := make([]string, len(avList)) - for idx, value := range avList { - newAvs[idx] = fmt.Sprintf("%v", value) - } - - return newAvs -} diff --git a/pkg/resources/tag_acceptance_test.go b/pkg/resources/tag_acceptance_test.go index f831685a6e..98ee76801e 100644 --- a/pkg/resources/tag_acceptance_test.go +++ b/pkg/resources/tag_acceptance_test.go @@ -1,34 +1,53 @@ package resources_test import ( + "fmt" "testing" acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert/resourceassert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert/resourceshowoutputassert" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/config" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/config/model" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/testenvs" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/snowflakeroles" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" - "github.com/hashicorp/terraform-plugin-testing/config" + tfconfig "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 TestAcc_Tag(t *testing.T) { +func TestAcc_Tag_basic(t *testing.T) { + _ = testenvs.GetOrSkipTest(t, testenvs.EnableAcceptance) + acc.TestAccPreCheck(t) id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() - resourceName := "snowflake_tag.t" - m := func() map[string]config.Variable { - return map[string]config.Variable{ - "name": config.StringVariable(id.Name()), - "database": config.StringVariable(acc.TestDatabaseName), - "schema": config.StringVariable(acc.TestSchemaName), - "comment": config.StringVariable("Terraform acceptance test"), - "allowed_values": config.ListVariable(config.StringVariable("")), - } - } - - variableSet2 := m() - variableSet2["allowed_values"] = config.ListVariable(config.StringVariable("alv1"), config.StringVariable("alv2")) - - variableSet3 := m() - variableSet3["comment"] = config.StringVariable("Terraform acceptance test - updated") + + maskingPolicy, maskingPolicyCleanup := acc.TestClient().MaskingPolicy.CreateMaskingPolicy(t) + t.Cleanup(maskingPolicyCleanup) + + maskingPolicy2, maskingPolicy2Cleanup := acc.TestClient().MaskingPolicy.CreateMaskingPolicy(t) + t.Cleanup(maskingPolicy2Cleanup) + + baseModel := model.Tag("test", id.DatabaseName(), id.Name(), id.SchemaName()) + + modelWithExtraFields := model.Tag("test", id.DatabaseName(), id.Name(), id.SchemaName()). + WithComment("foo"). + WithAllowedValues("foo", "", "bar"). + WithMaskingPolicies(maskingPolicy.ID()) + + modelWithDifferentListOrder := model.Tag("test", id.DatabaseName(), id.Name(), id.SchemaName()). + WithComment("foo"). + WithAllowedValues("", "bar", "foo"). + WithMaskingPolicies(maskingPolicy.ID()) + + modelWithDifferentValues := model.Tag("test", id.DatabaseName(), id.Name(), id.SchemaName()). + WithComment("bar"). + WithAllowedValues("abc", "def", ""). + WithMaskingPolicies(maskingPolicy2.ID()) resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -38,52 +57,334 @@ func TestAcc_Tag(t *testing.T) { }, CheckDestroy: acc.CheckDestroy(t, resources.Tag), Steps: []resource.TestStep{ + // base model { - ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Tag/basic"), - ConfigVariables: m(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", id.Name()), - resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), - resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), - resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), - resource.TestCheckResourceAttr(resourceName, "allowed_values.#", "1"), - resource.TestCheckResourceAttr(resourceName, "allowed_values.0", ""), - resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test"), + Config: config.FromModel(t, baseModel), + Check: assert.AssertThat(t, resourceassert.TagResource(t, baseModel.ResourceReference()). + HasNameString(id.Name()). + HasDatabaseString(id.DatabaseName()). + HasSchemaString(id.SchemaName()). + HasFullyQualifiedNameString(id.FullyQualifiedName()). + HasCommentString(""). + HasNoMaskingPolicies(). + HasNoAllowedValues(), + resourceshowoutputassert.TagShowOutput(t, baseModel.ResourceReference()). + HasCreatedOnNotEmpty(). + HasName(id.Name()). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()). + HasComment(""). + HasOwner(snowflakeroles.Accountadmin.Name()). + HasOwnerRoleType("ROLE"). + HasNoAllowedValues(), ), }, - - // test - change allowed values + // import without optionals + { + Config: config.FromModel(t, baseModel), + ResourceName: baseModel.ResourceReference(), + ImportState: true, + ImportStateVerify: true, + }, + // set all fields { - ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Tag/basic"), - ConfigVariables: variableSet2, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", id.Name()), - resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), - resource.TestCheckResourceAttr(resourceName, "allowed_values.#", "2"), - resource.TestCheckResourceAttr(resourceName, "allowed_values.0", "alv1"), - resource.TestCheckResourceAttr(resourceName, "allowed_values.1", "alv2"), + Config: config.FromModel(t, modelWithExtraFields), + Check: assert.AssertThat(t, resourceassert.TagResource(t, modelWithExtraFields.ResourceReference()). + HasNameString(id.Name()). + HasDatabaseString(id.DatabaseName()). + HasSchemaString(id.SchemaName()). + HasFullyQualifiedNameString(id.FullyQualifiedName()). + HasCommentString("foo"), + assert.Check(resource.TestCheckResourceAttr(modelWithExtraFields.ResourceReference(), "masking_policies.#", "1")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "masking_policies.*", maskingPolicy.ID().FullyQualifiedName())), + assert.Check(resource.TestCheckResourceAttr(modelWithExtraFields.ResourceReference(), "allowed_values.#", "3")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "allowed_values.*", "foo")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "allowed_values.*", "")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "allowed_values.*", "bar")), + resourceshowoutputassert.TagShowOutput(t, modelWithExtraFields.ResourceReference()). + HasCreatedOnNotEmpty(). + HasName(id.Name()). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()). + HasComment("foo"). + HasOwner(snowflakeroles.Accountadmin.Name()). + HasOwnerRoleType("ROLE"), + assert.Check(resource.TestCheckResourceAttr(modelWithExtraFields.ResourceReference(), "show_output.0.allowed_values.#", "3")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "show_output.0.allowed_values.*", "foo")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "show_output.0.allowed_values.*", "")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "show_output.0.allowed_values.*", "bar")), ), }, - - // test - change comment + // external change + { + PreConfig: func() { + acc.TestClient().Tag.Alter(t, sdk.NewAlterTagRequest(id).WithDrop([]string{"foo"})) + }, + Config: config.FromModel(t, modelWithExtraFields), + Check: assert.AssertThat(t, resourceassert.TagResource(t, modelWithExtraFields.ResourceReference()). + HasNameString(id.Name()). + HasDatabaseString(id.DatabaseName()). + HasSchemaString(id.SchemaName()). + HasFullyQualifiedNameString(id.FullyQualifiedName()). + HasCommentString("foo"), + assert.Check(resource.TestCheckResourceAttr(modelWithExtraFields.ResourceReference(), "masking_policies.#", "1")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "masking_policies.*", maskingPolicy.ID().FullyQualifiedName())), + assert.Check(resource.TestCheckResourceAttr(modelWithExtraFields.ResourceReference(), "allowed_values.#", "3")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "allowed_values.*", "foo")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "allowed_values.*", "")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "allowed_values.*", "bar")), + resourceshowoutputassert.TagShowOutput(t, modelWithExtraFields.ResourceReference()). + HasCreatedOnNotEmpty(). + HasName(id.Name()). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()). + HasComment("foo"). + HasOwner(snowflakeroles.Accountadmin.Name()). + HasOwnerRoleType("ROLE"), + assert.Check(resource.TestCheckResourceAttr(modelWithExtraFields.ResourceReference(), "show_output.0.allowed_values.#", "3")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "show_output.0.allowed_values.*", "foo")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "show_output.0.allowed_values.*", "")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithExtraFields.ResourceReference(), "show_output.0.allowed_values.*", "bar")), + ), + }, + // different set ordering + { + Config: config.FromModel(t, modelWithDifferentListOrder), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(modelWithDifferentListOrder.ResourceReference(), plancheck.ResourceActionNoop), + }, + }, + Check: assert.AssertThat(t, resourceassert.TagResource(t, modelWithDifferentListOrder.ResourceReference()). + HasNameString(id.Name()). + HasDatabaseString(id.DatabaseName()). + HasSchemaString(id.SchemaName()). + HasFullyQualifiedNameString(id.FullyQualifiedName()). + HasCommentString("foo"), + assert.Check(resource.TestCheckResourceAttr(modelWithDifferentListOrder.ResourceReference(), "masking_policies.#", "1")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentListOrder.ResourceReference(), "masking_policies.*", maskingPolicy.ID().FullyQualifiedName())), + assert.Check(resource.TestCheckResourceAttr(modelWithDifferentListOrder.ResourceReference(), "allowed_values.#", "3")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentListOrder.ResourceReference(), "allowed_values.*", "foo")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentListOrder.ResourceReference(), "allowed_values.*", "")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentListOrder.ResourceReference(), "allowed_values.*", "bar")), + resourceshowoutputassert.TagShowOutput(t, modelWithDifferentListOrder.ResourceReference()). + HasCreatedOnNotEmpty(). + HasName(id.Name()). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()). + HasComment("foo"). + HasOwner(snowflakeroles.Accountadmin.Name()). + HasOwnerRoleType("ROLE"), + assert.Check(resource.TestCheckResourceAttr(modelWithDifferentListOrder.ResourceReference(), "show_output.0.allowed_values.#", "3")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentListOrder.ResourceReference(), "show_output.0.allowed_values.*", "foo")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentListOrder.ResourceReference(), "show_output.0.allowed_values.*", "")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentListOrder.ResourceReference(), "show_output.0.allowed_values.*", "bar")), + ), + }, + // change some values + { + Config: config.FromModel(t, modelWithDifferentValues), + Check: assert.AssertThat(t, resourceassert.TagResource(t, modelWithDifferentValues.ResourceReference()). + HasNameString(id.Name()). + HasDatabaseString(id.DatabaseName()). + HasSchemaString(id.SchemaName()). + HasFullyQualifiedNameString(id.FullyQualifiedName()). + HasCommentString("bar"), + assert.Check(resource.TestCheckResourceAttr(modelWithDifferentValues.ResourceReference(), "masking_policies.#", "1")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentValues.ResourceReference(), "masking_policies.*", maskingPolicy2.ID().FullyQualifiedName())), + assert.Check(resource.TestCheckResourceAttr(modelWithDifferentValues.ResourceReference(), "allowed_values.#", "3")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentValues.ResourceReference(), "allowed_values.*", "abc")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentValues.ResourceReference(), "allowed_values.*", "")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentValues.ResourceReference(), "allowed_values.*", "def")), + resourceshowoutputassert.TagShowOutput(t, modelWithDifferentValues.ResourceReference()). + HasCreatedOnNotEmpty(). + HasName(id.Name()). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()). + HasComment("bar"). + HasOwner(snowflakeroles.Accountadmin.Name()). + HasOwnerRoleType("ROLE"), + assert.Check(resource.TestCheckResourceAttr(modelWithDifferentValues.ResourceReference(), "show_output.0.allowed_values.#", "3")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentValues.ResourceReference(), "show_output.0.allowed_values.*", "abc")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentValues.ResourceReference(), "show_output.0.allowed_values.*", "")), + assert.Check(resource.TestCheckTypeSetElemAttr(modelWithDifferentValues.ResourceReference(), "show_output.0.allowed_values.*", "def")), + ), + }, + // unset optionals { - ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Tag/basic"), - ConfigVariables: variableSet3, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", id.Name()), - resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), - resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test - updated"), + Config: config.FromModel(t, baseModel), + Check: assert.AssertThat(t, resourceassert.TagResource(t, baseModel.ResourceReference()). + HasNameString(id.Name()). + HasDatabaseString(id.DatabaseName()). + HasSchemaString(id.SchemaName()). + HasFullyQualifiedNameString(id.FullyQualifiedName()). + HasCommentString(""). + HasMaskingPoliciesLength(0). + HasAllowedValuesLength(0), + resourceshowoutputassert.TagShowOutput(t, baseModel.ResourceReference()). + HasCreatedOnNotEmpty(). + HasName(id.Name()). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()). + HasComment(""). + HasOwner(snowflakeroles.Accountadmin.Name()). + HasOwnerRoleType("ROLE"). + HasNoAllowedValues(), ), }, + }, + }) +} + +func TestAcc_Tag_complete(t *testing.T) { + _ = testenvs.GetOrSkipTest(t, testenvs.EnableAcceptance) + acc.TestAccPreCheck(t) + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + + maskingPolicy, maskingPolicyCleanup := acc.TestClient().MaskingPolicy.CreateMaskingPolicy(t) + t.Cleanup(maskingPolicyCleanup) + + model := model.Tag("test", id.DatabaseName(), id.Name(), id.SchemaName()). + WithComment("foo"). + WithAllowedValuesValue(tfconfig.ListVariable(tfconfig.StringVariable("foo"), tfconfig.StringVariable(""), tfconfig.StringVariable("bar"))). + WithMaskingPoliciesValue(tfconfig.ListVariable(tfconfig.StringVariable(maskingPolicy.ID().FullyQualifiedName()))) - // test - import + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: acc.CheckDestroy(t, resources.Tag), + Steps: []resource.TestStep{ { - ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Tag/basic"), - ConfigVariables: variableSet3, - ResourceName: resourceName, + Config: config.FromModel(t, model), + Check: assert.AssertThat(t, resourceassert.TagResource(t, model.ResourceReference()). + HasNameString(id.Name()). + HasDatabaseString(id.DatabaseName()). + HasSchemaString(id.SchemaName()). + HasFullyQualifiedNameString(id.FullyQualifiedName()). + HasCommentString("foo"), + assert.Check(resource.TestCheckResourceAttr(model.ResourceReference(), "masking_policies.#", "1")), + assert.Check(resource.TestCheckTypeSetElemAttr(model.ResourceReference(), "masking_policies.*", maskingPolicy.ID().FullyQualifiedName())), + assert.Check(resource.TestCheckResourceAttr(model.ResourceReference(), "allowed_values.#", "3")), + assert.Check(resource.TestCheckTypeSetElemAttr(model.ResourceReference(), "allowed_values.*", "foo")), + assert.Check(resource.TestCheckTypeSetElemAttr(model.ResourceReference(), "allowed_values.*", "")), + assert.Check(resource.TestCheckTypeSetElemAttr(model.ResourceReference(), "allowed_values.*", "bar")), + resourceshowoutputassert.TagShowOutput(t, model.ResourceReference()). + HasCreatedOnNotEmpty(). + HasName(id.Name()). + HasDatabaseName(id.DatabaseName()). + HasSchemaName(id.SchemaName()). + HasComment("foo"). + HasOwner(snowflakeroles.Accountadmin.Name()). + HasOwnerRoleType("ROLE"), + assert.Check(resource.TestCheckResourceAttr(model.ResourceReference(), "show_output.0.allowed_values.#", "3")), + assert.Check(resource.TestCheckTypeSetElemAttr(model.ResourceReference(), "show_output.0.allowed_values.*", "foo")), + assert.Check(resource.TestCheckTypeSetElemAttr(model.ResourceReference(), "show_output.0.allowed_values.*", "")), + assert.Check(resource.TestCheckTypeSetElemAttr(model.ResourceReference(), "show_output.0.allowed_values.*", "bar")), + ), + }, + { + Config: config.FromModel(t, model), + ResourceName: model.ResourceReference(), ImportState: true, ImportStateVerify: true, }, }, }) } + +func TestAcc_Tag_Rename(t *testing.T) { + oldId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + newId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + + modelWithOldId := model.Tag("test", oldId.DatabaseName(), oldId.Name(), oldId.SchemaName()) + modelWithNewId := model.Tag("test", newId.DatabaseName(), newId.Name(), newId.SchemaName()) + + 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.Tag), + Steps: []resource.TestStep{ + { + Config: config.FromModel(t, modelWithOldId), + Check: assert.AssertThat(t, resourceassert.TagResource(t, modelWithOldId.ResourceReference()). + HasNameString(oldId.Name()). + HasDatabaseString(oldId.DatabaseName()). + HasSchemaString(oldId.SchemaName()), + ), + }, + { + Config: config.FromModel(t, modelWithNewId), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(modelWithOldId.ResourceReference(), plancheck.ResourceActionUpdate), + }, + }, + Check: assert.AssertThat(t, resourceassert.TagResource(t, modelWithNewId.ResourceReference()). + HasNameString(newId.Name()). + HasDatabaseString(newId.DatabaseName()). + HasSchemaString(newId.SchemaName()), + ), + }, + }, + }) +} + +func TestAcc_Tag_migrateFromVersion_0_98_0(t *testing.T) { + t.Setenv(string(testenvs.ConfigureClientOnce), "") + _ = testenvs.GetOrSkipTest(t, testenvs.EnableAcceptance) + acc.TestAccPreCheck(t) + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + + model := model.Tag("test", id.DatabaseName(), id.Name(), id.SchemaName()). + WithAllowedValuesValue(tfconfig.ListVariable(tfconfig.StringVariable("foo"), tfconfig.StringVariable("bar"))) + + resource.Test(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + Steps: []resource.TestStep{ + { + ExternalProviders: acc.ExternalProviderWithExactVersion("0.98.0"), + Config: tag_v_0_98_0(id), + Check: assert.AssertThat(t, resourceassert.TagResource(t, model.ResourceReference()). + HasNameString(id.Name()), + assert.Check(resource.TestCheckResourceAttr(model.ResourceReference(), "allowed_values.#", "2")), + assert.Check(resource.TestCheckResourceAttr(model.ResourceReference(), "allowed_values.0", "bar")), + assert.Check(resource.TestCheckResourceAttr(model.ResourceReference(), "allowed_values.1", "foo")), + ), + }, + { + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + Config: config.FromModel(t, model), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(model.ResourceReference(), plancheck.ResourceActionNoop), + }, + }, + Check: assert.AssertThat(t, resourceassert.TagResource(t, model.ResourceReference()). + HasNameString(id.Name()), + assert.Check(resource.TestCheckResourceAttr(model.ResourceReference(), "allowed_values.#", "2")), + assert.Check(resource.TestCheckTypeSetElemAttr(model.ResourceReference(), "allowed_values.*", "foo")), + assert.Check(resource.TestCheckTypeSetElemAttr(model.ResourceReference(), "allowed_values.*", "bar")), + ), + }, + }, + }) +} + +func tag_v_0_98_0(id sdk.SchemaObjectIdentifier) string { + s := ` +resource "snowflake_tag" "test" { + name = "%[1]s" + database = "%[2]s" + schema = "%[3]s" + allowed_values = ["bar", "foo"] +} +` + return fmt.Sprintf(s, id.Name(), id.DatabaseName(), id.SchemaName()) +} diff --git a/pkg/resources/tag_association_acceptance_test.go b/pkg/resources/tag_association_acceptance_test.go index 420116c57d..37e1d54804 100644 --- a/pkg/resources/tag_association_acceptance_test.go +++ b/pkg/resources/tag_association_acceptance_test.go @@ -17,11 +17,11 @@ import ( ) func TestAcc_TagAssociation(t *testing.T) { - tagName := acc.TestClient().Ids.Alpha() + tagId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() resourceName := "snowflake_tag_association.test" m := func() map[string]config.Variable { return map[string]config.Variable{ - "tag_name": config.StringVariable(tagName), + "tag_name": config.StringVariable(tagId.Name()), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), } @@ -39,7 +39,7 @@ func TestAcc_TagAssociation(t *testing.T) { ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "object_type", "DATABASE"), - resource.TestCheckResourceAttr(resourceName, "tag_id", fmt.Sprintf("%s|%s|%s", acc.TestDatabaseName, acc.TestSchemaName, tagName)), + resource.TestCheckResourceAttr(resourceName, "tag_id", tagId.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "tag_value", "finance"), ), }, @@ -48,11 +48,11 @@ func TestAcc_TagAssociation(t *testing.T) { } func TestAcc_TagAssociationSchema(t *testing.T) { - tagName := acc.TestClient().Ids.Alpha() + tagId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() resourceName := "snowflake_tag_association.test" m := func() map[string]config.Variable { return map[string]config.Variable{ - "tag_name": config.StringVariable(tagName), + "tag_name": config.StringVariable(tagId.Name()), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), } @@ -77,12 +77,12 @@ func TestAcc_TagAssociationSchema(t *testing.T) { } func TestAcc_TagAssociationColumn(t *testing.T) { - tagName := acc.TestClient().Ids.Alpha() + tagId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() tableName := acc.TestClient().Ids.Alpha() resourceName := "snowflake_tag_association.test" m := func() map[string]config.Variable { return map[string]config.Variable{ - "tag_name": config.StringVariable(tagName), + "tag_name": config.StringVariable(tagId.Name()), "table_name": config.StringVariable(tableName), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), @@ -101,7 +101,7 @@ func TestAcc_TagAssociationColumn(t *testing.T) { ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "object_type", "COLUMN"), - resource.TestCheckResourceAttr(resourceName, "tag_id", fmt.Sprintf("%s|%s|%s", acc.TestDatabaseName, acc.TestSchemaName, tagName)), + resource.TestCheckResourceAttr(resourceName, "tag_id", tagId.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "tag_value", "TAG_VALUE"), resource.TestCheckResourceAttr(resourceName, "object_identifier.0.%", "3"), resource.TestCheckResourceAttr(resourceName, "object_identifier.0.name", fmt.Sprintf("%s.column_name", tableName)), @@ -113,12 +113,12 @@ func TestAcc_TagAssociationColumn(t *testing.T) { } func TestAcc_TagAssociationIssue1202(t *testing.T) { - tagName := acc.TestClient().Ids.Alpha() + tagId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() tableName := acc.TestClient().Ids.Alpha() resourceName := "snowflake_tag_association.test" m := func() map[string]config.Variable { return map[string]config.Variable{ - "tag_name": config.StringVariable(tagName), + "tag_name": config.StringVariable(tagId.Name()), "table_name": config.StringVariable(tableName), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), @@ -137,7 +137,7 @@ func TestAcc_TagAssociationIssue1202(t *testing.T) { ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "object_type", "TABLE"), - resource.TestCheckResourceAttr(resourceName, "tag_id", fmt.Sprintf("%s|%s|%s", acc.TestDatabaseName, acc.TestSchemaName, tagName)), + resource.TestCheckResourceAttr(resourceName, "tag_id", tagId.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "tag_value", "v1"), ), }, @@ -147,7 +147,6 @@ func TestAcc_TagAssociationIssue1202(t *testing.T) { func TestAcc_TagAssociationIssue1909(t *testing.T) { tagId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() - tagName := tagId.Name() tableName := acc.TestClient().Ids.Alpha() tableName2 := acc.TestClient().Ids.Alpha() columnName := "test.column" @@ -156,7 +155,7 @@ func TestAcc_TagAssociationIssue1909(t *testing.T) { objectID2 := sdk.NewTableColumnIdentifier(acc.TestDatabaseName, acc.TestSchemaName, tableName2, columnName) m := func() map[string]config.Variable { return map[string]config.Variable{ - "tag_name": config.StringVariable(tagName), + "tag_name": config.StringVariable(tagId.Name()), "table_name": config.StringVariable(tableName), "table_name2": config.StringVariable(tableName2), "column_name": config.StringVariable("test.column"), @@ -177,7 +176,7 @@ func TestAcc_TagAssociationIssue1909(t *testing.T) { ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "object_type", "COLUMN"), - resource.TestCheckResourceAttr(resourceName, "tag_id", fmt.Sprintf("%s|%s|%s", acc.TestDatabaseName, acc.TestSchemaName, tagName)), + resource.TestCheckResourceAttr(resourceName, "tag_id", tagId.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "tag_value", "v1"), testAccCheckTableColumnTagAssociation(tagId, objectID, "v1"), testAccCheckTableColumnTagAssociation(tagId, objectID2, "v1"), @@ -205,12 +204,12 @@ func testAccCheckTableColumnTagAssociation(tagID sdk.SchemaObjectIdentifier, obj func TestAcc_TagAssociationAccountIssues1910(t *testing.T) { // todo: use role with ORGADMIN in CI (SNOW-1165821) _ = testenvs.GetOrSkipTest(t, testenvs.TestAccountCreate) - tagName := acc.TestClient().Ids.Alpha() + tagId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() accountName := acc.TestClient().Ids.Alpha() resourceName := "snowflake_tag_association.test" m := func() map[string]config.Variable { return map[string]config.Variable{ - "tag_name": config.StringVariable(tagName), + "tag_name": config.StringVariable(tagId.Name()), "account_name": config.StringVariable(accountName), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), @@ -230,7 +229,7 @@ func TestAcc_TagAssociationAccountIssues1910(t *testing.T) { ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "object_type", "ACCOUNT"), - resource.TestCheckResourceAttr(resourceName, "tag_id", fmt.Sprintf("%s|%s|%s", acc.TestDatabaseName, acc.TestSchemaName, tagName)), + resource.TestCheckResourceAttr(resourceName, "tag_id", tagId.Name()), resource.TestCheckResourceAttr(resourceName, "tag_value", "v1"), ), }, @@ -239,13 +238,13 @@ func TestAcc_TagAssociationAccountIssues1910(t *testing.T) { } func TestAcc_TagAssociationIssue1926(t *testing.T) { - tagName := acc.TestClient().Ids.Alpha() + tagId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() tableName := acc.TestClient().Ids.Alpha() resourceName := "snowflake_tag_association.test" columnName := "test.column" m := func() map[string]config.Variable { return map[string]config.Variable{ - "tag_name": config.StringVariable(tagName), + "tag_name": config.StringVariable(tagId.Name()), "table_name": config.StringVariable(tableName), "column_name": config.StringVariable(columnName), "database": config.StringVariable(acc.TestDatabaseName), @@ -275,7 +274,7 @@ func TestAcc_TagAssociationIssue1926(t *testing.T) { ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "object_type", "COLUMN"), - resource.TestCheckResourceAttr(resourceName, "tag_id", fmt.Sprintf("%s|%s|%s", acc.TestDatabaseName, acc.TestSchemaName, tagName)), + resource.TestCheckResourceAttr(resourceName, "tag_id", tagId.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "tag_value", "v1"), resource.TestCheckResourceAttr(resourceName, "object_identifier.0.%", "3"), resource.TestCheckResourceAttr(resourceName, "object_identifier.0.name", fmt.Sprintf("%s.%s", tableName, columnName)), diff --git a/pkg/resources/tag_masking_policy_association.go b/pkg/resources/tag_masking_policy_association.go index f8f570f207..270ac027bd 100644 --- a/pkg/resources/tag_masking_policy_association.go +++ b/pkg/resources/tag_masking_policy_association.go @@ -13,6 +13,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + providerresources "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/snowflake" ) @@ -84,7 +85,8 @@ func TagMaskingPolicyAssociation() *schema.Resource { Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, - Description: "Attach a masking policy to a tag. Requires a current warehouse to be set. Either with SNOWFLAKE_WAREHOUSE env variable or in current session. If no warehouse is provided, a temporary warehouse will be created.", + Description: "Attach a masking policy to a tag. Requires a current warehouse to be set. Either with SNOWFLAKE_WAREHOUSE env variable or in current session. If no warehouse is provided, a temporary warehouse will be created.", + DeprecationMessage: deprecatedResourceDescription(string(providerresources.Tag)), } } diff --git a/pkg/resources/tag_masking_policy_association_acceptance_test.go b/pkg/resources/tag_masking_policy_association_acceptance_test.go index 43da75a3a0..2493681dd1 100644 --- a/pkg/resources/tag_masking_policy_association_acceptance_test.go +++ b/pkg/resources/tag_masking_policy_association_acceptance_test.go @@ -5,12 +5,18 @@ import ( "testing" acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/testenvs" + "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/tfversion" ) func TestAcc_TagMaskingPolicyAssociationBasic(t *testing.T) { + _ = testenvs.GetOrSkipTest(t, testenvs.EnableAcceptance) + acc.TestAccPreCheck(t) + tag, tagCleanup := acc.TestClient().Tag.CreateTag(t) + t.Cleanup(tagCleanup) accName := acc.TestClient().Ids.Alpha() resource.Test(t, resource.TestCase{ @@ -22,10 +28,10 @@ func TestAcc_TagMaskingPolicyAssociationBasic(t *testing.T) { CheckDestroy: nil, Steps: []resource.TestStep{ { - Config: tagAttachmentConfig(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: tagAttachmentConfig(accName, acc.TestDatabaseName, acc.TestSchemaName, tag.ID()), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_tag_masking_policy_association.test", "masking_policy_id", fmt.Sprintf("%s.%s.%s", acc.TestDatabaseName, acc.TestSchemaName, accName)), - resource.TestCheckResourceAttr("snowflake_tag_masking_policy_association.test", "tag_id", fmt.Sprintf("%s.%s.%s", acc.TestDatabaseName, acc.TestSchemaName, accName)), + resource.TestCheckResourceAttr("snowflake_tag_masking_policy_association.test", "tag_id", tag.ID().FullyQualifiedName()), ), }, }, @@ -92,16 +98,8 @@ func TestAcc_TagMaskingPolicyAssociationsystem_functions_integration_testComplet }) } -func tagAttachmentConfig(n string, databaseName string, schemaName string) string { +func tagAttachmentConfig(n string, databaseName string, schemaName string, tagId sdk.SchemaObjectIdentifier) string { return fmt.Sprintf(` -resource "snowflake_tag" "test" { - name = "%[1]v" - database = "%[2]s" - schema = "%[3]s" - allowed_values = [] - comment = "Terraform acceptance test" -} - resource "snowflake_masking_policy" "test" { name = "%[1]v" database = "%[2]s" @@ -116,8 +114,8 @@ resource "snowflake_masking_policy" "test" { } resource "snowflake_tag_masking_policy_association" "test" { - tag_id = "${snowflake_tag.test.database}.${snowflake_tag.test.schema}.${snowflake_tag.test.name}" + tag_id = "\"%s\".\"%s\".\"%s\"" masking_policy_id = "${snowflake_masking_policy.test.database}.${snowflake_masking_policy.test.schema}.${snowflake_masking_policy.test.name}" } -`, n, databaseName, schemaName) +`, n, databaseName, schemaName, tagId.DatabaseName(), tagId.SchemaName(), tagId.Name()) } diff --git a/pkg/resources/testdata/TestAcc_Tag/basic/test.tf b/pkg/resources/testdata/TestAcc_Tag/basic/test.tf deleted file mode 100644 index 10673ee3b9..0000000000 --- a/pkg/resources/testdata/TestAcc_Tag/basic/test.tf +++ /dev/null @@ -1,7 +0,0 @@ -resource "snowflake_tag" "t" { - name = var.name - database = var.database - schema = var.schema - comment = var.comment - allowed_values = var.allowed_values -} diff --git a/pkg/resources/testdata/TestAcc_Tag/basic/variables.tf b/pkg/resources/testdata/TestAcc_Tag/basic/variables.tf deleted file mode 100644 index ba89ff9f86..0000000000 --- a/pkg/resources/testdata/TestAcc_Tag/basic/variables.tf +++ /dev/null @@ -1,19 +0,0 @@ -variable "database" { - type = string -} - -variable "schema" { - type = string -} - -variable "name" { - type = string -} - -variable "comment" { - type = string -} - -variable "allowed_values" { - type = list(string) -} \ No newline at end of file diff --git a/pkg/resources/testdata/TestAcc_TagMaskingPolicyAssociation/basic/test.tf b/pkg/resources/testdata/TestAcc_TagMaskingPolicyAssociation/basic/test.tf index ca8364a3ea..e4fe8efa84 100644 --- a/pkg/resources/testdata/TestAcc_TagMaskingPolicyAssociation/basic/test.tf +++ b/pkg/resources/testdata/TestAcc_TagMaskingPolicyAssociation/basic/test.tf @@ -1,9 +1,11 @@ + resource "snowflake_tag" "test" { - name = var.name - database = var.database - schema = var.schema - comment = var.comment - allowed_values = ["alv1", "alv2"] + name = var.name + database = var.database + schema = var.schema + comment = var.comment + masking_policies = [snowflake_masking_policy.test.fully_qualified_name] + allowed_values = ["alv1", "alv2"] } resource "snowflake_masking_policy" "test" { diff --git a/pkg/schemas/tag_gen.go b/pkg/schemas/tag_gen.go index dc9cc242fe..68eee1df8b 100644 --- a/pkg/schemas/tag_gen.go +++ b/pkg/schemas/tag_gen.go @@ -34,7 +34,9 @@ var ShowTagSchema = map[string]*schema.Schema{ Computed: true, }, "allowed_values": { - Type: schema.TypeInvalid, + // Adjusted manually. + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, Computed: true, }, "owner_role_type": { diff --git a/pkg/sdk/testint/security_integrations_gen_integration_test.go b/pkg/sdk/testint/security_integrations_gen_integration_test.go index 29620dcd0a..3f6ee32ddf 100644 --- a/pkg/sdk/testint/security_integrations_gen_integration_test.go +++ b/pkg/sdk/testint/security_integrations_gen_integration_test.go @@ -780,8 +780,8 @@ func TestInt_SecurityIntegrations(t *testing.T) { enabled: "true", externalOauthIssuer: newIssuer, externalOauthAnyRoleMode: string(sdk.ExternalOauthSecurityIntegrationAnyRoleModeDisable), - externalOauthRsaPublicKey: rsaKey, externalOauthScopeMappingAttribute: "scp", + externalOauthRsaPublicKey: rsaKey, externalOauthRsaPublicKey2: rsaKey, externalOauthBlockedRolesList: role1.Name, externalOauthAudienceList: "foo", diff --git a/templates/resources/tag.md.tmpl b/templates/resources/tag.md.tmpl new file mode 100644 index 0000000000..7a876a0017 --- /dev/null +++ b/templates/resources/tag.md.tmpl @@ -0,0 +1,35 @@ +--- +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 }} +--- + +!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v0980--v0990) to use it. + +# {{.Name}} ({{.Type}}) + +{{ .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 }}