-
Notifications
You must be signed in to change notification settings - Fork 10.1k
Description
Not positive if this is a Terraform bug or a provider bug, but seems more like a core Terraform bug to me.
In the code below, when a new security group replaces the old one via create_before_destroy, Terraform does not update the VPC endpoint in the same plan/apply cycle. With other resources (such as aws_elasticache_replication_group) it is even more problematic because without updating the resource, Terraform will not remove the resource from the security group, and then AWS will refuse to destroy it, leading to an apply-time failure.
Workaround seems to be to remove compact(). Please provide another workaround if possible.
Terraform Version
Terraform v1.0.9
on darwin_amd64
+ provider registry.terraform.io/hashicorp/aws v3.63.0
Terraform Configuration Files
Click to reveal
variable "region" {
type = string
default = "us-east-2"
}
provider "aws" {
region = var.region
}
variable "sg_name" {
type = string
default = ""
}
resource "aws_vpc" "main" {
cidr_block = "10.111.0.0/16"
}
variable "associated_security_group_ids" {
type = list(string)
default = []
}
variable "existing_security_groups" {
type = list(string)
default = []
}
locals {
associated_security_group_ids = concat(var.existing_security_groups, var.associated_security_group_ids)
}
module "ingress" {
source = "cloudposse/security-group/aws"
version = "0.4.2"
create_before_destroy = true
security_group_name = length(var.sg_name) > 0 ? [var.sg_name] : []
allow_all_egress = false
vpc_id = aws_vpc.main.id
rules = [{
key = "allow_all_ingress"
type = "ingress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
description = "Allow all inbound traffic"
}]
}
module "egress" {
source = "cloudposse/security-group/aws"
version = "0.4.2"
create_before_destroy = true
allow_all_egress = true
vpc_id = aws_vpc.main.id
}
resource "aws_vpc_endpoint" "ec2" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${var.region}.ec2"
vpc_endpoint_type = "Interface"
security_group_ids = compact(concat(local.associated_security_group_ids, [
module.ingress.id,
module.egress.id,
]))
private_dns_enabled = false
}Steps to Reproduce
terraform initterraform applytf1 apply -var sg_name="first_replacement" -parallelism=1tf1 apply -var sg_name="first_replacement" -parallelism=1
Expected Behavior
The first tf1 apply -var sg_name="first_replacement" -parallelism=1 should create a new security group, update the aws_vpc_endpoint resource, replacing the old security group with the new one, then delete the old security group.
The second tf1 apply -var sg_name="first_replacement" -parallelism=1 should do nothing
Actual Behavior
The first tf1 apply -var sg_name="first_replacement" -parallelism=1 creates a new security group and deletes the old security group.
The second tf1 apply -var sg_name="first_replacement" -parallelism=1 updates the aws_vpc_endpoint resource, replacing the old security group with the new one.
Additional Context
If you replace
security_group_ids = compact(concat(local.associated_security_group_ids, [
module.ingress.id,
module.egress.id,
]))with
security_group_ids = concat(local.associated_security_group_ids, [
module.ingress.id,
module.egress.id,
])removing the compact() operation, then Terraform works as expected.