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_(default)_route_table: 'destination_prefix_list_id' attribute can be specified for managed prefix list destinations #17319

Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8638d27
r/aws_default_route_table: AWS Wavelength support.
ewbankkit Jan 6, 2021
052f75d
Revert "r/aws_default_route_table: AWS Wavelength support."
ewbankkit Jan 6, 2021
7df1469
r/aws_default_route_table: Add 'arn' attribute.
ewbankkit Jan 6, 2021
621c838
r/aws_route_table: 'destination_prefix_list_id' attribute can be spec…
ewbankkit Jan 27, 2021
985bb3c
Rename CHANGELOG entry file.
ewbankkit Jan 27, 2021
ce09aed
Add acceptance test pre-check.
ewbankkit Jan 27, 2021
d30ceb5
r/aws_default_route_table: 'destination_prefix_list_id' attribute can…
ewbankkit Jan 28, 2021
d8d5437
r/aws_(default)_route_table: Add 'ErrorCheck' to new acceptance tests.
ewbankkit Mar 26, 2021
5c59677
Fix issue when creating default route table that has a route propagation
gpiper14 Mar 8, 2019
9be0522
r/aws_default_route_table: Add 'TestAccAWSDefaultRouteTable_RevokeExi…
ewbankkit Mar 28, 2021
6c2cc1f
route_table: fail creation if later read does not find resource
staebler Mar 1, 2019
2fef042
r/aws_route_table: Add 'd.IsNewResource()' check to resource read (#1…
ewbankkit Mar 29, 2021
65d1d7a
r/route_table: Code consistency
YakDriver Mar 29, 2021
1961ca1
r/route_table: Code consistency
YakDriver Mar 29, 2021
3407ddf
r/route_table: Add waiter and status for route table
YakDriver Mar 29, 2021
90b0c97
r/route_table_association: Use waiter for route table status
YakDriver Mar 29, 2021
6c7be9d
r/route_table: Switch to waiter
YakDriver Mar 29, 2021
491cbfd
r/vpn_gateway_route_propagation: Use waiter for route table status
YakDriver Mar 29, 2021
56c538d
r/vpn_gateway_route_propagation: Use correct ID for waiter
YakDriver Mar 29, 2021
43181cd
r/route_table: Avoid changing API errors
YakDriver Mar 29, 2021
960b0d7
r/route_table: Rework waiters and VPN gateway route test
YakDriver Mar 29, 2021
7665057
r/route_table_associations: Check that route table exists
YakDriver Mar 29, 2021
ac11d76
r/route_table: Switch to using tfresource Not Found
YakDriver Mar 29, 2021
87fa5bf
r/route_table: Remove unnecessary check
YakDriver Mar 29, 2021
f36fc0a
route_table: Add changelog items
YakDriver Mar 29, 2021
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
7 changes: 7 additions & 0 deletions .changelog/17319.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-notes:enhancement
resource/aws_default_route_table: Add `destination_prefix_list_id` attribute
```

```release-notes:enhancement
resource/aws_route_table: Add `destination_prefix_list_id` attribute
```
27 changes: 27 additions & 0 deletions aws/internal/service/ec2/waiter/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/finder"
tfiam "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/iam"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource"
)

const (
Expand Down Expand Up @@ -245,6 +246,32 @@ func InstanceIamInstanceProfile(conn *ec2.EC2, id string) resource.StateRefreshF
}
}

const (
ErrCodeInvalidRouteTableIDNotFound = "InvalidRouteTableID.NotFound"
Copy link
Contributor Author

@ewbankkit ewbankkit Mar 29, 2021

Choose a reason for hiding this comment

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

Can remove this as it is should not be referenced below.


RouteTableStatusReady = "ready"
)

func RouteTableStatus(conn *ec2.EC2, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := finder.RouteTableByID(conn, id)

if tfresource.NotFound(err) {
return nil, "", nil
}

if err != nil {
return nil, "", err
}

if output == nil {
return nil, "", nil
}

return output, RouteTableStatusReady, nil
}
}

const (
SecurityGroupStatusCreated = "Created"

Expand Down
48 changes: 48 additions & 0 deletions aws/internal/service/ec2/waiter/waiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource"
)

const (
Expand Down Expand Up @@ -257,6 +258,53 @@ const (
NetworkAclEntryPropagationTimeout = 5 * time.Minute
)

const (
RouteTableReadyTimeout = 10 * time.Minute
RouteTableDeletedTimeout = 5 * time.Minute
RouteTableUpdateTimeout = 5 * time.Minute

RouteTableNotFoundChecks = 40
)

func RouteTableReady(conn *ec2.EC2, id string) (*ec2.RouteTable, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{},
Target: []string{RouteTableStatusReady},
Refresh: RouteTableStatus(conn, id),
Timeout: RouteTableReadyTimeout,
NotFoundChecks: RouteTableNotFoundChecks,
}

outputRaw, err := stateConf.WaitForState()

if output, ok := outputRaw.(*ec2.RouteTable); ok {
return output, err
}

return nil, err
}

func RouteTableDeleted(conn *ec2.EC2, id string) (*ec2.RouteTable, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{RouteTableStatusReady},
Target: []string{},
Refresh: RouteTableStatus(conn, id),
Timeout: RouteTableDeletedTimeout,
}

outputRaw, err := stateConf.WaitForState()

if tfresource.NotFound(err) {
Copy link
Member

Choose a reason for hiding this comment

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

This can go since the status eats NotFound.

return nil, nil
}

if output, ok := outputRaw.(*ec2.RouteTable); ok {
return output, err
}

return nil, err
}

func SecurityGroupCreated(conn *ec2.EC2, id string, timeout time.Duration) (*ec2.SecurityGroup, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{SecurityGroupStatusNotFound},
Expand Down
101 changes: 52 additions & 49 deletions aws/resource_aws_default_route_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package aws
import (
"fmt"
"log"
"strings"

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

func resourceAwsDefaultRouteTable() *schema.Resource {
Expand Down Expand Up @@ -50,6 +52,9 @@ func resourceAwsDefaultRouteTable() *schema.Resource {
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
///
// Destinations.
///
"cidr_block": {
Type: schema.TypeString,
Optional: true,
Expand All @@ -68,6 +73,14 @@ func resourceAwsDefaultRouteTable() *schema.Resource {
),
},

"destination_prefix_list_id": {
Type: schema.TypeString,
Optional: true,
},

//
// Targets.
//
"egress_only_gateway_id": {
Type: schema.TypeString,
Optional: true,
Expand All @@ -88,22 +101,22 @@ func resourceAwsDefaultRouteTable() *schema.Resource {
Optional: true,
},

"transit_gateway_id": {
"network_interface_id": {
Type: schema.TypeString,
Optional: true,
},

"vpc_endpoint_id": {
"transit_gateway_id": {
Type: schema.TypeString,
Optional: true,
},

"vpc_peering_connection_id": {
"vpc_endpoint_id": {
Type: schema.TypeString,
Optional: true,
},

"network_interface_id": {
"vpc_peering_connection_id": {
Type: schema.TypeString,
Optional: true,
},
Expand All @@ -128,31 +141,28 @@ func resourceAwsDefaultRouteTable() *schema.Resource {
}

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())()
routeTableID := d.Get("default_route_table_id").(string)

routeTable, err := finder.RouteTableByID(conn, routeTableID)

if err != nil {
return fmt.Errorf("error reading EC2 Default Route Table (%s): %s", d.Id(), err)
}
if rtRaw == nil {
return fmt.Errorf("error reading EC2 Default Route Table (%s): not found", d.Id())
return fmt.Errorf("error reading EC2 Default Route Table (%s): %w", routeTableID, err)
}

rt := rtRaw.(*ec2.RouteTable)

d.Set("vpc_id", rt.VpcId)
d.SetId(routeTableID)
d.Set("vpc_id", routeTable.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 {
if err := revokeAllRouteTableRules(conn, routeTable); err != nil {
return err
}

if v := d.Get("tags").(map[string]interface{}); len(v) > 0 {
if err := keyvaluetags.Ec2CreateTags(conn, d.Id(), v); err != nil {
return fmt.Errorf("error adding tags: %s", err)
return fmt.Errorf("error adding tags: %w", err)
}
}

Expand Down Expand Up @@ -203,75 +213,68 @@ func resourceAwsDefaultRouteTableDelete(d *schema.ResourceData, meta interface{}

// 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]

func revokeAllRouteTableRules(conn *ec2.EC2, routeTable *ec2.RouteTable) error {
// Remove all Gateway association
for _, r := range rt.PropagatingVgws {
log.Printf(
"[INFO] Deleting VGW propagation from %s: %s",
defaultRouteTableId, *r.GatewayId)
for _, r := range routeTable.PropagatingVgws {
_, err := conn.DisableVgwRoutePropagation(&ec2.DisableVgwRoutePropagationInput{
RouteTableId: aws.String(defaultRouteTableId),
RouteTableId: routeTable.RouteTableId,
GatewayId: r.GatewayId,
})

if err != nil {
return err
}
}

// Delete all routes
for _, r := range rt.Routes {
for _, r := range routeTable.Routes {
// you cannot delete the local route
if r.GatewayId != nil && *r.GatewayId == "local" {
if aws.StringValue(r.GatewayId) == "local" {
continue
}
if r.DestinationPrefixListId != nil {

if aws.StringValue(r.Origin) == ec2.RouteOriginEnableVgwRoutePropagation {
continue
}

if r.DestinationPrefixListId != nil && strings.HasPrefix(aws.StringValue(r.GatewayId), "vpce-") {
// 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),
RouteTableId: routeTable.RouteTableId,
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),
RouteTableId: routeTable.RouteTableId,
DestinationIpv6CidrBlock: r.DestinationIpv6CidrBlock,
})

if err != nil {
return err
}
}

if r.DestinationPrefixListId != nil {
_, err := conn.DeleteRoute(&ec2.DeleteRouteInput{
RouteTableId: routeTable.RouteTableId,
DestinationPrefixListId: r.DestinationPrefixListId,
})

if err != nil {
return err
}
}
}

return nil
Expand Down
Loading