Terraform v0.7.13
lifecycle {
prevent_destroy = "${var.prevent_destroy}"
ignore_changes = "${var.ignore_changes}"
}
vars.tf
variable "prevent_destroy" {
description = "Block destruction of this resource, typically for DB boxes"
default = true
}
variable "ignore_changes" {
description = "list of strings to ignore differences of"
type = "list"
default = [ "ami", "user_data" ]
}
NOTE: Tried with 'true' both quoted and unquoted, same issue
should have applied with no error, ignore changes in the ami or user_data variables
Error parsing lifecycle for aws_instance[gis]: 2 error(s) decoding:
Please list the steps required to reproduce the issue, for example:
terraform planNOTE: not using variables and using:
lifecycle {
prevent_destroy = true
ignore_changes = [ "ami", "user_data" ]
}
in main.tf results in no error and correct behavior (ignoring changes in AMI anduser_data)
We don't support variables in those since they need to be parsed and handled very early on in Terraform (before interpolations can be processed). We hope to loosen this requirement one day.
In the mean time, I'm going to change the issue to be a bug in order to add better validation and error messages to this case.
It sucks that you can't use a variable here as after you introduced create_timeout and then #10823 got resolved, we have to edit each of our MANY GCE google_compute_instances with adding create_timeout to ignore_changes... It's not a lot of work with find and sed, but it's ugly. So please consider implementing this soon.
Is this a duplicate of #3116?
https://github.com/hashicorp/terraform/issues/3116 is locked, otherwise I would have replied over there. These two issues do seem to be duplicates.
I was trying to use prevent_destroy to protect some important resources I don't want accidentally deleted and ran into this bug (and well https://github.com/hashicorp/terraform/issues/3116).
@zero-below offers a potential solution in that you can create a random_id which allows you to protect any given resource.
The problem is that I'd still like to be able to really override prevent_destroy, but not accidently destroy resources. We need an escape hatch.
It turns out you can terraform state rm random_id.protector and then you've got the ability to taint or destroy the protected resources.
$ terraform apply
null_resource.foo[1]: Creating...
null_resource.foo[0]: Creating...
null_resource.foo[1]: Provisioning with 'local-exec'...
null_resource.foo[0]: Provisioning with 'local-exec'...
null_resource.foo[1] (local-exec): Executing: ["/bin/sh" "-c" "date"]
null_resource.foo[0] (local-exec): Executing: ["/bin/sh" "-c" "date"]
null_resource.foo[0] (local-exec): Wed Mar 21 14:11:42 CDT 2018
null_resource.foo[0]: Creation complete after 0s (ID: 4489514678136010214)
null_resource.foo[1] (local-exec): Wed Mar 21 14:11:42 CDT 2018
null_resource.foo[1]: Creation complete after 0s (ID: 3245413214449441631)
random_id.protector: Creating...
b64: "" => "<computed>"
b64_std: "" => "<computed>"
b64_url: "" => "<computed>"
byte_length: "" => "8"
dec: "" => "<computed>"
hex: "" => "<computed>"
keepers.%: "" => "1"
keepers.ids: "" => "4489514678136010214,3245413214449441631"
random_id.protector: Creation complete after 0s (ID: fk_WthGJY6I)
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
# Verify we can't destroy
$ terraform destroy -target null_resource.foo[0]
null_resource.foo[0]: Refreshing state... (ID: 4489514678136010214)
Error: Error running plan: 1 error(s) occurred:
* random_id.protector: random_id.protector: the plan would destroy this resource, but it currently has lifecycle.prevent_destroy set to true. To avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or adjust the scope of the plan using the -target flag.
$ terraform destroy
null_resource.foo[1]: Refreshing state... (ID: 3245413214449441631)
null_resource.foo[0]: Refreshing state... (ID: 4489514678136010214)
random_id.protector: Refreshing state... (ID: fk_WthGJY6I)
Error: Error running plan: 1 error(s) occurred:
* random_id.protector: random_id.protector: the plan would destroy this resource, but it currently has lifecycle.prevent_destroy set to true. To avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or adjust the scope of the plan using the -target flag.
```
$ terraform state rm random_id.protector
1 items removed.
Item removal successful.
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
null_resource.foo[0]: Refreshing state... (ID: 4489514678136010214)
null_resource.foo[1]: Refreshing state... (ID: 3245413214449441631)
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
Terraform will perform the following actions:
Plan: 1 to add, 0 to change, 0 to destroy.
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
$ terraform taint null_resource.foo.0
The resource null_resource.foo.0 in the module root has been marked as tainted!
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
null_resource.foo[0]: Refreshing state... (ID: 4489514678136010214)
null_resource.foo[1]: Refreshing state... (ID: 3245413214449441631)
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
Terraform will perform the following actions:
-/+ null_resource.foo[0] (tainted) (new resource required)
id: "4489514678136010214" =>
Plan: 2 to add, 0 to change, 1 to destroy.
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
$ terraform apply
null_resource.foo[1]: Refreshing state... (ID: 3245413214449441631)
null_resource.foo[0]: Refreshing state... (ID: 4489514678136010214)
null_resource.foo[0]: Destroying... (ID: 4489514678136010214)
null_resource.foo[0]: Destruction complete after 0s
null_resource.foo[0]: Creating...
null_resource.foo[0]: Provisioning with 'local-exec'...
null_resource.foo[0] (local-exec): Executing: ["/bin/sh" "-c" "date"]
null_resource.foo[0] (local-exec): Wed Mar 21 14:12:03 CDT 2018
null_resource.foo[0]: Creation complete after 0s (ID: 6511311000836372604)
random_id.protector: Creating...
b64: "" => "
b64_std: "" => "
b64_url: "" => "
byte_length: "" => "8"
dec: "" => "
hex: "" => "
keepers.%: "" => "1"
keepers.ids: "" => "6511311000836372604,3245413214449441631"
random_id.protector: Creation complete after 0s (ID: bQx-fJV2ywQ)
Apply complete! Resources: 2 added, 0 changed, 1 destroyed.
$ terraform destroy
null_resource.foo[1]: Refreshing state... (ID: 3245413214449441631)
null_resource.foo[0]: Refreshing state... (ID: 6511311000836372604)
random_id.protector: Refreshing state... (ID: bQx-fJV2ywQ)
Error: Error running plan: 1 error(s) occurred:
```hcl
variable "prevent_machine_destroy" {
description = "Set lifecycle.prevent_destroy on machines"
default = true
}
resource "random_id" "protector" {
count = "${ var.prevent_machine_destroy ? 1 : 0 }"
byte_length = 8
keepers = {
ids = "${join(",", null_resource.foo.*.id)}"
}
lifecycle {
prevent_destroy = true
}
}
resource "null_resource" "foo" {
count = "2"
provisioner "local-exec" {
command = "date"
}
}
I'd also like to see variables usable in lifecycle blocks, not for prevent_destroy, but for AMI updates. It would be nice to have ignore_changes = ["ami"] set so that Amazon releasing a new AMI doesn't surprise me, then setting an "ok_to_update_ami" variable in the tfvars file when I am ready to have all my instances rebuilt with the latest AMI.
Hi all!
Looking back at the history here, it seems that the intended distinction between this issue and #3116 is that #3116 represents the feature request of supporting dynamic ignore_changes and prevent_destroy values while _this_ issue represented the bug that Terraform was producing bad error messages when reporting that it isn't supported today.
Since Terraform 0.12 includes specialized error messages for these scenarios, we're going to close out this one and leave #3116 to represent the feature request.
I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
I'd also like to see variables usable in lifecycle blocks, not for prevent_destroy, but for AMI updates. It would be nice to have ignore_changes = ["ami"] set so that Amazon releasing a new AMI doesn't surprise me, then setting an "ok_to_update_ami" variable in the tfvars file when I am ready to have all my instances rebuilt with the latest AMI.