terraform/builtin/providers/aws/resource_aws_default_route_...

237 lines
5.8 KiB
Go

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": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"vpc_id": {
Type: schema.TypeString,
Computed: true,
},
"propagating_vgws": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"route": {
Type: schema.TypeSet,
Computed: true,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cidr_block": {
Type: schema.TypeString,
Optional: true,
},
"ipv6_cidr_block": {
Type: schema.TypeString,
Optional: true,
},
"egress_only_gateway_id": {
Type: schema.TypeString,
Optional: true,
},
"gateway_id": {
Type: schema.TypeString,
Optional: true,
},
"instance_id": {
Type: schema.TypeString,
Optional: true,
},
"nat_gateway_id": {
Type: schema.TypeString,
Optional: true,
},
"vpc_peering_connection_id": {
Type: schema.TypeString,
Optional: true,
},
"network_interface_id": {
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)
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]
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
}
if r.DestinationPrefixListId != nil {
// Skipping because VPC endpoint routes are handled separately
// See aws_vpc_endpoint
continue
}
if r.DestinationCidrBlock != nil {
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
}
}
if r.DestinationIpv6CidrBlock != nil {
log.Printf(
"[INFO] Deleting route from %s: %s",
defaultRouteTableId, *r.DestinationIpv6CidrBlock)
_, err := conn.DeleteRoute(&ec2.DeleteRouteInput{
RouteTableId: aws.String(defaultRouteTableId),
DestinationIpv6CidrBlock: r.DestinationIpv6CidrBlock,
})
if err != nil {
return err
}
}
}
return nil
}