Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…rovider-aws into ewbankkit-issue-8199
  • Loading branch information
bflad committed Apr 24, 2019
2 parents 96ccb80 + c1021a3 commit eeddb00
Show file tree
Hide file tree
Showing 8 changed files with 344 additions and 57 deletions.
123 changes: 105 additions & 18 deletions aws/resource_aws_dx_gateway_association.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package aws
import (
"fmt"
"log"
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
Expand All @@ -12,31 +13,49 @@ import (
)

const (
GatewayAssociationStateDeleted = "deleted"
gatewayAssociationStateDeleted = "deleted"
)

func resourceAwsDxGatewayAssociation() *schema.Resource {
return &schema.Resource{
Create: resourceAwsDxGatewayAssociationCreate,
Read: resourceAwsDxGatewayAssociationRead,
Update: resourceAwsDxGatewayAssociationUpdate,
Delete: resourceAwsDxGatewayAssociationDelete,
Importer: &schema.ResourceImporter{
State: resourceAwsDxGatewayAssociationImport,
},

Schema: map[string]*schema.Schema{
"allowed_prefixes": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},

"dx_gateway_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"vpn_gateway_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"dx_gateway_association_id": {
Type: schema.TypeString,
Computed: true,
},
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(15 * time.Minute),
Delete: schema.DefaultTimeout(10 * time.Minute),
Update: schema.DefaultTimeout(10 * time.Minute),
Delete: schema.DefaultTimeout(15 * time.Minute),
},
}
}
Expand All @@ -47,14 +66,15 @@ func resourceAwsDxGatewayAssociationCreate(d *schema.ResourceData, meta interfac
dxgwId := d.Get("dx_gateway_id").(string)
vgwId := d.Get("vpn_gateway_id").(string)
req := &directconnect.CreateDirectConnectGatewayAssociationInput{
DirectConnectGatewayId: aws.String(dxgwId),
VirtualGatewayId: aws.String(vgwId),
AddAllowedPrefixesToDirectConnectGateway: expandDxRouteFilterPrefixes(d.Get("allowed_prefixes").(*schema.Set)),
DirectConnectGatewayId: aws.String(dxgwId),
VirtualGatewayId: aws.String(vgwId),
}

log.Printf("[DEBUG] Creating Direct Connect gateway association: %#v", req)
_, err := conn.CreateDirectConnectGatewayAssociation(req)
if err != nil {
return fmt.Errorf("Error creating Direct Connect gateway association: %s", err)
return fmt.Errorf("error creating Direct Connect gateway association: %s", err)
}

d.SetId(dxGatewayAssociationId(dxgwId, vgwId))
Expand All @@ -69,56 +89,123 @@ func resourceAwsDxGatewayAssociationCreate(d *schema.ResourceData, meta interfac
}
_, err = stateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for Direct Connect gateway association (%s) to become available: %s", d.Id(), err)
return fmt.Errorf("error waiting for Direct Connect gateway association (%s) to become available: %s", d.Id(), err)
}

return nil
return resourceAwsDxGatewayAssociationRead(d, meta)
}

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

dxgwId := d.Get("dx_gateway_id").(string)
vgwId := d.Get("vpn_gateway_id").(string)
_, state, err := dxGatewayAssociationStateRefresh(conn, dxgwId, vgwId)()
assocRaw, state, err := dxGatewayAssociationStateRefresh(conn, dxgwId, vgwId)()
if err != nil {
return fmt.Errorf("Error reading Direct Connect gateway association: %s", err)
return fmt.Errorf("error reading Direct Connect gateway association: %s", err)
}
if state == GatewayAssociationStateDeleted {
if state == gatewayAssociationStateDeleted {
log.Printf("[WARN] Direct Connect gateway association (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

assoc := assocRaw.(*directconnect.GatewayAssociation)
d.Set("dx_gateway_id", assoc.DirectConnectGatewayId)
d.Set("vpn_gateway_id", assoc.VirtualGatewayId)
d.Set("dx_gateway_association_id", assoc.AssociationId)
err = d.Set("allowed_prefixes", flattenDxRouteFilterPrefixes(assoc.AllowedPrefixesToDirectConnectGateway))
if err != nil {
return fmt.Errorf("error setting allowed_prefixes: %s", err)
}

return nil
}

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

dxgwId := d.Get("dx_gateway_id").(string)
vgwId := d.Get("vpn_gateway_id").(string)

if d.HasChange("allowed_prefixes") {
oraw, nraw := d.GetChange("allowed_prefixes")
o := oraw.(*schema.Set)
n := nraw.(*schema.Set)
del := o.Difference(n)
add := n.Difference(o)

req := &directconnect.UpdateDirectConnectGatewayAssociationInput{
AddAllowedPrefixesToDirectConnectGateway: expandDxRouteFilterPrefixes(add),
AssociationId: aws.String(d.Get("dx_gateway_association_id").(string)),
RemoveAllowedPrefixesToDirectConnectGateway: expandDxRouteFilterPrefixes(del),
}

log.Printf("[DEBUG] Direct Connect gateway association: %#v", req)
_, err := conn.UpdateDirectConnectGatewayAssociation(req)
if err != nil {
return fmt.Errorf("error updating Direct Connect gateway association (%s): %s", d.Id(), err)
}

stateConf := &resource.StateChangeConf{
Pending: []string{directconnect.GatewayAssociationStateUpdating},
Target: []string{directconnect.GatewayAssociationStateAssociated},
Refresh: dxGatewayAssociationStateRefresh(conn, dxgwId, vgwId),
Timeout: d.Timeout(schema.TimeoutUpdate),
Delay: 10 * time.Second,
MinTimeout: 5 * time.Second,
}
_, err = stateConf.WaitForState()
if err != nil {
return fmt.Errorf("error waiting for Direct Connect gateway association (%s) to become available: %s", d.Id(), err)
}
}

return resourceAwsDxGatewayAssociationRead(d, meta)
}

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

dxgwId := d.Get("dx_gateway_id").(string)
vgwId := d.Get("vpn_gateway_id").(string)

log.Printf("[DEBUG] Deleting Direct Connect gateway association: %s", d.Id())

_, err := conn.DeleteDirectConnectGatewayAssociation(&directconnect.DeleteDirectConnectGatewayAssociationInput{
DirectConnectGatewayId: aws.String(dxgwId),
VirtualGatewayId: aws.String(vgwId),
})
if isAWSErr(err, directconnect.ErrCodeClientException, "No association exists") {
return nil
}
if err != nil {
if isAWSErr(err, "DirectConnectClientException", "No association exists") {
return nil
}
return fmt.Errorf("Error deleting Direct Connect gateway association: %s", err)
return fmt.Errorf("error deleting Direct Connect gateway association: %s", err)
}

if err := waitForDirectConnectGatewayAssociationDeletion(conn, dxgwId, vgwId, d.Timeout(schema.TimeoutDelete)); err != nil {
return fmt.Errorf("Error waiting for Direct Connect gateway association (%s) to be deleted: %s", d.Id(), err.Error())
return fmt.Errorf("error waiting for Direct Connect gateway association (%s) to be deleted: %s", d.Id(), err.Error())
}

return nil
}

func resourceAwsDxGatewayAssociationImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
parts := strings.Split(d.Id(), "/")
if len(parts) != 2 {
return []*schema.ResourceData{}, fmt.Errorf("Wrong format of resource: %s. Please follow 'dx-gw-id/vgw-id'", d.Id())
}

dxgwId := parts[0]
vgwId := parts[1]
log.Printf("[DEBUG] Importing Direct Connect gateway association %s/%s", dxgwId, vgwId)

d.SetId(dxGatewayAssociationId(dxgwId, vgwId))
d.Set("dx_gateway_id", dxgwId)
d.Set("vpn_gateway_id", vgwId)

return []*schema.ResourceData{d}, nil
}

func dxGatewayAssociationStateRefresh(conn *directconnect.DirectConnect, dxgwId, vgwId string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
resp, err := conn.DescribeDirectConnectGatewayAssociations(&directconnect.DescribeDirectConnectGatewayAssociationsInput{
Expand All @@ -132,7 +219,7 @@ func dxGatewayAssociationStateRefresh(conn *directconnect.DirectConnect, dxgwId,
n := len(resp.DirectConnectGatewayAssociations)
switch n {
case 0:
return "", GatewayAssociationStateDeleted, nil
return "", gatewayAssociationStateDeleted, nil

case 1:
assoc := resp.DirectConnectGatewayAssociations[0]
Expand All @@ -151,7 +238,7 @@ func dxGatewayAssociationId(dxgwId, vgwId string) string {
func waitForDirectConnectGatewayAssociationDeletion(conn *directconnect.DirectConnect, directConnectGatewayID, virtualGatewayID string, timeout time.Duration) error {
stateConf := &resource.StateChangeConf{
Pending: []string{directconnect.GatewayAssociationStateDisassociating},
Target: []string{directconnect.GatewayAssociationStateDisassociated, GatewayAssociationStateDeleted},
Target: []string{directconnect.GatewayAssociationStateDisassociated, gatewayAssociationStateDeleted},
Refresh: dxGatewayAssociationStateRefresh(conn, directConnectGatewayID, virtualGatewayID),
Timeout: timeout,
Delay: 10 * time.Second,
Expand Down
Loading

0 comments on commit eeddb00

Please sign in to comment.