2015-06-24 05:44:02 +02:00
|
|
|
package aws
|
|
|
|
|
|
|
|
import (
|
2015-12-01 16:31:20 +01:00
|
|
|
"errors"
|
2015-06-24 05:44:02 +02:00
|
|
|
"fmt"
|
|
|
|
"log"
|
2016-04-20 00:23:42 +02:00
|
|
|
"time"
|
2015-06-24 05:44:02 +02:00
|
|
|
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
2016-04-20 00:23:42 +02:00
|
|
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
2015-06-24 05:44:02 +02:00
|
|
|
"github.com/aws/aws-sdk-go/service/ec2"
|
|
|
|
"github.com/hashicorp/terraform/helper/hashcode"
|
2016-04-20 00:23:42 +02:00
|
|
|
"github.com/hashicorp/terraform/helper/resource"
|
2015-06-24 05:44:02 +02:00
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
|
|
)
|
|
|
|
|
2015-12-01 16:31:20 +01:00
|
|
|
// How long to sleep if a limit-exceeded event happens
|
2016-06-27 12:54:19 +02:00
|
|
|
var routeTargetValidationError = errors.New("Error: more than 1 target specified. Only 1 of gateway_id, " +
|
2017-05-31 21:50:56 +02:00
|
|
|
"egress_only_gateway_id, nat_gateway_id, instance_id, network_interface_id or " +
|
2015-12-01 16:31:20 +01:00
|
|
|
"vpc_peering_connection_id is allowed.")
|
|
|
|
|
2015-10-15 23:55:47 +02:00
|
|
|
// AWS Route resource Schema declaration
|
2015-06-24 05:44:02 +02:00
|
|
|
func resourceAwsRoute() *schema.Resource {
|
|
|
|
return &schema.Resource{
|
|
|
|
Create: resourceAwsRouteCreate,
|
|
|
|
Read: resourceAwsRouteRead,
|
|
|
|
Update: resourceAwsRouteUpdate,
|
|
|
|
Delete: resourceAwsRouteDelete,
|
2015-10-15 23:55:47 +02:00
|
|
|
Exists: resourceAwsRouteExists,
|
2015-06-24 05:44:02 +02:00
|
|
|
|
|
|
|
Schema: map[string]*schema.Schema{
|
2017-03-14 11:41:40 +01:00
|
|
|
"destination_cidr_block": {
|
2015-06-24 05:44:02 +02:00
|
|
|
Type: schema.TypeString,
|
2017-03-14 11:41:40 +01:00
|
|
|
Optional: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
"destination_ipv6_cidr_block": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
2015-10-26 18:45:21 +01:00
|
|
|
ForceNew: true,
|
2015-06-24 05:44:02 +02:00
|
|
|
},
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
"destination_prefix_list_id": {
|
2015-06-24 05:44:02 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
"gateway_id": {
|
2015-06-24 05:44:02 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
2016-02-25 14:59:01 +01:00
|
|
|
Computed: true,
|
2015-06-24 05:44:02 +02:00
|
|
|
},
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
"egress_only_gateway_id": {
|
2015-12-18 08:20:13 +01:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
2016-02-25 14:59:01 +01:00
|
|
|
Computed: true,
|
2015-12-18 08:20:13 +01:00
|
|
|
},
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
"nat_gateway_id": {
|
2015-06-24 05:44:02 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
2016-02-25 14:59:01 +01:00
|
|
|
Computed: true,
|
2015-06-24 05:44:02 +02:00
|
|
|
},
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
"instance_id": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"instance_owner_id": {
|
2015-06-24 05:44:02 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
"network_interface_id": {
|
2015-06-24 05:44:02 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
2016-02-25 14:59:01 +01:00
|
|
|
Computed: true,
|
2015-06-24 05:44:02 +02:00
|
|
|
},
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
"origin": {
|
2015-06-24 05:44:02 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
"state": {
|
2015-06-24 05:44:02 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
"route_table_id": {
|
2015-06-24 05:44:02 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
"vpc_peering_connection_id": {
|
2015-06-24 05:44:02 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
conn := meta.(*AWSClient).ec2conn
|
|
|
|
var numTargets int
|
|
|
|
var setTarget string
|
|
|
|
allowedTargets := []string{
|
2017-03-14 11:41:40 +01:00
|
|
|
"egress_only_gateway_id",
|
2015-06-24 05:44:02 +02:00
|
|
|
"gateway_id",
|
2015-12-18 08:20:13 +01:00
|
|
|
"nat_gateway_id",
|
2015-06-24 05:44:02 +02:00
|
|
|
"instance_id",
|
|
|
|
"network_interface_id",
|
|
|
|
"vpc_peering_connection_id",
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if more than 1 target is specified
|
|
|
|
for _, target := range allowedTargets {
|
|
|
|
if len(d.Get(target).(string)) > 0 {
|
|
|
|
numTargets++
|
|
|
|
setTarget = target
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if numTargets > 1 {
|
2015-12-01 16:31:20 +01:00
|
|
|
return routeTargetValidationError
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
|
2015-10-15 23:55:47 +02:00
|
|
|
createOpts := &ec2.CreateRouteInput{}
|
2015-06-24 05:44:02 +02:00
|
|
|
// Formulate CreateRouteInput based on the target type
|
|
|
|
switch setTarget {
|
|
|
|
case "gateway_id":
|
|
|
|
createOpts = &ec2.CreateRouteInput{
|
2017-05-15 14:48:38 +02:00
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
GatewayId: aws.String(d.Get("gateway_id").(string)),
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, ok := d.GetOk("destination_cidr_block"); ok {
|
|
|
|
createOpts.DestinationCidrBlock = aws.String(v.(string))
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
2017-05-15 14:48:38 +02:00
|
|
|
|
|
|
|
if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok {
|
|
|
|
createOpts.DestinationIpv6CidrBlock = aws.String(v.(string))
|
|
|
|
}
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
case "egress_only_gateway_id":
|
|
|
|
createOpts = &ec2.CreateRouteInput{
|
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
DestinationIpv6CidrBlock: aws.String(d.Get("destination_ipv6_cidr_block").(string)),
|
|
|
|
EgressOnlyInternetGatewayId: aws.String(d.Get("egress_only_gateway_id").(string)),
|
|
|
|
}
|
2015-12-18 08:20:13 +01:00
|
|
|
case "nat_gateway_id":
|
|
|
|
createOpts = &ec2.CreateRouteInput{
|
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
|
|
|
|
NatGatewayId: aws.String(d.Get("nat_gateway_id").(string)),
|
|
|
|
}
|
2015-06-24 05:44:02 +02:00
|
|
|
case "instance_id":
|
|
|
|
createOpts = &ec2.CreateRouteInput{
|
2015-10-15 23:55:47 +02:00
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
|
|
|
|
InstanceId: aws.String(d.Get("instance_id").(string)),
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
case "network_interface_id":
|
|
|
|
createOpts = &ec2.CreateRouteInput{
|
2015-10-15 23:55:47 +02:00
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
|
|
|
|
NetworkInterfaceId: aws.String(d.Get("network_interface_id").(string)),
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
case "vpc_peering_connection_id":
|
|
|
|
createOpts = &ec2.CreateRouteInput{
|
2015-10-15 23:55:47 +02:00
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
|
|
|
|
VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)),
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
default:
|
2016-10-18 12:47:25 +02:00
|
|
|
return fmt.Errorf("An invalid target type specified: %s", setTarget)
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
2015-10-26 18:38:17 +01:00
|
|
|
log.Printf("[DEBUG] Route create config: %s", createOpts)
|
2015-06-24 05:44:02 +02:00
|
|
|
|
|
|
|
// Create the route
|
2016-04-20 00:23:42 +02:00
|
|
|
var err error
|
|
|
|
|
|
|
|
err = resource.Retry(2*time.Minute, func() *resource.RetryError {
|
|
|
|
_, err = conn.CreateRoute(createOpts)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
ec2err, ok := err.(awserr.Error)
|
|
|
|
if !ok {
|
|
|
|
return resource.NonRetryableError(err)
|
|
|
|
}
|
|
|
|
if ec2err.Code() == "InvalidParameterException" {
|
|
|
|
log.Printf("[DEBUG] Trying to create route again: %q", ec2err.Message())
|
|
|
|
return resource.RetryableError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return resource.NonRetryableError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
2015-06-24 05:44:02 +02:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error creating route: %s", err)
|
|
|
|
}
|
|
|
|
|
2016-07-05 22:04:09 +02:00
|
|
|
var route *ec2.Route
|
2017-03-14 11:41:40 +01:00
|
|
|
|
|
|
|
if v, ok := d.GetOk("destination_cidr_block"); ok {
|
|
|
|
err = resource.Retry(2*time.Minute, func() *resource.RetryError {
|
|
|
|
route, err = findResourceRoute(conn, d.Get("route_table_id").(string), v.(string), "")
|
|
|
|
return resource.RetryableError(err)
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error finding route after creating it: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok {
|
|
|
|
err = resource.Retry(2*time.Minute, func() *resource.RetryError {
|
|
|
|
route, err = findResourceRoute(conn, d.Get("route_table_id").(string), "", v.(string))
|
|
|
|
return resource.RetryableError(err)
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error finding route after creating it: %s", err)
|
|
|
|
}
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
d.SetId(routeIDHash(d, route))
|
2016-07-05 22:04:09 +02:00
|
|
|
resourceAwsRouteSetResourceData(d, route)
|
|
|
|
return nil
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
conn := meta.(*AWSClient).ec2conn
|
2016-10-18 12:47:25 +02:00
|
|
|
routeTableId := d.Get("route_table_id").(string)
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
destinationCidrBlock := d.Get("destination_cidr_block").(string)
|
|
|
|
destinationIpv6CidrBlock := d.Get("destination_ipv6_cidr_block").(string)
|
|
|
|
|
|
|
|
route, err := findResourceRoute(conn, routeTableId, destinationCidrBlock, destinationIpv6CidrBlock)
|
2015-06-24 05:44:02 +02:00
|
|
|
if err != nil {
|
2016-08-26 08:50:14 +02:00
|
|
|
if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidRouteTableID.NotFound" {
|
2016-10-18 12:47:25 +02:00
|
|
|
log.Printf("[WARN] Route Table %q could not be found. Removing Route from state.",
|
|
|
|
routeTableId)
|
2016-08-26 08:50:14 +02:00
|
|
|
d.SetId("")
|
|
|
|
return nil
|
|
|
|
}
|
2015-06-24 05:44:02 +02:00
|
|
|
return err
|
|
|
|
}
|
2016-07-05 22:04:09 +02:00
|
|
|
resourceAwsRouteSetResourceData(d, route)
|
|
|
|
return nil
|
|
|
|
}
|
2015-06-24 05:44:02 +02:00
|
|
|
|
2016-07-05 22:04:09 +02:00
|
|
|
func resourceAwsRouteSetResourceData(d *schema.ResourceData, route *ec2.Route) {
|
2015-10-15 23:55:47 +02:00
|
|
|
d.Set("destination_prefix_list_id", route.DestinationPrefixListId)
|
|
|
|
d.Set("gateway_id", route.GatewayId)
|
2017-03-14 11:41:40 +01:00
|
|
|
d.Set("egress_only_gateway_id", route.EgressOnlyInternetGatewayId)
|
2015-12-18 08:20:13 +01:00
|
|
|
d.Set("nat_gateway_id", route.NatGatewayId)
|
2015-10-15 23:55:47 +02:00
|
|
|
d.Set("instance_id", route.InstanceId)
|
|
|
|
d.Set("instance_owner_id", route.InstanceOwnerId)
|
|
|
|
d.Set("network_interface_id", route.NetworkInterfaceId)
|
2015-06-24 05:44:02 +02:00
|
|
|
d.Set("origin", route.Origin)
|
|
|
|
d.Set("state", route.State)
|
2015-10-15 23:55:47 +02:00
|
|
|
d.Set("vpc_peering_connection_id", route.VpcPeeringConnectionId)
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func resourceAwsRouteUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
conn := meta.(*AWSClient).ec2conn
|
|
|
|
var numTargets int
|
|
|
|
var setTarget string
|
2016-05-13 17:07:54 +02:00
|
|
|
|
2015-06-24 05:44:02 +02:00
|
|
|
allowedTargets := []string{
|
2017-03-14 11:41:40 +01:00
|
|
|
"egress_only_gateway_id",
|
2015-06-24 05:44:02 +02:00
|
|
|
"gateway_id",
|
2015-12-18 08:20:13 +01:00
|
|
|
"nat_gateway_id",
|
2015-06-24 05:44:02 +02:00
|
|
|
"network_interface_id",
|
2016-05-13 17:07:54 +02:00
|
|
|
"instance_id",
|
2015-06-24 05:44:02 +02:00
|
|
|
"vpc_peering_connection_id",
|
|
|
|
}
|
|
|
|
replaceOpts := &ec2.ReplaceRouteInput{}
|
|
|
|
|
|
|
|
// Check if more than 1 target is specified
|
|
|
|
for _, target := range allowedTargets {
|
|
|
|
if len(d.Get(target).(string)) > 0 {
|
|
|
|
numTargets++
|
|
|
|
setTarget = target
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-13 17:07:54 +02:00
|
|
|
switch setTarget {
|
|
|
|
//instance_id is a special case due to the fact that AWS will "discover" the network_interace_id
|
|
|
|
//when it creates the route and return that data. In the case of an update, we should ignore the
|
|
|
|
//existing network_interface_id
|
|
|
|
case "instance_id":
|
|
|
|
if numTargets > 2 || (numTargets == 2 && len(d.Get("network_interface_id").(string)) == 0) {
|
|
|
|
return routeTargetValidationError
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if numTargets > 1 {
|
|
|
|
return routeTargetValidationError
|
|
|
|
}
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Formulate ReplaceRouteInput based on the target type
|
|
|
|
switch setTarget {
|
|
|
|
case "gateway_id":
|
|
|
|
replaceOpts = &ec2.ReplaceRouteInput{
|
2015-10-15 23:55:47 +02:00
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
|
|
|
|
GatewayId: aws.String(d.Get("gateway_id").(string)),
|
2015-12-18 08:20:13 +01:00
|
|
|
}
|
2017-03-14 11:41:40 +01:00
|
|
|
case "egress_only_gateway_id":
|
|
|
|
replaceOpts = &ec2.ReplaceRouteInput{
|
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
DestinationIpv6CidrBlock: aws.String(d.Get("destination_ipv6_cidr_block").(string)),
|
|
|
|
EgressOnlyInternetGatewayId: aws.String(d.Get("egress_only_gateway_id").(string)),
|
|
|
|
}
|
2015-12-18 08:20:13 +01:00
|
|
|
case "nat_gateway_id":
|
|
|
|
replaceOpts = &ec2.ReplaceRouteInput{
|
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
|
|
|
|
NatGatewayId: aws.String(d.Get("nat_gateway_id").(string)),
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
case "instance_id":
|
|
|
|
replaceOpts = &ec2.ReplaceRouteInput{
|
2015-10-15 23:55:47 +02:00
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
|
|
|
|
InstanceId: aws.String(d.Get("instance_id").(string)),
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
case "network_interface_id":
|
|
|
|
replaceOpts = &ec2.ReplaceRouteInput{
|
2015-10-15 23:55:47 +02:00
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
|
|
|
|
NetworkInterfaceId: aws.String(d.Get("network_interface_id").(string)),
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
case "vpc_peering_connection_id":
|
|
|
|
replaceOpts = &ec2.ReplaceRouteInput{
|
2015-10-15 23:55:47 +02:00
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
|
|
|
|
VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)),
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
default:
|
2016-10-18 12:47:25 +02:00
|
|
|
return fmt.Errorf("An invalid target type specified: %s", setTarget)
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
2015-10-26 18:38:17 +01:00
|
|
|
log.Printf("[DEBUG] Route replace config: %s", replaceOpts)
|
2015-06-24 05:44:02 +02:00
|
|
|
|
|
|
|
// Replace the route
|
|
|
|
_, err := conn.ReplaceRoute(replaceOpts)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-10-26 18:45:21 +01:00
|
|
|
func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error {
|
2015-06-24 05:44:02 +02:00
|
|
|
conn := meta.(*AWSClient).ec2conn
|
2015-10-15 23:55:47 +02:00
|
|
|
|
2015-10-26 18:45:21 +01:00
|
|
|
deleteOpts := &ec2.DeleteRouteInput{
|
2017-03-14 11:41:40 +01:00
|
|
|
RouteTableId: aws.String(d.Get("route_table_id").(string)),
|
|
|
|
}
|
|
|
|
if v, ok := d.GetOk("destination_cidr_block"); ok {
|
|
|
|
deleteOpts.DestinationCidrBlock = aws.String(v.(string))
|
|
|
|
}
|
|
|
|
if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok {
|
|
|
|
deleteOpts.DestinationIpv6CidrBlock = aws.String(v.(string))
|
2015-10-15 23:55:47 +02:00
|
|
|
}
|
2015-10-26 18:45:21 +01:00
|
|
|
log.Printf("[DEBUG] Route delete opts: %s", deleteOpts)
|
2015-10-15 23:55:47 +02:00
|
|
|
|
2016-04-20 00:23:42 +02:00
|
|
|
var err error
|
|
|
|
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
|
|
|
|
log.Printf("[DEBUG] Trying to delete route with opts %s", deleteOpts)
|
|
|
|
resp, err := conn.DeleteRoute(deleteOpts)
|
|
|
|
log.Printf("[DEBUG] Route delete result: %s", resp)
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
ec2err, ok := err.(awserr.Error)
|
|
|
|
if !ok {
|
|
|
|
return resource.NonRetryableError(err)
|
|
|
|
}
|
|
|
|
if ec2err.Code() == "InvalidParameterException" {
|
|
|
|
log.Printf("[DEBUG] Trying to delete route again: %q",
|
|
|
|
ec2err.Message())
|
|
|
|
return resource.RetryableError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return resource.NonRetryableError(err)
|
|
|
|
})
|
|
|
|
|
2015-06-24 05:44:02 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetId("")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-10-15 23:55:47 +02:00
|
|
|
func resourceAwsRouteExists(d *schema.ResourceData, meta interface{}) (bool, error) {
|
|
|
|
conn := meta.(*AWSClient).ec2conn
|
|
|
|
routeTableId := d.Get("route_table_id").(string)
|
|
|
|
|
|
|
|
findOpts := &ec2.DescribeRouteTablesInput{
|
|
|
|
RouteTableIds: []*string{&routeTableId},
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err := conn.DescribeRouteTables(findOpts)
|
|
|
|
if err != nil {
|
2016-10-18 12:47:25 +02:00
|
|
|
if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidRouteTableID.NotFound" {
|
|
|
|
log.Printf("[WARN] Route Table %q could not be found.", routeTableId)
|
|
|
|
return false, nil
|
|
|
|
}
|
2016-03-25 20:55:27 +01:00
|
|
|
return false, fmt.Errorf("Error while checking if route exists: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(res.RouteTables) < 1 || res.RouteTables[0] == nil {
|
2016-10-18 12:47:25 +02:00
|
|
|
log.Printf("[WARN] Route Table %q is gone, or route does not exist.",
|
2016-03-25 20:55:27 +01:00
|
|
|
routeTableId)
|
|
|
|
return false, nil
|
2015-10-15 23:55:47 +02:00
|
|
|
}
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
if v, ok := d.GetOk("destination_cidr_block"); ok {
|
|
|
|
for _, route := range (*res.RouteTables[0]).Routes {
|
|
|
|
if route.DestinationCidrBlock != nil && *route.DestinationCidrBlock == v.(string) {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok {
|
|
|
|
for _, route := range (*res.RouteTables[0]).Routes {
|
|
|
|
if route.DestinationIpv6CidrBlock != nil && *route.DestinationIpv6CidrBlock == v.(string) {
|
|
|
|
return true, nil
|
|
|
|
}
|
2015-10-15 23:55:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
2015-06-24 05:44:02 +02:00
|
|
|
// Create an ID for a route
|
|
|
|
func routeIDHash(d *schema.ResourceData, r *ec2.Route) string {
|
2017-03-14 11:41:40 +01:00
|
|
|
|
|
|
|
if r.DestinationIpv6CidrBlock != nil && *r.DestinationIpv6CidrBlock != "" {
|
|
|
|
return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationIpv6CidrBlock))
|
|
|
|
}
|
|
|
|
|
2015-10-15 23:55:47 +02:00
|
|
|
return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationCidrBlock))
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Helper: retrieve a route
|
2017-03-14 11:41:40 +01:00
|
|
|
func findResourceRoute(conn *ec2.EC2, rtbid string, cidr string, ipv6cidr string) (*ec2.Route, error) {
|
2015-06-24 05:44:02 +02:00
|
|
|
routeTableID := rtbid
|
|
|
|
|
|
|
|
findOpts := &ec2.DescribeRouteTablesInput{
|
2015-10-15 23:55:47 +02:00
|
|
|
RouteTableIds: []*string{&routeTableID},
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := conn.DescribeRouteTables(findOpts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-03-25 20:55:27 +01:00
|
|
|
if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil {
|
2016-10-18 12:47:25 +02:00
|
|
|
return nil, fmt.Errorf("Route Table %q is gone, or route does not exist.",
|
2016-03-25 20:55:27 +01:00
|
|
|
routeTableID)
|
|
|
|
}
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
if cidr != "" {
|
|
|
|
for _, route := range (*resp.RouteTables[0]).Routes {
|
|
|
|
if route.DestinationCidrBlock != nil && *route.DestinationCidrBlock == cidr {
|
|
|
|
return route, nil
|
|
|
|
}
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
2017-03-14 11:41:40 +01:00
|
|
|
|
|
|
|
return nil, fmt.Errorf("Unable to find matching route for Route Table (%s) "+
|
|
|
|
"and destination CIDR block (%s).", rtbid, cidr)
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|
|
|
|
|
2017-03-14 11:41:40 +01:00
|
|
|
if ipv6cidr != "" {
|
|
|
|
for _, route := range (*resp.RouteTables[0]).Routes {
|
|
|
|
if route.DestinationIpv6CidrBlock != nil && *route.DestinationIpv6CidrBlock == ipv6cidr {
|
|
|
|
return route, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("Unable to find matching route for Route Table (%s) "+
|
|
|
|
"and destination IPv6 CIDR block (%s).", rtbid, ipv6cidr)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("When trying to find a matching route for Route Table %q "+
|
|
|
|
"you need to specify a CIDR block of IPv6 CIDR Block", rtbid)
|
|
|
|
|
2015-06-24 05:44:02 +02:00
|
|
|
}
|