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

New resource: aws_dx_transit_virtual_interface #8522

Merged
25 changes: 10 additions & 15 deletions aws/dx_vif.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
func dxVirtualInterfaceRead(id string, conn *directconnect.DirectConnect) (*directconnect.VirtualInterface, error) {
resp, state, err := dxVirtualInterfaceStateRefresh(conn, id)()
if err != nil {
return nil, fmt.Errorf("Error reading Direct Connect virtual interface: %s", err)
return nil, fmt.Errorf("error reading Direct Connect virtual interface (%s): %s", id, err)
}
if state == directconnect.VirtualInterfaceStateDeleted {
return nil, nil
Expand All @@ -26,26 +26,21 @@ func dxVirtualInterfaceRead(id string, conn *directconnect.DirectConnect) (*dire
func dxVirtualInterfaceUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).dxconn

req := &directconnect.UpdateVirtualInterfaceAttributesInput{
VirtualInterfaceId: aws.String(d.Id()),
}

requestUpdate := false
if d.HasChange("mtu") {
req.Mtu = aws.Int64(int64(d.Get("mtu").(int)))
requestUpdate = true
}
req := &directconnect.UpdateVirtualInterfaceAttributesInput{
Mtu: aws.Int64(int64(d.Get("mtu").(int))),
VirtualInterfaceId: aws.String(d.Id()),
}

if requestUpdate {
log.Printf("[DEBUG] Modifying Direct Connect virtual interface attributes: %#v", req)
_, err := conn.UpdateVirtualInterfaceAttributes(req)
if err != nil {
return fmt.Errorf("Error modifying Direct Connect virtual interface (%s) attributes, error: %s", d.Id(), err)
return fmt.Errorf("error modifying Direct Connect virtual interface (%s) attributes, error: %s", d.Id(), err)
}
}

if err := setTagsDX(conn, d, d.Get("arn").(string)); err != nil {
return err
return fmt.Errorf("error setting Direct Connect virtual interface (%s) tags: %s", d.Id(), err)
}

return nil
Expand All @@ -62,7 +57,7 @@ func dxVirtualInterfaceDelete(d *schema.ResourceData, meta interface{}) error {
if isAWSErr(err, directconnect.ErrCodeClientException, "does not exist") {
return nil
}
return fmt.Errorf("Error deleting Direct Connect virtual interface: %s", err)
return fmt.Errorf("error deleting Direct Connect virtual interface (%s): %s", d.Id(), err)
}

deleteStateConf := &resource.StateChangeConf{
Expand All @@ -85,7 +80,7 @@ func dxVirtualInterfaceDelete(d *schema.ResourceData, meta interface{}) error {
}
_, err = deleteStateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for Direct Connect virtual interface (%s) to be deleted: %s", d.Id(), err)
return fmt.Errorf("error waiting for Direct Connect virtual interface (%s) to be deleted: %s", d.Id(), err)
}

return nil
Expand Down Expand Up @@ -125,7 +120,7 @@ func dxVirtualInterfaceWaitUntilAvailable(conn *directconnect.DirectConnect, vif
MinTimeout: 5 * time.Second,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for Direct Connect virtual interface (%s) to become available: %s", vifId, err)
return fmt.Errorf("error waiting for Direct Connect virtual interface (%s) to become available: %s", vifId, err)
}

return nil
Expand Down
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ func Provider() terraform.ResourceProvider {
"aws_dx_lag": resourceAwsDxLag(),
"aws_dx_private_virtual_interface": resourceAwsDxPrivateVirtualInterface(),
"aws_dx_public_virtual_interface": resourceAwsDxPublicVirtualInterface(),
"aws_dx_transit_virtual_interface": resourceAwsDxTransitVirtualInterface(),
"aws_dynamodb_table": resourceAwsDynamoDbTable(),
"aws_dynamodb_table_item": resourceAwsDynamoDbTableItem(),
"aws_dynamodb_global_table": resourceAwsDynamoDbGlobalTable(),
Expand Down
228 changes: 228 additions & 0 deletions aws/resource_aws_dx_transit_virtual_interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
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/schema"
"github.com/hashicorp/terraform/helper/validation"
)

func resourceAwsDxTransitVirtualInterface() *schema.Resource {
return &schema.Resource{
Create: resourceAwsDxTransitVirtualInterfaceCreate,
Read: resourceAwsDxTransitVirtualInterfaceRead,
Update: resourceAwsDxTransitVirtualInterfaceUpdate,
Delete: resourceAwsDxTransitVirtualInterfaceDelete,
Importer: &schema.ResourceImporter{
State: resourceAwsDxTransitVirtualInterfaceImport,
},

Schema: map[string]*schema.Schema{
"address_family": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
directconnect.AddressFamilyIpv4,
directconnect.AddressFamilyIpv6,
}, false),
},
"amazon_address": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"arn": {
Type: schema.TypeString,
Computed: true,
},
"aws_device": {
Type: schema.TypeString,
Computed: true,
},
"bgp_asn": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
},
"bgp_auth_key": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"connection_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"customer_address": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"dx_gateway_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"jumbo_frame_capable": {
Type: schema.TypeBool,
Computed: true,
},
"mtu": {
Type: schema.TypeInt,
Default: 1500,
Optional: true,
ValidateFunc: validation.IntInSlice([]int{1500, 8500}),
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"tags": tagsSchema(),
"vlan": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
ValidateFunc: validation.IntBetween(1, 4094),
},
},

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

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

req := &directconnect.CreateTransitVirtualInterfaceInput{
ConnectionId: aws.String(d.Get("connection_id").(string)),
NewTransitVirtualInterface: &directconnect.NewTransitVirtualInterface{
AddressFamily: aws.String(d.Get("address_family").(string)),
Asn: aws.Int64(int64(d.Get("bgp_asn").(int))),
DirectConnectGatewayId: aws.String(d.Get("dx_gateway_id").(string)),
Mtu: aws.Int64(int64(d.Get("mtu").(int))),
VirtualInterfaceName: aws.String(d.Get("name").(string)),
Vlan: aws.Int64(int64(d.Get("vlan").(int))),
},
}
if v, ok := d.GetOk("amazon_address"); ok && v.(string) != "" {
req.NewTransitVirtualInterface.AmazonAddress = aws.String(v.(string))
}
if v, ok := d.GetOk("bgp_auth_key"); ok {
req.NewTransitVirtualInterface.AuthKey = aws.String(v.(string))
}
if v, ok := d.GetOk("customer_address"); ok && v.(string) != "" {
req.NewTransitVirtualInterface.CustomerAddress = aws.String(v.(string))
}

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

d.SetId(aws.StringValue(resp.VirtualInterface.VirtualInterfaceId))
arn := arn.ARN{
Partition: meta.(*AWSClient).partition,
Region: meta.(*AWSClient).region,
Service: "directconnect",
AccountID: meta.(*AWSClient).accountid,
Resource: fmt.Sprintf("dxvif/%s", d.Id()),
}.String()
d.Set("arn", arn)

if err := dxTransitVirtualInterfaceWaitUntilAvailable(conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil {
return err
}

return resourceAwsDxTransitVirtualInterfaceUpdate(d, meta)
Copy link
Contributor

Choose a reason for hiding this comment

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

Since CreateTransitVirtualInterface can support tag-on-create and already handles MTU appropriately above, we should prefer to call Read after Create.

Suggested change
return resourceAwsDxTransitVirtualInterfaceUpdate(d, meta)
return resourceAwsDxTransitVirtualInterfaceRead(d, meta)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do.

}

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

vif, err := dxVirtualInterfaceRead(d.Id(), conn)
if err != nil {
return err
}
if vif == nil {
log.Printf("[WARN] Direct Connect transit virtual interface (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

d.Set("address_family", vif.AddressFamily)
d.Set("amazon_address", vif.AmazonAddress)
d.Set("aws_device", vif.AwsDeviceV2)
d.Set("bgp_asn", vif.Asn)
d.Set("bgp_auth_key", vif.AuthKey)
d.Set("connection_id", vif.ConnectionId)
d.Set("customer_address", vif.CustomerAddress)
d.Set("dx_gateway_id", vif.DirectConnectGatewayId)
d.Set("jumbo_frame_capable", vif.JumboFrameCapable)
d.Set("mtu", vif.Mtu)
d.Set("name", vif.VirtualInterfaceName)
d.Set("vlan", vif.Vlan)
if err := getTagsDX(conn, d, d.Get("arn").(string)); err != nil {
return fmt.Errorf("error getting Direct Connect transit virtual interface (%s) tags: %s", d.Id(), err)
}

return nil
}

func resourceAwsDxTransitVirtualInterfaceUpdate(d *schema.ResourceData, meta interface{}) error {
if err := dxVirtualInterfaceUpdate(d, meta); err != nil {
return err
}

if err := dxTransitVirtualInterfaceWaitUntilAvailable(meta.(*AWSClient).dxconn, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil {
return err
}

return resourceAwsDxTransitVirtualInterfaceRead(d, meta)
}

func resourceAwsDxTransitVirtualInterfaceDelete(d *schema.ResourceData, meta interface{}) error {
return dxVirtualInterfaceDelete(d, meta)
}

func resourceAwsDxTransitVirtualInterfaceImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
arn := arn.ARN{
Partition: meta.(*AWSClient).partition,
Region: meta.(*AWSClient).region,
Service: "directconnect",
AccountID: meta.(*AWSClient).accountid,
Resource: fmt.Sprintf("dxvif/%s", d.Id()),
}.String()
d.Set("arn", arn)

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

func dxTransitVirtualInterfaceWaitUntilAvailable(conn *directconnect.DirectConnect, vifId string, timeout time.Duration) error {
return dxVirtualInterfaceWaitUntilAvailable(
conn,
vifId,
timeout,
[]string{
directconnect.VirtualInterfaceStatePending,
},
[]string{
directconnect.VirtualInterfaceStateAvailable,
directconnect.VirtualInterfaceStateDown,
})
}
Loading