Skip to content

Commit

Permalink
feat: Row access policy resource v1 (#3063)
Browse files Browse the repository at this point in the history
<!-- Feel free to delete comments as you fill this in -->

<!-- summary of changes -->
- add show and desc output
- rename fields
- change signature to arguments
- implement renaming
- fix permadiff on body
- adjust identifiers handling
- adjust examples
- gen resource asserts (config builders are not working because we have
a required list argument)
- improve handling data types
- move parsing signature to sdk
- support proper casing in arg names

## Test Plan
<!-- detail ways in which this PR has been tested or needs to be tested
-->
* [x] acceptance tests
<!-- add more below if you think they are relevant -->
* [ ] …

## References
<!-- issues documentation links, etc  -->
https://docs.snowflake.com/en/sql-reference/sql/create-row-access-policy

#2053

#1151
## TODO (next PR)
- rework data source
  • Loading branch information
sfc-gh-jmichalak authored and sfc-gh-fbudzynski committed Sep 19, 2024
1 parent 42fd40a commit 6c420a4
Show file tree
Hide file tree
Showing 32 changed files with 1,756 additions and 291 deletions.
41 changes: 37 additions & 4 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,39 @@ 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.95.0 ➞ v0.96.0
### snowflake_row_access_policy resource changes
New fields:
- `show_output` field that holds the response from SHOW ROW ACCESS POLICIES.
- `describe_output` field that holds the response from DESCRIBE ROW ACCESS POLICY.

#### *(breaking change)* Renamed fields in snowflake_row_access_policy resource
Renamed fields:
- `row_access_expression` to `body`
- `signature` to `arguments`
Please rename these fields in your configuration files. State will be migrated automatically.

#### *(breaking change)* Adjusted behavior of arguments/signature
Now, arguments are stored as a list, instead of a map. Please adjust that in your configs. State is migrated automatically. Also, this means that order of the items matters and may be adjusted.

Argument names are now case sensitive. All policies created previously in the provider have upper case argument names. If you used lower case before, please adjust your configs. Values in the state will be migrated to uppercase automatically.

#### *(breaking change)* Adjusted behavior on changing name
Previously, after changing `name` field, the resource was recreated. Now, the object is renamed with `RENAME TO`.

#### *(breaking change)* Mitigating permadiff on `body`
Previously, `body` of a policy was compared as a raw string. This led to permament diff because of leading newlines (see https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2053).

Now, similarly to handling statements in other resources, we replace blank characters with a space. The provider can cause false positives in cases where a change in case or run of whitespace is semantically significant.

#### *(breaking change)* Identifiers related changes
During [identifiers rework](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/ROADMAP.md#identifiers-rework) we decided to
migrate resource ids from pipe-separated to regular Snowflake identifiers (e.g. `<database_name>|<schema_name>` -> `"<database_name>"."<schema_name>"`). Importing resources also needs to be adjusted (see [example](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/row_access_policy#import)).

Also, we added diff suppress function that prevents Terraform from showing differences, when only quoting is different.

No change is required, the state will be migrated automatically.

## v0.94.x ➞ v0.95.0

### *(breaking change)* database roles data source; field rename, schema structure changes, and adding missing filtering options
Expand Down Expand Up @@ -37,7 +70,7 @@ New output fields

Breaking changes:
- `database` and `schema` are right now under `in` field
- `views` field now organizes output of show under `show_output` field and the output of describe under `describe_output` field.
- `views` field now organizes output of show under `show_output` field and the output of describe under `describe_output` field.

### snowflake_view resource changes
New fields:
Expand Down Expand Up @@ -133,7 +166,7 @@ Because of introducing a new `fully_qualified_name` field for all of the resourc

Correctly handle the situation when stage was rename/deleted externally (earlier it resulted in a permanent loop). No action is required on the user's side.

Connected issues: [#2972](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2972)
Connected issues: [#2972](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2972)

### snowflake_table resource changes

Expand Down Expand Up @@ -289,8 +322,8 @@ Type changes:
- `disabled`: bool -> string (To easily handle three-value logic (true, false, unknown) in provider's configs, read more in https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/751239b7d2fee4757471db6c03b952d4728ee099/v1-preparations/CHANGES_BEFORE_V1.md?plain=1#L24)

#### *(breaking change)* refactored snowflake_users datasource
> **IMPORTANT NOTE:** when querying users you don't have permissions to, the querying options are limited.
You won't get almost any field in `show_output` (only empty or default values), the DESCRIBE command cannot be called, so you have to set `with_describe = false`.
> **IMPORTANT NOTE:** when querying users you don't have permissions to, the querying options are limited.
You won't get almost any field in `show_output` (only empty or default values), the DESCRIBE command cannot be called, so you have to set `with_describe = false`.
Only `parameters` output is not affected by the lack of privileges.

Changes:
Expand Down
70 changes: 58 additions & 12 deletions docs/resources/row_access_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ description: |-
---

!> **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#v0950--v0960) to use it.

# snowflake_row_access_policy (Resource)


Expand All @@ -16,14 +18,22 @@ resource "snowflake_row_access_policy" "example_row_access_policy" {
name = "EXAMPLE_ROW_ACCESS_POLICY"
database = "EXAMPLE_DB"
schema = "EXAMPLE_SCHEMA"
signature = {
A = "VARCHAR",
B = "VARCHAR"
argument {
name = "ARG1"
type = "VARCHAR"
}
argument {
name = "ARG2"
type = "NUMBER"
}
row_access_expression = "case when current_role() in ('ANALYST') then true else false end"
argument {
name = "ARG3"
type = "TIMESTAMP_NTZ"
}
body = "case when current_role() in ('ANALYST') then true else false end"
comment = "comment"
}
```

-> **Note** Instead of using fully_qualified_name, you can reference objects managed outside Terraform by constructing a correct ID, consult [identifiers guide](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/guides/identifiers#new-computed-fully-qualified-name-field-in-resources).
<!-- TODO(SNOW-1634854): include an example showing both methods-->

Expand All @@ -32,26 +42,62 @@ resource "snowflake_row_access_policy" "example_row_access_policy" {

### Required

- `database` (String) The database in which to create the row access policy.
- `name` (String) Specifies the identifier for the row access policy; must be unique for the database and schema in which the row access policy is created.
- `row_access_expression` (String) Specifies the SQL expression. The expression can be any boolean-valued SQL expression.
- `schema` (String) The schema in which to create the row access policy.
- `signature` (Map of String) Specifies signature (arguments) for the row access policy (uppercase and sorted to avoid recreation of resource). A signature specifies a set of attributes that must be considered to determine whether the row is accessible. The attribute values come from the database object (e.g. table or view) to be protected by the row access policy.
- `argument` (Block List, Min: 1) List of the arguments for the row access policy. A signature specifies a set of attributes that must be considered to determine whether the row is accessible. The attribute values come from the database object (e.g. table or view) to be protected by the row access policy. If any argument name or type is changed, the resource is recreated. (see [below for nested schema](#nestedblock--argument))
- `body` (String) Specifies the SQL expression. The expression can be any boolean-valued SQL expression. To mitigate permadiff on this field, the provider replaces blank characters with a space. This can lead to false positives in cases where a change in case or run of whitespace is semantically significant.
- `database` (String) The database in which to create the row access policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"`
- `name` (String) Specifies the identifier for the row access policy; must be unique for the database and schema in which the row access policy is created. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"`
- `schema` (String) The schema in which to create the row access policy. Due to technical limitations (read more [here](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/identifiers_rework_design_decisions.md#known-limitations-and-identifier-recommendations)), avoid using the following characters: `|`, `.`, `(`, `)`, `"`

### Optional

- `comment` (String) Specifies a comment for the row access policy.

### Read-Only

- `describe_output` (List of Object) Outputs the result of `DESCRIBE ROW ACCESS POLICY` for the given row access policy. (see [below for nested schema](#nestedatt--describe_output))
- `fully_qualified_name` (String) Fully qualified name of the resource. For more information, see [object name resolution](https://docs.snowflake.com/en/sql-reference/name-resolution).
- `id` (String) The ID of this resource.
- `show_output` (List of Object) Outputs the result of `SHOW ROW ACCESS POLICY` for the given row access policy. (see [below for nested schema](#nestedatt--show_output))

<a id="nestedblock--argument"></a>
### Nested Schema for `argument`

Required:

- `name` (String) The argument name
- `type` (String) The argument type. VECTOR data types are not yet supported. For more information about data types, check [Snowflake docs](https://docs.snowflake.com/en/sql-reference/intro-summary-data-types).


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

Read-Only:

- `body` (String)
- `name` (String)
- `return_type` (String)
- `signature` (String)


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

Read-Only:

- `comment` (String)
- `created_on` (String)
- `database_name` (String)
- `kind` (String)
- `name` (String)
- `options` (String)
- `owner` (String)
- `owner_role_type` (String)
- `schema_name` (String)

## Import

Import is supported using the following syntax:

```shell
# format is database name | schema name | policy name
terraform import snowflake_row_access_policy.example 'dbName|schemaName|policyName'
terraform import snowflake_row_access_policy.example '"<database_name>"."<schema_name>"."<row_access_policy_name>"'
```
3 changes: 1 addition & 2 deletions examples/resources/snowflake_row_access_policy/import.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
# format is database name | schema name | policy name
terraform import snowflake_row_access_policy.example 'dbName|schemaName|policyName'
terraform import snowflake_row_access_policy.example '"<database_name>"."<schema_name>"."<row_access_policy_name>"'
17 changes: 13 additions & 4 deletions examples/resources/snowflake_row_access_policy/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@ resource "snowflake_row_access_policy" "example_row_access_policy" {
name = "EXAMPLE_ROW_ACCESS_POLICY"
database = "EXAMPLE_DB"
schema = "EXAMPLE_SCHEMA"
signature = {
A = "VARCHAR",
B = "VARCHAR"
argument {
name = "ARG1"
type = "VARCHAR"
}
row_access_expression = "case when current_role() in ('ANALYST') then true else false end"
argument {
name = "ARG2"
type = "NUMBER"
}
argument {
name = "ARG3"
type = "TIMESTAMP_NTZ"
}
body = "case when current_role() in ('ANALYST') then true else false end"
comment = "comment"
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ var allStructs = []SdkObjectDef{
ObjectType: sdk.ObjectTypeDatabaseRole,
ObjectStruct: sdk.DatabaseRole{},
},
{
IdType: "sdk.SchemaObjectIdentifier",
ObjectType: sdk.ObjectTypeRowAccessPolicy,
ObjectStruct: sdk.RowAccessPolicy{},
},
{
IdType: "sdk.AccountObjectIdentifier",
ObjectType: sdk.ObjectTypeUser,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,8 @@ var allResourceSchemaDefs = []ResourceSchemaDef{
name: "ResourceMonitor",
schema: resources.ResourceMonitor().Schema,
},
{
name: "RowAccessPolicy",
schema: resources.RowAccessPolicy().Schema,
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package resourceassert

import (
"fmt"
"strconv"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/bettertestspoc/assert"
"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk"
)

func (r *RowAccessPolicyResourceAssert) HasArguments(args []sdk.RowAccessPolicyArgument) *RowAccessPolicyResourceAssert {
r.AddAssertion(assert.ValueSet("argument.#", strconv.FormatInt(int64(len(args)), 10)))
for i, v := range args {
r.AddAssertion(assert.ValueSet(fmt.Sprintf("argument.%d.name", i), v.Name))
r.AddAssertion(assert.ValueSet(fmt.Sprintf("argument.%d.type", i), v.Type))
}
return r
}
Loading

0 comments on commit 6c420a4

Please sign in to comment.