From 23a1c4c05d4c8fdfce0aff5dab02d04d5b8d9e40 Mon Sep 17 00:00:00 2001 From: drewmullen Date: Tue, 4 Oct 2022 23:22:09 -0400 Subject: [PATCH 1/7] initial commit --- internal/provider/provider.go | 1 + internal/service/ec2/find.go | 24 +++ .../service/ec2/ipam_pools_data_source.go | 169 ++++++++++++++++++ .../ec2/ipam_pools_data_source_test.go | 123 +++++++++++++ website/docs/d/vpc_ipam_pools.html.markdown | 79 ++++++++ 5 files changed, 396 insertions(+) create mode 100644 internal/service/ec2/ipam_pools_data_source.go create mode 100644 internal/service/ec2/ipam_pools_data_source_test.go create mode 100644 website/docs/d/vpc_ipam_pools.html.markdown diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 7f0942e6dac2..c646ad6c3cfb 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -597,6 +597,7 @@ func New(_ context.Context) (*schema.Provider, error) { "aws_vpc_endpoint_service": ec2.DataSourceVPCEndpointService(), "aws_vpc_endpoint": ec2.DataSourceVPCEndpoint(), "aws_vpc_ipam_pool": ec2.DataSourceIPAMPool(), + "aws_vpc_ipam_pools": ec2.DataSourceIPAMPools(), "aws_vpc_ipam_pool_cidrs": ec2.DataSourceIPAMPoolCIDRs(), "aws_vpc_ipam_preview_next_cidr": ec2.DataSourceIPAMPreviewNextCIDR(), "aws_vpc_peering_connection": ec2.DataSourceVPCPeeringConnection(), diff --git a/internal/service/ec2/find.go b/internal/service/ec2/find.go index df9c0f660622..ba6160364f15 100644 --- a/internal/service/ec2/find.go +++ b/internal/service/ec2/find.go @@ -4968,6 +4968,30 @@ func FindIPAMPoolCIDRs(conn *ec2.EC2, input *ec2.GetIpamPoolCidrsInput) ([]*ec2. return output, nil } +func FindIPAMPools(conn *ec2.EC2, input *ec2.DescribeIpamPoolsInput) ([]*ec2.IpamPool, error) { + var output []*ec2.IpamPool + + err := conn.DescribeIpamPoolsPages(input, func(page *ec2.DescribeIpamPoolsOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + for _, v := range page.IpamPools { + if v != nil { + output = append(output, v) + } + } + + return !lastPage + }) + + if err != nil { + return nil, err + } + + return output, nil +} + func FindKeyPair(conn *ec2.EC2, input *ec2.DescribeKeyPairsInput) (*ec2.KeyPairInfo, error) { output, err := FindKeyPairs(conn, input) diff --git a/internal/service/ec2/ipam_pools_data_source.go b/internal/service/ec2/ipam_pools_data_source.go new file mode 100644 index 000000000000..128c3bc7d1b6 --- /dev/null +++ b/internal/service/ec2/ipam_pools_data_source.go @@ -0,0 +1,169 @@ +package ec2 + +import ( + "strings" + "time" + + "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" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +) + +func DataSourceIPAMPools() *schema.Resource { + return &schema.Resource{ + Read: dataSourceIPAMPoolsRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(20 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "filter": DataSourceFiltersSchema(), + "ipam_pools": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ipam_pool_id": { + Type: schema.TypeString, + Computed: true, + }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "address_family": { + Type: schema.TypeString, + Computed: true, + }, + "publicly_advertisable": { + Type: schema.TypeBool, + Computed: true, + }, + "allocation_default_netmask_length": { + Type: schema.TypeInt, + Computed: true, + }, + "allocation_max_netmask_length": { + Type: schema.TypeInt, + Computed: true, + }, + "allocation_min_netmask_length": { + Type: schema.TypeInt, + Computed: true, + }, + "allocation_resource_tags": tftags.TagsSchemaComputed(), + "auto_import": { + Type: schema.TypeBool, + Computed: true, + }, + "aws_service": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "id": { + Type: schema.TypeString, + Optional: true, + }, + "ipam_scope_id": { + Type: schema.TypeString, + Computed: true, + }, + "ipam_scope_type": { + Type: schema.TypeString, + Computed: true, + }, + "locale": { + Type: schema.TypeString, + Computed: true, + }, + "pool_depth": { + Type: schema.TypeInt, + Computed: true, + }, + "source_ipam_pool_id": { + Type: schema.TypeString, + Computed: true, + }, + "state": { + Type: schema.TypeString, + Computed: true, + }, + "tags": tftags.TagsSchemaComputed(), + }, + }, + }, + }, + } +} + +func dataSourceIPAMPoolsRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*conns.AWSClient).EC2Conn + ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig + + input := &ec2.DescribeIpamPoolsInput{} + + filters, filtersOk := d.GetOk("filter") + if filtersOk { + input.Filters = BuildFiltersDataSource(filters.(*schema.Set)) + } + + pools, err := FindIPAMPools(conn, input) + + if err != nil { + return err + } + + if len(pools) == 0 || pools[0] == nil { + return tfresource.SingularDataSourceFindError("EC2 VPC IPAM POOLS", tfresource.NewEmptyResultError(input)) + } + + d.Set("ipam_pools", flattenIPAMPools(pools, ignoreTagsConfig)) + // pool = output.IpamPools[0] + + d.SetId(meta.(*conns.AWSClient).Region) + + return nil +} + +func flattenIPAMPools(c []*ec2.IpamPool, ignoreTagsConfig *tftags.IgnoreConfig) []interface{} { + pools := []interface{}{} + for _, pool := range c { + pools = append(pools, flattenIPAMPool(pool, ignoreTagsConfig)) + } + return pools +} + +func flattenIPAMPool(p *ec2.IpamPool, ignoreTagsConfig *tftags.IgnoreConfig) map[string]interface{} { + pool := make(map[string]interface{}) + + pool["address_family"] = aws.StringValue(p.AddressFamily) + pool["allocation_default_netmask_length"] = aws.Int64Value(p.AllocationDefaultNetmaskLength) + pool["allocation_max_netmask_length"] = aws.Int64Value(p.AllocationMaxNetmaskLength) + pool["allocation_min_netmask_length"] = aws.Int64Value(p.AllocationMinNetmaskLength) + pool["allocation_resource_tags"] = KeyValueTags(tagsFromIPAMAllocationTags(p.AllocationResourceTags)).Map() + pool["arn"] = aws.StringValue(p.IpamPoolArn) + pool["auto_import"] = aws.BoolValue(p.AutoImport) + pool["aws_service"] = aws.StringValue(p.AwsService) + pool["description"] = aws.StringValue(p.Description) + pool["ipam_scope_id"] = strings.Split(aws.StringValue(p.IpamScopeArn), "/")[1] + pool["ipam_scope_type"] = aws.StringValue(p.IpamScopeType) + pool["locale"] = aws.StringValue(p.Locale) + pool["pool_depth"] = aws.Int64Value(p.PoolDepth) + pool["publicly_advertisable"] = aws.BoolValue(p.PubliclyAdvertisable) + pool["source_ipam_pool_id"] = aws.StringValue(p.SourceIpamPoolId) + pool["state"] = aws.StringValue(p.State) + + if v := p.Tags; v != nil { + pool["tags"] = KeyValueTags(v).IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Map() + } + + return pool +} diff --git a/internal/service/ec2/ipam_pools_data_source_test.go b/internal/service/ec2/ipam_pools_data_source_test.go new file mode 100644 index 000000000000..9b593bcb61bc --- /dev/null +++ b/internal/service/ec2/ipam_pools_data_source_test.go @@ -0,0 +1,123 @@ +package ec2_test + +import ( + "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 TestAccIPAMPoolsDataSource_basic(t *testing.T) { + dataSourceName := "data.aws_vpc_ipam_pools.test" + dataSourceNameTwo := "data.aws_vpc_ipam_pools.testtwo" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t); testAccIPAMPreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccIPAMPoolsDataSourceConfig_Basic, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "ipam_pools.#", "1"), + ), + }, + { + Config: testAccIPAMPoolsDataSourceConfig_BasicTwoPools, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "ipam_pools.#", "3"), + resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.#", "1"), + resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.allocation_resource_tags.test", "3"), + resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.allocation_default_netmask_length", "32"), + resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.allocation_max_netmask_length", "32"), + resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.allocation_min_netmask_length", "32"), + resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.description", "testthree"), + + resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.tags.tagtest", "3"), + ), + }, + }, + }) +} + +var testAccIPAMPoolsDataSourceConfig_Basic = acctest.ConfigCompose(testAccIPAMPoolConfig_base, ` +resource "aws_vpc_ipam_pool" "test" { + address_family = "ipv4" + ipam_scope_id = aws_vpc_ipam.test.private_default_scope_id + auto_import = true + allocation_default_netmask_length = 32 + allocation_max_netmask_length = 32 + allocation_min_netmask_length = 32 + allocation_resource_tags = { + test = "1" + } + description = "test" +} + +data "aws_vpc_ipam_pools" "test" { + depends_on = [ + aws_vpc_ipam_pool.test + ] +} +`) + +var testAccIPAMPoolsDataSourceConfig_BasicTwoPools = acctest.ConfigCompose(testAccIPAMPoolConfig_base, ` +resource "aws_vpc_ipam_pool" "test" { + address_family = "ipv4" + ipam_scope_id = aws_vpc_ipam.test.private_default_scope_id + auto_import = true + allocation_default_netmask_length = 32 + allocation_max_netmask_length = 32 + allocation_min_netmask_length = 32 + allocation_resource_tags = { + test = "1" + } + description = "test" +} + +resource "aws_vpc_ipam_pool" "testtwo" { + address_family = "ipv4" + ipam_scope_id = aws_vpc_ipam.test.private_default_scope_id + allocation_resource_tags = { + test = "2" + } + description = "testtwo" + } + + resource "aws_vpc_ipam_pool" "testthree" { + address_family = "ipv4" + ipam_scope_id = aws_vpc_ipam.test.private_default_scope_id + allocation_default_netmask_length = 32 + allocation_max_netmask_length = 32 + allocation_min_netmask_length = 32 + allocation_resource_tags = { + test = "3" + } + description = "testthree" + tags = { + tagtest = 3 + } + } + +data "aws_vpc_ipam_pools" "test" { + depends_on = [ + aws_vpc_ipam_pool.test, + aws_vpc_ipam_pool.testtwo, + aws_vpc_ipam_pool.testthree + ] +} + +data "aws_vpc_ipam_pools" "testtwo" { + filter { + name = "description" + values = ["*three*"] + } + + depends_on = [ + aws_vpc_ipam_pool.test, + aws_vpc_ipam_pool.testtwo, + aws_vpc_ipam_pool.testthree + ] + } +`) diff --git a/website/docs/d/vpc_ipam_pools.html.markdown b/website/docs/d/vpc_ipam_pools.html.markdown new file mode 100644 index 000000000000..69a49f8d4a19 --- /dev/null +++ b/website/docs/d/vpc_ipam_pools.html.markdown @@ -0,0 +1,79 @@ +--- +subcategory: "VPC IPAM (IP Address Manager)" +layout: "aws" +page_title: "AWS: aws_vpc_ipam_pools" +description: |- + Returns details about the first IPAM pool that matches search parameters provided. +--- + +# Data Source: aws_vpc_ipam_pools + +`aws_vpc_ipam_pools` provides details IPAM pools. + +This resource can prove useful when an ipam pool was created in another root +module and you need the pool's id as an input variable. For example, pools +can be shared via RAM and used to create vpcs with CIDRs from that pool. + +## Example Usage + +The following example shows an account that has only 1 pool, perhaps shared +via RAM, and using that pool id to create a VPC with a CIDR derived from +AWS IPAM. + +```terraform +data "aws_vpc_ipam_pools" "test" { + filter { + name = "description" + values = ["*test*"] + } + + filter { + name = "address-family" + values = ["ipv4"] + } +} +``` + +## Argument Reference + +The arguments of this data source act as filters for querying the available +IPAM Pools in the current region. + +* `filter` - Custom filter block as described below. + +## Attributes Reference + +All of the argument attributes except `filter` blocks are also exported as +result attributes. This data source will complete the data by populating +any fields that are not included in the configuration with the data for +the selected VPC. + +The following attribute is additionally exported: + +* `ipam_pools` - List of IPAM pools and their attributes. See below for details + +### ipam_pools + +The following attributes are available on each pool entry found. + +* `address_family` - IP protocol assigned to this pool. +* `publicly_advertisable` - Defines whether or not IPv6 pool space is publicly ∂advertisable over the internet. +* `allocation_default_netmask_length` - A default netmask length for allocations added to this pool. If, for example, the CIDR assigned to this pool is 10.0.0.0/8 and you enter 16 here, new allocations will default to 10.0.0.0/16. +* `allocation_max_netmask_length` - The maximum netmask length that will be required for CIDR allocations in this pool. +* `allocation_min_netmask_length` - The minimum netmask length that will be required for CIDR allocations in this pool. +* `allocation_resource_tags` - Tags that are required to create resources in using this pool. +* `arn` - ARN of the pool +* `auto_import` - If enabled, IPAM will continuously look for resources within the CIDR range of this pool and automatically import them as allocations into your IPAM. +* `aws_service` - Limits which service in AWS that the pool can be used in. "ec2", for example, allows users to use space for Elastic IP addresses and VPCs. +* `description` - Description for the IPAM pool. +* `id` - ID of the IPAM pool. +* `ipam_scope_id` - ID of the scope the pool belongs to. +* `locale` - Locale is the Region where your pool is available for allocations. You can only create pools with locales that match the operating Regions of the IPAM. You can only create VPCs from a pool whose locale matches the VPC's Region. +* `source_ipam_pool_id` - ID of the source IPAM pool. +* `tags` - Map of tags to assigned to the resource. + +## Timeouts + +[Configuration options](https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts): + +- `read` - (Default `20m`) From 8cfeda17bfb8dc563f1be72f89208c8760a7e7d2 Mon Sep 17 00:00:00 2001 From: drewmullen Date: Tue, 4 Oct 2022 23:23:28 -0400 Subject: [PATCH 2/7] terrafmt --- .../ec2/ipam_pools_data_source_test.go | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/internal/service/ec2/ipam_pools_data_source_test.go b/internal/service/ec2/ipam_pools_data_source_test.go index 9b593bcb61bc..605e960b5c04 100644 --- a/internal/service/ec2/ipam_pools_data_source_test.go +++ b/internal/service/ec2/ipam_pools_data_source_test.go @@ -57,7 +57,7 @@ resource "aws_vpc_ipam_pool" "test" { data "aws_vpc_ipam_pools" "test" { depends_on = [ - aws_vpc_ipam_pool.test + aws_vpc_ipam_pool.test ] } `) @@ -77,47 +77,47 @@ resource "aws_vpc_ipam_pool" "test" { } resource "aws_vpc_ipam_pool" "testtwo" { - address_family = "ipv4" - ipam_scope_id = aws_vpc_ipam.test.private_default_scope_id - allocation_resource_tags = { - test = "2" - } - description = "testtwo" + address_family = "ipv4" + ipam_scope_id = aws_vpc_ipam.test.private_default_scope_id + allocation_resource_tags = { + test = "2" } + description = "testtwo" +} - resource "aws_vpc_ipam_pool" "testthree" { - address_family = "ipv4" - ipam_scope_id = aws_vpc_ipam.test.private_default_scope_id - allocation_default_netmask_length = 32 - allocation_max_netmask_length = 32 - allocation_min_netmask_length = 32 - allocation_resource_tags = { - test = "3" - } - description = "testthree" - tags = { - tagtest = 3 - } +resource "aws_vpc_ipam_pool" "testthree" { + address_family = "ipv4" + ipam_scope_id = aws_vpc_ipam.test.private_default_scope_id + allocation_default_netmask_length = 32 + allocation_max_netmask_length = 32 + allocation_min_netmask_length = 32 + allocation_resource_tags = { + test = "3" } + description = "testthree" + tags = { + tagtest = 3 + } +} data "aws_vpc_ipam_pools" "test" { depends_on = [ - aws_vpc_ipam_pool.test, - aws_vpc_ipam_pool.testtwo, - aws_vpc_ipam_pool.testthree + aws_vpc_ipam_pool.test, + aws_vpc_ipam_pool.testtwo, + aws_vpc_ipam_pool.testthree ] } data "aws_vpc_ipam_pools" "testtwo" { - filter { - name = "description" - values = ["*three*"] - } - - depends_on = [ - aws_vpc_ipam_pool.test, - aws_vpc_ipam_pool.testtwo, - aws_vpc_ipam_pool.testthree - ] + filter { + name = "description" + values = ["*three*"] } + + depends_on = [ + aws_vpc_ipam_pool.test, + aws_vpc_ipam_pool.testtwo, + aws_vpc_ipam_pool.testthree + ] +} `) From a39dc0214642ee3deb5c456e415fb176b4cd2230 Mon Sep 17 00:00:00 2001 From: drewmullen Date: Tue, 4 Oct 2022 23:26:50 -0400 Subject: [PATCH 3/7] new ds vpc_ipam_pools --- .changelog/27101.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/27101.txt diff --git a/.changelog/27101.txt b/.changelog/27101.txt new file mode 100644 index 000000000000..f6b206250157 --- /dev/null +++ b/.changelog/27101.txt @@ -0,0 +1,3 @@ +```release-note:new-data-source +aws_vpc_ipam_pools +``` From 96f8518a6b4505a5416b2c882715e6e82544b18e Mon Sep 17 00:00:00 2001 From: drewmullen Date: Tue, 4 Oct 2022 23:28:19 -0400 Subject: [PATCH 4/7] semgrep --- internal/service/ec2/ipam_pools_data_source_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/service/ec2/ipam_pools_data_source_test.go b/internal/service/ec2/ipam_pools_data_source_test.go index 605e960b5c04..a337bc99e66d 100644 --- a/internal/service/ec2/ipam_pools_data_source_test.go +++ b/internal/service/ec2/ipam_pools_data_source_test.go @@ -18,13 +18,13 @@ func TestAccIPAMPoolsDataSource_basic(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccIPAMPoolsDataSourceConfig_Basic, + Config: testAccIPAMPoolsDataSourceConfig_basic, Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(dataSourceName, "ipam_pools.#", "1"), ), }, { - Config: testAccIPAMPoolsDataSourceConfig_BasicTwoPools, + Config: testAccIPAMPoolsDataSourceConfig_basicTwoPools, Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(dataSourceName, "ipam_pools.#", "3"), resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.#", "1"), @@ -41,7 +41,7 @@ func TestAccIPAMPoolsDataSource_basic(t *testing.T) { }) } -var testAccIPAMPoolsDataSourceConfig_Basic = acctest.ConfigCompose(testAccIPAMPoolConfig_base, ` +var testAccIPAMPoolsDataSourceConfig_basic = acctest.ConfigCompose(testAccIPAMPoolConfig_base, ` resource "aws_vpc_ipam_pool" "test" { address_family = "ipv4" ipam_scope_id = aws_vpc_ipam.test.private_default_scope_id @@ -62,7 +62,7 @@ data "aws_vpc_ipam_pools" "test" { } `) -var testAccIPAMPoolsDataSourceConfig_BasicTwoPools = acctest.ConfigCompose(testAccIPAMPoolConfig_base, ` +var testAccIPAMPoolsDataSourceConfig_basicTwoPools = acctest.ConfigCompose(testAccIPAMPoolConfig_base, ` resource "aws_vpc_ipam_pool" "test" { address_family = "ipv4" ipam_scope_id = aws_vpc_ipam.test.private_default_scope_id From 50a997ff3e3d855b54fed74e684429b85ae0c5cf Mon Sep 17 00:00:00 2001 From: drewmullen Date: Wed, 5 Oct 2022 06:45:04 -0400 Subject: [PATCH 5/7] rm leftover comment --- internal/service/ec2/ipam_pools_data_source.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/service/ec2/ipam_pools_data_source.go b/internal/service/ec2/ipam_pools_data_source.go index 128c3bc7d1b6..a8efaa8b6239 100644 --- a/internal/service/ec2/ipam_pools_data_source.go +++ b/internal/service/ec2/ipam_pools_data_source.go @@ -126,7 +126,6 @@ func dataSourceIPAMPoolsRead(d *schema.ResourceData, meta interface{}) error { } d.Set("ipam_pools", flattenIPAMPools(pools, ignoreTagsConfig)) - // pool = output.IpamPools[0] d.SetId(meta.(*conns.AWSClient).Region) From e22e759b3ff03ebecf75409a2131cd42a0744ddb Mon Sep 17 00:00:00 2001 From: drewmullen Date: Mon, 10 Oct 2022 08:20:51 -0400 Subject: [PATCH 6/7] test each attribute --- .../service/ec2/ipam_pools_data_source.go | 39 ++++++++++++------- .../ec2/ipam_pools_data_source_test.go | 26 ++++++++++--- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/internal/service/ec2/ipam_pools_data_source.go b/internal/service/ec2/ipam_pools_data_source.go index a8efaa8b6239..dc14005a7844 100644 --- a/internal/service/ec2/ipam_pools_data_source.go +++ b/internal/service/ec2/ipam_pools_data_source.go @@ -2,7 +2,6 @@ package ec2 import ( "strings" - "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" @@ -16,50 +15,46 @@ func DataSourceIPAMPools() *schema.Resource { return &schema.Resource{ Read: dataSourceIPAMPoolsRead, - Timeouts: &schema.ResourceTimeout{ - Read: schema.DefaultTimeout(20 * time.Minute), - }, - Schema: map[string]*schema.Schema{ "filter": DataSourceFiltersSchema(), + // computed "ipam_pools": { Type: schema.TypeSet, Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "ipam_pool_id": { - Type: schema.TypeString, - Computed: true, - }, "arn": { Type: schema.TypeString, Computed: true, }, + "address_family": { Type: schema.TypeString, Computed: true, }, - "publicly_advertisable": { - Type: schema.TypeBool, - Computed: true, - }, + "allocation_default_netmask_length": { Type: schema.TypeInt, Computed: true, }, + "allocation_max_netmask_length": { Type: schema.TypeInt, Computed: true, }, + "allocation_min_netmask_length": { Type: schema.TypeInt, Computed: true, }, + "allocation_resource_tags": tftags.TagsSchemaComputed(), + "auto_import": { Type: schema.TypeBool, Computed: true, }, + "aws_service": { Type: schema.TypeString, Computed: true, @@ -68,34 +63,52 @@ func DataSourceIPAMPools() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "id": { Type: schema.TypeString, Optional: true, }, + "ipam_scope_id": { Type: schema.TypeString, Computed: true, }, + "ipam_scope_type": { Type: schema.TypeString, Computed: true, }, + + "ipam_pool_id": { + Type: schema.TypeString, + Computed: true, + }, + "locale": { Type: schema.TypeString, Computed: true, }, + + "publicly_advertisable": { + Type: schema.TypeBool, + Computed: true, + }, + "pool_depth": { Type: schema.TypeInt, Computed: true, }, + "source_ipam_pool_id": { Type: schema.TypeString, Computed: true, }, + "state": { Type: schema.TypeString, Computed: true, }, + "tags": tftags.TagsSchemaComputed(), }, }, diff --git a/internal/service/ec2/ipam_pools_data_source_test.go b/internal/service/ec2/ipam_pools_data_source_test.go index a337bc99e66d..a2668132b8cf 100644 --- a/internal/service/ec2/ipam_pools_data_source_test.go +++ b/internal/service/ec2/ipam_pools_data_source_test.go @@ -11,6 +11,7 @@ import ( func TestAccIPAMPoolsDataSource_basic(t *testing.T) { dataSourceName := "data.aws_vpc_ipam_pools.test" dataSourceNameTwo := "data.aws_vpc_ipam_pools.testtwo" + resourceName := "aws_vpc_ipam_pool.testthree" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t); testAccIPAMPreCheck(t) }, @@ -26,14 +27,26 @@ func TestAccIPAMPoolsDataSource_basic(t *testing.T) { { Config: testAccIPAMPoolsDataSourceConfig_basicTwoPools, Check: resource.ComposeAggregateTestCheckFunc( + // DS 1 finds all 3 pools resource.TestCheckResourceAttr(dataSourceName, "ipam_pools.#", "3"), - resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.#", "1"), - resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.allocation_resource_tags.test", "3"), - resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.allocation_default_netmask_length", "32"), - resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.allocation_max_netmask_length", "32"), - resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.allocation_min_netmask_length", "32"), - resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.description", "testthree"), + // DS 2 filters on 1 specific pool to validate attributes + resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.#", "1"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.address_family", resourceName, "address_family"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.allocation_default_netmask_length", resourceName, "allocation_default_netmask_length"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.allocation_max_netmask_length", resourceName, "allocation_max_netmask_length"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.allocation_min_netmask_length", resourceName, "allocation_min_netmask_length"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.allocation_resource_tags.%", resourceName, "allocation_resource_tags.%"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.auto_import", resourceName, "auto_import"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.description", resourceName, "description"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.aws_service", resourceName, "aws_service"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.ipam_scope_id", resourceName, "ipam_scope_id"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.ipam_scope_type", resourceName, "ipam_scope_type"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.locale", resourceName, "locale"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.pool_depth", resourceName, "pool_depth"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.publicly_advertisable", resourceName, "publicly_advertisable"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.source_ipam_pool_id", resourceName, "source_ipam_pool_id"), resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.tags.tagtest", "3"), ), }, @@ -91,6 +104,7 @@ resource "aws_vpc_ipam_pool" "testthree" { allocation_default_netmask_length = 32 allocation_max_netmask_length = 32 allocation_min_netmask_length = 32 + auto_import = true allocation_resource_tags = { test = "3" } From 406b3791e032d59de48eaf3880266a3a0e7abd38 Mon Sep 17 00:00:00 2001 From: drewmullen Date: Mon, 10 Oct 2022 09:39:08 -0400 Subject: [PATCH 7/7] pr feedback --- .../service/ec2/ipam_pools_data_source.go | 7 +---- .../ec2/ipam_pools_data_source_test.go | 31 ++++++++++++++++++- website/docs/d/vpc_ipam_pools.html.markdown | 25 +++------------ 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/internal/service/ec2/ipam_pools_data_source.go b/internal/service/ec2/ipam_pools_data_source.go index dc14005a7844..64b52668f778 100644 --- a/internal/service/ec2/ipam_pools_data_source.go +++ b/internal/service/ec2/ipam_pools_data_source.go @@ -8,7 +8,6 @@ import ( "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" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) func DataSourceIPAMPools() *schema.Resource { @@ -17,7 +16,7 @@ func DataSourceIPAMPools() *schema.Resource { Schema: map[string]*schema.Schema{ "filter": DataSourceFiltersSchema(), - // computed + "ipam_pools": { Type: schema.TypeSet, Computed: true, @@ -134,10 +133,6 @@ func dataSourceIPAMPoolsRead(d *schema.ResourceData, meta interface{}) error { return err } - if len(pools) == 0 || pools[0] == nil { - return tfresource.SingularDataSourceFindError("EC2 VPC IPAM POOLS", tfresource.NewEmptyResultError(input)) - } - d.Set("ipam_pools", flattenIPAMPools(pools, ignoreTagsConfig)) d.SetId(meta.(*conns.AWSClient).Region) diff --git a/internal/service/ec2/ipam_pools_data_source_test.go b/internal/service/ec2/ipam_pools_data_source_test.go index a2668132b8cf..1867abaeb302 100644 --- a/internal/service/ec2/ipam_pools_data_source_test.go +++ b/internal/service/ec2/ipam_pools_data_source_test.go @@ -32,12 +32,13 @@ func TestAccIPAMPoolsDataSource_basic(t *testing.T) { // DS 2 filters on 1 specific pool to validate attributes resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.#", "1"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.address_family", resourceName, "address_family"), - resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.arn", resourceName, "arn"), resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.allocation_default_netmask_length", resourceName, "allocation_default_netmask_length"), resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.allocation_max_netmask_length", resourceName, "allocation_max_netmask_length"), resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.allocation_min_netmask_length", resourceName, "allocation_min_netmask_length"), resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.allocation_resource_tags.%", resourceName, "allocation_resource_tags.%"), + resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.arn", resourceName, "arn"), resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.auto_import", resourceName, "auto_import"), resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.description", resourceName, "description"), resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.aws_service", resourceName, "aws_service"), @@ -47,6 +48,7 @@ func TestAccIPAMPoolsDataSource_basic(t *testing.T) { resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.pool_depth", resourceName, "pool_depth"), resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.publicly_advertisable", resourceName, "publicly_advertisable"), resource.TestCheckResourceAttrPair(dataSourceNameTwo, "ipam_pools.0.source_ipam_pool_id", resourceName, "source_ipam_pool_id"), + resource.TestCheckResourceAttr(dataSourceNameTwo, "ipam_pools.0.tags.tagtest", "3"), ), }, @@ -54,6 +56,24 @@ func TestAccIPAMPoolsDataSource_basic(t *testing.T) { }) } +func TestAccIPAMPoolsDataSource_empty(t *testing.T) { + dataSourceName := "data.aws_vpc_ipam_pools.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t); testAccIPAMPreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccIPAMPoolsDataSourceConfig_empty, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "ipam_pools.#", "0"), + ), + }, + }, + }) +} + var testAccIPAMPoolsDataSourceConfig_basic = acctest.ConfigCompose(testAccIPAMPoolConfig_base, ` resource "aws_vpc_ipam_pool" "test" { address_family = "ipv4" @@ -135,3 +155,12 @@ data "aws_vpc_ipam_pools" "testtwo" { ] } `) + +var testAccIPAMPoolsDataSourceConfig_empty = acctest.ConfigCompose(` +data "aws_vpc_ipam_pools" "test" { + filter { + name = "description" + values = ["*none*"] + } +} +`) diff --git a/website/docs/d/vpc_ipam_pools.html.markdown b/website/docs/d/vpc_ipam_pools.html.markdown index 69a49f8d4a19..e5556fce16bf 100644 --- a/website/docs/d/vpc_ipam_pools.html.markdown +++ b/website/docs/d/vpc_ipam_pools.html.markdown @@ -3,23 +3,19 @@ subcategory: "VPC IPAM (IP Address Manager)" layout: "aws" page_title: "AWS: aws_vpc_ipam_pools" description: |- - Returns details about the first IPAM pool that matches search parameters provided. + Returns details about IPAM pools that match the search parameters provided. --- # Data Source: aws_vpc_ipam_pools -`aws_vpc_ipam_pools` provides details IPAM pools. +`aws_vpc_ipam_pools` provides details about IPAM pools. -This resource can prove useful when an ipam pool was created in another root -module and you need the pool's id as an input variable. For example, pools +This resource can prove useful when IPAM pools are created in another root +module and you need the pool ids as input variables. For example, pools can be shared via RAM and used to create vpcs with CIDRs from that pool. ## Example Usage -The following example shows an account that has only 1 pool, perhaps shared -via RAM, and using that pool id to create a VPC with a CIDR derived from -AWS IPAM. - ```terraform data "aws_vpc_ipam_pools" "test" { filter { @@ -43,12 +39,7 @@ IPAM Pools in the current region. ## Attributes Reference -All of the argument attributes except `filter` blocks are also exported as -result attributes. This data source will complete the data by populating -any fields that are not included in the configuration with the data for -the selected VPC. - -The following attribute is additionally exported: +In addition to all of the arguments above, the following attributes are exported: * `ipam_pools` - List of IPAM pools and their attributes. See below for details @@ -71,9 +62,3 @@ The following attributes are available on each pool entry found. * `locale` - Locale is the Region where your pool is available for allocations. You can only create pools with locales that match the operating Regions of the IPAM. You can only create VPCs from a pool whose locale matches the VPC's Region. * `source_ipam_pool_id` - ID of the source IPAM pool. * `tags` - Map of tags to assigned to the resource. - -## Timeouts - -[Configuration options](https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts): - -- `read` - (Default `20m`)