Skip to content

Commit

Permalink
Added data source 'aws_eips'. (#7537)
Browse files Browse the repository at this point in the history
Co-authored-by: David Chamard <d.chamard@samsung.com>
  • Loading branch information
2 people authored and anGie44 committed Feb 3, 2022
1 parent 11bfe19 commit 7c24938
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/7537.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-data-source
aws_eips
```
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ func Provider() *schema.Provider {
"aws_ec2_transit_gateway_vpc_attachment": ec2.DataSourceTransitGatewayVPCAttachment(),
"aws_ec2_transit_gateway_vpn_attachment": ec2.DataSourceTransitGatewayVPNAttachment(),
"aws_eip": ec2.DataSourceEIP(),
"aws_eips": ec2.DataSourceEIPs(),
"aws_instance": ec2.DataSourceInstance(),
"aws_instances": ec2.DataSourceInstances(),
"aws_internet_gateway": ec2.DataSourceInternetGateway(),
Expand Down
76 changes: 76 additions & 0 deletions internal/service/ec2/eips_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package ec2

import (
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
)

func DataSourceEIPs() *schema.Resource {
return &schema.Resource{
Read: dataSourceEIPsRead,

Schema: map[string]*schema.Schema{
"allocation_ids": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"filter": DataSourceFiltersSchema(),
"public_ips": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"tags": tftags.TagsSchemaComputed(),
},
}
}

func dataSourceEIPsRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).EC2Conn

input := &ec2.DescribeAddressesInput{}

if tags, tagsOk := d.GetOk("tags"); tagsOk {
input.Filters = append(input.Filters, BuildTagFilterList(
Tags(tftags.New(tags.(map[string]interface{}))),
)...)
}

if filters, filtersOk := d.GetOk("filter"); filtersOk {
input.Filters = append(input.Filters,
BuildFiltersDataSource(filters.(*schema.Set))...)
}

if len(input.Filters) == 0 {
input.Filters = nil
}

output, err := FindEIPs(conn, input)

if err != nil {
return fmt.Errorf("error reading EC2 EIPs: %w", err)
}

var allocationIDs []string
var publicIPs []string

for _, v := range output {
if aws.StringValue(v.Domain) == ec2.DomainTypeVpc {
allocationIDs = append(allocationIDs, aws.StringValue(v.AllocationId))
} else {
publicIPs = append(publicIPs, aws.StringValue(v.PublicIp))
}
}

d.SetId(meta.(*conns.AWSClient).Region)
d.Set("allocation_ids", allocationIDs)
d.Set("public_ips", publicIPs)

return nil
}
100 changes: 100 additions & 0 deletions internal/service/ec2/eips_data_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package ec2_test

import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go/service/ec2"
sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
)

func TestAccEC2EIPsDataSource_vpcDomain(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID),
Providers: acctest.Providers,
Steps: []resource.TestStep{
{
Config: testAccEIPsVPCDomainDataSourceConfig(rName),
Check: resource.ComposeTestCheckFunc(
acctest.CheckResourceAttrGreaterThanValue("data.aws_eips.all", "allocation_ids.#", "1"),
resource.TestCheckResourceAttr("data.aws_eips.by_tags", "allocation_ids.#", "1"),
resource.TestCheckResourceAttr("data.aws_eips.by_tags", "public_ips.#", "0"),
resource.TestCheckResourceAttr("data.aws_eips.none", "allocation_ids.#", "0"),
resource.TestCheckResourceAttr("data.aws_eips.none", "public_ips.#", "0"),
),
},
},
})
}

func TestAccEC2EIPsDataSource_standardDomain(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t); acctest.PreCheckEC2Classic(t) },
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID),
ProviderFactories: acctest.ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccEIPsStandardDomainDataSourceConfig(),
Check: resource.ComposeTestCheckFunc(
acctest.CheckResourceAttrGreaterThanValue("data.aws_eips.all", "public_ips.#", "0"),
),
},
},
})
}

func testAccEIPsVPCDomainDataSourceConfig(rName string) string {
return fmt.Sprintf(`
resource "aws_eip" "test1" {
vpc = true
tags = {
Name = "%[1]s-1"
}
}
resource "aws_eip" "test2" {
vpc = true
tags = {
Name = "%[1]s-2"
}
}
data "aws_eips" "all" {
depends_on = [aws_eip.test1, aws_eip.test2]
}
data "aws_eips" "by_tags" {
tags = {
Name = "%[1]s-1"
}
depends_on = [aws_eip.test1, aws_eip.test2]
}
data "aws_eips" "none" {
filter {
name = "tag-key"
values = ["%[1]s-3"]
}
depends_on = [aws_eip.test1, aws_eip.test2]
}
`, rName)
}

func testAccEIPsStandardDomainDataSourceConfig() string {
return acctest.ConfigCompose(acctest.ConfigEC2ClassicRegionProvider(), `
resource "aws_eip" "test" {}
data "aws_eips" "all" {
depends_on = [aws_eip.test]
}
`)
}
2 changes: 2 additions & 0 deletions internal/service/ec2/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const (
ErrCodeDependencyViolation = "DependencyViolation"
ErrCodeGatewayNotAttached = "Gateway.NotAttached"
ErrCodeIncorrectState = "IncorrectState"
ErrCodeInvalidAddressNotFound = "InvalidAddress.NotFound"
ErrCodeInvalidAllocationIDNotFound = "InvalidAllocationID.NotFound"
ErrCodeInvalidAssociationIDNotFound = "InvalidAssociationID.NotFound"
ErrCodeInvalidAttachmentIDNotFound = "InvalidAttachmentID.NotFound"
ErrCodeInvalidCarrierGatewayIDNotFound = "InvalidCarrierGatewayID.NotFound"
Expand Down
25 changes: 25 additions & 0 deletions internal/service/ec2/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,31 @@ func FindClientVPNRouteByID(conn *ec2.EC2, routeID string) (*ec2.DescribeClientV
return FindClientVPNRoute(conn, endpointID, targetSubnetID, destinationCidr)
}

func FindEIPs(conn *ec2.EC2, input *ec2.DescribeAddressesInput) ([]*ec2.Address, error) {
var addresses []*ec2.Address

output, err := conn.DescribeAddresses(input)

if tfawserr.ErrCodeEquals(err, ErrCodeInvalidAddressNotFound, ErrCodeInvalidAllocationIDNotFound) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

for _, v := range output.Addresses {
if v != nil {
addresses = append(addresses, v)
}
}

return addresses, nil
}

func FindHostByID(conn *ec2.EC2, id string) (*ec2.Host, error) {
input := &ec2.DescribeHostsInput{
HostIds: aws.StringSlice([]string{id}),
Expand Down
50 changes: 50 additions & 0 deletions website/docs/d/eips.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
subcategory: "VPC"
layout: "aws"
page_title: "AWS: aws_eips"
description: |-
Provides a list of Elastic IPs in a region
---

# Data Source: aws_eips

Provides a list of Elastic IPs in a region.

## Example Usage

The following shows outputing all Elastic IPs with the a specific tag value.

```terraform
data "aws_eips" "example" {
tags = {
Env = "dev"
}
}
# VPC EIPs.
output "allocation_ids" {
value = data.aws_eips.example.allocation_ids
}
# EC2-Classic EIPs.
output "public_ips" {
value = data.aws_eips.example.public_ips
}
```

## Argument Reference

* `filter` - (Optional) Custom filter block as described below.
* `tags` - (Optional) A map of tags, each pair of which must exactly match a pair on the desired Elastic IPs.

More complex filters can be expressed using one or more `filter` sub-blocks, which take the following arguments:

* `name` - (Required) The name of the field to filter by, as defined by
[the underlying AWS API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeAddresses.html).
* `values` - (Required) Set of values that are accepted for the given field. An Elastic IP will be selected if any one of the given values matches.

## Attributes Reference

* `id` - AWS Region.
* `allocation_ids` - A list of all the allocation IDs for address for use with EC2-VPC.
* `public_ips` - A list of all the Elastic IP addresses for use with EC2-Classic.

0 comments on commit 7c24938

Please sign in to comment.