-
Notifications
You must be signed in to change notification settings - Fork 10
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
Update resource lifecycle #60
Comments
Have you seen this? There is update support in the latest version. |
A PR is welcomed if you find something missing or broken! Thanks for your interest |
It seems I missed your reply, sorry! Actually, I haven't seen the update for delete lifecycle, but it doesn't solve our issue. May I describe what we are doing: Example: resource "snowsql_exec" "eap_cmdb_inventory" {
name = "eap_cmdb_inventory"
create {
number_of_statements = 1
statements = <<-EOT
MERGE INTO registry t
USING (
SELECT
'${upper(var.app_name)}' AS application_name,
'${var.owner}' AS owner,
'${var.accounting_number}' AS accounting_number,
'${var.version}' AS version,
parse_json('${jsonencode(var.stages)}') AS stages
) s ON t.application_name = s.application_name
WHEN MATCHED THEN UPDATE SET
t.owner = s.owner,
t.accounting_number = s.accounting_number,
t.version = s.version,
t.stages = s.stages
WHEN NOT MATCHED THEN INSERT (application_name, owner, accounting_number, version, stages)
VALUES (s.application_name, s.owner, s.accounting_number, s.version, s.stages)
;
EOT
}
delete {
number_of_statements = 1
statements = <<-EOT
DELETE FROM registry WHERE APPLICATION_NAME='${upper(var.app_name)}';
EOT
}
} I understand you wanted to make sure that the create statement doesn't change during the lifecycle - I do understand that, that could yield some pretty weird behavior if not noticed. Would it be possible to add an additional "update" lifecycle command, where we could duplicate the MERGE statement, so that it is clear that will only be called if the resource already exists in the state? Or do you have any other recommendation? |
I like your suggestion for adding an Would this be something you would be interested in contributing to the project? |
My Go is a bit rusty, but I'll give it a try! |
Hi @aidanmelen I've discussed this with a colleague. In our opinion, there are two possibilities:
I'm leaning towards the second option, so code must not be duplicated. Or maybe implementing both, but one could only set one of What do you think? |
Thank you for providing multiple solutions. To ensure the most comprehensive approach, only the addition or change to the It's important to understand Terraform lifecycles and Snowflake's object alteration behavior when implementing updates. When the update block is provided during the update lifecycle, the For instance, consider recreating the snowflake_user resource using the -- create
CREATE USER IF NOT EXISTS user1 PASSWORD='abc123' DEFAULT_ROLE = myrole DEFAULT_SECONDARY_ROLES = ('ALL') MUST_CHANGE_PASSWORD = TRUE;
-- read
SHOW USERS LIKE '%user1%';
-- update
ALTER USER IF EXISTS user1 SET EMAIL = 'user1@email.com';
-- delete
DROP USER IF EXISTS user1; The equivalent Terraform code would look like this: resource "snowsql_exec" "dcl" {
name = local.name
create {
statements = "CREATE USER IF NOT EXISTS user1 PASSWORD='abc123' DEFAULT_ROLE = myrole DEFAULT_SECONDARY_ROLES = ('ALL') MUST_CHANGE_PASSWORD = TRUE;"
}
delete {
statements = "DROP USER IF EXISTS user1;"
}
} On the first apply, the resource "snowsql_exec" "dcl" {
name = local.name
create {
statements = "CREATE USER IF NOT EXISTS user1 PASSWORD='abc123' DEFAULT_ROLE = myrole DEFAULT_SECONDARY_ROLES = ('ALL') MUST_CHANGE_PASSWORD = TRUE;"
}
update {
statements = "ALTER USER IF EXISTS user1 SET EMAIL = 'user1@email.com';"
}
delete {
statements = "DROP USER IF EXISTS user1;"
}
} What's more, all future changes to the update block should result in the in-place update. Note that implementing updates is a delicate process as in most cases the operator cannot simply copy and paste the |
We can keep our Terraform code DRY and maintain control over the Snowflake statements by using the built-in lifecycle meta-argument. Instead of having two similar but different locals {
merge_statement = <<-EOT
MERGE INTO registry t
USING (
SELECT
'${upper(var.app_name)}' AS application_name,
'${var.owner}' AS owner,
'${var.accounting_number}' AS accounting_number,
'${var.version}' AS version,
parse_json('${jsonencode(var.stages)}') AS stages
) s ON t.application_name = s.application_name
WHEN MATCHED THEN UPDATE SET
t.owner = s.owner,
t.accounting_number = s.accounting_number,
t.version = s.version,
t.stages = s.stages
WHEN NOT MATCHED THEN INSERT (application_name, owner, accounting_number, version, stages)
VALUES (s.application_name, s.owner, s.accounting_number, s.version, s.stages)
;
EOT
}
resource "snowsql_exec" "eap_cmdb_inventory" {
name = "eap_cmdb_inventory"
create {
statements = local.merge_statement
}
update {
statements = local.merge_statement
}
delete {
statements = "DELETE FROM registry WHERE APPLICATION_NAME='${upper(var.app_name)}';"
}
lifecycle {
ignore_changes = [
create,
]
}
} The update statements are still executed whenever the I would rather use the |
I haven't thought of that option, that's much more flexible and also even straight-forward to implement. I'll update the PR asap. |
Thanks @christophkreutzer, nice work on the new release (v1.1.0)! |
Hi,
I wanted to ask if it was a deliberate decision to only allow create/delete, but no update lifecycle? We have a use case where it would be "more beautiful" if it could be seen as "in-place update" instead of a force replacement.
Would you be open for a PR on that topic?
The text was updated successfully, but these errors were encountered: