diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 30898f1c5b..bf8805c80a 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -6,7 +6,40 @@ across different versions. ## v0.94.x ➞ v0.95.0 -### snowflake_warehouse resource changes +### New `fully_qualified_name` field in the resources. +We added a new `fully_qualified_name` to snowflake resources. This should help with referencing other resources in fields that expect a fully qualified name. For example, instead of +writing + +```object_name = “\”${snowflake_table.database}\”.\”${snowflake_table.schema}\”.\”${snowflake_table.name}\””``` + + now we can write + +```object_name = snowflake_table.fully_qualified_name``` + +See [example usage](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_privileges_to_account_role). + +Some of the resources are excluded from this change: +- deprecated resources + - `snowflake_database_old` + - `snowflake_oauth_integration` + - `snowflake_saml_integration` +- resources for which fully qualified name is not appropriate + - `snowflake_account_parameter` + - `snowflake_account_password_policy_attachment` + - `snowflake_network_policy_attachment` + - `snowflake_session_parameter` + - `snowflake_table_constraint` + - `snowflake_table_column_masking_policy_application` + - `snowflake_tag_masking_policy_association` + - `snowflake_tag_association` + - `snowflake_user_password_policy_attachment` + - `snowflake_user_public_keys` + - grant resources + +#### *(breaking change)* removed `qualified_name` from `snowflake_masking_policy`, `snowflake_network_rule`, `snowflake_password_policy` and `snowflake_table` +Because of introducing a new `fully_qualified_name` field for all of the resources, `qualified_name` was removed from `snowflake_masking_policy`, `snowflake_network_rule`, `snowflake_password_policy` and `snowflake_table`. Please adjust your configurations. State is automatically migrated. + +### snowflake_user resource changes #### *(breaking change)* user parameters added to snowflake_user resource @@ -461,7 +494,7 @@ resource "snowflake_database" "test" { } ``` -If you had `from_database` set, you should follow our [resource migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/resource_migration.md) to remove +If you had `from_database` set, you should follow our [resource migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/resource_migration.md) to remove the database from state to later import it in the newer version of the provider. Otherwise, it may cause issues when migrating to v0.93.0. For now, we're dropping the possibility to create a clone database from other databases. diff --git a/docs/resources/account.md b/docs/resources/account.md index e8c5ec44c6..add9d60485 100644 --- a/docs/resources/account.md +++ b/docs/resources/account.md @@ -60,6 +60,7 @@ resource "snowflake_account" "ac1" { ### 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. - `is_org_admin` (Boolean) Indicates whether the ORGADMIN role is enabled in an account. If TRUE, the role is enabled. diff --git a/docs/resources/account_password_policy_attachment.md b/docs/resources/account_password_policy_attachment.md index c65a3d706a..9474287ef3 100644 --- a/docs/resources/account_password_policy_attachment.md +++ b/docs/resources/account_password_policy_attachment.md @@ -19,7 +19,7 @@ resource "snowflake_password_policy" "default" { } resource "snowflake_account_password_policy_attachment" "attachment" { - password_policy = snowflake_password_policy.default.qualified_name + password_policy = snowflake_password_policy.default.fully_qualified_name } ``` diff --git a/docs/resources/account_role.md b/docs/resources/account_role.md index 6395b792b1..1be71bb81f 100644 --- a/docs/resources/account_role.md +++ b/docs/resources/account_role.md @@ -39,6 +39,7 @@ resource "snowflake_account_role" "complete" { ### 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 ROLES` for the given role. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/alert.md b/docs/resources/alert.md index 28f6dec8d7..c2906f22ca 100644 --- a/docs/resources/alert.md +++ b/docs/resources/alert.md @@ -47,6 +47,7 @@ resource "snowflake_alert" "alert" { ### 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. 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 ea13b5071a..76613bf024 100644 --- a/docs/resources/api_authentication_integration_with_authorization_code_grant.md +++ b/docs/resources/api_authentication_integration_with_authorization_code_grant.md @@ -60,6 +60,7 @@ resource "snowflake_api_authentication_integration_with_authorization_code_grant ### Read-Only - `describe_output` (List of Object) Outputs the result of `DESCRIBE SECURITY INTEGRATIONS` for the given security integration. (see [below for nested schema](#nestedatt--describe_output)) +- `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 SECURITY INTEGRATIONS` for the given security integration. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/api_authentication_integration_with_client_credentials.md b/docs/resources/api_authentication_integration_with_client_credentials.md index 00ae798573..9adeb93da8 100644 --- a/docs/resources/api_authentication_integration_with_client_credentials.md +++ b/docs/resources/api_authentication_integration_with_client_credentials.md @@ -57,6 +57,7 @@ resource "snowflake_api_authentication_integration_with_client_credentials" "tes ### Read-Only - `describe_output` (List of Object) Outputs the result of `DESCRIBE SECURITY INTEGRATIONS` for the given security integration. (see [below for nested schema](#nestedatt--describe_output)) +- `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 SECURITY INTEGRATIONS` for the given security integration. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/api_authentication_integration_with_jwt_bearer.md b/docs/resources/api_authentication_integration_with_jwt_bearer.md index b58db4dd9f..a804a4d54b 100644 --- a/docs/resources/api_authentication_integration_with_jwt_bearer.md +++ b/docs/resources/api_authentication_integration_with_jwt_bearer.md @@ -61,6 +61,7 @@ resource "snowflake_api_authentication_integration_with_jwt_bearer" "test" { ### Read-Only - `describe_output` (List of Object) Outputs the result of `DESCRIBE SECURITY INTEGRATIONS` for the given security integration. (see [below for nested schema](#nestedatt--describe_output)) +- `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 SECURITY INTEGRATIONS` for the given security integration. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/api_integration.md b/docs/resources/api_integration.md index 7c1294ae58..cb07c8cb9f 100644 --- a/docs/resources/api_integration.md +++ b/docs/resources/api_integration.md @@ -66,6 +66,7 @@ resource "snowflake_api_integration" "gcp" { - `azure_consent_url` (String) - `azure_multi_tenant_app_name` (String) - `created_on` (String) Date and time when the API integration was created. +- `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. ## Import diff --git a/docs/resources/cortex_search_service.md b/docs/resources/cortex_search_service.md index 92e287f4db..0998af5aed 100644 --- a/docs/resources/cortex_search_service.md +++ b/docs/resources/cortex_search_service.md @@ -75,6 +75,7 @@ resource "snowflake_cortex_search_service" "test" { ### Read-Only - `created_on` (String) Creation date for the given Cortex search service. +- `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. ## Import diff --git a/docs/resources/database.md b/docs/resources/database.md index 8371e9d137..fce5a16456 100644 --- a/docs/resources/database.md +++ b/docs/resources/database.md @@ -109,6 +109,7 @@ resource "snowflake_database" "primary" { ### 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. diff --git a/docs/resources/database_role.md b/docs/resources/database_role.md index 43ba32510c..a3cd48ca4a 100644 --- a/docs/resources/database_role.md +++ b/docs/resources/database_role.md @@ -33,6 +33,7 @@ resource "snowflake_database_role" "db_role" { ### 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. ## Import diff --git a/docs/resources/dynamic_table.md b/docs/resources/dynamic_table.md index c43bc04d1f..c1c885fb38 100644 --- a/docs/resources/dynamic_table.md +++ b/docs/resources/dynamic_table.md @@ -52,6 +52,7 @@ resource "snowflake_dynamic_table" "dt" { - `cluster_by` (String) The clustering key for the dynamic table. - `created_on` (String) Time when this dynamic table was created. - `data_timestamp` (String) Timestamp of the data in the base object(s) that is included in the dynamic table. +- `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. - `is_clone` (Boolean) TRUE if the dynamic table has been cloned, else FALSE. - `is_replica` (Boolean) TRUE if the dynamic table is a replica. else FALSE. diff --git a/docs/resources/email_notification_integration.md b/docs/resources/email_notification_integration.md index 2974b15f57..3212dbe1e1 100644 --- a/docs/resources/email_notification_integration.md +++ b/docs/resources/email_notification_integration.md @@ -36,6 +36,7 @@ resource "snowflake_email_notification_integration" "email_int" { ### 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. ## Import diff --git a/docs/resources/external_function.md b/docs/resources/external_function.md index e912577aed..7d776e324e 100644 --- a/docs/resources/external_function.md +++ b/docs/resources/external_function.md @@ -60,6 +60,7 @@ resource "snowflake_external_function" "test_ext_func" { ### Read-Only - `created_on` (String) Date and time when the external function was created. +- `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. diff --git a/docs/resources/external_oauth_integration.md b/docs/resources/external_oauth_integration.md index 616a6c71a6..fc253a218e 100644 --- a/docs/resources/external_oauth_integration.md +++ b/docs/resources/external_oauth_integration.md @@ -86,6 +86,7 @@ resource "snowflake_external_oauth_integration" "test" { ### Read-Only - `describe_output` (List of Object) Outputs the result of `DESCRIBE SECURITY INTEGRATIONS` for the given security integration. (see [below for nested schema](#nestedatt--describe_output)) +- `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. - `related_parameters` (List of Object) Paramteres related to this security integration. (see [below for nested schema](#nestedatt--related_parameters)) - `show_output` (List of Object) Outputs the result of `SHOW SECURITY INTEGRATIONS` for the given security integration. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/external_table.md b/docs/resources/external_table.md index cd68db24f9..6568e55fdc 100644 --- a/docs/resources/external_table.md +++ b/docs/resources/external_table.md @@ -57,6 +57,7 @@ resource "snowflake_external_table" "external_table" { ### 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. - `owner` (String) Name of the role that owns the external table. diff --git a/docs/resources/failover_group.md b/docs/resources/failover_group.md index f166661477..cc3baf344c 100644 --- a/docs/resources/failover_group.md +++ b/docs/resources/failover_group.md @@ -68,6 +68,7 @@ resource "snowflake_failover_group" "target_failover_group" { ### 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. diff --git a/docs/resources/file_format.md b/docs/resources/file_format.md index fad8eda415..b9ce90b978 100644 --- a/docs/resources/file_format.md +++ b/docs/resources/file_format.md @@ -67,6 +67,7 @@ resource "snowflake_file_format" "example_file_format" { ### 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. ## Import diff --git a/docs/resources/function.md b/docs/resources/function.md index a407dabb49..131d4c1fcc 100644 --- a/docs/resources/function.md +++ b/docs/resources/function.md @@ -114,6 +114,7 @@ resource "snowflake_function" "sql_test" { ### 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. diff --git a/docs/resources/grant_ownership.md b/docs/resources/grant_ownership.md index d58aa26be1..4dd448bf73 100644 --- a/docs/resources/grant_ownership.md +++ b/docs/resources/grant_ownership.md @@ -62,7 +62,7 @@ resource "snowflake_database_role" "test" { } resource "snowflake_grant_ownership" "test" { - database_role_name = "\"${snowflake_database_role.test.database}\".\"${snowflake_database_role.test.name}\"" + database_role_name = snowflake_database_role.test.fully_qualified_name outbound_privileges = "REVOKE" on { object_type = "SCHEMA" diff --git a/docs/resources/grant_privileges_to_account_role.md b/docs/resources/grant_privileges_to_account_role.md index d9fb537172..97da6b5105 100644 --- a/docs/resources/grant_privileges_to_account_role.md +++ b/docs/resources/grant_privileges_to_account_role.md @@ -22,6 +22,11 @@ resource "snowflake_database" "db" { name = "database" } +resource "snowflake_schema" "my_schema" { + database = snowflake_database.db.name + name = "my_schema" +} + resource "snowflake_account_role" "db_role" { name = "role_name" } @@ -124,7 +129,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] account_role_name = snowflake_account_role.db_role.name on_schema { - schema_name = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! + schema_name = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } @@ -134,7 +139,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { resource "snowflake_grant_privileges_to_account_role" "example" { account_role_name = snowflake_account_role.db_role.name on_schema { - schema_name = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! + schema_name = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } all_privileges = true with_grant_option = true @@ -174,7 +179,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { account_role_name = snowflake_account_role.db_role.name on_schema_object { object_type = "VIEW" - object_name = "\"${snowflake_database.db.name}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! + object_name = snowflake_view.my_view.fully_qualified_name # note this is a fully qualified name! } } @@ -185,7 +190,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { account_role_name = snowflake_account_role.db_role.name on_schema_object { object_type = "VIEW" - object_name = "\"${snowflake_database.db.name}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! + object_name = snowflake_view.my_view.fully_qualified_name # note this is a fully qualified name! } all_privileges = true with_grant_option = true @@ -214,7 +219,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { on_schema_object { all { object_type_plural = "TABLES" - in_schema = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! + in_schema = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } } @@ -242,7 +247,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { on_schema_object { future { object_type_plural = "TABLES" - in_schema = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! + in_schema = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } } diff --git a/docs/resources/grant_privileges_to_database_role.md b/docs/resources/grant_privileges_to_database_role.md index 711cddcd8b..271388ecf4 100644 --- a/docs/resources/grant_privileges_to_database_role.md +++ b/docs/resources/grant_privileges_to_database_role.md @@ -16,8 +16,17 @@ description: |- ## Example Usage ```terraform +resource "snowflake_database" "db" { + name = "database" +} + +resource "snowflake_schema" "my_schema" { + database = snowflake_database.db.name + name = "my_schema" +} + resource "snowflake_database_role" "db_role" { - database = "database" + database = snowflake_database.db.name name = "db_role_name" } @@ -28,13 +37,13 @@ resource "snowflake_database_role" "db_role" { # list of privileges resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["CREATE", "MONITOR"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_database = snowflake_database_role.db_role.database } # all privileges + grant option resource "snowflake_grant_privileges_to_database_role" "example" { - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_database = snowflake_database_role.db_role.database all_privileges = true with_grant_option = true @@ -42,7 +51,7 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # all privileges + grant option + always apply resource "snowflake_grant_privileges_to_database_role" "example" { - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_database = snowflake_database_role.db_role.database always_apply = true all_privileges = true @@ -56,17 +65,17 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # list of privileges resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema { - schema_name = "\"${snowflake_database_role.db_role.database}\".\"my_schema\"" # note this is a fully qualified name! + schema_name = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } # all privileges + grant option resource "snowflake_grant_privileges_to_database_role" "example" { - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema { - schema_name = "\"${snowflake_database_role.db_role.database}\".\"my_schema\"" # note this is a fully qualified name! + schema_name = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } all_privileges = true with_grant_option = true @@ -75,7 +84,7 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # all schemas in database resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema { all_schemas_in_database = snowflake_database_role.db_role.database } @@ -84,7 +93,7 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # future schemas in database resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema { future_schemas_in_database = snowflake_database_role.db_role.database } @@ -97,19 +106,19 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # list of privileges resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["SELECT", "REFERENCES"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { object_type = "VIEW" - object_name = "\"${snowflake_database_role.db_role.database}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! + object_name = snowflake_view.my_view.fully_qualified_name # note this is a fully qualified name! } } # all privileges + grant option resource "snowflake_grant_privileges_to_database_role" "example" { - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { object_type = "VIEW" - object_name = "\"${snowflake_database_role.db_role.database}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! + object_name = snowflake_view.my_view.fully_qualified_name # note this is a fully qualified name! } all_privileges = true with_grant_option = true @@ -118,7 +127,7 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # all in database resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["SELECT", "INSERT"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { all { object_type_plural = "TABLES" @@ -130,11 +139,11 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # all in schema resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["SELECT", "INSERT"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { all { object_type_plural = "TABLES" - in_schema = "\"${snowflake_database_role.db_role.database}\".\"my_schema\"" # note this is a fully qualified name! + in_schema = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } } @@ -142,7 +151,7 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # future in database resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["SELECT", "INSERT"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { future { object_type_plural = "TABLES" @@ -154,11 +163,11 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # future in schema resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["SELECT", "INSERT"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { future { object_type_plural = "TABLES" - in_schema = "\"${snowflake_database_role.db_role.database}\".\"my_schema\"" # note this is a fully qualified name! + in_schema = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } } diff --git a/docs/resources/managed_account.md b/docs/resources/managed_account.md index 00912bc7b4..cba3fc310e 100644 --- a/docs/resources/managed_account.md +++ b/docs/resources/managed_account.md @@ -42,6 +42,7 @@ resource "snowflake_managed_account" "account" { - `cloud` (String) Cloud in which the managed account is located. - `created_on` (String) Date and time when the managed account was created. +- `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. - `locator` (String) Display name of the managed account. - `region` (String) Snowflake Region in which the managed account is located. diff --git a/docs/resources/masking_policy.md b/docs/resources/masking_policy.md index 82a312076e..6f091a595b 100644 --- a/docs/resources/masking_policy.md +++ b/docs/resources/masking_policy.md @@ -58,8 +58,8 @@ resource "snowflake_masking_policy" "test" { ### 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. -- `qualified_name` (String) Specifies the qualified identifier for the masking policy. ### Nested Schema for `signature` diff --git a/docs/resources/materialized_view.md b/docs/resources/materialized_view.md index c6bab4067f..9579181efe 100644 --- a/docs/resources/materialized_view.md +++ b/docs/resources/materialized_view.md @@ -48,6 +48,7 @@ SQL ### 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. diff --git a/docs/resources/network_policy.md b/docs/resources/network_policy.md index fbfd54c596..db80cda3b9 100644 --- a/docs/resources/network_policy.md +++ b/docs/resources/network_policy.md @@ -48,6 +48,7 @@ resource "snowflake_network_policy" "basic" { ### Read-Only - `describe_output` (List of Object) Outputs the result of `DESCRIBE NETWORK POLICY` for the given network policy. (see [below for nested schema](#nestedatt--describe_output)) +- `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 NETWORK POLICIES` for the given network policy. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/network_rule.md b/docs/resources/network_rule.md index 38bae6e44f..37dc348881 100644 --- a/docs/resources/network_rule.md +++ b/docs/resources/network_rule.md @@ -41,8 +41,8 @@ resource "snowflake_network_rule" "rule" { ### 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. -- `qualified_name` (String) Qualified name of the network rule. ## Import diff --git a/docs/resources/notification_integration.md b/docs/resources/notification_integration.md index 4d289c1ec7..4c430d7929 100644 --- a/docs/resources/notification_integration.md +++ b/docs/resources/notification_integration.md @@ -67,6 +67,7 @@ resource "snowflake_notification_integration" "integration" { - `aws_sqs_external_id` (String, Deprecated) The external ID that Snowflake will use when assuming the AWS role - `aws_sqs_iam_user_arn` (String, Deprecated) The Snowflake user that will attempt to assume the AWS role. - `created_on` (String) Date and time when the notification integration was created. +- `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). - `gcp_pubsub_service_account` (String) The GCP service account identifier that Snowflake will use when assuming the GCP role - `id` (String) The ID of this resource. diff --git a/docs/resources/oauth_integration_for_custom_clients.md b/docs/resources/oauth_integration_for_custom_clients.md index 857fed4f11..8c9f1f7c68 100644 --- a/docs/resources/oauth_integration_for_custom_clients.md +++ b/docs/resources/oauth_integration_for_custom_clients.md @@ -69,6 +69,7 @@ resource "snowflake_oauth_integration_for_custom_clients" "complete" { ### Read-Only - `describe_output` (List of Object) Outputs the result of `DESCRIBE SECURITY INTEGRATION` for the given integration. (see [below for nested schema](#nestedatt--describe_output)) +- `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 SECURITY INTEGRATION` for the given integration. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/oauth_integration_for_partner_applications.md b/docs/resources/oauth_integration_for_partner_applications.md index 9ebac00ebe..2e0c1505b6 100644 --- a/docs/resources/oauth_integration_for_partner_applications.md +++ b/docs/resources/oauth_integration_for_partner_applications.md @@ -56,6 +56,7 @@ resource "snowflake_oauth_integration_for_partner_applications" "test" { ### Read-Only - `describe_output` (List of Object) Outputs the result of `DESCRIBE SECURITY INTEGRATION` for the given integration. (see [below for nested schema](#nestedatt--describe_output)) +- `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 SECURITY INTEGRATION` for the given integration. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/password_policy.md b/docs/resources/password_policy.md index 18529317cf..3214efcf68 100644 --- a/docs/resources/password_policy.md +++ b/docs/resources/password_policy.md @@ -39,5 +39,5 @@ A password policy specifies the requirements that must be met to create and rese ### 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. -- `qualified_name` (String) The qualified name for the password policy. diff --git a/docs/resources/pipe.md b/docs/resources/pipe.md index 1774334af8..59f92f287a 100644 --- a/docs/resources/pipe.md +++ b/docs/resources/pipe.md @@ -50,6 +50,7 @@ resource "snowflake_pipe" "pipe" { ### 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. - `notification_channel` (String) Amazon Resource Name of the Amazon SQS queue for the stage named in the DEFINITION column. - `owner` (String) Name of the role that owns the pipe. diff --git a/docs/resources/procedure.md b/docs/resources/procedure.md index ad04ae8fce..5f51b673a7 100644 --- a/docs/resources/procedure.md +++ b/docs/resources/procedure.md @@ -75,6 +75,7 @@ EOT ### 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. diff --git a/docs/resources/resource_monitor.md b/docs/resources/resource_monitor.md index 2f9c392ba8..2b55092b25 100644 --- a/docs/resources/resource_monitor.md +++ b/docs/resources/resource_monitor.md @@ -52,6 +52,7 @@ resource "snowflake_resource_monitor" "monitor" { ### 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. ## Import diff --git a/docs/resources/role.md b/docs/resources/role.md index 28187f91b5..f30eb5ac9f 100644 --- a/docs/resources/role.md +++ b/docs/resources/role.md @@ -39,6 +39,7 @@ resource "snowflake_role" "complete" { ### 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 ROLES` for the given role. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/row_access_policy.md b/docs/resources/row_access_policy.md index 0f982024db..990c8102e4 100644 --- a/docs/resources/row_access_policy.md +++ b/docs/resources/row_access_policy.md @@ -41,6 +41,7 @@ resource "snowflake_row_access_policy" "example_row_access_policy" { ### 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. ## Import diff --git a/docs/resources/saml2_integration.md b/docs/resources/saml2_integration.md index 62deaf49c4..38ebcacab8 100644 --- a/docs/resources/saml2_integration.md +++ b/docs/resources/saml2_integration.md @@ -75,6 +75,7 @@ resource "snowflake_saml2_integration" "test" { ### Read-Only - `describe_output` (List of Object) Outputs the result of `DESCRIBE SECURITY INTEGRATION` for the given integration. (see [below for nested schema](#nestedatt--describe_output)) +- `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 SECURITY INTEGRATION` for the given integration. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/schema.md b/docs/resources/schema.md index 704a302ce5..a200753683 100644 --- a/docs/resources/schema.md +++ b/docs/resources/schema.md @@ -83,6 +83,7 @@ resource "snowflake_schema" "schema" { ### Read-Only - `describe_output` (List of Object) Outputs the result of `DESCRIBE SCHEMA` for the given object. In order to handle this output, one must grant sufficient privileges, e.g. [grant_ownership](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_ownership) on all objects in the schema. (see [below for nested schema](#nestedatt--describe_output)) +- `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. - `parameters` (List of Object) Outputs the result of `SHOW PARAMETERS IN SCHEMA` for the given object. (see [below for nested schema](#nestedatt--parameters)) - `show_output` (List of Object) Outputs the result of `SHOW SCHEMA` for the given object. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/scim_integration.md b/docs/resources/scim_integration.md index bfa47bf537..ad939a7790 100644 --- a/docs/resources/scim_integration.md +++ b/docs/resources/scim_integration.md @@ -52,6 +52,7 @@ resource "snowflake_scim_integration" "test" { ### Read-Only - `describe_output` (List of Object) Outputs the result of `DESCRIBE SECURITY INTEGRATIONS` for the given security integration. (see [below for nested schema](#nestedatt--describe_output)) +- `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 SECURITY INTEGRATIONS` for the given security integration. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/secondary_database.md b/docs/resources/secondary_database.md index 22f3f3ab11..64cd5cabbf 100644 --- a/docs/resources/secondary_database.md +++ b/docs/resources/secondary_database.md @@ -116,6 +116,7 @@ resource "snowflake_task" "refresh_secondary_database" { ### 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. ## Import diff --git a/docs/resources/sequence.md b/docs/resources/sequence.md index 2b4dfba100..4a2355686d 100644 --- a/docs/resources/sequence.md +++ b/docs/resources/sequence.md @@ -45,7 +45,7 @@ resource "snowflake_sequence" "test_sequence" { ### Read-Only -- `fully_qualified_name` (String) The fully qualified name of the sequence. +- `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. - `next_value` (Number) The increment sequence interval. diff --git a/docs/resources/share.md b/docs/resources/share.md index 4a171639eb..0d2ef8266e 100644 --- a/docs/resources/share.md +++ b/docs/resources/share.md @@ -39,6 +39,7 @@ resource "snowflake_database" "example" { ### 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. ## Import diff --git a/docs/resources/shared_database.md b/docs/resources/shared_database.md index d63ca217fc..591563ac72 100644 --- a/docs/resources/shared_database.md +++ b/docs/resources/shared_database.md @@ -98,6 +98,7 @@ resource "snowflake_shared_database" "test" { ### 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. ## Import diff --git a/docs/resources/stage.md b/docs/resources/stage.md index 418919fe49..314f729cc3 100644 --- a/docs/resources/stage.md +++ b/docs/resources/stage.md @@ -46,6 +46,7 @@ resource "snowflake_stage" "example_stage" { ### 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. diff --git a/docs/resources/storage_integration.md b/docs/resources/storage_integration.md index 6ba5f1581b..5515599972 100644 --- a/docs/resources/storage_integration.md +++ b/docs/resources/storage_integration.md @@ -56,6 +56,7 @@ resource "snowflake_storage_integration" "integration" { - `azure_consent_url` (String) The consent URL that is used to create an Azure Snowflake service principle inside your tenant. - `azure_multi_tenant_app_name` (String) This is the name of the Snowflake client application created for your account. - `created_on` (String) Date and time when the storage integration was created. +- `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. - `storage_aws_external_id` (String) The external ID that Snowflake will use when assuming the AWS role. - `storage_aws_iam_user_arn` (String) The Snowflake user that will attempt to assume the AWS role. diff --git a/docs/resources/stream.md b/docs/resources/stream.md index 5d86bb1f34..8dd7800358 100644 --- a/docs/resources/stream.md +++ b/docs/resources/stream.md @@ -30,7 +30,7 @@ resource "snowflake_stream" "stream" { schema = "schema" name = "stream" - on_table = snowflake_table.table.qualified_name + on_table = snowflake_table.table.fully_qualified_name append_only = false insert_only = false @@ -59,6 +59,7 @@ resource "snowflake_stream" "stream" { ### 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. - `owner` (String) Name of the role that owns the stream. diff --git a/docs/resources/streamlit.md b/docs/resources/streamlit.md index 8071ba7bb5..fdaaee37a7 100644 --- a/docs/resources/streamlit.md +++ b/docs/resources/streamlit.md @@ -59,6 +59,7 @@ resource "snowflake_streamlit" "streamlit" { ### Read-Only - `describe_output` (List of Object) Outputs the result of `DESCRIBE STREAMLIT` for the given streamlit. (see [below for nested schema](#nestedatt--describe_output)) +- `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 STREAMLIT` for the given streamli. (see [below for nested schema](#nestedatt--show_output)) diff --git a/docs/resources/table.md b/docs/resources/table.md index b94590e963..e59d76dcec 100644 --- a/docs/resources/table.md +++ b/docs/resources/table.md @@ -100,9 +100,9 @@ resource "snowflake_table" "table" { ### 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. - `owner` (String) Name of the role that owns the table. -- `qualified_name` (String) Qualified name of the table. ### Nested Schema for `column` diff --git a/docs/resources/table_column_masking_policy_application.md b/docs/resources/table_column_masking_policy_application.md index 710258167a..dbeb682359 100644 --- a/docs/resources/table_column_masking_policy_application.md +++ b/docs/resources/table_column_masking_policy_application.md @@ -59,9 +59,9 @@ resource "snowflake_table" "table" { resource "snowflake_table_column_masking_policy_application" "application" { provider = snowflake.masking # Apply masking policy with masking_admin role - table = snowflake_table.table.qualified_name + table = snowflake_table.table.fully_qualified_name column = "secret" - masking_policy = snowflake_masking_policy.policy.qualified_name + masking_policy = snowflake_masking_policy.policy.fully_qualified_name } ``` diff --git a/docs/resources/table_constraint.md b/docs/resources/table_constraint.md index a7238ffd4b..d8cad4d90f 100644 --- a/docs/resources/table_constraint.md +++ b/docs/resources/table_constraint.md @@ -66,7 +66,7 @@ resource "snowflake_table" "fk_t" { resource "snowflake_table_constraint" "primary_key" { name = "myconstraint" type = "PRIMARY KEY" - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name columns = ["col1"] comment = "hello world" } @@ -74,11 +74,11 @@ resource "snowflake_table_constraint" "primary_key" { resource "snowflake_table_constraint" "foreign_key" { name = "myconstraintfk" type = "FOREIGN KEY" - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name columns = ["col2"] foreign_key_properties { references { - table_id = snowflake_table.fk_t.qualified_name + table_id = snowflake_table.fk_t.fully_qualified_name columns = ["fk_col1"] } } @@ -91,7 +91,7 @@ resource "snowflake_table_constraint" "foreign_key" { resource "snowflake_table_constraint" "unique" { name = "unique" type = "UNIQUE" - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name columns = ["col3"] comment = "hello unique" } diff --git a/docs/resources/tag.md b/docs/resources/tag.md index 189d212184..5d65eda1d3 100644 --- a/docs/resources/tag.md +++ b/docs/resources/tag.md @@ -45,6 +45,7 @@ resource "snowflake_tag" "tag" { ### 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. ## Import diff --git a/docs/resources/tag_masking_policy_association.md b/docs/resources/tag_masking_policy_association.md index 86468abf58..1cd06d980c 100644 --- a/docs/resources/tag_masking_policy_association.md +++ b/docs/resources/tag_masking_policy_association.md @@ -53,8 +53,8 @@ resource "snowflake_masking_policy" "example_masking_policy" { } resource "snowflake_tag_masking_policy_association" "name" { - tag_id = "\"${snowflake_tag.this.database}\".\"${snowflake_tag.this.schema}\".\"${snowflake_tag.this.name}\"" - masking_policy_id = "\"${snowflake_masking_policy.example_masking_policy.database}\".\"${snowflake_masking_policy.example_masking_policy.schema}\".\"${snowflake_masking_policy.example_masking_policy.name}\"" + tag_id = snowflake_tag.this.fully_qualified_name + masking_policy_id = snowflake_masking_policy.example_masking_policy.fully_qualified_name } ``` diff --git a/docs/resources/task.md b/docs/resources/task.md index 5ed71564e9..497184d8b5 100644 --- a/docs/resources/task.md +++ b/docs/resources/task.md @@ -95,6 +95,7 @@ resource "snowflake_task" "test_task" { ### 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. ## Import diff --git a/docs/resources/user.md b/docs/resources/user.md index ff060871c1..3d2082a05f 100644 --- a/docs/resources/user.md +++ b/docs/resources/user.md @@ -121,6 +121,7 @@ resource "snowflake_user" "user" { ### 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). - `has_rsa_public_key` (Boolean) Will be true if user as an RSA key set. - `id` (String) The ID of this resource. - `parameters` (List of Object) Outputs the result of `SHOW PARAMETERS IN USER` for the given user. (see [below for nested schema](#nestedatt--parameters)) diff --git a/docs/resources/user_password_policy_attachment.md b/docs/resources/user_password_policy_attachment.md index 2ca34a9a29..54b38a17cd 100644 --- a/docs/resources/user_password_policy_attachment.md +++ b/docs/resources/user_password_policy_attachment.md @@ -22,7 +22,7 @@ resource "snowflake_password_policy" "pp" { } resource "snowflake_user_password_policy_attachment" "ppa" { - password_policy_name = "\"${snowflake_password_policy.pp.database}\".\"${snowflake_password_policy.pp.schema}\".\"${snowflake_password_policy.pp.name}\"" + password_policy_name = snowflake_password_policy.pp.fully_qualified_name user_name = snowflake_user.user.name } ``` diff --git a/docs/resources/view.md b/docs/resources/view.md index 04d41b8c03..5c665a0fd8 100644 --- a/docs/resources/view.md +++ b/docs/resources/view.md @@ -48,6 +48,7 @@ SQL ### Read-Only - `created_on` (String) The timestamp at which the view was created. +- `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. diff --git a/docs/resources/warehouse.md b/docs/resources/warehouse.md index b6d73ac2c9..f4a9b55a8e 100644 --- a/docs/resources/warehouse.md +++ b/docs/resources/warehouse.md @@ -48,6 +48,7 @@ resource "snowflake_warehouse" "warehouse" { ### 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. - `parameters` (List of Object) Outputs the result of `SHOW PARAMETERS IN WAREHOUSE` for the given warehouse. (see [below for nested schema](#nestedatt--parameters)) - `show_output` (List of Object) Outputs the result of `SHOW WAREHOUSE` for the given warehouse. (see [below for nested schema](#nestedatt--show_output)) diff --git a/examples/resources/snowflake_account_password_policy_attachment/resource.tf b/examples/resources/snowflake_account_password_policy_attachment/resource.tf index ed7ed7a5ab..78ad1868e1 100644 --- a/examples/resources/snowflake_account_password_policy_attachment/resource.tf +++ b/examples/resources/snowflake_account_password_policy_attachment/resource.tf @@ -5,5 +5,5 @@ resource "snowflake_password_policy" "default" { } resource "snowflake_account_password_policy_attachment" "attachment" { - password_policy = snowflake_password_policy.default.qualified_name + password_policy = snowflake_password_policy.default.fully_qualified_name } diff --git a/examples/resources/snowflake_grant_ownership/resource.tf b/examples/resources/snowflake_grant_ownership/resource.tf index 151fff91ec..106c68d924 100644 --- a/examples/resources/snowflake_grant_ownership/resource.tf +++ b/examples/resources/snowflake_grant_ownership/resource.tf @@ -43,7 +43,7 @@ resource "snowflake_database_role" "test" { } resource "snowflake_grant_ownership" "test" { - database_role_name = "\"${snowflake_database_role.test.database}\".\"${snowflake_database_role.test.name}\"" + database_role_name = snowflake_database_role.test.fully_qualified_name outbound_privileges = "REVOKE" on { object_type = "SCHEMA" diff --git a/examples/resources/snowflake_grant_privileges_to_account_role/resource.tf b/examples/resources/snowflake_grant_privileges_to_account_role/resource.tf index d719359907..781507ac04 100644 --- a/examples/resources/snowflake_grant_privileges_to_account_role/resource.tf +++ b/examples/resources/snowflake_grant_privileges_to_account_role/resource.tf @@ -2,6 +2,11 @@ resource "snowflake_database" "db" { name = "database" } +resource "snowflake_schema" "my_schema" { + database = snowflake_database.db.name + name = "my_schema" +} + resource "snowflake_account_role" "db_role" { name = "role_name" } @@ -104,7 +109,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] account_role_name = snowflake_account_role.db_role.name on_schema { - schema_name = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! + schema_name = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } @@ -114,7 +119,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { resource "snowflake_grant_privileges_to_account_role" "example" { account_role_name = snowflake_account_role.db_role.name on_schema { - schema_name = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! + schema_name = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } all_privileges = true with_grant_option = true @@ -154,7 +159,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { account_role_name = snowflake_account_role.db_role.name on_schema_object { object_type = "VIEW" - object_name = "\"${snowflake_database.db.name}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! + object_name = snowflake_view.my_view.fully_qualified_name # note this is a fully qualified name! } } @@ -165,7 +170,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { account_role_name = snowflake_account_role.db_role.name on_schema_object { object_type = "VIEW" - object_name = "\"${snowflake_database.db.name}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! + object_name = snowflake_view.my_view.fully_qualified_name # note this is a fully qualified name! } all_privileges = true with_grant_option = true @@ -194,7 +199,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { on_schema_object { all { object_type_plural = "TABLES" - in_schema = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! + in_schema = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } } @@ -222,7 +227,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { on_schema_object { future { object_type_plural = "TABLES" - in_schema = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! + in_schema = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } } diff --git a/examples/resources/snowflake_grant_privileges_to_database_role/resource.tf b/examples/resources/snowflake_grant_privileges_to_database_role/resource.tf index a5de908db6..4fb825f167 100644 --- a/examples/resources/snowflake_grant_privileges_to_database_role/resource.tf +++ b/examples/resources/snowflake_grant_privileges_to_database_role/resource.tf @@ -1,5 +1,14 @@ +resource "snowflake_database" "db" { + name = "database" +} + +resource "snowflake_schema" "my_schema" { + database = snowflake_database.db.name + name = "my_schema" +} + resource "snowflake_database_role" "db_role" { - database = "database" + database = snowflake_database.db.name name = "db_role_name" } @@ -10,13 +19,13 @@ resource "snowflake_database_role" "db_role" { # list of privileges resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["CREATE", "MONITOR"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_database = snowflake_database_role.db_role.database } # all privileges + grant option resource "snowflake_grant_privileges_to_database_role" "example" { - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_database = snowflake_database_role.db_role.database all_privileges = true with_grant_option = true @@ -24,7 +33,7 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # all privileges + grant option + always apply resource "snowflake_grant_privileges_to_database_role" "example" { - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_database = snowflake_database_role.db_role.database always_apply = true all_privileges = true @@ -38,17 +47,17 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # list of privileges resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema { - schema_name = "\"${snowflake_database_role.db_role.database}\".\"my_schema\"" # note this is a fully qualified name! + schema_name = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } # all privileges + grant option resource "snowflake_grant_privileges_to_database_role" "example" { - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema { - schema_name = "\"${snowflake_database_role.db_role.database}\".\"my_schema\"" # note this is a fully qualified name! + schema_name = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } all_privileges = true with_grant_option = true @@ -57,7 +66,7 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # all schemas in database resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema { all_schemas_in_database = snowflake_database_role.db_role.database } @@ -66,7 +75,7 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # future schemas in database resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema { future_schemas_in_database = snowflake_database_role.db_role.database } @@ -79,19 +88,19 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # list of privileges resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["SELECT", "REFERENCES"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { object_type = "VIEW" - object_name = "\"${snowflake_database_role.db_role.database}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! + object_name = snowflake_view.my_view.fully_qualified_name # note this is a fully qualified name! } } # all privileges + grant option resource "snowflake_grant_privileges_to_database_role" "example" { - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { object_type = "VIEW" - object_name = "\"${snowflake_database_role.db_role.database}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! + object_name = snowflake_view.my_view.fully_qualified_name # note this is a fully qualified name! } all_privileges = true with_grant_option = true @@ -100,7 +109,7 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # all in database resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["SELECT", "INSERT"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { all { object_type_plural = "TABLES" @@ -112,11 +121,11 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # all in schema resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["SELECT", "INSERT"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { all { object_type_plural = "TABLES" - in_schema = "\"${snowflake_database_role.db_role.database}\".\"my_schema\"" # note this is a fully qualified name! + in_schema = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } } @@ -124,7 +133,7 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # future in database resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["SELECT", "INSERT"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { future { object_type_plural = "TABLES" @@ -136,11 +145,11 @@ resource "snowflake_grant_privileges_to_database_role" "example" { # future in schema resource "snowflake_grant_privileges_to_database_role" "example" { privileges = ["SELECT", "INSERT"] - database_role_name = "\"${snowflake_database_role.db_role.database}\".\"${snowflake_database_role.db_role.name}\"" + database_role_name = snowflake_database_role.db_role.fully_qualified_name on_schema_object { future { object_type_plural = "TABLES" - in_schema = "\"${snowflake_database_role.db_role.database}\".\"my_schema\"" # note this is a fully qualified name! + in_schema = snowflake_schema.my_schema.fully_qualified_name # note this is a fully qualified name! } } } diff --git a/examples/resources/snowflake_stream/resource.tf b/examples/resources/snowflake_stream/resource.tf index 231fdb6341..aba5459816 100644 --- a/examples/resources/snowflake_stream/resource.tf +++ b/examples/resources/snowflake_stream/resource.tf @@ -16,7 +16,7 @@ resource "snowflake_stream" "stream" { schema = "schema" name = "stream" - on_table = snowflake_table.table.qualified_name + on_table = snowflake_table.table.fully_qualified_name append_only = false insert_only = false diff --git a/examples/resources/snowflake_table_column_masking_policy_application/resource.tf b/examples/resources/snowflake_table_column_masking_policy_application/resource.tf index 17a8f8f758..3a30afe8b7 100644 --- a/examples/resources/snowflake_table_column_masking_policy_application/resource.tf +++ b/examples/resources/snowflake_table_column_masking_policy_application/resource.tf @@ -40,7 +40,7 @@ resource "snowflake_table" "table" { resource "snowflake_table_column_masking_policy_application" "application" { provider = snowflake.masking # Apply masking policy with masking_admin role - table = snowflake_table.table.qualified_name + table = snowflake_table.table.fully_qualified_name column = "secret" - masking_policy = snowflake_masking_policy.policy.qualified_name + masking_policy = snowflake_masking_policy.policy.fully_qualified_name } diff --git a/examples/resources/snowflake_table_constraint/resource.tf b/examples/resources/snowflake_table_constraint/resource.tf index 58d2747dfe..442003f591 100644 --- a/examples/resources/snowflake_table_constraint/resource.tf +++ b/examples/resources/snowflake_table_constraint/resource.tf @@ -52,7 +52,7 @@ resource "snowflake_table" "fk_t" { resource "snowflake_table_constraint" "primary_key" { name = "myconstraint" type = "PRIMARY KEY" - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name columns = ["col1"] comment = "hello world" } @@ -60,11 +60,11 @@ resource "snowflake_table_constraint" "primary_key" { resource "snowflake_table_constraint" "foreign_key" { name = "myconstraintfk" type = "FOREIGN KEY" - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name columns = ["col2"] foreign_key_properties { references { - table_id = snowflake_table.fk_t.qualified_name + table_id = snowflake_table.fk_t.fully_qualified_name columns = ["fk_col1"] } } @@ -77,7 +77,7 @@ resource "snowflake_table_constraint" "foreign_key" { resource "snowflake_table_constraint" "unique" { name = "unique" type = "UNIQUE" - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name columns = ["col3"] comment = "hello unique" } diff --git a/examples/resources/snowflake_tag_masking_policy_association/resource.tf b/examples/resources/snowflake_tag_masking_policy_association/resource.tf index 4a01c1bce4..94f080aa35 100644 --- a/examples/resources/snowflake_tag_masking_policy_association/resource.tf +++ b/examples/resources/snowflake_tag_masking_policy_association/resource.tf @@ -39,6 +39,6 @@ resource "snowflake_masking_policy" "example_masking_policy" { } resource "snowflake_tag_masking_policy_association" "name" { - tag_id = "\"${snowflake_tag.this.database}\".\"${snowflake_tag.this.schema}\".\"${snowflake_tag.this.name}\"" - masking_policy_id = "\"${snowflake_masking_policy.example_masking_policy.database}\".\"${snowflake_masking_policy.example_masking_policy.schema}\".\"${snowflake_masking_policy.example_masking_policy.name}\"" -} \ No newline at end of file + tag_id = snowflake_tag.this.fully_qualified_name + masking_policy_id = snowflake_masking_policy.example_masking_policy.fully_qualified_name +} diff --git a/examples/resources/snowflake_user_password_policy_attachment/resource.tf b/examples/resources/snowflake_user_password_policy_attachment/resource.tf index e0007b8e8c..45c5de2f3b 100644 --- a/examples/resources/snowflake_user_password_policy_attachment/resource.tf +++ b/examples/resources/snowflake_user_password_policy_attachment/resource.tf @@ -8,6 +8,6 @@ resource "snowflake_password_policy" "pp" { } resource "snowflake_user_password_policy_attachment" "ppa" { - password_policy_name = "\"${snowflake_password_policy.pp.database}\".\"${snowflake_password_policy.pp.schema}\".\"${snowflake_password_policy.pp.name}\"" + password_policy_name = snowflake_password_policy.pp.fully_qualified_name user_name = snowflake_user.user.name } diff --git a/pkg/datasources/testdata/TestAcc_Grants/On/SchemaObject/snowflake_grants_on_schema_object.tf b/pkg/datasources/testdata/TestAcc_Grants/On/SchemaObject/snowflake_grants_on_schema_object.tf index cd40a0d18c..f64d445a33 100644 --- a/pkg/datasources/testdata/TestAcc_Grants/On/SchemaObject/snowflake_grants_on_schema_object.tf +++ b/pkg/datasources/testdata/TestAcc_Grants/On/SchemaObject/snowflake_grants_on_schema_object.tf @@ -11,7 +11,7 @@ resource "snowflake_table" "test" { data "snowflake_grants" "test" { grants_on { - object_name = "\"${snowflake_table.test.database}\".\"${snowflake_table.test.schema}\".\"${snowflake_table.test.name}\"" + object_name = snowflake_table.test.fully_qualified_name object_type = "TABLE" } } diff --git a/pkg/resources/account.go b/pkg/resources/account.go index 57791e88ac..2f41737bdd 100644 --- a/pkg/resources/account.go +++ b/pkg/resources/account.go @@ -9,7 +9,9 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/util" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) @@ -202,6 +204,7 @@ var accountSchema = map[string]*schema.Schema{ Default: 3, Description: "Specifies the number of days to wait before dropping the account. The default is 3 days.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func Account() *schema.Resource { @@ -212,6 +215,10 @@ func Account() *schema.Resource { Update: UpdateAccount, Delete: DeleteAccount, + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), + Schema: accountSchema, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -324,6 +331,10 @@ func ReadAccount(d *schema.ResourceData, meta interface{}) error { return err } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } + if err = d.Set("name", acc.AccountName); err != nil { return fmt.Errorf("error setting name: %w", err) } diff --git a/pkg/resources/account_acceptance_test.go b/pkg/resources/account_acceptance_test.go index 0ec9cb8842..ceb1a5df64 100644 --- a/pkg/resources/account_acceptance_test.go +++ b/pkg/resources/account_acceptance_test.go @@ -15,7 +15,7 @@ import ( func TestAcc_Account_complete(t *testing.T) { _ = testenvs.GetOrSkipTest(t, testenvs.TestAccountCreate) - accountName := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() password := acc.TestClient().Ids.AlphaContaining("123ABC") resource.Test(t, resource.TestCase{ @@ -29,9 +29,10 @@ func TestAcc_Account_complete(t *testing.T) { // unless we change the resource to return nil on destroy then this is unavoidable Steps: []resource.TestStep{ { - Config: accountConfig(accountName, password, "Terraform acceptance test", 3), + Config: accountConfig(id.Name(), password, "Terraform acceptance test", 3), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_account.test", "name", accountName), + resource.TestCheckResourceAttr("snowflake_account.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_account.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_account.test", "admin_name", "someadmin"), resource.TestCheckResourceAttr("snowflake_account.test", "first_name", "Ad"), resource.TestCheckResourceAttr("snowflake_account.test", "last_name", "Min"), @@ -45,7 +46,7 @@ func TestAcc_Account_complete(t *testing.T) { }, // Change Grace Period In Days { - Config: accountConfig(accountName, password, "Terraform acceptance test", 4), + Config: accountConfig(id.Name(), password, "Terraform acceptance test", 4), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_account.test", "grace_period_in_days", "4"), ), diff --git a/pkg/resources/account_password_policy_attachment_acceptance_test.go b/pkg/resources/account_password_policy_attachment_acceptance_test.go index 0132bc8562..dc43401416 100644 --- a/pkg/resources/account_password_policy_attachment_acceptance_test.go +++ b/pkg/resources/account_password_policy_attachment_acceptance_test.go @@ -53,7 +53,7 @@ resource "snowflake_password_policy" "pa" { } resource "snowflake_account_password_policy_attachment" "att" { - password_policy = snowflake_password_policy.pa.qualified_name + password_policy = snowflake_password_policy.pa.fully_qualified_name } ` return fmt.Sprintf(s, databaseName, schemaName, prefix) diff --git a/pkg/resources/account_role.go b/pkg/resources/account_role.go index 25f87ebf01..0626082501 100644 --- a/pkg/resources/account_role.go +++ b/pkg/resources/account_role.go @@ -11,6 +11,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -33,6 +34,7 @@ var accountRoleSchema = map[string]*schema.Schema{ Schema: schemas.ShowRoleSchema, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func AccountRole() *schema.Resource { @@ -45,7 +47,10 @@ func AccountRole() *schema.Resource { UpdateContext: UpdateAccountRole, Description: "The resource is used for role management, where roles can be assigned privileges and, in turn, granted to users and other roles. When granted to roles they can create hierarchies of privilege structures. For more details, refer to the [official documentation](https://docs.snowflake.com/en/user-guide/security-access-control-overview).", - CustomizeDiff: ComputedIfAnyAttributeChanged(ShowOutputAttributeName, "name", "comment"), + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(ShowOutputAttributeName, "name", "comment"), + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -104,6 +109,10 @@ func ReadAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag } } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("name", sdk.NewAccountObjectIdentifier(accountRole.Name).Name()); err != nil { return diag.Diagnostics{ diag.Diagnostic{ diff --git a/pkg/resources/account_role_acceptance_test.go b/pkg/resources/account_role_acceptance_test.go index 8a0dcf6800..9b24568b96 100644 --- a/pkg/resources/account_role_acceptance_test.go +++ b/pkg/resources/account_role_acceptance_test.go @@ -148,6 +148,7 @@ func TestAcc_AccountRole_Complete(t *testing.T) { Config: accountRoleBasicConfig(id.Name(), comment), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("snowflake_account_role.role", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_account_role.role", "comment", comment), resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.#", "1"), @@ -169,6 +170,7 @@ func TestAcc_AccountRole_Complete(t *testing.T) { ImportState: true, ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "fully_qualified_name", id.FullyQualifiedName()), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "comment", comment), ), }, @@ -177,6 +179,7 @@ func TestAcc_AccountRole_Complete(t *testing.T) { Config: accountRoleBasicConfig(newId.Name(), newComment), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("snowflake_account_role.role", "name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_account_role.role", "comment", newComment), resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.#", "1"), diff --git a/pkg/resources/alert.go b/pkg/resources/alert.go index 6e7f48763f..15d7281937 100644 --- a/pkg/resources/alert.go +++ b/pkg/resources/alert.go @@ -11,6 +11,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/util" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -103,6 +104,7 @@ var alertSchema = map[string]*schema.Schema{ Default: false, Description: "Specifies if an alert should be 'started' (enabled) after creation or should remain 'suspended' (default).", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // Alert returns a pointer to the resource representing an alert. @@ -123,9 +125,9 @@ func Alert() *schema.Resource { // ReadAlert implements schema.ReadContextFunc. func ReadAlert(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*provider.Context).Client - objectIdentifier := helpers.DecodeSnowflakeID(d.Id()).(sdk.SchemaObjectIdentifier) + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.SchemaObjectIdentifier) - alert, err := client.Alerts.ShowByID(ctx, objectIdentifier) + alert, err := client.Alerts.ShowByID(ctx, id) if err != nil { // If not found, mark resource to be removed from state file during apply or refresh log.Printf("[DEBUG] alert (%s) not found", d.Id()) @@ -137,6 +139,10 @@ func ReadAlert(ctx context.Context, d *schema.ResourceData, meta interface{}) di return diag.FromErr(err) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("name", alert.Name); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/alert_acceptance_test.go b/pkg/resources/alert_acceptance_test.go index 243b4d6670..7725ddec5f 100644 --- a/pkg/resources/alert_acceptance_test.go +++ b/pkg/resources/alert_acceptance_test.go @@ -33,13 +33,13 @@ type ( ) var ( - alertName = acc.TestClient().Ids.Alpha() + id = acc.TestClient().Ids.RandomSchemaObjectIdentifier() alertInitialState = &AccAlertTestSettings{ //nolint WarehouseName: acc.TestWarehouseName, DatabaseName: acc.TestDatabaseName, Alert: &AlertSettings{ - Name: alertName, + Name: id.Name(), Condition: "select 0 as c", Action: "select 0 as c", Schema: acc.TestSchemaName, @@ -54,7 +54,7 @@ var ( WarehouseName: acc.TestWarehouseName, DatabaseName: acc.TestDatabaseName, Alert: &AlertSettings{ - Name: alertName, + Name: id.Name(), Condition: "select 1 as c", Action: "select 1 as c", Schema: acc.TestSchemaName, @@ -69,7 +69,7 @@ var ( WarehouseName: acc.TestWarehouseName, DatabaseName: acc.TestDatabaseName, Alert: &AlertSettings{ - Name: alertName, + Name: id.Name(), Condition: "select 2 as c", Action: "select 2 as c", Schema: acc.TestSchemaName, @@ -84,7 +84,7 @@ var ( WarehouseName: acc.TestWarehouseName, DatabaseName: acc.TestDatabaseName, Alert: &AlertSettings{ - Name: alertName, + Name: id.Name(), Condition: "select 2 as c", Action: "select 2 as c", Schema: acc.TestSchemaName, @@ -107,7 +107,8 @@ func TestAcc_Alert(t *testing.T) { Config: alertConfig(alertInitialState), Check: resource.ComposeTestCheckFunc( checkBool("snowflake_alert.test_alert", "enabled", alertInitialState.Alert.Enabled), - resource.TestCheckResourceAttr("snowflake_alert.test_alert", "name", alertName), + resource.TestCheckResourceAttr("snowflake_alert.test_alert", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_alert.test_alert", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "condition", alertInitialState.Alert.Condition), @@ -120,7 +121,8 @@ func TestAcc_Alert(t *testing.T) { Config: alertConfig(alertStepOne), Check: resource.ComposeTestCheckFunc( checkBool("snowflake_alert.test_alert", "enabled", alertStepOne.Alert.Enabled), - resource.TestCheckResourceAttr("snowflake_alert.test_alert", "name", alertName), + resource.TestCheckResourceAttr("snowflake_alert.test_alert", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_alert.test_alert", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "condition", alertStepOne.Alert.Condition), @@ -133,7 +135,8 @@ func TestAcc_Alert(t *testing.T) { Config: alertConfig(alertStepTwo), Check: resource.ComposeTestCheckFunc( checkBool("snowflake_alert.test_alert", "enabled", alertStepTwo.Alert.Enabled), - resource.TestCheckResourceAttr("snowflake_alert.test_alert", "name", alertName), + resource.TestCheckResourceAttr("snowflake_alert.test_alert", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_alert.test_alert", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "condition", alertStepTwo.Alert.Condition), @@ -146,7 +149,8 @@ func TestAcc_Alert(t *testing.T) { Config: alertConfig(alertStepThree), Check: resource.ComposeTestCheckFunc( checkBool("snowflake_alert.test_alert", "enabled", alertStepThree.Alert.Enabled), - resource.TestCheckResourceAttr("snowflake_alert.test_alert", "name", alertName), + resource.TestCheckResourceAttr("snowflake_alert.test_alert", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_alert.test_alert", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "condition", alertStepThree.Alert.Condition), @@ -159,7 +163,8 @@ func TestAcc_Alert(t *testing.T) { Config: alertConfig(alertInitialState), Check: resource.ComposeTestCheckFunc( checkBool("snowflake_alert.test_alert", "enabled", alertInitialState.Alert.Enabled), - resource.TestCheckResourceAttr("snowflake_alert.test_alert", "name", alertName), + resource.TestCheckResourceAttr("snowflake_alert.test_alert", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_alert.test_alert", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_alert.test_alert", "condition", alertInitialState.Alert.Condition), diff --git a/pkg/resources/api_authentication_integration_common.go b/pkg/resources/api_authentication_integration_common.go index aafad99b24..66ad533649 100644 --- a/pkg/resources/api_authentication_integration_common.go +++ b/pkg/resources/api_authentication_integration_common.go @@ -81,6 +81,7 @@ var apiAuthCommonSchema = map[string]*schema.Schema{ Schema: schemas.DescribeApiAuthSecurityIntegrationSchema, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } type commonApiAuthSet struct { @@ -268,11 +269,15 @@ func handleApiAuthImport(d *schema.ResourceData, integration *sdk.SecurityIntegr } func handleApiAuthRead(d *schema.ResourceData, + id sdk.AccountObjectIdentifier, integration *sdk.SecurityIntegration, properties []sdk.SecurityIntegrationProperty, withExternalChangesMarking bool, extraFieldsDescribeMappings []describeMapping, ) error { + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } if err := d.Set("name", integration.Name); err != nil { return err } diff --git a/pkg/resources/api_authentication_integration_with_authorization_code_grant.go b/pkg/resources/api_authentication_integration_with_authorization_code_grant.go index 538b6440da..63cb8ca0b4 100644 --- a/pkg/resources/api_authentication_integration_with_authorization_code_grant.go +++ b/pkg/resources/api_authentication_integration_with_authorization_code_grant.go @@ -169,7 +169,7 @@ func ReadContextApiAuthenticationIntegrationWithAuthorizationCodeGrant(withExter return diag.FromErr(err) } - if err := handleApiAuthRead(d, integration, properties, withExternalChangesMarking, []describeMapping{ + if err := handleApiAuthRead(d, id, integration, properties, withExternalChangesMarking, []describeMapping{ {"oauth_authorization_endpoint", "oauth_authorization_endpoint", oauthAuthorizationEndpoint.Value, oauthAuthorizationEndpoint.Value, nil}, {"oauth_allowed_scopes", "oauth_allowed_scopes", oauthAllowedScopes.Value, sdk.ParseCommaSeparatedStringArray(oauthAllowedScopes.Value, false), nil}, }); err != nil { diff --git a/pkg/resources/api_authentication_integration_with_authorization_code_grant_acceptance_test.go b/pkg/resources/api_authentication_integration_with_authorization_code_grant_acceptance_test.go index 046f5d0cc6..5c2ede3700 100644 --- a/pkg/resources/api_authentication_integration_with_authorization_code_grant_acceptance_test.go +++ b/pkg/resources/api_authentication_integration_with_authorization_code_grant_acceptance_test.go @@ -205,6 +205,7 @@ func TestAcc_ApiAuthenticationIntegrationWithAuthorizationCodeGrant_complete(t * resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "comment", "foo"), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "enabled", "true"), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "oauth_access_token_validity", "42"), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "oauth_authorization_endpoint", "https://example.com"), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "oauth_client_auth_method", string(sdk.ApiAuthenticationSecurityIntegrationOauthClientAuthMethodClientSecretPost)), diff --git a/pkg/resources/api_authentication_integration_with_client_credentials.go b/pkg/resources/api_authentication_integration_with_client_credentials.go index d027493ab2..d7eef75457 100644 --- a/pkg/resources/api_authentication_integration_with_client_credentials.go +++ b/pkg/resources/api_authentication_integration_with_client_credentials.go @@ -141,7 +141,7 @@ func ReadContextApiAuthenticationIntegrationWithClientCredentials(withExternalCh return diag.FromErr(err) } - if err := handleApiAuthRead(d, integration, properties, withExternalChangesMarking, []describeMapping{ + if err := handleApiAuthRead(d, id, integration, properties, withExternalChangesMarking, []describeMapping{ {"oauth_allowed_scopes", "oauth_allowed_scopes", oauthAllowedScopes.Value, sdk.ParseCommaSeparatedStringArray(oauthAllowedScopes.Value, false), nil}, }); err != nil { return diag.FromErr(err) diff --git a/pkg/resources/api_authentication_integration_with_client_credentials_acceptance_test.go b/pkg/resources/api_authentication_integration_with_client_credentials_acceptance_test.go index 3b259d8026..061074304b 100644 --- a/pkg/resources/api_authentication_integration_with_client_credentials_acceptance_test.go +++ b/pkg/resources/api_authentication_integration_with_client_credentials_acceptance_test.go @@ -199,6 +199,7 @@ func TestAcc_ApiAuthenticationIntegrationWithClientCredentials_complete(t *testi resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_client_credentials.test", "comment", "foo"), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_client_credentials.test", "enabled", "true"), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_client_credentials.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_client_credentials.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_client_credentials.test", "oauth_access_token_validity", "42"), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_client_credentials.test", "oauth_client_auth_method", string(sdk.ApiAuthenticationSecurityIntegrationOauthClientAuthMethodClientSecretPost)), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_client_credentials.test", "oauth_client_id", "foo"), diff --git a/pkg/resources/api_authentication_integration_with_jwt_bearer.go b/pkg/resources/api_authentication_integration_with_jwt_bearer.go index edc612f56d..73080acb8f 100644 --- a/pkg/resources/api_authentication_integration_with_jwt_bearer.go +++ b/pkg/resources/api_authentication_integration_with_jwt_bearer.go @@ -156,7 +156,7 @@ func ReadContextApiAuthenticationIntegrationWithJwtBearer(withExternalChangesMar if err != nil { return diag.FromErr(err) } - if err := handleApiAuthRead(d, integration, properties, withExternalChangesMarking, []describeMapping{ + if err := handleApiAuthRead(d, id, integration, properties, withExternalChangesMarking, []describeMapping{ {"oauth_authorization_endpoint", "oauth_authorization_endpoint", oauthAuthorizationEndpoint.Value, oauthAuthorizationEndpoint.Value, nil}, {"oauth_assertion_issuer", "oauth_assertion_issuer", oauthAssertionIssuer.Value, oauthAssertionIssuer.Value, nil}, }); err != nil { diff --git a/pkg/resources/api_authentication_integration_with_jwt_bearer_acceptance_test.go b/pkg/resources/api_authentication_integration_with_jwt_bearer_acceptance_test.go index 9f4d24d8ff..b7332e4fb7 100644 --- a/pkg/resources/api_authentication_integration_with_jwt_bearer_acceptance_test.go +++ b/pkg/resources/api_authentication_integration_with_jwt_bearer_acceptance_test.go @@ -163,6 +163,7 @@ func TestAcc_ApiAuthenticationIntegrationWithJwtBearer_complete(t *testing.T) { resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_jwt_bearer.test", "created_on", "foo"), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_jwt_bearer.test", "enabled", "true"), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_jwt_bearer.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_jwt_bearer.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_jwt_bearer.test", "oauth_access_token_validity", "42"), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_jwt_bearer.test", "oauth_authorization_endpoint", "foo"), resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_jwt_bearer.test", "oauth_client_auth_method", "foo"), diff --git a/pkg/resources/api_integration.go b/pkg/resources/api_integration.go index 5f8f3d5aa2..c6d8ffc8d7 100644 --- a/pkg/resources/api_integration.go +++ b/pkg/resources/api_integration.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -114,6 +115,7 @@ var apiIntegrationSchema = map[string]*schema.Schema{ Computed: true, Description: "Date and time when the API integration was created.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // APIIntegration returns a pointer to the resource representing an api integration. @@ -227,6 +229,10 @@ func ReadAPIIntegration(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("expected %v to be an api integration, got %v", id, c) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } + if err := d.Set("name", integration.Name); err != nil { return err } diff --git a/pkg/resources/api_integration_acceptance_test.go b/pkg/resources/api_integration_acceptance_test.go index 3840e62a7c..bd8a975c17 100644 --- a/pkg/resources/api_integration_acceptance_test.go +++ b/pkg/resources/api_integration_acceptance_test.go @@ -293,12 +293,12 @@ func TestAcc_ApiIntegration_changeApiProvider(t *testing.T) { const dummyAzureTenantId = "00000000-0000-0000-0000-000000000000" const dummyAzureAdApplicationId = "22222222-2222-2222-2222-222222222222" - name := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() comment := "acceptance test" key := "12345" m := func() map[string]config.Variable { return map[string]config.Variable{ - "name": config.StringVariable(name), + "name": config.StringVariable(id.Name()), "api_provider": config.StringVariable("aws_api_gateway"), "api_aws_role_arn": config.StringVariable(dummyAwsApiRoleArn), "api_allowed_prefixes": config.ListVariable( @@ -314,7 +314,7 @@ func TestAcc_ApiIntegration_changeApiProvider(t *testing.T) { } m2 := func() map[string]config.Variable { return map[string]config.Variable{ - "name": config.StringVariable(name), + "name": config.StringVariable(id.Name()), "azure_tenant_id": config.StringVariable(dummyAzureTenantId), "azure_ad_application_id": config.StringVariable(dummyAzureAdApplicationId), "api_allowed_prefixes": config.ListVariable( @@ -341,7 +341,8 @@ func TestAcc_ApiIntegration_changeApiProvider(t *testing.T) { ConfigDirectory: config.TestStepDirectory(), ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "name", name), + resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "api_provider", "aws_api_gateway"), resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "api_aws_role_arn", dummyAwsApiRoleArn), resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "api_allowed_prefixes.#", "1"), @@ -360,7 +361,8 @@ func TestAcc_ApiIntegration_changeApiProvider(t *testing.T) { ConfigDirectory: config.TestStepDirectory(), ConfigVariables: m2(), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "name", name), + resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "api_provider", "azure_api_management"), resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "azure_tenant_id", dummyAzureTenantId), resource.TestCheckResourceAttr("snowflake_api_integration.test_change", "azure_ad_application_id", dummyAzureAdApplicationId), diff --git a/pkg/resources/common.go b/pkg/resources/common.go index a2a33a7c1d..d9335e2a46 100644 --- a/pkg/resources/common.go +++ b/pkg/resources/common.go @@ -8,6 +8,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +const FullyQualifiedNameAttributeName = "fully_qualified_name" + // DiffSuppressStatement will suppress diffs between statements if they differ in only case or in // runs of whitespace (\s+ = \s). This is needed because the snowflake api does not faithfully // round-trip queries, so we cannot do a simple character-wise comparison to detect changes. diff --git a/pkg/resources/cortex_search_service.go b/pkg/resources/cortex_search_service.go index bcba7ea224..059e537aca 100644 --- a/pkg/resources/cortex_search_service.go +++ b/pkg/resources/cortex_search_service.go @@ -8,6 +8,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -73,6 +74,7 @@ var cortexSearchServiceSchema = map[string]*schema.Schema{ Computed: true, Description: "Creation date for the given Cortex search service.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // CortexSearchService returns a pointer to the resource representing a Cortex search service. @@ -110,6 +112,9 @@ func ReadCortexSearchService(ctx context.Context, d *schema.ResourceData, meta a } return diag.FromErr(err) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", cortexSearchService.Name); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/cortex_search_service_acceptance_test.go b/pkg/resources/cortex_search_service_acceptance_test.go index d4b831cbea..b99171d43e 100644 --- a/pkg/resources/cortex_search_service_acceptance_test.go +++ b/pkg/resources/cortex_search_service_acceptance_test.go @@ -54,6 +54,7 @@ func TestAcc_CortexSearchService_basic(t *testing.T) { }, 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, "on", "SOME_TEXT"), @@ -75,6 +76,7 @@ func TestAcc_CortexSearchService_basic(t *testing.T) { }, 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, "on", "SOME_TEXT"), diff --git a/pkg/resources/database.go b/pkg/resources/database.go index 63eb9e8271..8090832e75 100644 --- a/pkg/resources/database.go +++ b/pkg/resources/database.go @@ -9,6 +9,7 @@ import ( "time" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/util" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/hashicorp/go-cty/cty" @@ -16,6 +17,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -81,6 +83,7 @@ var databaseSchema = map[string]*schema.Schema{ Optional: true, Description: "Specifies a comment for the database.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func Database() *schema.Resource { @@ -98,7 +101,10 @@ func Database() *schema.Resource { StateContext: schema.ImportStatePassthroughContext, }, - CustomizeDiff: databaseParametersCustomDiff, + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + databaseParametersCustomDiff, + ), StateUpgraders: []schema.StateUpgrader{ { @@ -359,6 +365,10 @@ func ReadDatabase(ctx context.Context, d *schema.ResourceData, meta any) diag.Di return diag.FromErr(err) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("name", database.Name); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/database_acceptance_test.go b/pkg/resources/database_acceptance_test.go index eed0d2691b..d537cca366 100644 --- a/pkg/resources/database_acceptance_test.go +++ b/pkg/resources/database_acceptance_test.go @@ -368,6 +368,7 @@ func TestAcc_Database_Complete(t *testing.T) { ConfigVariables: completeConfigVariables, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_database.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_database.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_database.test", "is_transient", "false"), resource.TestCheckResourceAttr("snowflake_database.test", "comment", comment), @@ -465,12 +466,17 @@ func TestAcc_Database_Update(t *testing.T) { { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Database/basic"), ConfigVariables: basicConfigVariables(id, comment), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_database.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_database.test", "fully_qualified_name", id.FullyQualifiedName()), + ), }, { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Database/complete_optionals_set"), ConfigVariables: completeConfigVariables, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_database.test", "name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_database.test", "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_database.test", "is_transient", "false"), resource.TestCheckResourceAttr("snowflake_database.test", "comment", newComment), diff --git a/pkg/resources/database_role.go b/pkg/resources/database_role.go index 0a0700972f..d44d40a469 100644 --- a/pkg/resources/database_role.go +++ b/pkg/resources/database_role.go @@ -6,6 +6,7 @@ import ( "log" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -30,6 +31,7 @@ var databaseRoleSchema = map[string]*schema.Schema{ Optional: true, Description: "Specifies a comment for the database role.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // DatabaseRole returns a pointer to the resource representing a database role. @@ -51,10 +53,10 @@ func DatabaseRole() *schema.Resource { func ReadDatabaseRole(d *schema.ResourceData, meta interface{}) error { client := meta.(*provider.Context).Client - objectIdentifier := helpers.DecodeSnowflakeID(d.Id()).(sdk.DatabaseObjectIdentifier) + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.DatabaseObjectIdentifier) ctx := context.Background() - databaseRole, err := client.DatabaseRoles.ShowByID(ctx, objectIdentifier) + databaseRole, err := client.DatabaseRoles.ShowByID(ctx, id) if err != nil { // If not found, mark resource to be removed from state file during apply or refresh log.Printf("[DEBUG] database role (%s) not found", d.Id()) @@ -62,11 +64,15 @@ func ReadDatabaseRole(d *schema.ResourceData, meta interface{}) error { return nil } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } + if err := d.Set("name", databaseRole.Name); err != nil { return err } - if err := d.Set("database", objectIdentifier.DatabaseName()); err != nil { + if err := d.Set("database", id.DatabaseName()); err != nil { return err } diff --git a/pkg/resources/database_role_acceptance_test.go b/pkg/resources/database_role_acceptance_test.go index b0373efa75..92738f7de7 100644 --- a/pkg/resources/database_role_acceptance_test.go +++ b/pkg/resources/database_role_acceptance_test.go @@ -14,7 +14,7 @@ import ( func TestAcc_DatabaseRole(t *testing.T) { resourceName := "snowflake_database_role.test_db_role" - dbRoleName := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomDatabaseObjectIdentifier() comment := random.Comment() comment2 := random.Comment() @@ -27,17 +27,19 @@ func TestAcc_DatabaseRole(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.DatabaseRole), Steps: []resource.TestStep{ { - Config: databaseRoleConfig(dbRoleName, acc.TestDatabaseName, comment), + Config: databaseRoleConfig(id.Name(), acc.TestDatabaseName, comment), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", dbRoleName), + resource.TestCheckResourceAttr(resourceName, "name", id.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), resource.TestCheckResourceAttr(resourceName, "comment", comment), ), }, { - Config: databaseRoleConfig(dbRoleName, acc.TestDatabaseName, comment2), + Config: databaseRoleConfig(id.Name(), acc.TestDatabaseName, comment2), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", dbRoleName), + resource.TestCheckResourceAttr(resourceName, "name", id.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), resource.TestCheckResourceAttr(resourceName, "comment", comment2), ), diff --git a/pkg/resources/doc_helpers.go b/pkg/resources/doc_helpers.go index 020f70ce46..9ec0200963 100644 --- a/pkg/resources/doc_helpers.go +++ b/pkg/resources/doc_helpers.go @@ -12,3 +12,15 @@ func possibleValuesListed[T ~string](values []T) string { } return strings.Join(valuesWrapped, " | ") } + +func booleanStringFieldDescription(description string) string { + return fmt.Sprintf(`%s Available options are: "%s" or "%s". When the value is not set in the configuration the provider will put "%s" there which means to use the Snowflake default for this value.`, description, BooleanTrue, BooleanFalse, BooleanDefault) +} + +func externalChangesNotDetectedFieldDescription(description string) string { + return fmt.Sprintf(`%s 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".`, description) +} + +func withPrivilegedRolesDescription(description, paramName string) string { + return fmt.Sprintf(`%s By default, this list includes the ACCOUNTADMIN, ORGADMIN and SECURITYADMIN roles. To remove these privileged roles from the list, use the ALTER ACCOUNT command to set the %s account parameter to FALSE. `, description, paramName) +} diff --git a/pkg/resources/dynamic_table.go b/pkg/resources/dynamic_table.go index 606a2f760f..e8b64b64e4 100644 --- a/pkg/resources/dynamic_table.go +++ b/pkg/resources/dynamic_table.go @@ -8,6 +8,7 @@ import ( "time" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -156,6 +157,7 @@ var dynamicTableSchema = map[string]*schema.Schema{ Description: "Timestamp of the data in the base object(s) that is included in the dynamic table.", Computed: true, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // DynamicTable returns a pointer to the resource representing a dynamic table. @@ -184,6 +186,9 @@ func ReadDynamicTable(d *schema.ResourceData, meta interface{}) error { d.SetId("") return nil } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } if err := d.Set("name", dynamicTable.Name); err != nil { return err } diff --git a/pkg/resources/dynamic_table_acceptance_test.go b/pkg/resources/dynamic_table_acceptance_test.go index 092fa2185b..d7f58fbc37 100644 --- a/pkg/resources/dynamic_table_acceptance_test.go +++ b/pkg/resources/dynamic_table_acceptance_test.go @@ -15,13 +15,13 @@ import ( ) func TestAcc_DynamicTable_basic(t *testing.T) { - name := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() resourceName := "snowflake_dynamic_table.dt" - tableName := name + "_table" + tableName := id.Name() + "_table" newWarehouseName := acc.TestClient().Ids.Alpha() m := func() map[string]config.Variable { return map[string]config.Variable{ - "name": config.StringVariable(name), + "name": config.StringVariable(id.Name()), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), "warehouse": config.StringVariable(acc.TestWarehouseName), @@ -56,7 +56,8 @@ func TestAcc_DynamicTable_basic(t *testing.T) { ConfigDirectory: config.TestStepDirectory(), ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), + 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, "warehouse", acc.TestWarehouseName), @@ -94,7 +95,8 @@ func TestAcc_DynamicTable_basic(t *testing.T) { ConfigDirectory: config.TestStepDirectory(), ConfigVariables: variableSet2, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), + 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, "warehouse", newWarehouseName), diff --git a/pkg/resources/email_notification_integration.go b/pkg/resources/email_notification_integration.go index c75cb4066d..586adfc72d 100644 --- a/pkg/resources/email_notification_integration.go +++ b/pkg/resources/email_notification_integration.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -35,6 +36,7 @@ var emailNotificationIntegrationSchema = map[string]*schema.Schema{ Optional: true, Description: "A comment for the email integration.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // EmailNotificationIntegration returns a pointer to the resource representing a notification integration. @@ -104,6 +106,10 @@ func ReadEmailNotificationIntegration(d *schema.ResourceData, meta interface{}) return err } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } + if err := d.Set("name", integration.Name); err != nil { return err } diff --git a/pkg/resources/email_notification_integration_acceptance_test.go b/pkg/resources/email_notification_integration_acceptance_test.go index db7b422cab..311cc35a4f 100644 --- a/pkg/resources/email_notification_integration_acceptance_test.go +++ b/pkg/resources/email_notification_integration_acceptance_test.go @@ -13,7 +13,7 @@ import ( // TODO [SNOW-1007539]: use email of our service user (verified email address is required) func TestAcc_EmailNotificationIntegration(t *testing.T) { - emailIntegrationName := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() verifiedEmail := "artur.sawicki@snowflake.com" resource.Test(t, resource.TestCase{ @@ -25,9 +25,10 @@ func TestAcc_EmailNotificationIntegration(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.EmailNotificationIntegration), Steps: []resource.TestStep{ { - Config: emailNotificationIntegrationConfig(emailIntegrationName, verifiedEmail), + Config: emailNotificationIntegrationConfig(id.Name(), verifiedEmail), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_email_notification_integration.test", "name", emailIntegrationName), + resource.TestCheckResourceAttr("snowflake_email_notification_integration.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_email_notification_integration.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_email_notification_integration.test", "allowed_recipients.0", verifiedEmail), ), }, diff --git a/pkg/resources/external_function.go b/pkg/resources/external_function.go index e57e43ce51..669c73737d 100644 --- a/pkg/resources/external_function.go +++ b/pkg/resources/external_function.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -177,6 +178,7 @@ var externalFunctionSchema = map[string]*schema.Schema{ Computed: true, Description: "Date and time when the external function was created.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // ExternalFunction returns a pointer to the resource representing an external function. @@ -194,6 +196,9 @@ func ExternalFunction() *schema.Resource { StateContext: schema.ImportStatePassthroughContext, }, + // TODO(SNOW-1348352): add `name` and `arguments` to ComputedIfAnyAttributeChanged for FullyQualifiedNameAttributeName. + // This can't be done now because this function compares values without diff suppress. + StateUpgraders: []schema.StateUpgrader{ { Version: 0, @@ -333,6 +338,9 @@ func ReadContextExternalFunction(ctx context.Context, d *schema.ResourceData, me } // Some properties can come from the SHOW EXTERNAL FUNCTION call + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", externalFunction.Name); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/external_function_acceptance_test.go b/pkg/resources/external_function_acceptance_test.go index d147071fd2..d4b038aa00 100644 --- a/pkg/resources/external_function_acceptance_test.go +++ b/pkg/resources/external_function_acceptance_test.go @@ -152,13 +152,13 @@ func TestAcc_ExternalFunction_no_arguments(t *testing.T) { } func TestAcc_ExternalFunction_complete(t *testing.T) { - accName := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() m := func() map[string]config.Variable { return map[string]config.Variable{ "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), - "name": config.StringVariable(accName), + "name": config.StringVariable(id.Name()), "api_allowed_prefixes": config.ListVariable(config.StringVariable("https://123456.execute-api.us-west-2.amazonaws.com/prod/")), "url_of_proxy_and_resource": config.StringVariable("https://123456.execute-api.us-west-2.amazonaws.com/prod/test_func"), "comment": config.StringVariable("Terraform acceptance test"), @@ -182,7 +182,8 @@ func TestAcc_ExternalFunction_complete(t *testing.T) { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_ExternalFunction/complete"), ConfigVariables: configVariables, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", accName), + 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, "arg.#", "0"), @@ -199,8 +200,8 @@ func TestAcc_ExternalFunction_complete(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "header.0.name", "x-custom-header"), resource.TestCheckResourceAttr(resourceName, "header.0.value", "snowflake"), resource.TestCheckResourceAttr(resourceName, "max_batch_rows", "500"), - resource.TestCheckResourceAttr(resourceName, "request_translator", fmt.Sprintf("%s.%s.%s%s", acc.TestDatabaseName, acc.TestSchemaName, accName, "_request_translator")), - resource.TestCheckResourceAttr(resourceName, "response_translator", fmt.Sprintf("%s.%s.%s%s", acc.TestDatabaseName, acc.TestSchemaName, accName, "_response_translator")), + resource.TestCheckResourceAttr(resourceName, "request_translator", fmt.Sprintf("%s.%s.%s%s", acc.TestDatabaseName, acc.TestSchemaName, id.Name(), "_request_translator")), + resource.TestCheckResourceAttr(resourceName, "response_translator", fmt.Sprintf("%s.%s.%s%s", acc.TestDatabaseName, acc.TestSchemaName, id.Name(), "_response_translator")), ), }, { diff --git a/pkg/resources/external_oauth_integration.go b/pkg/resources/external_oauth_integration.go index 37c91ded28..1b98e1f76d 100644 --- a/pkg/resources/external_oauth_integration.go +++ b/pkg/resources/external_oauth_integration.go @@ -147,6 +147,7 @@ var externalOauthIntegrationSchema = map[string]*schema.Schema{ Schema: schemas.ShowExternalOauthParametersSchema, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func ExternalOauthIntegration() *schema.Resource { @@ -422,6 +423,9 @@ func ReadContextExternalOauthIntegration(withExternalChangesMarking bool) schema if c := integration.Category; c != sdk.SecurityIntegrationCategory { return diag.FromErr(fmt.Errorf("expected %v to be a %s integration, got %v", id, sdk.SecurityIntegrationCategory, c)) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", integration.Name); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/external_oauth_integration_acceptance_test.go b/pkg/resources/external_oauth_integration_acceptance_test.go index 02b5f57b58..93786843d7 100644 --- a/pkg/resources/external_oauth_integration_acceptance_test.go +++ b/pkg/resources/external_oauth_integration_acceptance_test.go @@ -380,6 +380,7 @@ func TestAcc_ExternalOauthIntegration_completeWithJwsKeysUrlAndAllowedRolesList( resource.TestCheckResourceAttr("snowflake_external_oauth_integration.test", "external_oauth_token_user_mapping_claim.#", "1"), resource.TestCheckResourceAttr("snowflake_external_oauth_integration.test", "external_oauth_token_user_mapping_claim.0", "foo"), resource.TestCheckResourceAttr("snowflake_external_oauth_integration.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_external_oauth_integration.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_external_oauth_integration.test", "external_oauth_type", string(sdk.ExternalOauthSecurityIntegrationTypeCustom)), resource.TestCheckResourceAttr("snowflake_external_oauth_integration.test", "show_output.#", "1"), diff --git a/pkg/resources/external_stage_acceptance_test.go b/pkg/resources/external_stage_acceptance_test.go index fb78e3b34e..4daf06d838 100644 --- a/pkg/resources/external_stage_acceptance_test.go +++ b/pkg/resources/external_stage_acceptance_test.go @@ -12,7 +12,7 @@ import ( ) func TestAcc_ExternalStage(t *testing.T) { - accName := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -23,9 +23,10 @@ func TestAcc_ExternalStage(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.Stage), Steps: []resource.TestStep{ { - Config: externalStageConfig(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: externalStageConfig(id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_stage.test", "name", accName), + resource.TestCheckResourceAttr("snowflake_stage.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_stage.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_stage.test", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_stage.test", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_stage.test", "comment", "Terraform acceptance test"), diff --git a/pkg/resources/external_table.go b/pkg/resources/external_table.go index bec15f6938..94cd921cf1 100644 --- a/pkg/resources/external_table.go +++ b/pkg/resources/external_table.go @@ -6,6 +6,7 @@ import ( "log" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -133,7 +134,8 @@ var externalTableSchema = map[string]*schema.Schema{ Computed: true, Description: "Name of the role that owns the external table.", }, - "tag": tagReferenceSchema, + "tag": tagReferenceSchema, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func ExternalTable() *schema.Resource { @@ -256,6 +258,10 @@ func ReadExternalTable(d *schema.ResourceData, meta any) error { return err } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } + if err := d.Set("name", externalTable.Name); err != nil { return err } diff --git a/pkg/resources/external_table_acceptance_test.go b/pkg/resources/external_table_acceptance_test.go index 24f575a5ba..0541a23059 100644 --- a/pkg/resources/external_table_acceptance_test.go +++ b/pkg/resources/external_table_acceptance_test.go @@ -81,6 +81,7 @@ func TestAcc_ExternalTable_basic(t *testing.T) { ConfigVariables: configVariables, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), resource.TestCheckResourceAttr(resourceName, "location", fmt.Sprintf(`@"%s"."%s"."%s"%s`, acc.TestDatabaseName, acc.TestSchemaName, name, innerDirectory)), diff --git a/pkg/resources/failover_group.go b/pkg/resources/failover_group.go index 6d51513345..e873436b58 100644 --- a/pkg/resources/failover_group.go +++ b/pkg/resources/failover_group.go @@ -10,6 +10,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -131,6 +132,7 @@ var failoverGroupSchema = map[string]*schema.Schema{ }, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // FailoverGroup returns a pointer to the resource representing a failover group. @@ -272,6 +274,10 @@ func ReadFailoverGroup(d *schema.ResourceData, meta interface{}) error { return err } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } + if err := d.Set("name", failoverGroup.Name); err != nil { return err } diff --git a/pkg/resources/failover_group_acceptance_test.go b/pkg/resources/failover_group_acceptance_test.go index f44e039ad6..58f68ab0d7 100644 --- a/pkg/resources/failover_group_acceptance_test.go +++ b/pkg/resources/failover_group_acceptance_test.go @@ -16,7 +16,7 @@ func TestAcc_FailoverGroupBasic(t *testing.T) { // TODO [SNOW-1002023]: Unskip; Business Critical Snowflake Edition needed _ = testenvs.GetOrSkipTest(t, testenvs.TestFailoverGroups) - randomCharacters := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() accountName := testenvs.GetOrSkipTest(t, testenvs.BusinessCriticalAccount) resource.Test(t, resource.TestCase{ @@ -28,9 +28,10 @@ func TestAcc_FailoverGroupBasic(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.FailoverGroup), Steps: []resource.TestStep{ { - Config: failoverGroupBasic(randomCharacters, accountName, acc.TestDatabaseName), + Config: failoverGroupBasic(id.Name(), accountName, acc.TestDatabaseName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_failover_group.fg", "name", randomCharacters), + resource.TestCheckResourceAttr("snowflake_failover_group.fg", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_failover_group.fg", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_failover_group.fg", "object_types.#", "4"), resource.TestCheckResourceAttr("snowflake_failover_group.fg", "allowed_accounts.#", "1"), resource.TestCheckResourceAttr("snowflake_failover_group.fg", "allowed_databases.#", "1"), diff --git a/pkg/resources/file_format.go b/pkg/resources/file_format.go index bb6a80bf18..adc751fca6 100644 --- a/pkg/resources/file_format.go +++ b/pkg/resources/file_format.go @@ -8,9 +8,11 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -288,6 +290,7 @@ var fileFormatSchema = map[string]*schema.Schema{ Optional: true, Description: "Specifies a comment for the file format.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } type fileFormatID struct { @@ -315,6 +318,10 @@ func FileFormat() *schema.Resource { Update: UpdateFileFormat, Delete: DeleteFileFormat, + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), + Schema: fileFormatSchema, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -544,6 +551,10 @@ func ReadFileFormat(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("cannot read file format: %w", err) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } + if err := d.Set("name", fileFormat.Name.Name()); err != nil { return err } diff --git a/pkg/resources/file_format_acceptance_test.go b/pkg/resources/file_format_acceptance_test.go index 4b4b0cd3f3..0ec415273f 100644 --- a/pkg/resources/file_format_acceptance_test.go +++ b/pkg/resources/file_format_acceptance_test.go @@ -450,8 +450,8 @@ func TestAcc_FileFormat_issue1947(t *testing.T) { } func TestAcc_FileFormat_Rename(t *testing.T) { - name := acc.TestClient().Ids.Alpha() - newName := acc.TestClient().Ids.Alpha() + oldId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + newId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() comment := random.Comment() newComment := random.Comment() resourceName := "snowflake_file_format.test" @@ -465,16 +465,18 @@ func TestAcc_FileFormat_Rename(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.FileFormat), Steps: []resource.TestStep{ { - Config: fileFormatConfigWithComment(name, acc.TestDatabaseName, acc.TestSchemaName, comment), + Config: fileFormatConfigWithComment(oldId.Name(), acc.TestDatabaseName, acc.TestSchemaName, comment), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "name", oldId.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", oldId.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "comment", comment), ), }, { - Config: fileFormatConfigWithComment(newName, acc.TestDatabaseName, acc.TestSchemaName, newComment), + Config: fileFormatConfigWithComment(newId.Name(), acc.TestDatabaseName, acc.TestSchemaName, newComment), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", newName), + resource.TestCheckResourceAttr(resourceName, "name", newId.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "comment", newComment), ), ConfigPlanChecks: resource.ConfigPlanChecks{ diff --git a/pkg/resources/function.go b/pkg/resources/function.go index f222c9b0a7..d13c61b272 100644 --- a/pkg/resources/function.go +++ b/pkg/resources/function.go @@ -8,10 +8,12 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/snowflake" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) @@ -157,6 +159,7 @@ var functionSchema = map[string]*schema.Schema{ ForceNew: true, Description: "The target path for the Java / Python functions. For Java, it is the path of compiled jar files and for the Python it is the path of the Python files.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func Function() *schema.Resource { @@ -168,6 +171,11 @@ func Function() *schema.Resource { UpdateContext: UpdateContextFunction, DeleteContext: DeleteContextFunction, + CustomizeDiff: customdiff.All( + // TODO(SNOW-1348103): add `arguments` to ComputedIfAnyAttributeChanged. This can't be done now because this function compares values without diff suppress. + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), + Schema: functionSchema, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -521,6 +529,9 @@ func ReadContextFunction(ctx context.Context, d *schema.ResourceData, meta inter if err != nil { return diag.FromErr(err) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", id.Name()); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/function_acceptance_test.go b/pkg/resources/function_acceptance_test.go index b4e99be301..b463874c36 100644 --- a/pkg/resources/function_acceptance_test.go +++ b/pkg/resources/function_acceptance_test.go @@ -271,8 +271,8 @@ func TestAcc_Function_EnsureSmoothResourceIdMigrationToV0950(t *testing.T) { } func TestAcc_Function_Rename(t *testing.T) { - name := acc.TestClient().Ids.Alpha() - newName := acc.TestClient().Ids.Alpha() + oldId := acc.TestClient().Ids.RandomSchemaObjectIdentifierWithArguments(sdk.DataTypeVARCHAR) + newId := acc.TestClient().Ids.RandomSchemaObjectIdentifierWithArguments(sdk.DataTypeVARCHAR) comment := random.Comment() newComment := random.Comment() resourceName := "snowflake_function.f" @@ -286,16 +286,18 @@ func TestAcc_Function_Rename(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.Function), Steps: []resource.TestStep{ { - Config: functionConfig(acc.TestDatabaseName, acc.TestSchemaName, name, comment), + Config: functionConfig(acc.TestDatabaseName, acc.TestSchemaName, oldId.Name(), comment), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "name", oldId.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", oldId.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "comment", comment), ), }, { - Config: functionConfig(acc.TestDatabaseName, acc.TestSchemaName, newName, newComment), + Config: functionConfig(acc.TestDatabaseName, acc.TestSchemaName, newId.Name(), newComment), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", newName), + resource.TestCheckResourceAttr(resourceName, "name", newId.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "comment", newComment), ), ConfigPlanChecks: resource.ConfigPlanChecks{ diff --git a/pkg/resources/internal_stage_acceptance_test.go b/pkg/resources/internal_stage_acceptance_test.go index 11b31c5ccc..c865589db1 100644 --- a/pkg/resources/internal_stage_acceptance_test.go +++ b/pkg/resources/internal_stage_acceptance_test.go @@ -12,7 +12,7 @@ import ( ) func TestAcc_InternalStage(t *testing.T) { - accName := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -23,9 +23,10 @@ func TestAcc_InternalStage(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.Stage), Steps: []resource.TestStep{ { - Config: internalStageConfig(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: internalStageConfig(id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_stage.test", "name", accName), + resource.TestCheckResourceAttr("snowflake_stage.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_stage.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_stage.test", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_stage.test", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_stage.test", "comment", "Terraform acceptance test"), diff --git a/pkg/resources/managed_account.go b/pkg/resources/managed_account.go index bbc1751152..a92d2bf76a 100644 --- a/pkg/resources/managed_account.go +++ b/pkg/resources/managed_account.go @@ -8,6 +8,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/util" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -76,6 +77,7 @@ var managedAccountSchema = map[string]*schema.Schema{ Computed: true, Description: "URL for accessing the managed account, particularly through the web interface.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // ManagedAccount returns a pointer to the resource representing a managed account. @@ -125,7 +127,7 @@ func ReadManagedAccount(d *schema.ResourceData, meta interface{}) error { client := meta.(*provider.Context).Client ctx := context.Background() - objectIdentifier := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) // We have to wait during the first read, since the locator takes some time to appear. // This approach has a downside of not handling correctly the situation where managed account was removed externally. @@ -133,7 +135,7 @@ func ReadManagedAccount(d *schema.ResourceData, meta interface{}) error { var managedAccount *sdk.ManagedAccount var err error err = util.Retry(5, 3*time.Second, func() (error, bool) { - managedAccount, err = client.ManagedAccounts.ShowByID(ctx, objectIdentifier) + managedAccount, err = client.ManagedAccounts.ShowByID(ctx, id) if err != nil { return nil, false } @@ -142,7 +144,9 @@ func ReadManagedAccount(d *schema.ResourceData, meta interface{}) error { if err != nil { return err } - + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } if err := d.Set("name", managedAccount.Name); err != nil { return err } diff --git a/pkg/resources/managed_account_acceptance_test.go b/pkg/resources/managed_account_acceptance_test.go index f5009a1587..0aee50698e 100644 --- a/pkg/resources/managed_account_acceptance_test.go +++ b/pkg/resources/managed_account_acceptance_test.go @@ -20,7 +20,7 @@ func TestAcc_ManagedAccount(t *testing.T) { // TODO [SNOW-1011985]: unskip the tests testenvs.SkipTestIfSet(t, testenvs.SkipManagedAccountTest, "error: 090337 (23001): Number of managed accounts allowed exceeded the limit. Please contact Snowflake support") - accName := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() adminName := acc.TestClient().Ids.Alpha() adminPass := acc.TestClient().Ids.AlphaWithPrefix("A1") @@ -33,9 +33,10 @@ func TestAcc_ManagedAccount(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.ManagedAccount), Steps: []resource.TestStep{ { - Config: managedAccountConfig(accName, adminName, adminPass), + Config: managedAccountConfig(id.Name(), adminName, adminPass), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_managed_account.test", "name", accName), + resource.TestCheckResourceAttr("snowflake_managed_account.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_managed_account.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_managed_account.test", "admin_name", adminName), resource.TestCheckResourceAttr("snowflake_managed_account.test", "admin_password", adminPass), resource.TestCheckResourceAttr("snowflake_managed_account.test", "comment", managedAccountComment), diff --git a/pkg/resources/masking_policy.go b/pkg/resources/masking_policy.go index 46427f128c..b962f8cf81 100644 --- a/pkg/resources/masking_policy.go +++ b/pkg/resources/masking_policy.go @@ -4,9 +4,11 @@ import ( "context" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -106,11 +108,7 @@ var maskingPolicySchema = map[string]*schema.Schema{ Optional: true, Description: "Specifies a comment for the masking policy.", }, - "qualified_name": { - Type: schema.TypeString, - Computed: true, - Description: "Specifies the qualified identifier for the masking policy.", - }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // DatabaseName|SchemaName|MaskingPolicyName. @@ -123,6 +121,10 @@ func MaskingPolicy() *schema.Resource { Update: UpdateMaskingPolicy, Delete: DeleteMaskingPolicy, + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), + Schema: maskingPolicySchema, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -186,13 +188,17 @@ func CreateMaskingPolicy(d *schema.ResourceData, meta interface{}) error { // ReadMaskingPolicy implements schema.ReadFunc. func ReadMaskingPolicy(d *schema.ResourceData, meta interface{}) error { client := meta.(*provider.Context).Client - objectIdentifier := helpers.DecodeSnowflakeID(d.Id()).(sdk.SchemaObjectIdentifier) + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.SchemaObjectIdentifier) ctx := context.Background() - maskingPolicy, err := client.MaskingPolicies.ShowByID(ctx, objectIdentifier) + maskingPolicy, err := client.MaskingPolicies.ShowByID(ctx, id) if err != nil { return err } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } + if err := d.Set("name", maskingPolicy.Name); err != nil { return err } @@ -213,7 +219,7 @@ func ReadMaskingPolicy(d *schema.ResourceData, meta interface{}) error { return err } - maskingPolicyDetails, err := client.MaskingPolicies.Describe(ctx, objectIdentifier) + maskingPolicyDetails, err := client.MaskingPolicies.Describe(ctx, id) if err != nil { return err } @@ -239,9 +245,6 @@ func ReadMaskingPolicy(d *schema.ResourceData, meta interface{}) error { if err := d.Set("signature", signature); err != nil { return err } - if err := d.Set("qualified_name", objectIdentifier.FullyQualifiedName()); err != nil { - return err - } return err } diff --git a/pkg/resources/masking_policy_acceptance_test.go b/pkg/resources/masking_policy_acceptance_test.go index 8a21066153..94c0e5494f 100644 --- a/pkg/resources/masking_policy_acceptance_test.go +++ b/pkg/resources/masking_policy_acceptance_test.go @@ -14,8 +14,8 @@ import ( ) func TestAcc_MaskingPolicy(t *testing.T) { - accName := acc.TestClient().Ids.Alpha() - accName2 := acc.TestClient().Ids.Alpha() + oldId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + newId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() comment := "Terraform acceptance test" comment2 := "Terraform acceptance test 2" resource.Test(t, resource.TestCase{ @@ -27,9 +27,10 @@ func TestAcc_MaskingPolicy(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.MaskingPolicy), Steps: []resource.TestStep{ { - Config: maskingPolicyConfig(accName, accName, comment, acc.TestDatabaseName, acc.TestSchemaName), + Config: maskingPolicyConfig(oldId.Name(), comment, acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_masking_policy.test", "name", accName), + resource.TestCheckResourceAttr("snowflake_masking_policy.test", "name", oldId.Name()), + resource.TestCheckResourceAttr("snowflake_masking_policy.test", "fully_qualified_name", oldId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_masking_policy.test", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_masking_policy.test", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_masking_policy.test", "comment", comment), @@ -43,20 +44,21 @@ func TestAcc_MaskingPolicy(t *testing.T) { }, // rename + change comment { - Config: maskingPolicyConfig(accName, accName2, comment2, acc.TestDatabaseName, acc.TestSchemaName), + Config: maskingPolicyConfig(newId.Name(), comment2, acc.TestDatabaseName, acc.TestSchemaName), ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectResourceAction("snowflake_masking_policy.test", plancheck.ResourceActionUpdate), }, }, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_masking_policy.test", "name", accName2), + resource.TestCheckResourceAttr("snowflake_masking_policy.test", "name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_masking_policy.test", "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_masking_policy.test", "comment", comment2), ), }, // change body and unset comment { - Config: maskingPolicyConfigMultiline(accName, accName2, acc.TestDatabaseName, acc.TestSchemaName), + Config: maskingPolicyConfigMultiline(newId.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_masking_policy.test", "masking_expression", "case\n\twhen current_role() in ('ROLE_A') then\n\t\tval\n\twhen is_role_in_session( 'ROLE_B' ) then\n\t\t'ABC123'\n\telse\n\t\t'******'\nend"), resource.TestCheckResourceAttr("snowflake_masking_policy.test", "comment", ""), @@ -72,7 +74,7 @@ func TestAcc_MaskingPolicy(t *testing.T) { }) } -func maskingPolicyConfig(n string, name string, comment string, databaseName string, schemaName string) string { +func maskingPolicyConfig(name string, comment string, databaseName string, schemaName string) string { return fmt.Sprintf(` resource "snowflake_masking_policy" "test" { name = "%s" @@ -91,7 +93,7 @@ resource "snowflake_masking_policy" "test" { `, name, databaseName, schemaName, comment) } -func maskingPolicyConfigMultiline(n string, name string, databaseName string, schemaName string) string { +func maskingPolicyConfigMultiline(name string, databaseName string, schemaName string) string { return fmt.Sprintf(` resource "snowflake_masking_policy" "test" { name = "%s" @@ -176,3 +178,41 @@ resource "snowflake_masking_policy" "test" { } `, name, databaseName, schemaName) } + +func TestAcc_MaskingPolicy_migrateFromVersion_0_94_1(t *testing.T) { + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + resourceName := "snowflake_masking_policy.test" + comment := "foo" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "snowflake": { + VersionConstraint: "=0.94.1", + Source: "Snowflake-Labs/snowflake", + }, + }, + Config: maskingPolicyConfig(id.Name(), comment, acc.TestDatabaseName, acc.TestSchemaName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", id.Name()), + resource.TestCheckResourceAttr(resourceName, "qualified_name", id.FullyQualifiedName()), + ), + }, + { + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + Config: maskingPolicyConfig(id.Name(), comment, acc.TestDatabaseName, acc.TestSchemaName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", id.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), + resource.TestCheckNoResourceAttr(resourceName, "qualified_name"), + ), + }, + }, + }) +} diff --git a/pkg/resources/materialized_view.go b/pkg/resources/materialized_view.go index 18c16b57c9..e280150418 100644 --- a/pkg/resources/materialized_view.go +++ b/pkg/resources/materialized_view.go @@ -6,10 +6,12 @@ import ( "log" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/snowflake" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -61,7 +63,8 @@ var materializedViewSchema = map[string]*schema.Schema{ ForceNew: true, DiffSuppressFunc: DiffSuppressStatement, }, - "tag": tagReferenceSchema, + "tag": tagReferenceSchema, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // MaterializedView returns a pointer to the resource representing a view. @@ -72,6 +75,10 @@ func MaterializedView() *schema.Resource { Update: UpdateMaterializedView, Delete: DeleteMaterializedView, + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), + Schema: materializedViewSchema, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -142,7 +149,9 @@ func ReadMaterializedView(d *schema.ResourceData, meta interface{}) error { d.SetId("") return nil } - + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } if err := d.Set("name", materializedView.Name); err != nil { return err } diff --git a/pkg/resources/materialized_view_acceptance_test.go b/pkg/resources/materialized_view_acceptance_test.go index 6b24a143ac..f77838c3a1 100644 --- a/pkg/resources/materialized_view_acceptance_test.go +++ b/pkg/resources/materialized_view_acceptance_test.go @@ -160,6 +160,7 @@ func TestAcc_MaterializedView_Rename(t *testing.T) { Config: materializedViewConfig(acc.TestWarehouseName, tableId, viewId, queryEscaped, "Terraform test resource", true, false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_materialized_view.test", "name", viewId.Name()), + resource.TestCheckResourceAttr("snowflake_materialized_view.test", "fully_qualified_name", viewId.FullyQualifiedName()), ), }, // rename with one param change @@ -167,6 +168,7 @@ func TestAcc_MaterializedView_Rename(t *testing.T) { Config: materializedViewConfig(acc.TestWarehouseName, tableId, newViewId, queryEscaped, "Terraform test resource", false, false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_materialized_view.test", "name", newViewId.Name()), + resource.TestCheckResourceAttr("snowflake_materialized_view.test", "fully_qualified_name", newViewId.FullyQualifiedName()), ), }, }, diff --git a/pkg/resources/network_policy.go b/pkg/resources/network_policy.go index 8ca3e82f94..381740912f 100644 --- a/pkg/resources/network_policy.go +++ b/pkg/resources/network_policy.go @@ -79,6 +79,7 @@ var networkPolicySchema = map[string]*schema.Schema{ Schema: schemas.DescribeNetworkPolicySchema, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func NetworkPolicy() *schema.Resource { @@ -111,6 +112,7 @@ func NetworkPolicy() *schema.Resource { "allowed_ip_list", "blocked_ip_list", ), + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), ), Importer: &schema.ResourceImporter{ @@ -184,6 +186,9 @@ func ReadContextNetworkPolicy(ctx context.Context, d *schema.ResourceData, meta }, } } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err = d.Set("name", sdk.NewAccountObjectIdentifier(networkPolicy.Name).Name()); err != nil { return diag.FromErr(err) diff --git a/pkg/resources/network_policy_acceptance_test.go b/pkg/resources/network_policy_acceptance_test.go index e552fe84e5..3c3c538e2a 100644 --- a/pkg/resources/network_policy_acceptance_test.go +++ b/pkg/resources/network_policy_acceptance_test.go @@ -324,6 +324,7 @@ func TestAcc_NetworkPolicy_Rename(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("snowflake_network_policy.test", "id", id.Name()), resource.TestCheckResourceAttr("snowflake_network_policy.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_network_policy.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_network_policy.test", "show_output.0.name", id.Name()), ), }, @@ -337,6 +338,7 @@ func TestAcc_NetworkPolicy_Rename(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("snowflake_network_policy.test", "id", newId.Name()), resource.TestCheckResourceAttr("snowflake_network_policy.test", "name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_network_policy.test", "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_network_policy.test", "show_output.0.name", newId.Name()), ), }, diff --git a/pkg/resources/network_rule.go b/pkg/resources/network_rule.go index 52a6a68daf..8cdac7d036 100644 --- a/pkg/resources/network_rule.go +++ b/pkg/resources/network_rule.go @@ -7,6 +7,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -58,11 +59,7 @@ var networkRuleSchema = map[string]*schema.Schema{ Optional: true, Description: "Specifies a comment for the network rule.", }, - "qualified_name": { - Type: schema.TypeString, - Computed: true, - Description: "Qualified name of the network rule.", - }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // NetworkRule returns a pointer to the resource representing a network rule. @@ -168,7 +165,7 @@ func ReadContextNetworkRule(ctx context.Context, d *schema.ResourceData, meta in if err = d.Set("comment", networkRule.Comment); err != nil { return diag.FromErr(err) } - if err = d.Set("qualified_name", id.FullyQualifiedName()); err != nil { + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/network_rule_acceptance_test.go b/pkg/resources/network_rule_acceptance_test.go index a9102801bb..0c4e274d88 100644 --- a/pkg/resources/network_rule_acceptance_test.go +++ b/pkg/resources/network_rule_acceptance_test.go @@ -121,3 +121,40 @@ resource "snowflake_network_rule" "test" { } `, name, database, schema, networkRuleComment) } + +func TestAcc_NetworkRule_migrateFromVersion_0_94_1(t *testing.T) { + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + resourceName := "snowflake_network_rule.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "snowflake": { + VersionConstraint: "=0.94.1", + Source: "Snowflake-Labs/snowflake", + }, + }, + Config: networkRuleIpv4(id.Name(), acc.TestDatabaseName, acc.TestSchemaName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", id.Name()), + resource.TestCheckResourceAttr(resourceName, "qualified_name", id.FullyQualifiedName()), + ), + }, + { + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + Config: networkRuleIpv4(id.Name(), acc.TestDatabaseName, acc.TestSchemaName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", id.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), + resource.TestCheckNoResourceAttr(resourceName, "qualified_name"), + ), + }, + }, + }) +} diff --git a/pkg/resources/notification_integration.go b/pkg/resources/notification_integration.go index a8db893f6e..a69e474f33 100644 --- a/pkg/resources/notification_integration.go +++ b/pkg/resources/notification_integration.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -144,6 +145,7 @@ var notificationIntegrationSchema = map[string]*schema.Schema{ Computed: true, Description: "The GCP service account identifier that Snowflake will use when assuming the GCP role", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // NotificationIntegration returns a pointer to the resource representing a notification integration. @@ -244,7 +246,9 @@ func ReadNotificationIntegration(d *schema.ResourceData, meta interface{}) error if c := integration.Category; c != "NOTIFICATION" { return fmt.Errorf("expected %v to be a NOTIFICATION integration, got %v", id, c) } - + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } if err := d.Set("name", integration.Name); err != nil { return err } diff --git a/pkg/resources/notification_integration_acceptance_test.go b/pkg/resources/notification_integration_acceptance_test.go index 826bc7f2d8..fc473440aa 100644 --- a/pkg/resources/notification_integration_acceptance_test.go +++ b/pkg/resources/notification_integration_acceptance_test.go @@ -13,7 +13,7 @@ import ( ) func TestAcc_NotificationIntegration_AutoGoogle(t *testing.T) { - accName := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() const gcpPubsubSubscriptionName = "projects/project-1234/subscriptions/sub2" const gcpOtherPubsubSubscriptionName = "projects/project-1234/subscriptions/other" @@ -27,10 +27,11 @@ func TestAcc_NotificationIntegration_AutoGoogle(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.NotificationIntegration), Steps: []resource.TestStep{ { - Config: googleAutoConfig(accName, gcpPubsubSubscriptionName), + Config: googleAutoConfig(id.Name(), gcpPubsubSubscriptionName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_notification_integration.test", "enabled", "true"), - resource.TestCheckResourceAttr("snowflake_notification_integration.test", "name", accName), + resource.TestCheckResourceAttr("snowflake_notification_integration.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_notification_integration.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_notification_integration.test", "notification_provider", "GCP_PUBSUB"), resource.TestCheckResourceAttr("snowflake_notification_integration.test", "gcp_pubsub_subscription_name", gcpPubsubSubscriptionName), resource.TestCheckResourceAttr("snowflake_notification_integration.test", "direction", "INBOUND"), @@ -39,10 +40,11 @@ func TestAcc_NotificationIntegration_AutoGoogle(t *testing.T) { }, // change parameters { - Config: googleAutoConfig(accName, gcpOtherPubsubSubscriptionName), + Config: googleAutoConfig(id.Name(), gcpOtherPubsubSubscriptionName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_notification_integration.test", "enabled", "true"), - resource.TestCheckResourceAttr("snowflake_notification_integration.test", "name", accName), + resource.TestCheckResourceAttr("snowflake_notification_integration.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_notification_integration.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_notification_integration.test", "notification_provider", "GCP_PUBSUB"), resource.TestCheckResourceAttr("snowflake_notification_integration.test", "gcp_pubsub_subscription_name", gcpOtherPubsubSubscriptionName), resource.TestCheckResourceAttr("snowflake_notification_integration.test", "direction", "INBOUND"), diff --git a/pkg/resources/oauth_integration_for_custom_clients.go b/pkg/resources/oauth_integration_for_custom_clients.go index c7b549f3a1..c287b87f95 100644 --- a/pkg/resources/oauth_integration_for_custom_clients.go +++ b/pkg/resources/oauth_integration_for_custom_clients.go @@ -144,6 +144,7 @@ var oauthIntegrationForCustomClientsSchema = map[string]*schema.Schema{ Schema: schemas.DescribeOauthIntegrationForCustomClients, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func OauthIntegrationForCustomClients() *schema.Resource { @@ -371,7 +372,9 @@ func ReadContextOauthIntegrationForCustomClients(withExternalChangesMarking bool if c := integration.Category; c != sdk.SecurityIntegrationCategory { return diag.FromErr(fmt.Errorf("expected %v to be a %s integration, got %v", id, sdk.SecurityIntegrationCategory, c)) } - + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", integration.Name); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/oauth_integration_for_custom_clients_acceptance_test.go b/pkg/resources/oauth_integration_for_custom_clients_acceptance_test.go index 2bc16b4af1..4eccc8625c 100644 --- a/pkg/resources/oauth_integration_for_custom_clients_acceptance_test.go +++ b/pkg/resources/oauth_integration_for_custom_clients_acceptance_test.go @@ -413,6 +413,7 @@ func TestAcc_OauthIntegrationForCustomClients_Complete(t *testing.T) { ConfigVariables: configVariables, Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("snowflake_oauth_integration_for_custom_clients.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_oauth_integration_for_custom_clients.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_oauth_integration_for_custom_clients.test", "oauth_client_type", string(sdk.OauthSecurityIntegrationClientTypeConfidential)), resource.TestCheckResourceAttr("snowflake_oauth_integration_for_custom_clients.test", "oauth_redirect_uri", validUrl), resource.TestCheckResourceAttr("snowflake_oauth_integration_for_custom_clients.test", "enabled", "true"), @@ -467,6 +468,7 @@ func TestAcc_OauthIntegrationForCustomClients_Complete(t *testing.T) { ImportState: true, ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "fully_qualified_name", id.FullyQualifiedName()), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "oauth_client_type", string(sdk.OauthSecurityIntegrationClientTypeConfidential)), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "oauth_redirect_uri", validUrl), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "enabled", "true"), diff --git a/pkg/resources/oauth_integration_for_partner_applications.go b/pkg/resources/oauth_integration_for_partner_applications.go index 4c9c34b1ba..e419ecf6e6 100644 --- a/pkg/resources/oauth_integration_for_partner_applications.go +++ b/pkg/resources/oauth_integration_for_partner_applications.go @@ -105,6 +105,7 @@ var oauthIntegrationForPartnerApplicationsSchema = map[string]*schema.Schema{ Schema: schemas.DescribeOauthIntegrationForPartnerApplications, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func OauthIntegrationForPartnerApplications() *schema.Resource { @@ -288,7 +289,9 @@ func ReadContextOauthIntegrationForPartnerApplications(withExternalChangesMarkin if c := integration.Category; c != sdk.SecurityIntegrationCategory { return diag.FromErr(fmt.Errorf("expected %v to be a %s integration, got %v", id, sdk.SecurityIntegrationCategory, c)) } - + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", sdk.NewAccountObjectIdentifier(integration.Name).Name()); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/oauth_integration_for_partner_applications_acceptance_test.go b/pkg/resources/oauth_integration_for_partner_applications_acceptance_test.go index d3f94e1257..8989040253 100644 --- a/pkg/resources/oauth_integration_for_partner_applications_acceptance_test.go +++ b/pkg/resources/oauth_integration_for_partner_applications_acceptance_test.go @@ -579,6 +579,7 @@ func TestAcc_OauthIntegrationForPartnerApplications_Complete(t *testing.T) { ConfigVariables: configVariables, Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("snowflake_oauth_integration_for_partner_applications.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_oauth_integration_for_partner_applications.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_oauth_integration_for_partner_applications.test", "oauth_client", string(sdk.OauthSecurityIntegrationClientTableauServer)), resource.TestCheckNoResourceAttr("snowflake_oauth_integration_for_partner_applications.test", "oauth_redirect_uri"), resource.TestCheckResourceAttr("snowflake_oauth_integration_for_partner_applications.test", "enabled", "true"), @@ -620,6 +621,7 @@ func TestAcc_OauthIntegrationForPartnerApplications_Complete(t *testing.T) { ImportState: true, ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "fully_qualified_name", id.FullyQualifiedName()), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "oauth_client", string(sdk.OauthSecurityIntegrationClientTableauServer)), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "enabled", "true"), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "oauth_issue_refresh_tokens", "false"), diff --git a/pkg/resources/password_policy.go b/pkg/resources/password_policy.go index 7035fc3895..6886353157 100644 --- a/pkg/resources/password_policy.go +++ b/pkg/resources/password_policy.go @@ -4,9 +4,11 @@ import ( "context" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) @@ -131,11 +133,7 @@ var passwordPolicySchema = map[string]*schema.Schema{ Optional: true, Description: "Adds a comment or overwrites an existing comment for the password policy.", }, - "qualified_name": { - Type: schema.TypeString, - Computed: true, - Description: "The qualified name for the password policy.", - }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func PasswordPolicy() *schema.Resource { @@ -146,6 +144,10 @@ func PasswordPolicy() *schema.Resource { Update: UpdatePasswordPolicy, Delete: DeletePasswordPolicy, + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), + Schema: passwordPolicySchema, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -194,14 +196,13 @@ func CreatePasswordPolicy(d *schema.ResourceData, meta interface{}) error { func ReadPasswordPolicy(d *schema.ResourceData, meta interface{}) error { client := meta.(*provider.Context).Client ctx := context.Background() - objectIdentifier := helpers.DecodeSnowflakeID(d.Id()).(sdk.SchemaObjectIdentifier) + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.SchemaObjectIdentifier) - if err := d.Set("qualified_name", objectIdentifier.FullyQualifiedName()); err != nil { + passwordPolicy, err := client.PasswordPolicies.ShowByID(ctx, id) + if err != nil { return err } - - passwordPolicy, err := client.PasswordPolicies.ShowByID(ctx, objectIdentifier) - if err != nil { + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { return err } @@ -217,7 +218,7 @@ func ReadPasswordPolicy(d *schema.ResourceData, meta interface{}) error { if err := d.Set("comment", passwordPolicy.Comment); err != nil { return err } - passwordPolicyDetails, err := client.PasswordPolicies.Describe(ctx, objectIdentifier) + passwordPolicyDetails, err := client.PasswordPolicies.Describe(ctx, id) if err != nil { return err } diff --git a/pkg/resources/password_policy_acceptance_test.go b/pkg/resources/password_policy_acceptance_test.go index 189bae44d6..6fef84a84d 100644 --- a/pkg/resources/password_policy_acceptance_test.go +++ b/pkg/resources/password_policy_acceptance_test.go @@ -1,11 +1,13 @@ package resources_test import ( + "fmt" "testing" "github.com/hashicorp/terraform-plugin-testing/plancheck" acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + "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" @@ -102,12 +104,12 @@ func TestAcc_PasswordPolicy(t *testing.T) { } func TestAcc_PasswordPolicyMaxAgeDays(t *testing.T) { - name := acc.TestClient().Ids.Alpha() - newName := acc.TestClient().Ids.Alpha() + oldId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + newId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() m := func(maxAgeDays int) map[string]config.Variable { return map[string]config.Variable{ - "name": config.StringVariable(name), + "name": config.StringVariable(oldId.Name()), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), "max_age_days": config.IntegerVariable(maxAgeDays), @@ -115,7 +117,7 @@ func TestAcc_PasswordPolicyMaxAgeDays(t *testing.T) { } configValueWithNewName := m(10) - configValueWithNewName["name"] = config.StringVariable(newName) + configValueWithNewName["name"] = config.StringVariable(newId.Name()) resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -131,6 +133,7 @@ func TestAcc_PasswordPolicyMaxAgeDays(t *testing.T) { ConfigVariables: m(0), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_password_policy.pa", "max_age_days", "0"), + resource.TestCheckResourceAttr("snowflake_password_policy.pa", "fully_qualified_name", oldId.FullyQualifiedName()), ), }, { @@ -152,7 +155,7 @@ func TestAcc_PasswordPolicyMaxAgeDays(t *testing.T) { { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_PasswordPolicy_noOptionals"), ConfigVariables: map[string]config.Variable{ - "name": config.StringVariable(newName), + "name": config.StringVariable(newId.Name()), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), }, @@ -162,14 +165,15 @@ func TestAcc_PasswordPolicyMaxAgeDays(t *testing.T) { }, }, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_password_policy.pa", "name", newName), + resource.TestCheckResourceAttr("snowflake_password_policy.pa", "name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_password_policy.pa", "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_password_policy.pa", "max_age_days", "90"), ), }, { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_PasswordPolicy_noOptionals"), ConfigVariables: map[string]config.Variable{ - "name": config.StringVariable(name), + "name": config.StringVariable(oldId.Name()), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), }, @@ -180,3 +184,49 @@ func TestAcc_PasswordPolicyMaxAgeDays(t *testing.T) { }, }) } + +func TestAcc_PasswordPolicy_migrateFromVersion_0_94_1(t *testing.T) { + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + resourceName := "snowflake_password_policy.pa" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "snowflake": { + VersionConstraint: "=0.94.1", + Source: "Snowflake-Labs/snowflake", + }, + }, + Config: passwordPolicyBasicConfig(id), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", id.Name()), + resource.TestCheckResourceAttr(resourceName, "qualified_name", id.FullyQualifiedName()), + ), + }, + { + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + Config: passwordPolicyBasicConfig(id), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", id.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), + resource.TestCheckNoResourceAttr(resourceName, "qualified_name"), + ), + }, + }, + }) +} + +func passwordPolicyBasicConfig(id sdk.SchemaObjectIdentifier) string { + return fmt.Sprintf(` +resource "snowflake_password_policy" "pa" { + name = "%s" + database = "%s" + schema = "%s" +}`, id.Name(), id.DatabaseName(), id.SchemaName()) +} diff --git a/pkg/resources/pipe.go b/pkg/resources/pipe.go index 6d6ddcc446..208d08e13a 100644 --- a/pkg/resources/pipe.go +++ b/pkg/resources/pipe.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -77,6 +78,7 @@ var pipeSchema = map[string]*schema.Schema{ Optional: true, Description: "Specifies the name of the notification integration used for error notifications.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func Pipe() *schema.Resource { @@ -151,10 +153,10 @@ func CreatePipe(d *schema.ResourceData, meta interface{}) error { // ReadPipe implements schema.ReadFunc. func ReadPipe(d *schema.ResourceData, meta interface{}) error { client := meta.(*provider.Context).Client - objectIdentifier := helpers.DecodeSnowflakeID(d.Id()).(sdk.SchemaObjectIdentifier) + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.SchemaObjectIdentifier) ctx := context.Background() - pipe, err := client.Pipes.ShowByID(ctx, objectIdentifier) + pipe, err := client.Pipes.ShowByID(ctx, id) if err != nil { // If not found, mark resource to be removed from state file during apply or refresh log.Printf("[DEBUG] pipe (%s) not found", d.Id()) @@ -162,6 +164,10 @@ func ReadPipe(d *schema.ResourceData, meta interface{}) error { return nil } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } + if err := d.Set("name", pipe.Name); err != nil { return err } diff --git a/pkg/resources/pipe_acceptance_test.go b/pkg/resources/pipe_acceptance_test.go index 5deb743dfb..de34f99b83 100644 --- a/pkg/resources/pipe_acceptance_test.go +++ b/pkg/resources/pipe_acceptance_test.go @@ -12,7 +12,7 @@ import ( ) func TestAcc_Pipe(t *testing.T) { - accName := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -23,9 +23,10 @@ func TestAcc_Pipe(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.Pipe), Steps: []resource.TestStep{ { - Config: pipeConfig(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: pipeConfig(id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_pipe.test", "name", accName), + resource.TestCheckResourceAttr("snowflake_pipe.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_pipe.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_pipe.test", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_pipe.test", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_pipe.test", "comment", "Terraform acceptance test"), diff --git a/pkg/resources/procedure.go b/pkg/resources/procedure.go index 118bcde253..ac98bb3247 100644 --- a/pkg/resources/procedure.go +++ b/pkg/resources/procedure.go @@ -9,9 +9,11 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) @@ -171,6 +173,7 @@ var procedureSchema = map[string]*schema.Schema{ ForceNew: true, Description: "The handler method for Java / Python procedures.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // Procedure returns a pointer to the resource representing a stored procedure. @@ -183,6 +186,12 @@ func Procedure() *schema.Resource { UpdateContext: UpdateContextProcedure, DeleteContext: DeleteContextProcedure, + // TODO(SNOW-1348106): add `arguments` to ComputedIfAnyAttributeChanged for FullyQualifiedNameAttributeName. + // This can't be done now because this function compares values without diff suppress. + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), + Schema: procedureSchema, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -525,6 +534,9 @@ func ReadContextProcedure(ctx context.Context, d *schema.ResourceData, meta inte client := meta.(*provider.Context).Client id := sdk.NewSchemaObjectIdentifierFromFullyQualifiedName(d.Id()) + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", id.Name()); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/procedure_acceptance_test.go b/pkg/resources/procedure_acceptance_test.go index 29e89243c1..8d7b3b3790 100644 --- a/pkg/resources/procedure_acceptance_test.go +++ b/pkg/resources/procedure_acceptance_test.go @@ -14,16 +14,16 @@ import ( "github.com/hashicorp/terraform-plugin-testing/tfversion" ) -func testAccProcedure(t *testing.T, configDirectory string) { +func testAccProcedure(t *testing.T, configDirectory string, args ...sdk.DataType) { t.Helper() - name := acc.TestClient().Ids.Alpha() - newName := acc.TestClient().Ids.Alpha() + oldId := acc.TestClient().Ids.RandomSchemaObjectIdentifierWithArgumentsOld(args...) + newId := acc.TestClient().Ids.RandomSchemaObjectIdentifierWithArgumentsOld(args...) resourceName := "snowflake_procedure.p" m := func() map[string]config.Variable { return map[string]config.Variable{ - "name": config.StringVariable(name), + "name": config.StringVariable(oldId.Name()), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), "comment": config.StringVariable("Terraform acceptance test"), @@ -31,7 +31,7 @@ func testAccProcedure(t *testing.T, configDirectory string) { } } variableSet2 := m() - variableSet2["name"] = config.StringVariable(newName) + variableSet2["name"] = config.StringVariable(newId.Name()) variableSet2["comment"] = config.StringVariable("Terraform acceptance test - updated") variableSet2["execute_as"] = config.StringVariable("OWNER") @@ -52,7 +52,8 @@ func testAccProcedure(t *testing.T, configDirectory string) { ConfigDirectory: acc.ConfigurationDirectory(configDirectory), ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "name", oldId.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", oldId.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test"), @@ -76,7 +77,8 @@ func testAccProcedure(t *testing.T, configDirectory string) { }, }, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", newName), + resource.TestCheckResourceAttr(resourceName, "name", newId.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "database", acc.TestDatabaseName), resource.TestCheckResourceAttr(resourceName, "schema", acc.TestSchemaName), resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test - updated"), @@ -98,7 +100,7 @@ func testAccProcedure(t *testing.T, configDirectory string) { } func TestAcc_Procedure_SQL(t *testing.T) { - testAccProcedure(t, "TestAcc_Procedure/sql") + testAccProcedure(t, "TestAcc_Procedure/sql", sdk.DataTypeVARCHAR) } /* @@ -113,11 +115,11 @@ func TestAcc_Procedure_Javascript(t *testing.T) { } func TestAcc_Procedure_Java(t *testing.T) { - testAccProcedure(t, "TestAcc_Procedure/java") + testAccProcedure(t, "TestAcc_Procedure/java", sdk.DataTypeVARCHAR, sdk.DataTypeVARCHAR) } func TestAcc_Procedure_Scala(t *testing.T) { - testAccProcedure(t, "TestAcc_Procedure/scala") + testAccProcedure(t, "TestAcc_Procedure/scala", sdk.DataTypeVARCHAR, sdk.DataTypeVARCHAR) } func TestAcc_Procedure_complex(t *testing.T) { diff --git a/pkg/resources/resource_monitor.go b/pkg/resources/resource_monitor.go index a79f52d245..bf862b715b 100644 --- a/pkg/resources/resource_monitor.go +++ b/pkg/resources/resource_monitor.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -99,6 +100,7 @@ var resourceMonitorSchema = map[string]*schema.Schema{ Description: "A list of warehouses to apply the resource monitor to.", Elem: &schema.Schema{Type: schema.TypeString}, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // ResourceMonitor returns a pointer to the resource representing a resource monitor. @@ -229,13 +231,16 @@ func CreateResourceMonitor(d *schema.ResourceData, meta interface{}) error { // ReadResourceMonitor implements schema.ReadFunc. func ReadResourceMonitor(d *schema.ResourceData, meta interface{}) error { client := meta.(*provider.Context).Client - objectIdentifier := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) ctx := context.Background() - resourceMonitor, err := client.ResourceMonitors.ShowByID(ctx, objectIdentifier) + resourceMonitor, err := client.ResourceMonitors.ShowByID(ctx, id) if err != nil { return err } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } if err := d.Set("name", resourceMonitor.Name); err != nil { return err diff --git a/pkg/resources/resource_monitor_acceptance_test.go b/pkg/resources/resource_monitor_acceptance_test.go index 7d207a0bf0..54aeaf7146 100644 --- a/pkg/resources/resource_monitor_acceptance_test.go +++ b/pkg/resources/resource_monitor_acceptance_test.go @@ -18,7 +18,7 @@ import ( func TestAcc_ResourceMonitor(t *testing.T) { // TODO test more attributes - name := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -29,9 +29,10 @@ func TestAcc_ResourceMonitor(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.ResourceMonitor), Steps: []resource.TestStep{ { - Config: resourceMonitorConfig(name, acc.TestWarehouseName), + Config: resourceMonitorConfig(id.Name(), acc.TestWarehouseName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "name", name), + resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "credit_quota", "100"), resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "set_for_account", "false"), resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "notify_triggers.0", "40"), @@ -41,9 +42,10 @@ func TestAcc_ResourceMonitor(t *testing.T) { }, // CHANGE PROPERTIES { - Config: resourceMonitorConfig2(name, 75), + Config: resourceMonitorConfig2(id.Name(), 75), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "name", name), + resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "credit_quota", "150"), resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "set_for_account", "true"), resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "notify_triggers.0", "50"), @@ -53,9 +55,10 @@ func TestAcc_ResourceMonitor(t *testing.T) { }, // CHANGE JUST suspend_trigger; proves https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2316 { - Config: resourceMonitorConfig2(name, 60), + Config: resourceMonitorConfig2(id.Name(), 60), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "name", name), + resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "credit_quota", "150"), resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "set_for_account", "true"), resource.TestCheckResourceAttr("snowflake_resource_monitor.test", "notify_triggers.0", "50"), diff --git a/pkg/resources/row_access_policy.go b/pkg/resources/row_access_policy.go index f0b119621f..544ec1cad2 100644 --- a/pkg/resources/row_access_policy.go +++ b/pkg/resources/row_access_policy.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -50,6 +51,7 @@ var rowAccessPolicySchema = map[string]*schema.Schema{ Optional: true, Description: "Specifies a comment for the row access policy.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // RowAccessPolicy returns a pointer to the resource representing a row access policy. @@ -115,6 +117,9 @@ func ReadRowAccessPolicy(d *schema.ResourceData, meta interface{}) error { d.SetId("") return nil } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } if err := d.Set("name", rowAccessPolicy.Name); err != nil { return err diff --git a/pkg/resources/row_access_policy_acceptance_test.go b/pkg/resources/row_access_policy_acceptance_test.go index a24ed1f656..c9544c203a 100644 --- a/pkg/resources/row_access_policy_acceptance_test.go +++ b/pkg/resources/row_access_policy_acceptance_test.go @@ -12,10 +12,10 @@ import ( ) func TestAcc_RowAccessPolicy(t *testing.T) { - name := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() m := func() map[string]config.Variable { return map[string]config.Variable{ - "name": config.StringVariable(name), + "name": config.StringVariable(id.Name()), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), } @@ -33,7 +33,8 @@ func TestAcc_RowAccessPolicy(t *testing.T) { ConfigDirectory: config.TestStepDirectory(), ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "name", name), + resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "comment", "Terraform acceptance test"), @@ -47,7 +48,8 @@ func TestAcc_RowAccessPolicy(t *testing.T) { ConfigDirectory: config.TestStepDirectory(), ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "name", name), + resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "comment", "Terraform acceptance test - changed comment"), @@ -61,7 +63,8 @@ func TestAcc_RowAccessPolicy(t *testing.T) { ConfigDirectory: config.TestStepDirectory(), ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "name", name), + resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_row_access_policy.test", "comment", "Terraform acceptance test - changed comment"), diff --git a/pkg/resources/saml2_integration.go b/pkg/resources/saml2_integration.go index f1261391fc..82a834d44e 100644 --- a/pkg/resources/saml2_integration.go +++ b/pkg/resources/saml2_integration.go @@ -149,6 +149,7 @@ var saml2IntegrationSchema = map[string]*schema.Schema{ Schema: schemas.DescribeSaml2IntegrationSchema, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func SAML2Integration() *schema.Resource { @@ -478,6 +479,9 @@ func ReadContextSAML2Integration(withExternalChangesMarking bool) schema.ReadCon if c := integration.Category; c != sdk.SecurityIntegrationCategory { return diag.FromErr(fmt.Errorf("expected %v to be a %s integration, got %v", id, sdk.SecurityIntegrationCategory, c)) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", sdk.NewAccountObjectIdentifier(integration.Name).Name()); err != nil { return diag.FromErr(err) diff --git a/pkg/resources/saml2_integration_acceptance_test.go b/pkg/resources/saml2_integration_acceptance_test.go index 318fafd3c4..fc3d112852 100644 --- a/pkg/resources/saml2_integration_acceptance_test.go +++ b/pkg/resources/saml2_integration_acceptance_test.go @@ -592,6 +592,7 @@ func TestAcc_Saml2Integration_complete(t *testing.T) { ConfigVariables: m(), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("snowflake_saml2_integration.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_saml2_integration.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_saml2_integration.test", "enabled", "true"), resource.TestCheckResourceAttr("snowflake_saml2_integration.test", "saml2_issuer", issuer), resource.TestCheckResourceAttr("snowflake_saml2_integration.test", "saml2_sso_url", validUrl), @@ -648,6 +649,7 @@ func TestAcc_Saml2Integration_complete(t *testing.T) { ImportState: true, ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "fully_qualified_name", id.FullyQualifiedName()), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "enabled", "true"), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "saml2_issuer", issuer), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "saml2_sso_url", validUrl), diff --git a/pkg/resources/schema.go b/pkg/resources/schema.go index 57c2baf88b..2a0e39ef79 100644 --- a/pkg/resources/schema.go +++ b/pkg/resources/schema.go @@ -82,6 +82,7 @@ var schemaSchema = map[string]*schema.Schema{ Schema: schemas.ShowSchemaParametersSchema, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // Schema returns a pointer to the resource representing a schema. @@ -98,6 +99,7 @@ func Schema() *schema.Resource { CustomizeDiff: customdiff.All( ComputedIfAnyAttributeChanged(ShowOutputAttributeName, "name", "comment", "with_managed_access", "is_transient"), ComputedIfAnyAttributeChanged(DescribeOutputAttributeName, "name"), + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), // TODO [SNOW-1348101]: use list from schema parameters definition instead listing all here (after moving to the SDK) ComputedIfAnyAttributeChanged(ParametersAttributeName, strings.ToLower(string(sdk.ObjectParameterDataRetentionTimeInDays)), @@ -254,6 +256,9 @@ func ReadContextSchema(withExternalChangesMarking bool) schema.ReadContextFunc { } return diag.FromErr(err) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", schema.Name); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/schema_acceptance_test.go b/pkg/resources/schema_acceptance_test.go index d07397a08e..fe0d041f81 100644 --- a/pkg/resources/schema_acceptance_test.go +++ b/pkg/resources/schema_acceptance_test.go @@ -402,8 +402,8 @@ func TestAcc_Schema_complete(t *testing.T) { } func TestAcc_Schema_Rename(t *testing.T) { - oldSchemaName := acc.TestClient().Ids.Alpha() - newSchemaName := acc.TestClient().Ids.Alpha() + oldId := acc.TestClient().Ids.RandomDatabaseObjectIdentifier() + newId := acc.TestClient().Ids.RandomDatabaseObjectIdentifier() comment := "Terraform acceptance test" resource.Test(t, resource.TestCase{ @@ -417,12 +417,13 @@ func TestAcc_Schema_Rename(t *testing.T) { { ConfigDirectory: config.TestNameDirectory(), ConfigVariables: map[string]config.Variable{ - "name": config.StringVariable(oldSchemaName), + "name": config.StringVariable(oldId.Name()), "database": config.StringVariable(acc.TestDatabaseName), "comment": config.StringVariable(comment), }, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_schema.test", "name", oldSchemaName), + resource.TestCheckResourceAttr("snowflake_schema.test", "name", oldId.Name()), + resource.TestCheckResourceAttr("snowflake_schema.test", "fully_qualified_name", oldId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_schema.test", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_schema.test", "comment", comment), ), @@ -430,7 +431,7 @@ func TestAcc_Schema_Rename(t *testing.T) { { ConfigDirectory: config.TestNameDirectory(), ConfigVariables: map[string]config.Variable{ - "name": config.StringVariable(newSchemaName), + "name": config.StringVariable(newId.Name()), "database": config.StringVariable(acc.TestDatabaseName), "comment": config.StringVariable(comment), }, @@ -440,7 +441,8 @@ func TestAcc_Schema_Rename(t *testing.T) { }, }, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_schema.test", "name", newSchemaName), + resource.TestCheckResourceAttr("snowflake_schema.test", "name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_schema.test", "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_schema.test", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_schema.test", "comment", comment), ), diff --git a/pkg/resources/scim_integration.go b/pkg/resources/scim_integration.go index ba78acbeac..6fb91db044 100644 --- a/pkg/resources/scim_integration.go +++ b/pkg/resources/scim_integration.go @@ -90,6 +90,7 @@ var scimIntegrationSchema = map[string]*schema.Schema{ Schema: schemas.DescribeScimSecurityIntegrationSchema, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func SCIMIntegration() *schema.Resource { @@ -271,6 +272,9 @@ func ReadContextSCIMIntegration(withExternalChangesMarking bool) schema.ReadCont } return diag.FromErr(err) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if c := integration.Category; c != sdk.SecurityIntegrationCategory { return diag.FromErr(fmt.Errorf("expected %v to be a SECURITY integration, got %v", id, c)) diff --git a/pkg/resources/scim_integration_acceptance_test.go b/pkg/resources/scim_integration_acceptance_test.go index 159b31e874..1ae06e9413 100644 --- a/pkg/resources/scim_integration_acceptance_test.go +++ b/pkg/resources/scim_integration_acceptance_test.go @@ -134,6 +134,7 @@ func TestAcc_ScimIntegration_basic(t *testing.T) { ImportState: true, ImportStateCheck: importchecks.ComposeImportStateCheck( importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "fully_qualified_name", id.FullyQualifiedName()), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "enabled", "true"), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "scim_client", "OKTA"), importchecks.TestCheckResourceAttrInstanceState(id.Name(), "run_as_role", role2.Name()), @@ -189,6 +190,7 @@ func TestAcc_ScimIntegration_complete(t *testing.T) { ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_scim_integration.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_scim_integration.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_scim_integration.test", "enabled", "false"), resource.TestCheckResourceAttr("snowflake_scim_integration.test", "scim_client", "GENERIC"), resource.TestCheckResourceAttr("snowflake_scim_integration.test", "run_as_role", role.Name()), diff --git a/pkg/resources/secondary_database.go b/pkg/resources/secondary_database.go index 111947a39e..9363a3e26d 100644 --- a/pkg/resources/secondary_database.go +++ b/pkg/resources/secondary_database.go @@ -7,8 +7,10 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -35,6 +37,7 @@ var secondaryDatabaseSchema = map[string]*schema.Schema{ Optional: true, Description: "Specifies a comment for the database.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func SecondaryDatabase() *schema.Resource { @@ -45,8 +48,11 @@ func SecondaryDatabase() *schema.Resource { DeleteContext: DeleteSecondaryDatabase, Description: "A secondary database creates a replica of an existing primary database (i.e. a secondary database). For more information about database replication, see [Introduction to database replication across multiple accounts](https://docs.snowflake.com/en/user-guide/db-replication-intro).", - CustomizeDiff: databaseParametersCustomDiff, - Schema: helpers.MergeMaps(secondaryDatabaseSchema, databaseParametersSchema), + CustomizeDiff: customdiff.All( + databaseParametersCustomDiff, + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), + Schema: helpers.MergeMaps(secondaryDatabaseSchema, databaseParametersSchema), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -170,6 +176,9 @@ func ReadSecondaryDatabase(ctx context.Context, d *schema.ResourceData, meta any if replicationPrimaryDatabase == nil { return diag.FromErr(fmt.Errorf("could not find replication database for %s", secondaryDatabaseId.Name())) } + if err := d.Set(FullyQualifiedNameAttributeName, secondaryDatabaseId.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", secondaryDatabase.Name); err != nil { return diag.FromErr(err) diff --git a/pkg/resources/secondary_database_acceptance_test.go b/pkg/resources/secondary_database_acceptance_test.go index edac458ec5..902922a469 100644 --- a/pkg/resources/secondary_database_acceptance_test.go +++ b/pkg/resources/secondary_database_acceptance_test.go @@ -91,6 +91,7 @@ func TestAcc_CreateSecondaryDatabase_Basic(t *testing.T) { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecondaryDatabase/basic"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_secondary_database.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_secondary_database.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_secondary_database.test", "as_replica_of", externalPrimaryId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_secondary_database.test", "comment", comment), @@ -118,6 +119,7 @@ func TestAcc_CreateSecondaryDatabase_Basic(t *testing.T) { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecondaryDatabase/basic"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_secondary_database.test", "name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_secondary_database.test", "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_secondary_database.test", "as_replica_of", externalPrimaryId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_secondary_database.test", "comment", newComment), diff --git a/pkg/resources/sequence.go b/pkg/resources/sequence.go index e0f98e5bd7..207b78d909 100644 --- a/pkg/resources/sequence.go +++ b/pkg/resources/sequence.go @@ -4,6 +4,7 @@ import ( "context" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -58,11 +59,7 @@ var sequenceSchema = map[string]*schema.Schema{ string(sdk.ValuesBehaviorOrder), }, false), }, - "fully_qualified_name": { - Type: schema.TypeString, - Description: "The fully qualified name of the sequence.", - Computed: true, - }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func Sequence() *schema.Resource { @@ -150,7 +147,7 @@ func ReadSequence(d *schema.ResourceData, meta interface{}) error { } } - if err := d.Set("fully_qualified_name", id.FullyQualifiedName()); err != nil { + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { return err } return nil diff --git a/pkg/resources/sequence_acceptance_test.go b/pkg/resources/sequence_acceptance_test.go index 1c7ed6b48d..c1c901a915 100644 --- a/pkg/resources/sequence_acceptance_test.go +++ b/pkg/resources/sequence_acceptance_test.go @@ -12,8 +12,8 @@ import ( ) func TestAcc_Sequence(t *testing.T) { - accName := acc.TestClient().Ids.Alpha() - accRename := acc.TestClient().Ids.Alpha() + oldId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + newId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -25,34 +25,34 @@ func TestAcc_Sequence(t *testing.T) { Steps: []resource.TestStep{ // CREATE { - Config: sequenceConfig(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: sequenceConfig(oldId.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "name", accName), + resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "name", oldId.Name()), resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "next_value", "1"), - resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "fully_qualified_name", fmt.Sprintf(`"%v"."%v"."%v"`, acc.TestDatabaseName, acc.TestSchemaName, accName)), + resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "fully_qualified_name", oldId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "ordering", "ORDER"), ), }, // Set comment and rename { - Config: sequenceConfigWithComment(accRename, "look at me I am a comment", acc.TestDatabaseName, acc.TestSchemaName), + Config: sequenceConfigWithComment(newId.Name(), "look at me I am a comment", acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "name", accRename), + resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "name", newId.Name()), resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "comment", "look at me I am a comment"), resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "next_value", "1"), - resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "fully_qualified_name", fmt.Sprintf(`"%v"."%v"."%v"`, acc.TestDatabaseName, acc.TestSchemaName, accRename)), + resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "fully_qualified_name", newId.FullyQualifiedName()), ), }, // Unset comment and set increment { - Config: sequenceConfigWithIncrement(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: sequenceConfigWithIncrement(oldId.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "name", accName), + resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "name", oldId.Name()), resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "comment", ""), resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "next_value", "1"), resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "increment", "32"), resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "ordering", "NOORDER"), - resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "fully_qualified_name", fmt.Sprintf(`"%v"."%v"."%v"`, acc.TestDatabaseName, acc.TestSchemaName, accName)), + resource.TestCheckResourceAttr("snowflake_sequence.test_sequence", "fully_qualified_name", oldId.FullyQualifiedName()), ), }, // IMPORT diff --git a/pkg/resources/share.go b/pkg/resources/share.go index f0fbcf8c3a..d14f63bd49 100644 --- a/pkg/resources/share.go +++ b/pkg/resources/share.go @@ -9,6 +9,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -37,6 +38,7 @@ var shareSchema = map[string]*schema.Schema{ "in the form of 'organization_name.account_name", DiffSuppressFunc: ignoreCaseSuppressFunc, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // Share returns a pointer to the resource representing a share. @@ -162,6 +164,9 @@ func ReadShare(d *schema.ResourceData, meta interface{}) error { if err != nil { return fmt.Errorf("error reading share (%v) err = %w", d.Id(), err) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } if err := d.Set("name", share.Name.Name()); err != nil { return err } diff --git a/pkg/resources/share_acceptance_test.go b/pkg/resources/share_acceptance_test.go index 7af1a7d3e7..675e53f01d 100644 --- a/pkg/resources/share_acceptance_test.go +++ b/pkg/resources/share_acceptance_test.go @@ -19,7 +19,7 @@ func TestAcc_Share(t *testing.T) { var account3 string shareComment := "Created by a Terraform acceptance test" - name := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -30,15 +30,16 @@ func TestAcc_Share(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.Share), Steps: []resource.TestStep{ { - Config: shareConfig(name, shareComment), + Config: shareConfig(id.Name(), shareComment), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_share.test", "name", name), + resource.TestCheckResourceAttr("snowflake_share.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_share.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_share.test", "comment", shareComment), resource.TestCheckResourceAttr("snowflake_share.test", "accounts.#", "0"), ), }, { - Config: shareConfigTwoAccounts(name, shareComment, account2, account3), + Config: shareConfigTwoAccounts(id.Name(), shareComment, account2, account3), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_share.test", "accounts.#", "2"), resource.TestCheckResourceAttr("snowflake_share.test", "accounts.0", account2), @@ -46,14 +47,14 @@ func TestAcc_Share(t *testing.T) { ), }, { - Config: shareConfigOneAccount(name, shareComment, account2), + Config: shareConfigOneAccount(id.Name(), shareComment, account2), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_share.test", "accounts.#", "1"), resource.TestCheckResourceAttr("snowflake_share.test", "accounts.0", account2), ), }, { - Config: shareConfig(name, shareComment), + Config: shareConfig(id.Name(), shareComment), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_share.test", "accounts.#", "0"), ), diff --git a/pkg/resources/shared_database.go b/pkg/resources/shared_database.go index 5f290b05c5..e5093201f6 100644 --- a/pkg/resources/shared_database.go +++ b/pkg/resources/shared_database.go @@ -7,8 +7,10 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -36,6 +38,7 @@ var sharedDatabaseSchema = map[string]*schema.Schema{ // ForceNew: true, // Description: "Specifies the database as transient. Transient databases do not have a Fail-safe period so they do not incur additional storage costs once they leave Time Travel; however, this means they are also not protected by Fail-safe in the event of a data loss.", // }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func SharedDatabase() *schema.Resource { @@ -46,6 +49,10 @@ func SharedDatabase() *schema.Resource { DeleteContext: DeleteSharedDatabase, Description: "A shared database creates a database from a share provided by another Snowflake account. For more information about shares, see [Introduction to Secure Data Sharing](https://docs.snowflake.com/en/user-guide/data-sharing-intro).", + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), + Schema: helpers.MergeMaps(sharedDatabaseSchema, sharedDatabaseParametersSchema), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -138,6 +145,9 @@ func ReadSharedDatabase(ctx context.Context, d *schema.ResourceData, meta any) d } return diag.FromErr(err) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", database.Name); err != nil { return diag.FromErr(err) diff --git a/pkg/resources/shared_database_acceptance_test.go b/pkg/resources/shared_database_acceptance_test.go index d700a25646..19d11a50af 100644 --- a/pkg/resources/shared_database_acceptance_test.go +++ b/pkg/resources/shared_database_acceptance_test.go @@ -82,6 +82,7 @@ func TestAcc_CreateSharedDatabase_Basic(t *testing.T) { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SharedDatabase/basic"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_shared_database.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_shared_database.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_shared_database.test", "from_share", shareExternalId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_shared_database.test", "comment", comment), @@ -111,6 +112,7 @@ func TestAcc_CreateSharedDatabase_Basic(t *testing.T) { }, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_shared_database.test", "name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_shared_database.test", "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_shared_database.test", "from_share", shareExternalId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_shared_database.test", "comment", newComment), @@ -205,6 +207,7 @@ func TestAcc_CreateSharedDatabase_complete(t *testing.T) { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SharedDatabase/complete"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_shared_database.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_shared_database.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_shared_database.test", "from_share", externalShareId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_shared_database.test", "comment", comment), diff --git a/pkg/resources/special_values.go b/pkg/resources/special_values.go index 4a74508a8e..5993e02cc0 100644 --- a/pkg/resources/special_values.go +++ b/pkg/resources/special_values.go @@ -33,15 +33,3 @@ func booleanStringToBool(value string) (bool, error) { return false, fmt.Errorf("cannot retrieve boolean value from %s", value) } } - -func booleanStringFieldDescription(description string) string { - return fmt.Sprintf(`%s Available options are: "%s" or "%s". When the value is not set in the configuration the provider will put "%s" there which means to use the Snowflake default for this value.`, description, BooleanTrue, BooleanFalse, BooleanDefault) -} - -func externalChangesNotDetectedFieldDescription(description string) string { - return fmt.Sprintf(`%s 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".`, description) -} - -func withPrivilegedRolesDescription(description, paramName string) string { - return fmt.Sprintf(`%s By default, this list includes the ACCOUNTADMIN, ORGADMIN and SECURITYADMIN roles. To remove these privileged roles from the list, use the ALTER ACCOUNT command to set the %s account parameter to FALSE. `, description, paramName) -} diff --git a/pkg/resources/stage.go b/pkg/resources/stage.go index 884ca76d79..d102bd2a71 100644 --- a/pkg/resources/stage.go +++ b/pkg/resources/stage.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -91,7 +92,8 @@ var stageSchema = map[string]*schema.Schema{ // Description based on https://docs.snowflake.com/en/user-guide/data-load-s3-config-aws-iam-role#step-3-create-an-external-stage Description: "An AWS IAM user created for your Snowflake account. This user is the same for every external S3 stage created in your account.", }, - "tag": tagReferenceSchema, + "tag": tagReferenceSchema, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // TODO (SNOW-1019005): Remove snowflake package that is used in Create and Update operations @@ -193,6 +195,9 @@ func ReadStage(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagn }, } } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err := d.Set("name", stage.Name); err != nil { return diag.FromErr(err) diff --git a/pkg/resources/stage_acceptance_test.go b/pkg/resources/stage_acceptance_test.go index f734f1de92..7275987e56 100644 --- a/pkg/resources/stage_acceptance_test.go +++ b/pkg/resources/stage_acceptance_test.go @@ -5,6 +5,7 @@ import ( "testing" acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/ids" @@ -17,7 +18,7 @@ import ( ) func TestAcc_StageAlterWhenBothURLAndStorageIntegrationChange(t *testing.T) { - name := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -28,16 +29,18 @@ func TestAcc_StageAlterWhenBothURLAndStorageIntegrationChange(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.Stage), Steps: []resource.TestStep{ { - Config: stageIntegrationConfig(name, "si1", "s3://foo/", acc.TestDatabaseName, acc.TestSchemaName), + Config: stageIntegrationConfig(id.Name(), "si1", "s3://foo/", acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_stage.test", "name", name), + resource.TestCheckResourceAttr("snowflake_stage.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_stage.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_stage.test", "url", "s3://foo/"), ), }, { - Config: stageIntegrationConfig(name, "changed", "s3://changed/", acc.TestDatabaseName, acc.TestSchemaName), + Config: stageIntegrationConfig(id.Name(), "changed", "s3://changed/", acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_stage.test", "name", name), + resource.TestCheckResourceAttr("snowflake_stage.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_stage.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_stage.test", "url", "s3://changed/"), ), }, @@ -53,6 +56,7 @@ func TestAcc_Stage_CreateAndAlter(t *testing.T) { databaseName := acc.TestClient().Ids.Alpha() schemaName := acc.TestClient().Ids.Alpha() name := acc.TestClient().Ids.Alpha() + id := sdk.NewSchemaObjectIdentifier(databaseName, schemaName, name) url := "s3://foo/" comment := random.Comment() initialStorageIntegration := "" @@ -119,6 +123,7 @@ func TestAcc_Stage_CreateAndAlter(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "database", databaseName), resource.TestCheckResourceAttr(resourceName, "schema", schemaName), resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "storage_integration", changedStorageIntegration.Name()), resource.TestCheckResourceAttr(resourceName, "credentials", credentials), resource.TestCheckResourceAttr(resourceName, "encryption", changedEncryption), @@ -138,6 +143,7 @@ func TestAcc_Stage_CreateAndAlter(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "database", databaseName), resource.TestCheckResourceAttr(resourceName, "schema", schemaName), resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "storage_integration", changedStorageIntegration.Name()), resource.TestCheckResourceAttr(resourceName, "credentials", credentials), resource.TestCheckResourceAttr(resourceName, "encryption", changedEncryption), @@ -162,6 +168,7 @@ func TestAcc_Stage_CreateAndAlter(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "database", databaseName), resource.TestCheckResourceAttr(resourceName, "schema", schemaName), resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "storage_integration", initialStorageIntegration), resource.TestCheckResourceAttr(resourceName, "credentials", credentials), resource.TestCheckResourceAttr(resourceName, "encryption", encryption), diff --git a/pkg/resources/storage_integration.go b/pkg/resources/storage_integration.go index 0a7a830841..8fd4fe378d 100644 --- a/pkg/resources/storage_integration.go +++ b/pkg/resources/storage_integration.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -104,6 +105,7 @@ var storageIntegrationSchema = map[string]*schema.Schema{ Computed: true, Description: "Date and time when the storage integration was created.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // StorageIntegration returns a pointer to the resource representing a storage integration. @@ -199,6 +201,9 @@ func ReadStorageIntegration(d *schema.ResourceData, meta any) error { d.SetId("") return nil } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } if s.Category != "STORAGE" { return fmt.Errorf("expected %v to be a STORAGE integration, got %v", d.Id(), s.Category) diff --git a/pkg/resources/storage_integration_acceptance_test.go b/pkg/resources/storage_integration_acceptance_test.go index ad85a207a4..38fe546e3f 100644 --- a/pkg/resources/storage_integration_acceptance_test.go +++ b/pkg/resources/storage_integration_acceptance_test.go @@ -87,11 +87,11 @@ func TestAcc_StorageIntegration_AWSObjectACL_Update(t *testing.T) { } func TestAcc_StorageIntegration_AWS_Update(t *testing.T) { - name := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() awsRoleArn := "arn:aws:iam::000000000001:/role/test" configVariables := func(set bool) config.Variables { variables := config.Variables{ - "name": config.StringVariable(name), + "name": config.StringVariable(id.Name()), "aws_role_arn": config.StringVariable(awsRoleArn), "allowed_locations": config.SetVariable( config.StringVariable("s3://foo/"), @@ -124,7 +124,8 @@ func TestAcc_StorageIntegration_AWS_Update(t *testing.T) { ConfigVariables: configVariables(false), ConfigDirectory: acc.ConfigurationDirectory("TestAcc_StorageIntegration/AWS_Update/unset"), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_storage_integration.test", "name", name), + resource.TestCheckResourceAttr("snowflake_storage_integration.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_storage_integration.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_storage_integration.test", "enabled", "false"), resource.TestCheckResourceAttr("snowflake_storage_integration.test", "storage_aws_role_arn", awsRoleArn), resource.TestCheckResourceAttr("snowflake_storage_integration.test", "storage_allowed_locations.#", "1"), @@ -138,7 +139,8 @@ func TestAcc_StorageIntegration_AWS_Update(t *testing.T) { ConfigVariables: configVariables(true), ConfigDirectory: acc.ConfigurationDirectory("TestAcc_StorageIntegration/AWS_Update/set"), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_storage_integration.test", "name", name), + resource.TestCheckResourceAttr("snowflake_storage_integration.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_storage_integration.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_storage_integration.test", "enabled", "true"), resource.TestCheckResourceAttr("snowflake_storage_integration.test", "comment", "some comment"), resource.TestCheckResourceAttr("snowflake_storage_integration.test", "storage_aws_role_arn", awsRoleArn), @@ -155,7 +157,8 @@ func TestAcc_StorageIntegration_AWS_Update(t *testing.T) { ConfigVariables: configVariables(false), ConfigDirectory: acc.ConfigurationDirectory("TestAcc_StorageIntegration/AWS_Update/unset"), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_storage_integration.test", "name", name), + resource.TestCheckResourceAttr("snowflake_storage_integration.test", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_storage_integration.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_storage_integration.test", "enabled", "false"), resource.TestCheckResourceAttr("snowflake_storage_integration.test", "storage_aws_role_arn", awsRoleArn), resource.TestCheckResourceAttr("snowflake_storage_integration.test", "storage_allowed_locations.#", "1"), diff --git a/pkg/resources/stream.go b/pkg/resources/stream.go index 7aa0701aaa..8af0f25be8 100644 --- a/pkg/resources/stream.go +++ b/pkg/resources/stream.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -93,6 +94,7 @@ var streamSchema = map[string]*schema.Schema{ Computed: true, Description: "Name of the role that owns the stream.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func Stream() *schema.Resource { @@ -232,6 +234,9 @@ func ReadStream(d *schema.ResourceData, meta interface{}) error { d.SetId("") return nil } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } if err := d.Set("name", stream.Name); err != nil { return err } diff --git a/pkg/resources/stream_acceptance_test.go b/pkg/resources/stream_acceptance_test.go index a13b17365d..a85c6d67a0 100644 --- a/pkg/resources/stream_acceptance_test.go +++ b/pkg/resources/stream_acceptance_test.go @@ -63,7 +63,7 @@ func TestAcc_StreamCreateOnStage(t *testing.T) { func TestAcc_Stream_OnTable(t *testing.T) { tableName := acc.TestClient().Ids.Alpha() tableName2 := acc.TestClient().Ids.Alpha() - name := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -74,9 +74,10 @@ func TestAcc_Stream_OnTable(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.Stream), Steps: []resource.TestStep{ { - Config: streamConfigOnTable(acc.TestDatabaseName, acc.TestSchemaName, tableName, name), + Config: streamConfigOnTable(acc.TestDatabaseName, acc.TestSchemaName, tableName, id.Name()), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_stream.test_stream", "name", name), + resource.TestCheckResourceAttr("snowflake_stream.test_stream", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_stream.test_stream", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_stream.test_stream", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_stream.test_stream", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_stream.test_stream", "on_table", fmt.Sprintf("\"%s\".\"%s\".%s", acc.TestDatabaseName, acc.TestSchemaName, tableName)), @@ -87,9 +88,10 @@ func TestAcc_Stream_OnTable(t *testing.T) { }, }, { - Config: streamConfigOnTable(acc.TestDatabaseName, acc.TestSchemaName, tableName2, name), + Config: streamConfigOnTable(acc.TestDatabaseName, acc.TestSchemaName, tableName2, id.Name()), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_stream.test_stream", "name", name), + resource.TestCheckResourceAttr("snowflake_stream.test_stream", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_stream.test_stream", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_stream.test_stream", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_stream.test_stream", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_stream.test_stream", "on_table", fmt.Sprintf("\"%s\".\"%s\".%s", acc.TestDatabaseName, acc.TestSchemaName, tableName2)), diff --git a/pkg/resources/streamlit.go b/pkg/resources/streamlit.go index 3b7ff3aa04..998924c4cf 100644 --- a/pkg/resources/streamlit.go +++ b/pkg/resources/streamlit.go @@ -96,6 +96,7 @@ var streamlitSchema = map[string]*schema.Schema{ Schema: schemas.DescribeStreamlitSchema, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func Streamlit() *schema.Resource { @@ -113,6 +114,7 @@ func Streamlit() *schema.Resource { CustomizeDiff: customdiff.All( ComputedIfAnyAttributeChanged(ShowOutputAttributeName, "name", "title", "comment", "query_warehouse"), + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), ComputedIfAnyAttributeChanged(DescribeOutputAttributeName, "name", "title", "comment", "root_location", "main_file", "query_warehouse", "external_access_integrations"), ), } @@ -228,6 +230,9 @@ func ReadContextStreamlit(ctx context.Context, d *schema.ResourceData, meta any) } return diag.FromErr(err) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } streamlitDetails, err := client.Streamlits.Describe(ctx, id) if err != nil { diff --git a/pkg/resources/streamlit_acceptance_test.go b/pkg/resources/streamlit_acceptance_test.go index 83194703c1..d22e90ee81 100644 --- a/pkg/resources/streamlit_acceptance_test.go +++ b/pkg/resources/streamlit_acceptance_test.go @@ -308,6 +308,7 @@ func TestAcc_Streamlit_complete(t *testing.T) { resource.TestCheckResourceAttr("snowflake_streamlit.test", "external_access_integrations.0", externalAccessIntegrationId.Name()), resource.TestCheckResourceAttr("snowflake_streamlit.test", "title", "foo"), resource.TestCheckResourceAttr("snowflake_streamlit.test", "comment", "foo"), + resource.TestCheckResourceAttr("snowflake_streamlit.test", "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_streamlit.test", "show_output.#", "1"), resource.TestCheckResourceAttrSet("snowflake_streamlit.test", "show_output.0.created_on"), @@ -378,6 +379,7 @@ func TestAcc_Streamlit_Rename(t *testing.T) { resource.TestCheckResourceAttr("snowflake_streamlit.test", "name", id.Name()), resource.TestCheckResourceAttr("snowflake_streamlit.test", "show_output.0.name", id.Name()), resource.TestCheckResourceAttr("snowflake_streamlit.test", "show_output.0.comment", "foo"), + resource.TestCheckResourceAttr("snowflake_streamlit.test", "fully_qualified_name", id.FullyQualifiedName()), ), }, { @@ -392,6 +394,7 @@ func TestAcc_Streamlit_Rename(t *testing.T) { resource.TestCheckResourceAttr("snowflake_streamlit.test", "name", newId.Name()), resource.TestCheckResourceAttr("snowflake_streamlit.test", "show_output.0.name", newId.Name()), resource.TestCheckResourceAttr("snowflake_streamlit.test", "show_output.0.comment", "bar"), + resource.TestCheckResourceAttr("snowflake_streamlit.test", "fully_qualified_name", newId.FullyQualifiedName()), ), }, }, diff --git a/pkg/resources/table.go b/pkg/resources/table.go index 434b12dd05..7b4731c68f 100644 --- a/pkg/resources/table.go +++ b/pkg/resources/table.go @@ -8,10 +8,12 @@ import ( "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/snowflake" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) @@ -196,12 +198,8 @@ var tableSchema = map[string]*schema.Schema{ Default: false, Description: "Specifies whether to enable change tracking on the table. Default false.", }, - "qualified_name": { - Type: schema.TypeString, - Computed: true, - Description: "Qualified name of the table.", - }, - "tag": tagReferenceSchema, + "tag": tagReferenceSchema, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func Table() *schema.Resource { @@ -211,6 +209,10 @@ func Table() *schema.Resource { Update: UpdateTable, Delete: DeleteTable, + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), + Schema: tableSchema, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -643,6 +645,9 @@ func ReadTable(d *schema.ResourceData, meta interface{}) error { d.SetId("") return nil } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } var schemaRetentionTime int64 // "retention_time" may sometimes be empty string instead of an integer { @@ -672,7 +677,6 @@ func ReadTable(d *schema.ResourceData, meta interface{}) error { "column": toColumnConfig(tableDescription), "cluster_by": table.GetClusterByKeys(), "change_tracking": table.ChangeTracking, - "qualified_name": id.FullyQualifiedName(), } if v := d.Get("data_retention_time_in_days"); v.(int) != IntDefault || int64(table.RetentionTime) != schemaRetentionTime { toSet["data_retention_time_in_days"] = table.RetentionTime diff --git a/pkg/resources/table_acceptance_test.go b/pkg/resources/table_acceptance_test.go index 937263d0a8..5fb73dce55 100644 --- a/pkg/resources/table_acceptance_test.go +++ b/pkg/resources/table_acceptance_test.go @@ -135,10 +135,9 @@ func TestAcc_TableWithSeparateDataRetentionObjectParameterWithLifecycle(t *testi } func TestAcc_Table(t *testing.T) { - accName := acc.TestClient().Ids.Alpha() - - table2Name := acc.TestClient().Ids.Alpha() - table3Name := acc.TestClient().Ids.Alpha() + table1Id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + table2Id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + table3Id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -149,9 +148,10 @@ func TestAcc_Table(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.Table), Steps: []resource.TestStep{ { - Config: tableConfig(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig(table1Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table", "name", accName), + resource.TestCheckResourceAttr("snowflake_table.test_table", "name", table1Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table", "fully_qualified_name", table1Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table", "data_retention_time_in_days", "1"), @@ -167,9 +167,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig2(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig2(table1Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table", "name", accName), + resource.TestCheckResourceAttr("snowflake_table.test_table", "name", table1Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table", "fully_qualified_name", table1Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table", "data_retention_time_in_days", "1"), @@ -186,9 +187,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig3(table2Name, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig3(table2Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Name), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "fully_qualified_name", table2Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table2", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "data_retention_time_in_days", "1"), @@ -203,9 +205,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig4(table2Name, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig4(table2Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Name), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "fully_qualified_name", table2Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table2", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "data_retention_time_in_days", "1"), @@ -219,9 +222,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig5(table2Name, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig5(table2Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Name), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "fully_qualified_name", table2Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table2", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "data_retention_time_in_days", "1"), @@ -235,9 +239,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig6(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig6(table1Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table", "name", accName), + resource.TestCheckResourceAttr("snowflake_table.test_table", "name", table1Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table", "fully_qualified_name", table1Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table", "data_retention_time_in_days", "1"), @@ -254,9 +259,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig7(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig7(table1Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table", "name", accName), + resource.TestCheckResourceAttr("snowflake_table.test_table", "name", table1Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table", "fully_qualified_name", table1Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table", "data_retention_time_in_days", "1"), @@ -274,9 +280,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig8(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig8(table1Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table", "name", accName), + resource.TestCheckResourceAttr("snowflake_table.test_table", "name", table1Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table", "fully_qualified_name", table1Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table", "data_retention_time_in_days", "1"), @@ -295,9 +302,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig9CreateTableWithColumnComment(table2Name, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig9CreateTableWithColumnComment(table2Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Name), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "fully_qualified_name", table2Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table2", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "data_retention_time_in_days", "1"), @@ -316,9 +324,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig10AlterTableColumnComment(table2Name, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig10AlterTableColumnComment(table2Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Name), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "fully_qualified_name", table2Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table2", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "data_retention_time_in_days", "1"), @@ -337,9 +346,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig11AlterTableAddColumnWithComment(table2Name, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig11AlterTableAddColumnWithComment(table2Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Name), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "name", table2Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table2", "fully_qualified_name", table2Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table2", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table2", "data_retention_time_in_days", "1"), @@ -362,9 +372,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig12CreateTableWithDataRetention(table3Name, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig12CreateTableWithDataRetention(table3Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table3", "name", table3Name), + resource.TestCheckResourceAttr("snowflake_table.test_table3", "name", table3Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table3", "fully_qualified_name", table3Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table3", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table3", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table3", "data_retention_time_in_days", "10"), @@ -379,9 +390,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig13AlterTableDataRetention(table3Name, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig13AlterTableDataRetention(table3Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table3", "name", table3Name), + resource.TestCheckResourceAttr("snowflake_table.test_table3", "name", table3Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table3", "fully_qualified_name", table3Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table3", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table3", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table3", "data_retention_time_in_days", "0"), @@ -396,9 +408,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig14AlterTableEnableChangeTracking(table3Name, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig14AlterTableEnableChangeTracking(table3Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table3", "name", table3Name), + resource.TestCheckResourceAttr("snowflake_table.test_table3", "name", table3Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table3", "fully_qualified_name", table3Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table3", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table3", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table3", "data_retention_time_in_days", "0"), @@ -413,9 +426,10 @@ func TestAcc_Table(t *testing.T) { ), }, { - Config: tableConfig15CreateTableWithChangeTracking(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConfig15CreateTableWithChangeTracking(table1Id.Name(), acc.TestDatabaseName, acc.TestSchemaName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table", "name", accName), + resource.TestCheckResourceAttr("snowflake_table.test_table", "name", table1Id.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table", "fully_qualified_name", table1Id.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table", "data_retention_time_in_days", "1"), @@ -1364,8 +1378,8 @@ resource "snowflake_table" "test_table" { } func TestAcc_TableRename(t *testing.T) { - oldTableName := acc.TestClient().Ids.Alpha() - newTableName := acc.TestClient().Ids.Alpha() + oldId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + newId := acc.TestClient().Ids.RandomSchemaObjectIdentifier() oldComment := acc.TestClient().Ids.Alpha() newComment := acc.TestClient().Ids.Alpha() @@ -1378,9 +1392,10 @@ func TestAcc_TableRename(t *testing.T) { CheckDestroy: acc.CheckDestroy(t, resources.Table), Steps: []resource.TestStep{ { - Config: tableConfigWithName(oldTableName, acc.TestDatabaseName, acc.TestSchemaName, oldComment), + Config: tableConfigWithName(oldId.Name(), acc.TestDatabaseName, acc.TestSchemaName, oldComment), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table", "name", oldTableName), + resource.TestCheckResourceAttr("snowflake_table.test_table", "name", oldId.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table", "fully_qualified_name", oldId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table", "comment", oldComment), @@ -1392,14 +1407,15 @@ func TestAcc_TableRename(t *testing.T) { ), }, { - Config: tableConfigWithName(newTableName, acc.TestDatabaseName, acc.TestSchemaName, newComment), + Config: tableConfigWithName(newId.Name(), acc.TestDatabaseName, acc.TestSchemaName, newComment), ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectResourceAction("snowflake_table.test_table", plancheck.ResourceActionUpdate), }, }, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_table.test_table", "name", newTableName), + resource.TestCheckResourceAttr("snowflake_table.test_table", "name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_table.test_table", "fully_qualified_name", newId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_table.test_table", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_table.test_table", "schema", acc.TestSchemaName), resource.TestCheckResourceAttr("snowflake_table.test_table", "comment", newComment), @@ -1747,7 +1763,7 @@ resource "snowflake_table" "test_table" { column { name = "column1" type = "VARCHAR(16)" - masking_policy = snowflake_masking_policy.%[4]s.qualified_name + masking_policy = snowflake_masking_policy.%[4]s.fully_qualified_name } } ` @@ -1967,3 +1983,40 @@ resource "snowflake_table" "test_table" { } `, database, schema, name) } + +func TestAcc_Table_migrateFromVersion_0_94_1(t *testing.T) { + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() + resourceName := "snowflake_table.test_table" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "snowflake": { + VersionConstraint: "=0.94.1", + Source: "Snowflake-Labs/snowflake", + }, + }, + Config: tableConfig(id.Name(), id.DatabaseName(), id.SchemaName()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", id.Name()), + resource.TestCheckResourceAttr(resourceName, "qualified_name", id.FullyQualifiedName()), + ), + }, + { + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + Config: tableConfig(id.Name(), id.DatabaseName(), id.SchemaName()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", id.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), + resource.TestCheckNoResourceAttr(resourceName, "qualified_name"), + ), + }, + }, + }) +} diff --git a/pkg/resources/table_column_masking_policy_application_acceptance_test.go b/pkg/resources/table_column_masking_policy_application_acceptance_test.go index 10b9e4a8b7..cb0b213935 100644 --- a/pkg/resources/table_column_masking_policy_application_acceptance_test.go +++ b/pkg/resources/table_column_masking_policy_application_acceptance_test.go @@ -67,8 +67,8 @@ resource "snowflake_table" "table" { } resource "snowflake_table_column_masking_policy_application" "mpa" { - table = snowflake_table.table.qualified_name + table = snowflake_table.table.fully_qualified_name column = "secret" - masking_policy = snowflake_masking_policy.test.qualified_name + masking_policy = snowflake_masking_policy.test.fully_qualified_name }`, databaseName, schemaName, databaseName, schemaName) } diff --git a/pkg/resources/table_constraint.go b/pkg/resources/table_constraint.go index fbdd00dcdb..f929dabcf6 100644 --- a/pkg/resources/table_constraint.go +++ b/pkg/resources/table_constraint.go @@ -211,7 +211,7 @@ func (v *tableConstraintID) parse(s string) { func getTableIdentifier(s string) (*sdk.SchemaObjectIdentifier, error) { var objectIdentifier sdk.ObjectIdentifier var err error - // TODO [SNOW-999049]: Fallback for old implementations using table.id instead of table.qualified_name - probably will be removed later. + // TODO [SNOW-999049]: Fallback for old implementations using table.id instead of table.fully_qualified_name - probably will be removed later. if strings.Contains(s, "|") { objectIdentifier = helpers.DecodeSnowflakeID(s) } else { diff --git a/pkg/resources/table_constraint_acceptance_test.go b/pkg/resources/table_constraint_acceptance_test.go index 8d09287322..2feb8eca0c 100644 --- a/pkg/resources/table_constraint_acceptance_test.go +++ b/pkg/resources/table_constraint_acceptance_test.go @@ -68,11 +68,11 @@ resource "snowflake_table" "fk_t" { resource "snowflake_table_constraint" "fk" { name="%s" type= "FOREIGN KEY" - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name columns = ["col1"] foreign_key_properties { references { - table_id = snowflake_table.fk_t.qualified_name + table_id = snowflake_table.fk_t.fully_qualified_name columns = ["fk_col1"] } } @@ -129,7 +129,7 @@ resource "snowflake_table" "t" { resource "snowflake_table_constraint" "pk" { name = "%[4]s" type = "PRIMARY KEY" - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name columns = ["col1"] enable = false deferrable = false @@ -209,7 +209,7 @@ resource "snowflake_table" "t" { resource "snowflake_table_constraint" "unique" { name="%s" type= "UNIQUE" - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name columns = ["col1"] enforced = true deferrable = false @@ -301,7 +301,7 @@ func TestAcc_Table_issue2535_existingTable(t *testing.T) { Source: "Snowflake-Labs/snowflake", }, }, - Config: tableConstraintUniqueConfigUsingFullyQualifiedName(accName, acc.TestDatabaseName, acc.TestSchemaName), + Config: tableConstraintUniqueConfigUsingQualifiedName(accName, acc.TestDatabaseName, acc.TestSchemaName), ExpectError: regexp.MustCompile(`.*table id is incorrect.*`), }, // fixed in the current version @@ -372,7 +372,7 @@ func TestAcc_TableConstraint_ProperlyHandles_EmptyForeignKeyProperties(t *testin }) } -func tableConstraintUniqueConfigUsingFullyQualifiedName(n string, databaseName string, schemaName string) string { +func tableConstraintUniqueConfigUsingQualifiedName(n string, databaseName string, schemaName string) string { return fmt.Sprintf(` resource "snowflake_table" "t" { name = "%s" @@ -394,6 +394,28 @@ resource "snowflake_table_constraint" "unique" { `, n, databaseName, schemaName, n) } +func tableConstraintUniqueConfigUsingFullyQualifiedName(n string, databaseName string, schemaName string) string { + return fmt.Sprintf(` +resource "snowflake_table" "t" { + name = "%s" + database = "%s" + schema = "%s" + + column { + name = "col1" + type = "NUMBER(38,0)" + } +} + +resource "snowflake_table_constraint" "unique" { + name = "%s" + type = "UNIQUE" + table_id = snowflake_table.t.fully_qualified_name + columns = ["col1"] +} +`, n, databaseName, schemaName, n) +} + func tableConstraintUniqueConfigUsingTableId(name string, databaseName string, schemaName string, idSeparator string) string { return fmt.Sprintf(` resource "snowflake_table" "t" { @@ -422,17 +444,17 @@ func tableConstraintEmptyForeignKeyProperties(name string, databaseName string, name = "%[3]s" database = "%[1]s" schema = "%[2]s" - + column { name = "col1" type = "NUMBER(38,0)" } } - + resource "snowflake_table_constraint" "unique" { name = "%[3]s" type = "FOREIGN KEY" - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name columns = ["col1"] foreign_key_properties { } @@ -446,22 +468,22 @@ func tableConstraintForeignKeyProperties(name string, databaseName string, schem name = "%[3]s" database = "%[1]s" schema = "%[2]s" - + column { name = "col1" type = "NUMBER(38,0)" } } - + resource "snowflake_table_constraint" "unique" { name = "%[3]s" type = "FOREIGN KEY" - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name columns = ["col1"] foreign_key_properties { references { columns = ["col1"] - table_id = snowflake_table.t.qualified_name + table_id = snowflake_table.t.fully_qualified_name } } } diff --git a/pkg/resources/tag.go b/pkg/resources/tag.go index 5029a5d3d8..37e4018b9d 100644 --- a/pkg/resources/tag.go +++ b/pkg/resources/tag.go @@ -10,6 +10,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" ) @@ -43,6 +44,7 @@ var tagSchema = map[string]*schema.Schema{ Optional: true, Description: "List of allowed values for the tag.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } var tagReferenceSchema = &schema.Schema{ @@ -122,6 +124,9 @@ func ReadContextTag(ctx context.Context, d *schema.ResourceData, meta any) diag. 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) } diff --git a/pkg/resources/tag_acceptance_test.go b/pkg/resources/tag_acceptance_test.go index 49ba2f0a8e..f831685a6e 100644 --- a/pkg/resources/tag_acceptance_test.go +++ b/pkg/resources/tag_acceptance_test.go @@ -12,11 +12,11 @@ import ( ) func TestAcc_Tag(t *testing.T) { - name := acc.TestClient().Ids.Alpha() + id := acc.TestClient().Ids.RandomSchemaObjectIdentifier() resourceName := "snowflake_tag.t" m := func() map[string]config.Variable { return map[string]config.Variable{ - "name": config.StringVariable(name), + "name": config.StringVariable(id.Name()), "database": config.StringVariable(acc.TestDatabaseName), "schema": config.StringVariable(acc.TestSchemaName), "comment": config.StringVariable("Terraform acceptance test"), @@ -42,7 +42,8 @@ func TestAcc_Tag(t *testing.T) { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Tag/basic"), ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), + 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"), @@ -56,7 +57,8 @@ func TestAcc_Tag(t *testing.T) { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Tag/basic"), ConfigVariables: variableSet2, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), + 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"), @@ -68,7 +70,8 @@ func TestAcc_Tag(t *testing.T) { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_Tag/basic"), ConfigVariables: variableSet3, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "name", id.Name()), + resource.TestCheckResourceAttr(resourceName, "fully_qualified_name", id.FullyQualifiedName()), resource.TestCheckResourceAttr(resourceName, "comment", "Terraform acceptance test - updated"), ), }, diff --git a/pkg/resources/task.go b/pkg/resources/task.go index 3b9cb73351..8a135be2c3 100644 --- a/pkg/resources/task.go +++ b/pkg/resources/task.go @@ -11,6 +11,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/util" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -118,6 +119,7 @@ var taskSchema = map[string]*schema.Schema{ Default: false, Description: "By default, Snowflake ensures that only one instance of a particular DAG is allowed to run at a time, setting the parameter value to TRUE permits DAG runs to overlap.", }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // difference find keys in 'a' but not in 'b'. @@ -176,6 +178,9 @@ func ReadTask(d *schema.ResourceData, meta interface{}) error { d.SetId("") return nil } + if err := d.Set(FullyQualifiedNameAttributeName, taskId.FullyQualifiedName()); err != nil { + return err + } if err := d.Set("enabled", task.IsStarted()); err != nil { return err diff --git a/pkg/resources/task_acceptance_test.go b/pkg/resources/task_acceptance_test.go index 4b046c1a4a..03b3b21255 100644 --- a/pkg/resources/task_acceptance_test.go +++ b/pkg/resources/task_acceptance_test.go @@ -41,7 +41,9 @@ type ( var ( rootname = acc.TestClient().Ids.AlphaContaining("_root_task") + rootId = sdk.NewSchemaObjectIdentifier(acc.TestDatabaseName, acc.TestSchemaName, rootname) childname = acc.TestClient().Ids.AlphaContaining("_child_task") + childId = sdk.NewSchemaObjectIdentifier(acc.TestDatabaseName, acc.TestSchemaName, childname) soloname = acc.TestClient().Ids.AlphaContaining("_standalone_task") initialState = &AccTaskTestSettings{ //nolint @@ -204,7 +206,9 @@ func TestAcc_Task(t *testing.T) { checkBool("snowflake_task.root_task", "enabled", true), checkBool("snowflake_task.child_task", "enabled", false), resource.TestCheckResourceAttr("snowflake_task.root_task", "name", rootname), + resource.TestCheckResourceAttr("snowflake_task.root_task", "fully_qualified_name", rootId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_task.child_task", "name", childname), + resource.TestCheckResourceAttr("snowflake_task.child_task", "fully_qualified_name", childId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_task.root_task", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_task.child_task", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_task.root_task", "schema", acc.TestSchemaName), @@ -228,7 +232,9 @@ func TestAcc_Task(t *testing.T) { checkBool("snowflake_task.root_task", "enabled", true), checkBool("snowflake_task.child_task", "enabled", true), resource.TestCheckResourceAttr("snowflake_task.root_task", "name", rootname), + resource.TestCheckResourceAttr("snowflake_task.root_task", "fully_qualified_name", rootId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_task.child_task", "name", childname), + resource.TestCheckResourceAttr("snowflake_task.child_task", "fully_qualified_name", childId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_task.root_task", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_task.child_task", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_task.root_task", "schema", acc.TestSchemaName), @@ -251,7 +257,9 @@ func TestAcc_Task(t *testing.T) { checkBool("snowflake_task.root_task", "enabled", true), checkBool("snowflake_task.child_task", "enabled", true), resource.TestCheckResourceAttr("snowflake_task.root_task", "name", rootname), + resource.TestCheckResourceAttr("snowflake_task.root_task", "fully_qualified_name", rootId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_task.child_task", "name", childname), + resource.TestCheckResourceAttr("snowflake_task.child_task", "fully_qualified_name", childId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_task.root_task", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_task.child_task", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_task.root_task", "schema", acc.TestSchemaName), @@ -274,7 +282,9 @@ func TestAcc_Task(t *testing.T) { checkBool("snowflake_task.root_task", "enabled", false), checkBool("snowflake_task.child_task", "enabled", false), resource.TestCheckResourceAttr("snowflake_task.root_task", "name", rootname), + resource.TestCheckResourceAttr("snowflake_task.root_task", "fully_qualified_name", rootId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_task.child_task", "name", childname), + resource.TestCheckResourceAttr("snowflake_task.child_task", "fully_qualified_name", childId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_task.root_task", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_task.child_task", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_task.root_task", "schema", acc.TestSchemaName), @@ -297,7 +307,9 @@ func TestAcc_Task(t *testing.T) { checkBool("snowflake_task.root_task", "enabled", true), checkBool("snowflake_task.child_task", "enabled", false), resource.TestCheckResourceAttr("snowflake_task.root_task", "name", rootname), + resource.TestCheckResourceAttr("snowflake_task.root_task", "fully_qualified_name", rootId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_task.child_task", "name", childname), + resource.TestCheckResourceAttr("snowflake_task.child_task", "fully_qualified_name", childId.FullyQualifiedName()), resource.TestCheckResourceAttr("snowflake_task.root_task", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_task.child_task", "database", acc.TestDatabaseName), resource.TestCheckResourceAttr("snowflake_task.root_task", "schema", acc.TestSchemaName), diff --git a/pkg/resources/testdata/TestAcc_GrantDatabaseRole/account_role/test.tf b/pkg/resources/testdata/TestAcc_GrantDatabaseRole/account_role/test.tf index d3504d5e73..c2b621bf7f 100644 --- a/pkg/resources/testdata/TestAcc_GrantDatabaseRole/account_role/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantDatabaseRole/account_role/test.tf @@ -20,6 +20,6 @@ resource "snowflake_account_role" "parent_role" { } resource "snowflake_grant_database_role" "g" { - database_role_name = "\"${var.database}\".\"${snowflake_database_role.database_role.name}\"" + database_role_name = snowflake_database_role.database_role.fully_qualified_name parent_role_name = snowflake_account_role.parent_role.name } diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_DatabaseRole_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_DatabaseRole_ToAccountRole/test.tf index b4f7255789..a486c8c677 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_DatabaseRole_ToAccountRole/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_DatabaseRole_ToAccountRole/test.tf @@ -15,6 +15,6 @@ resource "snowflake_grant_ownership" "test" { account_role_name = snowflake_account_role.test.name on { object_type = "DATABASE ROLE" - object_name = "\"${snowflake_database_role.test.database}\".\"${snowflake_database_role.test.name}\"" + object_name = snowflake_database_role.test.fully_qualified_name } } diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnPipe/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnPipe/test.tf index bee2bc3773..a9b3cd6c71 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnPipe/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnPipe/test.tf @@ -31,6 +31,6 @@ resource "snowflake_grant_ownership" "test" { on { object_type = "PIPE" - object_name = "\"${snowflake_pipe.test.database}\".\"${snowflake_pipe.test.schema}\".\"${snowflake_pipe.test.name}\"" + object_name = snowflake_pipe.test.fully_qualified_name } } diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask/test.tf index 1498779807..f7b80a6d9a 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask/test.tf @@ -15,6 +15,6 @@ resource "snowflake_grant_ownership" "test" { on { object_type = "TASK" - object_name = "\"${snowflake_task.test.database}\".\"${snowflake_task.test.schema}\".\"${snowflake_task.test.name}\"" + object_name = snowflake_task.test.fully_qualified_name } } diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/1/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/1/test.tf index 1498779807..f7b80a6d9a 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/1/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/1/test.tf @@ -15,6 +15,6 @@ resource "snowflake_grant_ownership" "test" { on { object_type = "TASK" - object_name = "\"${snowflake_task.test.database}\".\"${snowflake_task.test.schema}\".\"${snowflake_task.test.name}\"" + object_name = snowflake_task.test.fully_qualified_name } } diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/2/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/2/test.tf index bbd0671707..5aa8c57b5f 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/2/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/2/test.tf @@ -26,7 +26,7 @@ resource "snowflake_grant_ownership" "test" { on { object_type = "TASK" - object_name = "\"${snowflake_task.test.database}\".\"${snowflake_task.test.schema}\".\"${snowflake_task.test.name}\"" + object_name = snowflake_task.test.fully_qualified_name } } @@ -35,6 +35,6 @@ resource "snowflake_grant_ownership" "child" { on { object_type = "TASK" - object_name = "\"${snowflake_task.child.database}\".\"${snowflake_task.child.schema}\".\"${snowflake_task.child.name}\"" + object_name = snowflake_task.child.fully_qualified_name } -} \ No newline at end of file +} diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject/test.tf index 5f4cc61b8b..bf9bbfeee3 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject/test.tf @@ -17,6 +17,6 @@ resource "snowflake_grant_privileges_to_account_role" "test" { on_schema_object { object_type = "TABLE" - object_name = "\"${var.database}\".\"${var.schema}\".\"${var.table_name}\"" + object_name = snowflake_table.test.fully_qualified_name } } diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToShare/OnAllTablesInSchema/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToShare/OnAllTablesInSchema/test.tf index 9489f22e69..daca4d9bae 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToShare/OnAllTablesInSchema/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToShare/OnAllTablesInSchema/test.tf @@ -21,6 +21,6 @@ resource "snowflake_grant_privileges_to_share" "test_setup" { resource "snowflake_grant_privileges_to_share" "test" { to_share = snowflake_share.test.name privileges = var.privileges - on_all_tables_in_schema = "\"${snowflake_schema.test.database}\".\"${snowflake_schema.test.name}\"" + on_all_tables_in_schema = snowflake_schema.test.fully_qualified_name depends_on = [snowflake_grant_privileges_to_share.test_setup] } diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToShare/OnSchema/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToShare/OnSchema/test.tf index ebf6bc1ae5..24a22d32f9 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToShare/OnSchema/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToShare/OnSchema/test.tf @@ -21,6 +21,6 @@ resource "snowflake_grant_privileges_to_share" "test_setup" { resource "snowflake_grant_privileges_to_share" "test" { to_share = snowflake_share.test.name privileges = var.privileges - on_schema = "\"${snowflake_schema.test.database}\".\"${snowflake_schema.test.name}\"" + on_schema = snowflake_schema.test.fully_qualified_name depends_on = [snowflake_grant_privileges_to_share.test_setup] } diff --git a/pkg/resources/user.go b/pkg/resources/user.go index 6eb8009266..2f0c8c0a70 100644 --- a/pkg/resources/user.go +++ b/pkg/resources/user.go @@ -144,6 +144,7 @@ var userSchema = map[string]*schema.Schema{ Schema: schemas.ShowUserParametersSchema, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func User() *schema.Resource { @@ -163,6 +164,7 @@ func User() *schema.Resource { // ComputedIfAnyAttributeChanged(ShowOutputAttributeName), // TODO [SNOW-1348101]: use list from user parameters definition instead listing all here ComputedIfAnyAttributeChanged(ParametersAttributeName, strings.ToLower(string(sdk.UserParameterAbortDetachedQuery)), strings.ToLower(string(sdk.UserParameterAutocommit)), strings.ToLower(string(sdk.UserParameterBinaryInputFormat)), strings.ToLower(string(sdk.UserParameterBinaryOutputFormat)), strings.ToLower(string(sdk.UserParameterClientMemoryLimit)), strings.ToLower(string(sdk.UserParameterClientMetadataRequestUseConnectionCtx)), strings.ToLower(string(sdk.UserParameterClientPrefetchThreads)), strings.ToLower(string(sdk.UserParameterClientResultChunkSize)), strings.ToLower(string(sdk.UserParameterClientResultColumnCaseInsensitive)), strings.ToLower(string(sdk.UserParameterClientSessionKeepAlive)), strings.ToLower(string(sdk.UserParameterClientSessionKeepAliveHeartbeatFrequency)), strings.ToLower(string(sdk.UserParameterClientTimestampTypeMapping)), strings.ToLower(string(sdk.UserParameterDateInputFormat)), strings.ToLower(string(sdk.UserParameterDateOutputFormat)), strings.ToLower(string(sdk.UserParameterEnableUnloadPhysicalTypeOptimization)), strings.ToLower(string(sdk.UserParameterErrorOnNondeterministicMerge)), strings.ToLower(string(sdk.UserParameterErrorOnNondeterministicUpdate)), strings.ToLower(string(sdk.UserParameterGeographyOutputFormat)), strings.ToLower(string(sdk.UserParameterGeometryOutputFormat)), strings.ToLower(string(sdk.UserParameterJdbcTreatDecimalAsInt)), strings.ToLower(string(sdk.UserParameterJdbcTreatTimestampNtzAsUtc)), strings.ToLower(string(sdk.UserParameterJdbcUseSessionTimezone)), strings.ToLower(string(sdk.UserParameterJsonIndent)), strings.ToLower(string(sdk.UserParameterLockTimeout)), strings.ToLower(string(sdk.UserParameterLogLevel)), strings.ToLower(string(sdk.UserParameterMultiStatementCount)), strings.ToLower(string(sdk.UserParameterNoorderSequenceAsDefault)), strings.ToLower(string(sdk.UserParameterOdbcTreatDecimalAsInt)), strings.ToLower(string(sdk.UserParameterQueryTag)), strings.ToLower(string(sdk.UserParameterQuotedIdentifiersIgnoreCase)), strings.ToLower(string(sdk.UserParameterRowsPerResultset)), strings.ToLower(string(sdk.UserParameterS3StageVpceDnsName)), strings.ToLower(string(sdk.UserParameterSearchPath)), strings.ToLower(string(sdk.UserParameterSimulatedDataSharingConsumer)), strings.ToLower(string(sdk.UserParameterStatementQueuedTimeoutInSeconds)), strings.ToLower(string(sdk.UserParameterStatementTimeoutInSeconds)), strings.ToLower(string(sdk.UserParameterStrictJsonOutput)), strings.ToLower(string(sdk.UserParameterTimestampDayIsAlways24h)), strings.ToLower(string(sdk.UserParameterTimestampInputFormat)), strings.ToLower(string(sdk.UserParameterTimestampLtzOutputFormat)), strings.ToLower(string(sdk.UserParameterTimestampNtzOutputFormat)), strings.ToLower(string(sdk.UserParameterTimestampOutputFormat)), strings.ToLower(string(sdk.UserParameterTimestampTypeMapping)), strings.ToLower(string(sdk.UserParameterTimestampTzOutputFormat)), strings.ToLower(string(sdk.UserParameterTimezone)), strings.ToLower(string(sdk.UserParameterTimeInputFormat)), strings.ToLower(string(sdk.UserParameterTimeOutputFormat)), strings.ToLower(string(sdk.UserParameterTraceLevel)), strings.ToLower(string(sdk.UserParameterTransactionAbortOnError)), strings.ToLower(string(sdk.UserParameterTransactionDefaultIsolationLevel)), strings.ToLower(string(sdk.UserParameterTwoDigitCenturyStart)), strings.ToLower(string(sdk.UserParameterUnsupportedDdlAction)), strings.ToLower(string(sdk.UserParameterUseCachedResult)), strings.ToLower(string(sdk.UserParameterWeekOfYearPolicy)), strings.ToLower(string(sdk.UserParameterWeekStart)), strings.ToLower(string(sdk.UserParameterEnableUnredactedQuerySyntaxError)), strings.ToLower(string(sdk.UserParameterNetworkPolicy)), strings.ToLower(string(sdk.UserParameterPreventUnloadToInternalStages))), + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), userParametersCustomDiff, ), } @@ -284,12 +286,15 @@ func GetReadUserFunc(withExternalChangesMarking bool) schema.ReadContextFunc { } return diag.FromErr(err) } - userParameters, err := client.Users.ShowParameters(ctx, id) if err != nil { return diag.FromErr(err) } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } + if err := setStringProperty(d, "name", user.Name); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/user_acceptance_test.go b/pkg/resources/user_acceptance_test.go index 00e0de720a..e63696e9c6 100644 --- a/pkg/resources/user_acceptance_test.go +++ b/pkg/resources/user_acceptance_test.go @@ -47,6 +47,8 @@ func TestAcc_User(t *testing.T) { r := require.New(t) prefix := acc.TestClient().Ids.Alpha() prefix2 := acc.TestClient().Ids.Alpha() + id := sdk.NewAccountObjectIdentifier(prefix) + id2 := sdk.NewAccountObjectIdentifier(prefix2) comment := random.Comment() newComment := random.Comment() @@ -80,6 +82,7 @@ func TestAcc_User(t *testing.T) { resource.TestCheckResourceAttr("snowflake_user.w", "default_role", "foo"), resource.TestCheckResourceAttr("snowflake_user.w", "default_secondary_roles.0", "ALL"), resource.TestCheckResourceAttr("snowflake_user.w", "default_namespace", "foo.bar"), + resource.TestCheckResourceAttr("snowflake_user.w", "fully_qualified_name", id.FullyQualifiedName()), checkBool("snowflake_user.w", "has_rsa_public_key", true), checkBool("snowflake_user.w", "must_change_password", true), ), @@ -105,6 +108,7 @@ func TestAcc_User(t *testing.T) { resource.TestCheckResourceAttr("snowflake_user.w", "default_role", "foo"), resource.TestCheckResourceAttr("snowflake_user.w", "default_secondary_roles.0", "ALL"), resource.TestCheckResourceAttr("snowflake_user.w", "default_namespace", "foo.bar"), + resource.TestCheckResourceAttr("snowflake_user.w", "fully_qualified_name", id2.FullyQualifiedName()), ), }, // CHANGE PROPERTIES @@ -125,6 +129,7 @@ func TestAcc_User(t *testing.T) { resource.TestCheckResourceAttr("snowflake_user.w", "default_secondary_roles.#", "0"), resource.TestCheckResourceAttr("snowflake_user.w", "default_namespace", "bar.baz"), checkBool("snowflake_user.w", "has_rsa_public_key", false), + resource.TestCheckResourceAttr("snowflake_user.w", "fully_qualified_name", id2.FullyQualifiedName()), ), }, // IMPORT @@ -233,8 +238,9 @@ resource "snowflake_user" "w" { default_namespace="bar.baz" } ` + s = fmt.Sprintf(s, prefix, prefix) log.Printf("[DEBUG] s2 %s", s) - return fmt.Sprintf(s, prefix, prefix) + return s } // TestAcc_User_issue2058 proves https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2058 issue. diff --git a/pkg/resources/user_password_policy_attachment_acceptance_test.go b/pkg/resources/user_password_policy_attachment_acceptance_test.go index 82879446fd..1e466cc3c1 100644 --- a/pkg/resources/user_password_policy_attachment_acceptance_test.go +++ b/pkg/resources/user_password_policy_attachment_acceptance_test.go @@ -67,7 +67,7 @@ resource "snowflake_password_policy" "pp" { } resource "snowflake_user_password_policy_attachment" "ppa" { - password_policy_name = "\"${snowflake_password_policy.pp.database}\".\"${snowflake_password_policy.pp.schema}\".\"${snowflake_password_policy.pp.name}\"" + password_policy_name = snowflake_password_policy.pp.fully_qualified_name user_name = snowflake_user.user.name } `, userName, databaseName, schemaName, passwordPolicyName) diff --git a/pkg/resources/view.go b/pkg/resources/view.go index 8fea269008..33700718ab 100644 --- a/pkg/resources/view.go +++ b/pkg/resources/view.go @@ -7,10 +7,12 @@ import ( "regexp" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/snowflake" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -73,7 +75,8 @@ var viewSchema = map[string]*schema.Schema{ Computed: true, Description: "The timestamp at which the view was created.", }, - "tag": tagReferenceSchema, + "tag": tagReferenceSchema, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } // View returns a pointer to the resource representing a view. @@ -84,6 +87,10 @@ func View() *schema.Resource { Update: UpdateView, Delete: DeleteView, + CustomizeDiff: customdiff.All( + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), + ), + Schema: viewSchema, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -151,6 +158,9 @@ func ReadView(d *schema.ResourceData, meta interface{}) error { d.SetId("") return nil } + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return err + } if err = d.Set("name", view.Name); err != nil { return err diff --git a/pkg/resources/view_acceptance_test.go b/pkg/resources/view_acceptance_test.go index dc553bb1b2..b5149c8e7b 100644 --- a/pkg/resources/view_acceptance_test.go +++ b/pkg/resources/view_acceptance_test.go @@ -184,6 +184,8 @@ func TestAcc_View_Tags(t *testing.T) { func TestAcc_View_Rename(t *testing.T) { viewName := acc.TestClient().Ids.Alpha() newViewName := acc.TestClient().Ids.Alpha() + viewId := sdk.NewSchemaObjectIdentifier(acc.TestDatabaseName, acc.TestSchemaName, viewName) + newViewId := sdk.NewSchemaObjectIdentifier(acc.TestDatabaseName, acc.TestSchemaName, newViewName) query := "SELECT ROLE_NAME, ROLE_OWNER FROM INFORMATION_SCHEMA.APPLICABLE_ROLES" m := func() map[string]config.Variable { @@ -215,6 +217,7 @@ func TestAcc_View_Rename(t *testing.T) { ConfigVariables: m(), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_view.test", "name", viewName), + resource.TestCheckResourceAttr("snowflake_view.test", "fully_qualified_name", viewId.FullyQualifiedName()), ), }, // rename with one param changed @@ -229,6 +232,7 @@ func TestAcc_View_Rename(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_view.test", "name", newViewName), resource.TestCheckResourceAttr("snowflake_view.test", "comment", "new comment"), + resource.TestCheckResourceAttr("snowflake_view.test", "fully_qualified_name", newViewId.FullyQualifiedName()), ), }, }, diff --git a/pkg/resources/warehouse.go b/pkg/resources/warehouse.go index f5952b8570..d054d26c08 100644 --- a/pkg/resources/warehouse.go +++ b/pkg/resources/warehouse.go @@ -147,6 +147,7 @@ var warehouseSchema = map[string]*schema.Schema{ Schema: schemas.ShowWarehouseParametersSchema, }, }, + FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema, } func warehouseParametersProvider(ctx context.Context, d ResourceIdProvider, meta any) ([]*sdk.Parameter, error) { @@ -204,6 +205,7 @@ func Warehouse() *schema.Resource { CustomizeDiff: customdiff.All( ComputedIfAnyAttributeChanged(ShowOutputAttributeName, "warehouse_type", "warehouse_size", "max_cluster_count", "min_cluster_count", "scaling_policy", "auto_suspend", "auto_resume", "resource_monitor", "comment", "enable_query_acceleration", "query_acceleration_max_scale_factor"), ComputedIfAnyAttributeChanged(ParametersAttributeName, strings.ToLower(string(sdk.ObjectParameterMaxConcurrencyLevel)), strings.ToLower(string(sdk.ObjectParameterStatementQueuedTimeoutInSeconds)), strings.ToLower(string(sdk.ObjectParameterStatementTimeoutInSeconds))), + ComputedIfAnyAttributeChanged(FullyQualifiedNameAttributeName, "name"), customdiff.ForceNewIfChange("warehouse_size", func(ctx context.Context, old, new, meta any) bool { return old.(string) != "" && new.(string) == "" }), @@ -400,7 +402,9 @@ func GetReadWarehouseFunc(withExternalChangesMarking bool) schema.ReadContextFun return diag.FromErr(err) } } - + if err := d.Set(FullyQualifiedNameAttributeName, id.FullyQualifiedName()); err != nil { + return diag.FromErr(err) + } if err = d.Set("name", w.Name); err != nil { return diag.FromErr(err) } diff --git a/pkg/resources/warehouse_acceptance_test.go b/pkg/resources/warehouse_acceptance_test.go index 1c337f0f54..bb9656888a 100644 --- a/pkg/resources/warehouse_acceptance_test.go +++ b/pkg/resources/warehouse_acceptance_test.go @@ -121,6 +121,7 @@ func TestAcc_Warehouse_BasicFlows(t *testing.T) { HasAllDefaultsExplicit(), // we can still use normal checks assert.Check(resource.TestCheckResourceAttr("snowflake_warehouse.w", "name", warehouseId.Name())), + assert.Check(resource.TestCheckResourceAttr("snowflake_warehouse.w", "fully_qualified_name", warehouseId.FullyQualifiedName())), ), }, // IMPORT after empty config (in this method, most of the attributes will be filled with the defaults acquired from Snowflake) @@ -129,6 +130,7 @@ func TestAcc_Warehouse_BasicFlows(t *testing.T) { ImportState: true, ImportStateCheck: assert.AssertThatImport(t, assert.CheckImport(importchecks.TestCheckResourceAttrInstanceState(warehouseId.Name(), "name", name)), + assert.CheckImport(importchecks.TestCheckResourceAttrInstanceState(warehouseId.Name(), "fully_qualified_name", warehouseId.FullyQualifiedName())), resourceassert.ImportedWarehouseResource(t, warehouseId.Name()). HasNameString(name). HasWarehouseTypeString(string(sdk.WarehouseTypeStandard)). @@ -182,6 +184,7 @@ func TestAcc_Warehouse_BasicFlows(t *testing.T) { }, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("snowflake_warehouse.w", "name", name2), + resource.TestCheckResourceAttr("snowflake_warehouse.w", "fully_qualified_name", warehouseId2.FullyQualifiedName()), ), }, // Change config but use defaults for every attribute (but not the parameters) - expect no changes (because these are already SF values) except computed show_output (follow-up why suppress diff is not taken into account in has changes?) diff --git a/pkg/schemas/common_types.go b/pkg/schemas/common_types.go index 3193186928..ac4f7f9e0f 100644 --- a/pkg/schemas/common_types.go +++ b/pkg/schemas/common_types.go @@ -21,3 +21,9 @@ var DescribePropertyListSchema = &schema.Schema{ Schema: ShowSecurityIntegrationPropertySchema, }, } + +var FullyQualifiedNameSchema = &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution).", +}