Skip to content

Commit

Permalink
Merge pull request hashicorp#27274 from project0/feat/ipv6-associate-…
Browse files Browse the repository at this point in the history
…amazon-provided-pool

feat(vpc): Enable addition amazon provided ipv6 cidr
  • Loading branch information
ewbankkit authored Jul 26, 2024
2 parents 7346dee + 6d045a3 commit 528314a
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 18 deletions.
3 changes: 3 additions & 0 deletions .changelog/27274.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_vpc_ipv6_cidr_block_association: Add `assign_generated_ipv6_cidr_block` and `ipv6_pool` arguments
```
1 change: 1 addition & 0 deletions internal/service/ec2/exports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ var (
ResourceVPCEndpointService = resourceVPCEndpointService
ResourceVPCEndpointSubnetAssociation = resourceVPCEndpointSubnetAssociation
ResourceVPCIPv4CIDRBlockAssociation = resourceVPCIPv4CIDRBlockAssociation
ResourceVPCIPv6CIDRBlockAssociation = resourceVPCIPv6CIDRBlockAssociation
ResourceVPCPeeringConnection = resourceVPCPeeringConnection
ResourceVPNConnection = resourceVPNConnection
ResourceVPNConnectionRoute = resourceVPNConnectionRoute
Expand Down
48 changes: 33 additions & 15 deletions internal/service/ec2/vpc_ipv6_cidr_block_association.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,29 +42,39 @@ func resourceVPCIPv6CIDRBlockAssociation() *schema.Resource {
return nil
},
Schema: map[string]*schema.Schema{
"assign_generated_ipv6_cidr_block": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
ForceNew: true,
ConflictsWith: []string{"ipv6_pool", "ipv6_ipam_pool_id", "ipv6_cidr_block", "ipv6_netmask_length"},
},
"ipv6_cidr_block": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: validVPCIPv6CIDRBlock,
},
// ipam parameters are not required by the API but other usage mechanisms are not implemented yet. TODO ipv6 options:
// --amazon-provided-ipv6-cidr-block
// --ipv6-pool
"ipv6_ipam_pool_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ConflictsWith: []string{"assign_generated_ipv6_cidr_block", "ipv6_pool"},
},
"ipv6_netmask_length": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
ValidateFunc: validation.IntInSlice(vpcCIDRValidIPv6Netmasks),
ConflictsWith: []string{"ipv6_cidr_block"},
// This RequiredWith setting should be applied once L57 is completed
// RequiredWith: []string{"ipv6_ipam_pool_id"},
},
"ipv6_pool": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ConflictsWith: []string{"assign_generated_ipv6_cidr_block", "ipv6_ipam_pool_id"},
},
names.AttrVPCID: {
Type: schema.TypeString,
Expand All @@ -89,6 +99,10 @@ func resourceVPCIPv6CIDRBlockAssociationCreate(ctx context.Context, d *schema.Re
VpcId: aws.String(vpcID),
}

if v, ok := d.GetOk("assign_generated_ipv6_cidr_block"); ok {
input.AmazonProvidedIpv6CidrBlock = aws.Bool(v.(bool))
}

if v, ok := d.GetOk("ipv6_cidr_block"); ok {
input.Ipv6CidrBlock = aws.String(v.(string))
}
Expand All @@ -101,7 +115,10 @@ func resourceVPCIPv6CIDRBlockAssociationCreate(ctx context.Context, d *schema.Re
input.Ipv6NetmaskLength = aws.Int32(int32(v.(int)))
}

log.Printf("[DEBUG] Creating EC2 VPC IPv6 CIDR Block Association: %#v", input)
if v, ok := d.GetOk("ipv6_pool"); ok {
input.Ipv6Pool = aws.String(v.(string))
}

output, err := conn.AssociateVpcCidrBlock(ctx, input)

if err != nil {
Expand All @@ -110,9 +127,7 @@ func resourceVPCIPv6CIDRBlockAssociationCreate(ctx context.Context, d *schema.Re

d.SetId(aws.ToString(output.Ipv6CidrBlockAssociation.AssociationId))

_, err = waitVPCIPv6CIDRBlockAssociationCreated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate))

if err != nil {
if _, err := waitVPCIPv6CIDRBlockAssociationCreated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for EC2 VPC (%s) IPv6 CIDR block (%s) to become associated: %s", vpcID, d.Id(), err)
}

Expand All @@ -135,7 +150,12 @@ func resourceVPCIPv6CIDRBlockAssociationRead(ctx context.Context, d *schema.Reso
return sdkdiag.AppendErrorf(diags, "reading EC2 VPC IPv6 CIDR Block Association (%s): %s", d.Id(), err)
}

ipv6PoolID := aws.ToString(vpcIpv6CidrBlockAssociation.Ipv6Pool)
isAmazonIPv6Pool := ipv6PoolID == amazonIPv6PoolID

d.Set("assign_generated_ipv6_cidr_block", isAmazonIPv6Pool)
d.Set("ipv6_cidr_block", vpcIpv6CidrBlockAssociation.Ipv6CidrBlock)
d.Set("ipv6_pool", ipv6PoolID)
d.Set(names.AttrVPCID, vpc.VpcId)

return diags
Expand All @@ -158,9 +178,7 @@ func resourceVPCIPv6CIDRBlockAssociationDelete(ctx context.Context, d *schema.Re
return sdkdiag.AppendErrorf(diags, "deleting EC2 VPC IPv6 CIDR Block Association (%s): %s", d.Id(), err)
}

err = waitVPCIPv6CIDRBlockAssociationDeleted(ctx, conn, d.Id(), d.Timeout(schema.TimeoutDelete))

if err != nil {
if err := waitVPCIPv6CIDRBlockAssociationDeleted(ctx, conn, d.Id(), d.Timeout(schema.TimeoutDelete)); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for EC2 VPC IPv6 CIDR block (%s) to become disassociated: %s", d.Id(), err)
}

Expand Down
88 changes: 88 additions & 0 deletions internal/service/ec2/vpc_ipv6_cidr_block_association_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,82 @@ import (
"context"
"fmt"
"strings"
"testing"

"github.com/aws/aws-sdk-go-v2/aws"
awstypes "github.com/aws/aws-sdk-go-v2/service/ec2/types"
sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/names"
)

func TestAccVPCIPv6CIDRBlockAssociation_basic(t *testing.T) {
ctx := acctest.Context(t)
var associationSecondary, associationTertiary awstypes.VpcIpv6CidrBlockAssociation
resource1Name := "aws_vpc_ipv6_cidr_block_association.secondary_cidr"
resource2Name := "aws_vpc_ipv6_cidr_block_association.tertiary_cidr"
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: testAccCheckVPCIPv6CIDRBlockAssociationDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccVPCIPv6CIDRBlockAssociationConfig_amazonProvided(rName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckVPCIPv6CIDRBlockAssociationExists(ctx, resource1Name, &associationSecondary),
testAccCheckVPCIPv6CIDRBlockAssociationExists(ctx, resource2Name, &associationTertiary),
resource.TestCheckResourceAttr(resource1Name, "ipv6_pool", "Amazon"),
resource.TestCheckResourceAttr(resource2Name, "ipv6_pool", "Amazon"),
),
},
{
ResourceName: resource1Name,
ImportState: true,
ImportStateVerify: true,
},
{
ResourceName: resource2Name,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccVPCIPv6CIDRBlockAssociation_disappears(t *testing.T) {
ctx := acctest.Context(t)
var associationSecondary, associationTertiary awstypes.VpcIpv6CidrBlockAssociation
resource1Name := "aws_vpc_ipv6_cidr_block_association.secondary_cidr"
resource2Name := "aws_vpc_ipv6_cidr_block_association.tertiary_cidr"
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: testAccCheckVPCIPv6CIDRBlockAssociationDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccVPCIPv6CIDRBlockAssociationConfig_amazonProvided(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckVPCIPv6CIDRBlockAssociationExists(ctx, resource1Name, &associationSecondary),
testAccCheckVPCIPv6CIDRBlockAssociationExists(ctx, resource2Name, &associationTertiary),
acctest.CheckResourceDisappears(ctx, acctest.Provider, tfec2.ResourceVPCIPv6CIDRBlockAssociation(), resource1Name),
),
ExpectNonEmptyPlan: true,
},
},
})
}

func testAccCheckVPCIPv6CIDRBlockAssociationDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Client(ctx)
Expand Down Expand Up @@ -78,3 +143,26 @@ func testAccCheckVPCAssociationIPv6CIDRPrefix(association *awstypes.VpcIpv6CidrB
return nil
}
}

func testAccVPCIPv6CIDRBlockAssociationConfig_amazonProvided(rName string) string {
return fmt.Sprintf(`
resource "aws_vpc" "test" {
cidr_block = "10.1.0.0/16"
assign_generated_ipv6_cidr_block = true
tags = {
Name = %[1]q
}
}
resource "aws_vpc_ipv6_cidr_block_association" "secondary_cidr" {
vpc_id = aws_vpc.test.id
assign_generated_ipv6_cidr_block = true
}
resource "aws_vpc_ipv6_cidr_block_association" "tertiary_cidr" {
vpc_id = aws_vpc.test.id
assign_generated_ipv6_cidr_block = true
}
`, rName)
}
8 changes: 5 additions & 3 deletions website/docs/r/vpc_ipv6_cidr_block_association.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ resource "aws_vpc_ipv6_cidr_block_association" "test" {

This resource supports the following arguments:

* `ipv6_cidr_block` - (Optional) The IPv6 CIDR block for the VPC. CIDR can be explicitly set or it can be derived from IPAM using `ipv6_netmask_length`. This parameter is required if `ipv6_netmask_length` is not set and the IPAM pool does not have `allocation_default_netmask` set.
* `ipv6_ipam_pool_id` - (Required) The ID of an IPv6 IPAM pool you want to use for allocating this VPC's CIDR. IPAM is a VPC feature that you can use to automate your IP address management workflows including assigning, tracking, troubleshooting, and auditing IP addresses across AWS Regions and accounts.
* `ipv6_netmask_length` - (Optional) The netmask length of the IPv6 CIDR you want to allocate to this VPC. Requires specifying a `ipv6_ipam_pool_id`. This parameter is optional if the IPAM pool has `allocation_default_netmask` set, otherwise it or `cidr_block` are required
* `assign_generated_ipv6_cidr_block` - (Optional) Requests an Amazon-provided IPv6 CIDR block with a /56 prefix length for the VPC. You cannot specify the range of IPv6 addresses, or the size of the CIDR block. Default is `false`. Conflicts with `ipv6_pam_pool_id`, `ipv6_pool`, `ipv6_cidr_block` and `ipv6_netmask_length`.
* `ipv6_cidr_block` - (Optional) The IPv6 CIDR block for the VPC. CIDR can be explicitly set or it can be derived from IPAM using `ipv6_netmask_length`. This parameter is required if `ipv6_netmask_length` is not set and the IPAM pool does not have `allocation_default_netmask` set. Conflicts with `assign_generated_ipv6_cidr_block`.
* `ipv6_ipam_pool_id` - - (Optional) The ID of an IPv6 IPAM pool you want to use for allocating this VPC's CIDR. IPAM is a VPC feature that you can use to automate your IP address management workflows including assigning, tracking, troubleshooting, and auditing IP addresses across AWS Regions and accounts. Conflict with `assign_generated_ipv6_cidr_block` and `ipv6_ipam_pool_id`.
* `ipv6_netmask_length` - (Optional) The netmask length of the IPv6 CIDR you want to allocate to this VPC. Requires specifying a `ipv6_ipam_pool_id`. This parameter is optional if the IPAM pool has `allocation_default_netmask` set, otherwise it or `ipv6_cidr_block` are required. Conflicts with `assign_generated_ipv6_cidr_block` and `ipv6_ipam_pool_id`.
* `ipv6_pool` - (Optional) The ID of an IPv6 address pool from which to allocate the IPv6 CIDR block. Conflicts with `ipv6_pam_pool_id`, `ipv6_pool`.
* `vpc_id` - (Required) The ID of the VPC to make the association with.

## Timeouts
Expand Down

0 comments on commit 528314a

Please sign in to comment.