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

Add support for Direct Connect Gateway #4896

Merged
merged 10 commits into from
Jun 21, 2018
48 changes: 48 additions & 0 deletions aws/import_aws_dx_gateway.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package aws

import (
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/directconnect"
"github.com/hashicorp/terraform/helper/schema"
)

// Direct Connect Gateway import also imports all assocations
func resourceAwsDxGatewayImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
conn := meta.(*AWSClient).dxconn

id := d.Id()
resp, err := conn.DescribeDirectConnectGateways(&directconnect.DescribeDirectConnectGatewaysInput{
DirectConnectGatewayId: aws.String(id),
})
if err != nil {
return nil, err
}
if len(resp.DirectConnectGateways) < 1 || resp.DirectConnectGateways[0] == nil {
return nil, fmt.Errorf("Direct Connect Gateway %s was not found", id)
}
results := make([]*schema.ResourceData, 1)
results[0] = d

{
subResource := resourceAwsDxGatewayAssociation()
resp, err := conn.DescribeDirectConnectGatewayAssociations(&directconnect.DescribeDirectConnectGatewayAssociationsInput{
DirectConnectGatewayId: aws.String(id),
})
if err != nil {
return nil, err
}

for _, assoc := range resp.DirectConnectGatewayAssociations {
d := subResource.Data(nil)
d.SetType("aws_dx_gateway_association")
d.Set("dx_gateway_id", assoc.DirectConnectGatewayId)
d.Set("vpn_gateway_id", assoc.VirtualGatewayId)
d.SetId(dxGatewayAssociationId(aws.StringValue(assoc.DirectConnectGatewayId), aws.StringValue(assoc.VirtualGatewayId)))
results = append(results, d)
}
}

return results, nil
}
58 changes: 58 additions & 0 deletions aws/import_aws_dx_gateway_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package aws

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccAwsDxGateway_importBasic(t *testing.T) {
resourceName := "aws_dx_gateway.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAwsDxGatewayDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccDxGatewayConfig(acctest.RandString(5), randIntRange(64512, 65534)),
},

resource.TestStep{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAwsDxGateway_importComplex(t *testing.T) {
checkFn := func(s []*terraform.InstanceState) error {
if len(s) != 3 {
return fmt.Errorf("Got %d resources, expected 3. State: %#v", len(s), s)
}
return nil
}

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAwsDxGatewayDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccDxGatewayAssociationConfig_multiVgws(acctest.RandString(5), randIntRange(64512, 65534)),
},

resource.TestStep{
ResourceName: "aws_dx_gateway.test",
ImportState: true,
ImportStateCheck: checkFn,
ImportStateVerify: true,
},
},
})
}
2 changes: 2 additions & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,8 @@ func Provider() terraform.ResourceProvider {
"aws_dx_lag": resourceAwsDxLag(),
"aws_dx_connection": resourceAwsDxConnection(),
"aws_dx_connection_association": resourceAwsDxConnectionAssociation(),
"aws_dx_gateway": resourceAwsDxGateway(),
"aws_dx_gateway_association": resourceAwsDxGatewayAssociation(),
"aws_dynamodb_table": resourceAwsDynamoDbTable(),
"aws_dynamodb_table_item": resourceAwsDynamoDbTableItem(),
"aws_dynamodb_global_table": resourceAwsDynamoDbGlobalTable(),
Expand Down
154 changes: 154 additions & 0 deletions aws/resource_aws_dx_gateway.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package aws

import (
"fmt"
"log"
"strconv"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/directconnect"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsDxGateway() *schema.Resource {
return &schema.Resource{
Create: resourceAwsDxGatewayCreate,
Read: resourceAwsDxGatewayRead,
Delete: resourceAwsDxGatewayDelete,
Importer: &schema.ResourceImporter{
State: resourceAwsDxGatewayImportState,
},

Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"amazon_side_asn": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateAmazonSideAsn,
},
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(10 * time.Minute),
Delete: schema.DefaultTimeout(10 * time.Minute),
},
}
}

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

req := &directconnect.CreateDirectConnectGatewayInput{
DirectConnectGatewayName: aws.String(d.Get("name").(string)),
}
if asn, ok := d.GetOk("amazon_side_asn"); ok {
i, err := strconv.ParseInt(asn.(string), 10, 64)
if err != nil {
return err
}
req.AmazonSideAsn = aws.Int64(i)
}

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

d.SetId(aws.StringValue(resp.DirectConnectGateway.DirectConnectGatewayId))

stateConf := &resource.StateChangeConf{
Pending: []string{directconnect.GatewayStatePending},
Target: []string{directconnect.GatewayStateAvailable},
Refresh: dxGatewayStateRefresh(conn, d.Id()),
Timeout: d.Timeout(schema.TimeoutCreate),
Delay: 10 * time.Second,
MinTimeout: 5 * time.Second,
}
_, err = stateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for Direct Connect gateway (%s) to become available: %s", d.Id(), err)
}

return resourceAwsDxGatewayRead(d, meta)
}

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

dxGwRaw, state, err := dxGatewayStateRefresh(conn, d.Id())()
if err != nil {
return fmt.Errorf("Error reading Direct Connect gateway: %s", err)
}
if state == directconnect.GatewayStateDeleted {
log.Printf("[WARN] Direct Connect gateway (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

dxGw := dxGwRaw.(*directconnect.Gateway)
d.Set("name", aws.StringValue(dxGw.DirectConnectGatewayName))
d.Set("amazon_side_asn", strconv.FormatInt(aws.Int64Value(dxGw.AmazonSideAsn), 10))

return nil
}

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

_, err := conn.DeleteDirectConnectGateway(&directconnect.DeleteDirectConnectGatewayInput{
DirectConnectGatewayId: aws.String(d.Id()),
})
if err != nil {
if isAWSErr(err, "DirectConnectClientException", "does not exist") {
return nil
}
return fmt.Errorf("Error deleting Direct Connect gateway: %s", err)
}

stateConf := &resource.StateChangeConf{
Pending: []string{directconnect.GatewayStatePending, directconnect.GatewayStateAvailable, directconnect.GatewayStateDeleting},
Target: []string{directconnect.GatewayStateDeleted},
Refresh: dxGatewayStateRefresh(conn, d.Id()),
Timeout: d.Timeout(schema.TimeoutDelete),
Delay: 10 * time.Second,
MinTimeout: 5 * time.Second,
}
_, err = stateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for Direct Connect gateway (%s) to be deleted: %s", d.Id(), err)
}

return nil
}

func dxGatewayStateRefresh(conn *directconnect.DirectConnect, dxgwId string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
resp, err := conn.DescribeDirectConnectGateways(&directconnect.DescribeDirectConnectGatewaysInput{
DirectConnectGatewayId: aws.String(dxgwId),
})
if err != nil {
return nil, "", err
}

n := len(resp.DirectConnectGateways)
switch n {
case 0:
return "", directconnect.GatewayStateDeleted, nil

case 1:
dxgw := resp.DirectConnectGateways[0]
return dxgw, aws.StringValue(dxgw.DirectConnectGatewayState), nil

default:
return nil, "", fmt.Errorf("Found %d Direct Connect gateways for %s, expected 1", n, dxgwId)
}
}
}
Loading