Propagate create before destroy behavior to dependencies #31316
Description
Resources that depend on other resources should follow the lifecycle of the key resource when it is replaced.
Current Terraform Version
Terraform v1.2.0
Use-cases
I want to provision an AWS Security Group and I want to be able to modify it without a service outage. To support this, I set the lifecycle create_before_destroy
option to true
. This means that when a new security group needs to replace an old one (which can be triggered by simply changing its name), the new one will be ready and can be associated with other resources before the old one is destroyed.
However, a security group, in the AWS provider v4.0 model, does not directly have rules. (Use of inline rules is not recommended for many reasons, see References below.) Instead, rules are created for a security group by the aws_security_group_rule
resource. A security group will not function as intended until all of its rules are created. This creates a problem.
I cannot set create_before_destroy
to true
on the aws_security_group_rule
resources because of hashicorp/terraform-provider-aws#25173. Likely even if that bug were fixed, there would be other problems (see issues referenced in that issue) making it unwise to set create_before_destroy
to true
on the aws_security_group_rule
resources as a general proposition, because of the difficulty in ensuring that the new rules do not duplicate the existing rules, perhaps as a consequence of changing positions in a list and using count
. The issue here is avoiding duplicate rules in an existing security group.
So, if I make changes to the security group rules, the old ones are deleted before the new ones are created. This does create a brief outage, but the only fix for this would be for the provider to see that it is deleting and recreating identical resources and to move them instead. That would be a great feature, but seems too much to ask, so I will accept this limitation. (On the other hand, I will open a a feature request and or suggested bug fix for hashicorp/terraform-provider-aws#25173 and a bunch of related bugs if you think it will receive serious consideration. Just point the way.)
However, if I make a change to the security group itself, currently this is the order of operations:
- Destroy the existing security group rules
- Create the new security group
- Create the new security group rules
- Destroy the deposed security group
Attempted Solutions
I tried using a null_resource
that depended on the rules and had create_before_destroy = true
, triggered by the security group ID, but that caused the problematic create_before_destroy
behavior on the rules even when the security group ID did not change. In fact, just the declaration of the null_resource
with depends_on
triggered the behavior, even if the resource was not created because of count = 0
. (Is this a bug?)
Click to reveal configuration
Changing the value of var.cidr
in this example causes "create replacement and then destroy" behavior for aws_security_group_rule.example
, even though no changes were planned for the security group or the null resource. I would like Terraform to destroy the rule first, since the security group ID is not changing.
resource "aws_security_group" "cbd" {
vpc_id = aws_vpc.example.id
lifecycle {
create_before_destroy = true
}
}
resource "aws_security_group_rule" "example" {
security_group_id = aws_security_group.cbd.id
type = "egress"
from_port = 0
to_port = 0 # [sic] from and to port ignored when protocol is "-1", warning if not zero
protocol = "-1"
description = "Allow ingress from VPC"
cidr_blocks = [var.sg_cidr]
lifecycle {
create_before_destroy = false
}
}
resource "null_resource" "rules" {
count = 0
# Replacement of the security group requires re-provisioning
triggers = {
sg_id = aws_security_group.cbd.id
}
depends_on = [aws_security_group_rule.example]
lifecycle {
create_before_destroy = true
}
}
Proposal
While I do not expect Terraform to know the intimate details of the resource dependencies and requirements, in this particular case, Terraform does know that the rules are being replaced because the security group ID is changing (plan
flags this as forcing replacement). In this particular situation, I would like Terraform to see that the resource is being replaced because of a resource that has create before destroy behavior, and for this particular plan, implement the same behavior for the dependent resource. So the order of operations would be:
- Create the new security group
- Create the new security group rules
- Destroy the deposed security group rules
- Destroy the deposed security group
It would be fine with me if this were configurable via lifecycle or dependency (or other) blocks. The key factor here is that for rules, the create before destroy behavior is desirable and only practical when the security group they depend on is changing. So I would like that behavior to be inherited from the security group's lifecycle when that is the trigger for replacing them.