diff --git a/aws/data_source_aws_nat_gateway.go b/aws/data_source_aws_nat_gateway.go new file mode 100644 index 000000000000..852976252401 --- /dev/null +++ b/aws/data_source_aws_nat_gateway.go @@ -0,0 +1,114 @@ +package aws + +import ( + "fmt" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform/helper/schema" +) + +func dataSourceAwsNatGateway() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsNatGatewayRead, + + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "state": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "vpc_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "subnet_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "tags": tagsSchemaComputed(), + + "filter": ec2CustomFiltersSchema(), + }, + } +} + +func dataSourceAwsNatGatewayRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + req := &ec2.DescribeNatGatewaysInput{} + + if id, ok := d.GetOk("id"); ok { + req.NatGatewayIds = aws.StringSlice([]string{id.(string)}) + } + + if vpc_id, ok := d.GetOk("vpc_id"); ok { + req.Filter = append(req.Filter, buildEC2AttributeFilterList( + map[string]string{ + "vpc-id": vpc_id.(string), + }, + )...) + } + + if state, ok := d.GetOk("state"); ok { + req.Filter = append(req.Filter, buildEC2AttributeFilterList( + map[string]string{ + "state": state.(string), + }, + )...) + } + + if subnet_id, ok := d.GetOk("subnet_id"); ok { + req.Filter = append(req.Filter, buildEC2AttributeFilterList( + map[string]string{ + "subnet-id": subnet_id.(string), + }, + )...) + } + + req.Filter = append(req.Filter, buildEC2CustomFilterList( + d.Get("filter").(*schema.Set), + )...) + if len(req.Filter) == 0 { + // Don't send an empty filters list; the EC2 API won't accept it. + req.Filter = nil + } + log.Printf("[DEBUG] Reading NAT Gateway: %s", req) + resp, err := conn.DescribeNatGateways(req) + if err != nil { + return err + } + if resp == nil || len(resp.NatGateways) == 0 { + return fmt.Errorf("no matching NAT gateway found: %#v", req) + } + if len(resp.NatGateways) > 1 { + return fmt.Errorf("multiple NAT gateways matched; use additional constraints to reduce matches to a single NAT gateway") + } + + ngw := resp.NatGateways[0] + + d.SetId(aws.StringValue(ngw.NatGatewayId)) + d.Set("state", ngw.State) + d.Set("subnet_id", ngw.SubnetId) + d.Set("vpc_id", ngw.VpcId) + + for _, address := range ngw.NatGatewayAddresses { + if *address.AllocationId != "" { + d.Set("allocation_id", address.AllocationId) + d.Set("network_interface_id", address.NetworkInterfaceId) + d.Set("private_ip", address.PrivateIp) + d.Set("public_ip", address.PublicIp) + break + } + } + + return nil +} diff --git a/aws/data_source_aws_nat_gateway_test.go b/aws/data_source_aws_nat_gateway_test.go new file mode 100644 index 000000000000..e1e516e288dd --- /dev/null +++ b/aws/data_source_aws_nat_gateway_test.go @@ -0,0 +1,89 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDataSourceAwsNatGateway(t *testing.T) { + // This is used as a portion of CIDR network addresses. + rInt := acctest.RandIntRange(4, 254) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccDataSourceAwsNatGatewayConfig(rInt), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPair( + "data.aws_nat_gateway.test_by_id", "id", + "aws_nat_gateway.test", "id"), + resource.TestCheckResourceAttrPair( + "data.aws_nat_gateway.test_by_subnet_id", "subnet_id", + "aws_nat_gateway.test", "subnet_id"), + resource.TestCheckResourceAttrSet("data.aws_nat_gateway.test_by_id", "state"), + resource.TestCheckNoResourceAttr("data.aws_nat_gateway.test_by_id", "attached_vpc_id"), + ), + }, + }, + }) +} + +func testAccDataSourceAwsNatGatewayConfig(rInt int) string { + return fmt.Sprintf(` +provider "aws" { + region = "us-west-2" +} + +resource "aws_vpc" "test" { + cidr_block = "172.%d.0.0/16" + tags { + Name = "terraform-testacc-nat-gateway-data-source-%d" + } +} + +resource "aws_subnet" "test" { + vpc_id = "${aws_vpc.test.id}" + cidr_block = "172.%d.123.0/24" + availability_zone = "us-west-2a" + + tags { + Name = "terraform-testacc-nat-gateway-data-source-%d" + } +} + +# EIPs are not taggable +resource "aws_eip" "test" { + vpc = true +} + +# IGWs are required for an NGW to spin up; manual dependency +resource "aws_internet_gateway" "test" { + vpc_id = "${aws_vpc.test.id}" + tags { + Name = "terraform-testacc-nat-gateway-data-source-%d" + } +} + +# NGWs are not taggable, either +resource "aws_nat_gateway" "test" { + subnet_id = "${aws_subnet.test.id}" + allocation_id = "${aws_eip.test.id}" + + depends_on = ["aws_internet_gateway.test"] +} + +data "aws_nat_gateway" "test_by_id" { + id = "${aws_nat_gateway.test.id}" +} + +data "aws_nat_gateway" "test_by_subnet_id" { + subnet_id = "${aws_nat_gateway.test.subnet_id}" +} + +`, rInt, rInt, rInt, rInt, rInt) +} diff --git a/aws/provider.go b/aws/provider.go index b0dab0f5576a..3079f4ffd968 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -200,6 +200,7 @@ func Provider() terraform.ResourceProvider { "aws_kms_alias": dataSourceAwsKmsAlias(), "aws_kms_ciphertext": dataSourceAwsKmsCiphertext(), "aws_kms_secret": dataSourceAwsKmsSecret(), + "aws_nat_gateway": dataSourceAwsNatGateway(), "aws_partition": dataSourceAwsPartition(), "aws_prefix_list": dataSourceAwsPrefixList(), "aws_redshift_service_account": dataSourceAwsRedshiftServiceAccount(), diff --git a/website/aws.erb b/website/aws.erb index d2cbf0efe199..d9ec207c7fdf 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -143,6 +143,8 @@ > aws_kms_secret + > + aws_nat_gateway > aws_lb diff --git a/website/docs/d/nat_gateway.html.markdown b/website/docs/d/nat_gateway.html.markdown new file mode 100644 index 000000000000..5ca998a998e7 --- /dev/null +++ b/website/docs/d/nat_gateway.html.markdown @@ -0,0 +1,66 @@ +--- +layout: "aws" +page_title: "AWS: aws_nat_gateway" +sidebar_current: "docs-aws-datasource-nat_gateway" +description: |- + Provides details about a specific Nat Gateway +--- + +# aws_nat_gateway + +Provides details about a specific Nat Gateway. + +## Example Usage + +```hcl +variable "subnet_id" {} + +data "aws_nat_gateway" "default" { + subnet_id = "${aws_subnet.public.id}" +} +``` + +Usage with tags: + +```hcl +data "aws_nat_gateway" "default" { + subnet_id = "${aws_subnet.public.id}" + + tags { + Name = "gw NAT" + } +} +``` + +## Argument Reference + +The arguments of this data source act as filters for querying the available +Nat Gateways in the current region. The given filters must match exactly one +Nat Gateway whose data will be exported as attributes. + +* `id` - (Optional) The id of the specific Nat Gateway to retrieve. +* `subnet_id` - (Optional) The id of subnet that the Nat Gateway resides in. +* `vpc_id` - (Optional) The id of the VPC that the Nat Gateway resides in. +* `state` - (Optional) The state of the NAT gateway (pending | failed | available | deleting | deleted ). +* `filter` - (Optional) Custom filter block as described below. +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. + An Nat Gateway will be selected if any one of the given values matches. + +## Attributes Reference + +All of the argument attributes except `filter` block 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 Nat Gateway. + +`addresses` are also exported with the following attributes, when they are relevant: +Each attachement supports the following: + +* `allocation_id` - The Id of the EIP allocated to the selected Nat Gateway. +* `network_interface_id` - The Id of the ENI allocated to the selected Nat Gateway. +* `private_ip` - The private Ip address of the selected Nat Gateway. +* `public_ip` - The public Ip (EIP) address of the selected Nat Gateway.