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: Tag association v1 readiness #3210

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open

Conversation

sfc-gh-jmichalak
Copy link
Collaborator

@sfc-gh-jmichalak sfc-gh-jmichalak commented Nov 20, 2024

  • rework tag_association resource
  • return nil from GetTag instead of failing
  • add more tests regarding tag/masking policy: assert that ALTER MASKING POLICY SET TAG differs from ALTER TAG SET MASKING POLICY
  • support tagging account for identifiers with org name
  • support IF EXISTS for unsetting tags
  • add notes about manually unassigning policies from objects, add a todo with an issue number
  • fix a wrong issue number in essential objects list

Test Plan

  • acceptance tests

References

https://docs.snowflake.com/en/user-guide/object-tagging
https://docs.snowflake.com/en/sql-reference/functions/system_get_tag
#3145
#1910
#2943
#3235

TODO

  • use generated config and asserts, remove old test tf files

Ideas

  • extract a separate resource for tagging accounts?

Copy link

Integration tests failure for 8aa6ea667b3781751030a662948cb08d39c1c647

Copy link

Integration tests failure for f97b0e8b9fdee53a6442fa8b6e76eaf351a5ba06

Copy link

Integration tests success for 818d00b33e87a83140565a1320a695221e9e66c1

}
```

The state is migrated automatically. There is no need to adjust configuration files, unless you use resource id like `snowflake_tag_association.example.id`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't understand this part: There is no need to adjust configuration files, unless you use resource id like snowflake_tag_association.example.id., could you elaborate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Rephrased.

pkg/acceptance/helpers/context_client.go Outdated Show resolved Hide resolved
pkg/resources/tag_association.go Show resolved Hide resolved
ConfigVariables: m(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "object_type", "DATABASE"),
ConfigVariables: m(tagId, tagValue),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why didn't we use model + custom asserts approach 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.

As stated in the TODO section of the PR description, I'll do this in the next PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Used the generated builders for the new tests.

pkg/sdk/system_functions.go Show resolved Hide resolved
}
```

The state is migrated automatically. There is no need to adjust configuration files, unless you use resource id like `snowflake_tag_association.example.id`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: unless you use ... as reference in other resources

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

@@ -9,6 +9,61 @@ across different versions.

## v0.98.0 ➞ v0.99.0

### snowflake_tag_association resource changes
#### *(behavior change)* new id format
In order to provide more functionality for tagging objects, we have changed the resource id from `"TAG_DATABASE"."TAG_SCHEMA"."TAG_NAME"` to `"TAG_DATABASE"."TAG_SCHEMA"."TAG_NAME"|TAG_VALUE|OBJECT_TYPE`. This allows to group tags associations per tag ID, tag value and object type in one resource.
Copy link
Collaborator

Choose a reason for hiding this comment

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

so it means that if I want to add the same tag, same value to the same object type, then I have to put all of them in one resource, right? (here it would mean that changing silver to gold in the second resource is not permitted because both these resources would have the same id)

If I understand this correctly, then I think it would be good to add this info, directly to the resource docs, and here too.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, added more explanation.

@@ -5,6 +5,8 @@ description: |-
Resource used to manage authentication policy objects. For more information, check authentication policy documentation https://docs.snowflake.com/en/sql-reference/sql/create-authentication-policy.
---

-> **Note** According to Snowflake [docs](https://docs.snowflake.com/en/sql-reference/sql/drop-authentication-policy#usage-notes), an authentication policy cannot be dropped successfully if it is currently assigned to another object. Currently, the provider does not unassign such objects automatically. Before dropping the resource, list the assigned objects with `SELECT * from table(information_schema.policy_references(policy_name=>'<string>'));` and unassign them manually with `ALTER ...` or with updated Terraform configuration, if possible.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: maybe even warning for this

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It was done in #3226.

@@ -5,6 +5,8 @@ description: |-
Resource used to manage authentication policy objects. For more information, check authentication policy documentation https://docs.snowflake.com/en/sql-reference/sql/create-authentication-policy.
---

-> **Note** According to Snowflake [docs](https://docs.snowflake.com/en/sql-reference/sql/drop-authentication-policy#usage-notes), an authentication policy cannot be dropped successfully if it is currently assigned to another object. Currently, the provider does not unassign such objects automatically. Before dropping the resource, list the assigned objects with `SELECT * from table(information_schema.policy_references(policy_name=>'<string>'));` and unassign them manually with `ALTER ...` or with updated Terraform configuration, if possible.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's suggest going through terraform config changes in two steps and manual SQL as an alternative. Also, let's add example to guides/ and reference it here.

In guide let's show:

  • the example config creating policy assignment
  • error that will be a result of just a removal
  • step 1 - unnasigning policy (by changing config and running tf plan_apply)
  • step 2 - successful removal

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This change was merged in #3226. I'll add such a guide in a next PR.

tag, err := TestClient().SystemFunctions.GetTag(t, tagId, id, objectType)
if err != nil {
if strings.Contains(err.Error(), "does not exist or not authorized") {
// Note: this can happen if the object has been deleted as well; in this case, ignore the error
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: t.Logf at least in such a case

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

if objectType == string(sdk.ObjectTypeAccount) {
id = sdk.NewAccountIdentifierFromFullyQualifiedName(obj["name"].(string))
} else {
database := obj["database"].(string)
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: there is getTagObjectIdentifier function already; maybe we could extend and use it (or at least use it for the else part)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

return diag.FromErr(err)
}

addedids, removedids := ListDiff(oldIds, newIds)
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: addedIds and removedIds

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

if err != nil {
return diag.FromErr(err)
}
if d.HasChange("tag_value") {
Copy link
Collaborator

Choose a reason for hiding this comment

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

in this two subsequent ifs we do exactly the same "setup" logic:

  • we get the tag value
  • we get the lists of ids (old, new, common)

Let's merge this logic:

  1. If object is removed, unset the tag, no matter the value
  2. If the object is added, set the tag, no matter if the value changed (we just use the new one in all cases)
  3. If object is common, set only if the value changed

It covers all the cases (I guess) but is more straightforward

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

resource.TestCheckResourceAttr(resourceName, "tag_value", tagValue),
),
},
// external change
Copy link
Collaborator

Choose a reason for hiding this comment

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

external change can be either unset or setting to different value which are a bit different, please add also this one.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added.

"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfversion"
)

func TestAcc_TagAssociation(t *testing.T) {
_ = testenvs.GetOrSkipTest(t, testenvs.EnableAcceptance)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we have two more tests, please:

  1. Test with more objects, so that we verify the logic behind added, removed, common (i.e. we have 3 objects, we remove 1 and add 1 and verify all)
  2. Test for object type change (maybe I missed this one) - let's verify forceNew and proper removal of all previous yags

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

sfc-gh-jmichalak added a commit that referenced this pull request Nov 25, 2024
#3215)

<!-- Feel free to delete comments as you fill this in -->
- remove deprecated data sources and resources
- some of the tag related fields are not removed - will be done after
merging
#3210
- some resources (procedures, functions, unsafe_execute) are not removed
- can be done after reworking
- remove deprecated fields in the provider config
- deprecated fields in the resources/data sources that we haven't
reworked are still there
- remove some unused code from `snowflake` package
- remove deprecated `JWT` value from `authenticator`
- improve doc generator, so that the headers are added only in case of
non-empty lists
- I have left some comments in the templates because the generated files
must not be blank
<!-- summary of changes -->

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

## TODO
- remove objects related with tags, procedures, functions,
unsafe_execute
sfc-gh-jmichalak added a commit that referenced this pull request Nov 26, 2024
<!-- Feel free to delete comments as you fill this in -->
Changes included (they are really small or fix some wrong changes done
during tag rework that were not released yet):
- smaller fixes extracted from
https://github.com/Snowflake-Labs/terraform-provider-snowflake/pull/3210/files
- support tagging account for identifiers with org name
- add notes about manually unassigning policies from objects, add a todo
with an issue number
- fix a wrong issue number in essential objects list

Changes NOT included
- rework tag_association resource
- return nil from GetTag instead of failing
- add more tests regarding tag/masking policy: assert that ALTER MASKING
POLICY SET TAG differs from ALTER TAG SET MASKING POLICY
- support IF EXISTS for unsetting tags

<!-- summary of changes -->

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

## References
<!-- issues documentation links, etc  -->
#3210
Copy link

Integration tests failure for b53d7c5c60883896a65720d0a81b8fb529229552

Copy link

Integration tests failure for c856aa87d6273a8cebd47d5826f6432795eb93df

@@ -11,7 +11,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.

-> **Note** According to Snowflake [docs](https://docs.snowflake.com/en/sql-reference/sql/drop-row-access-policy#usage-notes), a row access policy cannot be dropped successfully if it is currently assigned to another object. Currently, the provider does not unassign such objects automatically. Before dropping the resource, list the assigned objects with `SELECT * from table(information_schema.policy_references(policy_name=>'<string>'));` and unassign them manually with `ALTER ...` or with updated Terraform configuration, if possible.
> [!WARNING]
> According to Snowflake [docs](https://docs.snowflake.com/en/sql-reference/sql/drop-row-access-policy#usage-notes), a row access policy cannot be dropped successfully if it is currently assigned to another object. Currently, the provider does not unassign such objects automatically. Before dropping the resource, list the assigned objects with `SELECT * from table(information_schema.policy_references(policy_name=>'<string>'));` and unassign them manually with `ALTER ...` or with updated Terraform configuration, if possible.
Copy link
Collaborator

Choose a reason for hiding this comment

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

why this format? Warning has different one, it won't show properly in the docs as warning section.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants