Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: Add a new account roles data source #3257

Merged
merged 11 commits into from
Dec 12, 2024
5 changes: 4 additions & 1 deletion MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ across different versions.

## v0.99.0 ➞ v0.100.0

### snowflake_roles data source deprecation
`snowflake_roles` is now deprecated in favor of `snowflake_account_roles` with the same schema and behavior. It will be removed with the v1 release. Please adjust your configuration files.

### snowflake_account resource changes

Changes:
- `admin_user_type` is now supported. No action required during the migration.
- `grace_period_in_days` is now required. The field should be explicitly set in the following versions.
- Account renaming is now supported.
- `is_org_admin` is a settable field (previously it was read-only field). Changing its value is also supported.
- `must_change_password` and `is_org_admin` type was changed from `bool` to bool-string (more on that [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/v1-preparations/CHANGES_BEFORE_V1.md#empty-values)). No action required during the migration.
- `must_change_password` and `is_org_admin` type was changed from `bool` to bool-string (more on that [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/v1-preparations/CHANGES_BEFORE_V1.md#empty-values)). No action required during the migration.
- The underlying resource identifier was changed from `<account_locator>` to `<organization_name>.<account_name>`. Migration will be done automatically. Notice this introduces changes in how `snowflake_account` resource is imported.
- New `show_output` field was added (see [raw Snowflake output](./v1-preparations/CHANGES_BEFORE_V1.md#raw-snowflake-output)).

Expand Down
99 changes: 99 additions & 0 deletions docs/data-sources/account_roles.md
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: |-
Data source 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)

Data source 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

- `account_roles` (List of Object) Holds the aggregated output of all account role details queries. (see [below for nested schema](#nestedatt--account_roles))
- `id` (String) The ID of this resource.

<a id="nestedatt--account_roles"></a>
### Nested Schema for `account_roles`

Read-Only:

- `show_output` (List of Object) (see [below for nested schema](#nestedobjatt--account_roles--show_output))

<a id="nestedobjatt--account_roles--show_output"></a>
### Nested Schema for `account_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)
2 changes: 1 addition & 1 deletion docs/data-sources/role.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: |-

# snowflake_role (Data Source)

~> **Deprecation** This resource is deprecated and will be removed in a future major version release. Please use [snowflake_roles](./roles) instead. <deprecation>
~> **Deprecation** This resource is deprecated and will be removed in a future major version release. Please use [snowflake_account_roles](./account_roles) instead. <deprecation>

## Example Usage

Expand Down
2 changes: 2 additions & 0 deletions docs/data-sources/roles.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ description: |-

# snowflake_roles (Data Source)

~> **Deprecation** This resource is deprecated and will be removed in a future major version release. Please use [snowflake_account_roles](./account_roles) instead. <deprecation>

Data source 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.

## Example Usage
Expand Down
3 changes: 2 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,4 +370,5 @@ provider "snowflake" {

## Currently deprecated datasources

- [snowflake_role](./docs/data-sources/role) - use [snowflake_roles](./docs/data-sources/roles) instead
- [snowflake_role](./docs/data-sources/role) - use [snowflake_account_roles](./docs/data-sources/account_roles) instead
- [snowflake_roles](./docs/data-sources/roles) - use [snowflake_account_roles](./docs/data-sources/account_roles) instead
3 changes: 1 addition & 2 deletions docs/resources/database.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ description: |-

!> **Note** The provider does not detect external changes on database type. In this case, remove the database of wrong type manually with `terraform destroy` and recreate the resource. It will be addressed in the future.

!> **Note** A database cannot be dropped successfully if it contains network rule-network policy associations. The error looks like `098507 (2BP01): Cannot drop database DATABASE as it includes network rule - policy associations.
`. Currently, the provider does not unassign such objects automatically. Before dropping the resource, first unassign the network rule from the relevant objects. See [guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/unassigning_policies) for more details.
!> **Note** A database cannot be dropped successfully if it contains network rule-network policy associations. The error looks like `098507 (2BP01): Cannot drop database DATABASE as it includes network rule - policy associations.`. Currently, the provider does not unassign such objects automatically. Before dropping the resource, first unassign the network rule from the relevant objects. See [guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/unassigning_policies) for more details.

# snowflake_database (Resource)

Expand Down
3 changes: 1 addition & 2 deletions docs/resources/secondary_database.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ description: |-

!> **Note** The provider does not detect external changes on database type. In this case, remove the database of wrong type manually with `terraform destroy` and recreate the resource. It will be addressed in the future.

!> **Note** A database cannot be dropped successfully if it contains network rule-network policy associations. The error looks like `098507 (2BP01): Cannot drop database DATABASE as it includes network rule - policy associations.
`. Currently, the provider does not unassign such objects automatically. Before dropping the resource, first unassign the network rule from the relevant objects. See [guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/unassigning_policies) for more details.
!> **Note** A database cannot be dropped successfully if it contains network rule-network policy associations. The error looks like `098507 (2BP01): Cannot drop database DATABASE as it includes network rule - policy associations.`. Currently, the provider does not unassign such objects automatically. Before dropping the resource, first unassign the network rule from the relevant objects. See [guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/unassigning_policies) for more details.

# snowflake_secondary_database (Resource)

Expand Down
3 changes: 1 addition & 2 deletions docs/resources/shared_database.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ description: |-

!> **Note** The provider does not detect external changes on database type. In this case, remove the database of wrong type manually with `terraform destroy` and recreate the resource. It will be addressed in the future.

!> **Note** A database cannot be dropped successfully if it contains network rule-network policy associations. The error looks like `098507 (2BP01): Cannot drop database DATABASE as it includes network rule - policy associations.
`. Currently, the provider does not unassign such objects automatically. Before dropping the resource, first unassign the network rule from the relevant objects. See [guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/unassigning_policies) for more details.
!> **Note** A database cannot be dropped successfully if it contains network rule-network policy associations. The error looks like `098507 (2BP01): Cannot drop database DATABASE as it includes network rule - policy associations.`. Currently, the provider does not unassign such objects automatically. Before dropping the resource, first unassign the network rule from the relevant objects. See [guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/unassigning_policies) for more details.

# snowflake_shared_database (Resource)

Expand Down
3 changes: 2 additions & 1 deletion examples/additional/deprecated_datasources.MD
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_role](./docs/data-sources/role) - use [snowflake_account_roles](./docs/data-sources/account_roles) instead
- [snowflake_roles](./docs/data-sources/roles) - use [snowflake_account_roles](./docs/data-sources/account_roles) instead
48 changes: 48 additions & 0 deletions examples/data-sources/snowflake_account_roles/data-source.tf
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"
}
}
1 change: 1 addition & 0 deletions pkg/acceptance/bettertestspoc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ func (w *WarehouseDatasourceShowOutputAssert) IsEmpty() {
- generate assertions checking that time is not empty - we often do not compare time fields by value, but check if they are set
- utilize `ContainsExactlyInAnyOrder` function in `pkg/acceptance/bettertestspoc/assert/commons.go` to create asserts on collections that are order independent
- Additional asserts for sets and lists that wouldn't rely on the order of items saved to the state (SNOW-1706544)
- this should also support nested sets and lists (see `accountRolesDataSourceContainsRole` for example)
- support generating provider config and use generated configs in `pkg/provider/provider_acceptance_test.go`
- add config builders for other block types (Variable, Output, Locals, Module, Terraform)
- add provider to resource/datasource models (use in the grant_ownership_acceptance_test)
Expand Down
94 changes: 94 additions & 0 deletions pkg/datasources/account_roles.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
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": likeSchema,
"in_class": {
Type: schema.TypeString,
Optional: true,
ValidateDiagFunc: resources.IsValidIdentifier[sdk.SchemaObjectIdentifier](),
Description: "Filters the SHOW GRANTS output by class name.",
},
"account_roles": {
Type: schema.TypeList,
Computed: true,
Description: "Holds the aggregated output of all account 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.AccountRoles, ReadAccountRoles),
Schema: accountRolesSchema,
Description: "Data source 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()

handleLike(d, &req.Like)

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
}
Loading
Loading