Skip to content

Commit

Permalink
Merge pull request #22643 from drewmullen/f-preview-cidr-ds
Browse files Browse the repository at this point in the history
data/aws_vpc_ipam_preview_next_cidr
  • Loading branch information
ewbankkit authored Jan 20, 2022
2 parents fd7960a + 05c38f9 commit 5ed654d
Show file tree
Hide file tree
Showing 5 changed files with 315 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/22643.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-data-source
aws_vpc_ipam_preview_next_cidr
```
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ func Provider() *schema.Provider {
"aws_vpc_endpoint_service": ec2.DataSourceVPCEndpointService(),
"aws_vpc_endpoint": ec2.DataSourceVPCEndpoint(),
"aws_vpc_ipam_pool": ec2.DataSourceVPCIpamPool(),
"aws_vpc_ipam_preview_next_cidr": ec2.DataSourceVPCIpamPreviewNextCidr(),
"aws_vpc_peering_connection": ec2.DataSourceVPCPeeringConnection(),
"aws_vpc_peering_connections": ec2.DataSourceVPCPeeringConnections(),
"aws_vpc": ec2.DataSourceVPC(),
Expand Down
91 changes: 91 additions & 0 deletions internal/service/ec2/vpc_ipam_preview_next_cidr_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
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/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

func DataSourceVPCIpamPreviewNextCidr() *schema.Resource {
return &schema.Resource{
Read: dataSourceVPCIpamPreviewNextCidrRead,

Schema: map[string]*schema.Schema{
"cidr": {
Type: schema.TypeString,
Computed: true,
},
"disallowed_cidrs": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.Any(
verify.ValidIPv4CIDRNetworkAddress,
// Follow the numbers used for netmask_length
validation.IsCIDRNetwork(0, 32),
),
},
},
"ipam_pool_id": {
Type: schema.TypeString,
Required: true,
},
"netmask_length": {
// Possible netmask lengths for IPv4 addresses are 0 - 32.
// AllocateIpamPoolCidr API
// - If there is no DefaultNetmaskLength allocation rule set on the pool,
// you must specify either the NetmaskLength or the CIDR.
// - If the DefaultNetmaskLength allocation rule is set on the pool,
// you can specify either the NetmaskLength or the CIDR and the
// DefaultNetmaskLength allocation rule will be ignored.
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(0, 32),
},
},
}
}

func dataSourceVPCIpamPreviewNextCidrRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).EC2Conn
poolId := d.Get("ipam_pool_id").(string)

input := &ec2.AllocateIpamPoolCidrInput{
ClientToken: aws.String(resource.UniqueId()),
IpamPoolId: aws.String(poolId),
PreviewNextCidr: aws.Bool(true),
}

if v, ok := d.GetOk("disallowed_cidrs"); ok && v.(*schema.Set).Len() > 0 {
input.DisallowedCidrs = flex.ExpandStringSet(v.(*schema.Set))
}

if v, ok := d.GetOk("netmask_length"); ok {
input.NetmaskLength = aws.Int64(int64(v.(int)))
}

output, err := conn.AllocateIpamPoolCidr(input)

if err != nil {
return fmt.Errorf("Error previewing next cidr from IPAM pool (%s): %w", d.Get("ipam_pool_id").(string), err)
}

if output == nil || output.IpamPoolAllocation == nil {
return fmt.Errorf("error previewing next cidr from ipam pool (%s): empty response", poolId)
}

cidr := output.IpamPoolAllocation.Cidr

d.Set("cidr", cidr)
d.SetId(encodeVPCIpamPreviewNextCidrID(aws.StringValue(cidr), poolId))

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

import (
"fmt"
"testing"

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

func TestAccDataSourceVPCIpamPreviewNextCidr_ipv4Basic(t *testing.T) {
datasourceName := "data.aws_vpc_ipam_preview_next_cidr.test"
netmaskLength := "28"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t); testAccIPAMPreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: testAccDataSourceVPCIpamPreviewNextCidrIpv4Basic(netmaskLength),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(datasourceName, "cidr"),
resource.TestCheckResourceAttrPair(datasourceName, "ipam_pool_id", "aws_vpc_ipam_pool.test", "id"),
resource.TestCheckResourceAttr(datasourceName, "netmask_length", netmaskLength),
),
},
},
})
}

func TestAccDataSourceVPCIpamPreviewNextCidr_ipv4Allocated(t *testing.T) {
datasourceName := "data.aws_vpc_ipam_preview_next_cidr.test"
netmaskLength := "28"
allocatedCidr := "172.2.0.0/28"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t); testAccIPAMPreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: testAccDataSourceVPCIpamPreviewNextCidrIpv4Basic(netmaskLength),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(datasourceName, "cidr", allocatedCidr),
resource.TestCheckResourceAttrPair(datasourceName, "ipam_pool_id", "aws_vpc_ipam_pool.test", "id"),
resource.TestCheckResourceAttr(datasourceName, "netmask_length", netmaskLength),
),
},
{
Config: testAccDataSourceVPCIpamPreviewNextCidrIpv4Allocated(netmaskLength),
Check: resource.ComposeTestCheckFunc(
// cidr should not change even after allocation
resource.TestCheckResourceAttr(datasourceName, "cidr", allocatedCidr),
resource.TestCheckResourceAttrPair(datasourceName, "ipam_pool_id", "aws_vpc_ipam_pool.test", "id"),
resource.TestCheckResourceAttr(datasourceName, "netmask_length", netmaskLength),
),
},
},
})
}

func TestAccDataSourceVPCIpamPreviewNextCidr_ipv4DisallowedCidr(t *testing.T) {
datasourceName := "data.aws_vpc_ipam_preview_next_cidr.test"
disallowedCidr := "172.2.0.0/28"
netmaskLength := "28"
expectedCidr := "172.2.0.16/28"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t); testAccIPAMPreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: testAccDataSourceVPCIpamPreviewNextCidrIpv4DisallowedCidr(netmaskLength, disallowedCidr),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(datasourceName, "cidr", expectedCidr),
resource.TestCheckResourceAttr(datasourceName, "disallowed_cidrs.#", "1"),
resource.TestCheckResourceAttr(datasourceName, "disallowed_cidrs.0", disallowedCidr),
resource.TestCheckResourceAttrPair(datasourceName, "ipam_pool_id", "aws_vpc_ipam_pool.test", "id"),
resource.TestCheckResourceAttr(datasourceName, "netmask_length", netmaskLength),
),
},
},
})
}

const testAccDataSourceVPCIpamPreviewNextCidrIpv4Base = `
data "aws_region" "current" {}
resource "aws_vpc_ipam" "test" {
description = "test"
operating_regions {
region_name = data.aws_region.current.name
}
}
resource "aws_vpc_ipam_pool" "test" {
address_family = "ipv4"
ipam_scope_id = aws_vpc_ipam.test.private_default_scope_id
locale = data.aws_region.current.name
}
resource "aws_vpc_ipam_pool_cidr" "test" {
ipam_pool_id = aws_vpc_ipam_pool.test.id
cidr = "172.2.0.0/24"
}
`

func testAccDataSourceVPCIpamPreviewNextCidrIpv4Basic(netmaskLength string) string {
return acctest.ConfigCompose(
testAccDataSourceVPCIpamPreviewNextCidrIpv4Base,
fmt.Sprintf(`
data "aws_vpc_ipam_preview_next_cidr" "test" {
ipam_pool_id = aws_vpc_ipam_pool.test.id
netmask_length = %[1]q
depends_on = [
aws_vpc_ipam_pool_cidr.test
]
}
`, netmaskLength))
}

func testAccDataSourceVPCIpamPreviewNextCidrIpv4Allocated(netmaskLength string) string {
return acctest.ConfigCompose(
testAccDataSourceVPCIpamPreviewNextCidrIpv4Base,
fmt.Sprintf(`
data "aws_vpc_ipam_preview_next_cidr" "test" {
ipam_pool_id = aws_vpc_ipam_pool.test.id
netmask_length = %[1]q
depends_on = [
aws_vpc_ipam_pool_cidr.test
]
}
resource "aws_vpc_ipam_pool_cidr_allocation" "test" {
ipam_pool_id = aws_vpc_ipam_pool.test.id
cidr = data.aws_vpc_ipam_preview_next_cidr.test.cidr
lifecycle {
ignore_changes = [cidr]
}
}
`, netmaskLength))
}

func testAccDataSourceVPCIpamPreviewNextCidrIpv4DisallowedCidr(netmaskLength, disallowedCidr string) string {
return testAccDataSourceVPCIpamPreviewNextCidrIpv4Base + fmt.Sprintf(`
data "aws_vpc_ipam_preview_next_cidr" "test" {
ipam_pool_id = aws_vpc_ipam_pool.test.id
netmask_length = %[1]q
disallowed_cidrs = [
%[2]q
]
depends_on = [
aws_vpc_ipam_pool_cidr.test
]
}
`, netmaskLength, disallowedCidr)
}
52 changes: 52 additions & 0 deletions website/docs/d/vpc_ipam_preview_next_cidr.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
subcategory: "VPC"
layout: "aws"
page_title: "AWS: aws_vpc_ipam_preview_next_cidr"
description: |-
Previews a CIDR from an IPAM address pool.
---

# Data Source: aws_vpc_ipam_preview_next_cidr

Previews a CIDR from an IPAM address pool. Only works for private IPv4.

~> **NOTE:** This functionality is also encapsulated in a resource sharing the same name. The data source can be used when you need to use the cidr in a calculation of the same Root module, `count` for example. However, once a cidr range has been allocated that was previewed, the next refresh will find a **new** cidr and may force new resources downstream. Make sure to use Terraform's lifecycle `ignore_changes` policy if this is undesirable.

## Example Usage

Basic usage:

```terraform
data "aws_vpc_ipam_preview_next_cidr" "test" {
ipam_pool_id = aws_vpc_ipam_pool.test.id
netmask_length = 28
depends_on = [
aws_vpc_ipam_pool_cidr.test
]
}
resource "aws_vpc_ipam_pool_cidr_allocation" "test" {
ipam_pool_id = aws_vpc_ipam_pool.test.id
cidr = data.aws_vpc_ipam_preview_next_cidr.test.cidr
lifecycle {
ignore_changes = [cidr]
}
}
```

## Argument Reference

The following arguments are supported:

* `disallowed_cidrs` - (Optional) Exclude a particular CIDR range from being returned by the pool.
* `ipam_pool_id` - (Required) The ID of the pool to which you want to assign a CIDR.
* `netmask_length` - (Optional) The netmask length of the CIDR you would like to preview from the IPAM pool.

## Attributes Reference

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

* `cidr` - The previewed CIDR from the pool.
* `id` - The ID of the preview.

0 comments on commit 5ed654d

Please sign in to comment.