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

chore: Add annotation about fully_qualified_name and fix handling granteeName #3009

Merged
merged 8 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/guides/identifiers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
page_title: "Identifiers rework"
subcategory: ""
description: |-

---
# Identifiers rework

## New computed fully qualified name field in resources

With the combination of quotes, old parsing methods, and other factors, it was a struggle to specify the fully qualified name of an object needed (e.g. [#2164](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2164), [#2754](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2754)). Now, with v0.95.0, every resource that represents an object in Snowflake (e.g. user, role), and not an association (e.g. grants) will have a new computed field named `fully_qualified_name`. With the new computed field, it will be much easier to use resources requiring fully qualified names, for examples of usage head over to the [documentation for granting privileges to account role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_privileges_to_account_role).
sfc-gh-asawicki marked this conversation as resolved.
Show resolved Hide resolved
sfc-gh-asawicki marked this conversation as resolved.
Show resolved Hide resolved

For example, instead of writing

```object_name = “\”${snowflake_table.database}\”.\”${snowflake_table.schema}\”.\”${snowflake_table.name}\””```

now we can write

```object_name = snowflake_table.fully_qualified_name```

If you don't manage table in Terraform, you can construct the proper id yourself like before: `"\"database_name\".\"schema_name\".\"table_name\""`
sfc-gh-asawicki marked this conversation as resolved.
Show resolved Hide resolved

<!--- TODO: fill the rest of the document -->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will go in here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rest of the document about identifiers rework.

3 changes: 3 additions & 0 deletions docs/resources/account_password_policy_attachment.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ description: |-

Specifies the password policy to use for the current account. To set the password policy of a different account, use a provider alias.


## Example Usage

```terraform
Expand All @@ -23,6 +24,8 @@ resource "snowflake_account_password_policy_attachment" "attachment" {
}
```

-> **Note** If you don't manage password policy in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remember to validate this link after the release

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll comment in this thread.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now it points to the repository markdown, maybe it should point the registry documentation?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but after release it should behave correctly (it's a relative URL, so it will point to the registry)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it still needs to be validated :)


<!-- schema generated by tfplugindocs -->
## Schema

Expand Down
2 changes: 2 additions & 0 deletions docs/resources/grant_ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ resource "snowflake_schema" "test" {
}
```

-> **Note** If you don't manage database role in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)

## Granting ownership on pipes
To transfer ownership of a pipe, there must be additional conditions met. Otherwise, additional manual work
will be needed afterward or in some cases, the ownership won't be transferred (resulting in error).
Expand Down
2 changes: 2 additions & 0 deletions docs/resources/grant_privileges_to_account_role.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ resource "snowflake_grant_privileges_to_account_role" "example" {
## ID: "\"role_name\"|false|false|SELECT,INSERT|OnSchemaObject|OnFuture|TABLES|InSchema|\"database\".\"my_schema\""
```

-> **Note** If you don't manage referenced objects in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)

<!-- schema generated by tfplugindocs -->
## Schema

Expand Down
2 changes: 2 additions & 0 deletions docs/resources/grant_privileges_to_database_role.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ resource "snowflake_grant_privileges_to_database_role" "example" {
}
```

-> **Note** If you don't manage referenced objects in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)

<!-- schema generated by tfplugindocs -->
## Schema

Expand Down
3 changes: 3 additions & 0 deletions docs/resources/stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ description: |-




## Example Usage

```terraform
Expand Down Expand Up @@ -38,6 +39,8 @@ resource "snowflake_stream" "stream" {
}
```

-> **Note** If you don't manage table in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)

<!-- schema generated by tfplugindocs -->
## Schema

Expand Down
2 changes: 2 additions & 0 deletions docs/resources/table_column_masking_policy_application.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ resource "snowflake_table_column_masking_policy_application" "application" {
}
```

-> **Note** If you don't manage referenced objects in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)

<!-- schema generated by tfplugindocs -->
## Schema

Expand Down
3 changes: 3 additions & 0 deletions docs/resources/table_constraint.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ description: |-




## Example Usage

```terraform
Expand Down Expand Up @@ -97,6 +98,8 @@ resource "snowflake_table_constraint" "unique" {
}
```

-> **Note** If you don't manage table in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)

<!-- schema generated by tfplugindocs -->
## Schema

Expand Down
3 changes: 3 additions & 0 deletions docs/resources/tag_masking_policy_association.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ description: |-

Attach a masking policy to a tag. Requires a current warehouse to be set. Either with SNOWFLAKE_WAREHOUSE env variable or in current session. If no warehouse is provided, a temporary warehouse will be created.


## Example Usage

```terraform
Expand Down Expand Up @@ -58,6 +59,8 @@ resource "snowflake_tag_masking_policy_association" "name" {
}
```

-> **Note** If you don't manage referenced objects in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)

<!-- schema generated by tfplugindocs -->
## Schema

Expand Down
3 changes: 3 additions & 0 deletions docs/resources/user_password_policy_attachment.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ description: |-

Specifies the password policy to use for a certain user.


## Example Usage

```terraform
Expand All @@ -27,6 +28,8 @@ resource "snowflake_user_password_policy_attachment" "ppa" {
}
```

-> **Note** If you don't manage password policy in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)

<!-- schema generated by tfplugindocs -->
## Schema

Expand Down
42 changes: 4 additions & 38 deletions pkg/resources/grant_database_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,44 +153,10 @@ func ReadGrantDatabaseRole(d *schema.ResourceData, meta interface{}) error {

var found bool
for _, grant := range grants {
if grant.GrantedTo == sdk.ObjectType(objectType) {
if grant.GrantedTo == sdk.ObjectTypeRole || grant.GrantedTo == sdk.ObjectTypeShare {
if grant.GranteeName.FullyQualifiedName() == targetIdentifier {
found = true
break
}
} else {
/*
note that grantee_name is not saved as a valid identifier in the
SHOW GRANTS OF DATABASE ROLE <database_role_name> command
for example, "ABC"."test_parent_role" is saved as ABC."test_parent_role"
or "ABC"."test_parent_role" is saved as ABC.test_parent_role
and our internal mapper thereby fails to parse it correctly, returning "ABC."test_parent_role"
so this funny string replacement is needed to make it work
*/
s := grant.GranteeName.FullyQualifiedName()
if !strings.Contains(s, "\"") {
parts := strings.Split(s, ".")
s = sdk.NewDatabaseObjectIdentifier(parts[0], parts[1]).FullyQualifiedName()
} else {
parts := strings.Split(s, "\".\"")
if len(parts) < 2 {
parts = strings.Split(s, "\".")
if len(parts) < 2 {
parts = strings.Split(s, ".\"")
if len(parts) < 2 {
s = strings.Trim(s, "\"")
parts = strings.Split(s, ".")
}
}
}
s = sdk.NewDatabaseObjectIdentifier(parts[0], parts[1]).FullyQualifiedName()
}
if s == targetIdentifier {
found = true
break
}
}
if grant.GrantedTo == sdk.ObjectType(objectType) &&
sfc-gh-jcieslak marked this conversation as resolved.
Show resolved Hide resolved
grant.GranteeName.FullyQualifiedName() == targetIdentifier {
found = true
break
}
}
if !found {
Expand Down
42 changes: 42 additions & 0 deletions pkg/resources/grant_database_role_acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,45 @@ func TestAcc_GrantDatabaseRole_share(t *testing.T) {
},
})
}

func TestAcc_GrantDatabaseRole_shareWithDots(t *testing.T) {
databaseId := acc.TestClient().Ids.RandomAccountObjectIdentifier()
databaseRoleId := acc.TestClient().Ids.RandomDatabaseObjectIdentifierInDatabase(databaseId)
shareId := acc.TestClient().Ids.RandomAccountObjectIdentifierContaining(".")

configVariables := func() config.Variables {
return config.Variables{
"database": config.StringVariable(databaseId.Name()),
"database_role_name": config.StringVariable(databaseRoleId.Name()),
"share_name": config.StringVariable(shareId.Name()),
}
}
resourceName := "snowflake_grant_database_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.CheckGrantDatabaseRoleDestroy(t),
Steps: []resource.TestStep{
{
ConfigDirectory: config.StaticDirectory("testdata/TestAcc_GrantDatabaseRole/share"),
ConfigVariables: configVariables(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "database_role_name", databaseRoleId.FullyQualifiedName()),
resource.TestCheckResourceAttr(resourceName, "share_name", shareId.Name()),
resource.TestCheckResourceAttr(resourceName, "id", fmt.Sprintf(`%v|%v|%v`, databaseRoleId.FullyQualifiedName(), "SHARE", shareId.FullyQualifiedName())),
),
},
// test import
{
ConfigDirectory: config.StaticDirectory("testdata/TestAcc_GrantDatabaseRole/share"),
ConfigVariables: configVariables(),
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
19 changes: 1 addition & 18 deletions pkg/sdk/grants.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,24 +229,7 @@ func (v *Grant) ID() ObjectIdentifier {
func (row grantRow) convert() *Grant {
grantedTo := ObjectType(strings.ReplaceAll(row.GrantedTo, "_", " "))
grantTo := ObjectType(strings.ReplaceAll(row.GrantTo, "_", " "))
var granteeName AccountObjectIdentifier
if grantedTo == ObjectTypeShare {
// TODO(SNOW-1058419): Change this logic during identifiers rework
parts := strings.Split(row.GranteeName, ".")
switch {
case len(parts) == 1:
granteeName = NewAccountObjectIdentifier(parts[0])
case len(parts) == 2:
granteeName = NewAccountObjectIdentifier(parts[1])
default:
fallback := row.GranteeName[strings.IndexRune(row.GranteeName, '.')+1:]
log.Printf("unsupported case for share's grantee name: %s Falling back to account object identifier: %s", row.GranteeName, fallback)
granteeName = NewAccountObjectIdentifier(fallback)
}
} else {
granteeName = NewAccountObjectIdentifier(row.GranteeName)
}

granteeName := NewAccountObjectIdentifier(row.GranteeName)
var grantedOn ObjectType
// true for current grants
if row.GrantedOn != "" {
Expand Down
17 changes: 17 additions & 0 deletions pkg/sdk/grants_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"log"
"slices"
"strings"

"github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk/internal/collections"

Expand Down Expand Up @@ -261,6 +262,22 @@ func (v *grants) Show(ctx context.Context, opts *ShowGrantOptions) ([]Grant, err
}
logging.DebugLogger.Printf("[DEBUG] Show grants: converting rows")
resultList := convertRows[grantRow, Grant](dbRows)
for i, grant := range resultList {
// SHOW GRANTS of DATABASE ROLE requires a special handling:
// - it returns no account name, so for other SHOW GRANTS types it needs to be skipped
// - it returns fully qualified name for database objects
if !(valueSet(opts.Of) && valueSet(opts.Of.DatabaseRole)) {
if grant.GrantedTo == ObjectTypeShare {
oldId := grant.GranteeName.Name()
skipAccount := oldId[strings.IndexRune(oldId, '.')+1:]
resultList[i].GranteeName = NewAccountObjectIdentifier(skipAccount)
}
} else {
if grant.GrantedTo != ObjectTypeRole && grant.GrantedTo != ObjectTypeShare {
resultList[i].GranteeName = NewDatabaseObjectIdentifierFromFullyQualifiedName(grant.GranteeName.FullyQualifiedName())
sfc-gh-jcieslak marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
logging.DebugLogger.Printf("[DEBUG] Show grants: rows converted")
return resultList, nil
}
Expand Down
23 changes: 23 additions & 0 deletions templates/guides/identifiers.md.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
page_title: "Identifiers rework"
subcategory: ""
description: |-

---
# Identifiers rework

## New computed fully qualified name field in resources

With the combination of quotes, old parsing methods, and other factors, it was a struggle to specify the fully qualified name of an object needed (e.g. [#2164](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2164), [#2754](https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/2754)). Now, with v0.95.0, every resource that represents an object in Snowflake (e.g. user, role), and not an association (e.g. grants) will have a new computed field named `fully_qualified_name`. With the new computed field, it will be much easier to use resources requiring fully qualified names, for examples of usage head over to the [documentation for granting privileges to account role](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_privileges_to_account_role).

For example, instead of writing

```object_name = “\”${snowflake_table.database}\”.\”${snowflake_table.schema}\”.\”${snowflake_table.name}\””```

now we can write

```object_name = snowflake_table.fully_qualified_name```

If you don't manage table in Terraform, you can construct the proper id yourself like before: `"\"database_name\".\"schema_name\".\"table_name\""`

<!--- TODO: fill the rest of the document -->
32 changes: 32 additions & 0 deletions templates/resources/account_password_policy_attachment.md.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}"
subcategory: ""
description: |-
{{ if gt (len (split .Description "<deprecation>")) 1 -}}
{{ index (split .Description "<deprecation>") 1 | plainmarkdown | trimspace | prefixlines " " }}
{{- else -}}
{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
{{- end }}
---

# {{.Name}} ({{.Type}})

{{ .Description | trimspace }}


## Example Usage

{{ tffile (printf "examples/resources/%s/resource.tf" .Name)}}

-> **Note** If you don't manage password policy in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)

{{ .SchemaMarkdown | trimspace }}

{{- if .HasImport }}

## Import

Import is supported using the following syntax:

{{ codefile "shell" (printf "examples/resources/%s/import.sh" .Name)}}
{{- end }}
2 changes: 2 additions & 0 deletions templates/resources/grant_ownership.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ description: |-
## Example Usage

{{ tffile (printf "examples/resources/%s/resource.tf" .Name)}}

-> **Note** If you don't manage database role in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)
{{- end }}

## Granting ownership on pipes
Expand Down
2 changes: 2 additions & 0 deletions templates/resources/grant_privileges_to_account_role.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ description: |-
## Example Usage

{{ tffile (printf "examples/resources/%s/resource.tf" .Name)}}

-> **Note** If you don't manage referenced objects in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)
sfc-gh-asawicki marked this conversation as resolved.
Show resolved Hide resolved
{{- end }}

{{ .SchemaMarkdown | trimspace }}
Expand Down
2 changes: 2 additions & 0 deletions templates/resources/grant_privileges_to_database_role.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ description: |-
## Example Usage

{{ tffile (printf "examples/resources/%s/resource.tf" .Name)}}

-> **Note** If you don't manage referenced objects in Terraform, you can construct the proper id yourself, consult [identifiers guide](../guides/identifiers#new-computed-fully-qualified-name-field-in-resources)
{{- end }}

{{ .SchemaMarkdown | trimspace }}
Expand Down
Loading
Loading