diff --git a/docs/resources/grant_application_role.md b/docs/resources/grant_application_role.md index 5f4fafaefd..f6c9222006 100644 --- a/docs/resources/grant_application_role.md +++ b/docs/resources/grant_application_role.md @@ -13,7 +13,7 @@ description: |- ```terraform locals { - application_role_identifier = "\"my_appplication\".\"app_role_1\"" + application_role_identifier = "\"my_application\".\"app_role_1\"" } ################################## diff --git a/docs/resources/grant_ownership.md b/docs/resources/grant_ownership.md index 56391876f4..355636ca0a 100644 --- a/docs/resources/grant_ownership.md +++ b/docs/resources/grant_ownership.md @@ -8,6 +8,8 @@ description: |- ~> **Note** For more details about granting ownership, please visit [`GRANT OWNERSHIP` Snowflake documentation page](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership), and our [grant ownership resource overview](https://github.com/Snowflake-Labs/terraform-provider-snowflake/tree/main/docs/technical-documentation/grant_ownership_resource_overview.md). +~> **Note** Manage grants on `HYBRID TABLE` by specifying `TABLE` or `TABLES` in `object_type` field. This applies to a single object, all objects, or future objects. This reflects the current behavior in Snowflake. + !> **Warning** Grant ownership resource still has some limitations. Delete operation is not implemented for on_future grants (you have to remove the config and then revoke ownership grant on future X manually). # snowflake_grant_ownership (Resource) diff --git a/docs/resources/grant_privileges_to_account_role.md b/docs/resources/grant_privileges_to_account_role.md index 1f649c4a95..fcbceb0b1b 100644 --- a/docs/resources/grant_privileges_to_account_role.md +++ b/docs/resources/grant_privileges_to_account_role.md @@ -9,6 +9,8 @@ description: |- !> **Warning** Be careful when using `always_apply` field. It will always produce a plan (even when no changes were made) and can be harmful in some setups. For more details why we decided to introduce it to go our document explaining those design decisions (coming soon). +~> **Note** Manage grants on `HYBRID TABLE` by specifying `TABLE` or `TABLES` in `object_type` field. This applies to a single object, all objects, or future objects. This reflects the current behavior in Snowflake. + ~> **Note** When granting privileges on applications (for example, the default "SNOWFLAKE" application) use `on_account_object.object_type = "DATABASE"` instead. # snowflake_grant_privileges_to_account_role (Resource) diff --git a/docs/resources/grant_privileges_to_database_role.md b/docs/resources/grant_privileges_to_database_role.md index aef4fff7e8..3ce074d845 100644 --- a/docs/resources/grant_privileges_to_database_role.md +++ b/docs/resources/grant_privileges_to_database_role.md @@ -9,6 +9,8 @@ description: |- !> **Warning** Be careful when using `always_apply` field. It will always produce a plan (even when no changes were made) and can be harmful in some setups. For more details why we decided to introduce it to go our document explaining those design decisions (coming soon). +~> **Note** Manage grants on `HYBRID TABLE` by specifying `TABLE` or `TABLES` in `object_type` field. This applies to a single object, all objects, or future objects. This reflects the current behavior in Snowflake. + # snowflake_grant_privileges_to_database_role (Resource) diff --git a/examples/resources/snowflake_grant_application_role/resource.tf b/examples/resources/snowflake_grant_application_role/resource.tf index e7d0d2accd..2776697970 100644 --- a/examples/resources/snowflake_grant_application_role/resource.tf +++ b/examples/resources/snowflake_grant_application_role/resource.tf @@ -1,5 +1,5 @@ locals { - application_role_identifier = "\"my_appplication\".\"app_role_1\"" + application_role_identifier = "\"my_application\".\"app_role_1\"" } ################################## diff --git a/pkg/acceptance/helpers/hybrid_table_client.go b/pkg/acceptance/helpers/hybrid_table_client.go new file mode 100644 index 0000000000..40065bec8a --- /dev/null +++ b/pkg/acceptance/helpers/hybrid_table_client.go @@ -0,0 +1,51 @@ +package helpers + +import ( + "context" + "fmt" + "testing" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/stretchr/testify/require" +) + +type HybridTableClient struct { + context *TestClientContext + ids *IdsGenerator +} + +func NewHybridTableClient(context *TestClientContext, idsGenerator *IdsGenerator) *HybridTableClient { + return &HybridTableClient{ + context: context, + ids: idsGenerator, + } +} + +func (c *HybridTableClient) exec(sql string) error { + ctx := context.Background() + _, err := c.context.client.ExecForTests(ctx, sql) + return err +} + +// TODO(SNOW-999142): Use SDK implementation for Hybrid Table once it's available +func (c *HybridTableClient) Create(t *testing.T) (sdk.SchemaObjectIdentifier, func()) { + t.Helper() + id := c.ids.RandomSchemaObjectIdentifier() + err := c.exec(fmt.Sprintf(` +create hybrid table %s ( + id INT AUTOINCREMENT PRIMARY KEY +) +`, id.FullyQualifiedName())) + require.NoError(t, err) + + return id, c.DropFunc(t, id) +} + +func (c *HybridTableClient) DropFunc(t *testing.T, id sdk.SchemaObjectIdentifier) func() { + t.Helper() + + return func() { + err := c.exec(fmt.Sprintf(`drop table if exists %s`, id.FullyQualifiedName())) + require.NoError(t, err) + } +} diff --git a/pkg/acceptance/helpers/test_client.go b/pkg/acceptance/helpers/test_client.go index d7d115b9ec..056554e4d5 100644 --- a/pkg/acceptance/helpers/test_client.go +++ b/pkg/acceptance/helpers/test_client.go @@ -36,6 +36,7 @@ type TestClient struct { FileFormat *FileFormatClient Function *FunctionClient Grant *GrantClient + HybridTable *HybridTableClient InformationSchema *InformationSchemaClient MaskingPolicy *MaskingPolicyClient MaterializedView *MaterializedViewClient @@ -110,6 +111,7 @@ func NewTestClient(c *sdk.Client, database string, schema string, warehouse stri FileFormat: NewFileFormatClient(context, idsGenerator), Function: NewFunctionClient(context, idsGenerator), Grant: NewGrantClient(context, idsGenerator), + HybridTable: NewHybridTableClient(context, idsGenerator), InformationSchema: NewInformationSchemaClient(context, idsGenerator), MaskingPolicy: NewMaskingPolicyClient(context, idsGenerator), MaterializedView: NewMaterializedViewClient(context, idsGenerator), diff --git a/pkg/resources/grant_ownership_acceptance_test.go b/pkg/resources/grant_ownership_acceptance_test.go index ac4ef7b9df..d2ad123879 100644 --- a/pkg/resources/grant_ownership_acceptance_test.go +++ b/pkg/resources/grant_ownership_acceptance_test.go @@ -1556,3 +1556,40 @@ func TestAcc_GrantOwnership_OnObject_ResourceMonitor_ToAccountRole(t *testing.T) }, }) } + +// This test proves that managing grants on HYBRID TABLE is not supported in Snowflake. TABLE should be used instead. +func TestAcc_GrantOwnership_OnObject_HybridTable_ToAccountRole_Fails(t *testing.T) { + acc.TestAccPreCheck(t) + hybridTableId, hybridTableCleanup := acc.TestClient().HybridTable.Create(t) + t.Cleanup(hybridTableCleanup) + + accountRoleId := acc.TestClient().Ids.RandomAccountObjectIdentifier() + accountRoleName := accountRoleId.Name() + + configVariables := func(objectType sdk.ObjectType) config.Variables { + cfg := config.Variables{ + "account_role_name": config.StringVariable(accountRoleName), + "hybrid_table_fully_qualified_name": config.StringVariable(hybridTableId.FullyQualifiedName()), + "object_type": config.StringVariable(string(objectType)), + } + return cfg + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + Steps: []resource.TestStep{ + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantOwnership/OnObject_HybridTable_ToAccountRole"), + ConfigVariables: configVariables(sdk.ObjectTypeHybridTable), + ExpectError: regexp.MustCompile("syntax error line 1 at position 26 unexpected 'TABLE"), + }, + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantOwnership/OnObject_HybridTable_ToAccountRole"), + ConfigVariables: configVariables(sdk.ObjectTypeTable), + }, + }, + }) +} diff --git a/pkg/resources/grant_privileges_to_account_role_acceptance_test.go b/pkg/resources/grant_privileges_to_account_role_acceptance_test.go index c9a0a44ce2..619f269d0b 100644 --- a/pkg/resources/grant_privileges_to_account_role_acceptance_test.go +++ b/pkg/resources/grant_privileges_to_account_role_acceptance_test.go @@ -1955,3 +1955,43 @@ resource "snowflake_grant_privileges_to_account_role" "test" { } `, accountRoleName, strings.Join(collections.Map(privileges, strconv.Quote), ","), objectTypePlural, databaseName) } + +// This test proves that managing grants on HYBRID TABLE is not supported in Snowflake. TABLE should be used instead. +func TestAcc_GrantPrivileges_OnObject_HybridTable_ToAccountRole_Fails(t *testing.T) { + acc.TestAccPreCheck(t) + hybridTableId, hybridTableCleanup := acc.TestClient().HybridTable.Create(t) + t.Cleanup(hybridTableCleanup) + + accountRole, accountRoleCleanup := acc.TestClient().Role.CreateRole(t) + t.Cleanup(accountRoleCleanup) + + configVariables := func(objectType sdk.ObjectType) config.Variables { + cfg := config.Variables{ + "account_role_name": config.StringVariable(accountRole.ID().FullyQualifiedName()), + "privileges": config.ListVariable( + config.StringVariable(string(sdk.SchemaObjectPrivilegeApplyBudget)), + ), + "hybrid_table_fully_qualified_name": config.StringVariable(hybridTableId.FullyQualifiedName()), + "object_type": config.StringVariable(string(objectType)), + } + return cfg + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + Steps: []resource.TestStep{ + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject_HybridTable"), + ConfigVariables: configVariables(sdk.ObjectTypeHybridTable), + ExpectError: regexp.MustCompile("syntax error line 1 at position 28 unexpected 'TABLE"), + }, + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject_HybridTable"), + ConfigVariables: configVariables(sdk.ObjectTypeTable), + }, + }, + }) +} diff --git a/pkg/resources/grant_privileges_to_database_role_acceptance_test.go b/pkg/resources/grant_privileges_to_database_role_acceptance_test.go index 8b701424e4..0ec778c34f 100644 --- a/pkg/resources/grant_privileges_to_database_role_acceptance_test.go +++ b/pkg/resources/grant_privileges_to_database_role_acceptance_test.go @@ -1543,3 +1543,43 @@ resource "snowflake_grant_privileges_to_database_role" "test" { } `, databaseRoleId.Name(), databaseRoleId.DatabaseName(), strings.Join(collections.Map(privileges, strconv.Quote), ","), objectTypePlural, databaseName) } + +// This test proves that managing grants on HYBRID TABLE is not supported in Snowflake. TABLE should be used instead. +func TestAcc_GrantPrivileges_OnObject_HybridTable_ToDatabaseRole_Fails(t *testing.T) { + acc.TestAccPreCheck(t) + hybridTableId, hybridTableCleanup := acc.TestClient().HybridTable.Create(t) + t.Cleanup(hybridTableCleanup) + + databaseRole, databaseRoleCleanup := acc.TestClient().DatabaseRole.CreateDatabaseRole(t) + t.Cleanup(databaseRoleCleanup) + + configVariables := func(objectType sdk.ObjectType) config.Variables { + cfg := config.Variables{ + "database_role_name": config.StringVariable(databaseRole.ID().FullyQualifiedName()), + "privileges": config.ListVariable( + config.StringVariable(string(sdk.SchemaObjectPrivilegeApplyBudget)), + ), + "hybrid_table_fully_qualified_name": config.StringVariable(hybridTableId.FullyQualifiedName()), + "object_type": config.StringVariable(string(objectType)), + } + return cfg + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + Steps: []resource.TestStep{ + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject_HybridTable"), + ConfigVariables: configVariables(sdk.ObjectTypeHybridTable), + ExpectError: regexp.MustCompile("syntax error line 1 at position 28 unexpected 'TABLE"), + }, + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject_HybridTable"), + ConfigVariables: configVariables(sdk.ObjectTypeTable), + }, + }, + }) +} diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_HybridTable_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_HybridTable_ToAccountRole/test.tf new file mode 100644 index 0000000000..bdb2dd1aeb --- /dev/null +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_HybridTable_ToAccountRole/test.tf @@ -0,0 +1,11 @@ +resource "snowflake_account_role" "test" { + name = var.account_role_name +} + +resource "snowflake_grant_ownership" "test" { + account_role_name = snowflake_account_role.test.name + on { + object_type = var.object_type + object_name = var.hybrid_table_fully_qualified_name + } +} diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_HybridTable_ToAccountRole/variables.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_HybridTable_ToAccountRole/variables.tf new file mode 100644 index 0000000000..cc25e3abe6 --- /dev/null +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_HybridTable_ToAccountRole/variables.tf @@ -0,0 +1,11 @@ +variable "account_role_name" { + type = string +} + +variable "hybrid_table_fully_qualified_name" { + type = string +} + +variable "object_type" { + type = string +} diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Table_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Table_ToAccountRole/test.tf index 9501038779..630167e855 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Table_ToAccountRole/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Table_ToAccountRole/test.tf @@ -26,6 +26,6 @@ resource "snowflake_grant_ownership" "test" { account_role_name = snowflake_account_role.test.name on { object_type = "TABLE" - object_name = "\"${snowflake_database.test.name}\".\"${snowflake_schema.test.name}\".\"${snowflake_table.test.name}\"" + object_name = snowflake_table.test.fully_qualified_name } } diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject_HybridTable/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject_HybridTable/test.tf new file mode 100644 index 0000000000..b8d76c5121 --- /dev/null +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject_HybridTable/test.tf @@ -0,0 +1,9 @@ +resource "snowflake_grant_privileges_to_account_role" "test" { + account_role_name = var.account_role_name + privileges = var.privileges + + on_schema_object { + object_type = var.object_type + object_name = var.hybrid_table_fully_qualified_name + } +} diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject_HybridTable/variables.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject_HybridTable/variables.tf new file mode 100644 index 0000000000..a9102ceb43 --- /dev/null +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnObject_HybridTable/variables.tf @@ -0,0 +1,15 @@ +variable "hybrid_table_fully_qualified_name" { + type = string +} + +variable "privileges" { + type = list(string) +} + +variable "account_role_name" { + type = string +} + +variable "object_type" { + type = string +} diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject/test.tf index 2d480820ae..37bb21c5c9 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject/test.tf @@ -10,13 +10,12 @@ resource "snowflake_table" "test" { } resource "snowflake_grant_privileges_to_database_role" "test" { - depends_on = [snowflake_table.test] database_role_name = "\"${var.database}\".\"${var.name}\"" privileges = var.privileges with_grant_option = var.with_grant_option 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_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject_HybridTable/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject_HybridTable/test.tf new file mode 100644 index 0000000000..e6f7b0f8af --- /dev/null +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject_HybridTable/test.tf @@ -0,0 +1,9 @@ +resource "snowflake_grant_privileges_to_database_role" "test" { + database_role_name = var.database_role_name + privileges = var.privileges + + on_schema_object { + object_type = var.object_type + object_name = var.hybrid_table_fully_qualified_name + } +} diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject_HybridTable/variables.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject_HybridTable/variables.tf new file mode 100644 index 0000000000..04ceac7604 --- /dev/null +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnObject_HybridTable/variables.tf @@ -0,0 +1,15 @@ +variable "hybrid_table_fully_qualified_name" { + type = string +} + +variable "privileges" { + type = list(string) +} + +variable "database_role_name" { + type = string +} + +variable "object_type" { + type = string +} diff --git a/templates/resources/grant_ownership.md.tmpl b/templates/resources/grant_ownership.md.tmpl index 8da2afbaff..47ccc97d81 100644 --- a/templates/resources/grant_ownership.md.tmpl +++ b/templates/resources/grant_ownership.md.tmpl @@ -12,6 +12,8 @@ description: |- ~> **Note** For more details about granting ownership, please visit [`GRANT OWNERSHIP` Snowflake documentation page](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership), and our [grant ownership resource overview](https://github.com/Snowflake-Labs/terraform-provider-snowflake/tree/main/docs/technical-documentation/grant_ownership_resource_overview.md). +~> **Note** Manage grants on `HYBRID TABLE` by specifying `TABLE` or `TABLES` in `object_type` field. This applies to a single object, all objects, or future objects. This reflects the current behavior in Snowflake. + !> **Warning** Grant ownership resource still has some limitations. Delete operation is not implemented for on_future grants (you have to remove the config and then revoke ownership grant on future X manually). # {{.Name}} ({{.Type}}) diff --git a/templates/resources/grant_privileges_to_account_role.md.tmpl b/templates/resources/grant_privileges_to_account_role.md.tmpl index 784653e7ac..72e698574f 100644 --- a/templates/resources/grant_privileges_to_account_role.md.tmpl +++ b/templates/resources/grant_privileges_to_account_role.md.tmpl @@ -13,6 +13,8 @@ description: |- {{/* SNOW-990811 */}} !> **Warning** Be careful when using `always_apply` field. It will always produce a plan (even when no changes were made) and can be harmful in some setups. For more details why we decided to introduce it to go our document explaining those design decisions (coming soon). +~> **Note** Manage grants on `HYBRID TABLE` by specifying `TABLE` or `TABLES` in `object_type` field. This applies to a single object, all objects, or future objects. This reflects the current behavior in Snowflake. + ~> **Note** When granting privileges on applications (for example, the default "SNOWFLAKE" application) use `on_account_object.object_type = "DATABASE"` instead. # {{.Name}} ({{.Type}}) diff --git a/templates/resources/grant_privileges_to_database_role.md.tmpl b/templates/resources/grant_privileges_to_database_role.md.tmpl index beb22dd524..0f5e7858ab 100644 --- a/templates/resources/grant_privileges_to_database_role.md.tmpl +++ b/templates/resources/grant_privileges_to_database_role.md.tmpl @@ -13,6 +13,8 @@ description: |- {{/* SNOW-990811 */}} !> **Warning** Be careful when using `always_apply` field. It will always produce a plan (even when no changes were made) and can be harmful in some setups. For more details why we decided to introduce it to go our document explaining those design decisions (coming soon). +~> **Note** Manage grants on `HYBRID TABLE` by specifying `TABLE` or `TABLES` in `object_type` field. This applies to a single object, all objects, or future objects. This reflects the current behavior in Snowflake. + # {{.Name}} ({{.Type}}) {{ .Description | trimspace }}