Skip to content

Commit

Permalink
feat: Upgrade tag SDK (#3126)
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 missing object types
(#1496,
#1862,
#2598)
- adjust show options
- add ifExists to tag queries
- add missing masking policy note about v1 rc
- add integration tests for setting, getting, and unsetting tags,
except:
  - failover group - business critical edition needed
  - alert, password policy, network policy - missing tag handling in SDK
- git repo, iceberg table, budget, classification, replication group -
objects not implemented in the sdk

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

## References
<!-- issues documentation links, etc  -->
https://docs.snowflake.com/en/sql-reference/sql/create-tag
https://docs.snowflake.com/en/user-guide/object-tagging
https://docs.snowflake.com/en/sql-reference/functions/system_get_tag

## TODO
- change GetTag to not fail on null values
- move tag assignments integration tests to a common place
- restrict the list of object types we want to support, instead of all
of them
- rework tag, tag_association resource
- remove tag_masking_policy_association_resource (tag_association will
be used instead)
  • Loading branch information
sfc-gh-jmichalak authored Oct 21, 2024
1 parent 8110138 commit 893b288
Show file tree
Hide file tree
Showing 32 changed files with 673 additions and 215 deletions.
3 changes: 2 additions & 1 deletion docs/resources/masking_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ description: |-
Resource used to manage masking policies. For more information, check masking policies documentation https://docs.snowflake.com/en/sql-reference/sql/create-masking-policy.
---

!> **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_masking_policy (Resource)

Resource used to manage masking policies. For more information, check [masking policies documentation](https://docs.snowflake.com/en/sql-reference/sql/create-masking-policy).
Expand Down Expand Up @@ -74,7 +76,6 @@ EOF
comment = "example masking policy"
}
```

-> **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 Down
2 changes: 1 addition & 1 deletion docs/resources/tag_association.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ resource "snowflake_tag_association" "column_association" {
### Required

- `object_identifier` (Block List, Min: 1) Specifies the object identifier for the tag association. (see [below for nested schema](#nestedblock--object_identifier))
- `object_type` (String) Specifies the type of object to add a tag. Allowed object types: [ACCOUNT APPLICATION APPLICATION PACKAGE DATABASE INTEGRATION NETWORK POLICY ROLE SHARE USER WAREHOUSE DATABASE ROLE SCHEMA ALERT EXTERNAL FUNCTION EXTERNAL TABLE GIT REPOSITORY ICEBERG TABLE MATERIALIZED VIEW PIPE MASKING POLICY PASSWORD POLICY ROW ACCESS POLICY SESSION POLICY PROCEDURE STAGE STREAM TABLE TASK VIEW COLUMN EVENT TABLE].
- `object_type` (String) Specifies the type of object to add a tag. Allowed object types: [ACCOUNT APPLICATION APPLICATION PACKAGE DATABASE FAILOVER GROUP INTEGRATION NETWORK POLICY REPLICATION GROUP ROLE SHARE USER WAREHOUSE DATABASE ROLE SCHEMA ALERT SNOWFLAKE.CORE.BUDGET SNOWFLAKE.ML.CLASSIFICATION EXTERNAL FUNCTION EXTERNAL TABLE FUNCTION GIT REPOSITORY ICEBERG TABLE MATERIALIZED VIEW PIPE MASKING POLICY PASSWORD POLICY ROW ACCESS POLICY SESSION POLICY PRIVACY POLICY PROCEDURE STAGE STREAM TABLE TASK VIEW COLUMN EVENT TABLE].
- `tag_id` (String) Specifies the identifier for the tag. Note: format must follow: "databaseName"."schemaName"."tagName" or "databaseName.schemaName.tagName" or "databaseName|schemaName.tagName" (snowflake_tag.tag.id)
- `tag_value` (String) Specifies the value of the tag, (e.g. 'finance' or 'engineering')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ var allStructs = []SdkObjectDef{
ObjectType: sdk.ObjectTypeStream,
ObjectStruct: sdk.Stream{},
},
{
IdType: "sdk.SchemaObjectIdentifier",
ObjectType: sdk.ObjectTypeTag,
ObjectStruct: sdk.Tag{},
},
}

func GetSdkObjectDetails() []genhelpers.SdkObjectDetails {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package objectassert

import (
"errors"
"fmt"
"slices"
"testing"

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

func (s *TagAssert) HasAllowedValues(expected ...string) *TagAssert {
s.AddAssertion(func(t *testing.T, o *sdk.Tag) error {
t.Helper()
if len(o.AllowedValues) != len(expected) {
return fmt.Errorf("expected allowed values length: %v; got: %v", len(expected), len(o.AllowedValues))
}
var errs []error
for _, wantElem := range expected {
if !slices.ContainsFunc(o.AllowedValues, func(gotElem string) bool {
return wantElem == gotElem
}) {
errs = append(errs, fmt.Errorf("expected value: %s, to be in the value list: %v", wantElem, o.AllowedValues))
}
}
return errors.Join(errs...)
})
return s
}
109 changes: 109 additions & 0 deletions pkg/acceptance/bettertestspoc/assert/objectassert/tag_snowflake_gen.go

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

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

25 changes: 20 additions & 5 deletions pkg/acceptance/helpers/tag_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,27 @@ func (c *TagClient) CreateTag(t *testing.T) (*sdk.Tag, func()) {
return c.CreateTagInSchema(t, c.ids.SchemaId())
}

func (c *TagClient) CreateTagWithIdentifier(t *testing.T, id sdk.SchemaObjectIdentifier) (*sdk.Tag, func()) {
t.Helper()
return c.CreateWithRequest(t, sdk.NewCreateTagRequest(id))
}

func (c *TagClient) CreateTagInSchema(t *testing.T, schemaId sdk.DatabaseObjectIdentifier) (*sdk.Tag, func()) {
t.Helper()
ctx := context.Background()
return c.CreateWithRequest(t, sdk.NewCreateTagRequest(c.ids.RandomSchemaObjectIdentifierInSchema(schemaId)))
}

id := c.ids.RandomSchemaObjectIdentifierInSchema(schemaId)
func (c *TagClient) CreateWithRequest(t *testing.T, req *sdk.CreateTagRequest) (*sdk.Tag, func()) {
t.Helper()
ctx := context.Background()

err := c.client().Create(ctx, sdk.NewCreateTagRequest(id))
err := c.client().Create(ctx, req)
require.NoError(t, err)

tag, err := c.client().ShowByID(ctx, id)
tag, err := c.client().ShowByID(ctx, req.GetName())
require.NoError(t, err)

return tag, c.DropTagFunc(t, id)
return tag, c.DropTagFunc(t, req.GetName())
}

func (c *TagClient) DropTagFunc(t *testing.T, id sdk.SchemaObjectIdentifier) func() {
Expand All @@ -53,3 +61,10 @@ func (c *TagClient) DropTagFunc(t *testing.T, id sdk.SchemaObjectIdentifier) fun
require.NoError(t, err)
}
}

func (c *TagClient) Show(t *testing.T, id sdk.SchemaObjectIdentifier) (*sdk.Tag, error) {
t.Helper()
ctx := context.Background()

return c.client().ShowByID(ctx, id)
}
1 change: 1 addition & 0 deletions pkg/resources/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ var tagSchema = map[string]*schema.Schema{
FullyQualifiedNameAttributeName: schemas.FullyQualifiedNameSchema,
}

// TODO(SNOW-1348114, SNOW-1348110, SNOW-1348355, SNOW-1348353): remove after rework of external table, materialized view, stage and table
var tagReferenceSchema = &schema.Schema{
Type: schema.TypeList,
Optional: true,
Expand Down
9 changes: 9 additions & 0 deletions pkg/sdk/object_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const (
ObjectTypeNetworkPolicy ObjectType = "NETWORK POLICY"
ObjectTypePasswordPolicy ObjectType = "PASSWORD POLICY"
ObjectTypeSessionPolicy ObjectType = "SESSION POLICY"
ObjectTypePrivacyPolicy ObjectType = "PRIVACY POLICY"
ObjectTypeReplicationGroup ObjectType = "REPLICATION GROUP"
ObjectTypeFailoverGroup ObjectType = "FAILOVER GROUP"
ObjectTypeConnection ObjectType = "CONNECTION"
Expand Down Expand Up @@ -56,6 +57,8 @@ const (
ObjectTypeFileFormat ObjectType = "FILE FORMAT"
ObjectTypePipe ObjectType = "PIPE"
ObjectTypeAlert ObjectType = "ALERT"
ObjectTypeBudget ObjectType = "SNOWFLAKE.CORE.BUDGET"
ObjectTypeClassification ObjectType = "SNOWFLAKE.ML.CLASSIFICATION"
ObjectTypeApplication ObjectType = "APPLICATION"
ObjectTypeApplicationPackage ObjectType = "APPLICATION PACKAGE"
ObjectTypeApplicationRole ObjectType = "APPLICATION ROLE"
Expand Down Expand Up @@ -98,6 +101,7 @@ func objectTypeSingularToPluralMap() map[ObjectType]PluralObjectType {
ObjectTypeNetworkPolicy: PluralObjectTypeNetworkPolicies,
ObjectTypePasswordPolicy: PluralObjectTypePasswordPolicies,
ObjectTypeSessionPolicy: PluralObjectTypeSessionPolicies,
ObjectTypePrivacyPolicy: PluralObjectTypePrivacyPolicies,
ObjectTypeReplicationGroup: PluralObjectTypeReplicationGroups,
ObjectTypeFailoverGroup: PluralObjectTypeFailoverGroups,
ObjectTypeConnection: PluralObjectTypeConnections,
Expand Down Expand Up @@ -129,6 +133,8 @@ func objectTypeSingularToPluralMap() map[ObjectType]PluralObjectType {
ObjectTypeFileFormat: PluralObjectTypeFileFormats,
ObjectTypePipe: PluralObjectTypePipes,
ObjectTypeAlert: PluralObjectTypeAlerts,
ObjectTypeBudget: PluralObjectTypeBudgets,
ObjectTypeClassification: PluralObjectTypeClassifications,
ObjectTypeApplication: PluralObjectTypeApplications,
ObjectTypeApplicationPackage: PluralObjectTypeApplicationPackages,
ObjectTypeApplicationRole: PluralObjectTypeApplicationRoles,
Expand Down Expand Up @@ -206,6 +212,7 @@ const (
PluralObjectTypeNetworkPolicies PluralObjectType = "NETWORK POLICIES"
PluralObjectTypePasswordPolicies PluralObjectType = "PASSWORD POLICIES"
PluralObjectTypeSessionPolicies PluralObjectType = "SESSION POLICIES"
PluralObjectTypePrivacyPolicies PluralObjectType = "PRIVACY POLICIES"
PluralObjectTypeReplicationGroups PluralObjectType = "REPLICATION GROUPS"
PluralObjectTypeFailoverGroups PluralObjectType = "FAILOVER GROUPS"
PluralObjectTypeConnections PluralObjectType = "CONNECTIONS"
Expand Down Expand Up @@ -237,6 +244,8 @@ const (
PluralObjectTypeFileFormats PluralObjectType = "FILE FORMATS"
PluralObjectTypePipes PluralObjectType = "PIPES"
PluralObjectTypeAlerts PluralObjectType = "ALERTS"
PluralObjectTypeBudgets PluralObjectType = "SNOWFLAKE.CORE.BUDGET"
PluralObjectTypeClassifications PluralObjectType = "SNOWFLAKE.ML.CLASSIFICATION"
PluralObjectTypeApplications PluralObjectType = "APPLICATIONS"
PluralObjectTypeApplicationPackages PluralObjectType = "APPLICATION PACKAGES"
PluralObjectTypeApplicationRoles PluralObjectType = "APPLICATION ROLES"
Expand Down
Loading

0 comments on commit 893b288

Please sign in to comment.