Skip to content

Terraform loses track of dependency #29799

@Nuru

Description

@Nuru

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

  1. terraform init
  2. terraform apply
  3. tf1 apply -var sg_name="first_replacement" -parallelism=1
  4. tf1 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    explaineda Terraform Core team member has described the root cause of this issue in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions