-
Notifications
You must be signed in to change notification settings - Fork 426
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
Breaking migration from deprecated to new grant types #2340
Comments
@jakemingolla As you described when removing one and creating the other some race conditions may occur. We can avoid such issues and achieve the "no downtime" update by changing the Terraform configuration and altering the state, so Terraform wouldn't have to run anything on the infra (because we'll only change the state). You can achieve it by following this guide, but to show my point I'll make step-by-step with your case. Let's start with the config resource "snowflake_database" "test" {
name = "snow_test_db"
}
resource "snowflake_role" "a" {
name = "snow_test_role_a"
}
resource "snowflake_role" "b" {
name = "snow_test_role_b"
}
resource "snowflake_database_grant" "old" {
depends_on = [ snowflake_database.test, snowflake_role.a, snowflake_role.b ]
database_name = snowflake_database.test.name
privilege = "USAGE"
roles = [ snowflake_role.a.name, snowflake_role.b.name ]
}
# resource "snowflake_grant_privileges_to_role" "new" {
# depends_on = [ snowflake_database.test, snowflake_role.a, snowflake_role.b ]
# for_each = toset([ snowflake_role.a.name, snowflake_role.b.name ])
# privileges = [ "USAGE" ]
# role_name = each.key
# on_account_object {
# object_type = "DATABASE"
# object_name = snowflake_database.test.name
# }
#
terraform import 'snowflake_grant_privileges_to_role.new["snow_test_role_a"]' "snow_test_role_a|USAGE|false|false|false|true|false|false|false|false|DATABASE|snow_test_db||false||false||"
terraform import 'snowflake_grant_privileges_to_role.new["snow_test_role_b"]' "snow_test_role_b|USAGE|false|false|false|true|false|false|false|false|DATABASE|snow_test_db||false||false||" After that sequence of steps, grants should be granted as they were and Terraform shouldn't produce any plan when the
I hope this helps :) |
Hi @sfc-gh-jcieslak, thanks for the quick response! After reading through the recommended approach, I'm not sure how well this will work in practice with hundreds of grants across multiple roles in separate Snowflake accounts. Relying on human intervention to remove and import each grant is likely to be error prone and difficult to synchronize across Terraform configurations. Do you know if there are any examples of public repositories undergoing migrations for large Terraform configurations to use as a blueprint? One potential workaround I've been thinking about would be if it would be possible to add functionality to the deprecated role grant types to ignore roles not directly controlled by the resource. This would allow new In addition, reducing the Let me know if any of the above needs clarification. |
I believe this can be somewhat achieved by lifecycle meta-tags. For example resource "snowflake_database_grant" "grant" {
# ...
lifecycle {
ignore_changes = all
}
} will ignore all changes to the parameters and won't update (afaik this doesn't prevent from creating or deleting, so before deleting the resource it would be best to remove it from the state and let the
I know that grant resources may be hard to migrate manually, but on the other hand, the resource could be generated with a simple scripts that would minimize human error. But before that, I highly recommend waiting a bit for the We are aware that migrating a large amount of resources (mostly that's the case for grant resources) can be hard and we have plans to consider introducing a tool for automated migrations, but right now we don't have the capacity to do so. |
With the lifecycle meta argument, will that also account for other competing terraform resources for grants on the same Snowflake object? For example, after applying:
Would the |
Any change (by another resource or manually) in Snowflake won't be considered by the resource when resource "snowflake_database" "db" {
name = "test-db"
}
resource "snowflake_role" "test_role" {
name = "test_role_321"
}
resource "snowflake_database_grant" "a" {
database_name = snowflake_database.db.name
privilege = "USAGE"
roles = [
snowflake_role.test_role.name,
]
# lifecycle {
# ignore_changes = all
# }
} Run the configuration above (with lifecycle commented). See that the database has usage granted: show grants on database "test-db"; Revoke usage manually: revoke usage on database "test-db" from role "test_role_321"; Run |
@jakemingolla Hey 👋 can we close the issue or is there anything else you would like to know? |
sure, feel free to close it |
Terraform CLI and Provider Versions
Terraform Configuration
Expected Behavior
Overview
This series of steps will introduce an incompatibility between
snowflake_database_grant
andsnowflake_grant_privileges_to_role
for the same underlying Snowflake resource. Attempting to upgrade between the two is prone to a race condition where grants on the same resource overwrite each other. Furthermore, subsequents plans using the two terraform resources causes a permanent diff due to contention for grants on the same resource.Baseline
Applying the above configuration creates expected grants on the resources:
Attempted upgrade to
snowflake_grant_privileges_to_role
Then, change
ROLE_B
to be grantedUSAGE
via a separatesnowflake_grant_privileges_to_role
resource:This results in the follow plan:
During the apply, the following output is produced
Warning
Note the order of operations between the start & end of the modifications and creation of role grants
Race condition
There is a race condition when contending for the
USAGE
grants on theROLE_TESTING
database. Looking at the history of the grants applied in terraform (read top to bottom in chronologically descending order):Because the
GRANT
completes before theREVOKE
the resulting grants are not as expected:"Fixing" it
Attempting to re-plan the configuration yields the following:
After re-applying, both roles are successfully granted
USAGE
to the databaseHowever...
Subsequent plans are polluted with the following diff:
Note
The
snowflake_database_grant
no longer managesROLE_B
, that is handled by the non-deprecatedsnowflake_grant_privileges_to_role
Actual Behavior
As shown above, sharing Snowflake resources between
snowflake_database_grant
andsnowflake_grant_privileges_to_role
terraform constructs results in both broken applies and subsequently confusing plans. This makes migrating from the deprecated role resource types to the newsnowflake_grant_privileges_to_role
almost impossible in a large terraform configuration with hundreds of grants split across a multitude of resources and roles.It would be nice if a dedicated migration guide was provided for migrating off of the deprecated resource types onto the new
snowflake_grant_privileges_to_role
. Simply revoking and re-adding all of the grants in subsequent commits would result in downtime and isn't a reasonable solution for production-grade Snowflake resources we expose to end-user facing roles.(Note that while
snowflake_database_grant
was the sole resource used in the example above it impacts other resource types as well).Steps to Reproduce
See above. I'm happy to provide more details if anything is unclear.
How much impact is this issue causing?
High
Logs
No response
Additional Information
No response
The text was updated successfully, but these errors were encountered: