From 51f6b96ec1d3f55eac49e94bbe635c5ca341d24c Mon Sep 17 00:00:00 2001 From: Alex Bacchin Date: Sun, 6 Oct 2024 00:25:29 +1000 Subject: [PATCH 1/6] added IpamPoolId to aws_eip --- internal/service/ec2/ec2_eip.go | 59 +++++++++++++++++++++++- internal/service/ec2/ec2_eip_test.go | 68 ++++++++++++++++++++++++++++ website/docs/r/eip.html.markdown | 10 ++++ 3 files changed, 136 insertions(+), 1 deletion(-) diff --git a/internal/service/ec2/ec2_eip.go b/internal/service/ec2/ec2_eip.go index d03109791e6..a9703423966 100644 --- a/internal/service/ec2/ec2_eip.go +++ b/internal/service/ec2/ec2_eip.go @@ -17,10 +17,12 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/enum" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" @@ -96,11 +98,16 @@ func resourceEIP() *schema.Resource { Optional: true, Computed: true, }, + "ipam_pool_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, "network_border_group": { Type: schema.TypeString, Optional: true, Computed: true, - ForceNew: true, }, "network_interface": { Type: schema.TypeString, @@ -171,6 +178,10 @@ func resourceEIPCreate(ctx context.Context, d *schema.ResourceData, meta interfa input.Domain = types.DomainTypeVpc } + if v, ok := d.GetOk("ipam_pool_id"); ok { + input.IpamPoolId = aws.String(v.(string)) + } + if v, ok := d.GetOk("network_border_group"); ok { input.NetworkBorderGroup = aws.String(v.(string)) } @@ -244,6 +255,9 @@ func resourceEIPRead(ctx context.Context, d *schema.ResourceData, meta interface d.Set("network_border_group", address.NetworkBorderGroup) d.Set("network_interface", address.NetworkInterfaceId) d.Set("public_ipv4_pool", address.PublicIpv4Pool) + if strings.HasPrefix(*address.PublicIpv4Pool, "ipam-pool") { + d.Set("ipam_pool_id", address.PublicIpv4Pool) + } d.Set("private_ip", address.PrivateIpAddress) if v := aws.ToString(address.PrivateIpAddress); v != "" { d.Set("private_dns", meta.(*conns.AWSClient).EC2PrivateDNSNameForIP(ctx, v)) @@ -326,6 +340,27 @@ func resourceEIPDelete(ctx context.Context, d *schema.ResourceData, meta interfa log.Printf("[INFO] Deleting EC2 EIP: %s", d.Id()) _, err := conn.ReleaseAddress(ctx, input) + // If the EIP's CIDR block was allocated from an IPAM pool, wait for the allocation to disappear. + var ipamPoolID, eipAllocationId string + if v, ok := d.GetOk("ipam_pool_id"); ok { + ipamPoolID = v.(string) + } + if v, ok := d.GetOk("allocation_id"); ok { + eipAllocationId = v.(string) + } + if ipamPoolID != "" { + const ( + timeout = 10 * time.Minute // IPAM eventual consistency + ) + _, err := tfresource.RetryUntilNotFound(ctx, timeout, func() (interface{}, error) { + return findIPAMPoolAllocationsForEip(ctx, conn, ipamPoolID, eipAllocationId) + }) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for EC2 EIP (%s) IPAM Pool (%s) Allocation delete: %s", d.Id(), ipamPoolID, err) + } + } + if tfawserr.ErrCodeEquals(err, errCodeInvalidAllocationIDNotFound) { return diags } @@ -423,3 +458,25 @@ func eipARN(c *conns.AWSClient, allocationID string) string { Resource: "elastic-ip/" + allocationID, }.String() } + +func findIPAMPoolAllocationsForEip(ctx context.Context, conn *ec2.Client, poolID, eipAllocationId string) ([]types.IpamPoolAllocation, error) { + input := &ec2.GetIpamPoolAllocationsInput{ + IpamPoolId: aws.String(poolID), + } + + output, err := findIPAMPoolAllocations(ctx, conn, input) + + if err != nil { + return nil, err + } + + output = tfslices.Filter(output, func(v types.IpamPoolAllocation) bool { + return string(v.ResourceType) == string(types.IpamPoolAllocationResourceTypeEip) && aws.ToString(v.ResourceId) == eipAllocationId + }) + + if len(output) == 0 { + return nil, &retry.NotFoundError{} + } + + return output, nil +} diff --git a/internal/service/ec2/ec2_eip_test.go b/internal/service/ec2/ec2_eip_test.go index e94b2406c22..b77384085e5 100644 --- a/internal/service/ec2/ec2_eip_test.go +++ b/internal/service/ec2/ec2_eip_test.go @@ -503,6 +503,31 @@ func TestAccEC2EIP_PublicIPv4Pool_custom(t *testing.T) { }) } +func TestAccEC2EIP_PublicIPv4Pool_IpamPoolId(t *testing.T) { + ctx := acctest.Context(t) + var conf types.Address + resourceName := "aws_eip.test" + ipamPoolDataSourceName := "aws_vpc_ipam_pool.test_pool" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EC2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckEIPDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccEIPConfig_publicIPv4IpamPoolId(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckEIPExists(ctx, resourceName, &conf), + resource.TestCheckResourceAttrSet(resourceName, "public_ip"), + resource.TestCheckResourceAttrPair(resourceName, "ipam_pool_id", ipamPoolDataSourceName, "id"), + ), + }, + }, + }) +} + func TestAccEC2EIP_customerOwnedIPv4Pool(t *testing.T) { ctx := acctest.Context(t) var conf types.Address @@ -1149,6 +1174,49 @@ resource "aws_eip" "test" { } `, rName, poolName) } +func testAccEIPConfig_setupIpamPool() string { + return fmt.Sprintf(` + + `) +} +func testAccEIPConfig_publicIPv4IpamPoolId(rName string) string { + return fmt.Sprintf(` +data "aws_region" "current" {} + +resource "aws_vpc_ipam" "test" { + operating_regions { + region_name = data.aws_region.current.name + } + tier = "free" +} + +resource "aws_vpc_ipam_pool" "test_pool" { + address_family = "ipv4" + ipam_scope_id = aws_vpc_ipam.test.public_default_scope_id + locale = data.aws_region.current.name + public_ip_source = "amazon" + description = "Test Amazon CIDR Pool" + aws_service = "ec2" +} + +resource "aws_vpc_ipam_pool_cidr" "test_cidr" { + ipam_pool_id = aws_vpc_ipam_pool.test_pool.id + netmask_length = 30 +} + +resource "aws_eip" "test" { + domain = "vpc" + ipam_pool_id = aws_vpc_ipam_pool.test_pool.id + + tags = { + Name = %[1]q + } + + depends_on = [aws_vpc_ipam_pool_cidr.test_cidr] + +} +`, rName) +} func testAccEIPConfig_customerOwnedIPv4Pool(rName string) string { return fmt.Sprintf(` diff --git a/website/docs/r/eip.html.markdown b/website/docs/r/eip.html.markdown index feafb069321..10222ab21dc 100644 --- a/website/docs/r/eip.html.markdown +++ b/website/docs/r/eip.html.markdown @@ -93,6 +93,15 @@ resource "aws_eip" "byoip-ip" { } ``` +### Allocating EIP from the IPAM Pool + +```terraform +resource "aws_eip" "ipam-ip" { + domain = "vpc" + ipam_pool_id = "ipam-pool-07ccc86aa41bef7ce" +} +``` + ## Argument Reference This resource supports the following arguments: @@ -102,6 +111,7 @@ This resource supports the following arguments: * `customer_owned_ipv4_pool` - (Optional) ID of a customer-owned address pool. For more on customer owned IP addressed check out [Customer-owned IP addresses guide](https://docs.aws.amazon.com/outposts/latest/userguide/outposts-networking-components.html#ip-addressing). * `domain` - Indicates if this EIP is for use in VPC (`vpc`). * `instance` - (Optional) EC2 instance ID. +* `ipam_pool_id`- (Optional) The ID of an IPAM pool which has an Amazon-provided or BYOIP public IPv4 CIDR provisioned to it. * `network_border_group` - (Optional) Location from which the IP address is advertised. Use this parameter to limit the address to this location. * `network_interface` - (Optional) Network interface ID to associate with. * `public_ipv4_pool` - (Optional) EC2 IPv4 address pool identifier or `amazon`. From df108137d23d4588b694e1acd3239b18520a1d0c Mon Sep 17 00:00:00 2001 From: Alex Bacchin Date: Sun, 6 Oct 2024 21:25:15 +1100 Subject: [PATCH 2/6] added changelog, formating fixes and cleanup --- .changelog/39604.txt | 3 +++ internal/service/ec2/ec2_eip.go | 4 ++-- internal/service/ec2/ec2_eip_test.go | 8 ++------ website/docs/r/eip.html.markdown | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) create mode 100644 .changelog/39604.txt diff --git a/.changelog/39604.txt b/.changelog/39604.txt new file mode 100644 index 00000000000..8805d3c2e9f --- /dev/null +++ b/.changelog/39604.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_eip: Add ipam_pool_id attribute to support public IPAM pools +``` \ No newline at end of file diff --git a/internal/service/ec2/ec2_eip.go b/internal/service/ec2/ec2_eip.go index a9703423966..424746975d9 100644 --- a/internal/service/ec2/ec2_eip.go +++ b/internal/service/ec2/ec2_eip.go @@ -353,7 +353,7 @@ func resourceEIPDelete(ctx context.Context, d *schema.ResourceData, meta interfa timeout = 10 * time.Minute // IPAM eventual consistency ) _, err := tfresource.RetryUntilNotFound(ctx, timeout, func() (interface{}, error) { - return findIPAMPoolAllocationsForEip(ctx, conn, ipamPoolID, eipAllocationId) + return findIpamPoolAllocationsForEip(ctx, conn, ipamPoolID, eipAllocationId) }) if err != nil { @@ -459,7 +459,7 @@ func eipARN(c *conns.AWSClient, allocationID string) string { }.String() } -func findIPAMPoolAllocationsForEip(ctx context.Context, conn *ec2.Client, poolID, eipAllocationId string) ([]types.IpamPoolAllocation, error) { +func findIpamPoolAllocationsForEip(ctx context.Context, conn *ec2.Client, poolID, eipAllocationId string) ([]types.IpamPoolAllocation, error) { input := &ec2.GetIpamPoolAllocationsInput{ IpamPoolId: aws.String(poolID), } diff --git a/internal/service/ec2/ec2_eip_test.go b/internal/service/ec2/ec2_eip_test.go index b77384085e5..1fcae2b333e 100644 --- a/internal/service/ec2/ec2_eip_test.go +++ b/internal/service/ec2/ec2_eip_test.go @@ -503,7 +503,7 @@ func TestAccEC2EIP_PublicIPv4Pool_custom(t *testing.T) { }) } -func TestAccEC2EIP_PublicIPv4Pool_IpamPoolId(t *testing.T) { +func TestAccEC2EIP_publicIpv4Pool_ipamPoolId(t *testing.T) { ctx := acctest.Context(t) var conf types.Address resourceName := "aws_eip.test" @@ -521,7 +521,7 @@ func TestAccEC2EIP_PublicIPv4Pool_IpamPoolId(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckEIPExists(ctx, resourceName, &conf), resource.TestCheckResourceAttrSet(resourceName, "public_ip"), - resource.TestCheckResourceAttrPair(resourceName, "ipam_pool_id", ipamPoolDataSourceName, "id"), + resource.TestCheckResourceAttrPair(resourceName, "ipam_pool_id", ipamPoolDataSourceName, names.AttrID), ), }, }, @@ -1174,11 +1174,7 @@ resource "aws_eip" "test" { } `, rName, poolName) } -func testAccEIPConfig_setupIpamPool() string { - return fmt.Sprintf(` - `) -} func testAccEIPConfig_publicIPv4IpamPoolId(rName string) string { return fmt.Sprintf(` data "aws_region" "current" {} diff --git a/website/docs/r/eip.html.markdown b/website/docs/r/eip.html.markdown index 10222ab21dc..0cbe45ca394 100644 --- a/website/docs/r/eip.html.markdown +++ b/website/docs/r/eip.html.markdown @@ -97,7 +97,7 @@ resource "aws_eip" "byoip-ip" { ```terraform resource "aws_eip" "ipam-ip" { - domain = "vpc" + domain = "vpc" ipam_pool_id = "ipam-pool-07ccc86aa41bef7ce" } ``` From dfd829b0247f41cd82340ad67571c58802d48e08 Mon Sep 17 00:00:00 2001 From: Alex Bacchin Date: Sun, 6 Oct 2024 21:32:19 +1100 Subject: [PATCH 3/6] fixed IPAM caps --- internal/service/ec2/ec2_eip.go | 4 ++-- internal/service/ec2/ec2_eip_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/service/ec2/ec2_eip.go b/internal/service/ec2/ec2_eip.go index 424746975d9..c979a750bb0 100644 --- a/internal/service/ec2/ec2_eip.go +++ b/internal/service/ec2/ec2_eip.go @@ -353,7 +353,7 @@ func resourceEIPDelete(ctx context.Context, d *schema.ResourceData, meta interfa timeout = 10 * time.Minute // IPAM eventual consistency ) _, err := tfresource.RetryUntilNotFound(ctx, timeout, func() (interface{}, error) { - return findIpamPoolAllocationsForEip(ctx, conn, ipamPoolID, eipAllocationId) + return findIPAMPoolAllocationsForEIP(ctx, conn, ipamPoolID, eipAllocationId) }) if err != nil { @@ -459,7 +459,7 @@ func eipARN(c *conns.AWSClient, allocationID string) string { }.String() } -func findIpamPoolAllocationsForEip(ctx context.Context, conn *ec2.Client, poolID, eipAllocationId string) ([]types.IpamPoolAllocation, error) { +func findIPAMPoolAllocationsForEIP(ctx context.Context, conn *ec2.Client, poolID, eipAllocationId string) ([]types.IpamPoolAllocation, error) { input := &ec2.GetIpamPoolAllocationsInput{ IpamPoolId: aws.String(poolID), } diff --git a/internal/service/ec2/ec2_eip_test.go b/internal/service/ec2/ec2_eip_test.go index 1fcae2b333e..cfb4018e67d 100644 --- a/internal/service/ec2/ec2_eip_test.go +++ b/internal/service/ec2/ec2_eip_test.go @@ -503,7 +503,7 @@ func TestAccEC2EIP_PublicIPv4Pool_custom(t *testing.T) { }) } -func TestAccEC2EIP_publicIpv4Pool_ipamPoolId(t *testing.T) { +func TestAccEC2EIP_PublicIPv4Pool_IPAMPoolId(t *testing.T) { ctx := acctest.Context(t) var conf types.Address resourceName := "aws_eip.test" @@ -517,7 +517,7 @@ func TestAccEC2EIP_publicIpv4Pool_ipamPoolId(t *testing.T) { CheckDestroy: testAccCheckEIPDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccEIPConfig_publicIPv4IpamPoolId(rName), + Config: testAccEIPConfig_publicIPv4_IPAMPoolId(rName), Check: resource.ComposeTestCheckFunc( testAccCheckEIPExists(ctx, resourceName, &conf), resource.TestCheckResourceAttrSet(resourceName, "public_ip"), @@ -1175,7 +1175,7 @@ resource "aws_eip" "test" { `, rName, poolName) } -func testAccEIPConfig_publicIPv4IpamPoolId(rName string) string { +func testAccEIPConfig_publicIPv4_IPAMPoolId(rName string) string { return fmt.Sprintf(` data "aws_region" "current" {} From 105c885a643b51f3964df32d8dbb8aeb825ec63d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 8 Oct 2024 10:28:40 -0400 Subject: [PATCH 4/6] Tweak CHANGELOG entry. --- .changelog/39604.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/39604.txt b/.changelog/39604.txt index 8805d3c2e9f..fc0065f9ea1 100644 --- a/.changelog/39604.txt +++ b/.changelog/39604.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -resource/aws_eip: Add ipam_pool_id attribute to support public IPAM pools +resource/aws_eip: Add `ipam_pool_id` argument in support of [public IPAM pools](https://docs.aws.amazon.com/vpc/latest/ipam/tutorials-eip-pool.html) ``` \ No newline at end of file From acfca9ea9f384882ba6cd67e1c45ed7e74d6f74e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 8 Oct 2024 10:43:53 -0400 Subject: [PATCH 5/6] Cosmetics. --- internal/service/ec2/consts.go | 5 +++-- internal/service/ec2/ec2_eip.go | 22 ++++++++-------------- internal/service/ec2/vpc_.go | 6 +++--- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/internal/service/ec2/consts.go b/internal/service/ec2/consts.go index 009a5257b09..daa24a88313 100644 --- a/internal/service/ec2/consts.go +++ b/internal/service/ec2/consts.go @@ -242,8 +242,9 @@ func vpnConnectionType_Values() []string { } const ( - amazonIPv6PoolID = "Amazon" - ipamManagedIPv6PoolID = "IPAM Managed" + amazonIPv6PoolID = "Amazon" + ipamManagedIPv6PoolID = "IPAM Managed" + publicIPv4PoolIDIPAMPoolPrefix = "ipam-pool-" ) const ( diff --git a/internal/service/ec2/ec2_eip.go b/internal/service/ec2/ec2_eip.go index c979a750bb0..b7e6c6b0a08 100644 --- a/internal/service/ec2/ec2_eip.go +++ b/internal/service/ec2/ec2_eip.go @@ -252,12 +252,12 @@ func resourceEIPRead(ctx context.Context, d *schema.ResourceData, meta interface d.Set("customer_owned_ipv4_pool", address.CustomerOwnedIpv4Pool) d.Set(names.AttrDomain, address.Domain) d.Set("instance", address.InstanceId) + if v := aws.ToString(address.PublicIpv4Pool); strings.HasPrefix(v, publicIPv4PoolIDIPAMPoolPrefix) { + d.Set("ipam_pool_id", v) + } d.Set("network_border_group", address.NetworkBorderGroup) d.Set("network_interface", address.NetworkInterfaceId) d.Set("public_ipv4_pool", address.PublicIpv4Pool) - if strings.HasPrefix(*address.PublicIpv4Pool, "ipam-pool") { - d.Set("ipam_pool_id", address.PublicIpv4Pool) - } d.Set("private_ip", address.PrivateIpAddress) if v := aws.ToString(address.PrivateIpAddress); v != "" { d.Set("private_dns", meta.(*conns.AWSClient).EC2PrivateDNSNameForIP(ctx, v)) @@ -341,19 +341,13 @@ func resourceEIPDelete(ctx context.Context, d *schema.ResourceData, meta interfa _, err := conn.ReleaseAddress(ctx, input) // If the EIP's CIDR block was allocated from an IPAM pool, wait for the allocation to disappear. - var ipamPoolID, eipAllocationId string if v, ok := d.GetOk("ipam_pool_id"); ok { - ipamPoolID = v.(string) - } - if v, ok := d.GetOk("allocation_id"); ok { - eipAllocationId = v.(string) - } - if ipamPoolID != "" { + ipamPoolID := v.(string) const ( timeout = 10 * time.Minute // IPAM eventual consistency ) _, err := tfresource.RetryUntilNotFound(ctx, timeout, func() (interface{}, error) { - return findIPAMPoolAllocationsForEIP(ctx, conn, ipamPoolID, eipAllocationId) + return findIPAMPoolAllocationsForEIP(ctx, conn, ipamPoolID, d.Get("allocation_id").(string)) }) if err != nil { @@ -459,9 +453,9 @@ func eipARN(c *conns.AWSClient, allocationID string) string { }.String() } -func findIPAMPoolAllocationsForEIP(ctx context.Context, conn *ec2.Client, poolID, eipAllocationId string) ([]types.IpamPoolAllocation, error) { +func findIPAMPoolAllocationsForEIP(ctx context.Context, conn *ec2.Client, ipamPoolID, eipAllocationID string) ([]types.IpamPoolAllocation, error) { input := &ec2.GetIpamPoolAllocationsInput{ - IpamPoolId: aws.String(poolID), + IpamPoolId: aws.String(ipamPoolID), } output, err := findIPAMPoolAllocations(ctx, conn, input) @@ -471,7 +465,7 @@ func findIPAMPoolAllocationsForEIP(ctx context.Context, conn *ec2.Client, poolID } output = tfslices.Filter(output, func(v types.IpamPoolAllocation) bool { - return string(v.ResourceType) == string(types.IpamPoolAllocationResourceTypeEip) && aws.ToString(v.ResourceId) == eipAllocationId + return v.ResourceType == types.IpamPoolAllocationResourceTypeEip && aws.ToString(v.ResourceId) == eipAllocationID }) if len(output) == 0 { diff --git a/internal/service/ec2/vpc_.go b/internal/service/ec2/vpc_.go index ac371e9c846..198112d79d1 100644 --- a/internal/service/ec2/vpc_.go +++ b/internal/service/ec2/vpc_.go @@ -550,7 +550,7 @@ func defaultIPv6CIDRBlockAssociation(vpc *types.Vpc, associationID string) *type if associationID != "" { for _, v := range vpc.Ipv6CidrBlockAssociationSet { - if state := string(v.Ipv6CidrBlockState.State); state == string(types.VpcCidrBlockStateCodeAssociated) && aws.ToString(v.AssociationId) == associationID { + if state := v.Ipv6CidrBlockState.State; state == types.VpcCidrBlockStateCodeAssociated && aws.ToString(v.AssociationId) == associationID { ipv6CIDRBlockAssociation = v break } @@ -559,7 +559,7 @@ func defaultIPv6CIDRBlockAssociation(vpc *types.Vpc, associationID string) *type if ipv6CIDRBlockAssociation == (types.VpcIpv6CidrBlockAssociation{}) { for _, v := range vpc.Ipv6CidrBlockAssociationSet { - if string(v.Ipv6CidrBlockState.State) == string(types.VpcCidrBlockStateCodeAssociated) { + if v.Ipv6CidrBlockState.State == types.VpcCidrBlockStateCodeAssociated { ipv6CIDRBlockAssociation = v } } @@ -741,7 +741,7 @@ func findIPAMPoolAllocationsForVPC(ctx context.Context, conn *ec2.Client, poolID } output = tfslices.Filter(output, func(v types.IpamPoolAllocation) bool { - return string(v.ResourceType) == string(types.IpamPoolAllocationResourceTypeVpc) && aws.ToString(v.ResourceId) == vpcID + return v.ResourceType == types.IpamPoolAllocationResourceTypeVpc && aws.ToString(v.ResourceId) == vpcID }) if len(output) == 0 { From 313d5124e88a5dfffe4761037a88a7c55ad0bc8c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 8 Oct 2024 10:47:41 -0400 Subject: [PATCH 6/6] d/aws_eip: Add `ipam_pool_id` attribute. --- .changelog/39604.txt | 4 ++++ internal/service/ec2/ec2_eip_data_source.go | 8 ++++++++ internal/service/ec2/ec2_eip_data_source_test.go | 3 ++- website/docs/d/eip.html.markdown | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.changelog/39604.txt b/.changelog/39604.txt index fc0065f9ea1..ef79f15e6ff 100644 --- a/.changelog/39604.txt +++ b/.changelog/39604.txt @@ -1,3 +1,7 @@ ```release-note:enhancement resource/aws_eip: Add `ipam_pool_id` argument in support of [public IPAM pools](https://docs.aws.amazon.com/vpc/latest/ipam/tutorials-eip-pool.html) +``` + +```release-note:enhancement +data-source/aws_eip: Add `ipam_pool_id` attribute ``` \ No newline at end of file diff --git a/internal/service/ec2/ec2_eip_data_source.go b/internal/service/ec2/ec2_eip_data_source.go index 95f4553d9f0..f4ac551c628 100644 --- a/internal/service/ec2/ec2_eip_data_source.go +++ b/internal/service/ec2/ec2_eip_data_source.go @@ -5,6 +5,7 @@ package ec2 import ( "context" + "strings" "time" "github.com/aws/aws-sdk-go-v2/aws" @@ -65,6 +66,10 @@ func dataSourceEIP() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "ipam_pool_id": { + Type: schema.TypeString, + Computed: true, + }, names.AttrNetworkInterfaceID: { Type: schema.TypeString, Computed: true, @@ -162,6 +167,9 @@ func dataSourceEIPRead(ctx context.Context, d *schema.ResourceData, meta interfa d.Set("customer_owned_ipv4_pool", eip.CustomerOwnedIpv4Pool) d.Set(names.AttrDomain, eip.Domain) d.Set(names.AttrInstanceID, eip.InstanceId) + if v := aws.ToString(eip.PublicIpv4Pool); strings.HasPrefix(v, publicIPv4PoolIDIPAMPoolPrefix) { + d.Set("ipam_pool_id", v) + } d.Set(names.AttrNetworkInterfaceID, eip.NetworkInterfaceId) d.Set("network_interface_owner_id", eip.NetworkInterfaceOwnerId) d.Set("public_ipv4_pool", eip.PublicIpv4Pool) diff --git a/internal/service/ec2/ec2_eip_data_source_test.go b/internal/service/ec2/ec2_eip_data_source_test.go index 651d7bd6765..380b8e98009 100644 --- a/internal/service/ec2/ec2_eip_data_source_test.go +++ b/internal/service/ec2/ec2_eip_data_source_test.go @@ -74,10 +74,11 @@ func TestAccEC2EIPDataSource_publicIP(t *testing.T) { { Config: testAccEIPDataSourceConfig_publicIP(rName), Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, names.AttrDomain, resourceName, names.AttrDomain), resource.TestCheckResourceAttrPair(dataSourceName, names.AttrID, resourceName, names.AttrID), + resource.TestCheckResourceAttrPair(dataSourceName, "ipam_pool_id", resourceName, "ipam_pool_id"), resource.TestCheckResourceAttrPair(dataSourceName, "public_dns", resourceName, "public_dns"), resource.TestCheckResourceAttrPair(dataSourceName, "public_ip", resourceName, "public_ip"), - resource.TestCheckResourceAttrPair(dataSourceName, names.AttrDomain, resourceName, names.AttrDomain), ), }, }, diff --git a/website/docs/d/eip.html.markdown b/website/docs/d/eip.html.markdown index bfcee229f45..a7ad75e0d19 100644 --- a/website/docs/d/eip.html.markdown +++ b/website/docs/d/eip.html.markdown @@ -71,6 +71,7 @@ This data source exports the following attributes in addition to the arguments a * `domain` - 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` - ID of the instance that the address is associated with (if any). +* `ipam_pool_id`- The ID of an IPAM pool which has an Amazon-provided or BYOIP public IPv4 CIDR provisioned to it. * `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` - Private IP address associated with the Elastic IP address.