-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3253 from ewbankkit/issue-3249
New Resource: aws_dx_private_virtual_interface
- Loading branch information
Showing
8 changed files
with
604 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"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 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) | ||
} | ||
if state == directconnect.VirtualInterfaceStateDeleted { | ||
return nil, nil | ||
} | ||
|
||
return resp.(*directconnect.VirtualInterface), nil | ||
} | ||
|
||
func dxVirtualInterfaceUpdate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).dxconn | ||
|
||
if err := setTagsDX(conn, d, d.Get("arn").(string)); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func dxVirtualInterfaceDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).dxconn | ||
|
||
log.Printf("[DEBUG] Deleting Direct Connect virtual interface: %s", d.Id()) | ||
_, err := conn.DeleteVirtualInterface(&directconnect.DeleteVirtualInterfaceInput{ | ||
VirtualInterfaceId: aws.String(d.Id()), | ||
}) | ||
if err != nil { | ||
if isAWSErr(err, directconnect.ErrCodeClientException, "does not exist") { | ||
return nil | ||
} | ||
return fmt.Errorf("Error deleting Direct Connect virtual interface: %s", err) | ||
} | ||
|
||
deleteStateConf := &resource.StateChangeConf{ | ||
Pending: []string{ | ||
directconnect.VirtualInterfaceStateAvailable, | ||
directconnect.VirtualInterfaceStateConfirming, | ||
directconnect.VirtualInterfaceStateDeleting, | ||
directconnect.VirtualInterfaceStateDown, | ||
directconnect.VirtualInterfaceStatePending, | ||
directconnect.VirtualInterfaceStateRejected, | ||
directconnect.VirtualInterfaceStateVerifying, | ||
}, | ||
Target: []string{ | ||
directconnect.VirtualInterfaceStateDeleted, | ||
}, | ||
Refresh: dxVirtualInterfaceStateRefresh(conn, d.Id()), | ||
Timeout: d.Timeout(schema.TimeoutDelete), | ||
Delay: 10 * time.Second, | ||
MinTimeout: 5 * time.Second, | ||
} | ||
_, 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 nil | ||
} | ||
|
||
func dxVirtualInterfaceStateRefresh(conn *directconnect.DirectConnect, vifId string) resource.StateRefreshFunc { | ||
return func() (interface{}, string, error) { | ||
resp, err := conn.DescribeVirtualInterfaces(&directconnect.DescribeVirtualInterfacesInput{ | ||
VirtualInterfaceId: aws.String(vifId), | ||
}) | ||
if err != nil { | ||
return nil, "", err | ||
} | ||
|
||
n := len(resp.VirtualInterfaces) | ||
switch n { | ||
case 0: | ||
return "", directconnect.VirtualInterfaceStateDeleted, nil | ||
|
||
case 1: | ||
vif := resp.VirtualInterfaces[0] | ||
return vif, aws.StringValue(vif.VirtualInterfaceState), nil | ||
|
||
default: | ||
return nil, "", fmt.Errorf("Found %d Direct Connect virtual interfaces for %s, expected 1", n, vifId) | ||
} | ||
} | ||
} | ||
|
||
func dxVirtualInterfaceWaitUntilAvailable(d *schema.ResourceData, conn *directconnect.DirectConnect, pending, target []string) error { | ||
stateConf := &resource.StateChangeConf{ | ||
Pending: pending, | ||
Target: target, | ||
Refresh: dxVirtualInterfaceStateRefresh(conn, d.Id()), | ||
Timeout: d.Timeout(schema.TimeoutCreate), | ||
Delay: 10 * time.Second, | ||
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", d.Id(), err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
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 resourceAwsDxPrivateVirtualInterface() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceAwsDxPrivateVirtualInterfaceCreate, | ||
Read: resourceAwsDxPrivateVirtualInterfaceRead, | ||
Update: resourceAwsDxPrivateVirtualInterfaceUpdate, | ||
Delete: resourceAwsDxPrivateVirtualInterfaceDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: resourceAwsDxPrivateVirtualInterfaceImport, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"arn": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"connection_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"vpn_gateway_id": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
ForceNew: true, | ||
ConflictsWith: []string{"dx_gateway_id"}, | ||
}, | ||
"dx_gateway_id": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
ForceNew: true, | ||
ConflictsWith: []string{"vpn_gateway_id"}, | ||
}, | ||
"vlan": { | ||
Type: schema.TypeInt, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validation.IntBetween(1, 4094), | ||
}, | ||
"bgp_asn": { | ||
Type: schema.TypeInt, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"bgp_auth_key": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
ForceNew: true, | ||
}, | ||
"address_family": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validation.StringInSlice([]string{directconnect.AddressFamilyIpv4, directconnect.AddressFamilyIpv6}, false), | ||
}, | ||
"customer_address": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
ForceNew: true, | ||
}, | ||
"amazon_address": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
ForceNew: true, | ||
}, | ||
"tags": tagsSchema(), | ||
}, | ||
|
||
Timeouts: &schema.ResourceTimeout{ | ||
Create: schema.DefaultTimeout(10 * time.Minute), | ||
Delete: schema.DefaultTimeout(10 * time.Minute), | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsDxPrivateVirtualInterfaceCreate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).dxconn | ||
|
||
vgwIdRaw, vgwOk := d.GetOk("vpn_gateway_id") | ||
dxgwIdRaw, dxgwOk := d.GetOk("dx_gateway_id") | ||
if vgwOk == dxgwOk { | ||
return fmt.Errorf( | ||
"One of ['vpn_gateway_id', 'dx_gateway_id'] must be set to create a Direct Connect private virtual interface") | ||
} | ||
|
||
req := &directconnect.CreatePrivateVirtualInterfaceInput{ | ||
ConnectionId: aws.String(d.Get("connection_id").(string)), | ||
NewPrivateVirtualInterface: &directconnect.NewPrivateVirtualInterface{ | ||
VirtualInterfaceName: aws.String(d.Get("name").(string)), | ||
Vlan: aws.Int64(int64(d.Get("vlan").(int))), | ||
Asn: aws.Int64(int64(d.Get("bgp_asn").(int))), | ||
AddressFamily: aws.String(d.Get("address_family").(string)), | ||
}, | ||
} | ||
if vgwOk && vgwIdRaw.(string) != "" { | ||
req.NewPrivateVirtualInterface.VirtualGatewayId = aws.String(vgwIdRaw.(string)) | ||
} | ||
if dxgwOk && dxgwIdRaw.(string) != "" { | ||
req.NewPrivateVirtualInterface.DirectConnectGatewayId = aws.String(dxgwIdRaw.(string)) | ||
} | ||
if v, ok := d.GetOk("bgp_auth_key"); ok { | ||
req.NewPrivateVirtualInterface.AuthKey = aws.String(v.(string)) | ||
} | ||
if v, ok := d.GetOk("customer_address"); ok && v.(string) != "" { | ||
req.NewPrivateVirtualInterface.CustomerAddress = aws.String(v.(string)) | ||
} | ||
if v, ok := d.GetOk("amazon_address"); ok && v.(string) != "" { | ||
req.NewPrivateVirtualInterface.AmazonAddress = aws.String(v.(string)) | ||
} | ||
|
||
log.Printf("[DEBUG] Creating Direct Connect private virtual interface: %#v", req) | ||
resp, err := conn.CreatePrivateVirtualInterface(req) | ||
if err != nil { | ||
return fmt.Errorf("Error creating Direct Connect private virtual interface: %s", err.Error()) | ||
} | ||
|
||
d.SetId(aws.StringValue(resp.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 := dxPrivateVirtualInterfaceWaitUntilAvailable(d, conn); err != nil { | ||
return err | ||
} | ||
|
||
return resourceAwsDxPrivateVirtualInterfaceUpdate(d, meta) | ||
} | ||
|
||
func resourceAwsDxPrivateVirtualInterfaceRead(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 virtual interface (%s) not found, removing from state", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
d.Set("connection_id", vif.ConnectionId) | ||
d.Set("name", vif.VirtualInterfaceName) | ||
d.Set("vlan", vif.Vlan) | ||
d.Set("bgp_asn", vif.Asn) | ||
d.Set("bgp_auth_key", vif.AuthKey) | ||
d.Set("address_family", vif.AddressFamily) | ||
d.Set("customer_address", vif.CustomerAddress) | ||
d.Set("amazon_address", vif.AmazonAddress) | ||
d.Set("vpn_gateway_id", vif.VirtualGatewayId) | ||
d.Set("dx_gateway_id", vif.DirectConnectGatewayId) | ||
if err := getTagsDX(conn, d, d.Get("arn").(string)); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsDxPrivateVirtualInterfaceUpdate(d *schema.ResourceData, meta interface{}) error { | ||
if err := dxVirtualInterfaceUpdate(d, meta); err != nil { | ||
return err | ||
} | ||
|
||
return resourceAwsDxPrivateVirtualInterfaceRead(d, meta) | ||
} | ||
|
||
func resourceAwsDxPrivateVirtualInterfaceDelete(d *schema.ResourceData, meta interface{}) error { | ||
return dxVirtualInterfaceDelete(d, meta) | ||
} | ||
|
||
func resourceAwsDxPrivateVirtualInterfaceImport(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 dxPrivateVirtualInterfaceWaitUntilAvailable(d *schema.ResourceData, conn *directconnect.DirectConnect) error { | ||
return dxVirtualInterfaceWaitUntilAvailable( | ||
d, | ||
conn, | ||
[]string{ | ||
directconnect.VirtualInterfaceStatePending, | ||
}, | ||
[]string{ | ||
directconnect.VirtualInterfaceStateAvailable, | ||
directconnect.VirtualInterfaceStateDown, | ||
}) | ||
} |
Oops, something went wrong.