Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Add notes about managing grants on hybrid table #3368

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/resources/grant_application_role.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ description: |-

```terraform
locals {
application_role_identifier = "\"my_appplication\".\"app_role_1\""
application_role_identifier = "\"my_application\".\"app_role_1\""
}
##################################
Expand Down
2 changes: 2 additions & 0 deletions docs/resources/grant_ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions docs/resources/grant_privileges_to_account_role.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions docs/resources/grant_privileges_to_database_role.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
locals {
application_role_identifier = "\"my_appplication\".\"app_role_1\""
application_role_identifier = "\"my_application\".\"app_role_1\""
}

##################################
Expand Down
51 changes: 51 additions & 0 deletions pkg/acceptance/helpers/hybrid_table_client.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
2 changes: 2 additions & 0 deletions pkg/acceptance/helpers/test_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type TestClient struct {
FileFormat *FileFormatClient
Function *FunctionClient
Grant *GrantClient
HybridTable *HybridTableClient
InformationSchema *InformationSchemaClient
MaskingPolicy *MaskingPolicyClient
MaterializedView *MaterializedViewClient
Expand Down Expand Up @@ -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),
Expand Down
37 changes: 37 additions & 0 deletions pkg/resources/grant_ownership_acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
},
},
})
}
40 changes: 40 additions & 0 deletions pkg/resources/grant_privileges_to_account_role_acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
},
},
})
}
40 changes: 40 additions & 0 deletions pkg/resources/grant_privileges_to_database_role_acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
},
},
})
}
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
variable "account_role_name" {
type = string
}

variable "hybrid_table_fully_qualified_name" {
type = string
}

variable "object_type" {
type = string
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.fully_qualified_name
}
}
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.fully_qualified_name
}
}
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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
}
2 changes: 2 additions & 0 deletions templates/resources/grant_ownership.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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}})
Expand Down
2 changes: 2 additions & 0 deletions templates/resources/grant_privileges_to_account_role.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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}})
Expand Down
2 changes: 2 additions & 0 deletions templates/resources/grant_privileges_to_database_role.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand Down
Loading