Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow forced replacement of route table associated with subnet #6999

Merged
merged 5 commits into from
Jul 31, 2019
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
r/aws_route_table_association: Allow force replacement
YakDriver committed Jul 31, 2019
commit 139557f719a9d2b3338cabeee9320e980f6b8d3f
68 changes: 64 additions & 4 deletions aws/resource_aws_route_table_association.go
Original file line number Diff line number Diff line change
@@ -30,6 +30,12 @@ func resourceAwsRouteTableAssociation() *schema.Resource {
Type: schema.TypeString,
Required: true,
},

"force_replace": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
}
}
@@ -47,17 +53,40 @@ func resourceAwsRouteTableAssociationCreate(d *schema.ResourceData, meta interfa
SubnetId: aws.String(d.Get("subnet_id").(string)),
}

var resp *ec2.AssociateRouteTableOutput
var associationID string
var err error
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
resp, err = conn.AssociateRouteTable(&associationOpts)
err = resource.Retry(30*time.Second, func() *resource.RetryError {
resp, err := conn.AssociateRouteTable(&associationOpts)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
if awsErr.Code() == "InvalidRouteTableID.NotFound" {
return resource.RetryableError(awsErr)
}
if awsErr.Code() == "Resource.AlreadyAssociated" && d.Get(
"force_replace").(bool) {

associationID, err = findExistingSubnetAssociationID(
conn,
d.Get("subnet_id").(string),
)
if err != nil {
return resource.NonRetryableError(err)
}

log.Print("[INFO] Replacing route table association")
input := &ec2.ReplaceRouteTableAssociationInput{
AssociationId: aws.String(associationID),
RouteTableId: aws.String(d.Get("route_table_id").(string)),
}
_, err = conn.ReplaceRouteTableAssociation(input)
if err == nil {
return nil
}
}
}
return resource.NonRetryableError(err)
} else {
associationID = *resp.AssociationId
}
return nil
})
@@ -66,7 +95,7 @@ func resourceAwsRouteTableAssociationCreate(d *schema.ResourceData, meta interfa
}

// Set the ID and return
d.SetId(*resp.AssociationId)
d.SetId(associationID)
log.Printf("[INFO] Association ID: %s", d.Id())

return nil
@@ -153,3 +182,34 @@ func resourceAwsRouteTableAssociationDelete(d *schema.ResourceData, meta interfa

return nil
}

func findExistingSubnetAssociationID(conn *ec2.EC2, subnetID string) (string, error) {
// only way to get association id is through the route table

input := &ec2.DescribeRouteTablesInput{}
input.Filters = buildEC2AttributeFilterList(
map[string]string{
"association.subnet-id": subnetID,
},
)

output, err := conn.DescribeRouteTables(input)
if err != nil || len(output.RouteTables) == 0 {
return "", fmt.Errorf("Error finding route table: %v", err)
}

rt := output.RouteTables[0]

var associationID string
for _, a := range rt.Associations {
if *a.SubnetId == subnetID {
YakDriver marked this conversation as resolved.
Show resolved Hide resolved
associationID = *a.RouteTableAssociationId
YakDriver marked this conversation as resolved.
Show resolved Hide resolved
break
}
}
if associationID == "" {
return "", fmt.Errorf("Error finding route table, ID: %v", *rt.RouteTableId)
}

return associationID, nil
}