terraform-aws-modules / terraform-aws-transit-gateway

Terraform module to create AWS Transit Gateway resources 🇺🇦
https://registry.terraform.io/modules/terraform-aws-modules/transit-gateway/aws
Apache License 2.0
141 stars 224 forks source link

always diff on transit_gateway_default_route_table_association = false -> true #90

Closed vainkop closed 1 year ago

vainkop commented 1 year ago

Description

I'm using this module to provision TGW & TGW attachments in multiaccount environment. Everything works however on every terraform plan I see a diff for transit_gateway_default_route_table_association = true -> false

There is a related issue with a workaround provided here but lifecycle can be used only inside the resource which means that only the owner of the module can implement it or I have to pull the code into my repo which is undesired.

  transit_gateway_default_route_table_association = false
  transit_gateway_default_route_table_propagation = false

  lifecycle {
    ignore_changes = [
      transit_gateway_default_route_table_association,
      transit_gateway_default_route_table_propagation
    ]
  }

Versions

Reproduction Code [Required]

module "tgw" {
  source  = "terraform-aws-modules/transit-gateway/aws"
  version = "= 2.8.1"

  name        = local.name
  description = "TGW shared with several other AWS accounts"

  create_tgw = var.create_tgw
  share_tgw  = var.share_tgw

  amazon_side_asn = 64532
  enable_auto_accept_shared_attachments = var.enable_auto_accept_shared_attachments

  enable_mutlicast_support = var.enable_mutlicast_support
  ram_resource_share_arn   = var.ram_resource_share_arn

  enable_default_route_table_association = false
  enable_default_route_table_propagation = true

  vpc_attachments = {
    "${var.env}-vpc" = {
      vpc_id       = module.vpc.vpc_id
      tgw_id       = var.tgw_id
      subnet_ids   = module.vpc.private_subnets
      dns_support  = var.enable_dns_support_tgw
      ipv6_support = false

      transit_gateway_default_route_table_association = var.create_tgw ? true : false
      transit_gateway_default_route_table_propagation = var.create_tgw ? false : true
    }
  }

  ram_allow_external_principals = true
  ram_principals                = var.ram_principals
  tags = {
    topology = var.create_tgw ? "hub" : "spoke"
  }
}

locals {
  subaccount_vpc_attachments = var.create_tgw ? compact([for x in tolist(data.aws_ec2_transit_gateway_vpc_attachments.filtered[0].ids) : x == module.tgw.ec2_transit_gateway_vpc_attachment_ids[0] ? "" : x]) : []
}

data "aws_ec2_transit_gateway_vpc_attachments" "filtered" {
  count = var.create_tgw ? 1 : 0

  filter {
    name   = "transit-gateway-id"
    values = [module.tgw.ec2_transit_gateway_id]
  }
}

resource "aws_ec2_transit_gateway_route" "spoke_routes" {
  count = var.create_tgw ? 1 : 0

  destination_cidr_block         = module.vpc.vpc_cidr_block
  transit_gateway_attachment_id  = module.tgw.ec2_transit_gateway_vpc_attachment_ids[0]
  transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.spoke_route_table[0].id
}

resource "aws_ec2_transit_gateway_route_table" "spoke_route_table" {
  count = var.create_tgw ? 1 : 0

  transit_gateway_id = module.tgw.ec2_transit_gateway_id
}

resource "aws_ec2_transit_gateway_route_table_association" "spoke_route_table_association" {
  for_each = toset(local.subaccount_vpc_attachments)

  transit_gateway_attachment_id  = each.key
  transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.spoke_route_table[0].id
}

resource "aws_ec2_transit_gateway_route_table_association" "hub_route_table_association" {
  count = var.create_tgw ? 1 : 0

  transit_gateway_attachment_id  = module.tgw.ec2_transit_gateway_vpc_attachment_ids[0]
  transit_gateway_route_table_id = module.tgw.ec2_transit_gateway_propagation_default_route_table_id
}

resource "aws_route" "this_public" {
  count = length(var.routes_destination_cidr_blocks)

  route_table_id         = module.vpc.public_route_table_ids[0]
  destination_cidr_block = element(var.routes_destination_cidr_blocks, count.index)
  transit_gateway_id     = var.create_tgw ? module.tgw.ec2_transit_gateway_id : var.tgw_id
}

resource "aws_route" "this_private" {
  count = length(var.routes_destination_cidr_blocks)

  route_table_id         = module.vpc.private_route_table_ids[0]
  destination_cidr_block = element(var.routes_destination_cidr_blocks, count.index)
  transit_gateway_id     = var.create_tgw ? module.tgw.ec2_transit_gateway_id : var.tgw_id
}

Steps to reproduce the behavior:

No. Using terragrunt.

Yes

terrafomr/terragrunt plan

Expected behavior

no diff

Actual behavior

There is always a diff regardless if the account has a TGW or only attachment. Example:

  # module.tgw.aws_ec2_transit_gateway_vpc_attachment.this["staging-vpc"] will be updated in-place
  ~ resource "aws_ec2_transit_gateway_vpc_attachment" "this" {
        id                                              = "tgw-attach-0408540f40c2c1646"
        tags                                            = {
            "Name"     = "staging-tgw"
            "topology" = "spoke"
        }
      ~ transit_gateway_default_route_table_association = true -> false
        # (9 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.
github-actions[bot] commented 1 year ago

This issue has been automatically marked as stale because it has been open 30 days with no activity. Remove stale label or comment or this issue will be closed in 10 days

github-actions[bot] commented 1 year ago

This issue was automatically closed because of stale in 10 days

vainkop commented 1 year ago

/reopen

github-actions[bot] commented 1 year ago

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.