Skip to content

Commit

Permalink
New Resource: aws_ec2_local_gateway_route_table_vpc_association (#13765)
Browse files Browse the repository at this point in the history
Reference: #13501

Output from acceptance testing:

```
--- PASS: TestAccAwsEc2LocalGatewayRouteTableVpcAssociation_basic (35.14s)
--- PASS: TestAccAwsEc2LocalGatewayRouteTableVpcAssociation_disappears (37.27s)
--- PASS: TestAccAwsEc2LocalGatewayRouteTableVpcAssociation_Tags (74.40s)
```
  • Loading branch information
bflad authored Jun 17, 2020
1 parent 17dba10 commit 1f26314
Show file tree
Hide file tree
Showing 7 changed files with 569 additions and 0 deletions.
41 changes: 41 additions & 0 deletions aws/internal/service/ec2/waiter/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package waiter

import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
)

// LocalGatewayRouteTableVpcAssociationState fetches the LocalGatewayRouteTableVpcAssociation and its State
func LocalGatewayRouteTableVpcAssociationState(conn *ec2.EC2, localGatewayRouteTableVpcAssociationID string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
input := &ec2.DescribeLocalGatewayRouteTableVpcAssociationsInput{
LocalGatewayRouteTableVpcAssociationIds: aws.StringSlice([]string{localGatewayRouteTableVpcAssociationID}),
}

output, err := conn.DescribeLocalGatewayRouteTableVpcAssociations(input)

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

var association *ec2.LocalGatewayRouteTableVpcAssociation

for _, outputAssociation := range output.LocalGatewayRouteTableVpcAssociations {
if outputAssociation == nil {
continue
}

if aws.StringValue(outputAssociation.LocalGatewayRouteTableVpcAssociationId) == localGatewayRouteTableVpcAssociationID {
association = outputAssociation
break
}
}

if association == nil {
return association, ec2.RouteTableAssociationStateCodeDisassociated, nil
}

return association, aws.StringValue(association.State), nil
}
}
52 changes: 52 additions & 0 deletions aws/internal/service/ec2/waiter/waiter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package waiter

import (
"time"

"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
)

const (
// Maximum amount of time to wait for a LocalGatewayRouteTableVpcAssociation to return Associated
LocalGatewayRouteTableVpcAssociationAssociatedTimeout = 5 * time.Minute

// Maximum amount of time to wait for a LocalGatewayRouteTableVpcAssociation to return Disassociated
LocalGatewayRouteTableVpcAssociationDisassociatedTimeout = 5 * time.Minute
)

// LocalGatewayRouteTableVpcAssociationAssociated waits for a LocalGatewayRouteTableVpcAssociation to return Associated
func LocalGatewayRouteTableVpcAssociationAssociated(conn *ec2.EC2, localGatewayRouteTableVpcAssociationID string) (*ec2.LocalGatewayRouteTableVpcAssociation, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{ec2.RouteTableAssociationStateCodeAssociating},
Target: []string{ec2.RouteTableAssociationStateCodeAssociated},
Refresh: LocalGatewayRouteTableVpcAssociationState(conn, localGatewayRouteTableVpcAssociationID),
Timeout: LocalGatewayRouteTableVpcAssociationAssociatedTimeout,
}

outputRaw, err := stateConf.WaitForState()

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

return nil, err
}

// LocalGatewayRouteTableVpcAssociationDisassociated waits for a LocalGatewayRouteTableVpcAssociation to return Disassociated
func LocalGatewayRouteTableVpcAssociationDisassociated(conn *ec2.EC2, localGatewayRouteTableVpcAssociationID string) (*ec2.LocalGatewayRouteTableVpcAssociation, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{ec2.RouteTableAssociationStateCodeDisassociating},
Target: []string{ec2.RouteTableAssociationStateCodeDisassociated},
Refresh: LocalGatewayRouteTableVpcAssociationState(conn, localGatewayRouteTableVpcAssociationID),
Timeout: LocalGatewayRouteTableVpcAssociationAssociatedTimeout,
}

outputRaw, err := stateConf.WaitForState()

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

return nil, err
}
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,7 @@ func Provider() terraform.ResourceProvider {
"aws_ec2_capacity_reservation": resourceAwsEc2CapacityReservation(),
"aws_ec2_client_vpn_endpoint": resourceAwsEc2ClientVpnEndpoint(),
"aws_ec2_client_vpn_network_association": resourceAwsEc2ClientVpnNetworkAssociation(),
"aws_ec2_local_gateway_route_table_vpc_association": resourceAwsEc2LocalGatewayRouteTableVpcAssociation(),
"aws_ec2_fleet": resourceAwsEc2Fleet(),
"aws_ec2_tag": resourceAwsEc2Tag(),
"aws_ec2_traffic_mirror_filter": resourceAwsEc2TrafficMirrorFilter(),
Expand Down
174 changes: 174 additions & 0 deletions aws/resource_aws_ec2_local_gateway_route_table_vpc_association.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package aws

import (
"fmt"
"log"

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

const (
// Missing constant in AWS Go SDK
ec2ResourceTypeLocalGatewayRouteTableVpcAssociation = "local-gateway-route-table-vpc-association"
)

func resourceAwsEc2LocalGatewayRouteTableVpcAssociation() *schema.Resource {
return &schema.Resource{
Create: resourceAwsEc2LocalGatewayRouteTableVpcAssociationCreate,
Read: resourceAwsEc2LocalGatewayRouteTableVpcAssociationRead,
Update: resourceAwsEc2LocalGatewayRouteTableVpcAssociationUpdate,
Delete: resourceAwsEc2LocalGatewayRouteTableVpcAssociationDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"local_gateway_id": {
Type: schema.TypeString,
Computed: true,
},
"local_gateway_route_table_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"tags": tagsSchema(),
"vpc_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}

func resourceAwsEc2LocalGatewayRouteTableVpcAssociationCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn

req := &ec2.CreateLocalGatewayRouteTableVpcAssociationInput{
LocalGatewayRouteTableId: aws.String(d.Get("local_gateway_route_table_id").(string)),
TagSpecifications: ec2TagSpecificationsFromMap(d.Get("tags").(map[string]interface{}), ec2ResourceTypeLocalGatewayRouteTableVpcAssociation),
VpcId: aws.String(d.Get("vpc_id").(string)),
}

output, err := conn.CreateLocalGatewayRouteTableVpcAssociation(req)

if err != nil {
return fmt.Errorf("error creating EC2 Local Gateway Route Table VPC Association: %w", err)
}

d.SetId(aws.StringValue(output.LocalGatewayRouteTableVpcAssociation.LocalGatewayRouteTableVpcAssociationId))

if _, err := waiter.LocalGatewayRouteTableVpcAssociationAssociated(conn, d.Id()); err != nil {
return fmt.Errorf("error waiting for EC2 Local Gateway Route Table VPC Association (%s) to associate: %w", d.Id(), err)
}

return resourceAwsEc2LocalGatewayRouteTableVpcAssociationRead(d, meta)
}

func resourceAwsEc2LocalGatewayRouteTableVpcAssociationRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

association, err := getEc2LocalGatewayRouteTableVpcAssociation(conn, d.Id())

if err != nil {
return fmt.Errorf("error reading EC2 Local Gateway Route Table VPC Association (%s): %w", d.Id(), err)
}

if association == nil {
log.Printf("[WARN] EC2 Local Gateway Route Table VPC Association (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if aws.StringValue(association.State) != ec2.RouteTableAssociationStateCodeAssociated {
log.Printf("[WARN] EC2 Local Gateway Route Table VPC Association (%s) status (%s), removing from state", d.Id(), aws.StringValue(association.State))
d.SetId("")
return nil
}

d.Set("local_gateway_id", association.LocalGatewayId)
d.Set("local_gateway_route_table_id", association.LocalGatewayRouteTableId)

if err := d.Set("tags", keyvaluetags.Ec2KeyValueTags(association.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %s", err)
}

d.Set("vpc_id", association.VpcId)

return nil
}

func resourceAwsEc2LocalGatewayRouteTableVpcAssociationUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn

if d.HasChange("tags") {
o, n := d.GetChange("tags")

if err := keyvaluetags.Ec2UpdateTags(conn, d.Id(), o, n); err != nil {
return fmt.Errorf("error updating EC2 Local Gateway Route Table VPC Association (%s) tags: %w", d.Id(), err)
}
}

return resourceAwsEc2LocalGatewayRouteTableVpcAssociationRead(d, meta)
}

func resourceAwsEc2LocalGatewayRouteTableVpcAssociationDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn

input := &ec2.DeleteLocalGatewayRouteTableVpcAssociationInput{
LocalGatewayRouteTableVpcAssociationId: aws.String(d.Id()),
}

_, err := conn.DeleteLocalGatewayRouteTableVpcAssociation(input)

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

if err != nil {
return fmt.Errorf("error deleting EC2 Local Gateway Route Table VPC Association (%s): %w", d.Id(), err)
}

if _, err := waiter.LocalGatewayRouteTableVpcAssociationDisassociated(conn, d.Id()); err != nil {
return fmt.Errorf("error waiting for EC2 Local Gateway Route Table VPC Association (%s) to disassociate: %w", d.Id(), err)
}

return nil
}

func getEc2LocalGatewayRouteTableVpcAssociation(conn *ec2.EC2, localGatewayRouteTableVpcAssociationID string) (*ec2.LocalGatewayRouteTableVpcAssociation, error) {
input := &ec2.DescribeLocalGatewayRouteTableVpcAssociationsInput{
LocalGatewayRouteTableVpcAssociationIds: aws.StringSlice([]string{localGatewayRouteTableVpcAssociationID}),
}

output, err := conn.DescribeLocalGatewayRouteTableVpcAssociations(input)

if err != nil {
return nil, err
}

if output == nil {
return nil, fmt.Errorf("empty response")
}

var association *ec2.LocalGatewayRouteTableVpcAssociation

for _, outputAssociation := range output.LocalGatewayRouteTableVpcAssociations {
if outputAssociation == nil {
continue
}

if aws.StringValue(outputAssociation.LocalGatewayRouteTableVpcAssociationId) == localGatewayRouteTableVpcAssociationID {
association = outputAssociation
break
}
}

return association, nil
}
Loading

0 comments on commit 1f26314

Please sign in to comment.