From b2dae02c3be1053c368cf1ede2b67e8da0a36be2 Mon Sep 17 00:00:00 2001 From: Artur Sawicki Date: Wed, 27 Mar 2024 14:10:57 +0100 Subject: [PATCH 1/7] Prove issue with granting ML privileges References: #2651 --- .../grant_privileges_to_account_role.md | 3 ++ ...vileges_to_account_role_acceptance_test.go | 52 +++++++++++++++++++ .../grant_privileges_to_account_role.md.tmpl | 3 ++ 3 files changed, 58 insertions(+) diff --git a/docs/resources/grant_privileges_to_account_role.md b/docs/resources/grant_privileges_to_account_role.md index 64af3480f7..5577dcfb87 100644 --- a/docs/resources/grant_privileges_to_account_role.md +++ b/docs/resources/grant_privileges_to_account_role.md @@ -329,6 +329,9 @@ Optional: - `in_database` (String) - `in_schema` (String) +## Known limitations +- Setting the `CREATE SNOWFLAKE.ML.ANOMALY_DETECTION` or `CREATE SNOWFLAKE.ML.FORECAST` privileges on schema results in a permadiff because of the probably incorrect Snowflake's behavior of `SHOW GRANTS ON `. More in the [comment](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2651#issuecomment-2022634952). + ## Import ~> **Note** All the ..._name parts should be fully qualified names (where every part is quoted), e.g. for schema object it is `""."".""` 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 309d92aa09..213f31fb15 100644 --- a/pkg/resources/grant_privileges_to_account_role_acceptance_test.go +++ b/pkg/resources/grant_privileges_to_account_role_acceptance_test.go @@ -1059,6 +1059,58 @@ func TestAcc_GrantPrivilegesToAccountRole_OnExternalVolume(t *testing.T) { }) } +// proves https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2651 +// TODO [SNOW-1270457]: This seems to be a Snowflake error, we are waiting for the confirmation. Alter the test when the behavior is fixed. Update the resource documentation (section known issues). +func TestAcc_GrantPrivilegesToAccountRole_MLPrivileges(t *testing.T) { + name := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)) + roleName := sdk.NewAccountObjectIdentifier(name).FullyQualifiedName() + configVariables := config.Variables{ + "name": config.StringVariable(roleName), + "privileges": config.ListVariable( + config.StringVariable(string(sdk.SchemaPrivilegeCreateSnowflakeMlAnomalyDetection)), + config.StringVariable(string(sdk.SchemaPrivilegeCreateSnowflakeMlForecast)), + ), + "database": config.StringVariable(acc.TestDatabaseName), + "schema": config.StringVariable(acc.TestSchemaName), + "with_grant_option": config.BoolVariable(false), + } + resourceName := "snowflake_grant_privileges_to_account_role.test" + + schemaName := sdk.NewDatabaseObjectIdentifier(acc.TestDatabaseName, acc.TestSchemaName).FullyQualifiedName() + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: testAccCheckAccountRolePrivilegesRevoked(name), + Steps: []resource.TestStep{ + { + PreConfig: func() { createAccountRoleOutsideTerraform(t, name) }, + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantPrivilegesToAccountRole/OnSchema"), + ConfigVariables: configVariables, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "account_role_name", roleName), + resource.TestCheckResourceAttr(resourceName, "privileges.#", "2"), + resource.TestCheckResourceAttr(resourceName, "privileges.0", string(sdk.SchemaPrivilegeCreateSnowflakeMlAnomalyDetection)), + resource.TestCheckResourceAttr(resourceName, "privileges.1", string(sdk.SchemaPrivilegeCreateSnowflakeMlForecast)), + resource.TestCheckResourceAttr(resourceName, "on_schema.#", "1"), + resource.TestCheckResourceAttr(resourceName, "on_schema.0.schema_name", schemaName), + resource.TestCheckResourceAttr(resourceName, "with_grant_option", "false"), + resource.TestCheckResourceAttr(resourceName, "id", fmt.Sprintf("%s|false|false|CREATE SNOWFLAKE.ML.ANOMALY_DETECTION,CREATE SNOWFLAKE.ML.FORECAST|OnSchema|OnSchema|%s", roleName, schemaName)), + ), + ExpectNonEmptyPlan: true, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectNonEmptyPlan(), + }, + }, + }, + }, + }) +} + func getSecondaryAccountName(t *testing.T) (string, error) { t.Helper() config, err := sdk.ProfileConfig(testprofiles.Secondary) diff --git a/templates/resources/grant_privileges_to_account_role.md.tmpl b/templates/resources/grant_privileges_to_account_role.md.tmpl index f591bf021c..e12d772e80 100644 --- a/templates/resources/grant_privileges_to_account_role.md.tmpl +++ b/templates/resources/grant_privileges_to_account_role.md.tmpl @@ -29,6 +29,9 @@ description: |- {{ .SchemaMarkdown | trimspace }} +## Known limitations +- Setting the `CREATE SNOWFLAKE.ML.ANOMALY_DETECTION` or `CREATE SNOWFLAKE.ML.FORECAST` privileges on schema results in a permadiff because of the probably incorrect Snowflake's behavior of `SHOW GRANTS ON `. More in the [comment](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2651#issuecomment-2022634952). + ## Import ~> **Note** All the ..._name parts should be fully qualified names (where every part is quoted), e.g. for schema object it is `""."".""` From ca5d1d580b2b8e79a5b582e4b67c738b1c6dfa2d Mon Sep 17 00:00:00 2001 From: Artur Sawicki Date: Wed, 27 Mar 2024 14:43:37 +0100 Subject: [PATCH 2/7] Refactor grant to object type validations --- .../grant_privileges_to_account_role.md | 6 +- .../grant_privileges_to_database_role.md | 6 +- docs/resources/grant_privileges_to_role.md | 6 +- pkg/resources/grant_helpers.go | 64 +------------------ .../grant_privileges_to_account_role.go | 8 +-- .../grant_privileges_to_database_role.go | 9 +-- pkg/resources/grant_privileges_to_role.go | 12 ++-- pkg/sdk/grants_validations.go | 34 ++++++++++ 8 files changed, 59 insertions(+), 86 deletions(-) diff --git a/docs/resources/grant_privileges_to_account_role.md b/docs/resources/grant_privileges_to_account_role.md index 5577dcfb87..75805e3ad3 100644 --- a/docs/resources/grant_privileges_to_account_role.md +++ b/docs/resources/grant_privileges_to_account_role.md @@ -302,14 +302,14 @@ Optional: - `all` (Block List, Max: 1) Configures the privilege to be granted on all objects in either a database or schema. (see [below for nested schema](#nestedblock--on_schema_object--all)) - `future` (Block List, Max: 1) Configures the privilege to be granted on all objects in either a database or schema. (see [below for nested schema](#nestedblock--on_schema_object--future)) - `object_name` (String) The fully qualified name of the object on which privileges will be granted. -- `object_type` (String) The object type of the schema object on which privileges will be granted. Valid values are: ALERT | DYNAMIC TABLE | EVENT TABLE | FILE FORMAT | FUNCTION | PROCEDURE | SECRET | SEQUENCE | PIPE | MASKING POLICY | PASSWORD POLICY | ROW ACCESS POLICY | SESSION POLICY | TAG | STAGE | STREAM | TABLE | EXTERNAL TABLE | TASK | VIEW | MATERIALIZED VIEW | NETWORK RULE | PACKAGES POLICY | ICEBERG TABLE +- `object_type` (String) The object type of the schema object on which privileges will be granted. Valid values are: ALERT | DYNAMIC TABLE | EVENT TABLE | FILE FORMAT | FUNCTION | PROCEDURE | SECRET | SEQUENCE | PIPE | MASKING POLICY | PASSWORD POLICY | ROW ACCESS POLICY | SESSION POLICY | TAG | STAGE | STREAM | TABLE | EXTERNAL TABLE | TASK | VIEW | MATERIALIZED VIEW | NETWORK RULE | PACKAGES POLICY | STREAMLIT | ICEBERG TABLE ### Nested Schema for `on_schema_object.all` Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | ICEBERG TABLES +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES Optional: @@ -322,7 +322,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | ICEBERG TABLES +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES Optional: diff --git a/docs/resources/grant_privileges_to_database_role.md b/docs/resources/grant_privileges_to_database_role.md index e853927cc6..94627d9e51 100644 --- a/docs/resources/grant_privileges_to_database_role.md +++ b/docs/resources/grant_privileges_to_database_role.md @@ -206,14 +206,14 @@ Optional: - `all` (Block List, Max: 1) Configures the privilege to be granted on all objects in either a database or schema. (see [below for nested schema](#nestedblock--on_schema_object--all)) - `future` (Block List, Max: 1) Configures the privilege to be granted on future objects in either a database or schema. (see [below for nested schema](#nestedblock--on_schema_object--future)) - `object_name` (String) The fully qualified name of the object on which privileges will be granted. -- `object_type` (String) The object type of the schema object on which privileges will be granted. Valid values are: ALERT | DYNAMIC TABLE | EVENT TABLE | FILE FORMAT | FUNCTION | PROCEDURE | SECRET | SEQUENCE | PIPE | MASKING POLICY | PASSWORD POLICY | ROW ACCESS POLICY | SESSION POLICY | TAG | STAGE | STREAM | TABLE | EXTERNAL TABLE | TASK | VIEW | MATERIALIZED VIEW | NETWORK RULE | PACKAGES POLICY | ICEBERG TABLE +- `object_type` (String) The object type of the schema object on which privileges will be granted. Valid values are: ALERT | DYNAMIC TABLE | EVENT TABLE | FILE FORMAT | FUNCTION | PROCEDURE | SECRET | SEQUENCE | PIPE | MASKING POLICY | PASSWORD POLICY | ROW ACCESS POLICY | SESSION POLICY | TAG | STAGE | STREAM | TABLE | EXTERNAL TABLE | TASK | VIEW | MATERIALIZED VIEW | NETWORK RULE | PACKAGES POLICY | STREAMLIT | ICEBERG TABLE ### Nested Schema for `on_schema_object.all` Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | ICEBERG TABLES +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES Optional: @@ -226,7 +226,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | ICEBERG TABLES +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES Optional: diff --git a/docs/resources/grant_privileges_to_role.md b/docs/resources/grant_privileges_to_role.md index f6983d3de4..416a4adc6c 100644 --- a/docs/resources/grant_privileges_to_role.md +++ b/docs/resources/grant_privileges_to_role.md @@ -219,14 +219,14 @@ Optional: - `all` (Block List, Max: 1) Configures the privilege to be granted on all objects in eihter a database or schema. (see [below for nested schema](#nestedblock--on_schema_object--all)) - `future` (Block List, Max: 1) Configures the privilege to be granted on future objects in eihter a database or schema. (see [below for nested schema](#nestedblock--on_schema_object--future)) - `object_name` (String) The fully qualified name of the object on which privileges will be granted. -- `object_type` (String) The object type of the schema object on which privileges will be granted. Valid values are: ALERT | DYNAMIC TABLE | EVENT TABLE | FILE FORMAT | FUNCTION | ICEBERG TABLE | PROCEDURE | SECRET | SEQUENCE | PIPE | MASKING POLICY | PASSWORD POLICY | ROW ACCESS POLICY | SESSION POLICY | TAG | STAGE | STREAM | TABLE | EXTERNAL TABLE | TASK | VIEW | MATERIALIZED VIEW +- `object_type` (String) The object type of the schema object on which privileges will be granted. Valid values are: ALERT | DYNAMIC TABLE | EVENT TABLE | FILE FORMAT | FUNCTION | PROCEDURE | SECRET | SEQUENCE | PIPE | MASKING POLICY | PASSWORD POLICY | ROW ACCESS POLICY | SESSION POLICY | TAG | STAGE | STREAM | TABLE | EXTERNAL TABLE | TASK | VIEW | MATERIALIZED VIEW | NETWORK RULE | PACKAGES POLICY | STREAMLIT | ICEBERG TABLE ### Nested Schema for `on_schema_object.all` Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | ICEBERG TABLES | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES Optional: @@ -239,7 +239,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | ICEBERG TABLES | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES Optional: diff --git a/pkg/resources/grant_helpers.go b/pkg/resources/grant_helpers.go index d4d6afeaa5..6217041957 100644 --- a/pkg/resources/grant_helpers.go +++ b/pkg/resources/grant_helpers.go @@ -7,12 +7,9 @@ import ( "time" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" - - "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/Snowflake-Labs/terraform-provider-snowflake/pkg/snowflake" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/jmoiron/sqlx" "github.com/snowflakedb/gosnowflake" @@ -411,62 +408,3 @@ func isNotOwnershipGrant() func(value any, path cty.Path) diag.Diagnostics { return diags } } - -func ValidGrantedObjectType() schema.SchemaValidateDiagFunc { - return StringInSlice([]string{ - sdk.ObjectTypeAlert.String(), - sdk.ObjectTypeDynamicTable.String(), - sdk.ObjectTypeEventTable.String(), - sdk.ObjectTypeFileFormat.String(), - sdk.ObjectTypeFunction.String(), - sdk.ObjectTypeProcedure.String(), - sdk.ObjectTypeSecret.String(), - sdk.ObjectTypeSequence.String(), - sdk.ObjectTypePipe.String(), - sdk.ObjectTypeMaskingPolicy.String(), - sdk.ObjectTypePasswordPolicy.String(), - sdk.ObjectTypeRowAccessPolicy.String(), - sdk.ObjectTypeSessionPolicy.String(), - sdk.ObjectTypeTag.String(), - sdk.ObjectTypeStage.String(), - sdk.ObjectTypeStream.String(), - sdk.ObjectTypeTable.String(), - sdk.ObjectTypeExternalTable.String(), - sdk.ObjectTypeTask.String(), - sdk.ObjectTypeView.String(), - sdk.ObjectTypeMaterializedView.String(), - sdk.ObjectTypeNetworkRule.String(), - sdk.ObjectTypePackagesPolicy.String(), - sdk.ObjectTypeIcebergTable.String(), - }, true) -} - -func ValidGrantedPluralObjectType() schema.SchemaValidateDiagFunc { - return StringInSlice( - []string{ - sdk.PluralObjectTypeAlerts.String(), - sdk.PluralObjectTypeDynamicTables.String(), - sdk.PluralObjectTypeEventTables.String(), - sdk.PluralObjectTypeFileFormats.String(), - sdk.PluralObjectTypeFunctions.String(), - sdk.PluralObjectTypeProcedures.String(), - sdk.PluralObjectTypeSecrets.String(), - sdk.PluralObjectTypeSequences.String(), - sdk.PluralObjectTypePipes.String(), - sdk.PluralObjectTypeMaskingPolicies.String(), - sdk.PluralObjectTypePasswordPolicies.String(), - sdk.PluralObjectTypeRowAccessPolicies.String(), - sdk.PluralObjectTypeSessionPolicies.String(), - sdk.PluralObjectTypeTags.String(), - sdk.PluralObjectTypeStages.String(), - sdk.PluralObjectTypeStreams.String(), - sdk.PluralObjectTypeTables.String(), - sdk.PluralObjectTypeExternalTables.String(), - sdk.PluralObjectTypeTasks.String(), - sdk.PluralObjectTypeViews.String(), - sdk.PluralObjectTypeMaterializedViews.String(), - sdk.PluralObjectTypeNetworkRules.String(), - sdk.PluralObjectTypePackagesPolicies.String(), - sdk.PluralObjectTypeIcebergTables.String(), - }, true) -} diff --git a/pkg/resources/grant_privileges_to_account_role.go b/pkg/resources/grant_privileges_to_account_role.go index 6095a5fb21..ee9a9736cc 100644 --- a/pkg/resources/grant_privileges_to_account_role.go +++ b/pkg/resources/grant_privileges_to_account_role.go @@ -196,7 +196,7 @@ var grantPrivilegesToAccountRoleSchema = map[string]*schema.Schema{ Type: schema.TypeString, Optional: true, ForceNew: true, - Description: "The object type of the schema object on which privileges will be granted. Valid values are: ALERT | DYNAMIC TABLE | EVENT TABLE | FILE FORMAT | FUNCTION | PROCEDURE | SECRET | SEQUENCE | PIPE | MASKING POLICY | PASSWORD POLICY | ROW ACCESS POLICY | SESSION POLICY | TAG | STAGE | STREAM | TABLE | EXTERNAL TABLE | TASK | VIEW | MATERIALIZED VIEW | NETWORK RULE | PACKAGES POLICY | ICEBERG TABLE", + Description: fmt.Sprintf("The object type of the schema object on which privileges will be granted. Valid values are: %s", strings.Join(sdk.ValidGrantToObjectTypesString, " | ")), RequiredWith: []string{ "on_schema_object.0.object_name", }, @@ -204,7 +204,7 @@ var grantPrivilegesToAccountRoleSchema = map[string]*schema.Schema{ "on_schema_object.0.all", "on_schema_object.0.future", }, - ValidateDiagFunc: ValidGrantedObjectType(), + ValidateDiagFunc: StringInSlice(sdk.ValidGrantToObjectTypesString, true), }, "object_name": { Type: schema.TypeString, @@ -267,8 +267,8 @@ var grantPrivilegesOnAccountRoleBulkOperationSchema = map[string]*schema.Schema{ Type: schema.TypeString, Required: true, ForceNew: true, - Description: "The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | ICEBERG TABLES", - ValidateDiagFunc: ValidGrantedPluralObjectType(), + Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values are: %s", strings.Join(sdk.ValidGrantToPluralObjectTypesString, " | ")), + ValidateDiagFunc: StringInSlice(sdk.ValidGrantToPluralObjectTypesString, true), }, "in_database": { Type: schema.TypeString, diff --git a/pkg/resources/grant_privileges_to_database_role.go b/pkg/resources/grant_privileges_to_database_role.go index 6dc873d323..9112759f32 100644 --- a/pkg/resources/grant_privileges_to_database_role.go +++ b/pkg/resources/grant_privileges_to_database_role.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "slices" + "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" @@ -147,7 +148,7 @@ var grantPrivilegesToDatabaseRoleSchema = map[string]*schema.Schema{ Type: schema.TypeString, Optional: true, ForceNew: true, - Description: "The object type of the schema object on which privileges will be granted. Valid values are: ALERT | DYNAMIC TABLE | EVENT TABLE | FILE FORMAT | FUNCTION | PROCEDURE | SECRET | SEQUENCE | PIPE | MASKING POLICY | PASSWORD POLICY | ROW ACCESS POLICY | SESSION POLICY | TAG | STAGE | STREAM | TABLE | EXTERNAL TABLE | TASK | VIEW | MATERIALIZED VIEW | NETWORK RULE | PACKAGES POLICY | ICEBERG TABLE", + Description: fmt.Sprintf("The object type of the schema object on which privileges will be granted. Valid values are: %s", strings.Join(sdk.ValidGrantToObjectTypesString, " | ")), RequiredWith: []string{ "on_schema_object.0.object_name", }, @@ -155,7 +156,7 @@ var grantPrivilegesToDatabaseRoleSchema = map[string]*schema.Schema{ "on_schema_object.0.all", "on_schema_object.0.future", }, - ValidateDiagFunc: ValidGrantedObjectType(), + ValidateDiagFunc: StringInSlice(sdk.ValidGrantToObjectTypesString, true), }, "object_name": { Type: schema.TypeString, @@ -218,8 +219,8 @@ var grantPrivilegesOnDatabaseRoleBulkOperationSchema = map[string]*schema.Schema Type: schema.TypeString, Required: true, ForceNew: true, - Description: "The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | ICEBERG TABLES", - ValidateDiagFunc: ValidGrantedPluralObjectType(), + Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values are: %s", strings.Join(sdk.ValidGrantToPluralObjectTypesString, " | ")), + ValidateDiagFunc: StringInSlice(sdk.ValidGrantToPluralObjectTypesString, true), }, "in_database": { Type: schema.TypeString, diff --git a/pkg/resources/grant_privileges_to_role.go b/pkg/resources/grant_privileges_to_role.go index 109385bb82..0b6d584cd7 100644 --- a/pkg/resources/grant_privileges_to_role.go +++ b/pkg/resources/grant_privileges_to_role.go @@ -130,11 +130,11 @@ var grantPrivilegesToRoleSchema = map[string]*schema.Schema{ "object_type": { Type: schema.TypeString, Optional: true, - Description: "The object type of the schema object on which privileges will be granted. Valid values are: ALERT | DYNAMIC TABLE | EVENT TABLE | FILE FORMAT | FUNCTION | ICEBERG TABLE | PROCEDURE | SECRET | SEQUENCE | PIPE | MASKING POLICY | PASSWORD POLICY | ROW ACCESS POLICY | SESSION POLICY | TAG | STAGE | STREAM | TABLE | EXTERNAL TABLE | TASK | VIEW | MATERIALIZED VIEW", + Description: fmt.Sprintf("The object type of the schema object on which privileges will be granted. Valid values are: %s", strings.Join(sdk.ValidGrantToObjectTypesString, " | ")), RequiredWith: []string{"on_schema_object.0.object_name"}, ConflictsWith: []string{"on_schema_object.0.all", "on_schema_object.0.future"}, ForceNew: true, - ValidateDiagFunc: ValidGrantedObjectType(), + ValidateDiagFunc: StringInSlice(sdk.ValidGrantToObjectTypesString, true), }, "object_name": { Type: schema.TypeString, @@ -156,9 +156,9 @@ var grantPrivilegesToRoleSchema = map[string]*schema.Schema{ "object_type_plural": { Type: schema.TypeString, Required: true, - Description: "The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | ICEBERG TABLES | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS", + Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values are: %s", strings.Join(sdk.ValidGrantToPluralObjectTypesString, " | ")), ForceNew: true, - ValidateDiagFunc: ValidGrantedPluralObjectType(), + ValidateDiagFunc: StringInSlice(sdk.ValidGrantToPluralObjectTypesString, true), }, "in_database": { Type: schema.TypeString, @@ -190,9 +190,9 @@ var grantPrivilegesToRoleSchema = map[string]*schema.Schema{ "object_type_plural": { Type: schema.TypeString, Required: true, - Description: "The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | ICEBERG TABLES | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS", + Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values are: %s", strings.Join(sdk.ValidGrantToPluralObjectTypesString, " | ")), ForceNew: true, - ValidateDiagFunc: ValidGrantedPluralObjectType(), + ValidateDiagFunc: StringInSlice(sdk.ValidGrantToPluralObjectTypesString, true), }, "in_database": { Type: schema.TypeString, diff --git a/pkg/sdk/grants_validations.go b/pkg/sdk/grants_validations.go index 1df10d643e..e284dc9a4a 100644 --- a/pkg/sdk/grants_validations.go +++ b/pkg/sdk/grants_validations.go @@ -61,9 +61,39 @@ var validGrantOwnershipObjectTypes = []ObjectType{ ObjectTypeWarehouse, } +var validGrantToObjectTypes = []ObjectType{ + ObjectTypeAlert, + ObjectTypeDynamicTable, + ObjectTypeEventTable, + ObjectTypeFileFormat, + ObjectTypeFunction, + ObjectTypeProcedure, + ObjectTypeSecret, + ObjectTypeSequence, + ObjectTypePipe, + ObjectTypeMaskingPolicy, + ObjectTypePasswordPolicy, + ObjectTypeRowAccessPolicy, + ObjectTypeSessionPolicy, + ObjectTypeTag, + ObjectTypeStage, + ObjectTypeStream, + ObjectTypeTable, + ObjectTypeExternalTable, + ObjectTypeTask, + ObjectTypeView, + ObjectTypeMaterializedView, + ObjectTypeNetworkRule, + ObjectTypePackagesPolicy, + ObjectTypeStreamlit, + ObjectTypeIcebergTable, +} + var ( ValidGrantOwnershipObjectTypesString = make([]string, len(validGrantOwnershipObjectTypes)) ValidGrantOwnershipPluralObjectTypesString = make([]string, len(validGrantOwnershipObjectTypes)) + ValidGrantToObjectTypesString = make([]string, len(validGrantToObjectTypes)) + ValidGrantToPluralObjectTypesString = make([]string, len(validGrantToObjectTypes)) ) func init() { @@ -71,6 +101,10 @@ func init() { ValidGrantOwnershipObjectTypesString[i] = objectType.String() ValidGrantOwnershipPluralObjectTypesString[i] = objectType.Plural().String() } + for i, objectType := range validGrantToObjectTypes { + ValidGrantToObjectTypesString[i] = objectType.String() + ValidGrantToPluralObjectTypesString[i] = objectType.Plural().String() + } } func (opts *GrantPrivilegesToAccountRoleOptions) validate() error { From a0afe1472b9f80bd7ba02dd5d38fd58d38d054bd Mon Sep 17 00:00:00 2001 From: Artur Sawicki Date: Wed, 27 Mar 2024 15:38:20 +0100 Subject: [PATCH 3/7] Prove STREAMLIT privileges grants References: #2656 --- ...vileges_to_account_role_acceptance_test.go | 86 ++++++++++++++++++- .../OnSchemaObject_OnAll_InDatabase/test.tf | 2 +- .../variables.tf | 4 + .../test.tf | 2 +- .../variables.tf | 4 + .../testint/streamlits_integration_test.go | 67 +++++++++++++++ 6 files changed, 159 insertions(+), 6 deletions(-) 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 213f31fb15..95e735d03a 100644 --- a/pkg/resources/grant_privileges_to_account_role_acceptance_test.go +++ b/pkg/resources/grant_privileges_to_account_role_acceptance_test.go @@ -469,8 +469,9 @@ func TestAcc_GrantPrivilegesToAccountRole_OnSchemaObject_OnAll_InDatabase(t *tes config.StringVariable(string(sdk.SchemaObjectPrivilegeInsert)), config.StringVariable(string(sdk.SchemaObjectPrivilegeUpdate)), ), - "database": config.StringVariable(databaseName), - "with_grant_option": config.BoolVariable(false), + "database": config.StringVariable(databaseName), + "object_type_plural": config.StringVariable(sdk.PluralObjectTypeTables.String()), + "with_grant_option": config.BoolVariable(false), } resourceName := "snowflake_grant_privileges_to_account_role.test" @@ -569,8 +570,9 @@ func TestAcc_GrantPrivilegesToAccountRole_OnSchemaObject_OnFuture_InDatabase(t * config.StringVariable(string(sdk.SchemaObjectPrivilegeInsert)), config.StringVariable(string(sdk.SchemaObjectPrivilegeUpdate)), ), - "database": config.StringVariable(databaseName), - "with_grant_option": config.BoolVariable(false), + "database": config.StringVariable(databaseName), + "object_type_plural": config.StringVariable(sdk.PluralObjectTypeTables.String()), + "with_grant_option": config.BoolVariable(false), } resourceName := "snowflake_grant_privileges_to_account_role.test" @@ -610,6 +612,82 @@ func TestAcc_GrantPrivilegesToAccountRole_OnSchemaObject_OnFuture_InDatabase(t * }) } +// TODO [SNOW-1272222]: fix the test when it starts working on Snowflake side +func TestAcc_GrantPrivilegesToAccountRole_OnSchemaObject_OnFuture_Streamlits_InDatabase(t *testing.T) { + name := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)) + roleName := sdk.NewAccountObjectIdentifier(name).FullyQualifiedName() + databaseName := sdk.NewAccountObjectIdentifier(acc.TestDatabaseName).FullyQualifiedName() + configVariables := config.Variables{ + "name": config.StringVariable(roleName), + "privileges": config.ListVariable( + config.StringVariable(string(sdk.SchemaObjectPrivilegeUsage)), + ), + "database": config.StringVariable(databaseName), + "object_type_plural": config.StringVariable(sdk.PluralObjectTypeStreamlits.String()), + "with_grant_option": config.BoolVariable(false), + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: testAccCheckAccountRolePrivilegesRevoked(name), + Steps: []resource.TestStep{ + { + PreConfig: func() { createAccountRoleOutsideTerraform(t, name) }, + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnFuture_InDatabase"), + ConfigVariables: configVariables, + ExpectError: regexp.MustCompile("Unsupported feature 'STREAMLIT'"), + }, + }, + }) +} + +func TestAcc_GrantPrivilegesToAccountRole_OnSchemaObject_OnAll_Streamlits_InDatabase(t *testing.T) { + name := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)) + roleName := sdk.NewAccountObjectIdentifier(name).FullyQualifiedName() + databaseName := sdk.NewAccountObjectIdentifier(acc.TestDatabaseName).FullyQualifiedName() + configVariables := config.Variables{ + "name": config.StringVariable(roleName), + "privileges": config.ListVariable( + config.StringVariable(string(sdk.SchemaObjectPrivilegeUsage)), + ), + "database": config.StringVariable(databaseName), + "object_type_plural": config.StringVariable(sdk.PluralObjectTypeStreamlits.String()), + "with_grant_option": config.BoolVariable(false), + } + resourceName := "snowflake_grant_privileges_to_account_role.test" + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: testAccCheckAccountRolePrivilegesRevoked(name), + Steps: []resource.TestStep{ + { + PreConfig: func() { createAccountRoleOutsideTerraform(t, name) }, + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnAll_InDatabase"), + ConfigVariables: configVariables, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "account_role_name", roleName), + resource.TestCheckResourceAttr(resourceName, "privileges.#", "1"), + resource.TestCheckResourceAttr(resourceName, "privileges.0", string(sdk.SchemaObjectPrivilegeUsage)), + resource.TestCheckResourceAttr(resourceName, "on_schema_object.#", "1"), + resource.TestCheckResourceAttr(resourceName, "on_schema_object.0.all.#", "1"), + resource.TestCheckResourceAttr(resourceName, "on_schema_object.0.all.0.object_type_plural", string(sdk.PluralObjectTypeStreamlits)), + resource.TestCheckResourceAttr(resourceName, "on_schema_object.0.all.0.in_database", databaseName), + resource.TestCheckResourceAttr(resourceName, "with_grant_option", "false"), + resource.TestCheckResourceAttr(resourceName, "id", fmt.Sprintf("%s|false|false|USAGE|OnSchemaObject|OnAll|STREAMLITS|InDatabase|%s", roleName, databaseName)), + ), + }, + }, + }) +} + func TestAcc_GrantPrivilegesToAccountRole_UpdatePrivileges(t *testing.T) { name := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)) roleName := sdk.NewAccountObjectIdentifier(name).FullyQualifiedName() diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnAll_InDatabase/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnAll_InDatabase/test.tf index 7fa86e21f7..b787a89214 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnAll_InDatabase/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnAll_InDatabase/test.tf @@ -5,7 +5,7 @@ resource "snowflake_grant_privileges_to_account_role" "test" { on_schema_object { all { - object_type_plural = "TABLES" + object_type_plural = var.object_type_plural in_database = var.database } } diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnAll_InDatabase/variables.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnAll_InDatabase/variables.tf index 0e22e903d7..fde4549568 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnAll_InDatabase/variables.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnAll_InDatabase/variables.tf @@ -10,6 +10,10 @@ variable "database" { type = string } +variable "object_type_plural" { + type = string +} + variable "with_grant_option" { type = bool } diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnFuture_InDatabase/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnFuture_InDatabase/test.tf index ed7804ce4b..4da613126e 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnFuture_InDatabase/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnFuture_InDatabase/test.tf @@ -5,7 +5,7 @@ resource "snowflake_grant_privileges_to_account_role" "test" { on_schema_object { future { - object_type_plural = "TABLES" + object_type_plural = var.object_type_plural in_database = var.database } } diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnFuture_InDatabase/variables.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnFuture_InDatabase/variables.tf index 0e22e903d7..fde4549568 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnFuture_InDatabase/variables.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/OnSchemaObject_OnFuture_InDatabase/variables.tf @@ -10,6 +10,10 @@ variable "database" { type = string } +variable "object_type_plural" { + type = string +} + variable "with_grant_option" { type = bool } diff --git a/pkg/sdk/testint/streamlits_integration_test.go b/pkg/sdk/testint/streamlits_integration_test.go index 1680389baa..c30c73aceb 100644 --- a/pkg/sdk/testint/streamlits_integration_test.go +++ b/pkg/sdk/testint/streamlits_integration_test.go @@ -6,6 +6,7 @@ import ( "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/internal/collections" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/internal/random" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -69,6 +70,72 @@ func TestInt_Streamlits(t *testing.T) { assertStreamlit(t, id, comment, "") }) + // TODO [SNOW-1272222]: fix the test when it starts working on Snowflake side + t.Run("grant privilege to streamlits", func(t *testing.T) { + stage, cleanupStage := createStage(t, client, sdk.NewSchemaObjectIdentifier(TestDatabaseName, TestSchemaName, random.AlphaN(4))) + t.Cleanup(cleanupStage) + + role, roleCleanup := createRole(t, client) + t.Cleanup(roleCleanup) + + comment := random.StringN(4) + id := sdk.NewSchemaObjectIdentifier(databaseTest.Name, schemaTest.Name, random.StringN(4)) + mainFile := "manifest.yml" + request := sdk.NewCreateStreamlitRequest(id, stage.Location(), mainFile).WithComment(&comment) + err := client.Streamlits.Create(ctx, request) + require.NoError(t, err) + t.Cleanup(cleanupStreamlitHandle(id)) + + assertStreamlit(t, id, comment, "") + + privileges := &sdk.AccountRoleGrantPrivileges{ + SchemaObjectPrivileges: []sdk.SchemaObjectPrivilege{sdk.SchemaObjectPrivilegeUsage}, + } + on := &sdk.AccountRoleGrantOn{ + SchemaObject: &sdk.GrantOnSchemaObject{ + SchemaObject: &sdk.Object{ + ObjectType: sdk.ObjectTypeStreamlit, + Name: id, + }, + }, + } + err = client.Grants.GrantPrivilegesToAccountRole(ctx, privileges, on, role.ID(), nil) + require.NoError(t, err) + + grants, err := client.Grants.Show(ctx, &sdk.ShowGrantOptions{ + To: &sdk.ShowGrantsTo{ + Role: role.ID(), + }, + }) + require.NoError(t, err) + assert.Equal(t, 1, len(grants)) + assert.Equal(t, sdk.SchemaObjectPrivilegeUsage.String(), grants[0].Privilege) + assert.Equal(t, id.FullyQualifiedName(), grants[0].Name.FullyQualifiedName()) + + on = &sdk.AccountRoleGrantOn{ + SchemaObject: &sdk.GrantOnSchemaObject{ + Future: &sdk.GrantOnSchemaObjectIn{ + PluralObjectType: sdk.PluralObjectTypeStreamlits, + InDatabase: sdk.Pointer(sdk.NewAccountObjectIdentifier(TestDatabaseName)), + }, + }, + } + err = client.Grants.GrantPrivilegesToAccountRole(ctx, privileges, on, role.ID(), nil) + require.Error(t, err) + require.ErrorContains(t, err, "Unsupported feature 'STREAMLIT'") + + on = &sdk.AccountRoleGrantOn{ + SchemaObject: &sdk.GrantOnSchemaObject{ + All: &sdk.GrantOnSchemaObjectIn{ + PluralObjectType: sdk.PluralObjectTypeStreamlits, + InDatabase: sdk.Pointer(sdk.NewAccountObjectIdentifier(TestDatabaseName)), + }, + }, + } + err = client.Grants.GrantPrivilegesToAccountRole(ctx, privileges, on, role.ID(), nil) + require.NoError(t, err) + }) + t.Run("alter streamlit: set", func(t *testing.T) { stage, cleanupStage := createStage(t, client, sdk.NewSchemaObjectIdentifier(TestDatabaseName, TestSchemaName, random.AlphaN(4))) t.Cleanup(cleanupStage) From a5490408bfcfa1b1b703ee02f083e8391f39b0c1 Mon Sep 17 00:00:00 2001 From: Artur Sawicki Date: Wed, 27 Mar 2024 15:50:08 +0100 Subject: [PATCH 4/7] Update the docs --- docs/resources/grant_privileges_to_account_role.md | 4 ++-- docs/resources/grant_privileges_to_database_role.md | 4 ++-- docs/resources/grant_privileges_to_role.md | 2 +- pkg/resources/grant_privileges_to_account_role.go | 2 +- pkg/resources/grant_privileges_to_database_role.go | 2 +- pkg/resources/grant_privileges_to_role.go | 4 ++-- pkg/sdk/grants_validations.go | 8 ++++++++ 7 files changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/resources/grant_privileges_to_account_role.md b/docs/resources/grant_privileges_to_account_role.md index 75805e3ad3..8a4152723c 100644 --- a/docs/resources/grant_privileges_to_account_role.md +++ b/docs/resources/grant_privileges_to_account_role.md @@ -309,7 +309,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES. For FUTURE all values but STREAMLITS are supported. Optional: @@ -322,7 +322,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES. For FUTURE all values but STREAMLITS are supported. Optional: diff --git a/docs/resources/grant_privileges_to_database_role.md b/docs/resources/grant_privileges_to_database_role.md index 94627d9e51..693d176ac5 100644 --- a/docs/resources/grant_privileges_to_database_role.md +++ b/docs/resources/grant_privileges_to_database_role.md @@ -213,7 +213,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES. For FUTURE all values but STREAMLITS are supported. Optional: @@ -226,7 +226,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES. For FUTURE all values but STREAMLITS are supported. Optional: diff --git a/docs/resources/grant_privileges_to_role.md b/docs/resources/grant_privileges_to_role.md index 416a4adc6c..2275a332cc 100644 --- a/docs/resources/grant_privileges_to_role.md +++ b/docs/resources/grant_privileges_to_role.md @@ -239,7 +239,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | ICEBERG TABLES Optional: diff --git a/pkg/resources/grant_privileges_to_account_role.go b/pkg/resources/grant_privileges_to_account_role.go index ee9a9736cc..606bcfa6a4 100644 --- a/pkg/resources/grant_privileges_to_account_role.go +++ b/pkg/resources/grant_privileges_to_account_role.go @@ -267,7 +267,7 @@ var grantPrivilegesOnAccountRoleBulkOperationSchema = map[string]*schema.Schema{ Type: schema.TypeString, Required: true, ForceNew: true, - Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values are: %s", strings.Join(sdk.ValidGrantToPluralObjectTypesString, " | ")), + Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: %s. For FUTURE all values but %s are supported.", strings.Join(sdk.ValidGrantToPluralObjectTypesString, " | "), sdk.PluralObjectTypeStreamlits.String()), ValidateDiagFunc: StringInSlice(sdk.ValidGrantToPluralObjectTypesString, true), }, "in_database": { diff --git a/pkg/resources/grant_privileges_to_database_role.go b/pkg/resources/grant_privileges_to_database_role.go index 9112759f32..d7857c752c 100644 --- a/pkg/resources/grant_privileges_to_database_role.go +++ b/pkg/resources/grant_privileges_to_database_role.go @@ -219,7 +219,7 @@ var grantPrivilegesOnDatabaseRoleBulkOperationSchema = map[string]*schema.Schema Type: schema.TypeString, Required: true, ForceNew: true, - Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values are: %s", strings.Join(sdk.ValidGrantToPluralObjectTypesString, " | ")), + Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: %s. For FUTURE all values but %s are supported.", strings.Join(sdk.ValidGrantToPluralObjectTypesString, " | "), sdk.PluralObjectTypeStreamlits.String()), ValidateDiagFunc: StringInSlice(sdk.ValidGrantToPluralObjectTypesString, true), }, "in_database": { diff --git a/pkg/resources/grant_privileges_to_role.go b/pkg/resources/grant_privileges_to_role.go index 0b6d584cd7..c54ed16fe3 100644 --- a/pkg/resources/grant_privileges_to_role.go +++ b/pkg/resources/grant_privileges_to_role.go @@ -190,9 +190,9 @@ var grantPrivilegesToRoleSchema = map[string]*schema.Schema{ "object_type_plural": { Type: schema.TypeString, Required: true, - Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values are: %s", strings.Join(sdk.ValidGrantToPluralObjectTypesString, " | ")), + Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values are: %s", strings.Join(sdk.ValidGrantToFuturePluralObjectTypesString, " | ")), ForceNew: true, - ValidateDiagFunc: StringInSlice(sdk.ValidGrantToPluralObjectTypesString, true), + ValidateDiagFunc: StringInSlice(sdk.ValidGrantToFuturePluralObjectTypesString, true), }, "in_database": { Type: schema.TypeString, diff --git a/pkg/sdk/grants_validations.go b/pkg/sdk/grants_validations.go index e284dc9a4a..7b9e92f7c7 100644 --- a/pkg/sdk/grants_validations.go +++ b/pkg/sdk/grants_validations.go @@ -89,11 +89,16 @@ var validGrantToObjectTypes = []ObjectType{ ObjectTypeIcebergTable, } +var invalidGrantToFutureObjectTypes = []ObjectType{ + ObjectTypeStreamlit, +} + var ( ValidGrantOwnershipObjectTypesString = make([]string, len(validGrantOwnershipObjectTypes)) ValidGrantOwnershipPluralObjectTypesString = make([]string, len(validGrantOwnershipObjectTypes)) ValidGrantToObjectTypesString = make([]string, len(validGrantToObjectTypes)) ValidGrantToPluralObjectTypesString = make([]string, len(validGrantToObjectTypes)) + ValidGrantToFuturePluralObjectTypesString = make([]string, 0) ) func init() { @@ -104,6 +109,9 @@ func init() { for i, objectType := range validGrantToObjectTypes { ValidGrantToObjectTypesString[i] = objectType.String() ValidGrantToPluralObjectTypesString[i] = objectType.Plural().String() + if !slices.Contains(invalidGrantToFutureObjectTypes, objectType) { + ValidGrantToFuturePluralObjectTypesString = append(ValidGrantToFuturePluralObjectTypesString, objectType.Plural().String()) + } } } From ee4cd80ce924e54b3992019f164a2b907d1cb469 Mon Sep 17 00:00:00 2001 From: Artur Sawicki Date: Wed, 27 Mar 2024 16:00:06 +0100 Subject: [PATCH 5/7] Split the bulk schemas for all and future --- .../grant_privileges_to_account_role.md | 4 +- .../grant_privileges_to_database_role.md | 4 +- .../grant_privileges_to_account_role.go | 46 +++++++++-------- ...vileges_to_account_role_acceptance_test.go | 1 + .../grant_privileges_to_database_role.go | 50 ++++++++++--------- 5 files changed, 55 insertions(+), 50 deletions(-) diff --git a/docs/resources/grant_privileges_to_account_role.md b/docs/resources/grant_privileges_to_account_role.md index 8a4152723c..4a9ba582be 100644 --- a/docs/resources/grant_privileges_to_account_role.md +++ b/docs/resources/grant_privileges_to_account_role.md @@ -309,7 +309,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES. For FUTURE all values but STREAMLITS are supported. +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES. Optional: @@ -322,7 +322,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES. For FUTURE all values but STREAMLITS are supported. +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | ICEBERG TABLES. Optional: diff --git a/docs/resources/grant_privileges_to_database_role.md b/docs/resources/grant_privileges_to_database_role.md index 693d176ac5..b3e8b16564 100644 --- a/docs/resources/grant_privileges_to_database_role.md +++ b/docs/resources/grant_privileges_to_database_role.md @@ -213,7 +213,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES. For FUTURE all values but STREAMLITS are supported. +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES. Optional: @@ -226,7 +226,7 @@ Optional: Required: -- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | STREAMLITS | ICEBERG TABLES. For FUTURE all values but STREAMLITS are supported. +- `object_type_plural` (String) The plural object type of the schema object on which privileges will be granted. Valid values are: ALERTS | DYNAMIC TABLES | EVENT TABLES | FILE FORMATS | FUNCTIONS | PROCEDURES | SECRETS | SEQUENCES | PIPES | MASKING POLICIES | PASSWORD POLICIES | ROW ACCESS POLICIES | SESSION POLICIES | TAGS | STAGES | STREAMS | TABLES | EXTERNAL TABLES | TASKS | VIEWS | MATERIALIZED VIEWS | NETWORK RULES | PACKAGES POLICIES | ICEBERG TABLES. Optional: diff --git a/pkg/resources/grant_privileges_to_account_role.go b/pkg/resources/grant_privileges_to_account_role.go index 606bcfa6a4..16c5633e71 100644 --- a/pkg/resources/grant_privileges_to_account_role.go +++ b/pkg/resources/grant_privileges_to_account_role.go @@ -228,7 +228,7 @@ var grantPrivilegesToAccountRoleSchema = map[string]*schema.Schema{ Description: "Configures the privilege to be granted on all objects in either a database or schema.", MaxItems: 1, Elem: &schema.Resource{ - Schema: grantPrivilegesOnAccountRoleBulkOperationSchema, + Schema: getGrantPrivilegesOnAccountRoleBulkOperationSchema(sdk.ValidGrantToPluralObjectTypesString), }, ConflictsWith: []string{ "on_schema_object.0.object_type", @@ -246,7 +246,7 @@ var grantPrivilegesToAccountRoleSchema = map[string]*schema.Schema{ Description: "Configures the privilege to be granted on all objects in either a database or schema.", MaxItems: 1, Elem: &schema.Resource{ - Schema: grantPrivilegesOnAccountRoleBulkOperationSchema, + Schema: getGrantPrivilegesOnAccountRoleBulkOperationSchema(sdk.ValidGrantToFuturePluralObjectTypesString), }, ConflictsWith: []string{ "on_schema_object.0.object_type", @@ -262,26 +262,28 @@ var grantPrivilegesToAccountRoleSchema = map[string]*schema.Schema{ }, } -var grantPrivilegesOnAccountRoleBulkOperationSchema = map[string]*schema.Schema{ - "object_type_plural": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: %s. For FUTURE all values but %s are supported.", strings.Join(sdk.ValidGrantToPluralObjectTypesString, " | "), sdk.PluralObjectTypeStreamlits.String()), - ValidateDiagFunc: StringInSlice(sdk.ValidGrantToPluralObjectTypesString, true), - }, - "in_database": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateDiagFunc: IsValidIdentifier[sdk.AccountObjectIdentifier](), - }, - "in_schema": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateDiagFunc: IsValidIdentifier[sdk.DatabaseObjectIdentifier](), - }, +func getGrantPrivilegesOnAccountRoleBulkOperationSchema(validGrantToObjectTypes []string) map[string]*schema.Schema { + return map[string]*schema.Schema{ + "object_type_plural": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values are: %s.", strings.Join(validGrantToObjectTypes, " | ")), + ValidateDiagFunc: StringInSlice(validGrantToObjectTypes, true), + }, + "in_database": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateDiagFunc: IsValidIdentifier[sdk.AccountObjectIdentifier](), + }, + "in_schema": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateDiagFunc: IsValidIdentifier[sdk.DatabaseObjectIdentifier](), + }, + } } func GrantPrivilegesToAccountRole() *schema.Resource { 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 95e735d03a..61efcbc081 100644 --- a/pkg/resources/grant_privileges_to_account_role_acceptance_test.go +++ b/pkg/resources/grant_privileges_to_account_role_acceptance_test.go @@ -614,6 +614,7 @@ func TestAcc_GrantPrivilegesToAccountRole_OnSchemaObject_OnFuture_InDatabase(t * // TODO [SNOW-1272222]: fix the test when it starts working on Snowflake side func TestAcc_GrantPrivilegesToAccountRole_OnSchemaObject_OnFuture_Streamlits_InDatabase(t *testing.T) { + t.Skip("Fix after it starts working on Snowflake side, reference: SNOW-1272222") name := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)) roleName := sdk.NewAccountObjectIdentifier(name).FullyQualifiedName() databaseName := sdk.NewAccountObjectIdentifier(acc.TestDatabaseName).FullyQualifiedName() diff --git a/pkg/resources/grant_privileges_to_database_role.go b/pkg/resources/grant_privileges_to_database_role.go index d7857c752c..972dea9d51 100644 --- a/pkg/resources/grant_privileges_to_database_role.go +++ b/pkg/resources/grant_privileges_to_database_role.go @@ -180,7 +180,7 @@ var grantPrivilegesToDatabaseRoleSchema = map[string]*schema.Schema{ Description: "Configures the privilege to be granted on all objects in either a database or schema.", MaxItems: 1, Elem: &schema.Resource{ - Schema: grantPrivilegesOnDatabaseRoleBulkOperationSchema, + Schema: getGrantPrivilegesOnDatabaseRoleBulkOperationSchema(sdk.ValidGrantToPluralObjectTypesString), }, ConflictsWith: []string{ "on_schema_object.0.object_type", @@ -198,7 +198,7 @@ var grantPrivilegesToDatabaseRoleSchema = map[string]*schema.Schema{ Description: "Configures the privilege to be granted on future objects in either a database or schema.", MaxItems: 1, Elem: &schema.Resource{ - Schema: grantPrivilegesOnDatabaseRoleBulkOperationSchema, + Schema: getGrantPrivilegesOnDatabaseRoleBulkOperationSchema(sdk.ValidGrantToFuturePluralObjectTypesString), }, ConflictsWith: []string{ "on_schema_object.0.object_type", @@ -214,28 +214,30 @@ var grantPrivilegesToDatabaseRoleSchema = map[string]*schema.Schema{ }, } -var grantPrivilegesOnDatabaseRoleBulkOperationSchema = map[string]*schema.Schema{ - "object_type_plural": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values for ALL are: %s. For FUTURE all values but %s are supported.", strings.Join(sdk.ValidGrantToPluralObjectTypesString, " | "), sdk.PluralObjectTypeStreamlits.String()), - ValidateDiagFunc: StringInSlice(sdk.ValidGrantToPluralObjectTypesString, true), - }, - "in_database": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: "The fully qualified name of the database.", - ValidateDiagFunc: IsValidIdentifier[sdk.AccountObjectIdentifier](), - }, - "in_schema": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: "The fully qualified name of the schema.", - ValidateDiagFunc: IsValidIdentifier[sdk.DatabaseObjectIdentifier](), - }, +func getGrantPrivilegesOnDatabaseRoleBulkOperationSchema(validGrantToObjectTypes []string) map[string]*schema.Schema { + return map[string]*schema.Schema{ + "object_type_plural": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values are: %s.", strings.Join(validGrantToObjectTypes, " | ")), + ValidateDiagFunc: StringInSlice(sdk.ValidGrantToPluralObjectTypesString, true), + }, + "in_database": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The fully qualified name of the database.", + ValidateDiagFunc: IsValidIdentifier[sdk.AccountObjectIdentifier](), + }, + "in_schema": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The fully qualified name of the schema.", + ValidateDiagFunc: IsValidIdentifier[sdk.DatabaseObjectIdentifier](), + }, + } } func GrantPrivilegesToDatabaseRole() *schema.Resource { From 0907ba085f9a3323f6961aa5487ac03258321cfb Mon Sep 17 00:00:00 2001 From: Artur Sawicki Date: Wed, 27 Mar 2024 16:30:10 +0100 Subject: [PATCH 6/7] Add tests to database roles too --- .../grant_privileges_to_database_role.go | 2 +- ...ileges_to_database_role_acceptance_test.go | 86 ++++++++++++++++++- .../OnSchemaObject_OnAll_InDatabase/test.tf | 2 +- .../variables.tf | 4 + .../test.tf | 2 +- .../variables.tf | 4 + .../testint/streamlits_integration_test.go | 69 ++++++++++++++- 7 files changed, 161 insertions(+), 8 deletions(-) diff --git a/pkg/resources/grant_privileges_to_database_role.go b/pkg/resources/grant_privileges_to_database_role.go index 972dea9d51..9834ca7fc0 100644 --- a/pkg/resources/grant_privileges_to_database_role.go +++ b/pkg/resources/grant_privileges_to_database_role.go @@ -221,7 +221,7 @@ func getGrantPrivilegesOnDatabaseRoleBulkOperationSchema(validGrantToObjectTypes Required: true, ForceNew: true, Description: fmt.Sprintf("The plural object type of the schema object on which privileges will be granted. Valid values are: %s.", strings.Join(validGrantToObjectTypes, " | ")), - ValidateDiagFunc: StringInSlice(sdk.ValidGrantToPluralObjectTypesString, true), + ValidateDiagFunc: StringInSlice(validGrantToObjectTypes, true), }, "in_database": { Type: schema.TypeString, 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 f3c9497428..96bc7503a9 100644 --- a/pkg/resources/grant_privileges_to_database_role_acceptance_test.go +++ b/pkg/resources/grant_privileges_to_database_role_acceptance_test.go @@ -385,8 +385,9 @@ func TestAcc_GrantPrivilegesToDatabaseRole_OnSchemaObject_OnAll_InDatabase(t *te config.StringVariable(string(sdk.SchemaObjectPrivilegeInsert)), config.StringVariable(string(sdk.SchemaObjectPrivilegeUpdate)), ), - "database": config.StringVariable(acc.TestDatabaseName), - "with_grant_option": config.BoolVariable(false), + "database": config.StringVariable(acc.TestDatabaseName), + "object_type_plural": config.StringVariable(sdk.PluralObjectTypeTables.String()), + "with_grant_option": config.BoolVariable(false), } resourceName := "snowflake_grant_privileges_to_database_role.test" @@ -487,8 +488,9 @@ func TestAcc_GrantPrivilegesToDatabaseRole_OnSchemaObject_OnFuture_InDatabase(t config.StringVariable(string(sdk.SchemaObjectPrivilegeInsert)), config.StringVariable(string(sdk.SchemaObjectPrivilegeUpdate)), ), - "database": config.StringVariable(acc.TestDatabaseName), - "with_grant_option": config.BoolVariable(false), + "database": config.StringVariable(acc.TestDatabaseName), + "object_type_plural": config.StringVariable(sdk.PluralObjectTypeTables.String()), + "with_grant_option": config.BoolVariable(false), } resourceName := "snowflake_grant_privileges_to_database_role.test" @@ -531,6 +533,82 @@ func TestAcc_GrantPrivilegesToDatabaseRole_OnSchemaObject_OnFuture_InDatabase(t }) } +// TODO [SNOW-1272222]: fix the test when it starts working on Snowflake side +func TestAcc_GrantPrivilegesToDatabaseRole_OnSchemaObject_OnFuture_Streamlits_InDatabase(t *testing.T) { + t.Skip("Fix after it starts working on Snowflake side, reference: SNOW-1272222") + name := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)) + configVariables := config.Variables{ + "name": config.StringVariable(name), + "privileges": config.ListVariable( + config.StringVariable(string(sdk.SchemaObjectPrivilegeUsage)), + ), + "database": config.StringVariable(acc.TestDatabaseName), + "object_type_plural": config.StringVariable(sdk.PluralObjectTypeStreamlits.String()), + "with_grant_option": config.BoolVariable(false), + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: testAccCheckDatabaseRolePrivilegesRevoked, + Steps: []resource.TestStep{ + { + PreConfig: func() { createDatabaseRoleOutsideTerraform(t, name) }, + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnFuture_InDatabase"), + ConfigVariables: configVariables, + ExpectError: regexp.MustCompile("Unsupported feature 'STREAMLIT'"), + }, + }, + }) +} + +func TestAcc_GrantPrivilegesToDatabaseRole_OnSchemaObject_OnAll_Streamlits_InDatabase(t *testing.T) { + name := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)) + configVariables := config.Variables{ + "name": config.StringVariable(name), + "privileges": config.ListVariable( + config.StringVariable(string(sdk.SchemaObjectPrivilegeUsage)), + ), + "database": config.StringVariable(acc.TestDatabaseName), + "object_type_plural": config.StringVariable(sdk.PluralObjectTypeStreamlits.String()), + "with_grant_option": config.BoolVariable(false), + } + resourceName := "snowflake_grant_privileges_to_database_role.test" + + databaseRoleName := sdk.NewDatabaseObjectIdentifier(acc.TestDatabaseName, name).FullyQualifiedName() + databaseName := sdk.NewAccountObjectIdentifier(acc.TestDatabaseName).FullyQualifiedName() + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: testAccCheckAccountRolePrivilegesRevoked(name), + Steps: []resource.TestStep{ + { + PreConfig: func() { createDatabaseRoleOutsideTerraform(t, name) }, + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnAll_InDatabase"), + ConfigVariables: configVariables, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "database_role_name", databaseRoleName), + resource.TestCheckResourceAttr(resourceName, "privileges.#", "1"), + resource.TestCheckResourceAttr(resourceName, "privileges.0", string(sdk.SchemaObjectPrivilegeUsage)), + resource.TestCheckResourceAttr(resourceName, "on_schema_object.#", "1"), + resource.TestCheckResourceAttr(resourceName, "on_schema_object.0.all.#", "1"), + resource.TestCheckResourceAttr(resourceName, "on_schema_object.0.all.0.object_type_plural", string(sdk.PluralObjectTypeStreamlits)), + resource.TestCheckResourceAttr(resourceName, "on_schema_object.0.all.0.in_database", databaseName), + resource.TestCheckResourceAttr(resourceName, "with_grant_option", "false"), + resource.TestCheckResourceAttr(resourceName, "id", fmt.Sprintf("%s|false|false|USAGE|OnSchemaObject|OnAll|STREAMLITS|InDatabase|%s", databaseRoleName, databaseName)), + ), + }, + }, + }) +} + func TestAcc_GrantPrivilegesToDatabaseRole_UpdatePrivileges(t *testing.T) { name := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)) configVariables := func(allPrivileges bool, privileges []sdk.AccountObjectPrivilege) config.Variables { diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnAll_InDatabase/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnAll_InDatabase/test.tf index 230a702d23..75e38e11c6 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnAll_InDatabase/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnAll_InDatabase/test.tf @@ -5,7 +5,7 @@ resource "snowflake_grant_privileges_to_database_role" "test" { on_schema_object { all { - object_type_plural = "TABLES" + object_type_plural = var.object_type_plural in_database = "\"${var.database}\"" } } diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnAll_InDatabase/variables.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnAll_InDatabase/variables.tf index 0e22e903d7..fde4549568 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnAll_InDatabase/variables.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnAll_InDatabase/variables.tf @@ -10,6 +10,10 @@ variable "database" { type = string } +variable "object_type_plural" { + type = string +} + variable "with_grant_option" { type = bool } diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnFuture_InDatabase/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnFuture_InDatabase/test.tf index 3463a24a8f..42b8c2a0b1 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnFuture_InDatabase/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnFuture_InDatabase/test.tf @@ -5,7 +5,7 @@ resource "snowflake_grant_privileges_to_database_role" "test" { on_schema_object { future { - object_type_plural = "TABLES" + object_type_plural = var.object_type_plural in_database = "\"${var.database}\"" } } diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnFuture_InDatabase/variables.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnFuture_InDatabase/variables.tf index 0e22e903d7..fde4549568 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnFuture_InDatabase/variables.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToDatabaseRole/OnSchemaObject_OnFuture_InDatabase/variables.tf @@ -10,6 +10,10 @@ variable "database" { type = string } +variable "object_type_plural" { + type = string +} + variable "with_grant_option" { type = bool } diff --git a/pkg/sdk/testint/streamlits_integration_test.go b/pkg/sdk/testint/streamlits_integration_test.go index c30c73aceb..ace858a844 100644 --- a/pkg/sdk/testint/streamlits_integration_test.go +++ b/pkg/sdk/testint/streamlits_integration_test.go @@ -71,7 +71,7 @@ func TestInt_Streamlits(t *testing.T) { }) // TODO [SNOW-1272222]: fix the test when it starts working on Snowflake side - t.Run("grant privilege to streamlits", func(t *testing.T) { + t.Run("grant privilege to streamlits to role", func(t *testing.T) { stage, cleanupStage := createStage(t, client, sdk.NewSchemaObjectIdentifier(TestDatabaseName, TestSchemaName, random.AlphaN(4))) t.Cleanup(cleanupStage) @@ -136,6 +136,73 @@ func TestInt_Streamlits(t *testing.T) { require.NoError(t, err) }) + // TODO [SNOW-1272222]: fix the test when it starts working on Snowflake side + t.Run("grant privilege to streamlits to database role", func(t *testing.T) { + stage, cleanupStage := createStage(t, client, sdk.NewSchemaObjectIdentifier(TestDatabaseName, TestSchemaName, random.AlphaN(4))) + t.Cleanup(cleanupStage) + + databaseRole, databaseRoleCleanup := createDatabaseRole(t, client, testDb(t)) + t.Cleanup(databaseRoleCleanup) + + databaseRoleId := sdk.NewDatabaseObjectIdentifier(testDb(t).Name, databaseRole.Name) + + comment := random.StringN(4) + id := sdk.NewSchemaObjectIdentifier(databaseTest.Name, schemaTest.Name, random.StringN(4)) + mainFile := "manifest.yml" + request := sdk.NewCreateStreamlitRequest(id, stage.Location(), mainFile).WithComment(&comment) + err := client.Streamlits.Create(ctx, request) + require.NoError(t, err) + t.Cleanup(cleanupStreamlitHandle(id)) + + assertStreamlit(t, id, comment, "") + + privileges := &sdk.DatabaseRoleGrantPrivileges{ + SchemaObjectPrivileges: []sdk.SchemaObjectPrivilege{sdk.SchemaObjectPrivilegeUsage}, + } + on := &sdk.DatabaseRoleGrantOn{ + SchemaObject: &sdk.GrantOnSchemaObject{ + SchemaObject: &sdk.Object{ + ObjectType: sdk.ObjectTypeStreamlit, + Name: id, + }, + }, + } + err = client.Grants.GrantPrivilegesToDatabaseRole(ctx, privileges, on, databaseRoleId, nil) + require.NoError(t, err) + + grants, err := client.Grants.Show(ctx, &sdk.ShowGrantOptions{ + To: &sdk.ShowGrantsTo{ + DatabaseRole: databaseRoleId, + }, + }) + require.NoError(t, err) + // Expecting two grants because database role has usage on database by default + require.Equal(t, 2, len(grants)) + + on = &sdk.DatabaseRoleGrantOn{ + SchemaObject: &sdk.GrantOnSchemaObject{ + Future: &sdk.GrantOnSchemaObjectIn{ + PluralObjectType: sdk.PluralObjectTypeStreamlits, + InDatabase: sdk.Pointer(sdk.NewAccountObjectIdentifier(TestDatabaseName)), + }, + }, + } + err = client.Grants.GrantPrivilegesToDatabaseRole(ctx, privileges, on, databaseRoleId, nil) + require.Error(t, err) + require.ErrorContains(t, err, "Unsupported feature 'STREAMLIT'") + + on = &sdk.DatabaseRoleGrantOn{ + SchemaObject: &sdk.GrantOnSchemaObject{ + All: &sdk.GrantOnSchemaObjectIn{ + PluralObjectType: sdk.PluralObjectTypeStreamlits, + InDatabase: sdk.Pointer(sdk.NewAccountObjectIdentifier(TestDatabaseName)), + }, + }, + } + err = client.Grants.GrantPrivilegesToDatabaseRole(ctx, privileges, on, databaseRoleId, nil) + require.NoError(t, err) + }) + t.Run("alter streamlit: set", func(t *testing.T) { stage, cleanupStage := createStage(t, client, sdk.NewSchemaObjectIdentifier(TestDatabaseName, TestSchemaName, random.AlphaN(4))) t.Cleanup(cleanupStage) From b7bbf2e1ade827223ca18143acbcd0c1d8377b41 Mon Sep 17 00:00:00 2001 From: Artur Sawicki Date: Wed, 27 Mar 2024 18:00:21 +0100 Subject: [PATCH 7/7] Fix after review --- .../grant_privileges_to_account_role.md | 2 +- docs/resources/grant_privileges_to_share.md | 3 ++ .../grant_privileges_to_account_role.go | 2 +- ...ileges_to_database_role_acceptance_test.go | 52 +++++++++++++++++++ .../grant_privileges_to_share.md.tmpl | 3 ++ 5 files changed, 60 insertions(+), 2 deletions(-) diff --git a/docs/resources/grant_privileges_to_account_role.md b/docs/resources/grant_privileges_to_account_role.md index 4a9ba582be..9358449ece 100644 --- a/docs/resources/grant_privileges_to_account_role.md +++ b/docs/resources/grant_privileges_to_account_role.md @@ -300,7 +300,7 @@ Optional: Optional: - `all` (Block List, Max: 1) Configures the privilege to be granted on all objects in either a database or schema. (see [below for nested schema](#nestedblock--on_schema_object--all)) -- `future` (Block List, Max: 1) Configures the privilege to be granted on all objects in either a database or schema. (see [below for nested schema](#nestedblock--on_schema_object--future)) +- `future` (Block List, Max: 1) Configures the privilege to be granted on future objects in either a database or schema. (see [below for nested schema](#nestedblock--on_schema_object--future)) - `object_name` (String) The fully qualified name of the object on which privileges will be granted. - `object_type` (String) The object type of the schema object on which privileges will be granted. Valid values are: ALERT | DYNAMIC TABLE | EVENT TABLE | FILE FORMAT | FUNCTION | PROCEDURE | SECRET | SEQUENCE | PIPE | MASKING POLICY | PASSWORD POLICY | ROW ACCESS POLICY | SESSION POLICY | TAG | STAGE | STREAM | TABLE | EXTERNAL TABLE | TASK | VIEW | MATERIALIZED VIEW | NETWORK RULE | PACKAGES POLICY | STREAMLIT | ICEBERG TABLE diff --git a/docs/resources/grant_privileges_to_share.md b/docs/resources/grant_privileges_to_share.md index a9e4c07377..6fa78c3e08 100644 --- a/docs/resources/grant_privileges_to_share.md +++ b/docs/resources/grant_privileges_to_share.md @@ -119,6 +119,9 @@ resource "snowflake_grant_privileges_to_share" "example" { - `id` (String) The ID of this resource. +## Known limitations +- Setting the `CREATE SNOWFLAKE.ML.ANOMALY_DETECTION` or `CREATE SNOWFLAKE.ML.FORECAST` privileges on schema results in a permadiff because of the probably incorrect Snowflake's behavior of `SHOW GRANTS ON `. More in the [comment](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2651#issuecomment-2022634952). + ## Import ~> **Note** All the ..._name parts should be fully qualified names, e.g. for database object it is `"".""` diff --git a/pkg/resources/grant_privileges_to_account_role.go b/pkg/resources/grant_privileges_to_account_role.go index 16c5633e71..14c988c8db 100644 --- a/pkg/resources/grant_privileges_to_account_role.go +++ b/pkg/resources/grant_privileges_to_account_role.go @@ -243,7 +243,7 @@ var grantPrivilegesToAccountRoleSchema = map[string]*schema.Schema{ Type: schema.TypeList, Optional: true, ForceNew: true, - Description: "Configures the privilege to be granted on all objects in either a database or schema.", + Description: "Configures the privilege to be granted on future objects in either a database or schema.", MaxItems: 1, Elem: &schema.Resource{ Schema: getGrantPrivilegesOnAccountRoleBulkOperationSchema(sdk.ValidGrantToFuturePluralObjectTypesString), 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 96bc7503a9..0de8ff0c69 100644 --- a/pkg/resources/grant_privileges_to_database_role_acceptance_test.go +++ b/pkg/resources/grant_privileges_to_database_role_acceptance_test.go @@ -877,6 +877,58 @@ func TestAcc_GrantPrivilegesToDatabaseRole_AlwaysApply(t *testing.T) { }) } +// proves https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2651 +// TODO [SNOW-1270457]: This seems to be a Snowflake error, we are waiting for the confirmation. Alter the test when the behavior is fixed. Update the resource documentation (section known issues). +func TestAcc_GrantPrivilegesToDatabaseRole_MLPrivileges(t *testing.T) { + name := strings.ToUpper(acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)) + configVariables := config.Variables{ + "name": config.StringVariable(name), + "privileges": config.ListVariable( + config.StringVariable(string(sdk.SchemaPrivilegeCreateSnowflakeMlAnomalyDetection)), + config.StringVariable(string(sdk.SchemaPrivilegeCreateSnowflakeMlForecast)), + ), + "database": config.StringVariable(acc.TestDatabaseName), + "schema": config.StringVariable(acc.TestSchemaName), + "with_grant_option": config.BoolVariable(false), + } + resourceName := "snowflake_grant_privileges_to_database_role.test" + + databaseRoleName := sdk.NewDatabaseObjectIdentifier(acc.TestDatabaseName, name).FullyQualifiedName() + schemaName := sdk.NewDatabaseObjectIdentifier(acc.TestDatabaseName, acc.TestSchemaName).FullyQualifiedName() + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + PreCheck: func() { acc.TestAccPreCheck(t) }, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: testAccCheckAccountRolePrivilegesRevoked(name), + Steps: []resource.TestStep{ + { + PreConfig: func() { createDatabaseRoleOutsideTerraform(t, name) }, + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_GrantPrivilegesToDatabaseRole/OnSchema"), + ConfigVariables: configVariables, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "database_role_name", databaseRoleName), + resource.TestCheckResourceAttr(resourceName, "privileges.#", "2"), + resource.TestCheckResourceAttr(resourceName, "privileges.0", string(sdk.SchemaPrivilegeCreateSnowflakeMlAnomalyDetection)), + resource.TestCheckResourceAttr(resourceName, "privileges.1", string(sdk.SchemaPrivilegeCreateSnowflakeMlForecast)), + resource.TestCheckResourceAttr(resourceName, "on_schema.#", "1"), + resource.TestCheckResourceAttr(resourceName, "on_schema.0.schema_name", schemaName), + resource.TestCheckResourceAttr(resourceName, "with_grant_option", "false"), + resource.TestCheckResourceAttr(resourceName, "id", fmt.Sprintf("%s|false|false|CREATE SNOWFLAKE.ML.ANOMALY_DETECTION,CREATE SNOWFLAKE.ML.FORECAST|OnSchema|OnSchema|%s", databaseRoleName, schemaName)), + ), + ExpectNonEmptyPlan: true, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectNonEmptyPlan(), + }, + }, + }, + }, + }) +} + func createDatabaseRoleOutsideTerraform(t *testing.T, name string) { t.Helper() client, err := sdk.NewDefaultClient() diff --git a/templates/resources/grant_privileges_to_share.md.tmpl b/templates/resources/grant_privileges_to_share.md.tmpl index ebfe2a54df..2132602c86 100644 --- a/templates/resources/grant_privileges_to_share.md.tmpl +++ b/templates/resources/grant_privileges_to_share.md.tmpl @@ -24,6 +24,9 @@ description: |- {{ .SchemaMarkdown | trimspace }} +## Known limitations +- Setting the `CREATE SNOWFLAKE.ML.ANOMALY_DETECTION` or `CREATE SNOWFLAKE.ML.FORECAST` privileges on schema results in a permadiff because of the probably incorrect Snowflake's behavior of `SHOW GRANTS ON `. More in the [comment](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2651#issuecomment-2022634952). + ## Import ~> **Note** All the ..._name parts should be fully qualified names, e.g. for database object it is `"".""`