-
Notifications
You must be signed in to change notification settings - Fork 9.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New Resource: aws_ec2_local_gateway_route (#13768)
Reference: #13503 Output from acceptance testing: ``` --- PASS: TestAccAWSEc2LocalGatewayRoute_disappears (22.00s) --- PASS: TestAccAWSEc2LocalGatewayRoute_basic (22.43s) ```
- Loading branch information
Showing
5 changed files
with
420 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"strings" | ||
"time" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/ec2" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
) | ||
|
||
const ( | ||
ec2LocalGatewayRouteEventualConsistencyTimeout = 1 * time.Minute | ||
) | ||
|
||
func resourceAwsEc2LocalGatewayRoute() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceAwsEc2LocalGatewayRouteCreate, | ||
Read: resourceAwsEc2LocalGatewayRouteRead, | ||
Delete: resourceAwsEc2LocalGatewayRouteDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"destination_cidr_block": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validateCIDRNetworkAddress, | ||
}, | ||
"local_gateway_route_table_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"local_gateway_virtual_interface_group_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsEc2LocalGatewayRouteCreate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
|
||
destination := d.Get("destination_cidr_block").(string) | ||
localGatewayRouteTableID := d.Get("local_gateway_route_table_id").(string) | ||
|
||
input := &ec2.CreateLocalGatewayRouteInput{ | ||
DestinationCidrBlock: aws.String(destination), | ||
LocalGatewayRouteTableId: aws.String(localGatewayRouteTableID), | ||
LocalGatewayVirtualInterfaceGroupId: aws.String(d.Get("local_gateway_virtual_interface_group_id").(string)), | ||
} | ||
|
||
_, err := conn.CreateLocalGatewayRoute(input) | ||
|
||
if err != nil { | ||
return fmt.Errorf("error creating EC2 Local Gateway Route: %s", err) | ||
} | ||
|
||
d.SetId(fmt.Sprintf("%s_%s", localGatewayRouteTableID, destination)) | ||
|
||
return resourceAwsEc2LocalGatewayRouteRead(d, meta) | ||
} | ||
|
||
func resourceAwsEc2LocalGatewayRouteRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
|
||
localGatewayRouteTableID, destination, err := decodeEc2LocalGatewayRouteID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var localGatewayRoute *ec2.LocalGatewayRoute | ||
err = resource.Retry(ec2LocalGatewayRouteEventualConsistencyTimeout, func() *resource.RetryError { | ||
var err error | ||
localGatewayRoute, err = getEc2LocalGatewayRoute(conn, localGatewayRouteTableID, destination) | ||
|
||
if err != nil { | ||
return resource.NonRetryableError(err) | ||
} | ||
|
||
if d.IsNewResource() && localGatewayRoute == nil { | ||
return resource.RetryableError(&resource.NotFoundError{}) | ||
} | ||
|
||
return nil | ||
}) | ||
|
||
if isResourceTimeoutError(err) { | ||
localGatewayRoute, err = getEc2LocalGatewayRoute(conn, localGatewayRouteTableID, destination) | ||
} | ||
|
||
if isAWSErr(err, "InvalidRouteTableID.NotFound", "") { | ||
log.Printf("[WARN] EC2 Local Gateway Route Table (%s) not found, removing from state", localGatewayRouteTableID) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
if !d.IsNewResource() && isResourceNotFoundError(err) { | ||
log.Printf("[WARN] EC2 Local Gateway Route (%s) not found, removing from state", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
if err != nil { | ||
return fmt.Errorf("error reading EC2 Local Gateway Route: %s", err) | ||
} | ||
|
||
if localGatewayRoute == nil { | ||
log.Printf("[WARN] EC2 Local Gateway Route (%s) not found, removing from state", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
state := aws.StringValue(localGatewayRoute.State) | ||
if state == ec2.LocalGatewayRouteStateDeleted || state == ec2.LocalGatewayRouteStateDeleting { | ||
log.Printf("[WARN] EC2 Local Gateway Route (%s) deleted, removing from state", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
d.Set("destination_cidr_block", localGatewayRoute.DestinationCidrBlock) | ||
d.Set("local_gateway_virtual_interface_group_id", localGatewayRoute.LocalGatewayVirtualInterfaceGroupId) | ||
d.Set("local_gateway_route_table_id", localGatewayRoute.LocalGatewayRouteTableId) | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsEc2LocalGatewayRouteDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
|
||
localGatewayRouteTableID, destination, err := decodeEc2LocalGatewayRouteID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
input := &ec2.DeleteLocalGatewayRouteInput{ | ||
DestinationCidrBlock: aws.String(destination), | ||
LocalGatewayRouteTableId: aws.String(localGatewayRouteTableID), | ||
} | ||
|
||
log.Printf("[DEBUG] Deleting EC2 Local Gateway Route (%s): %s", d.Id(), input) | ||
_, err = conn.DeleteLocalGatewayRoute(input) | ||
|
||
if isAWSErr(err, "InvalidRoute.NotFound", "") || isAWSErr(err, "InvalidRouteTableID.NotFound", "") { | ||
return nil | ||
} | ||
|
||
if err != nil { | ||
return fmt.Errorf("error deleting EC2 Local Gateway Route: %s", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func decodeEc2LocalGatewayRouteID(id string) (string, string, error) { | ||
parts := strings.Split(id, "_") | ||
|
||
if len(parts) != 2 { | ||
return "", "", fmt.Errorf("Unexpected format of ID (%q), expected tgw-rtb-ID_DESTINATION", id) | ||
} | ||
|
||
return parts[0], parts[1], nil | ||
} | ||
|
||
func getEc2LocalGatewayRoute(conn *ec2.EC2, localGatewayRouteTableID, destination string) (*ec2.LocalGatewayRoute, error) { | ||
input := &ec2.SearchLocalGatewayRoutesInput{ | ||
Filters: []*ec2.Filter{ | ||
{ | ||
Name: aws.String("type"), | ||
Values: aws.StringSlice([]string{"static"}), | ||
}, | ||
}, | ||
LocalGatewayRouteTableId: aws.String(localGatewayRouteTableID), | ||
} | ||
|
||
output, err := conn.SearchLocalGatewayRoutes(input) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if output == nil || len(output.Routes) == 0 { | ||
return nil, nil | ||
} | ||
|
||
for _, route := range output.Routes { | ||
if route == nil { | ||
continue | ||
} | ||
|
||
if aws.StringValue(route.DestinationCidrBlock) == destination { | ||
return route, nil | ||
} | ||
} | ||
|
||
return nil, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/terraform" | ||
) | ||
|
||
func TestAccAWSEc2LocalGatewayRoute_basic(t *testing.T) { | ||
// Hide Outposts testing behind consistent environment variable | ||
outpostArn := os.Getenv("AWS_OUTPOST_ARN") | ||
if outpostArn == "" { | ||
t.Skip( | ||
"Environment variable AWS_OUTPOST_ARN is not set. " + | ||
"This environment variable must be set to the ARN of " + | ||
"a deployed Outpost to enable this test.") | ||
} | ||
|
||
rInt := randIntRange(0, 255) | ||
destinationCidrBlock := fmt.Sprintf("172.16.%d.0/24", rInt) | ||
localGatewayRouteTableDataSourceName := "data.aws_ec2_local_gateway_route_table.test" | ||
localGatewayVirtualInterfaceGroupDataSourceName := "data.aws_ec2_local_gateway_virtual_interface_group.test" | ||
resourceName := "aws_ec2_local_gateway_route.test" | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckAWSEc2LocalGatewayRouteDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccAWSEc2LocalGatewayRouteConfigDestinationCidrBlock(destinationCidrBlock), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAWSEc2LocalGatewayRouteExists(resourceName), | ||
resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidrBlock), | ||
resource.TestCheckResourceAttrPair(resourceName, "local_gateway_route_table_id", localGatewayRouteTableDataSourceName, "id"), | ||
resource.TestCheckResourceAttrPair(resourceName, "local_gateway_virtual_interface_group_id", localGatewayVirtualInterfaceGroupDataSourceName, "id"), | ||
), | ||
}, | ||
{ | ||
ResourceName: resourceName, | ||
ImportState: true, | ||
ImportStateVerify: true, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccAWSEc2LocalGatewayRoute_disappears(t *testing.T) { | ||
// Hide Outposts testing behind consistent environment variable | ||
outpostArn := os.Getenv("AWS_OUTPOST_ARN") | ||
if outpostArn == "" { | ||
t.Skip( | ||
"Environment variable AWS_OUTPOST_ARN is not set. " + | ||
"This environment variable must be set to the ARN of " + | ||
"a deployed Outpost to enable this test.") | ||
} | ||
|
||
rInt := randIntRange(0, 255) | ||
destinationCidrBlock := fmt.Sprintf("172.16.%d.0/24", rInt) | ||
resourceName := "aws_ec2_local_gateway_route.test" | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckAWSEc2LocalGatewayRouteDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccAWSEc2LocalGatewayRouteConfigDestinationCidrBlock(destinationCidrBlock), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAWSEc2LocalGatewayRouteExists(resourceName), | ||
testAccCheckResourceDisappears(testAccProvider, resourceAwsEc2LocalGatewayRoute(), resourceName), | ||
), | ||
ExpectNonEmptyPlan: true, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckAWSEc2LocalGatewayRouteExists(resourceName string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[resourceName] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", resourceName) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("No EC2 Local Gateway Route ID is set") | ||
} | ||
|
||
localGatewayRouteTableID, destination, err := decodeEc2LocalGatewayRouteID(rs.Primary.ID) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
conn := testAccProvider.Meta().(*AWSClient).ec2conn | ||
|
||
route, err := getEc2LocalGatewayRoute(conn, localGatewayRouteTableID, destination) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
if route == nil { | ||
return fmt.Errorf("EC2 Local Gateway Route (%s) not found", rs.Primary.ID) | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckAWSEc2LocalGatewayRouteDestroy(s *terraform.State) error { | ||
conn := testAccProvider.Meta().(*AWSClient).ec2conn | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "aws_ec2_local_gateway_route" { | ||
continue | ||
} | ||
|
||
localGatewayRouteTableID, destination, err := decodeEc2LocalGatewayRouteID(rs.Primary.ID) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
route, err := getEc2LocalGatewayRoute(conn, localGatewayRouteTableID, destination) | ||
|
||
if isAWSErr(err, "InvalidRouteTableID.NotFound", "") { | ||
continue | ||
} | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
if route == nil { | ||
continue | ||
} | ||
|
||
return fmt.Errorf("EC2 Local Gateway Route (%s) still exists", rs.Primary.ID) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func testAccAWSEc2LocalGatewayRouteConfigDestinationCidrBlock(destinationCidrBlock string) string { | ||
return fmt.Sprintf(` | ||
data "aws_ec2_local_gateways" "test" {} | ||
data "aws_ec2_local_gateway_route_table" "test" { | ||
local_gateway_id = tolist(data.aws_ec2_local_gateways.test.ids)[0] | ||
} | ||
data "aws_ec2_local_gateway_virtual_interface_group" "test" { | ||
local_gateway_id = tolist(data.aws_ec2_local_gateways.test.ids)[0] | ||
} | ||
resource "aws_ec2_local_gateway_route" "test" { | ||
destination_cidr_block = %[1]q | ||
local_gateway_route_table_id = data.aws_ec2_local_gateway_route_table.test.id | ||
local_gateway_virtual_interface_group_id = data.aws_ec2_local_gateway_virtual_interface_group.test.id | ||
} | ||
`, destinationCidrBlock) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.