hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.74k stars 9.1k forks source link

[Bug]: New Association for route table rtb-******* conflicts with an existing association #38960

Closed gizumov closed 3 weeks ago

gizumov commented 3 weeks ago

Terraform Core Version

1.9.4

AWS Provider Version

5.63.0

Affected Resource(s)

aws_subnet aws_route_table aws_route_table_association

Expected Behavior

Route table association has been changed for the subnet.

Actual Behavior

terraform apply works inconsistently and fails from time to time (~once in 5-10 runs) with the following error: Error: creating Route Table (rtb-*********) Association: operation error EC2: AssociateRouteTable, https response error StatusCode: 400, RequestID: b7647190-1165-409a-87a6-bf99324d0d73, api error Resource.AlreadyAssociated: the specified association for route table rtb-********* conflicts with an existing association However, the next terraform apply run works fine.

Relevant Error/Panic Output Snippet

Error: creating Route Table (rtb-**********) Association: operation error EC2: AssociateRouteTable, https response error StatusCode: 400, RequestID: b7647190-1165-409a-87a6-bf99324d0d73, api error Resource.AlreadyAssociated: the specified association for route table rtb-********* conflicts with an existing association

Terraform Configuration Files

To reproduce this bug, I created a simple Terraform setup similar to what I tried to use: Please update vpc_id and cidr_block to match your setup.

locals {
    use_first_rtb = true
    vpc_id = "vpc-**********"
    cidr_block = "192.168.144.0/20"
}

resource "aws_subnet" "test_subnet" {
  vpc_id            = local.vpc_id
  cidr_block        = local.cidr_block
  tags = {
    Name="test-subnet"
  }
}

resource "aws_route_table" "test_rtb_1" {

  vpc_id = local.vpc_id
  tags = {
    Name="test-rtb-1"
  }
}

resource "aws_route_table" "test_rtb_2" {
  vpc_id = local.vpc_id
  tags = {
    Name="test-rtb-2"
  }
}

resource "aws_route_table_association" "test_1" {
count = local.use_first_rtb ? 1 : 0
  subnet_id      = aws_subnet.test_subnet.id
  route_table_id = aws_route_table.test_rtb_1.id

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route_table_association" "test_2" {
count = local.use_first_rtb ? 0 : 1
  subnet_id      = aws_subnet.test_subnet.id
  route_table_id = aws_route_table.test_rtb_2.id

  lifecycle {
    create_before_destroy = true
  }
}

Steps to Reproduce

  1. Run terraform apply
  2. If apply is successful, flip use_first_rtb variable to the opposite to use a different route table
  3. Run terraform apply again
  4. Repeat steps 2 and 3 until the specified association for route table rtb-********* conflicts with an existing association error is thrown

Debug Output

debug.log

Panic Output

No response

Important Factoids

I'm aware of another issue connected to this topic: https://github.com/hashicorp/terraform-provider-aws/issues/73, but it might be the issue wasn't fixed properly last time.

References

https://github.com/hashicorp/terraform-provider-aws/issues/73

Would you like to implement a fix?

None

github-actions[bot] commented 3 weeks ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

justinretzolk commented 3 weeks ago

Hey @gizumov 👋 Thank you for taking the time to raise this! In this case, while it's hard to call this "expected behavior", it's not exactly "unexpected behavior" either.

The two aws_route_table_association resources have no dependency between them. This means that when flipping use_first_rtb, Terraform performs the creation of one and deletion of the other as two entirely separate operations, with no guarantee as to which will happen first. This becomes a problem because, as mentioned in the "import" section of the aws_route_table_association documentation:

Attempting to associate a route table with a subnet or gateway, where either is already associated, will result in an error (e.g., Resource.AlreadyAssociated: the specified association for route table rtb-4176657279 conflicts with an existing association)

To fix this, you'll need to change your approach to your configuration. My (untested) initial thought would be to eliminate one of the aws_route_table_association resources entirely, and update the other to something like:

resource "aws_route_table_association" "test" {
  subnet_id      = aws_subnet.test_subnet.id
  route_table_id = local.use_first_rtb ? aws_route_table.test_rtb_1.id : aws_route_table.test_rtb_2.id
}

This would net the same benefit of changing the route_table_id argument based on use_first_rtb. Unless I've misunderstood, attempting to make this kind of association when the route table is already associated with a subnet or the subnet is already associated with a route table will throw an error. With that in mind, I omitted create_before_destroy in my updated example, but you may find that I'm incorrect in that understanding.

Given that this is ultimately something that will need to be solved via configuration, and isn't something that we'll need to make provider-side changes for, I'm going to close this issue. If you experience unexpected behavior in the future, please do let us know!

github-actions[bot] commented 3 weeks ago

[!WARNING] This issue has been closed, meaning that any additional comments are hard for our team to see. Please assume that the maintainers will not see them.

Ongoing conversations amongst community members are welcome, however, the issue will be locked after 30 days. Moving conversations to another venue, such as the AWS Provider forum, is recommended. If you have additional concerns, please open a new issue, referencing this one where needed.

gizumov commented 3 weeks ago

Hi @justinretzolk!

Thank you so much for your answer! I just ran a few tests, and it works as expected. We will update our Terraform module as you recommended.