-
Notifications
You must be signed in to change notification settings - Fork 9.7k
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
provider/aws: Add aws_default_route_table resource #8323
Changes from all commits
1668f46
5327d79
7b2063e
49686f9
bbaf3bb
f43bdf0
782f2f6
8706b27
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/ec2" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
) | ||
|
||
func resourceAwsDefaultRouteTable() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceAwsDefaultRouteTableCreate, | ||
Read: resourceAwsDefaultRouteTableRead, | ||
Update: resourceAwsRouteTableUpdate, | ||
Delete: resourceAwsDefaultRouteTableDelete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"default_route_table_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"vpc_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
|
||
"propagating_vgws": &schema.Schema{ | ||
Type: schema.TypeSet, | ||
Optional: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
Set: schema.HashString, | ||
}, | ||
|
||
"route": &schema.Schema{ | ||
Type: schema.TypeSet, | ||
Computed: true, | ||
Optional: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"cidr_block": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
|
||
"gateway_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
|
||
"instance_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
|
||
"nat_gateway_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
|
||
"vpc_peering_connection_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
|
||
"network_interface_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
}, | ||
}, | ||
Set: resourceAwsRouteTableHash, | ||
}, | ||
|
||
"tags": tagsSchema(), | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsDefaultRouteTableCreate(d *schema.ResourceData, meta interface{}) error { | ||
d.SetId(d.Get("default_route_table_id").(string)) | ||
|
||
conn := meta.(*AWSClient).ec2conn | ||
rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(conn, d.Id())() | ||
if err != nil { | ||
return err | ||
} | ||
if rtRaw == nil { | ||
log.Printf("[WARN] Default Route Table not found") | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
rt := rtRaw.(*ec2.RouteTable) | ||
|
||
d.Set("vpc_id", rt.VpcId) | ||
|
||
// revoke all default and pre-existing routes on the default route table. | ||
// In the UPDATE method, we'll apply only the rules in the configuration. | ||
log.Printf("[DEBUG] Revoking default routes for Default Route Table for %s", d.Id()) | ||
if err := revokeAllRouteTableRules(d.Id(), meta); err != nil { | ||
return err | ||
} | ||
|
||
return resourceAwsRouteTableUpdate(d, meta) | ||
} | ||
|
||
func resourceAwsDefaultRouteTableRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
// look up default route table for VPC | ||
filter1 := &ec2.Filter{ | ||
Name: aws.String("association.main"), | ||
Values: []*string{aws.String("true")}, | ||
} | ||
filter2 := &ec2.Filter{ | ||
Name: aws.String("vpc-id"), | ||
Values: []*string{aws.String(d.Get("vpc_id").(string))}, | ||
} | ||
|
||
findOpts := &ec2.DescribeRouteTablesInput{ | ||
Filters: []*ec2.Filter{filter1, filter2}, | ||
} | ||
|
||
resp, err := conn.DescribeRouteTables(findOpts) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it not be best to use d.Id here as part of the lookup? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. on read we need to find the default route table for this VPC. Unlike Default Network ACLs or Default Security Groups, the Default Route Table can be changed (you can make a new one and then make that "default"). So we need to find if we are the default, and then refresh and show a diff (if there is one) accordingly. |
||
if err != nil { | ||
return err | ||
} | ||
|
||
if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil { | ||
return fmt.Errorf("Default Route table not found") | ||
} | ||
|
||
rt := resp.RouteTables[0] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was being stupid here... comment revoked ;) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
d.Set("default_route_table_id", rt.RouteTableId) | ||
d.SetId(*rt.RouteTableId) | ||
|
||
// re-use regular AWS Route Table READ. This is an extra API call but saves us | ||
// from trying to manually keep parity | ||
return resourceAwsRouteTableRead(d, meta) | ||
} | ||
|
||
func resourceAwsDefaultRouteTableDelete(d *schema.ResourceData, meta interface{}) error { | ||
log.Printf("[WARN] Cannot destroy Default Route Table. Terraform will remove this resource from the state file, however resources may remain.") | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
// revokeAllRouteTableRules revoke all routes on the Default Route Table | ||
// This should only be ran once at creation time of this resource | ||
func revokeAllRouteTableRules(defaultRouteTableId string, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
log.Printf("\n***\nrevokeAllRouteTableRules\n***\n") | ||
|
||
resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesInput{ | ||
RouteTableIds: []*string{aws.String(defaultRouteTableId)}, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil { | ||
return fmt.Errorf("Default Route table not found") | ||
} | ||
|
||
rt := resp.RouteTables[0] | ||
|
||
// Remove all Gateway association | ||
for _, r := range rt.PropagatingVgws { | ||
log.Printf( | ||
"[INFO] Deleting VGW propagation from %s: %s", | ||
defaultRouteTableId, *r.GatewayId) | ||
_, err := conn.DisableVgwRoutePropagation(&ec2.DisableVgwRoutePropagationInput{ | ||
RouteTableId: aws.String(defaultRouteTableId), | ||
GatewayId: r.GatewayId, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
// Delete all routes | ||
for _, r := range rt.Routes { | ||
// you cannot delete the local route | ||
if r.GatewayId != nil && *r.GatewayId == "local" { | ||
continue | ||
} | ||
log.Printf( | ||
"[INFO] Deleting route from %s: %s", | ||
defaultRouteTableId, *r.DestinationCidrBlock) | ||
_, err := conn.DeleteRoute(&ec2.DeleteRouteInput{ | ||
RouteTableId: aws.String(defaultRouteTableId), | ||
DestinationCidrBlock: r.DestinationCidrBlock, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a potentially for this to cause issues if the revoke happens and the update fails?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to revoke the rules regardless if there is any update to be made. The procedure is that during "creation" we wipe the slate clean. This is documented to warn people .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍