Skip to content

Commit

Permalink
Add support for tagging aws_dx_lag and aws_dx_connection resources (#…
Browse files Browse the repository at this point in the history
…2990)

* Add support for tagging aws_dx_lag and aws_dx_connection resources.

* Fix indentation for configuration generation.

* Remove Direct Connect connection from state only if it's in 'Deleted' state.

* Do not remove LAG if it's in Deleting state
  • Loading branch information
ewbankkit authored and radeksimko committed Feb 13, 2018
1 parent c231d4c commit 1787b2b
Show file tree
Hide file tree
Showing 8 changed files with 596 additions and 74 deletions.
107 changes: 87 additions & 20 deletions aws/resource_aws_dx_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package aws

import (
"fmt"
"log"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/service/directconnect"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
Expand All @@ -14,79 +16,137 @@ func resourceAwsDxConnection() *schema.Resource {
return &schema.Resource{
Create: resourceAwsDxConnectionCreate,
Read: resourceAwsDxConnectionRead,
Update: resourceAwsDxConnectionUpdate,
Delete: resourceAwsDxConnectionDelete,

Schema: map[string]*schema.Schema{
"name": &schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"bandwidth": &schema.Schema{
"bandwidth": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateDxConnectionBandWidth,
},
"location": &schema.Schema{
"location": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"tags": tagsSchema(),
},
}
}

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

input := &directconnect.CreateConnectionInput{
req := &directconnect.CreateConnectionInput{
Bandwidth: aws.String(d.Get("bandwidth").(string)),
ConnectionName: aws.String(d.Get("name").(string)),
Location: aws.String(d.Get("location").(string)),
}
resp, err := conn.CreateConnection(input)

log.Printf("[DEBUG] Creating Direct Connect connection: %#v", req)
resp, err := conn.CreateConnection(req)
if err != nil {
return err
}
d.SetId(*resp.ConnectionId)
return resourceAwsDxConnectionRead(d, meta)

d.SetId(aws.StringValue(resp.ConnectionId))
return resourceAwsDxConnectionUpdate(d, meta)
}

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

connectionId := d.Id()
input := &directconnect.DescribeConnectionsInput{
ConnectionId: aws.String(connectionId),
}
resp, err := conn.DescribeConnections(input)
resp, err := conn.DescribeConnections(&directconnect.DescribeConnectionsInput{
ConnectionId: aws.String(d.Id()),
})
if err != nil {
if isNoSuchDxConnectionErr(err) {
log.Printf("[WARN] Direct Connect connection (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}
return err
}

if len(resp.Connections) < 1 {
log.Printf("[WARN] Direct Connect connection (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}
if len(resp.Connections) != 1 {
return fmt.Errorf("[ERROR] Number of DX Connection (%s) isn't one, got %d", connectionId, len(resp.Connections))
return fmt.Errorf("[ERROR] Number of Direct Connect connections (%s) isn't one, got %d", d.Id(), len(resp.Connections))
}
connection := resp.Connections[0]
if d.Id() != aws.StringValue(connection.ConnectionId) {
return fmt.Errorf("[ERROR] Direct Connect connection (%s) not found", d.Id())
}
if aws.StringValue(connection.ConnectionState) == directconnect.ConnectionStateDeleted {
log.Printf("[WARN] Direct Connect connection (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}
if d.Id() != *resp.Connections[0].ConnectionId {
return fmt.Errorf("[ERROR] DX Connection (%s) not found", connectionId)

arn := arn.ARN{
Partition: meta.(*AWSClient).partition,
Region: meta.(*AWSClient).region,
Service: "directconnect",
AccountID: meta.(*AWSClient).accountid,
Resource: fmt.Sprintf("dxcon/%s", d.Id()),
}.String()
d.Set("arn", arn)
d.Set("name", connection.ConnectionName)
d.Set("bandwidth", connection.Bandwidth)
d.Set("location", connection.Location)

if err := getTagsDX(conn, d, arn); err != nil {
return err
}

return nil
}

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

arn := arn.ARN{
Partition: meta.(*AWSClient).partition,
Region: meta.(*AWSClient).region,
Service: "directconnect",
AccountID: meta.(*AWSClient).accountid,
Resource: fmt.Sprintf("dxcon/%s", d.Id()),
}.String()
if err := setTagsDX(conn, d, arn); err != nil {
return err
}

return resourceAwsDxConnectionRead(d, meta)
}

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

input := &directconnect.DeleteConnectionInput{
log.Printf("[DEBUG] Deleting Direct Connect connection: %s", d.Id())
_, err := conn.DeleteConnection(&directconnect.DeleteConnectionInput{
ConnectionId: aws.String(d.Id()),
}
_, err := conn.DeleteConnection(input)
})
if err != nil {
if isNoSuchDxConnectionErr(err) {
return nil
}
return err
}

deleteStateConf := &resource.StateChangeConf{
Pending: []string{directconnect.ConnectionStatePending, directconnect.ConnectionStateOrdering, directconnect.ConnectionStateAvailable, directconnect.ConnectionStateRequested, directconnect.ConnectionStateDeleting},
Target: []string{directconnect.ConnectionStateDeleted},
Expand All @@ -97,9 +157,9 @@ func resourceAwsDxConnectionDelete(d *schema.ResourceData, meta interface{}) err
}
_, err = deleteStateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for Dx Connection (%s) to be deleted: %s", d.Id(), err)
return fmt.Errorf("Error waiting for Direct Connect connection (%s) to be deleted: %s", d.Id(), err)
}
d.SetId("")

return nil
}

Expand All @@ -112,6 +172,13 @@ func dxConnectionRefreshStateFunc(conn *directconnect.DirectConnect, connId stri
if err != nil {
return nil, "failed", err
}
if len(resp.Connections) < 1 {
return resp, directconnect.ConnectionStateDeleted, nil
}
return resp, *resp.Connections[0].ConnectionState, nil
}
}

func isNoSuchDxConnectionErr(err error) bool {
return isAWSErr(err, "DirectConnectClientException", "Could not find Connection with ID")
}
81 changes: 73 additions & 8 deletions aws/resource_aws_dx_connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,51 @@ import (
)

func TestAccAwsDxConnection_basic(t *testing.T) {
connectionName := fmt.Sprintf("tf-dx-%s", acctest.RandString(5))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAwsDxConnectionDestroy,
Steps: []resource.TestStep{
{
Config: testAccDxConnectionConfig(connectionName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsDxConnectionExists("aws_dx_connection.hoge"),
resource.TestCheckResourceAttr("aws_dx_connection.hoge", "name", connectionName),
resource.TestCheckResourceAttr("aws_dx_connection.hoge", "bandwidth", "1Gbps"),
resource.TestCheckResourceAttr("aws_dx_connection.hoge", "location", "EqSe2"),
resource.TestCheckResourceAttr("aws_dx_connection.hoge", "tags.%", "0"),
),
},
},
})
}

func TestAccAwsDxConnection_tags(t *testing.T) {
connectionName := fmt.Sprintf("tf-dx-%s", acctest.RandString(5))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAwsDxConnectionDestroy,
Steps: []resource.TestStep{
{
Config: testAccDxConnectionConfig(acctest.RandString(5)),
Config: testAccDxConnectionConfig_tags(connectionName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsDxConnectionExists("aws_dx_connection.hoge"),
resource.TestCheckResourceAttr("aws_dx_connection.hoge", "name", connectionName),
resource.TestCheckResourceAttr("aws_dx_connection.hoge", "tags.%", "2"),
resource.TestCheckResourceAttr("aws_dx_connection.hoge", "tags.Usage", "original"),
),
},
{
Config: testAccDxConnectionConfig_tagsChanged(connectionName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsDxConnectionExists("aws_dx_connection.hoge"),
resource.TestCheckResourceAttr("aws_dx_connection.hoge", "name", connectionName),
resource.TestCheckResourceAttr("aws_dx_connection.hoge", "tags.%", "1"),
resource.TestCheckResourceAttr("aws_dx_connection.hoge", "tags.Usage", "changed"),
),
},
},
Expand Down Expand Up @@ -63,12 +99,41 @@ func testAccCheckAwsDxConnectionExists(name string) resource.TestCheckFunc {
}
}

func testAccDxConnectionConfig(rName string) string {
func testAccDxConnectionConfig(n string) string {
return fmt.Sprintf(`
resource "aws_dx_connection" "hoge" {
name = "%s"
bandwidth = "1Gbps"
location = "EqSe2"
}
`, n)
}

func testAccDxConnectionConfig_tags(n string) string {
return fmt.Sprintf(`
resource "aws_dx_connection" "hoge" {
name = "%s"
bandwidth = "1Gbps"
location = "EqSe2"
tags {
Environment = "production"
Usage = "original"
}
}
`, n)
}

func testAccDxConnectionConfig_tagsChanged(n string) string {
return fmt.Sprintf(`
resource "aws_dx_connection" "hoge" {
name = "tf-dx-%s"
bandwidth = "1Gbps"
location = "EqSe2"
}
`, rName)
resource "aws_dx_connection" "hoge" {
name = "%s"
bandwidth = "1Gbps"
location = "EqSe2"
tags {
Usage = "changed"
}
}
`, n)
}
Loading

0 comments on commit 1787b2b

Please sign in to comment.