Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

data/aws_vpc_ipam_preview_next_cidr #22643

Merged
merged 5 commits into from
Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -484,6 +484,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.