From e6a38c3c7f1b3fc934815db6dd2686abbc630a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Cie=C5=9Blak?= Date: Tue, 9 Jul 2024 13:53:57 +0200 Subject: [PATCH 1/7] wip --- MIGRATION_GUIDE.md | 14 ++ pkg/datasources/roles.go | 70 +++--- pkg/datasources/roles_acceptance_test.go | 91 ++----- .../test.tf | 2 +- .../variables.tf | 2 +- pkg/provider/provider.go | 55 ++--- pkg/resources/role.go | 102 +++----- pkg/resources/role_acceptance_test.go | 223 +++++++++++------- templates/resources/role.md.tmpl | 32 +++ 9 files changed, 293 insertions(+), 298 deletions(-) rename pkg/datasources/testdata/{TestAcc_AccountRoles_basic => TestAcc_AccountRoles_Complete}/test.tf (94%) rename pkg/datasources/testdata/{TestAcc_AccountRoles_basic => TestAcc_AccountRoles_Complete}/variables.tf (91%) create mode 100644 templates/resources/role.md.tmpl diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 9790aa2f10..a96cbbf0d7 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -20,6 +20,20 @@ They are all described in short in the [changes before v1 doc](./v1-preparations ### old grant resources removal Following the [announcement](https://github.com/Snowflake-Labs/terraform-provider-snowflake/discussions/2736) we have removed the old grant resources. The two resources [snowflake_role_ownership_grant](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_ownership_grant) and [snowflake_user_ownership_grant](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/user_ownership_grant) were not listed in the announcement, but they were also marked as deprecated ones. We are removing them too to conclude the grants redesign saga. + +### *(new feature)* new field in the snowflake_role resource + +No migration is needed. + +New fields: +- added `show_output` field that holds the response from SHOW ROLES. Remember that the field will be only recomputed if one of the fields (`name` or `comment`) are changed. + +### *(breaking change)* refactored snowflake_roles data source + +Changes: +- `pattern` was renamed to `like` +- output of SHOW is enclosed in `show_output`, so before, e.g. `roles.0.comment` is now `roles.0.show_output.0.comment` + ### *(new feature)* Api authentication resources Added new api authentication resources, i.e.: - `snowflake_api_authentication_integration_with_authorization_code_grant` diff --git a/pkg/datasources/roles.go b/pkg/datasources/roles.go index 72110abc23..c9ebb2ae95 100644 --- a/pkg/datasources/roles.go +++ b/pkg/datasources/roles.go @@ -3,6 +3,8 @@ package datasources import ( "context" "fmt" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/resources" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" @@ -12,31 +14,29 @@ import ( ) var accountRolesSchema = map[string]*schema.Schema{ - "pattern": { + "like": { Type: schema.TypeString, Optional: true, - Description: "Filters the command output by object name.", + Description: "Filters the output with **case-insensitive** pattern, with support for SQL wildcard characters (`%` and `_`).", + }, + "in_class": { + Type: schema.TypeString, + Optional: true, + Description: "Filters the output and returns only the records for the specified class name.", }, "roles": { Type: schema.TypeList, Computed: true, - Description: "List of all the roles which you can view across your entire account, including the system-defined roles and any custom roles that exist.", + Description: "Holds the aggregated output of all role details queries.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Computed: true, - Description: "Identifier for the role.", - }, - "comment": { - Type: schema.TypeString, + resources.ShowOutputAttributeName: { + Type: schema.TypeList, Computed: true, - Description: "The comment on the role", - }, - "owner": { - Type: schema.TypeString, - Computed: true, - Description: "The owner of the role", + Description: "Holds the output of SHOW ROLES.", + Elem: &schema.Resource{ + Schema: schemas.ShowRoleSchema, + }, }, }, }, @@ -47,6 +47,7 @@ func Roles() *schema.Resource { return &schema.Resource{ ReadContext: ReadAccountRoles, Schema: accountRolesSchema, + Description: "Datasource used to get details of filtered roles. Filtering is aligned with the current possibilities for [SHOW ROLES](https://docs.snowflake.com/en/sql-reference/sql/show-roles) query (`like` and `in_class` are all supported). The results of SHOW are encapsulated in one output collection.", } } @@ -54,8 +55,15 @@ func ReadAccountRoles(ctx context.Context, d *schema.ResourceData, meta any) dia client := meta.(*provider.Context).Client req := sdk.NewShowRoleRequest() - if pattern, ok := d.GetOk("pattern"); ok { - req.WithLike(sdk.NewLikeRequest(pattern.(string))) + + if likePattern, ok := d.GetOk("like"); ok { + req.WithLike(sdk.NewLikeRequest(likePattern.(string))) + } + + if className, ok := d.GetOk("in_class"); ok { + req.WithInClass(sdk.RolesInClass{ + Class: sdk.NewAccountObjectIdentifier(className.(string)), + }) } roles, err := client.Roles.Show(ctx, req) @@ -64,31 +72,25 @@ func ReadAccountRoles(ctx context.Context, d *schema.ResourceData, meta any) dia diag.Diagnostic{ Severity: diag.Error, Summary: "Failed to show account roles", - Detail: fmt.Sprintf("Search pattern: %v, err: %s", d.Get("pattern").(string), err), + Detail: fmt.Sprintf("Error: %s", err), }, } } - mappedRoles := make([]map[string]any, len(roles)) + d.SetId("roles_read") + + flattenedRoles := make([]map[string]any, len(roles)) for i, role := range roles { - mappedRoles[i] = map[string]any{ - "name": role.Name, - "comment": role.Comment, - "owner": role.Owner, + role := role + flattenedRoles[i] = map[string]any{ + resources.ShowOutputAttributeName: []map[string]any{schemas.RoleToSchema(&role)}, } } - if err := d.Set("roles", mappedRoles); err != nil { - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to set roles", - Detail: fmt.Sprintf("Search pattern: %v, err: %s", d.Get("pattern").(string), err), - }, - } + err = d.Set("roles", flattenedRoles) + if err != nil { + return diag.FromErr(err) } - d.SetId("roles_read") - return nil } diff --git a/pkg/datasources/roles_acceptance_test.go b/pkg/datasources/roles_acceptance_test.go index 42791f8fe1..8800d24014 100644 --- a/pkg/datasources/roles_acceptance_test.go +++ b/pkg/datasources/roles_acceptance_test.go @@ -2,6 +2,7 @@ package datasources_test import ( "fmt" + "maps" "strconv" "testing" @@ -14,58 +15,27 @@ import ( "github.com/hashicorp/terraform-plugin-testing/tfversion" ) -const ( - accountAdmin = "ACCOUNTADMIN" -) - -func TestAcc_Roles(t *testing.T) { - roleName := acc.TestClient().Ids.Alpha() - roleName2 := acc.TestClient().Ids.Alpha() - comment := random.Comment() - resource.Test(t, resource.TestCase{ - ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - CheckDestroy: nil, - Steps: []resource.TestStep{ - { - Config: roles(roleName, roleName2, comment), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet("data.snowflake_roles.r", "roles.#"), - resource.TestCheckResourceAttrSet("data.snowflake_roles.r", "roles.0.name"), - // resource.TestCheckTypeSetElemAttr("data.snowflake_roles.r", "roles.*", "name"), - // TODO SHOW ROLES output also includes built in roles, i.e. ACCOUNTADMIN, SYSADMIN, etc. - ), - }, - { - Config: rolesPattern(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet("data.snowflake_roles.r", "roles.#"), - // resource.TestCheckResourceAttrSet("data.snowflake_roles.r", "roles.0.name"), - resource.TestCheckResourceAttr("data.snowflake_roles.r", "roles.#", "1"), - resource.TestCheckResourceAttr("data.snowflake_roles.r", "roles.0.name", accountAdmin), - ), - }, - }, - }) -} - -func TestAcc_AccountRoles_basic(t *testing.T) { - accountRoleNamePrefix := "account_roles_test_prefix_" + random.AlphaN(4) - accountRoleName1 := acc.TestClient().Ids.AlphaWithPrefix(accountRoleNamePrefix) - accountRoleName2 := acc.TestClient().Ids.AlphaWithPrefix(accountRoleNamePrefix) +func TestAcc_AccountRoles_Complete(t *testing.T) { + accountRoleNamePrefix := random.AlphaN(10) + accountRoleName1 := acc.TestClient().Ids.AlphaWithPrefix(accountRoleNamePrefix + "1") + accountRoleName2 := acc.TestClient().Ids.AlphaWithPrefix(accountRoleNamePrefix + "2") accountRoleName3 := acc.TestClient().Ids.Alpha() comment := random.Comment() - configVariables := config.Variables{ + commonVariables := config.Variables{ "account_role_name_1": config.StringVariable(accountRoleName1), "account_role_name_2": config.StringVariable(accountRoleName2), "account_role_name_3": config.StringVariable(accountRoleName3), - "pattern": config.StringVariable(accountRoleNamePrefix + "%"), "comment": config.StringVariable(comment), } + likeVariables := maps.Clone(commonVariables) + likeVariables["like"] = config.StringVariable(accountRoleNamePrefix + "%") + + // TODO(SNOW-1353303): Add test case for instance classes after they're available in the provider + inClassVariables := maps.Clone(commonVariables) + inClassVariables["in_class"] = config.StringVariable("TODO") + resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, PreCheck: func() { acc.TestAccPreCheck(t) }, @@ -75,7 +45,7 @@ func TestAcc_AccountRoles_basic(t *testing.T) { Steps: []resource.TestStep{ { ConfigDirectory: config.TestNameDirectory(), - ConfigVariables: configVariables, + ConfigVariables: likeVariables, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("data.snowflake_roles.test", "roles.#", "2"), containsAccountRole(accountRoleName1, comment), @@ -90,7 +60,7 @@ func TestAcc_AccountRoles_basic(t *testing.T) { func doesntContainAccountRole(name string, comment string) func(s *terraform.State) error { return func(state *terraform.State) error { err := containsAccountRole(name, comment)(state) - if err.Error() == fmt.Sprintf("role %s not found", name) { + if err != nil && err.Error() == fmt.Sprintf("role %s not found", name) { return nil } return fmt.Errorf("expected %s not to be present", name) @@ -110,8 +80,8 @@ func containsAccountRole(name string, comment string) func(s *terraform.State) e } for i := 0; i < int(iter); i++ { - if rs.Primary.Attributes[fmt.Sprintf("roles.%d.name", i)] == name { - actualComment := rs.Primary.Attributes[fmt.Sprintf("roles.%d.comment", i)] + if rs.Primary.Attributes[fmt.Sprintf("roles.%d.show_output.0.name", i)] == name { + actualComment := rs.Primary.Attributes[fmt.Sprintf("roles.%d.show_output.0.comment", i)] if actualComment != comment { return fmt.Errorf("expected comment: %s, but got: %s", comment, actualComment) } @@ -124,30 +94,3 @@ func containsAccountRole(name string, comment string) func(s *terraform.State) e return fmt.Errorf("role %s not found", name) } } - -func roles(roleName, roleName2, comment string) string { - return fmt.Sprintf(` - resource snowflake_role "test_role" { - name = "%v" - comment = "%v" - } - resource snowflake_role "test_role_2" { - name = "%v" - comment = "%v" - } - data snowflake_roles "r" { - depends_on = [ - snowflake_role.test_role, - snowflake_role.test_role_2, - ] - } - `, roleName, comment, roleName2, comment) -} - -func rolesPattern() string { - return fmt.Sprintf(` - data snowflake_roles "r" { - pattern = "%v" - } - `, accountAdmin) -} diff --git a/pkg/datasources/testdata/TestAcc_AccountRoles_basic/test.tf b/pkg/datasources/testdata/TestAcc_AccountRoles_Complete/test.tf similarity index 94% rename from pkg/datasources/testdata/TestAcc_AccountRoles_basic/test.tf rename to pkg/datasources/testdata/TestAcc_AccountRoles_Complete/test.tf index 00ebde112b..50927990e3 100644 --- a/pkg/datasources/testdata/TestAcc_AccountRoles_basic/test.tf +++ b/pkg/datasources/testdata/TestAcc_AccountRoles_Complete/test.tf @@ -19,5 +19,5 @@ data "snowflake_roles" "test" { snowflake_role.test2, snowflake_role.test3, ] - pattern = var.pattern + like = var.like } diff --git a/pkg/datasources/testdata/TestAcc_AccountRoles_basic/variables.tf b/pkg/datasources/testdata/TestAcc_AccountRoles_Complete/variables.tf similarity index 91% rename from pkg/datasources/testdata/TestAcc_AccountRoles_basic/variables.tf rename to pkg/datasources/testdata/TestAcc_AccountRoles_Complete/variables.tf index c632a5527e..fcd75c445f 100644 --- a/pkg/datasources/testdata/TestAcc_AccountRoles_basic/variables.tf +++ b/pkg/datasources/testdata/TestAcc_AccountRoles_Complete/variables.tf @@ -14,6 +14,6 @@ variable "comment" { type = string } -variable "pattern" { +variable "like" { type = string } diff --git a/pkg/provider/provider.go b/pkg/provider/provider.go index 83e99b4a16..d81bf32201 100644 --- a/pkg/provider/provider.go +++ b/pkg/provider/provider.go @@ -462,33 +462,34 @@ func getResources() map[string]*schema.Resource { "snowflake_pipe": resources.Pipe(), "snowflake_procedure": resources.Procedure(), "snowflake_resource_monitor": resources.ResourceMonitor(), - "snowflake_role": resources.Role(), - "snowflake_row_access_policy": resources.RowAccessPolicy(), - "snowflake_saml_integration": resources.SAMLIntegration(), - "snowflake_saml2_integration": resources.SAML2Integration(), - "snowflake_schema": resources.Schema(), - "snowflake_scim_integration": resources.SCIMIntegration(), - "snowflake_secondary_database": resources.SecondaryDatabase(), - "snowflake_sequence": resources.Sequence(), - "snowflake_session_parameter": resources.SessionParameter(), - "snowflake_share": resources.Share(), - "snowflake_shared_database": resources.SharedDatabase(), - "snowflake_stage": resources.Stage(), - "snowflake_storage_integration": resources.StorageIntegration(), - "snowflake_stream": resources.Stream(), - "snowflake_table": resources.Table(), - "snowflake_table_column_masking_policy_application": resources.TableColumnMaskingPolicyApplication(), - "snowflake_table_constraint": resources.TableConstraint(), - "snowflake_tag": resources.Tag(), - "snowflake_tag_association": resources.TagAssociation(), - "snowflake_tag_masking_policy_association": resources.TagMaskingPolicyAssociation(), - "snowflake_task": resources.Task(), - "snowflake_unsafe_execute": resources.UnsafeExecute(), - "snowflake_user": resources.User(), - "snowflake_user_password_policy_attachment": resources.UserPasswordPolicyAttachment(), - "snowflake_user_public_keys": resources.UserPublicKeys(), - "snowflake_view": resources.View(), - "snowflake_warehouse": resources.Warehouse(), + // TODO: Should it be account role ??? + "snowflake_role": resources.Role(), + "snowflake_row_access_policy": resources.RowAccessPolicy(), + "snowflake_saml_integration": resources.SAMLIntegration(), + "snowflake_saml2_integration": resources.SAML2Integration(), + "snowflake_schema": resources.Schema(), + "snowflake_scim_integration": resources.SCIMIntegration(), + "snowflake_secondary_database": resources.SecondaryDatabase(), + "snowflake_sequence": resources.Sequence(), + "snowflake_session_parameter": resources.SessionParameter(), + "snowflake_share": resources.Share(), + "snowflake_shared_database": resources.SharedDatabase(), + "snowflake_stage": resources.Stage(), + "snowflake_storage_integration": resources.StorageIntegration(), + "snowflake_stream": resources.Stream(), + "snowflake_table": resources.Table(), + "snowflake_table_column_masking_policy_application": resources.TableColumnMaskingPolicyApplication(), + "snowflake_table_constraint": resources.TableConstraint(), + "snowflake_tag": resources.Tag(), + "snowflake_tag_association": resources.TagAssociation(), + "snowflake_tag_masking_policy_association": resources.TagMaskingPolicyAssociation(), + "snowflake_task": resources.Task(), + "snowflake_unsafe_execute": resources.UnsafeExecute(), + "snowflake_user": resources.User(), + "snowflake_user_password_policy_attachment": resources.UserPasswordPolicyAttachment(), + "snowflake_user_public_keys": resources.UserPublicKeys(), + "snowflake_view": resources.View(), + "snowflake_warehouse": resources.Warehouse(), } } diff --git a/pkg/resources/role.go b/pkg/resources/role.go index bf585ddf7f..22784240bf 100644 --- a/pkg/resources/role.go +++ b/pkg/resources/role.go @@ -4,8 +4,8 @@ import ( "context" "errors" "fmt" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -24,17 +24,27 @@ var accountRoleSchema = map[string]*schema.Schema{ Type: schema.TypeString, Optional: true, }, - "tag": tagReferenceSchema, + ShowOutputAttributeName: { + Type: schema.TypeList, + Computed: true, + Description: "Outputs the result of `SHOW ROLES` for the given role.", + Elem: &schema.Resource{ + Schema: schemas.ShowRoleSchema, + }, + }, } func Role() *schema.Resource { return &schema.Resource{ + Schema: accountRoleSchema, + CreateContext: CreateAccountRole, ReadContext: ReadAccountRole, DeleteContext: DeleteAccountRole, UpdateContext: UpdateAccountRole, - Schema: accountRoleSchema, + CustomizeDiff: ComputedIfAnyAttributeChanged(ShowOutputAttributeName, "name", "comment"), + Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -44,25 +54,20 @@ func Role() *schema.Resource { func CreateAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { client := meta.(*provider.Context).Client - name := d.Get("name").(string) - id := sdk.NewAccountObjectIdentifier(name) + id := sdk.NewAccountObjectIdentifier(d.Get("name").(string)) req := sdk.NewCreateRoleRequest(id) if v, ok := d.GetOk("comment"); ok { req.WithComment(v.(string)) } - if _, ok := d.GetOk("tag"); ok { - req.WithTag(getPropertyTags(d, "tag")) - } - err := client.Roles.Create(ctx, req) if err != nil { return diag.Diagnostics{ diag.Diagnostic{ Severity: diag.Error, Summary: "Failed to create account role", - Detail: fmt.Sprintf("Account role name: %s, err: %s", name, err), + Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), }, } } @@ -84,7 +89,7 @@ func ReadAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag diag.Diagnostic{ Severity: diag.Warning, Summary: "Account role not found; marking it as removed", - Detail: fmt.Sprintf("Account role name: %s, err: %s", id.FullyQualifiedName(), err), + Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), }, } } @@ -92,12 +97,12 @@ func ReadAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag diag.Diagnostic{ Severity: diag.Error, Summary: "Failed to show account role by id", - Detail: fmt.Sprintf("Account role name: %s, err: %s", id.FullyQualifiedName(), err), + Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), }, } } - if err := d.Set("name", accountRole.Name); err != nil { + if err := d.Set("name", sdk.NewAccountObjectIdentifier(accountRole.Name).Name()); err != nil { return diag.Diagnostics{ diag.Diagnostic{ Severity: diag.Error, @@ -117,7 +122,9 @@ func ReadAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag } } - d.SetId(helpers.EncodeSnowflakeID(id)) + if err = d.Set(ShowOutputAttributeName, []map[string]any{schemas.RoleToSchema(accountRole)}); err != nil { + return diag.FromErr(err) + } return nil } @@ -128,13 +135,12 @@ func UpdateAccountRole(ctx context.Context, d *schema.ResourceData, meta any) di if d.HasChange("comment") { if v, ok := d.GetOk("comment"); ok { - err := client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithSetComment(v.(string))) - if err != nil { + if err := client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithSetComment(v.(string))); err != nil { return diag.Diagnostics{ diag.Diagnostic{ Severity: diag.Error, Summary: "Failed to set account role comment", - Detail: fmt.Sprintf("Account role name: %s, comment: %s, err: %s", id.FullyQualifiedName(), v, err), + Detail: fmt.Sprintf("Account role name: %s, comment: %s, err: %s", id.Name(), v, err), }, } } @@ -145,45 +151,7 @@ func UpdateAccountRole(ctx context.Context, d *schema.ResourceData, meta any) di diag.Diagnostic{ Severity: diag.Error, Summary: "Failed to unset account role comment", - Detail: fmt.Sprintf("Account role name: %s, err: %s", id.FullyQualifiedName(), err), - }, - } - } - } - } - - if d.HasChange("tag") { - unsetTags, setTags := GetTagsDiff(d, "tag") - - if len(unsetTags) > 0 { - err := client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithUnsetTags(unsetTags)) - if err != nil { - tagNames := make([]string, len(unsetTags)) - for i, v := range unsetTags { - tagNames[i] = v.FullyQualifiedName() - } - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to unset account role tags", - Detail: fmt.Sprintf("Account role name: %s, tags to unset: %v, err: %s", id.FullyQualifiedName(), tagNames, err), - }, - } - } - } - - if len(setTags) > 0 { - err := client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithSetTags(setTags)) - if err != nil { - tagNames := make([]string, len(unsetTags)) - for i, v := range unsetTags { - tagNames[i] = v.FullyQualifiedName() - } - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to set account role tags", - Detail: fmt.Sprintf("Account role name: %s, tags to set: %v, err: %s", id.FullyQualifiedName(), tagNames, err), + Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), }, } } @@ -191,30 +159,19 @@ func UpdateAccountRole(ctx context.Context, d *schema.ResourceData, meta any) di } if d.HasChange("name") { - _, newName := d.GetChange("name") - - newId, err := helpers.DecodeSnowflakeParameterID(newName.(string)) - if err != nil { - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to parse account role name", - Detail: fmt.Sprintf("Account role name: %s, err: %s", newName, err), - }, - } - } + newId := sdk.NewAccountObjectIdentifier(d.Get("name").(string)) - err = client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithRenameTo(newId.(sdk.AccountObjectIdentifier))) - if err != nil { + if err := client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithRenameTo(newId)); err != nil { return diag.Diagnostics{ diag.Diagnostic{ Severity: diag.Error, Summary: "Failed to rename account role name", - Detail: fmt.Sprintf("Previous account role name: %s, new account role name: %s, err: %s", id, newName, err), + Detail: fmt.Sprintf("Previous account role name: %s, new account role name: %s, err: %s", id.Name(), newId.Name(), err), }, } } + id = newId d.SetId(helpers.EncodeSnowflakeID(newId)) } @@ -225,8 +182,7 @@ func DeleteAccountRole(ctx context.Context, d *schema.ResourceData, meta any) di client := meta.(*provider.Context).Client id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) - err := client.Roles.Drop(ctx, sdk.NewDropRoleRequest(id)) - if err != nil { + if err := client.Roles.Drop(ctx, sdk.NewDropRoleRequest(id).WithIfExists(true)); err != nil { return diag.Diagnostics{ diag.Diagnostic{ Severity: diag.Error, diff --git a/pkg/resources/role_acceptance_test.go b/pkg/resources/role_acceptance_test.go index 6a68a7e008..5225155b42 100644 --- a/pkg/resources/role_acceptance_test.go +++ b/pkg/resources/role_acceptance_test.go @@ -1,21 +1,27 @@ package resources_test import ( + "context" "fmt" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/importchecks" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/stretchr/testify/require" "testing" acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" - "github.com/hashicorp/terraform-plugin-testing/config" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) -func TestAcc_Role(t *testing.T) { - name := acc.TestClient().Ids.Alpha() - name2 := acc.TestClient().Ids.Alpha() +func TestAcc_Role_Basic(t *testing.T) { + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() + comment := random.Comment() + + currentRole, err := acc.Client(t).ContextFunctions.CurrentRole(context.Background()) + require.NoError(t, err) resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, @@ -25,124 +31,165 @@ func TestAcc_Role(t *testing.T) { PreCheck: func() { acc.TestAccPreCheck(t) }, CheckDestroy: acc.CheckDestroy(t, resources.Role), Steps: []resource.TestStep{ + // create with empty optionals { - Config: roleBasicConfig(name, "test comment"), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_role.role", "name", name), - resource.TestCheckResourceAttr("snowflake_role.role", "comment", "test comment"), + Config: roleBasicConfig(id.Name(), ""), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_role.role", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "comment", ""), + + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.#", "1"), + resource.TestCheckResourceAttrSet("snowflake_role.role", "show_output.0.created_on"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_default", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_current", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_inherited", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.assigned_to_users", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_to_roles", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_roles", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.owner", currentRole.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.comment", ""), ), }, - // IMPORT + // import - without optionals { - ResourceName: "snowflake_role.role", - ImportState: true, - ImportStateVerify: true, - }, - // RENAME - { - Config: roleBasicConfig(name2, "test comment"), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_role.role", "name", name2), - resource.TestCheckResourceAttr("snowflake_role.role", "comment", "test comment"), + Config: roleBasicConfig(id.Name(), ""), + ResourceName: "snowflake_role.role", + ImportState: true, + ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "comment", ""), ), }, - // CHANGE PROPERTIES + // set optionals { - Config: roleBasicConfig(name2, "test comment 2"), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_role.role", "name", name2), - resource.TestCheckResourceAttr("snowflake_role.role", "comment", "test comment 2"), + Config: roleBasicConfig(id.Name(), comment), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("snowflake_role.role", plancheck.ResourceActionUpdate), + }, + }, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_role.role", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "comment", comment), + + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.#", "1"), + resource.TestCheckResourceAttrSet("snowflake_role.role", "show_output.0.created_on"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_default", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_current", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_inherited", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.assigned_to_users", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_to_roles", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_roles", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.owner", currentRole.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.comment", comment), ), }, - }, - }) -} - -func TestAcc_AccountRole_basic(t *testing.T) { - name := acc.TestClient().Ids.Alpha() - comment := random.Comment() - configVariables := map[string]config.Variable{ - "name": config.StringVariable(name), - "comment": config.StringVariable(comment), - } - resourceName := "snowflake_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: acc.CheckDestroy(t, resources.Role), - Steps: []resource.TestStep{ + // import - complete { - ConfigDirectory: config.TestNameDirectory(), - ConfigVariables: configVariables, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "comment", comment), - resource.TestCheckResourceAttr(resourceName, "id", name), + Config: roleBasicConfig(id.Name(), ""), + ResourceName: "snowflake_role.role", + ImportState: true, + ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "comment", comment), ), }, - // test import + // unset { - ConfigDirectory: config.TestNameDirectory(), - ConfigVariables: configVariables, - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + Config: roleBasicConfig(id.Name(), ""), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("snowflake_role.role", plancheck.ResourceActionUpdate), + }, + }, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_role.role", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "comment", ""), + + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.#", "1"), + resource.TestCheckResourceAttrSet("snowflake_role.role", "show_output.0.created_on"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_default", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_current", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_inherited", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.assigned_to_users", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_to_roles", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_roles", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.owner", currentRole.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.comment", ""), + ), }, }, }) } -func TestAcc_AccountRole_updates(t *testing.T) { - configVariables := func(name string, comment string) config.Variables { - return config.Variables{ - "name": config.StringVariable(name), - "comment": config.StringVariable(comment), - } - } - - name := acc.TestClient().Ids.Alpha() - newName := acc.TestClient().Ids.Alpha() +func TestAcc_Role_Complete(t *testing.T) { + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() comment := random.Comment() - NewComment := "updated comment with 'single' quotes" - resourceName := "snowflake_role.test" + + newId := acc.TestClient().Ids.RandomAccountObjectIdentifier() + newComment := random.Comment() + + currentRole, err := acc.Client(t).ContextFunctions.CurrentRole(context.Background()) + require.NoError(t, err) resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, - PreCheck: func() { acc.TestAccPreCheck(t) }, TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.RequireAbove(tfversion.Version1_5_0), }, + PreCheck: func() { acc.TestAccPreCheck(t) }, CheckDestroy: acc.CheckDestroy(t, resources.Role), Steps: []resource.TestStep{ { - ConfigDirectory: config.TestNameDirectory(), - ConfigVariables: configVariables(name, comment), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "comment", comment), - resource.TestCheckResourceAttr(resourceName, "id", name), + Config: roleBasicConfig(id.Name(), comment), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_role.role", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "comment", comment), + + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.#", "1"), + resource.TestCheckResourceAttrSet("snowflake_role.role", "show_output.0.created_on"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_default", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_current", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_inherited", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.assigned_to_users", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_to_roles", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_roles", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.owner", currentRole.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.comment", comment), ), }, { - ConfigDirectory: config.TestNameDirectory(), - ConfigVariables: configVariables(newName, NewComment), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "name", newName), - resource.TestCheckResourceAttr(resourceName, "comment", NewComment), - resource.TestCheckResourceAttr(resourceName, "id", newName), + Config: roleBasicConfig(id.Name(), ""), + ResourceName: "snowflake_role.role", + ImportState: true, + ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "comment", comment), ), }, - // test import + // rename + comment change { - ConfigDirectory: config.TestNameDirectory(), - ConfigVariables: configVariables(newName, NewComment), - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + Config: roleBasicConfig(newId.Name(), newComment), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_role.role", "name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "comment", newComment), + + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.#", "1"), + resource.TestCheckResourceAttrSet("snowflake_role.role", "show_output.0.created_on"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_default", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_current", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_inherited", "false"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.assigned_to_users", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_to_roles", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_roles", "0"), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.owner", currentRole.Name()), + resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.comment", newComment), + ), }, }, }) diff --git a/templates/resources/role.md.tmpl b/templates/resources/role.md.tmpl new file mode 100644 index 0000000000..e7f66bbf91 --- /dev/null +++ b/templates/resources/role.md.tmpl @@ -0,0 +1,32 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ if gt (len (split .Description "")) 1 -}} +{{ index (split .Description "") 1 | plainmarkdown | trimspace | prefixlines " " }} +{{- else -}} +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +{{- end }} +--- + +!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v0920--v0930) to use it. + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +{{ if .HasExample -}} +## Example Usage + +{{ tffile (printf "examples/resources/%s/resource.tf" .Name)}} +{{- end }} + +{{ .SchemaMarkdown | trimspace }} +{{- if .HasImport }} + +## Import + +Import is supported using the following syntax: + +{{ codefile "shell" (printf "examples/resources/%s/import.sh" .Name)}} +{{- end }} From e1860a10ab8f374c26ea5476f685f64dec1e00d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Cie=C5=9Blak?= Date: Tue, 9 Jul 2024 15:32:52 +0200 Subject: [PATCH 2/7] Adjust documentation for roles --- docs/data-sources/roles.md | 40 +++++++++++++++++-- docs/resources/role.md | 14 +++++-- .../snowflake_roles/data-source.tf | 38 ++++++++++++++++-- examples/resources/snowflake_role/import.sh | 2 +- examples/resources/snowflake_role/resource.tf | 12 ++++-- pkg/datasources/role.go | 2 + templates/data-sources/roles.md.tmpl | 24 +++++++++++ 7 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 templates/data-sources/roles.md.tmpl diff --git a/docs/data-sources/roles.md b/docs/data-sources/roles.md index c899866d91..1c4a7d5aef 100644 --- a/docs/data-sources/roles.md +++ b/docs/data-sources/roles.md @@ -5,6 +5,8 @@ description: |- Datasource used to get details of filtered roles. Filtering is aligned with the current possibilities for SHOW ROLES https://docs.snowflake.com/en/sql-reference/sql/show-roles query (like and in_class are all supported). The results of SHOW are encapsulated in one output collection. --- +!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v0920--v0930) to use it. + # snowflake_roles (Data Source) Datasource used to get details of filtered roles. Filtering is aligned with the current possibilities for [SHOW ROLES](https://docs.snowflake.com/en/sql-reference/sql/show-roles) query (`like` and `in_class` are all supported). The results of SHOW are encapsulated in one output collection. @@ -12,12 +14,44 @@ Datasource used to get details of filtered roles. Filtering is aligned with the ## Example Usage ```terraform -data "snowflake_roles" "this" { +# Simple usage +data "snowflake_roles" "simple" { +} +output "simple_output" { + value = data.snowflake_roles.simple.roles } -data "snowflake_roles" "ad" { - pattern = "SYSADMIN" +# Filtering (like) +data "snowflake_roles" "like" { + like = "role-name" +} + +output "like_output" { + value = data.snowflake_roles.like.roles +} + +# Ensure the number of roles is equal to at least one element (with the use of postcondition) +data "snowflake_roles" "assert_with_postcondition" { + like = "role-name-%" + lifecycle { + postcondition { + condition = length(self.roles) > 0 + error_message = "there should be at least one role" + } + } +} + +# Ensure the number of roles is equal to at exactly one element (with the use of check block) +check "role_check" { + data "snowflake_roles" "assert_with_check_block" { + like = "role-name" + } + + assert { + condition = length(data.snowflake_roles.assert_with_check_block.roles) == 1 + error_message = "Roles filtered by '${data.snowflake_roles.assert_with_check_block.like}' returned ${length(data.snowflake_roles.assert_with_check_block.roles)} roles where one was expected" + } } ``` diff --git a/docs/resources/role.md b/docs/resources/role.md index d7e06f4c49..2afc44dcef 100644 --- a/docs/resources/role.md +++ b/docs/resources/role.md @@ -14,9 +14,15 @@ description: |- ## Example Usage ```terraform -resource "snowflake_role" "role" { - name = "role1" - comment = "A role." +## Minimal +resource "snowflake_role" "minimal" { + name = "role_name" +} + +## Complete (with every optional set) +resource "snowflake_role" "complete" { + name = "role_name" + comment = "my account role" } ``` @@ -57,5 +63,5 @@ Read-Only: Import is supported using the following syntax: ```shell -terraform import snowflake_role.example roleName +terraform import snowflake_role.example "name" ``` diff --git a/examples/data-sources/snowflake_roles/data-source.tf b/examples/data-sources/snowflake_roles/data-source.tf index dd4c517183..fe510a2ca9 100644 --- a/examples/data-sources/snowflake_roles/data-source.tf +++ b/examples/data-sources/snowflake_roles/data-source.tf @@ -1,7 +1,39 @@ -data "snowflake_roles" "this" { +# Simple usage +data "snowflake_roles" "simple" { +} + +output "simple_output" { + value = data.snowflake_roles.simple.roles +} + +# Filtering (like) +data "snowflake_roles" "like" { + like = "role-name" +} + +output "like_output" { + value = data.snowflake_roles.like.roles +} +# Ensure the number of roles is equal to at least one element (with the use of postcondition) +data "snowflake_roles" "assert_with_postcondition" { + like = "role-name-%" + lifecycle { + postcondition { + condition = length(self.roles) > 0 + error_message = "there should be at least one role" + } + } } -data "snowflake_roles" "ad" { - pattern = "SYSADMIN" +# Ensure the number of roles is equal to at exactly one element (with the use of check block) +check "role_check" { + data "snowflake_roles" "assert_with_check_block" { + like = "role-name" + } + + assert { + condition = length(data.snowflake_roles.assert_with_check_block.roles) == 1 + error_message = "Roles filtered by '${data.snowflake_roles.assert_with_check_block.like}' returned ${length(data.snowflake_roles.assert_with_check_block.roles)} roles where one was expected" + } } diff --git a/examples/resources/snowflake_role/import.sh b/examples/resources/snowflake_role/import.sh index d43d64eaba..e0d1439a34 100644 --- a/examples/resources/snowflake_role/import.sh +++ b/examples/resources/snowflake_role/import.sh @@ -1 +1 @@ -terraform import snowflake_role.example roleName +terraform import snowflake_role.example "name" diff --git a/examples/resources/snowflake_role/resource.tf b/examples/resources/snowflake_role/resource.tf index 58a2af9abe..97d8851c29 100644 --- a/examples/resources/snowflake_role/resource.tf +++ b/examples/resources/snowflake_role/resource.tf @@ -1,4 +1,10 @@ -resource "snowflake_role" "role" { - name = "role1" - comment = "A role." +## Minimal +resource "snowflake_role" "minimal" { + name = "role_name" +} + +## Complete (with every optional set) +resource "snowflake_role" "complete" { + name = "role_name" + comment = "my account role" } diff --git a/pkg/datasources/role.go b/pkg/datasources/role.go index 2629ade57e..8ac32a11b7 100644 --- a/pkg/datasources/role.go +++ b/pkg/datasources/role.go @@ -10,6 +10,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +// TODO: Adjust + var roleSchema = map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/templates/data-sources/roles.md.tmpl b/templates/data-sources/roles.md.tmpl new file mode 100644 index 0000000000..18e5fffd7a --- /dev/null +++ b/templates/data-sources/roles.md.tmpl @@ -0,0 +1,24 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "" +description: |- +{{ if gt (len (split .Description "")) 1 -}} +{{ index (split .Description "") 1 | plainmarkdown | trimspace | prefixlines " " }} +{{- else -}} +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +{{- end }} +--- + +!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v0920--v0930) to use it. + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +{{ if .HasExample -}} +## Example Usage + +{{ tffile (printf "examples/data-sources/%s/data-source.tf" .Name)}} +{{- end }} + +{{ .SchemaMarkdown | trimspace }} From bf99277169dfbfc820a2811e2287a1c90c16fed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Cie=C5=9Blak?= Date: Wed, 10 Jul 2024 08:49:10 +0200 Subject: [PATCH 3/7] Rename references to deprecated role resource --- MIGRATION_GUIDE.md | 6 +- docs/index.md | 1 + docs/resources/account_role.md | 67 ++++++ docs/resources/grant_account_role.md | 10 +- docs/resources/grant_application_role.md | 4 +- docs/resources/grant_database_role.md | 4 +- docs/resources/grant_ownership.md | 18 +- .../grant_privileges_to_account_role.md | 36 +-- docs/resources/role.md | 6 +- examples/additional/deprecated_resources.MD | 1 + .../snowflake_account_role/import.sh | 1 + .../snowflake_account_role/resource.tf | 10 + .../snowflake_grant_account_role/resource.tf | 10 +- .../resource.tf | 4 +- .../snowflake_grant_database_role/resource.tf | 4 +- .../snowflake_grant_ownership/resource.tf | 18 +- .../resource.tf | 36 +-- pkg/acceptance/check_destroy.go | 3 + pkg/datasources/roles.go | 10 +- pkg/datasources/roles_acceptance_test.go | 6 +- ...erate_scim_access_token_acceptance_test.go | 2 +- .../TestAcc_AccountRoles_Complete/test.tf | 23 -- .../testdata/TestAcc_Roles_Complete/test.tf | 23 ++ .../variables.tf | 0 pkg/provider/provider.go | 56 ++--- pkg/provider/resources/resources.go | 1 + pkg/resources/account_role.go | 200 +++++++++++++++++ pkg/resources/account_role_acceptance_test.go | 207 ++++++++++++++++++ .../grant_ownership_acceptance_test.go | 2 +- .../object_parameter_acceptance_test.go | 4 + pkg/resources/role.go | 198 +---------------- pkg/resources/role_acceptance_test.go | 207 ------------------ .../TestAcc_AccountRole_basic/test.tf | 2 +- .../TestAcc_AccountRole_updates/test.tf | 2 +- .../account_role/test.tf | 8 +- .../TestAcc_GrantAccountRole/user/test.tf | 4 +- .../account_role/test.tf | 4 +- .../test.tf | 4 +- .../test.tf | 4 +- .../test.tf | 6 +- .../TestAcc_GrantOwnership/OnAllPipes/test.tf | 4 +- .../TestAcc_GrantOwnership/OnAllTasks/test.tf | 4 +- .../OnAll_InDatabase_ToAccountRole/test.tf | 4 +- .../OnAll_InSchema_ToAccountRole/test.tf | 4 +- .../OnFuture_InDatabase_ToAccountRole/test.tf | 4 +- .../OnFuture_InSchema_ToAccountRole/test.tf | 4 +- .../test.tf | 4 +- .../OnObject_Database_ToAccountRole/test.tf | 4 +- .../test.tf | 4 +- .../test.tf | 4 +- .../OnObject_Schema_ToAccountRole/test.tf | 4 +- .../OnObject_Table_ToAccountRole/test.tf | 4 +- .../TestAcc_GrantOwnership/OnPipe/test.tf | 4 +- .../TestAcc_GrantOwnership/OnTask/test.tf | 4 +- .../OnTask_Discussion2877/1/test.tf | 4 +- .../OnTask_Discussion2877/2/test.tf | 6 +- .../OnTask_Discussion2877/3/test.tf | 2 +- .../OnTask_Discussion2877/4/test.tf | 4 +- .../RoleBasedAccessControlUseCase/test.tf | 6 +- .../ImportedPrivileges/test.tf | 4 +- .../ImportedPrivileges/test.tf | 4 +- pkg/resources/view_acceptance_test.go | 2 +- .../{role.md.tmpl => account_role.md.tmpl} | 0 63 files changed, 699 insertions(+), 601 deletions(-) create mode 100644 docs/resources/account_role.md create mode 100644 examples/resources/snowflake_account_role/import.sh create mode 100644 examples/resources/snowflake_account_role/resource.tf delete mode 100644 pkg/datasources/testdata/TestAcc_AccountRoles_Complete/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_Roles_Complete/test.tf rename pkg/datasources/testdata/{TestAcc_AccountRoles_Complete => TestAcc_Roles_Complete}/variables.tf (100%) create mode 100644 pkg/resources/account_role.go create mode 100644 pkg/resources/account_role_acceptance_test.go delete mode 100644 pkg/resources/role_acceptance_test.go rename templates/resources/{role.md.tmpl => account_role.md.tmpl} (100%) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 35fde4d83e..c7aac5228b 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -20,10 +20,10 @@ They are all described in short in the [changes before v1 doc](./v1-preparations ### old grant resources removal Following the [announcement](https://github.com/Snowflake-Labs/terraform-provider-snowflake/discussions/2736) we have removed the old grant resources. The two resources [snowflake_role_ownership_grant](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_ownership_grant) and [snowflake_user_ownership_grant](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/user_ownership_grant) were not listed in the announcement, but they were also marked as deprecated ones. We are removing them too to conclude the grants redesign saga. +### *(new feature)* new snowflake_account_role resource -### *(new feature)* new field in the snowflake_role resource - -No migration is needed. +Already existing `snowflake_role` was deprecated in favor of the new `snowflake_account_role`. The old resource got upgraded to +have the same features as the new one. The only difference is the deprecation message on the old resource. New fields: - added `show_output` field that holds the response from SHOW ROLES. Remember that the field will be only recomputed if one of the fields (`name` or `comment`) are changed. diff --git a/docs/index.md b/docs/index.md index 0bc8493349..6219e19331 100644 --- a/docs/index.md +++ b/docs/index.md @@ -231,6 +231,7 @@ The Snowflake provider will use the following order of precedence when determini - [snowflake_database_old](./docs/resources/database_old) - [snowflake_oauth_integration](./docs/resources/oauth_integration) +- [snowflake_role](./docs/resources/role) - use [snowflake_account_role](./docs/resources/account_role) instead - [snowflake_saml_integration](./docs/resources/saml_integration) - use [snowflake_saml2_integration](./docs/resources/saml2_integration) instead - [snowflake_unsafe_execute](./docs/resources/unsafe_execute) diff --git a/docs/resources/account_role.md b/docs/resources/account_role.md new file mode 100644 index 0000000000..6395b792b1 --- /dev/null +++ b/docs/resources/account_role.md @@ -0,0 +1,67 @@ +--- +page_title: "snowflake_account_role Resource - terraform-provider-snowflake" +subcategory: "" +description: |- + The resource is used for role management, where roles can be assigned privileges and, in turn, granted to users and other roles. When granted to roles they can create hierarchies of privilege structures. For more details, refer to the official documentation https://docs.snowflake.com/en/user-guide/security-access-control-overview. +--- + +!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v0920--v0930) to use it. + +# snowflake_account_role (Resource) + +The resource is used for role management, where roles can be assigned privileges and, in turn, granted to users and other roles. When granted to roles they can create hierarchies of privilege structures. For more details, refer to the [official documentation](https://docs.snowflake.com/en/user-guide/security-access-control-overview). + +## Example Usage + +```terraform +## Minimal +resource "snowflake_account_role" "minimal" { + name = "role_name" +} + +## Complete (with every optional set) +resource "snowflake_account_role" "complete" { + name = "role_name" + comment = "my account role" +} +``` + + +## Schema + +### Required + +- `name` (String) + +### Optional + +- `comment` (String) + +### Read-Only + +- `id` (String) The ID of this resource. +- `show_output` (List of Object) Outputs the result of `SHOW ROLES` for the given role. (see [below for nested schema](#nestedatt--show_output)) + + +### Nested Schema for `show_output` + +Read-Only: + +- `assigned_to_users` (Number) +- `comment` (String) +- `created_on` (String) +- `granted_roles` (Number) +- `granted_to_roles` (Number) +- `is_current` (Boolean) +- `is_default` (Boolean) +- `is_inherited` (Boolean) +- `name` (String) +- `owner` (String) + +## Import + +Import is supported using the following syntax: + +```shell +terraform import snowflake_account_role.example "name" +``` diff --git a/docs/resources/grant_account_role.md b/docs/resources/grant_account_role.md index a808c8442e..57f6d4100c 100644 --- a/docs/resources/grant_account_role.md +++ b/docs/resources/grant_account_role.md @@ -16,17 +16,17 @@ description: |- ### grant account role to account role ################################## -resource "snowflake_role" "role" { +resource "snowflake_account_role" "role" { name = var.role_name } -resource "snowflake_role" "parent_role" { +resource "snowflake_account_role" "parent_role" { name = var.parent_role_name } resource "snowflake_grant_account_role" "g" { - role_name = snowflake_role.role.name - parent_role_name = snowflake_role.parent_role.name + role_name = snowflake_account_role.role.name + parent_role_name = snowflake_account_role.parent_role.name } @@ -34,7 +34,7 @@ resource "snowflake_grant_account_role" "g" { ### grant account role to user ################################## -resource "snowflake_role" "role" { +resource "snowflake_account_role" "role" { name = var.role_name } diff --git a/docs/resources/grant_application_role.md b/docs/resources/grant_application_role.md index cf23749b39..73066d2428 100644 --- a/docs/resources/grant_application_role.md +++ b/docs/resources/grant_application_role.md @@ -21,13 +21,13 @@ locals { ################################## -resource "snowflake_role" "role" { +resource "snowflake_account_role" "role" { name = "my_role" } resource "snowflake_grant_application_role" "g" { application_role_name = local.application_role_identifier - parent_account_role_name = snowflake_role.role.name + parent_account_role_name = snowflake_account_role.role.name } ################################## diff --git a/docs/resources/grant_database_role.md b/docs/resources/grant_database_role.md index 5a50d83c7d..fb6d9c63de 100644 --- a/docs/resources/grant_database_role.md +++ b/docs/resources/grant_database_role.md @@ -21,13 +21,13 @@ resource "snowflake_database_role" "database_role" { name = var.database_role_name } -resource "snowflake_role" "parent_role" { +resource "snowflake_account_role" "parent_role" { name = var.parent_role_name } resource "snowflake_grant_database_role" "g" { database_role_name = "\"${var.database}\".\"${snowflake_database_role.database_role.name}\"" - parent_role_name = snowflake_role.parent_role.name + parent_role_name = snowflake_account_role.parent_role.name } ################################## diff --git a/docs/resources/grant_ownership.md b/docs/resources/grant_ownership.md index 04daa50dbc..d58aa26be1 100644 --- a/docs/resources/grant_ownership.md +++ b/docs/resources/grant_ownership.md @@ -21,7 +21,7 @@ description: |- ### on object to account role ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "test_role" } @@ -74,7 +74,7 @@ resource "snowflake_grant_ownership" "test" { ### on all tables in database to account role ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "test_role" } @@ -96,7 +96,7 @@ resource "snowflake_grant_ownership" "test" { ### on all tables in schema to account role ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "test_role" } @@ -123,7 +123,7 @@ resource "snowflake_grant_ownership" "test" { ### on future tables in database to account role ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "test_role" } @@ -145,7 +145,7 @@ resource "snowflake_grant_ownership" "test" { ### on future tables in schema to account role ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "test_role" } @@ -172,7 +172,7 @@ resource "snowflake_grant_ownership" "test" { ### RoleBasedAccessControl (RBAC example) ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "role" } @@ -181,7 +181,7 @@ resource "snowflake_database" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "DATABASE" object_name = snowflake_database.test.name @@ -189,14 +189,14 @@ resource "snowflake_grant_ownership" "test" { } resource "snowflake_grant_account_role" "test" { - role_name = snowflake_role.test.name + role_name = snowflake_account_role.test.name user_name = "username" } provider "snowflake" { profile = "default" alias = "secondary" - role = snowflake_role.test.name + role = snowflake_account_role.test.name } ## With ownership on the database, the secondary provider is able to create schema on it without any additional privileges. diff --git a/docs/resources/grant_privileges_to_account_role.md b/docs/resources/grant_privileges_to_account_role.md index 8c843935e3..d81fcba923 100644 --- a/docs/resources/grant_privileges_to_account_role.md +++ b/docs/resources/grant_privileges_to_account_role.md @@ -22,7 +22,7 @@ resource "snowflake_database" "db" { name = "database" } -resource "snowflake_role" "db_role" { +resource "snowflake_account_role" "db_role" { name = "role_name" } @@ -33,7 +33,7 @@ resource "snowflake_role" "db_role" { # list of privileges resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["CREATE DATABASE", "CREATE USER"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account = true } @@ -41,7 +41,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account = true all_privileges = true with_grant_option = true @@ -51,7 +51,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option + always apply resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account = true always_apply = true all_privileges = true @@ -67,7 +67,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # list of privileges resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["CREATE SCHEMA", "CREATE DATABASE ROLE"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account_object { object_type = "DATABASE" object_name = snowflake_database.db.name @@ -78,7 +78,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account_object { object_type = "DATABASE" object_name = snowflake_database.db.name @@ -91,7 +91,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # grant IMPORTED PRIVILEGES on SNOWFLAKE application resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name privileges = ["IMPORTED PRIVILEGES"] on_account_object { object_type = "DATABASE" # All applications should be using DATABASE object_type @@ -103,7 +103,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option + always apply resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account_object { object_type = "DATABASE" object_name = snowflake_database.db.name @@ -122,7 +122,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # list of privileges resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema { schema_name = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! } @@ -132,7 +132,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema { schema_name = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! } @@ -145,7 +145,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all schemas in database resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema { all_schemas_in_database = snowflake_database.db.name } @@ -156,7 +156,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # future schemas in database resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema { future_schemas_in_database = snowflake_database.db.name } @@ -171,7 +171,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # list of privileges resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["SELECT", "REFERENCES"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { object_type = "VIEW" object_name = "\"${snowflake_database.db.name}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! @@ -182,7 +182,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { object_type = "VIEW" object_name = "\"${snowflake_database.db.name}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! @@ -196,7 +196,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all in database resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["SELECT", "INSERT"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { all { object_type_plural = "TABLES" @@ -210,7 +210,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all in schema resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["SELECT", "INSERT"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { all { object_type_plural = "TABLES" @@ -224,7 +224,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # future in database resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["SELECT", "INSERT"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { future { object_type_plural = "TABLES" @@ -238,7 +238,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # future in schema resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["SELECT", "INSERT"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { future { object_type_plural = "TABLES" diff --git a/docs/resources/role.md b/docs/resources/role.md index 2afc44dcef..28187f91b5 100644 --- a/docs/resources/role.md +++ b/docs/resources/role.md @@ -2,14 +2,14 @@ page_title: "snowflake_role Resource - terraform-provider-snowflake" subcategory: "" description: |- - + The resource is used for role management, where roles can be assigned privileges and, in turn, granted to users and other roles. When granted to roles they can create hierarchies of privilege structures. For more details, refer to the official documentation https://docs.snowflake.com/en/user-guide/security-access-control-overview. --- -!> **V1 release candidate** This resource was reworked and is a release candidate for the V1. We do not expect significant changes in it before the V1. We will welcome any feedback and adjust the resource if needed. Any errors reported will be resolved with a higher priority. We encourage checking this resource out before the V1 release. Please follow the [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/MIGRATION_GUIDE.md#v0920--v0930) to use it. - # snowflake_role (Resource) +~> **Deprecation** This resource is deprecated and will be removed in a future major version release. Please use [snowflake_account_role](./account_role) instead. +The resource is used for role management, where roles can be assigned privileges and, in turn, granted to users and other roles. When granted to roles they can create hierarchies of privilege structures. For more details, refer to the [official documentation](https://docs.snowflake.com/en/user-guide/security-access-control-overview). ## Example Usage diff --git a/examples/additional/deprecated_resources.MD b/examples/additional/deprecated_resources.MD index e33ef71107..a8e8144389 100644 --- a/examples/additional/deprecated_resources.MD +++ b/examples/additional/deprecated_resources.MD @@ -2,5 +2,6 @@ - [snowflake_database_old](./docs/resources/database_old) - [snowflake_oauth_integration](./docs/resources/oauth_integration) +- [snowflake_role](./docs/resources/role) - use [snowflake_account_role](./docs/resources/account_role) instead - [snowflake_saml_integration](./docs/resources/saml_integration) - use [snowflake_saml2_integration](./docs/resources/saml2_integration) instead - [snowflake_unsafe_execute](./docs/resources/unsafe_execute) diff --git a/examples/resources/snowflake_account_role/import.sh b/examples/resources/snowflake_account_role/import.sh new file mode 100644 index 0000000000..d7d6ebddbe --- /dev/null +++ b/examples/resources/snowflake_account_role/import.sh @@ -0,0 +1 @@ +terraform import snowflake_account_role.example "name" diff --git a/examples/resources/snowflake_account_role/resource.tf b/examples/resources/snowflake_account_role/resource.tf new file mode 100644 index 0000000000..5ceb171a6d --- /dev/null +++ b/examples/resources/snowflake_account_role/resource.tf @@ -0,0 +1,10 @@ +## Minimal +resource "snowflake_account_role" "minimal" { + name = "role_name" +} + +## Complete (with every optional set) +resource "snowflake_account_role" "complete" { + name = "role_name" + comment = "my account role" +} diff --git a/examples/resources/snowflake_grant_account_role/resource.tf b/examples/resources/snowflake_grant_account_role/resource.tf index 75e7891cc9..d07d79afe7 100644 --- a/examples/resources/snowflake_grant_account_role/resource.tf +++ b/examples/resources/snowflake_grant_account_role/resource.tf @@ -2,17 +2,17 @@ ### grant account role to account role ################################## -resource "snowflake_role" "role" { +resource "snowflake_account_role" "role" { name = var.role_name } -resource "snowflake_role" "parent_role" { +resource "snowflake_account_role" "parent_role" { name = var.parent_role_name } resource "snowflake_grant_account_role" "g" { - role_name = snowflake_role.role.name - parent_role_name = snowflake_role.parent_role.name + role_name = snowflake_account_role.role.name + parent_role_name = snowflake_account_role.parent_role.name } @@ -20,7 +20,7 @@ resource "snowflake_grant_account_role" "g" { ### grant account role to user ################################## -resource "snowflake_role" "role" { +resource "snowflake_account_role" "role" { name = var.role_name } diff --git a/examples/resources/snowflake_grant_application_role/resource.tf b/examples/resources/snowflake_grant_application_role/resource.tf index 354352e105..e7d0d2accd 100644 --- a/examples/resources/snowflake_grant_application_role/resource.tf +++ b/examples/resources/snowflake_grant_application_role/resource.tf @@ -7,13 +7,13 @@ locals { ################################## -resource "snowflake_role" "role" { +resource "snowflake_account_role" "role" { name = "my_role" } resource "snowflake_grant_application_role" "g" { application_role_name = local.application_role_identifier - parent_account_role_name = snowflake_role.role.name + parent_account_role_name = snowflake_account_role.role.name } ################################## diff --git a/examples/resources/snowflake_grant_database_role/resource.tf b/examples/resources/snowflake_grant_database_role/resource.tf index f3f331cf05..b61239c538 100644 --- a/examples/resources/snowflake_grant_database_role/resource.tf +++ b/examples/resources/snowflake_grant_database_role/resource.tf @@ -7,13 +7,13 @@ resource "snowflake_database_role" "database_role" { name = var.database_role_name } -resource "snowflake_role" "parent_role" { +resource "snowflake_account_role" "parent_role" { name = var.parent_role_name } resource "snowflake_grant_database_role" "g" { database_role_name = "\"${var.database}\".\"${snowflake_database_role.database_role.name}\"" - parent_role_name = snowflake_role.parent_role.name + parent_role_name = snowflake_account_role.parent_role.name } ################################## diff --git a/examples/resources/snowflake_grant_ownership/resource.tf b/examples/resources/snowflake_grant_ownership/resource.tf index 72890f6eed..151fff91ec 100644 --- a/examples/resources/snowflake_grant_ownership/resource.tf +++ b/examples/resources/snowflake_grant_ownership/resource.tf @@ -2,7 +2,7 @@ ### on object to account role ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "test_role" } @@ -55,7 +55,7 @@ resource "snowflake_grant_ownership" "test" { ### on all tables in database to account role ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "test_role" } @@ -77,7 +77,7 @@ resource "snowflake_grant_ownership" "test" { ### on all tables in schema to account role ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "test_role" } @@ -104,7 +104,7 @@ resource "snowflake_grant_ownership" "test" { ### on future tables in database to account role ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "test_role" } @@ -126,7 +126,7 @@ resource "snowflake_grant_ownership" "test" { ### on future tables in schema to account role ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "test_role" } @@ -153,7 +153,7 @@ resource "snowflake_grant_ownership" "test" { ### RoleBasedAccessControl (RBAC example) ################################## -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "role" } @@ -162,7 +162,7 @@ resource "snowflake_database" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "DATABASE" object_name = snowflake_database.test.name @@ -170,14 +170,14 @@ resource "snowflake_grant_ownership" "test" { } resource "snowflake_grant_account_role" "test" { - role_name = snowflake_role.test.name + role_name = snowflake_account_role.test.name user_name = "username" } provider "snowflake" { profile = "default" alias = "secondary" - role = snowflake_role.test.name + role = snowflake_account_role.test.name } ## With ownership on the database, the secondary provider is able to create schema on it without any additional privileges. diff --git a/examples/resources/snowflake_grant_privileges_to_account_role/resource.tf b/examples/resources/snowflake_grant_privileges_to_account_role/resource.tf index 05a5805bd3..d719359907 100644 --- a/examples/resources/snowflake_grant_privileges_to_account_role/resource.tf +++ b/examples/resources/snowflake_grant_privileges_to_account_role/resource.tf @@ -2,7 +2,7 @@ resource "snowflake_database" "db" { name = "database" } -resource "snowflake_role" "db_role" { +resource "snowflake_account_role" "db_role" { name = "role_name" } @@ -13,7 +13,7 @@ resource "snowflake_role" "db_role" { # list of privileges resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["CREATE DATABASE", "CREATE USER"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account = true } @@ -21,7 +21,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account = true all_privileges = true with_grant_option = true @@ -31,7 +31,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option + always apply resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account = true always_apply = true all_privileges = true @@ -47,7 +47,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # list of privileges resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["CREATE SCHEMA", "CREATE DATABASE ROLE"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account_object { object_type = "DATABASE" object_name = snowflake_database.db.name @@ -58,7 +58,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account_object { object_type = "DATABASE" object_name = snowflake_database.db.name @@ -71,7 +71,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # grant IMPORTED PRIVILEGES on SNOWFLAKE application resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name privileges = ["IMPORTED PRIVILEGES"] on_account_object { object_type = "DATABASE" # All applications should be using DATABASE object_type @@ -83,7 +83,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option + always apply resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_account_object { object_type = "DATABASE" object_name = snowflake_database.db.name @@ -102,7 +102,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # list of privileges resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema { schema_name = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! } @@ -112,7 +112,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema { schema_name = "\"${snowflake_database.db.name}\".\"my_schema\"" # note this is a fully qualified name! } @@ -125,7 +125,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all schemas in database resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema { all_schemas_in_database = snowflake_database.db.name } @@ -136,7 +136,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # future schemas in database resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["MODIFY", "CREATE TABLE"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema { future_schemas_in_database = snowflake_database.db.name } @@ -151,7 +151,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # list of privileges resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["SELECT", "REFERENCES"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { object_type = "VIEW" object_name = "\"${snowflake_database.db.name}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! @@ -162,7 +162,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all privileges + grant option resource "snowflake_grant_privileges_to_account_role" "example" { - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { object_type = "VIEW" object_name = "\"${snowflake_database.db.name}\".\"my_schema\".\"my_view\"" # note this is a fully qualified name! @@ -176,7 +176,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all in database resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["SELECT", "INSERT"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { all { object_type_plural = "TABLES" @@ -190,7 +190,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # all in schema resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["SELECT", "INSERT"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { all { object_type_plural = "TABLES" @@ -204,7 +204,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # future in database resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["SELECT", "INSERT"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { future { object_type_plural = "TABLES" @@ -218,7 +218,7 @@ resource "snowflake_grant_privileges_to_account_role" "example" { # future in schema resource "snowflake_grant_privileges_to_account_role" "example" { privileges = ["SELECT", "INSERT"] - account_role_name = snowflake_role.db_role.name + account_role_name = snowflake_account_role.db_role.name on_schema_object { future { object_type_plural = "TABLES" diff --git a/pkg/acceptance/check_destroy.go b/pkg/acceptance/check_destroy.go index 5483146d8b..2d730efd0a 100644 --- a/pkg/acceptance/check_destroy.go +++ b/pkg/acceptance/check_destroy.go @@ -64,6 +64,9 @@ var showByIdFunctions = map[resources.Resource]showByIdFunc{ resources.Account: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.Accounts.ShowByID) }, + resources.AccountRole: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { + return runShowById(ctx, id, client.Roles.ShowByID) + }, resources.Alert: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.Alerts.ShowByID) }, diff --git a/pkg/datasources/roles.go b/pkg/datasources/roles.go index ea59ce540c..085544684d 100644 --- a/pkg/datasources/roles.go +++ b/pkg/datasources/roles.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -var accountRolesSchema = map[string]*schema.Schema{ +var rolesSchema = map[string]*schema.Schema{ "like": { Type: schema.TypeString, Optional: true, @@ -46,13 +46,13 @@ var accountRolesSchema = map[string]*schema.Schema{ func Roles() *schema.Resource { return &schema.Resource{ - ReadContext: ReadAccountRoles, - Schema: accountRolesSchema, + ReadContext: ReadRoles, + Schema: rolesSchema, Description: "Datasource used to get details of filtered roles. Filtering is aligned with the current possibilities for [SHOW ROLES](https://docs.snowflake.com/en/sql-reference/sql/show-roles) query (`like` and `in_class` are all supported). The results of SHOW are encapsulated in one output collection.", } } -func ReadAccountRoles(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { +func ReadRoles(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { client := meta.(*provider.Context).Client req := sdk.NewShowRoleRequest() @@ -72,7 +72,7 @@ func ReadAccountRoles(ctx context.Context, d *schema.ResourceData, meta any) dia return diag.Diagnostics{ diag.Diagnostic{ Severity: diag.Error, - Summary: "Failed to show account roles", + Summary: "Failed to show roles", Detail: fmt.Sprintf("Error: %s", err), }, } diff --git a/pkg/datasources/roles_acceptance_test.go b/pkg/datasources/roles_acceptance_test.go index 8800d24014..40f3b50a5a 100644 --- a/pkg/datasources/roles_acceptance_test.go +++ b/pkg/datasources/roles_acceptance_test.go @@ -15,7 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/tfversion" ) -func TestAcc_AccountRoles_Complete(t *testing.T) { +func TestAcc_Roles_Complete(t *testing.T) { accountRoleNamePrefix := random.AlphaN(10) accountRoleName1 := acc.TestClient().Ids.AlphaWithPrefix(accountRoleNamePrefix + "1") accountRoleName2 := acc.TestClient().Ids.AlphaWithPrefix(accountRoleNamePrefix + "2") @@ -33,8 +33,8 @@ func TestAcc_AccountRoles_Complete(t *testing.T) { likeVariables["like"] = config.StringVariable(accountRoleNamePrefix + "%") // TODO(SNOW-1353303): Add test case for instance classes after they're available in the provider - inClassVariables := maps.Clone(commonVariables) - inClassVariables["in_class"] = config.StringVariable("TODO") + // inClassVariables := maps.Clone(commonVariables) + // inClassVariables["in_class"] = config.StringVariable("") resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, diff --git a/pkg/datasources/system_generate_scim_access_token_acceptance_test.go b/pkg/datasources/system_generate_scim_access_token_acceptance_test.go index f7ecbaefc2..de90ade47f 100644 --- a/pkg/datasources/system_generate_scim_access_token_acceptance_test.go +++ b/pkg/datasources/system_generate_scim_access_token_acceptance_test.go @@ -33,7 +33,7 @@ func TestAcc_SystemGenerateSCIMAccessToken(t *testing.T) { func generateAccessTokenConfig(name string) string { return fmt.Sprintf(` - resource "snowflake_role" "azured" { + resource "snowflake_account_role" "azured" { name = "AAD_PROVISIONER" comment = "test comment" } diff --git a/pkg/datasources/testdata/TestAcc_AccountRoles_Complete/test.tf b/pkg/datasources/testdata/TestAcc_AccountRoles_Complete/test.tf deleted file mode 100644 index 50927990e3..0000000000 --- a/pkg/datasources/testdata/TestAcc_AccountRoles_Complete/test.tf +++ /dev/null @@ -1,23 +0,0 @@ -resource "snowflake_role" "test1" { - name = var.account_role_name_1 - comment = var.comment -} - -resource "snowflake_role" "test2" { - name = var.account_role_name_2 - comment = var.comment -} - -resource "snowflake_role" "test3" { - name = var.account_role_name_3 - comment = var.comment -} - -data "snowflake_roles" "test" { - depends_on = [ - snowflake_role.test1, - snowflake_role.test2, - snowflake_role.test3, - ] - like = var.like -} diff --git a/pkg/datasources/testdata/TestAcc_Roles_Complete/test.tf b/pkg/datasources/testdata/TestAcc_Roles_Complete/test.tf new file mode 100644 index 0000000000..68afff3b58 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_Roles_Complete/test.tf @@ -0,0 +1,23 @@ +resource "snowflake_account_role" "test1" { + name = var.account_role_name_1 + comment = var.comment +} + +resource "snowflake_account_role" "test2" { + name = var.account_role_name_2 + comment = var.comment +} + +resource "snowflake_account_role" "test3" { + name = var.account_role_name_3 + comment = var.comment +} + +data "snowflake_account_roles" "test" { + depends_on = [ + snowflake_account_role.test1, + snowflake_account_role.test2, + snowflake_account_role.test3, + ] + like = var.like +} diff --git a/pkg/datasources/testdata/TestAcc_AccountRoles_Complete/variables.tf b/pkg/datasources/testdata/TestAcc_Roles_Complete/variables.tf similarity index 100% rename from pkg/datasources/testdata/TestAcc_AccountRoles_Complete/variables.tf rename to pkg/datasources/testdata/TestAcc_Roles_Complete/variables.tf diff --git a/pkg/provider/provider.go b/pkg/provider/provider.go index 480c3aebf9..b454c8c032 100644 --- a/pkg/provider/provider.go +++ b/pkg/provider/provider.go @@ -422,6 +422,7 @@ func Provider() *schema.Provider { func getResources() map[string]*schema.Resource { return map[string]*schema.Resource{ "snowflake_account": resources.Account(), + "snowflake_account_role": resources.AccountRole(), "snowflake_account_password_policy_attachment": resources.AccountPasswordPolicyAttachment(), "snowflake_account_parameter": resources.AccountParameter(), "snowflake_alert": resources.Alert(), @@ -463,34 +464,33 @@ func getResources() map[string]*schema.Resource { "snowflake_pipe": resources.Pipe(), "snowflake_procedure": resources.Procedure(), "snowflake_resource_monitor": resources.ResourceMonitor(), - // TODO: Should it be account role ??? - "snowflake_role": resources.Role(), - "snowflake_row_access_policy": resources.RowAccessPolicy(), - "snowflake_saml_integration": resources.SAMLIntegration(), - "snowflake_saml2_integration": resources.SAML2Integration(), - "snowflake_schema": resources.Schema(), - "snowflake_scim_integration": resources.SCIMIntegration(), - "snowflake_secondary_database": resources.SecondaryDatabase(), - "snowflake_sequence": resources.Sequence(), - "snowflake_session_parameter": resources.SessionParameter(), - "snowflake_share": resources.Share(), - "snowflake_shared_database": resources.SharedDatabase(), - "snowflake_stage": resources.Stage(), - "snowflake_storage_integration": resources.StorageIntegration(), - "snowflake_stream": resources.Stream(), - "snowflake_table": resources.Table(), - "snowflake_table_column_masking_policy_application": resources.TableColumnMaskingPolicyApplication(), - "snowflake_table_constraint": resources.TableConstraint(), - "snowflake_tag": resources.Tag(), - "snowflake_tag_association": resources.TagAssociation(), - "snowflake_tag_masking_policy_association": resources.TagMaskingPolicyAssociation(), - "snowflake_task": resources.Task(), - "snowflake_unsafe_execute": resources.UnsafeExecute(), - "snowflake_user": resources.User(), - "snowflake_user_password_policy_attachment": resources.UserPasswordPolicyAttachment(), - "snowflake_user_public_keys": resources.UserPublicKeys(), - "snowflake_view": resources.View(), - "snowflake_warehouse": resources.Warehouse(), + "snowflake_role": resources.Role(), + "snowflake_row_access_policy": resources.RowAccessPolicy(), + "snowflake_saml_integration": resources.SAMLIntegration(), + "snowflake_saml2_integration": resources.SAML2Integration(), + "snowflake_schema": resources.Schema(), + "snowflake_scim_integration": resources.SCIMIntegration(), + "snowflake_secondary_database": resources.SecondaryDatabase(), + "snowflake_sequence": resources.Sequence(), + "snowflake_session_parameter": resources.SessionParameter(), + "snowflake_share": resources.Share(), + "snowflake_shared_database": resources.SharedDatabase(), + "snowflake_stage": resources.Stage(), + "snowflake_storage_integration": resources.StorageIntegration(), + "snowflake_stream": resources.Stream(), + "snowflake_table": resources.Table(), + "snowflake_table_column_masking_policy_application": resources.TableColumnMaskingPolicyApplication(), + "snowflake_table_constraint": resources.TableConstraint(), + "snowflake_tag": resources.Tag(), + "snowflake_tag_association": resources.TagAssociation(), + "snowflake_tag_masking_policy_association": resources.TagMaskingPolicyAssociation(), + "snowflake_task": resources.Task(), + "snowflake_unsafe_execute": resources.UnsafeExecute(), + "snowflake_user": resources.User(), + "snowflake_user_password_policy_attachment": resources.UserPasswordPolicyAttachment(), + "snowflake_user_public_keys": resources.UserPublicKeys(), + "snowflake_view": resources.View(), + "snowflake_warehouse": resources.Warehouse(), } } diff --git a/pkg/provider/resources/resources.go b/pkg/provider/resources/resources.go index 07825cdad0..a96b996051 100644 --- a/pkg/provider/resources/resources.go +++ b/pkg/provider/resources/resources.go @@ -4,6 +4,7 @@ type resource string const ( Account resource = "snowflake_account" + AccountRole resource = "snowflake_account_role" Alert resource = "snowflake_alert" ApiIntegration resource = "snowflake_api_integration" CortexSearchService resource = "snowflake_cortex_search_service" diff --git a/pkg/resources/account_role.go b/pkg/resources/account_role.go new file mode 100644 index 0000000000..25f87ebf01 --- /dev/null +++ b/pkg/resources/account_role.go @@ -0,0 +1,200 @@ +package resources + +import ( + "context" + "errors" + "fmt" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +var accountRoleSchema = map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + // TODO(SNOW-999049): Uncomment once better identifier validation will be implemented + // ValidateDiagFunc: IsValidIdentifier[sdk.AccountObjectIdentifier](), + }, + "comment": { + Type: schema.TypeString, + Optional: true, + }, + ShowOutputAttributeName: { + Type: schema.TypeList, + Computed: true, + Description: "Outputs the result of `SHOW ROLES` for the given role.", + Elem: &schema.Resource{ + Schema: schemas.ShowRoleSchema, + }, + }, +} + +func AccountRole() *schema.Resource { + return &schema.Resource{ + Schema: accountRoleSchema, + + CreateContext: CreateAccountRole, + ReadContext: ReadAccountRole, + DeleteContext: DeleteAccountRole, + UpdateContext: UpdateAccountRole, + Description: "The resource is used for role management, where roles can be assigned privileges and, in turn, granted to users and other roles. When granted to roles they can create hierarchies of privilege structures. For more details, refer to the [official documentation](https://docs.snowflake.com/en/user-guide/security-access-control-overview).", + + CustomizeDiff: ComputedIfAnyAttributeChanged(ShowOutputAttributeName, "name", "comment"), + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + } +} + +func CreateAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client := meta.(*provider.Context).Client + + id := sdk.NewAccountObjectIdentifier(d.Get("name").(string)) + req := sdk.NewCreateRoleRequest(id) + + if v, ok := d.GetOk("comment"); ok { + req.WithComment(v.(string)) + } + + err := client.Roles.Create(ctx, req) + if err != nil { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Failed to create account role", + Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), + }, + } + } + + d.SetId(helpers.EncodeSnowflakeID(id)) + + return ReadAccountRole(ctx, d, meta) +} + +func ReadAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client := meta.(*provider.Context).Client + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) + + accountRole, err := client.Roles.ShowByID(ctx, id) + if err != nil { + if errors.Is(err, sdk.ErrObjectNotFound) { + d.SetId("") + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Warning, + Summary: "Account role not found; marking it as removed", + Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), + }, + } + } + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Failed to show account role by id", + Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), + }, + } + } + + if err := d.Set("name", sdk.NewAccountObjectIdentifier(accountRole.Name).Name()); err != nil { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Failed to set account role name", + Detail: fmt.Sprintf("Account role name: %s, err: %s", accountRole.Name, err), + }, + } + } + + if err := d.Set("comment", accountRole.Comment); err != nil { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Failed to set account role comment", + Detail: fmt.Sprintf("Account role name: %s, comment: %s, err: %s", accountRole.Name, accountRole.Comment, err), + }, + } + } + + if err = d.Set(ShowOutputAttributeName, []map[string]any{schemas.RoleToSchema(accountRole)}); err != nil { + return diag.FromErr(err) + } + + return nil +} + +func UpdateAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client := meta.(*provider.Context).Client + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) + + if d.HasChange("name") { + newId := sdk.NewAccountObjectIdentifier(d.Get("name").(string)) + + if err := client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithRenameTo(newId)); err != nil { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Failed to rename account role name", + Detail: fmt.Sprintf("Previous account role name: %s, new account role name: %s, err: %s", id.Name(), newId.Name(), err), + }, + } + } + + id = newId + d.SetId(helpers.EncodeSnowflakeID(newId)) + } + + if d.HasChange("comment") { + if v, ok := d.GetOk("comment"); ok { + if err := client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithSetComment(v.(string))); err != nil { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Failed to set account role comment", + Detail: fmt.Sprintf("Account role name: %s, comment: %s, err: %s", id.Name(), v, err), + }, + } + } + } else { + err := client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithUnsetComment(true)) + if err != nil { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Failed to unset account role comment", + Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), + }, + } + } + } + } + + return ReadAccountRole(ctx, d, meta) +} + +func DeleteAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client := meta.(*provider.Context).Client + id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) + + if err := client.Roles.Drop(ctx, sdk.NewDropRoleRequest(id).WithIfExists(true)); err != nil { + return diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Failed to drop account role", + Detail: fmt.Sprintf("Account role name: %s, err: %s", d.Id(), err), + }, + } + } + + d.SetId("") + + return nil +} diff --git a/pkg/resources/account_role_acceptance_test.go b/pkg/resources/account_role_acceptance_test.go new file mode 100644 index 0000000000..8a0dcf6800 --- /dev/null +++ b/pkg/resources/account_role_acceptance_test.go @@ -0,0 +1,207 @@ +package resources_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/importchecks" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/stretchr/testify/require" + + acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/tfversion" +) + +func TestAcc_AccountRole_Basic(t *testing.T) { + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() + comment := random.Comment() + + currentRole, err := acc.Client(t).ContextFunctions.CurrentRole(context.Background()) + require.NoError(t, err) + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + PreCheck: func() { acc.TestAccPreCheck(t) }, + CheckDestroy: acc.CheckDestroy(t, resources.AccountRole), + Steps: []resource.TestStep{ + // create with empty optionals + { + Config: accountRoleBasicConfig(id.Name(), ""), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_account_role.role", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "comment", ""), + + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.#", "1"), + resource.TestCheckResourceAttrSet("snowflake_account_role.role", "show_output.0.created_on"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_default", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_current", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_inherited", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.assigned_to_users", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.granted_to_roles", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.granted_roles", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.owner", currentRole.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.comment", ""), + ), + }, + // import - without optionals + { + Config: accountRoleBasicConfig(id.Name(), ""), + ResourceName: "snowflake_account_role.role", + ImportState: true, + ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "comment", ""), + ), + }, + // set optionals + { + Config: accountRoleBasicConfig(id.Name(), comment), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("snowflake_account_role.role", plancheck.ResourceActionUpdate), + }, + }, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_account_role.role", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "comment", comment), + + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.#", "1"), + resource.TestCheckResourceAttrSet("snowflake_account_role.role", "show_output.0.created_on"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_default", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_current", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_inherited", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.assigned_to_users", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.granted_to_roles", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.granted_roles", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.owner", currentRole.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.comment", comment), + ), + }, + // import - complete + { + Config: accountRoleBasicConfig(id.Name(), ""), + ResourceName: "snowflake_account_role.role", + ImportState: true, + ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "comment", comment), + ), + }, + // unset + { + Config: accountRoleBasicConfig(id.Name(), ""), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("snowflake_account_role.role", plancheck.ResourceActionUpdate), + }, + }, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_account_role.role", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "comment", ""), + + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.#", "1"), + resource.TestCheckResourceAttrSet("snowflake_account_role.role", "show_output.0.created_on"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_default", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_current", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_inherited", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.assigned_to_users", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.granted_to_roles", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.granted_roles", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.owner", currentRole.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.comment", ""), + ), + }, + }, + }) +} + +func TestAcc_AccountRole_Complete(t *testing.T) { + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() + comment := random.Comment() + + newId := acc.TestClient().Ids.RandomAccountObjectIdentifier() + newComment := random.Comment() + + currentRole, err := acc.Client(t).ContextFunctions.CurrentRole(context.Background()) + require.NoError(t, err) + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + PreCheck: func() { acc.TestAccPreCheck(t) }, + CheckDestroy: acc.CheckDestroy(t, resources.AccountRole), + Steps: []resource.TestStep{ + { + Config: accountRoleBasicConfig(id.Name(), comment), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_account_role.role", "name", id.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "comment", comment), + + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.#", "1"), + resource.TestCheckResourceAttrSet("snowflake_account_role.role", "show_output.0.created_on"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_default", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_current", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_inherited", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.assigned_to_users", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.granted_to_roles", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.granted_roles", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.owner", currentRole.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.comment", comment), + ), + }, + { + Config: accountRoleBasicConfig(id.Name(), ""), + ResourceName: "snowflake_account_role.role", + ImportState: true, + ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), + importchecks.TestCheckResourceAttrInstanceState(id.Name(), "comment", comment), + ), + }, + // rename + comment change + { + Config: accountRoleBasicConfig(newId.Name(), newComment), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("snowflake_account_role.role", "name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "comment", newComment), + + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.#", "1"), + resource.TestCheckResourceAttrSet("snowflake_account_role.role", "show_output.0.created_on"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.name", newId.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_default", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_current", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.is_inherited", "false"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.assigned_to_users", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.granted_to_roles", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.granted_roles", "0"), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.owner", currentRole.Name()), + resource.TestCheckResourceAttr("snowflake_account_role.role", "show_output.0.comment", newComment), + ), + }, + }, + }) +} + +func accountRoleBasicConfig(name, comment string) string { + s := ` +resource "snowflake_account_role" "role" { + name = "%s" + comment = "%s" +} +` + return fmt.Sprintf(s, name, comment) +} diff --git a/pkg/resources/grant_ownership_acceptance_test.go b/pkg/resources/grant_ownership_acceptance_test.go index d10d6051bd..2417174ddb 100644 --- a/pkg/resources/grant_ownership_acceptance_test.go +++ b/pkg/resources/grant_ownership_acceptance_test.go @@ -768,7 +768,7 @@ func TestAcc_GrantOwnership_RoleBasedAccessControlUseCase(t *testing.T) { func roleBasedAccessControlUseCaseConfig(accountRoleName string, databaseName string, userName string, schemaName string, withSecondaryProvider bool) string { baseConfig := fmt.Sprintf(` -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "%[1]s" } diff --git a/pkg/resources/object_parameter_acceptance_test.go b/pkg/resources/object_parameter_acceptance_test.go index a66b2ad437..02ea1d5994 100644 --- a/pkg/resources/object_parameter_acceptance_test.go +++ b/pkg/resources/object_parameter_acceptance_test.go @@ -2,6 +2,7 @@ package resources_test import ( "fmt" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "testing" acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" @@ -32,6 +33,9 @@ func TestAcc_ObjectParameter(t *testing.T) { } func TestAcc_ObjectParameterAccount(t *testing.T) { + t.Cleanup(func() { + acc.TestClient().Parameter.UnsetAccountParameter(t, sdk.AccountParameterDataRetentionTimeInDays) + }) resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, TerraformVersionChecks: []tfversion.TerraformVersionCheck{ diff --git a/pkg/resources/role.go b/pkg/resources/role.go index 5ce1a69fb7..443de76734 100644 --- a/pkg/resources/role.go +++ b/pkg/resources/role.go @@ -1,199 +1,9 @@ package resources -import ( - "context" - "errors" - "fmt" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/provider" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/schemas" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -var accountRoleSchema = map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - // TODO(SNOW-999049): Uncomment once better identifier validation will be implemented - // ValidateDiagFunc: IsValidIdentifier[sdk.AccountObjectIdentifier](), - }, - "comment": { - Type: schema.TypeString, - Optional: true, - }, - ShowOutputAttributeName: { - Type: schema.TypeList, - Computed: true, - Description: "Outputs the result of `SHOW ROLES` for the given role.", - Elem: &schema.Resource{ - Schema: schemas.ShowRoleSchema, - }, - }, -} +import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" func Role() *schema.Resource { - return &schema.Resource{ - Schema: accountRoleSchema, - - CreateContext: CreateAccountRole, - ReadContext: ReadAccountRole, - DeleteContext: DeleteAccountRole, - UpdateContext: UpdateAccountRole, - - CustomizeDiff: ComputedIfAnyAttributeChanged(ShowOutputAttributeName, "name", "comment"), - - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - } -} - -func CreateAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - client := meta.(*provider.Context).Client - - id := sdk.NewAccountObjectIdentifier(d.Get("name").(string)) - req := sdk.NewCreateRoleRequest(id) - - if v, ok := d.GetOk("comment"); ok { - req.WithComment(v.(string)) - } - - err := client.Roles.Create(ctx, req) - if err != nil { - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to create account role", - Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), - }, - } - } - - d.SetId(helpers.EncodeSnowflakeID(id)) - - return ReadAccountRole(ctx, d, meta) -} - -func ReadAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - client := meta.(*provider.Context).Client - id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) - - accountRole, err := client.Roles.ShowByID(ctx, id) - if err != nil { - if errors.Is(err, sdk.ErrObjectNotFound) { - d.SetId("") - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Warning, - Summary: "Account role not found; marking it as removed", - Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), - }, - } - } - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to show account role by id", - Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), - }, - } - } - - if err := d.Set("name", sdk.NewAccountObjectIdentifier(accountRole.Name).Name()); err != nil { - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to set account role name", - Detail: fmt.Sprintf("Account role name: %s, err: %s", accountRole.Name, err), - }, - } - } - - if err := d.Set("comment", accountRole.Comment); err != nil { - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to set account role comment", - Detail: fmt.Sprintf("Account role name: %s, comment: %s, err: %s", accountRole.Name, accountRole.Comment, err), - }, - } - } - - if err = d.Set(ShowOutputAttributeName, []map[string]any{schemas.RoleToSchema(accountRole)}); err != nil { - return diag.FromErr(err) - } - - return nil -} - -func UpdateAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - client := meta.(*provider.Context).Client - id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) - - if d.HasChange("name") { - newId := sdk.NewAccountObjectIdentifier(d.Get("name").(string)) - - if err := client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithRenameTo(newId)); err != nil { - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to rename account role name", - Detail: fmt.Sprintf("Previous account role name: %s, new account role name: %s, err: %s", id.Name(), newId.Name(), err), - }, - } - } - - id = newId - d.SetId(helpers.EncodeSnowflakeID(newId)) - } - - if d.HasChange("comment") { - if v, ok := d.GetOk("comment"); ok { - if err := client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithSetComment(v.(string))); err != nil { - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to set account role comment", - Detail: fmt.Sprintf("Account role name: %s, comment: %s, err: %s", id.Name(), v, err), - }, - } - } - } else { - err := client.Roles.Alter(ctx, sdk.NewAlterRoleRequest(id).WithUnsetComment(true)) - if err != nil { - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to unset account role comment", - Detail: fmt.Sprintf("Account role name: %s, err: %s", id.Name(), err), - }, - } - } - } - } - - return ReadAccountRole(ctx, d, meta) -} - -func DeleteAccountRole(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - client := meta.(*provider.Context).Client - id := helpers.DecodeSnowflakeID(d.Id()).(sdk.AccountObjectIdentifier) - - if err := client.Roles.Drop(ctx, sdk.NewDropRoleRequest(id).WithIfExists(true)); err != nil { - return diag.Diagnostics{ - diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to drop account role", - Detail: fmt.Sprintf("Account role name: %s, err: %s", d.Id(), err), - }, - } - } - - d.SetId("") - - return nil + accountRole := AccountRole() + accountRole.DeprecationMessage = "This resource is deprecated and will be removed in a future major version release. Please use snowflake_account_role instead." + return accountRole } diff --git a/pkg/resources/role_acceptance_test.go b/pkg/resources/role_acceptance_test.go deleted file mode 100644 index 2721153152..0000000000 --- a/pkg/resources/role_acceptance_test.go +++ /dev/null @@ -1,207 +0,0 @@ -package resources_test - -import ( - "context" - "fmt" - "testing" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/importchecks" - "github.com/hashicorp/terraform-plugin-testing/plancheck" - "github.com/stretchr/testify/require" - - acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" - - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/tfversion" -) - -func TestAcc_Role_Basic(t *testing.T) { - id := acc.TestClient().Ids.RandomAccountObjectIdentifier() - comment := random.Comment() - - currentRole, err := acc.Client(t).ContextFunctions.CurrentRole(context.Background()) - require.NoError(t, err) - - resource.Test(t, resource.TestCase{ - ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - PreCheck: func() { acc.TestAccPreCheck(t) }, - CheckDestroy: acc.CheckDestroy(t, resources.Role), - Steps: []resource.TestStep{ - // create with empty optionals - { - Config: roleBasicConfig(id.Name(), ""), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_role.role", "name", id.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "comment", ""), - - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.#", "1"), - resource.TestCheckResourceAttrSet("snowflake_role.role", "show_output.0.created_on"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.name", id.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_default", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_current", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_inherited", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.assigned_to_users", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_to_roles", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_roles", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.owner", currentRole.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.comment", ""), - ), - }, - // import - without optionals - { - Config: roleBasicConfig(id.Name(), ""), - ResourceName: "snowflake_role.role", - ImportState: true, - ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( - importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), - importchecks.TestCheckResourceAttrInstanceState(id.Name(), "comment", ""), - ), - }, - // set optionals - { - Config: roleBasicConfig(id.Name(), comment), - ConfigPlanChecks: resource.ConfigPlanChecks{ - PreApply: []plancheck.PlanCheck{ - plancheck.ExpectResourceAction("snowflake_role.role", plancheck.ResourceActionUpdate), - }, - }, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_role.role", "name", id.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "comment", comment), - - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.#", "1"), - resource.TestCheckResourceAttrSet("snowflake_role.role", "show_output.0.created_on"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.name", id.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_default", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_current", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_inherited", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.assigned_to_users", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_to_roles", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_roles", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.owner", currentRole.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.comment", comment), - ), - }, - // import - complete - { - Config: roleBasicConfig(id.Name(), ""), - ResourceName: "snowflake_role.role", - ImportState: true, - ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( - importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), - importchecks.TestCheckResourceAttrInstanceState(id.Name(), "comment", comment), - ), - }, - // unset - { - Config: roleBasicConfig(id.Name(), ""), - ConfigPlanChecks: resource.ConfigPlanChecks{ - PreApply: []plancheck.PlanCheck{ - plancheck.ExpectResourceAction("snowflake_role.role", plancheck.ResourceActionUpdate), - }, - }, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_role.role", "name", id.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "comment", ""), - - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.#", "1"), - resource.TestCheckResourceAttrSet("snowflake_role.role", "show_output.0.created_on"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.name", id.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_default", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_current", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_inherited", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.assigned_to_users", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_to_roles", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_roles", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.owner", currentRole.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.comment", ""), - ), - }, - }, - }) -} - -func TestAcc_Role_Complete(t *testing.T) { - id := acc.TestClient().Ids.RandomAccountObjectIdentifier() - comment := random.Comment() - - newId := acc.TestClient().Ids.RandomAccountObjectIdentifier() - newComment := random.Comment() - - currentRole, err := acc.Client(t).ContextFunctions.CurrentRole(context.Background()) - require.NoError(t, err) - - resource.Test(t, resource.TestCase{ - ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.RequireAbove(tfversion.Version1_5_0), - }, - PreCheck: func() { acc.TestAccPreCheck(t) }, - CheckDestroy: acc.CheckDestroy(t, resources.Role), - Steps: []resource.TestStep{ - { - Config: roleBasicConfig(id.Name(), comment), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_role.role", "name", id.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "comment", comment), - - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.#", "1"), - resource.TestCheckResourceAttrSet("snowflake_role.role", "show_output.0.created_on"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.name", id.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_default", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_current", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_inherited", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.assigned_to_users", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_to_roles", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_roles", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.owner", currentRole.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.comment", comment), - ), - }, - { - Config: roleBasicConfig(id.Name(), ""), - ResourceName: "snowflake_role.role", - ImportState: true, - ImportStateCheck: importchecks.ComposeAggregateImportStateCheck( - importchecks.TestCheckResourceAttrInstanceState(id.Name(), "name", id.Name()), - importchecks.TestCheckResourceAttrInstanceState(id.Name(), "comment", comment), - ), - }, - // rename + comment change - { - Config: roleBasicConfig(newId.Name(), newComment), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("snowflake_role.role", "name", newId.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "comment", newComment), - - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.#", "1"), - resource.TestCheckResourceAttrSet("snowflake_role.role", "show_output.0.created_on"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.name", newId.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_default", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_current", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.is_inherited", "false"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.assigned_to_users", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_to_roles", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.granted_roles", "0"), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.owner", currentRole.Name()), - resource.TestCheckResourceAttr("snowflake_role.role", "show_output.0.comment", newComment), - ), - }, - }, - }) -} - -func roleBasicConfig(name, comment string) string { - s := ` -resource "snowflake_role" "role" { - name = "%s" - comment = "%s" -} -` - return fmt.Sprintf(s, name, comment) -} diff --git a/pkg/resources/testdata/TestAcc_AccountRole_basic/test.tf b/pkg/resources/testdata/TestAcc_AccountRole_basic/test.tf index 7dac5cc2c3..1aa83161f4 100644 --- a/pkg/resources/testdata/TestAcc_AccountRole_basic/test.tf +++ b/pkg/resources/testdata/TestAcc_AccountRole_basic/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.name comment = var.comment } diff --git a/pkg/resources/testdata/TestAcc_AccountRole_updates/test.tf b/pkg/resources/testdata/TestAcc_AccountRole_updates/test.tf index 7dac5cc2c3..1aa83161f4 100644 --- a/pkg/resources/testdata/TestAcc_AccountRole_updates/test.tf +++ b/pkg/resources/testdata/TestAcc_AccountRole_updates/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.name comment = var.comment } diff --git a/pkg/resources/testdata/TestAcc_GrantAccountRole/account_role/test.tf b/pkg/resources/testdata/TestAcc_GrantAccountRole/account_role/test.tf index 6e13214569..7c715ff5b9 100644 --- a/pkg/resources/testdata/TestAcc_GrantAccountRole/account_role/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantAccountRole/account_role/test.tf @@ -6,15 +6,15 @@ variable "parent_role_name" { type = string } -resource "snowflake_role" "role" { +resource "snowflake_account_role" "role" { name = var.role_name } -resource "snowflake_role" "parent_role" { +resource "snowflake_account_role" "parent_role" { name = var.parent_role_name } resource "snowflake_grant_account_role" "g" { - role_name = snowflake_role.role.name - parent_role_name = snowflake_role.parent_role.name + role_name = snowflake_account_role.role.name + parent_role_name = snowflake_account_role.parent_role.name } diff --git a/pkg/resources/testdata/TestAcc_GrantAccountRole/user/test.tf b/pkg/resources/testdata/TestAcc_GrantAccountRole/user/test.tf index 4e200570f4..cec69f003d 100644 --- a/pkg/resources/testdata/TestAcc_GrantAccountRole/user/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantAccountRole/user/test.tf @@ -6,7 +6,7 @@ variable "user_name" { type = string } -resource "snowflake_role" "role" { +resource "snowflake_account_role" "role" { name = var.role_name } @@ -15,6 +15,6 @@ resource "snowflake_user" "user" { } resource "snowflake_grant_account_role" "g" { - role_name = snowflake_role.role.name + role_name = snowflake_account_role.role.name user_name = snowflake_user.user.name } diff --git a/pkg/resources/testdata/TestAcc_GrantDatabaseRole/account_role/test.tf b/pkg/resources/testdata/TestAcc_GrantDatabaseRole/account_role/test.tf index 4ed7e1936b..d3504d5e73 100644 --- a/pkg/resources/testdata/TestAcc_GrantDatabaseRole/account_role/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantDatabaseRole/account_role/test.tf @@ -15,11 +15,11 @@ resource "snowflake_database_role" "database_role" { name = var.database_role_name } -resource "snowflake_role" "parent_role" { +resource "snowflake_account_role" "parent_role" { name = var.parent_role_name } resource "snowflake_grant_database_role" "g" { database_role_name = "\"${var.database}\".\"${snowflake_database_role.database_role.name}\"" - parent_role_name = snowflake_role.parent_role.name + parent_role_name = snowflake_account_role.parent_role.name } diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/InvalidConfiguration_EmptyObjectType/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/InvalidConfiguration_EmptyObjectType/test.tf index 989b68472d..7c9746e237 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/InvalidConfiguration_EmptyObjectType/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/InvalidConfiguration_EmptyObjectType/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -7,7 +7,7 @@ resource "snowflake_database" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "" object_name = snowflake_database.test.name diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/InvalidConfiguration_MultipleTargets/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/InvalidConfiguration_MultipleTargets/test.tf index a1dd26c2e9..f79255d8c3 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/InvalidConfiguration_MultipleTargets/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/InvalidConfiguration_MultipleTargets/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -7,7 +7,7 @@ resource "snowflake_database" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "DATABASE" object_name = snowflake_database.test.name diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/MoveResourceOwnershipOutsideTerraform/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/MoveResourceOwnershipOutsideTerraform/test.tf index 219b1223d8..ac4a859008 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/MoveResourceOwnershipOutsideTerraform/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/MoveResourceOwnershipOutsideTerraform/test.tf @@ -1,8 +1,8 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } -resource "snowflake_role" "other_role" { +resource "snowflake_account_role" "other_role" { name = var.other_account_role_name } @@ -11,7 +11,7 @@ resource "snowflake_database" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "DATABASE" object_name = snowflake_database.test.name diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnAllPipes/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnAllPipes/test.tf index 9df0ff70be..dcf0934fb5 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnAllPipes/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnAllPipes/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -35,7 +35,7 @@ resource "snowflake_pipe" "second_test" { resource "snowflake_grant_ownership" "test" { depends_on = [snowflake_pipe.test, snowflake_pipe.second_test] - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { all { diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnAllTasks/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnAllTasks/test.tf index 6480a83dab..f4c901edaf 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnAllTasks/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnAllTasks/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -18,7 +18,7 @@ resource "snowflake_task" "second_test" { resource "snowflake_grant_ownership" "test" { depends_on = [snowflake_task.test, snowflake_task.second_test] - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { all { diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnAll_InDatabase_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnAll_InDatabase_ToAccountRole/test.tf index 122ad22fdb..bf2b48cb73 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnAll_InDatabase_ToAccountRole/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnAll_InDatabase_ToAccountRole/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -35,7 +35,7 @@ resource "snowflake_table" "test2" { resource "snowflake_grant_ownership" "test" { depends_on = [snowflake_table.test, snowflake_table.test2] - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { all { object_type_plural = "TABLES" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnAll_InSchema_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnAll_InSchema_ToAccountRole/test.tf index b77eb8f5cf..d698723ba7 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnAll_InSchema_ToAccountRole/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnAll_InSchema_ToAccountRole/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -35,7 +35,7 @@ resource "snowflake_table" "test2" { resource "snowflake_grant_ownership" "test" { depends_on = [snowflake_table.test, snowflake_table.test2] - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { all { object_type_plural = "TABLES" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnFuture_InDatabase_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnFuture_InDatabase_ToAccountRole/test.tf index 8fd47cd829..79bb4f3cab 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnFuture_InDatabase_ToAccountRole/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnFuture_InDatabase_ToAccountRole/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -7,7 +7,7 @@ resource "snowflake_database" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { future { object_type_plural = "TABLES" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnFuture_InSchema_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnFuture_InSchema_ToAccountRole/test.tf index db037510a9..8a5f2e707c 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnFuture_InSchema_ToAccountRole/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnFuture_InSchema_ToAccountRole/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -12,7 +12,7 @@ resource "snowflake_schema" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { future { object_type_plural = "TABLES" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_DatabaseRole_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_DatabaseRole_ToAccountRole/test.tf index f261e39bae..b4f7255789 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_DatabaseRole_ToAccountRole/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_DatabaseRole_ToAccountRole/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -12,7 +12,7 @@ resource "snowflake_database_role" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "DATABASE ROLE" object_name = "\"${snowflake_database_role.test.database}\".\"${snowflake_database_role.test.name}\"" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Database_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Database_ToAccountRole/test.tf index a2c97c0a92..2396f2c252 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Database_ToAccountRole/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Database_ToAccountRole/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -7,7 +7,7 @@ resource "snowflake_database" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "DATABASE" object_name = snowflake_database.test.name diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Database_ToAccountRole_NoDatabaseResource/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Database_ToAccountRole_NoDatabaseResource/test.tf index c4aca147cb..20d419c8d2 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Database_ToAccountRole_NoDatabaseResource/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Database_ToAccountRole_NoDatabaseResource/test.tf @@ -1,9 +1,9 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "DATABASE" object_name = var.database_name diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_MaterializedView_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_MaterializedView_ToAccountRole/test.tf index 1fd903cb08..e48a4cfc9d 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_MaterializedView_ToAccountRole/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_MaterializedView_ToAccountRole/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -31,7 +31,7 @@ resource "snowflake_materialized_view" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "MATERIALIZED VIEW" object_name = "\"${snowflake_database.test.name}\".\"${snowflake_schema.test.name}\".\"${snowflake_materialized_view.test.name}\"" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Schema_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Schema_ToAccountRole/test.tf index 20e43e8375..d1e2deebee 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Schema_ToAccountRole/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Schema_ToAccountRole/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -12,7 +12,7 @@ resource "snowflake_schema" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "SCHEMA" object_name = "\"${snowflake_database.test.name}\".\"${snowflake_schema.test.name}\"" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Table_ToAccountRole/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Table_ToAccountRole/test.tf index cb0b31622e..9501038779 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Table_ToAccountRole/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnObject_Table_ToAccountRole/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -23,7 +23,7 @@ resource "snowflake_table" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + 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}\"" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnPipe/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnPipe/test.tf index f17827dcb4..bee2bc3773 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnPipe/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnPipe/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -27,7 +27,7 @@ resource "snowflake_pipe" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "PIPE" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask/test.tf index a53d465eb8..1498779807 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -11,7 +11,7 @@ resource "snowflake_task" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "TASK" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/1/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/1/test.tf index a53d465eb8..1498779807 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/1/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/1/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -11,7 +11,7 @@ resource "snowflake_task" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "TASK" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/2/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/2/test.tf index fa6f766361..bbd0671707 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/2/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/2/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -22,7 +22,7 @@ resource "snowflake_task" "child" { resource "snowflake_grant_ownership" "test" { depends_on = [snowflake_task.child] - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "TASK" @@ -31,7 +31,7 @@ resource "snowflake_grant_ownership" "test" { } resource "snowflake_grant_ownership" "child" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "TASK" diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/3/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/3/test.tf index f8556dea2c..c8ef0f9c56 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/3/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/3/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/4/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/4/test.tf index 560b9be2df..d57869ed64 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/4/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/OnTask_Discussion2877/4/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -21,7 +21,7 @@ resource "snowflake_task" "child" { resource "snowflake_grant_ownership" "test" { depends_on = [snowflake_task.test, snowflake_task.child] - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { all { diff --git a/pkg/resources/testdata/TestAcc_GrantOwnership/RoleBasedAccessControlUseCase/test.tf b/pkg/resources/testdata/TestAcc_GrantOwnership/RoleBasedAccessControlUseCase/test.tf index 4184d0f209..b8d0768999 100644 --- a/pkg/resources/testdata/TestAcc_GrantOwnership/RoleBasedAccessControlUseCase/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantOwnership/RoleBasedAccessControlUseCase/test.tf @@ -1,4 +1,4 @@ -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.account_role_name } @@ -7,7 +7,7 @@ resource "snowflake_database" "test" { } resource "snowflake_grant_ownership" "test" { - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on { object_type = "DATABASE" object_name = snowflake_database.test.name @@ -17,7 +17,7 @@ resource "snowflake_grant_ownership" "test" { provider "snowflake" { profile = "default" alias = "secondary" - role = snowflake_role.test.name + role = snowflake_account_role.test.name } resource "snowflake_schema" "test" { diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/ImportedPrivileges/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/ImportedPrivileges/test.tf index 767b17da93..189a45bf09 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/ImportedPrivileges/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToAccountRole/ImportedPrivileges/test.tf @@ -3,12 +3,12 @@ resource "snowflake_shared_database" "test" { from_share = var.external_share_name } -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.role_name } resource "snowflake_grant_privileges_to_account_role" "test" { - depends_on = [snowflake_shared_database.test, snowflake_role.test] + depends_on = [snowflake_shared_database.test, snowflake_account_role.test] account_role_name = "\"${var.role_name}\"" privileges = var.privileges on_account_object { diff --git a/pkg/resources/testdata/TestAcc_GrantPrivilegesToRole/ImportedPrivileges/test.tf b/pkg/resources/testdata/TestAcc_GrantPrivilegesToRole/ImportedPrivileges/test.tf index 786d7d34bc..ba0f295fa5 100644 --- a/pkg/resources/testdata/TestAcc_GrantPrivilegesToRole/ImportedPrivileges/test.tf +++ b/pkg/resources/testdata/TestAcc_GrantPrivilegesToRole/ImportedPrivileges/test.tf @@ -3,12 +3,12 @@ resource "snowflake_shared_database" "test" { from_share = var.external_share_name } -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = var.role_name } resource "snowflake_grant_privileges_to_role" "test" { - depends_on = [snowflake_shared_database.test, snowflake_role.test] + depends_on = [snowflake_shared_database.test, snowflake_account_role.test] role_name = "\"${var.role_name}\"" privileges = var.privileges on_account_object { diff --git a/pkg/resources/view_acceptance_test.go b/pkg/resources/view_acceptance_test.go index 3a28a4126b..3a6324783d 100644 --- a/pkg/resources/view_acceptance_test.go +++ b/pkg/resources/view_acceptance_test.go @@ -491,7 +491,7 @@ resource "snowflake_view" "test" { is_secure = true } -resource "snowflake_role" "test" { +resource "snowflake_account_role" "test" { name = "test" } diff --git a/templates/resources/role.md.tmpl b/templates/resources/account_role.md.tmpl similarity index 100% rename from templates/resources/role.md.tmpl rename to templates/resources/account_role.md.tmpl From 7d636f10190128edc673b4f872b669ad0f16df01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Cie=C5=9Blak?= Date: Wed, 10 Jul 2024 12:47:29 +0200 Subject: [PATCH 4/7] Fix tests --- docs/data-sources/roles.md | 2 +- pkg/datasources/role.go | 2 -- pkg/datasources/roles.go | 2 +- .../system_generate_scim_access_token_acceptance_test.go | 6 +++--- pkg/datasources/testdata/TestAcc_Roles_Complete/test.tf | 2 +- pkg/resources/object_parameter_acceptance_test.go | 4 +++- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/data-sources/roles.md b/docs/data-sources/roles.md index 1c4a7d5aef..2fa1cfa06f 100644 --- a/docs/data-sources/roles.md +++ b/docs/data-sources/roles.md @@ -60,7 +60,7 @@ check "role_check" { ### Optional -- `in_class` (String) Filters the output and returns only the records for the specified class name. +- `in_class` (String) Filters the SHOW GRANTS output by class name. - `like` (String) Filters the output with **case-insensitive** pattern, with support for SQL wildcard characters (`%` and `_`). ### Read-Only diff --git a/pkg/datasources/role.go b/pkg/datasources/role.go index 8ac32a11b7..2629ade57e 100644 --- a/pkg/datasources/role.go +++ b/pkg/datasources/role.go @@ -10,8 +10,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -// TODO: Adjust - var roleSchema = map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/pkg/datasources/roles.go b/pkg/datasources/roles.go index 085544684d..76811cc4f6 100644 --- a/pkg/datasources/roles.go +++ b/pkg/datasources/roles.go @@ -23,7 +23,7 @@ var rolesSchema = map[string]*schema.Schema{ "in_class": { Type: schema.TypeString, Optional: true, - Description: "Filters the output and returns only the records for the specified class name.", + Description: "Filters the SHOW GRANTS output by class name.", }, "roles": { Type: schema.TypeList, diff --git a/pkg/datasources/system_generate_scim_access_token_acceptance_test.go b/pkg/datasources/system_generate_scim_access_token_acceptance_test.go index de90ade47f..42bdaa9fb6 100644 --- a/pkg/datasources/system_generate_scim_access_token_acceptance_test.go +++ b/pkg/datasources/system_generate_scim_access_token_acceptance_test.go @@ -39,13 +39,13 @@ func generateAccessTokenConfig(name string) string { } resource "snowflake_grant_privileges_to_account_role" "azure_grants" { - account_role_name = snowflake_role.azured.name + account_role_name = snowflake_account_role.azured.name privileges = ["CREATE USER", "CREATE ROLE"] on_account = true } resource "snowflake_grant_account_role" "azured" { - role_name = snowflake_role.azured.name + role_name = snowflake_account_role.azured.name parent_role_name = "ACCOUNTADMIN" } @@ -53,7 +53,7 @@ func generateAccessTokenConfig(name string) string { name = "%s" enabled = true scim_client = "AZURE" - run_as_role = snowflake_role.azured.name + run_as_role = snowflake_account_role.azured.name depends_on = [ snowflake_grant_privileges_to_account_role.azure_grants, snowflake_grant_account_role.azured diff --git a/pkg/datasources/testdata/TestAcc_Roles_Complete/test.tf b/pkg/datasources/testdata/TestAcc_Roles_Complete/test.tf index 68afff3b58..ecef265a1c 100644 --- a/pkg/datasources/testdata/TestAcc_Roles_Complete/test.tf +++ b/pkg/datasources/testdata/TestAcc_Roles_Complete/test.tf @@ -13,7 +13,7 @@ resource "snowflake_account_role" "test3" { comment = var.comment } -data "snowflake_account_roles" "test" { +data "snowflake_roles" "test" { depends_on = [ snowflake_account_role.test1, snowflake_account_role.test2, diff --git a/pkg/resources/object_parameter_acceptance_test.go b/pkg/resources/object_parameter_acceptance_test.go index 02ea1d5994..96d4498d04 100644 --- a/pkg/resources/object_parameter_acceptance_test.go +++ b/pkg/resources/object_parameter_acceptance_test.go @@ -2,9 +2,10 @@ package resources_test import ( "fmt" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "testing" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" + acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -33,6 +34,7 @@ func TestAcc_ObjectParameter(t *testing.T) { } func TestAcc_ObjectParameterAccount(t *testing.T) { + // TODO(SNOW-1528546): Remove after parameter-setting resources are using UNSET in the delete operation. t.Cleanup(func() { acc.TestClient().Parameter.UnsetAccountParameter(t, sdk.AccountParameterDataRetentionTimeInDays) }) From 761fe3bbaef8db59f1ae9df57ec82de852d4bd26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Cie=C5=9Blak?= Date: Thu, 11 Jul 2024 17:36:51 +0200 Subject: [PATCH 5/7] Changes after review --- MIGRATION_GUIDE.md | 31 ++++++++++--------- docs/data-sources/roles.md | 9 ++++++ .../snowflake_roles/data-source.tf | 9 ++++++ pkg/datasources/roles.go | 9 +++--- pkg/datasources/roles_acceptance_test.go | 31 +++++++++++++------ .../TestAcc_Roles_Complete/{ => 1}/test.tf | 0 .../{ => 1}/variables.tf | 0 .../testdata/TestAcc_Roles_Complete/2/test.tf | 3 ++ 8 files changed, 64 insertions(+), 28 deletions(-) rename pkg/datasources/testdata/TestAcc_Roles_Complete/{ => 1}/test.tf (100%) rename pkg/datasources/testdata/TestAcc_Roles_Complete/{ => 1}/variables.tf (100%) create mode 100644 pkg/datasources/testdata/TestAcc_Roles_Complete/2/test.tf diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index c7aac5228b..fd028d6ab0 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -4,6 +4,23 @@ This document is meant to help you migrate your Terraform config to the new newe describe deprecations or breaking changes and help you to change your configuration to keep the same (or similar) behavior across different versions. +## v0.93.0 ➞ v0.94.0 + +### *(new feature)* new snowflake_account_role resource + +Already existing `snowflake_role` was deprecated in favor of the new `snowflake_account_role`. The old resource got upgraded to +have the same features as the new one. The only difference is the deprecation message on the old resource. + +New fields: +- added `show_output` field that holds the response from SHOW ROLES. Remember that the field will be only recomputed if one of the fields (`name` or `comment`) are changed. + +### *(breaking change)* refactored snowflake_roles data source + +Changes: +- New filter option `in_class` +- `pattern` was renamed to `like` +- output of SHOW is enclosed in `show_output`, so before, e.g. `roles.0.comment` is now `roles.0.show_output.0.comment` + ## v0.92.0 ➞ v0.93.0 ### general changes @@ -20,20 +37,6 @@ They are all described in short in the [changes before v1 doc](./v1-preparations ### old grant resources removal Following the [announcement](https://github.com/Snowflake-Labs/terraform-provider-snowflake/discussions/2736) we have removed the old grant resources. The two resources [snowflake_role_ownership_grant](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_ownership_grant) and [snowflake_user_ownership_grant](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/user_ownership_grant) were not listed in the announcement, but they were also marked as deprecated ones. We are removing them too to conclude the grants redesign saga. -### *(new feature)* new snowflake_account_role resource - -Already existing `snowflake_role` was deprecated in favor of the new `snowflake_account_role`. The old resource got upgraded to -have the same features as the new one. The only difference is the deprecation message on the old resource. - -New fields: -- added `show_output` field that holds the response from SHOW ROLES. Remember that the field will be only recomputed if one of the fields (`name` or `comment`) are changed. - -### *(breaking change)* refactored snowflake_roles data source - -Changes: -- `pattern` was renamed to `like` -- output of SHOW is enclosed in `show_output`, so before, e.g. `roles.0.comment` is now `roles.0.show_output.0.comment` - ### *(new feature)* Api authentication resources Added new api authentication resources, i.e.: - `snowflake_api_authentication_integration_with_authorization_code_grant` diff --git a/docs/data-sources/roles.md b/docs/data-sources/roles.md index 2fa1cfa06f..4d43f7348e 100644 --- a/docs/data-sources/roles.md +++ b/docs/data-sources/roles.md @@ -31,6 +31,15 @@ output "like_output" { value = data.snowflake_roles.like.roles } +# Filtering (in class) +data "snowflake_roles" "in_class" { + in_class = "SNOWFLAKE.CORE.BUDGET" +} + +output "in_class_output" { + value = data.snowflake_roles.in_class.roles +} + # Ensure the number of roles is equal to at least one element (with the use of postcondition) data "snowflake_roles" "assert_with_postcondition" { like = "role-name-%" diff --git a/examples/data-sources/snowflake_roles/data-source.tf b/examples/data-sources/snowflake_roles/data-source.tf index fe510a2ca9..24ed09708b 100644 --- a/examples/data-sources/snowflake_roles/data-source.tf +++ b/examples/data-sources/snowflake_roles/data-source.tf @@ -15,6 +15,15 @@ output "like_output" { value = data.snowflake_roles.like.roles } +# Filtering (in class) +data "snowflake_roles" "in_class" { + in_class = "SNOWFLAKE.CORE.BUDGET" +} + +output "in_class_output" { + value = data.snowflake_roles.in_class.roles +} + # Ensure the number of roles is equal to at least one element (with the use of postcondition) data "snowflake_roles" "assert_with_postcondition" { like = "role-name-%" diff --git a/pkg/datasources/roles.go b/pkg/datasources/roles.go index 76811cc4f6..6af7cf88cf 100644 --- a/pkg/datasources/roles.go +++ b/pkg/datasources/roles.go @@ -21,9 +21,10 @@ var rolesSchema = map[string]*schema.Schema{ Description: "Filters the output with **case-insensitive** pattern, with support for SQL wildcard characters (`%` and `_`).", }, "in_class": { - Type: schema.TypeString, - Optional: true, - Description: "Filters the SHOW GRANTS output by class name.", + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: resources.IsValidIdentifier[sdk.SchemaObjectIdentifier](), + Description: "Filters the SHOW GRANTS output by class name.", }, "roles": { Type: schema.TypeList, @@ -63,7 +64,7 @@ func ReadRoles(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagn if className, ok := d.GetOk("in_class"); ok { req.WithInClass(sdk.RolesInClass{ - Class: sdk.NewAccountObjectIdentifier(className.(string)), + Class: sdk.NewSchemaObjectIdentifierFromFullyQualifiedName(className.(string)), }) } diff --git a/pkg/datasources/roles_acceptance_test.go b/pkg/datasources/roles_acceptance_test.go index 40f3b50a5a..af29e8fd11 100644 --- a/pkg/datasources/roles_acceptance_test.go +++ b/pkg/datasources/roles_acceptance_test.go @@ -2,7 +2,6 @@ package datasources_test import ( "fmt" - "maps" "strconv" "testing" @@ -22,20 +21,14 @@ func TestAcc_Roles_Complete(t *testing.T) { accountRoleName3 := acc.TestClient().Ids.Alpha() comment := random.Comment() - commonVariables := config.Variables{ + likeVariables := config.Variables{ "account_role_name_1": config.StringVariable(accountRoleName1), "account_role_name_2": config.StringVariable(accountRoleName2), "account_role_name_3": config.StringVariable(accountRoleName3), "comment": config.StringVariable(comment), + "like": config.StringVariable(accountRoleNamePrefix + "%"), } - likeVariables := maps.Clone(commonVariables) - likeVariables["like"] = config.StringVariable(accountRoleNamePrefix + "%") - - // TODO(SNOW-1353303): Add test case for instance classes after they're available in the provider - // inClassVariables := maps.Clone(commonVariables) - // inClassVariables["in_class"] = config.StringVariable("") - resource.Test(t, resource.TestCase{ ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, PreCheck: func() { acc.TestAccPreCheck(t) }, @@ -44,7 +37,7 @@ func TestAcc_Roles_Complete(t *testing.T) { }, Steps: []resource.TestStep{ { - ConfigDirectory: config.TestNameDirectory(), + ConfigDirectory: config.TestStepDirectory(), ConfigVariables: likeVariables, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("data.snowflake_roles.test", "roles.#", "2"), @@ -53,6 +46,24 @@ func TestAcc_Roles_Complete(t *testing.T) { doesntContainAccountRole(accountRoleName3, comment), ), }, + { + ConfigDirectory: config.TestStepDirectory(), + ConfigVariables: config.Variables{}, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrWith("data.snowflake_roles.test", "roles.#", func(value string) error { + numberOfRoles, err := strconv.ParseInt(value, 10, 8) + if err != nil { + return err + } + + if numberOfRoles == 0 { + return fmt.Errorf("expected roles to be non-empty") + } + + return nil + }), + ), + }, }, }) } diff --git a/pkg/datasources/testdata/TestAcc_Roles_Complete/test.tf b/pkg/datasources/testdata/TestAcc_Roles_Complete/1/test.tf similarity index 100% rename from pkg/datasources/testdata/TestAcc_Roles_Complete/test.tf rename to pkg/datasources/testdata/TestAcc_Roles_Complete/1/test.tf diff --git a/pkg/datasources/testdata/TestAcc_Roles_Complete/variables.tf b/pkg/datasources/testdata/TestAcc_Roles_Complete/1/variables.tf similarity index 100% rename from pkg/datasources/testdata/TestAcc_Roles_Complete/variables.tf rename to pkg/datasources/testdata/TestAcc_Roles_Complete/1/variables.tf diff --git a/pkg/datasources/testdata/TestAcc_Roles_Complete/2/test.tf b/pkg/datasources/testdata/TestAcc_Roles_Complete/2/test.tf new file mode 100644 index 0000000000..371634b3d1 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_Roles_Complete/2/test.tf @@ -0,0 +1,3 @@ +data "snowflake_roles" "test" { + in_class = "SNOWFLAKE.CORE.BUDGET" +} From 05ee620c82c6decbdb74e94215cbe81a041bfc63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Cie=C5=9Blak?= Date: Fri, 12 Jul 2024 09:45:45 +0200 Subject: [PATCH 6/7] Changes after review --- MIGRATION_GUIDE.md | 2 +- pkg/provider/resources/resources.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index b7ba09ec56..020a152886 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -17,7 +17,7 @@ New fields: ### *(breaking change)* refactored snowflake_roles data source Changes: -- New filter option `in_class` +- New `in_class` filtering option to filter out roles by class name, e.g. `in_class = "SNOWFLAKE.CORE.BUDGET"` - `pattern` was renamed to `like` - output of SHOW is enclosed in `show_output`, so before, e.g. `roles.0.comment` is now `roles.0.show_output.0.comment` diff --git a/pkg/provider/resources/resources.go b/pkg/provider/resources/resources.go index 527751ca83..1dd71871eb 100644 --- a/pkg/provider/resources/resources.go +++ b/pkg/provider/resources/resources.go @@ -4,7 +4,7 @@ type resource string const ( Account resource = "snowflake_account" - AccountRole resource = "snowflake_account_role" + AccountRole resource = "snowflake_account_role" Alert resource = "snowflake_alert" ApiAuthenticationIntegrationWithAuthorizationCodeGrant resource = "snowflake_api_authentication_integration_with_authorization_code_grant" ApiAuthenticationIntegrationWithClientCredentials resource = "snowflake_api_authentication_integration_with_client_credentials" From 680a7b7705a4f2ed6f9796251bcfec9c5e246b02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Cie=C5=9Blak?= Date: Fri, 12 Jul 2024 15:21:28 +0200 Subject: [PATCH 7/7] Test fix --- pkg/resources/view_acceptance_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/resources/view_acceptance_test.go b/pkg/resources/view_acceptance_test.go index 3a6324783d..dc553bb1b2 100644 --- a/pkg/resources/view_acceptance_test.go +++ b/pkg/resources/view_acceptance_test.go @@ -497,7 +497,7 @@ resource "snowflake_account_role" "test" { resource "snowflake_grant_privileges_to_account_role" "grant" { privileges = ["SELECT"] - account_role_name = snowflake_role.test.name + account_role_name = snowflake_account_role.test.name on_schema_object { object_type = "VIEW" object_name = "\"%[1]s\".\"%[2]s\".\"${snowflake_view.test.name}\""