-
Notifications
You must be signed in to change notification settings - Fork 430
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
548ec42
commit 54272c5
Showing
15 changed files
with
428 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
--- | ||
page_title: "snowflake_account_roles Data Source - terraform-provider-snowflake" | ||
subcategory: "" | ||
description: |- | ||
Datasource used to get details of filtered account 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. | ||
--- | ||
|
||
# snowflake_account_roles (Data Source) | ||
|
||
Datasource used to get details of filtered account 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. | ||
|
||
## Example Usage | ||
|
||
```terraform | ||
# Simple usage | ||
data "snowflake_account_roles" "simple" { | ||
} | ||
output "simple_output" { | ||
value = data.snowflake_account_roles.simple.roles | ||
} | ||
# Filtering (like) | ||
data "snowflake_account_roles" "like" { | ||
like = "role-name" | ||
} | ||
output "like_output" { | ||
value = data.snowflake_account_roles.like.roles | ||
} | ||
# Filtering (in class) | ||
data "snowflake_account_roles" "in_class" { | ||
in_class = "SNOWFLAKE.CORE.BUDGET" | ||
} | ||
output "in_class_output" { | ||
value = data.snowflake_account_roles.in_class.roles | ||
} | ||
# Ensure the number of roles is equal to at least one element (with the use of postcondition) | ||
data "snowflake_account_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_account_roles" "assert_with_check_block" { | ||
like = "role-name" | ||
} | ||
assert { | ||
condition = length(data.snowflake_account_roles.assert_with_check_block.roles) == 1 | ||
error_message = "Roles filtered by '${data.snowflake_account_roles.assert_with_check_block.like}' returned ${length(data.snowflake_account_roles.assert_with_check_block.roles)} roles where one was expected" | ||
} | ||
} | ||
``` | ||
|
||
<!-- schema generated by tfplugindocs --> | ||
## Schema | ||
|
||
### Optional | ||
|
||
- `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 | ||
|
||
- `id` (String) The ID of this resource. | ||
- `roles` (List of Object) Holds the aggregated output of all role details queries. (see [below for nested schema](#nestedatt--roles)) | ||
|
||
<a id="nestedatt--roles"></a> | ||
### Nested Schema for `roles` | ||
|
||
Read-Only: | ||
|
||
- `show_output` (List of Object) (see [below for nested schema](#nestedobjatt--roles--show_output)) | ||
|
||
<a id="nestedobjatt--roles--show_output"></a> | ||
### Nested Schema for `roles.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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
## Currently deprecated datasources | ||
|
||
- [snowflake_role](./docs/data-sources/role) - use [snowflake_roles](./docs/data-sources/roles) instead | ||
- [snowflake_roles](./docs/data-sources/roles) - use [snowflake_account_roles](./docs/data-sources/account_roles) instead |
48 changes: 48 additions & 0 deletions
48
examples/data-sources/snowflake_account_roles/data-source.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# Simple usage | ||
data "snowflake_account_roles" "simple" { | ||
} | ||
|
||
output "simple_output" { | ||
value = data.snowflake_account_roles.simple.roles | ||
} | ||
|
||
# Filtering (like) | ||
data "snowflake_account_roles" "like" { | ||
like = "role-name" | ||
} | ||
|
||
output "like_output" { | ||
value = data.snowflake_account_roles.like.roles | ||
} | ||
|
||
# Filtering (in class) | ||
data "snowflake_account_roles" "in_class" { | ||
in_class = "SNOWFLAKE.CORE.BUDGET" | ||
} | ||
|
||
output "in_class_output" { | ||
value = data.snowflake_account_roles.in_class.roles | ||
} | ||
|
||
# Ensure the number of roles is equal to at least one element (with the use of postcondition) | ||
data "snowflake_account_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_account_roles" "assert_with_check_block" { | ||
like = "role-name" | ||
} | ||
|
||
assert { | ||
condition = length(data.snowflake_account_roles.assert_with_check_block.roles) == 1 | ||
error_message = "Roles filtered by '${data.snowflake_account_roles.assert_with_check_block.like}' returned ${length(data.snowflake_account_roles.assert_with_check_block.roles)} roles where one was expected" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package datasources | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/datasources" | ||
|
||
"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" | ||
|
||
"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 accountRolesSchema = map[string]*schema.Schema{ | ||
"like": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Description: "Filters the output with **case-insensitive** pattern, with support for SQL wildcard characters (`%` and `_`).", | ||
}, | ||
"in_class": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
ValidateDiagFunc: resources.IsValidIdentifier[sdk.SchemaObjectIdentifier](), | ||
Description: "Filters the SHOW GRANTS output by class name.", | ||
}, | ||
"roles": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Description: "Holds the aggregated output of all role details queries.", | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
resources.ShowOutputAttributeName: { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Description: "Holds the output of SHOW ROLES.", | ||
Elem: &schema.Resource{ | ||
Schema: schemas.ShowRoleSchema, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
func AccountRoles() *schema.Resource { | ||
return &schema.Resource{ | ||
ReadContext: TrackingReadWrapper(datasources.Roles, ReadRoles), | ||
Schema: accountRolesSchema, | ||
Description: "Datasource used to get details of filtered account 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 { | ||
client := meta.(*provider.Context).Client | ||
|
||
req := sdk.NewShowRoleRequest() | ||
|
||
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.NewSchemaObjectIdentifierFromFullyQualifiedName(className.(string)), | ||
}) | ||
} | ||
|
||
roles, err := client.Roles.Show(ctx, req) | ||
if err != nil { | ||
return diag.Diagnostics{ | ||
diag.Diagnostic{ | ||
Severity: diag.Error, | ||
Summary: "Failed to show account roles", | ||
Detail: fmt.Sprintf("Error: %s", err), | ||
}, | ||
} | ||
} | ||
|
||
d.SetId("account_roles_read") | ||
|
||
flattenedAccountRoles := make([]map[string]any, len(roles)) | ||
for i, role := range roles { | ||
role := role | ||
flattenedAccountRoles[i] = map[string]any{ | ||
resources.ShowOutputAttributeName: []map[string]any{schemas.RoleToSchema(&role)}, | ||
} | ||
} | ||
|
||
err = d.Set("account_roles", flattenedAccountRoles) | ||
if err != nil { | ||
return diag.FromErr(err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package datasources_test | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
"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/acceptance/testenvs" | ||
"github.com/hashicorp/terraform-plugin-testing/config" | ||
"github.com/hashicorp/terraform-plugin-testing/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-testing/terraform" | ||
"github.com/hashicorp/terraform-plugin-testing/tfversion" | ||
) | ||
|
||
func TestAcc_AccountRoles_Complete(t *testing.T) { | ||
_ = testenvs.GetOrSkipTest(t, testenvs.EnableAcceptance) | ||
acc.TestAccPreCheck(t) | ||
|
||
accountRoleNamePrefix := random.AlphaN(10) | ||
accountRoleName1 := acc.TestClient().Ids.AlphaWithPrefix(accountRoleNamePrefix + "1") | ||
accountRoleName2 := acc.TestClient().Ids.AlphaWithPrefix(accountRoleNamePrefix + "2") | ||
accountRoleName3 := acc.TestClient().Ids.Alpha() | ||
dbRoleName := acc.TestClient().Ids.AlphaWithPrefix(accountRoleNamePrefix + "db") | ||
comment := random.Comment() | ||
|
||
// Proof that database role with the same prefix is not in the output of SHOW ROLES. | ||
dbRole, dbRoleCleanup := acc.TestClient().DatabaseRole.CreateDatabaseRoleWithName(t, dbRoleName) | ||
t.Cleanup(dbRoleCleanup) | ||
|
||
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 + "%"), | ||
} | ||
|
||
resource.Test(t, resource.TestCase{ | ||
ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, | ||
TerraformVersionChecks: []tfversion.TerraformVersionCheck{ | ||
tfversion.RequireAbove(tfversion.Version1_5_0), | ||
}, | ||
Steps: []resource.TestStep{ | ||
{ | ||
ConfigDirectory: config.TestStepDirectory(), | ||
ConfigVariables: likeVariables, | ||
Check: resource.ComposeAggregateTestCheckFunc( | ||
resource.TestCheckResourceAttr("data.snowflake_account_roles.test", "roles.#", "2"), | ||
accountRolesDataSourceContainsRole(accountRoleName1, comment), | ||
accountRolesDataSourceContainsRole(accountRoleName2, comment), | ||
accountRolesDataSourceDoesNotContainRole(accountRoleName3, comment), | ||
accountRolesDataSourceDoesNotContainRole(dbRole.ID().FullyQualifiedName(), comment), | ||
), | ||
}, | ||
{ | ||
ConfigDirectory: config.TestStepDirectory(), | ||
ConfigVariables: config.Variables{}, | ||
Check: resource.ComposeAggregateTestCheckFunc( | ||
resource.TestCheckResourceAttrWith("data.snowflake_account_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 | ||
}), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func accountRolesDataSourceDoesNotContainRole(name string, comment string) func(s *terraform.State) error { | ||
return func(state *terraform.State) error { | ||
err := accountRolesDataSourceContainsRole(name, comment)(state) | ||
if err != nil && err.Error() == fmt.Sprintf("role %s not found", name) { | ||
return nil | ||
} | ||
return fmt.Errorf("expected %s not to be present", name) | ||
} | ||
} | ||
|
||
func accountRolesDataSourceContainsRole(name string, comment string) func(s *terraform.State) error { | ||
return func(s *terraform.State) error { | ||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "snowflake_account_roles" { | ||
continue | ||
} | ||
|
||
iter, err := strconv.ParseInt(rs.Primary.Attributes["roles.#"], 10, 32) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for i := 0; i < int(iter); 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) | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
} | ||
|
||
return fmt.Errorf("role %s not found", name) | ||
} | ||
} |
Oops, something went wrong.