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

r/aws_route: Correctly handle update of route target #16219

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
f151d22
r/aws_route: Tidy up 'testAccAWSRouteConfigBasic()'.
ewbankkit Jun 25, 2020
5c00eab
r/aws_route: Rename 'TestAccAWSRoute_ipv6Support' to 'TestAccAWSRoute…
ewbankkit Jun 25, 2020
29ba4f9
Remove 'TestAccAWSRoute_noopdiff'. Test steps implicitly test this fu…
ewbankkit Jun 25, 2020
0c47b7c
r/aws_route: Tidy up 'TestAccAWSRoute_doesNotCrashWithVPCEndpoint'.
ewbankkit Jun 25, 2020
b56b698
r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToInternetGateway'.
ewbankkit Jun 26, 2020
04376c4
r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToInstance'.
ewbankkit Jun 26, 2020
c42ed98
r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToNetworkInterface'.
ewbankkit Jun 26, 2020
cd6854b
r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToVpcPeeringConnection'.
ewbankkit Jun 26, 2020
665ebe2
r/aws_route: Tidy up 'TestAccAWSRoute_TransitGatewayID_DestinationCid…
ewbankkit Jun 26, 2020
9384007
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_Instance'.
ewbankkit Jun 26, 2020
e0fd1d7
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NetworkInterface'.
ewbankkit Jun 26, 2020
cf982f1
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_VpcPeeringConnection'.
ewbankkit Jun 26, 2020
9f2f17e
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NatGateway'.
ewbankkit Jun 26, 2020
367c0ce
r/aws_route: Comment out failing target update test.
ewbankkit Jun 26, 2020
712f7f9
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_VpnGateway'.
ewbankkit Jun 27, 2020
6660eab
r/aws_route: Add 'TestAccAWSRoute_IPv6_To_VpnGateway'.
ewbankkit Jun 27, 2020
500a82f
r/aws_route: Test computed attributes.
ewbankkit Jun 27, 2020
5bf4423
r/aws_route: Changes for #13766, #13771.
ewbankkit Jun 27, 2020
e1368e0
r/aws_route: 'testAccCheckAWSRouteNumberOfRoutes' -> 'testAccCheckAWS…
ewbankkit Jun 29, 2020
325c19a
r/aws_route: Add 'TestAccAWSRoute_routeTableDisappears'.
ewbankkit Jun 29, 2020
c63c1fd
r/aws_route: Rework 'TestAccAWSRoute_ConditionalCidrBlock'.
ewbankkit Jul 1, 2020
6b573fb
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NetworkInterface_Attached' …
ewbankkit Jul 4, 2020
63fc15d
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachm…
ewbankkit Jul 4, 2020
2465e62
r/aws_route: Comment out failing 'TestAccAWSRoute_IPv4_To_NetworkInte…
ewbankkit Jul 4, 2020
2dcc784
r/aws_route: Use 'available' as the name of the 'aws_availability_zon…
ewbankkit Jul 6, 2020
9b1b292
r/aws_route: Use Amazon NAT instance AMI for instance tests.
ewbankkit Jul 15, 2020
b539198
Use 'testAccAvailableAZsNoOptInDefaultExcludeConfig'.
ewbankkit Aug 9, 2020
3220c66
r/aws_route: Add 'TestAccAWSRoute_IPv6_To_TransitGateway'.
ewbankkit Sep 4, 2020
ffa00f2
r/aws_route: Add 'TestAccAWSRoute_IPv6_To_LocalGateway'.
ewbankkit Sep 4, 2020
f5d7076
Rename 'TestAccAWSRoute_VpcEndpointId' to 'TestAccAWSRoute_IPv4_To_Vp…
ewbankkit Nov 15, 2020
88d8014
r/aws_route: Better validation.
ewbankkit Jul 1, 2020
61ed7fa
Add 'TestAccAWSRoute_IPv4_Update_Target'.
ewbankkit Nov 16, 2020
08076fd
Add 'TestAccAWSRoute_IPv6_Update_Target'.
ewbankkit Nov 16, 2020
11d0e3b
r/aws_route: Correctly handle route target updates.
ewbankkit Jul 3, 2020
b915d91
Uncomment 'TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments'.
ewbankkit Nov 16, 2020
8d023cf
r/aws_route: Use 'available' as the name of the 'aws_availability_zon…
ewbankkit Jul 6, 2020
611674a
r/aws_route: Add 'TestAccAWSRoute_LocalRoute' to test ability to impo…
ewbankkit Jul 8, 2020
bdd9ec0
r/aws_route: Add error constants to 'aws/internal/service/ec2'. Tweak…
ewbankkit Jul 10, 2020
0b26ae0
r/aw3s_route: Move route finders to 'aws/internal/service/ec2/finder'…
ewbankkit Jul 10, 2020
4a55181
r/aws_route: Add 'createRoute' function.
ewbankkit Jul 10, 2020
bc9c27f
Use 'testAccAvailableAZsNoOptInDefaultExcludeConfig'.
ewbankkit Aug 10, 2020
ef2cde7
Use 'RouteCreateID' in 'internal/service/ec2' package.
ewbankkit Aug 10, 2020
9d79531
Tweak EC2 error code constants.
ewbankkit Aug 23, 2020
78f52ab
Use 'tfnet.CIDRBlocksEqual' for IPv4 destination CIDR blocks.
ewbankkit Aug 23, 2020
ef5eabc
Tidy up route destination and target attribute checking in an attempt…
ewbankkit Aug 25, 2020
8efb4d8
r/aws_route: 'gateway_id', 'egress_only_gateway_id' and 'nat_gateway_…
ewbankkit Aug 25, 2020
508e49d
r/aws_route: Add 'getRouteDestinationAndTargetAttributeKeysFromMap' w…
ewbankkit Aug 25, 2020
5363227
r/aws_route: Minor tweak to error messages.
ewbankkit Aug 25, 2020
20d92b7
r/aws_route: Tweak route attribute IP version support.
ewbankkit Aug 26, 2020
1f16d61
r/aws_route: Use interface to abstract over '*schema.ResourceData' an…
ewbankkit Aug 26, 2020
32ac8d3
r/aws_route: Add 'local_gateway_id' to attribute checking.
ewbankkit Sep 6, 2020
a2ddacf
r/aws_route: Add plan-time validation that multiple destination and t…
ewbankkit Sep 6, 2020
0570169
Exclude 'resource_aws_route_test.go' from acceptance test Terraform l…
ewbankkit Oct 19, 2020
c825f7f
r/aws_route: Use attribute-level 'ConflictsWith' for IPv4 and IPv6-on…
ewbankkit Oct 20, 2020
9b64993
r/aws_route: Always set 'gateway_id' and 'vpc_endpoint_id'.
ewbankkit Nov 16, 2020
0529fee
r/aws_route: Use tfawserr.Err... functions.
ewbankkit Nov 19, 2020
2faf21f
r/aws_route: Use tfresource.TimedOut function.
ewbankkit Nov 19, 2020
ddaa35f
Rename 'TestAccAWSRoute_routeTableDisappears' to 'TestAccAWSRoute_dis…
ewbankkit Dec 8, 2020
5989ecf
Remove 'testAccCheckAWSRouteExists' (#16435).
ewbankkit Dec 8, 2020
aec57d3
r/aws_route: Prefer 'testAccAvailableAZsNoOptInConfig' over 'testAccA…
ewbankkit Dec 29, 2020
f0cbaa5
r/aws_route: Refactor acceptance test configuration generators so as …
ewbankkit Dec 29, 2020
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
15 changes: 15 additions & 0 deletions aws/data_source_aws_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2"
)

func dataSourceAwsRoute() *schema.Resource {
Expand Down Expand Up @@ -202,3 +204,16 @@ func getRoutes(table *ec2.RouteTable, d *schema.ResourceData) []*ec2.Route {
}
return routes
}

// Helper: Create an ID for a route
func resourceAwsRouteID(d *schema.ResourceData, r *ec2.Route) string {
routeTableID := d.Get("route_table_id").(string)

if destination := aws.StringValue(r.DestinationCidrBlock); destination != "" {
return tfec2.RouteCreateID(routeTableID, destination)
} else if destination := aws.StringValue(r.DestinationIpv6CidrBlock); destination != "" {
return tfec2.RouteCreateID(routeTableID, destination)
}

return ""
}
5 changes: 0 additions & 5 deletions aws/data_source_aws_route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)
Expand All @@ -28,7 +27,6 @@ func TestAccAWSRouteDataSource_basic(t *testing.T) {
}

func TestAccAWSRouteDataSource_TransitGatewayID(t *testing.T) {
var route ec2.Route
dataSourceName := "data.aws_route.test"
resourceName := "aws_route.test"

Expand All @@ -40,7 +38,6 @@ func TestAccAWSRouteDataSource_TransitGatewayID(t *testing.T) {
{
Config: testAccAWSRouteDataSourceConfigTransitGatewayID(),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRouteExists(resourceName, &route),
resource.TestCheckResourceAttrPair(resourceName, "destination_cidr_block", dataSourceName, "destination_cidr_block"),
resource.TestCheckResourceAttrPair(resourceName, "route_table_id", dataSourceName, "route_table_id"),
resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", dataSourceName, "transit_gateway_id"),
Expand All @@ -51,7 +48,6 @@ func TestAccAWSRouteDataSource_TransitGatewayID(t *testing.T) {
}

func TestAccAWSRouteDataSource_LocalGatewayID(t *testing.T) {
var route ec2.Route
dataSourceName := "data.aws_route.by_local_gateway_id"
resourceName := "aws_route.test"

Expand All @@ -63,7 +59,6 @@ func TestAccAWSRouteDataSource_LocalGatewayID(t *testing.T) {
{
Config: testAccAWSRouteDataSourceConfigLocalGatewayID(),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRouteExists(resourceName, &route),
resource.TestCheckResourceAttrPair(resourceName, "destination_cidr_block", dataSourceName, "destination_cidr_block"),
resource.TestCheckResourceAttrPair(resourceName, "route_table_id", dataSourceName, "route_table_id"),
resource.TestCheckResourceAttrPair(resourceName, "local_gateway_id", dataSourceName, "local_gateway_id"),
Expand Down
23 changes: 23 additions & 0 deletions aws/internal/net/cidr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net

import (
"net"
)

// CIDRBlocksEqual returns whether or not two CIDR blocks are equal:
// - Both CIDR blocks parse to an IP address and network
// - The string representation of the IP addresses are equal
// - The string representation of the networks are equal
// This function is especially useful for IPv6 CIDR blocks which have multiple valid representations.
func CIDRBlocksEqual(cidr1, cidr2 string) bool {
ip1, ipnet1, err := net.ParseCIDR(cidr1)
if err != nil {
return false
}
ip2, ipnet2, err := net.ParseCIDR(cidr2)
if err != nil {
return false
}

return ip2.String() == ip1.String() && ipnet2.String() == ipnet1.String()
}
26 changes: 26 additions & 0 deletions aws/internal/net/cidr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package net

import (
"testing"
)

func Test_CIDRBlocksEqual(t *testing.T) {
for _, ts := range []struct {
cidr1 string
cidr2 string
equal bool
}{
{"10.2.2.0/24", "10.2.2.0/24", true},
{"10.2.2.0/1234", "10.2.2.0/24", false},
{"10.2.2.0/24", "10.2.2.0/1234", false},
{"2001::/15", "2001::/15", true},
{"::/0", "2001::/15", false},
{"::/0", "::0/0", true},
{"", "", false},
} {
equal := CIDRBlocksEqual(ts.cidr1, ts.cidr2)
if ts.equal != equal {
t.Fatalf("CIDRBlocksEqual(%q, %q) should be: %t", ts.cidr1, ts.cidr2, ts.equal)
}
}
}
21 changes: 21 additions & 0 deletions aws/internal/service/ec2/errors.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,42 @@
package ec2

// Common.
const (
ErrCodeInvalidParameterException = "InvalidParameterException"
ErrCodeInvalidParameterValue = "InvalidParameterValue"
)

// Client VPN.
const (
ErrCodeClientVpnEndpointIdNotFound = "InvalidClientVpnEndpointId.NotFound"
ErrCodeClientVpnAuthorizationRuleNotFound = "InvalidClientVpnEndpointAuthorizationRuleNotFound"
ErrCodeClientVpnAssociationIdNotFound = "InvalidClientVpnAssociationId.NotFound"
ErrCodeClientVpnRouteNotFound = "InvalidClientVpnRouteNotFound"
)

// Security Group.
const (
InvalidSecurityGroupIDNotFound = "InvalidSecurityGroupID.NotFound"
InvalidGroupNotFound = "InvalidGroup.NotFound"
)

// Route and Route Table.
const (
ErrCodeInvalidRouteNotFound = "InvalidRoute.NotFound"
ErrCodeInvalidRouteTableIDNotFound = "InvalidRouteTableID.NotFound"
)

// Transit Gateway.
const (
ErrCodeInvalidTransitGatewayIDNotFound = "InvalidTransitGatewayID.NotFound"
)

// VPC Peering Connection.
const (
ErrCodeInvalidVpcPeeringConnectionIDNotFound = "InvalidVpcPeeringConnectionID.NotFound"
)

// VPN Gateway.
const (
InvalidVpnGatewayAttachmentNotFound = "InvalidVpnGatewayAttachment.NotFound"
InvalidVpnGatewayIDNotFound = "InvalidVpnGatewayID.NotFound"
Expand Down
56 changes: 56 additions & 0 deletions aws/internal/service/ec2/finder/finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package finder
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
tfnet "github.com/terraform-providers/terraform-provider-aws/aws/internal/net"
tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2"
)

Expand Down Expand Up @@ -55,6 +56,61 @@ func ClientVpnRouteByID(conn *ec2.EC2, routeID string) (*ec2.DescribeClientVpnRo
return ClientVpnRoute(conn, endpointID, targetSubnetID, destinationCidr)
}

// RouteTableByID returns the route table corresponding to the specified identifier.
// Returns nil if no route table is found.
func RouteTableByID(conn *ec2.EC2, routeTableID string) (*ec2.RouteTable, error) {
input := &ec2.DescribeRouteTablesInput{
RouteTableIds: aws.StringSlice([]string{routeTableID}),
}

output, err := conn.DescribeRouteTables(input)
if err != nil {
return nil, err
}

if output == nil || len(output.RouteTables) == 0 || output.RouteTables[0] == nil {
return nil, nil
}

return output.RouteTables[0], nil
}

type RouteFinder func(*ec2.EC2, string, string) (*ec2.Route, error)

// RouteByIpv4Destination returns the route corresponding to the specified IPv4 destination.
// Returns nil if no route is found.
func RouteByIpv4Destination(conn *ec2.EC2, routeTableID, destinationCidr string) (*ec2.Route, error) {
routeTable, err := RouteTableByID(conn, routeTableID)
if err != nil {
return nil, err
}

for _, route := range routeTable.Routes {
if tfnet.CIDRBlocksEqual(aws.StringValue(route.DestinationCidrBlock), destinationCidr) {
return route, nil
}
}

return nil, nil
}

// RouteByIpv6Destination returns the route corresponding to the specified IPv6 destination.
// Returns nil if no route is found.
func RouteByIpv6Destination(conn *ec2.EC2, routeTableID, destinationIpv6Cidr string) (*ec2.Route, error) {
routeTable, err := RouteTableByID(conn, routeTableID)
if err != nil {
return nil, err
}

for _, route := range routeTable.Routes {
if tfnet.CIDRBlocksEqual(aws.StringValue(route.DestinationIpv6CidrBlock), destinationIpv6Cidr) {
return route, nil
}
}

return nil, nil
}

// SecurityGroupByID looks up a security group by ID. When not found, returns nil and potentially an API error.
func SecurityGroupByID(conn *ec2.EC2, id string) (*ec2.SecurityGroup, error) {
req := &ec2.DescribeSecurityGroupsInput{
Expand Down
5 changes: 5 additions & 0 deletions aws/internal/service/ec2/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ func ClientVpnRouteParseID(id string) (string, string, string, error) {
"target-subnet-id"+clientVpnRouteIDSeparator+"destination-cidr-block", id)
}

// RouteCreateID returns a route resource ID.
func RouteCreateID(routeTableID, destination string) string {
return fmt.Sprintf("r-%s%d", routeTableID, hashcode.String(destination))
}

func VpnGatewayVpcAttachmentCreateID(vpnGatewayID, vpcID string) string {
return fmt.Sprintf("vpn-attachment-%x", hashcode.String(fmt.Sprintf("%s-%s", vpcID, vpnGatewayID)))
}
Loading