charles uneze
charles uneze

Reputation: 159

I have trouble auto accepting a Transit Gateway Peering using Terraform

I wrote a script that peers two Transit gateways within the same region. A peering is created however, it is refusing to accept the requests.

resource "aws_ec2_transit_gateway_peering_attachment" "TGW_A_B_Peering_Attachment_Request" {
  peer_account_id         = aws_ec2_transit_gateway.Transit_GW_A.owner_id
  peer_transit_gateway_id = aws_ec2_transit_gateway.Transit_GW_B.id
  transit_gateway_id      = aws_ec2_transit_gateway.Transit_GW_A.id
  peer_region             = var.region_2

  tags = {
    Name = "TGW A and B Peering Request"
  }
}

resource "aws_ec2_transit_gateway_peering_attachment_accepter" "TGW_A_B_Peering_Attachment_Accept" {
  transit_gateway_attachment_id = aws_ec2_transit_gateway_peering_attachment.TGW_A_B_Peering_Attachment_Request.id

  tags = {
    Name = "TGW A and B Peering Accept"
  }
}

│ Error: accepting EC2 Transit Gateway Peering Attachment (tgw-attach-01aa81f3b119adda2): InvalidParameterValue: Cannot accept tgw-attach-01aa81f3b119adda2 as the source of the peering request.

I think I must be missing something, but I can't tell.

Upvotes: 0

Views: 1428

Answers (3)

Alephпτ1
Alephпτ1

Reputation: 81

So, if you found this post because like me you are handling cross-account peering connections that require using multiple providers, AND you have multiple peering connections - worry no more.

Disclaimer: I cannot guarentee that terraform supports this as I am using tofu, but I am assuming there is mutual compatibility as tofu strives for this. I have no tested this on terraform without tofu support.

When looking through the data block implementation code in the tofu repo, I came across the _ escape block test. It appears to be used to apply additional filtering when multiple results are found, but I assume that a provider giving Multiple Results Found error is handled the same was as No Results Found. The feature does not appear to be implemented, according to my language server, but the code runs and executes just fine.

From what I can tell, the code below attempts to query an attachment based on "pendingAcceptance", and if that fails to resolve the filter due to the state of the attachment - then it hits the escape block and attempts to filter based on "Available" results matching the given name. This seems to work for my case where my data is either [pending, id] or [available, id, "named"] but never both.

data "aws_ec2_transit_gateway_peering_attachment" "peering_attachment" {
    provider = aws.peer

    filter {
        name   = "state"
        values = ["pendingAcceptance"]
    }

    filter {
        name  = "transit-gateway-id"
        values = [aws_ec2_transit_gateway_peering_attachment.local_attachment.peer_transit_gateway_id]
    }

    _ {
        filter {
            name   = "state"
            values = ["available"]
        }

        filter {
            name  = "tag:Name"
            values = ["My-Peer-Gateway-Attachment"]
        }
    }
}

I don't know if there is any way to use this to toggle some value or return any default values if the results are none, but this definitely solved my issue where data parameters change based on the state of the infrastructure, and there are multiple 'available' resources associated with a given gateway.

Upvotes: 0

Ronnie G
Ronnie G

Reputation: 31

The proposed solution worked for me but I use a pipeline to deploy my resources so the subsequent deploy fail. I added an available condition so this passes on subsequent deploys. Keep in mind additional filtering like tags may be needed if there are multiple peering attachments being created for the TGW.

data "aws_ec2_transit_gateway_peering_attachment" "TGW_A_B_Peering_Attachment" {
  depends_on = [ aws_ec2_transit_gateway_peering_attachment.TGW_A_B_Peering_Attachment_Request ]

  filter {
    name = "state"
    values = [ "pendingAcceptance" , "available" ]
  }

  # Only the second accepter/peer transit gateway is called from the peering attachment.
  filter {
    name = "transit-gateway-id"
    values = [ aws_ec2_transit_gateway_peering_attachment.TGW_A_B_Peering_Attachment_Request.peer_transit_gateway_id ]
  }
}

Upvotes: 1

charles uneze
charles uneze

Reputation: 159

So, it turns out that the aws_ec2_transit_gateway_peering_attachment resource creates two peerings in the AWS console; Requester and Accepter. To use the Accepter peering, a data resource must be created which filters for the second Accepter peering.

data "aws_ec2_transit_gateway_peering_attachment" "TGW_A_B_Peering_Attachment" {
  depends_on = [ aws_ec2_transit_gateway_peering_attachment.TGW_A_B_Peering_Attachment_Request ]

  filter {
    name = "state"
    values = [ "pendingAcceptance" ]
  }

  # Only the second accepter/peer transit gateway is called from the peering attachment.
  filter {
    name = "transit-gateway-id"
    values = [ aws_ec2_transit_gateway_peering_attachment.TGW_A_B_Peering_Attachment_Request.peer_transit_gateway_id ]
  }
}

The above filters and depends_on is the only combination that works. The resource is flawed, so this data source must be used.

Lastly, I will call the data source into the accepted resource.

resource "aws_ec2_transit_gateway_peering_attachment_accepter" "TGW_A_B_Peering_Attachment_Accept" {
  transit_gateway_attachment_id = data.aws_ec2_transit_gateway_peering_attachment.TGW_A_B_Peering_Attachment.id

  tags = {
    Name = "TGW A and B Peering Accept"
  }
}

Upvotes: 0

Related Questions