Merge branch 'f-aws-associate-eip-to-eni' of https://github.com/jstremick/terraform into jstremick-f-aws-associate-eip-to-eni

This commit is contained in:
Mitchell Hashimoto 2015-05-05 13:24:50 -07:00
commit 1c2d5fbd0a
2 changed files with 81 additions and 19 deletions

View File

@ -31,6 +31,12 @@ func resourceAwsEip() *schema.Resource {
Optional: true, Optional: true,
}, },
"network_interface": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"instance"},
},
"allocation_id": &schema.Schema{ "allocation_id": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
@ -102,22 +108,18 @@ func resourceAwsEipRead(d *schema.ResourceData, meta interface{}) error {
domain := resourceAwsEipDomain(d) domain := resourceAwsEipDomain(d)
id := d.Id() id := d.Id()
var assocIds []*string req := &ec2.DescribeAddressesInput{}
var publicIps []*string
if domain == "vpc" { if domain == "vpc" {
assocIds = []*string{aws.String(id)} req.AllocationIDs = []*string{aws.String(id)}
} else { } else {
publicIps = []*string{aws.String(id)} req.PublicIPs = []*string{aws.String(id)}
} }
log.Printf( log.Printf(
"[DEBUG] EIP describe configuration: %#v, %#v (domain: %s)", "[DEBUG] EIP describe configuration: %#v (domain: %s)",
assocIds, publicIps, domain) req, domain)
req := &ec2.DescribeAddressesInput{
AllocationIDs: assocIds,
PublicIPs: publicIps,
}
describeAddresses, err := ec2conn.DescribeAddresses(req) describeAddresses, err := ec2conn.DescribeAddresses(req)
if err != nil { if err != nil {
if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidAllocationID.NotFound" { if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidAllocationID.NotFound" {
@ -143,6 +145,9 @@ func resourceAwsEipRead(d *schema.ResourceData, meta interface{}) error {
if address.InstanceID != nil { if address.InstanceID != nil {
d.Set("instance", address.InstanceID) d.Set("instance", address.InstanceID)
} }
if address.NetworkInterfaceID != nil {
d.Set("network_interface", address.NetworkInterfaceID)
}
d.Set("private_ip", address.PrivateIPAddress) d.Set("private_ip", address.PrivateIPAddress)
d.Set("public_ip", address.PublicIP) d.Set("public_ip", address.PublicIP)
@ -154,9 +159,13 @@ func resourceAwsEipUpdate(d *schema.ResourceData, meta interface{}) error {
domain := resourceAwsEipDomain(d) domain := resourceAwsEipDomain(d)
// Only register with an instance if we have one // Associate to instance or interface if specified
if v, ok := d.GetOk("instance"); ok { v_instance, ok_instance := d.GetOk("instance")
instanceId := v.(string) v_interface, ok_interface := d.GetOk("network_interface")
if ok_instance || ok_interface {
instanceId := v_instance.(string)
networkInterfaceId := v_interface.(string)
assocOpts := &ec2.AssociateAddressInput{ assocOpts := &ec2.AssociateAddressInput{
InstanceID: aws.String(instanceId), InstanceID: aws.String(instanceId),
@ -166,9 +175,9 @@ func resourceAwsEipUpdate(d *schema.ResourceData, meta interface{}) error {
// more unique ID conditionals // more unique ID conditionals
if domain == "vpc" { if domain == "vpc" {
assocOpts = &ec2.AssociateAddressInput{ assocOpts = &ec2.AssociateAddressInput{
InstanceID: aws.String(instanceId), NetworkInterfaceID: aws.String(networkInterfaceId),
AllocationID: aws.String(d.Id()), InstanceID: aws.String(instanceId),
PublicIP: aws.String(""), AllocationID: aws.String(d.Id()),
} }
} }
@ -178,7 +187,8 @@ func resourceAwsEipUpdate(d *schema.ResourceData, meta interface{}) error {
// Prevent saving instance if association failed // Prevent saving instance if association failed
// e.g. missing internet gateway in VPC // e.g. missing internet gateway in VPC
d.Set("instance", "") d.Set("instance", "")
return fmt.Errorf("Failure associating instances: %s", err) d.Set("network_interface", "")
return fmt.Errorf("Failure associating EIP: %s", err)
} }
} }
@ -196,8 +206,8 @@ func resourceAwsEipDelete(d *schema.ResourceData, meta interface{}) error {
return nil return nil
} }
// If we are attached to an instance, detach first. // If we are attached to an instance or interface, detach first.
if d.Get("instance").(string) != "" { if d.Get("instance").(string) != "" || d.Get("association_id").(string) != "" {
log.Printf("[DEBUG] Disassociating EIP: %s", d.Id()) log.Printf("[DEBUG] Disassociating EIP: %s", d.Id())
var err error var err error
switch resourceAwsEipDomain(d) { switch resourceAwsEipDomain(d) {

View File

@ -57,6 +57,26 @@ func TestAccAWSEIP_instance(t *testing.T) {
}) })
} }
func TestAccAWSEIP_network_interface(t *testing.T) {
var conf ec2.Address
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEIPDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSEIPNetworkInterfaceConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEIPExists("aws_eip.bar", &conf),
testAccCheckAWSEIPAttributes(&conf),
testAccCheckAWSEIPAssociated(&conf),
),
},
},
})
}
func testAccCheckAWSEIPDestroy(s *terraform.State) error { func testAccCheckAWSEIPDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ec2conn conn := testAccProvider.Meta().(*AWSClient).ec2conn
@ -101,6 +121,16 @@ func testAccCheckAWSEIPAttributes(conf *ec2.Address) resource.TestCheckFunc {
} }
} }
func testAccCheckAWSEIPAssociated(conf *ec2.Address) resource.TestCheckFunc {
return func(s *terraform.State) error {
if *conf.AssociationID == "" {
return fmt.Errorf("empty association_id")
}
return nil
}
}
func testAccCheckAWSEIPExists(n string, res *ec2.Address) resource.TestCheckFunc { func testAccCheckAWSEIPExists(n string, res *ec2.Address) resource.TestCheckFunc {
return func(s *terraform.State) error { return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n] rs, ok := s.RootModule().Resources[n]
@ -177,3 +207,25 @@ resource "aws_eip" "bar" {
instance = "${aws_instance.bar.id}" instance = "${aws_instance.bar.id}"
} }
` `
const testAccAWSEIPNetworkInterfaceConfig = `
resource "aws_vpc" "bar" {
cidr_block = "10.0.0.0/24"
}
resource "aws_internet_gateway" "bar" {
vpc_id = "${aws_vpc.bar.id}"
}
resource "aws_subnet" "bar" {
vpc_id = "${aws_vpc.bar.id}"
availability_zone = "us-west-2a"
cidr_block = "10.0.0.0/24"
}
resource "aws_network_interface" "bar" {
subnet_id = "${aws_subnet.bar.id}"
private_ips = ["10.0.0.10"]
security_groups = [ "${aws_vpc.bar.default_security_group_id}" ]
}
resource "aws_eip" "bar" {
vpc = "true"
network_interface = "${aws_network_interface.bar.id}"
}
`