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

[WIP] r/aws_route: Correctly handle update of route target #15049

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
2848e4b
r/aws_route: Tidy up 'testAccAWSRouteConfigBasic()'.
ewbankkit Jun 25, 2020
99a3774
r/aws_route: Rename 'TestAccAWSRoute_ipv6Support' to 'TestAccAWSRoute…
ewbankkit Jun 25, 2020
e300f4c
Remove 'TestAccAWSRoute_noopdiff'. Test steps implicitly test this fu…
ewbankkit Jun 25, 2020
3113117
r/aws_route: Tidy up 'TestAccAWSRoute_doesNotCrashWithVPCEndpoint'.
ewbankkit Jun 25, 2020
320b50a
r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToInternetGateway'.
ewbankkit Jun 26, 2020
6b3340f
r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToInstance'.
ewbankkit Jun 26, 2020
444ca9a
r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToNetworkInterface'.
ewbankkit Jun 26, 2020
8702b54
r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToVpcPeeringConnection'.
ewbankkit Jun 26, 2020
d7b9cc3
r/aws_route: Tidy up 'TestAccAWSRoute_TransitGatewayID_DestinationCid…
ewbankkit Jun 26, 2020
f316b53
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_Instance'.
ewbankkit Jun 26, 2020
e5e0c24
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NetworkInterface'.
ewbankkit Jun 26, 2020
e4186c8
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_VpcPeeringConnection'.
ewbankkit Jun 26, 2020
e8e3e0d
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NatGateway'.
ewbankkit Jun 26, 2020
f79717a
r/aws_route: Comment out failing target update test.
ewbankkit Jun 26, 2020
80389f0
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_VpnGateway'.
ewbankkit Jun 27, 2020
3653129
r/aws_route: Add 'TestAccAWSRoute_IPv6_To_VpnGateway'.
ewbankkit Jun 27, 2020
f7d8deb
r/aws_route: Test computed attributes.
ewbankkit Jun 27, 2020
f0ea86f
r/aws_route: Changes for #13766, #13771.
ewbankkit Jun 27, 2020
69a8fb7
r/aws_route: 'testAccCheckAWSRouteNumberOfRoutes' -> 'testAccCheckAWS…
ewbankkit Jun 29, 2020
9de465c
r/aws_route: Add 'TestAccAWSRoute_routeTableDisappears'.
ewbankkit Jun 29, 2020
223fe32
r/aws_route: Rework 'TestAccAWSRoute_ConditionalCidrBlock'.
ewbankkit Jul 1, 2020
c7e6ac0
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NetworkInterface_Attached' …
ewbankkit Jul 4, 2020
c80e7cf
r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachm…
ewbankkit Jul 4, 2020
27f943b
r/aws_route: Comment out failing 'TestAccAWSRoute_IPv4_To_NetworkInte…
ewbankkit Jul 4, 2020
627589a
r/aws_route: Use 'available' as the name of the 'aws_availability_zon…
ewbankkit Jul 6, 2020
449cf71
r/aws_route: Use Amazon NAT instance AMI for instance tests.
ewbankkit Jul 15, 2020
14f2e58
Use 'testAccAvailableAZsNoOptInDefaultExcludeConfig'.
ewbankkit Aug 9, 2020
25dc08f
r/aws_route: Add 'TestAccAWSRoute_IPv6_To_TransitGateway'.
ewbankkit Sep 4, 2020
2163d22
r/aws_route: Add 'TestAccAWSRoute_IPv6_To_LocalGateway'.
ewbankkit Sep 4, 2020
b51d0bb
r/aws_route: Add 'TestAccAWSRoute_IPv4_Update_Target'. Currently fails.
ewbankkit Jun 27, 2020
70b839b
r/aws_route: Add 'TestAccAWSRoute_IPv6_Update_Target'. Currently fails.
ewbankkit Jun 28, 2020
32aa5ca
r/aws_route: Better validation.
ewbankkit Jul 1, 2020
d4ca1f4
r/aws_route: Correctly handle route target updates.
ewbankkit Jul 3, 2020
3ba48be
r/aws_route: Uncommented 'TestAccAWSRoute_IPv4_To_NetworkInterface_Tw…
ewbankkit Jul 4, 2020
e94bc67
Acceptance test output:
ewbankkit Jul 4, 2020
059c95f
r/aws_route: Use 'available' as the name of the 'aws_availability_zon…
ewbankkit Jul 6, 2020
99738d8
r/aws_route: Add 'TestAccAWSRoute_LocalRoute' to test ability to impo…
ewbankkit Jul 8, 2020
b234a41
r/aws_route: Add error constants to 'aws/internal/service/ec2'. Tweak…
ewbankkit Jul 10, 2020
af40160
r/aw3s_route: Move route finders to 'aws/internal/service/ec2/finder'…
ewbankkit Jul 10, 2020
4d06124
r/aws_route: Add 'createRoute' function.
ewbankkit Jul 10, 2020
158d780
Use 'testAccAvailableAZsNoOptInDefaultExcludeConfig'.
ewbankkit Aug 10, 2020
d656cba
Use 'RouteCreateID' in 'internal/service/ec2' package.
ewbankkit Aug 10, 2020
cc2f8fb
Tweak EC2 error code constants.
ewbankkit Aug 23, 2020
3affa49
Use 'tfnet.CIDRBlocksEqual' for IPv4 destination CIDR blocks.
ewbankkit Aug 23, 2020
f0cefd8
Tidy up route destination and target attribute checking in an attempt…
ewbankkit Aug 25, 2020
99f150e
r/aws_route: 'gateway_id', 'egress_only_gateway_id' and 'nat_gateway_…
ewbankkit Aug 25, 2020
67a569d
r/aws_route: Add 'getRouteDestinationAndTargetAttributeKeysFromMap' w…
ewbankkit Aug 25, 2020
f4f54b0
r/aws_route: Minor tweak to error messages.
ewbankkit Aug 25, 2020
dd110e1
r/aws_route: Tweak route attribute IP version support.
ewbankkit Aug 26, 2020
50234dc
r/aws_route: Use interface to abstract over '*schema.ResourceData' an…
ewbankkit Aug 26, 2020
275b329
r/aws_route: Add 'local_gateway_id' to attribute checking.
ewbankkit Sep 6, 2020
2909c2a
r/aws_route: Add plan-time validation that multiple destination and t…
ewbankkit Sep 6, 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 {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved here temporarily. Will need to clean up when support for managed prefix list IDs added.

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 ""
}
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)
}
}
}
19 changes: 19 additions & 0 deletions aws/internal/service/ec2/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,33 @@ func ErrCodeEquals(err error, code string) bool {
return false
}

// Common.
const (
InvalidParameterException = "InvalidParameterException"
InvalidParameterValue = "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 (
InvalidRouteNotFound = "InvalidRoute.NotFound"
InvalidRouteTableIDNotFound = "InvalidRouteTableID.NotFound"
)

// Transit Gateway.
const (
InvalidTransitGatewayIDNotFound = "InvalidTransitGatewayID.NotFound"
)
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
7 changes: 7 additions & 0 deletions aws/internal/service/ec2/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package ec2
import (
"fmt"
"strings"

"github.com/terraform-providers/terraform-provider-aws/aws/internal/hashcode"
)

const clientVpnAuthorizationRuleIDSeparator = ","
Expand Down Expand Up @@ -68,3 +70,8 @@ func ClientVpnRouteParseID(id string) (string, string, string, error) {
fmt.Errorf("unexpected format for ID (%q), expected endpoint-id"+clientVpnRouteIDSeparator+
"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))
}
Loading