From a3153917e3d558aead52c8a2b4223d6a7969e1c8 Mon Sep 17 00:00:00 2001 From: Andrew Titmuss Date: Tue, 12 Apr 2022 11:36:28 +1000 Subject: [PATCH 1/6] add aws_nat_gateways datasource --- internal/provider/provider.go | 1 + .../service/ec2/nat_gateways_data_source.go | 76 +++++++ .../ec2/nat_gateways_data_source_test.go | 192 ++++++++++++++++++ 3 files changed, 269 insertions(+) create mode 100644 internal/service/ec2/nat_gateways_data_source.go create mode 100644 internal/service/ec2/nat_gateways_data_source_test.go diff --git a/internal/provider/provider.go b/internal/provider/provider.go index df93e4b5c5a5..6f8a0496ebd6 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -558,6 +558,7 @@ func Provider() *schema.Provider { "aws_key_pair": ec2.DataSourceKeyPair(), "aws_launch_template": ec2.DataSourceLaunchTemplate(), "aws_nat_gateway": ec2.DataSourceNATGateway(), + "aws_nat_gateways": ec2.DataSourceNATGateways(), "aws_network_acls": ec2.DataSourceNetworkACLs(), "aws_network_interface": ec2.DataSourceNetworkInterface(), "aws_network_interfaces": ec2.DataSourceNetworkInterfaces(), diff --git a/internal/service/ec2/nat_gateways_data_source.go b/internal/service/ec2/nat_gateways_data_source.go new file mode 100644 index 000000000000..37854281fcac --- /dev/null +++ b/internal/service/ec2/nat_gateways_data_source.go @@ -0,0 +1,76 @@ +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/schema" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" +) + +func DataSourceNATGateways() *schema.Resource { + return &schema.Resource{ + Read: dataSourceNATGatewaysRead, + + Schema: map[string]*schema.Schema{ + "filter": DataSourceFiltersSchema(), + "ids": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "tags": tftags.TagsSchemaComputed(), + "vpc_id": { + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func dataSourceNATGatewaysRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*conns.AWSClient).EC2Conn + + input := &ec2.DescribeNatGatewaysInput{} + + if v, ok := d.GetOk("vpc_id"); ok { + input.Filter = append(input.Filter, BuildAttributeFilterList( + map[string]string{ + "vpc-id": v.(string), + }, + )...) + } + + if tags, ok := d.GetOk("tags"); ok { + input.Filter = append(input.Filter, BuildTagFilterList( + Tags(tftags.New(tags.(map[string]interface{}))), + )...) + } + + input.Filter = append(input.Filter, BuildFiltersDataSource( + d.Get("filter").(*schema.Set), + )...) + if len(input.Filter) == 0 { + // Don't send an empty filters list; the EC2 API won't accept it. + input.Filter = nil + } + + ngws, err := FindNATGateways(conn, input) + + if err != nil { + return fmt.Errorf("error reading EC2 NAT Gateways: %w", err) + } + + var natGatewayIds []string + + for _, v := range ngws { + natGatewayIds = append(natGatewayIds, aws.StringValue(v.NatGatewayId)) + } + + d.SetId(meta.(*conns.AWSClient).Region) + d.Set("ids", natGatewayIds) + + return nil +} diff --git a/internal/service/ec2/nat_gateways_data_source_test.go b/internal/service/ec2/nat_gateways_data_source_test.go new file mode 100644 index 000000000000..c774ad6f3965 --- /dev/null +++ b/internal/service/ec2/nat_gateways_data_source_test.go @@ -0,0 +1,192 @@ +package ec2_test + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/ec2" + sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" +) + +func TestAccEC2NATGatewaysDataSource_basic(t *testing.T) { + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckVpcDestroy, + Steps: []resource.TestStep{ + { + Config: testAccNATGatewaysDataSourceConfig(rName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.aws_nat_gateways.by_vpc_id", "ids.#", "2"), + resource.TestCheckResourceAttr("data.aws_nat_gateways.by_tags", "ids.#", "1"), + resource.TestCheckResourceAttr("data.aws_nat_gateways.by_filter", "ids.#", "3"), + resource.TestCheckResourceAttr("data.aws_nat_gateways.empty", "ids.#", "0"), + ), + }, + }, + }) +} + +func testAccNATGatewaysDataSourceConfig(rName string) string { + return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptIn(), fmt.Sprintf(` +resource "aws_vpc" "test1" { + cidr_block = "172.5.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc" "test2" { + cidr_block = "172.5.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test1" { + vpc_id = aws_vpc.test1.id + cidr_block = "172.5.123.0/24" + availability_zone = data.aws_availability_zones.available.names[0] + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test2" { + vpc_id = aws_vpc.test2.id + cidr_block = "172.5.123.0/24" + availability_zone = data.aws_availability_zones.available.names[0] + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test3" { + vpc_id = aws_vpc.test2.id + cidr_block = "172.5.124.0/24" + availability_zone = data.aws_availability_zones.available.names[0] + + tags = { + Name = %[1]q + } +} + +resource "aws_eip" "test1" { + vpc = true + + tags = { + Name = %[1]q + } +} + +resource "aws_eip" "test2" { + vpc = true + + tags = { + Name = %[1]q + } +} + +resource "aws_eip" "test3" { + vpc = true + + tags = { + Name = %[1]q + } +} + +resource "aws_internet_gateway" "test1" { + vpc_id = aws_vpc.test1.id + + tags = { + Name = %[1]q + } +} + +resource "aws_internet_gateway" "test2" { + vpc_id = aws_vpc.test2.id + + tags = { + Name = %[1]q + } +} + +resource "aws_nat_gateway" "test1" { + subnet_id = aws_subnet.test1.id + allocation_id = aws_eip.test1.id + + tags = { + Name = %[1]q + OtherTag = "some-value" + } + + depends_on = [aws_internet_gateway.test1] +} + +resource "aws_nat_gateway" "test2" { + subnet_id = aws_subnet.test2.id + allocation_id = aws_eip.test2.id + + tags = { + Name = %[1]q + OtherTag = "some-other-value" + } + + depends_on = [aws_internet_gateway.test2] +} + +resource "aws_nat_gateway" "test3" { + subnet_id = aws_subnet.test3.id + allocation_id = aws_eip.test3.id + + tags = { + Name = %[1]q + OtherTag = "some-other-value" + } + + depends_on = [aws_internet_gateway.test2] +} + +data "aws_nat_gateways" "by_vpc_id" { + vpc_id = aws_vpc.test2.id + + depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] +} + +data "aws_nat_gateways" "by_tags" { + tags = { + OtherTag = "some-value" + } + + depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] +} + +data "aws_nat_gateways" "by_filter" { + filter { + name = "vpc-id" + values = [aws_vpc.test1.id, aws_vpc.test2.id] + } + + depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] +} + +data "aws_nat_gateways" "empty" { + vpc_id = aws_vpc.test2.id + + tags = { + OtherTag = "some-value" + } + + depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] +} +`, rName)) +} From 5859c701d23e78bf34c552f69b410b00993ddd18 Mon Sep 17 00:00:00 2001 From: Andrew Titmuss Date: Tue, 12 Apr 2022 11:48:02 +1000 Subject: [PATCH 2/6] add documentation for aws_nat_gateways --- website/docs/d/nat_gateways.html.markdown | 51 +++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 website/docs/d/nat_gateways.html.markdown diff --git a/website/docs/d/nat_gateways.html.markdown b/website/docs/d/nat_gateways.html.markdown new file mode 100644 index 000000000000..cd78e0fc9dbf --- /dev/null +++ b/website/docs/d/nat_gateways.html.markdown @@ -0,0 +1,51 @@ +--- +subcategory: "VPC (Virtual Private Cloud)" +layout: "aws" +page_title: "AWS: aws_nat_gateways" +description: |- + Get information on Amazon NAT Gateways. +--- + +# Data Source: aws_nat_gateways + +This resource can be useful for getting back a list of NAT gateway ids to be referenced elsewhere. + +## Example Usage + +The following returns all NAT gateways in a specified VPC that are marked as available + +```terraform +data "aws_nat_gateways" "ngws" { + vpc_id = var.vpc_id + + filter { + name = "state" + values = ["available"] + } +} + +data "aws_nat_gateway" "ngw" { + count = length(data.aws_nat_gateways.ngws.ids) + id = tolist(data.aws_nat_gateways.ngws.ids)[count.index] +} +``` + +## Argument Reference + +* `filter` - (Optional) Custom filter block as described below. +* `vpc_id` - (Optional) The VPC ID that you want to filter from. +* `tags` - (Optional) A map of tags, each pair of which must exactly match + a pair on the desired NAT Gateways. + +More complex filters can be expressed using one or more `filter` sub-blocks, +which take the following arguments: + +* `name` - (Required) The name of the field to filter by, as defined by + [the underlying AWS API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeNatGateways.html). +* `values` - (Required) Set of values that are accepted for the given field. + A Nat Gateway will be selected if any one of the given values matches. + +## Attributes Reference + +* `id` - AWS Region. +* `ids` - A list of all the NAT gateway ids found. From 046d9e8267c24cc7bab2e3d5b8e75beeaa9c5b29 Mon Sep 17 00:00:00 2001 From: Andrew Titmuss Date: Tue, 12 Apr 2022 12:02:17 +1000 Subject: [PATCH 3/6] Update CHANGELOG for #24190 --- .changelog/24190.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/24190.txt diff --git a/.changelog/24190.txt b/.changelog/24190.txt new file mode 100644 index 000000000000..ab98f02eb345 --- /dev/null +++ b/.changelog/24190.txt @@ -0,0 +1,3 @@ +```release-note:new-data-source +aws_nat_gateways +``` \ No newline at end of file From ffdd3e82a8a56fd47e7b0d84b3f692b288e1634c Mon Sep 17 00:00:00 2001 From: Andrew Titmuss Date: Tue, 12 Apr 2022 12:16:40 +1000 Subject: [PATCH 4/6] update acceptance test to prevent errors when running again in same hour window --- internal/service/ec2/nat_gateways_data_source_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/service/ec2/nat_gateways_data_source_test.go b/internal/service/ec2/nat_gateways_data_source_test.go index c774ad6f3965..ecc3d57dabdb 100644 --- a/internal/service/ec2/nat_gateways_data_source_test.go +++ b/internal/service/ec2/nat_gateways_data_source_test.go @@ -163,6 +163,11 @@ data "aws_nat_gateways" "by_vpc_id" { } data "aws_nat_gateways" "by_tags" { + filter { + name = "state" + values = ["available"] + } + tags = { OtherTag = "some-value" } From 0e3f2b774df01402935387744055dc5fd873ac09 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 12 Apr 2022 10:01:25 -0400 Subject: [PATCH 5/6] Fix terrafmt errors. --- .../service/ec2/nat_gateways_data_source.go | 12 +++--- .../ec2/nat_gateways_data_source_test.go | 43 +++++++++---------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/internal/service/ec2/nat_gateways_data_source.go b/internal/service/ec2/nat_gateways_data_source.go index 37854281fcac..be29d107bd95 100644 --- a/internal/service/ec2/nat_gateways_data_source.go +++ b/internal/service/ec2/nat_gateways_data_source.go @@ -52,25 +52,25 @@ func dataSourceNATGatewaysRead(d *schema.ResourceData, meta interface{}) error { input.Filter = append(input.Filter, BuildFiltersDataSource( d.Get("filter").(*schema.Set), )...) + if len(input.Filter) == 0 { - // Don't send an empty filters list; the EC2 API won't accept it. input.Filter = nil } - ngws, err := FindNATGateways(conn, input) + output, err := FindNATGateways(conn, input) if err != nil { return fmt.Errorf("error reading EC2 NAT Gateways: %w", err) } - var natGatewayIds []string + var natGatewayIDs []string - for _, v := range ngws { - natGatewayIds = append(natGatewayIds, aws.StringValue(v.NatGatewayId)) + for _, v := range output { + natGatewayIDs = append(natGatewayIDs, aws.StringValue(v.NatGatewayId)) } d.SetId(meta.(*conns.AWSClient).Region) - d.Set("ids", natGatewayIds) + d.Set("ids", natGatewayIDs) return nil } diff --git a/internal/service/ec2/nat_gateways_data_source_test.go b/internal/service/ec2/nat_gateways_data_source_test.go index ecc3d57dabdb..e7aeec0ae238 100644 --- a/internal/service/ec2/nat_gateways_data_source_test.go +++ b/internal/service/ec2/nat_gateways_data_source_test.go @@ -17,7 +17,6 @@ func TestAccEC2NATGatewaysDataSource_basic(t *testing.T) { PreCheck: func() { acctest.PreCheck(t) }, ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), Providers: acctest.Providers, - CheckDestroy: testAccCheckVpcDestroy, Steps: []resource.TestStep{ { Config: testAccNATGatewaysDataSourceConfig(rName), @@ -43,11 +42,11 @@ resource "aws_vpc" "test1" { } resource "aws_vpc" "test2" { - cidr_block = "172.5.0.0/16" + cidr_block = "172.5.0.0/16" - tags = { - Name = %[1]q - } + tags = { + Name = %[1]q + } } resource "aws_subnet" "test1" { @@ -97,11 +96,11 @@ resource "aws_eip" "test2" { } resource "aws_eip" "test3" { - vpc = true + vpc = true - tags = { - Name = %[1]q - } + tags = { + Name = %[1]q + } } resource "aws_internet_gateway" "test1" { @@ -159,7 +158,7 @@ resource "aws_nat_gateway" "test3" { data "aws_nat_gateways" "by_vpc_id" { vpc_id = aws_vpc.test2.id - depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] + depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] } data "aws_nat_gateways" "by_tags" { @@ -168,30 +167,30 @@ data "aws_nat_gateways" "by_tags" { values = ["available"] } - tags = { - OtherTag = "some-value" - } + tags = { + OtherTag = "some-value" + } - depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] + depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] } data "aws_nat_gateways" "by_filter" { filter { - name = "vpc-id" - values = [aws_vpc.test1.id, aws_vpc.test2.id] + name = "vpc-id" + values = [aws_vpc.test1.id, aws_vpc.test2.id] } - depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] + depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] } data "aws_nat_gateways" "empty" { - vpc_id = aws_vpc.test2.id + vpc_id = aws_vpc.test2.id - tags = { - OtherTag = "some-value" - } + tags = { + OtherTag = "some-value" + } - depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] + depends_on = [aws_nat_gateway.test1, aws_nat_gateway.test2, aws_nat_gateway.test3] } `, rName)) } From d9e9d4f70c6a3d04e1958e96a8cd99b8d3887306 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 12 Apr 2022 10:34:48 -0400 Subject: [PATCH 6/6] Run 'go fmt'. --- internal/service/ec2/nat_gateways_data_source_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/service/ec2/nat_gateways_data_source_test.go b/internal/service/ec2/nat_gateways_data_source_test.go index e7aeec0ae238..53241da8a265 100644 --- a/internal/service/ec2/nat_gateways_data_source_test.go +++ b/internal/service/ec2/nat_gateways_data_source_test.go @@ -14,9 +14,9 @@ func TestAccEC2NATGatewaysDataSource_basic(t *testing.T) { rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(t) }, - ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), - Providers: acctest.Providers, + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + Providers: acctest.Providers, Steps: []resource.TestStep{ { Config: testAccNATGatewaysDataSourceConfig(rName),