Skip to content

Commit

Permalink
Merge pull request #6518 from mhorbul/byoip-support-for-eip
Browse files Browse the repository at this point in the history
r/eip, d/eip: add extra computed attributes and BYOIP feature support
  • Loading branch information
bflad committed Nov 19, 2018
2 parents e1537e7 + dd83d71 commit 01491a1
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 2 deletions.
35 changes: 35 additions & 0 deletions aws/data_source_aws_eip.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,45 @@ func dataSourceAwsEip() *schema.Resource {
Read: dataSourceAwsEipRead,

Schema: map[string]*schema.Schema{
"association_id": {
Type: schema.TypeString,
Computed: true,
},
"domain": {
Type: schema.TypeString,
Computed: true,
},
"filter": ec2CustomFiltersSchema(),
"id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"instance_id": {
Type: schema.TypeString,
Computed: true,
},
"network_interface_id": {
Type: schema.TypeString,
Computed: true,
},
"network_interface_owner_id": {
Type: schema.TypeString,
Computed: true,
},
"private_ip": {
Type: schema.TypeString,
Computed: true,
},
"public_ip": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"public_ipv4_pool": {
Type: schema.TypeString,
Computed: true,
},
"tags": tagsSchemaComputed(),
},
}
Expand Down Expand Up @@ -79,7 +107,14 @@ func dataSourceAwsEipRead(d *schema.ResourceData, meta interface{}) error {
d.SetId(aws.StringValue(eip.PublicIp))
}

d.Set("association_id", eip.AssociationId)
d.Set("domain", eip.Domain)
d.Set("instance_id", eip.InstanceId)
d.Set("network_interface_id", eip.NetworkInterfaceId)
d.Set("network_interface_owner_id", eip.NetworkInterfaceOwnerId)
d.Set("private_ip", eip.PrivateIpAddress)
d.Set("public_ip", eip.PublicIp)
d.Set("public_ipv4_pool", eip.PublicIpv4Pool)
d.Set("tags", tagsToMap(eip.Tags))

return nil
Expand Down
115 changes: 115 additions & 0 deletions aws/data_source_aws_eip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func TestAccDataSourceAwsEip_PublicIP_VPC(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "id", resourceName, "id"),
resource.TestCheckResourceAttrPair(dataSourceName, "public_ip", resourceName, "public_ip"),
resource.TestCheckResourceAttrPair(dataSourceName, "domain", resourceName, "domain"),
),
},
},
Expand All @@ -107,6 +108,47 @@ func TestAccDataSourceAwsEip_Tags(t *testing.T) {
})
}

func TestAccDataSourceAwsEip_NetworkInterface(t *testing.T) {
dataSourceName := "data.aws_eip.test"
resourceName := "aws_eip.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAwsEipConfigNetworkInterface,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "id", resourceName, "id"),
resource.TestCheckResourceAttrPair(dataSourceName, "network_interface_id", resourceName, "network_interface"),
resource.TestCheckResourceAttrPair(dataSourceName, "private_ip", resourceName, "private_ip"),
resource.TestCheckResourceAttrPair(dataSourceName, "domain", resourceName, "domain"),
),
},
},
})
}

func TestAccDataSourceAwsEip_Instance(t *testing.T) {
dataSourceName := "data.aws_eip.test"
resourceName := "aws_eip.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAwsEipConfigInstance,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "id", resourceName, "id"),
resource.TestCheckResourceAttrPair(dataSourceName, "instance_id", resourceName, "instance"),
resource.TestCheckResourceAttrPair(dataSourceName, "association_id", resourceName, "association_id"),
),
},
},
})
}

func testAccDataSourceAwsEipConfigFilter(rName string) string {
return fmt.Sprintf(`
resource "aws_eip" "test" {
Expand Down Expand Up @@ -175,3 +217,76 @@ data "aws_eip" "test" {
}
`, rName)
}

const testAccDataSourceAwsEipConfigNetworkInterface = `
resource "aws_vpc" "test" {
cidr_block = "10.1.0.0/16"
}
resource "aws_subnet" "test" {
vpc_id = "${aws_vpc.test.id}"
cidr_block = "10.1.0.0/24"
}
resource "aws_internet_gateway" "test" {
vpc_id = "${aws_vpc.test.id}"
}
resource "aws_network_interface" "test" {
subnet_id = "${aws_subnet.test.id}"
}
resource "aws_eip" "test" {
vpc = true
network_interface = "${aws_network_interface.test.id}"
}
data "aws_eip" "test" {
filter {
name = "network-interface-id"
values = ["${aws_eip.test.network_interface}"]
}
}
`

const testAccDataSourceAwsEipConfigInstance = `
resource "aws_vpc" "test" {
cidr_block = "10.2.0.0/16"
}
resource "aws_subnet" "test" {
vpc_id = "${aws_vpc.test.id}"
cidr_block = "10.2.0.0/24"
}
resource "aws_internet_gateway" "test" {
vpc_id = "${aws_vpc.test.id}"
}
data "aws_ami" "test" {
most_recent = true
name_regex = "^amzn-ami.*ecs-optimized$"
owners = [
"amazon",
]
}
resource "aws_instance" "test" {
ami = "${data.aws_ami.test.id}"
subnet_id = "${aws_subnet.test.id}"
instance_type = "t2.micro"
}
resource "aws_eip" "test" {
vpc = true
instance = "${aws_instance.test.id}"
}
data "aws_eip" "test" {
filter {
name = "instance-id"
values = ["${aws_eip.test.instance}"]
}
}
`
12 changes: 12 additions & 0 deletions aws/resource_aws_eip.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ func resourceAwsEip() *schema.Resource {
Optional: true,
},

"public_ipv4_pool": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},

"tags": tagsSchema(),
},
}
Expand All @@ -98,6 +105,10 @@ func resourceAwsEipCreate(d *schema.ResourceData, meta interface{}) error {
Domain: aws.String(domainOpt),
}

if v, ok := d.GetOk("public_ipv4_pool"); ok {
allocOpts.PublicIpv4Pool = aws.String(v.(string))
}

log.Printf("[DEBUG] EIP create configuration: %#v", allocOpts)
allocResp, err := ec2conn.AllocateAddress(allocOpts)
if err != nil {
Expand Down Expand Up @@ -211,6 +222,7 @@ func resourceAwsEipRead(d *schema.ResourceData, meta interface{}) error {
}
d.Set("private_ip", address.PrivateIpAddress)
d.Set("public_ip", address.PublicIp)
d.Set("public_ipv4_pool", address.PublicIpv4Pool)

// On import (domain never set, which it must've been if we created),
// set the 'vpc' attribute depending on if we're in a VPC.
Expand Down
69 changes: 67 additions & 2 deletions aws/resource_aws_eip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,56 @@ func TestAccAWSEIP_tags(t *testing.T) {
})
}

func TestAccAWSEIP_PublicIpv4Pool_default(t *testing.T) {
var conf ec2.Address
resourceName := "aws_eip.bar"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
IDRefreshName: resourceName,
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEIPDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEIPConfig_PublicIpv4Pool_default,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEIPExists(resourceName, &conf),
testAccCheckAWSEIPAttributes(&conf),
resource.TestCheckResourceAttr(resourceName, "public_ipv4_pool", "amazon"),
),
},
},
})
}

func TestAccAWSEIP_PublicIpv4Pool_custom(t *testing.T) {
if os.Getenv("AWS_EC2_EIP_PUBLIC_IPV4_POOL") == "" {
t.Skip("Environment variable AWS_EC2_EIP_PUBLIC_IPV4_POOL is not set")
}

var conf ec2.Address
resourceName := "aws_eip.bar"

poolName := fmt.Sprintf("%s", os.Getenv("AWS_EC2_EIP_PUBLIC_IPV4_POOL"))

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
IDRefreshName: resourceName,
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEIPDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEIPConfig_PublicIpv4Pool_custom(poolName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEIPExists(resourceName, &conf),
testAccCheckAWSEIPAttributes(&conf),
resource.TestCheckResourceAttr(resourceName, "public_ipv4_pool", poolName),
),
},
},
})
}

func testAccCheckAWSEIPDisappears(v *ec2.Address) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ec2conn
Expand Down Expand Up @@ -454,6 +504,21 @@ resource "aws_eip" "bar" {
`, rName, testName)
}

const testAccAWSEIPConfig_PublicIpv4Pool_default = `
resource "aws_eip" "bar" {
vpc = true
}
`

func testAccAWSEIPConfig_PublicIpv4Pool_custom(poolName string) string {
return fmt.Sprintf(`
resource "aws_eip" "bar" {
vpc = true
public_ipv4_pool = "%s"
}
`, poolName)
}

const testAccAWSEIPInstanceEc2Classic = `
provider "aws" {
region = "us-east-1"
Expand Down Expand Up @@ -716,7 +781,7 @@ resource "aws_subnet" "bar" {
availability_zone = "us-west-2a"
cidr_block = "10.0.0.0/24"
tags {
Name = "tf-acc-eip-network-interface"
Name = "tf-acc-eip-network-interface"
}
}
Expand Down Expand Up @@ -750,7 +815,7 @@ resource "aws_subnet" "bar" {
availability_zone = "us-west-2a"
cidr_block = "10.0.0.0/24"
tags {
Name = "tf-acc-eip-multi-network-interface"
Name = "tf-acc-eip-multi-network-interface"
}
}
Expand Down
7 changes: 7 additions & 0 deletions website/docs/d/eip.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ Elastic IP whose data will be exported as attributes.

In addition to all arguments above, the following attributes are exported:

* `association_id` - The ID representing the association of the address with an instance in a VPC.
* `domain` - Indicates whether the address is for use in EC2-Classic (standard) or in a VPC (vpc).
* `id` - If VPC Elastic IP, the allocation identifier. If EC2-Classic Elastic IP, the public IP address.
* `instance_id` - The ID of the instance that the address is associated with (if any).
* `network_interface_id` - The ID of the network interface.
* `network_interface_owner_id` - The ID of the AWS account that owns the network interface.
* `private_ip` - The private IP address associated with the Elastic IP address.
* `public_ip` - Public IP address of Elastic IP.
* `public_ipv4_pool` - The ID of an address pool.
* `tags` - Key-value map of tags associated with Elastic IP.
11 changes: 11 additions & 0 deletions website/docs/r/eip.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ resource "aws_eip" "bar" {
}
```

Allocating EIP from the BYOIP pool:

```hcl
resource "aws_eip" "byoip-ip" {
vpc = true
public_ipv4_pool = "ipv4pool-ec2-012345"
}
```

## Argument Reference

The following arguments are supported:
Expand All @@ -95,6 +104,7 @@ The following arguments are supported:
associate with the Elastic IP address. If no private IP address is specified,
the Elastic IP address is associated with the primary private IP address.
* `tags` - (Optional) A mapping of tags to assign to the resource.
* `public_ipv4_pool` - (Optional) EC2 IPv4 address pool identifier or `amazon`. This option is only available for VPC EIPs.

~> **NOTE:** You can specify either the `instance` ID or the `network_interface` ID,
but not both. Including both will **not** return an error from the AWS API, but will
Expand All @@ -112,6 +122,7 @@ In addition to all arguments above, the following attributes are exported:
* `public_ip` - Contains the public IP address.
* `instance` - Contains the ID of the attached instance.
* `network_interface` - Contains the ID of the attached network interface.
* `public_ipv4_pool` - EC2 IPv4 address pool identifier (if in VPC).

## Timeouts
`aws_eip` provides the following [Timeouts](/docs/configuration/resources.html#timeouts) configuration options:
Expand Down

0 comments on commit 01491a1

Please sign in to comment.