diff --git a/builtin/providers/aws/data_source_aws_vpc_peering_connection.go b/builtin/providers/aws/data_source_aws_vpc_peering_connection.go new file mode 100644 index 000000000..8d800751f --- /dev/null +++ b/builtin/providers/aws/data_source_aws_vpc_peering_connection.go @@ -0,0 +1,143 @@ +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 dataSourceAwsVpcPeeringConnection() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsVpcPeeringConnectionRead, + + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "vpc_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "owner_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "cidr_block": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "peer_vpc_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "peer_owner_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "peer_cidr_block": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "accepter": { + Type: schema.TypeMap, + Computed: true, + Elem: schema.TypeBool, + }, + "requester": { + Type: schema.TypeMap, + Computed: true, + Elem: schema.TypeBool, + }, + "filter": ec2CustomFiltersSchema(), + "tags": tagsSchemaComputed(), + }, + } +} + +func dataSourceAwsVpcPeeringConnectionRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + + log.Printf("[DEBUG] Reading VPC Peering Connections.") + + req := &ec2.DescribeVpcPeeringConnectionsInput{} + + if id, ok := d.GetOk("id"); ok { + req.VpcPeeringConnectionIds = aws.StringSlice([]string{id.(string)}) + } + + req.Filters = buildEC2AttributeFilterList( + map[string]string{ + "status-code": d.Get("status").(string), + "requester-vpc-info.vpc-id": d.Get("vpc_id").(string), + "requester-vpc-info.owner-id": d.Get("owner_id").(string), + "requester-vpc-info.cidr-block": d.Get("cidr_block").(string), + "accepter-vpc-info.vpc-id": d.Get("peer_vpc_id").(string), + "accepter-vpc-info.owner-id": d.Get("peer_owner_id").(string), + "accepter-vpc-info.cidr-block": d.Get("peer_cidr_block").(string), + }, + ) + req.Filters = append(req.Filters, buildEC2TagFilterList( + tagsFromMap(d.Get("tags").(map[string]interface{})), + )...) + req.Filters = append(req.Filters, buildEC2CustomFilterList( + d.Get("filter").(*schema.Set), + )...) + if len(req.Filters) == 0 { + // Don't send an empty filters list; the EC2 API won't accept it. + req.Filters = nil + } + + resp, err := conn.DescribeVpcPeeringConnections(req) + if err != nil { + return err + } + if resp == nil || len(resp.VpcPeeringConnections) == 0 { + return fmt.Errorf("no matching VPC peering connection found") + } + if len(resp.VpcPeeringConnections) > 1 { + return fmt.Errorf("multiple VPC peering connections matched; use additional constraints to reduce matches to a single VPC peering connection") + } + + pcx := resp.VpcPeeringConnections[0] + + d.SetId(aws.StringValue(pcx.VpcPeeringConnectionId)) + d.Set("id", pcx.VpcPeeringConnectionId) + d.Set("status", pcx.Status.Code) + d.Set("vpc_id", pcx.RequesterVpcInfo.VpcId) + d.Set("owner_id", pcx.RequesterVpcInfo.OwnerId) + d.Set("cidr_block", pcx.RequesterVpcInfo.CidrBlock) + d.Set("peer_vpc_id", pcx.AccepterVpcInfo.VpcId) + d.Set("peer_owner_id", pcx.AccepterVpcInfo.OwnerId) + d.Set("peer_cidr_block", pcx.AccepterVpcInfo.CidrBlock) + d.Set("tags", tagsToMap(pcx.Tags)) + + if pcx.AccepterVpcInfo.PeeringOptions != nil { + if err := d.Set("accepter", flattenPeeringOptions(pcx.AccepterVpcInfo.PeeringOptions)[0]); err != nil { + return err + } + } + + if pcx.RequesterVpcInfo.PeeringOptions != nil { + if err := d.Set("requester", flattenPeeringOptions(pcx.RequesterVpcInfo.PeeringOptions)[0]); err != nil { + return err + } + } + + return nil +} diff --git a/builtin/providers/aws/data_source_aws_vpc_peering_connection_test.go b/builtin/providers/aws/data_source_aws_vpc_peering_connection_test.go new file mode 100644 index 000000000..366921a72 --- /dev/null +++ b/builtin/providers/aws/data_source_aws_vpc_peering_connection_test.go @@ -0,0 +1,129 @@ +// make testacc TEST=./builtin/providers/aws/ TESTARGS='-run=TestAccDataSourceAwsVpcPeeringConnection_' +package aws + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccDataSourceAwsVpcPeeringConnection_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccDataSourceAwsVpcPeeringConnectionConfig, + Check: resource.ComposeTestCheckFunc( + testAccDataSourceAwsVpcPeeringConnectionCheck("data.aws_vpc_peering_connection.test_by_id"), + testAccDataSourceAwsVpcPeeringConnectionCheck("data.aws_vpc_peering_connection.test_by_requester_vpc_id"), + testAccDataSourceAwsVpcPeeringConnectionCheck("data.aws_vpc_peering_connection.test_by_accepter_vpc_id"), + testAccDataSourceAwsVpcPeeringConnectionCheck("data.aws_vpc_peering_connection.test_by_requester_cidr_block"), + testAccDataSourceAwsVpcPeeringConnectionCheck("data.aws_vpc_peering_connection.test_by_accepter_cidr_block"), + testAccDataSourceAwsVpcPeeringConnectionCheck("data.aws_vpc_peering_connection.test_by_owner_ids"), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccDataSourceAwsVpcPeeringConnectionCheck(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("root module has no resource called %s", name) + } + + pcxRs, ok := s.RootModule().Resources["aws_vpc_peering_connection.test"] + if !ok { + return fmt.Errorf("can't find aws_vpc_peering_connection.test in state") + } + + attr := rs.Primary.Attributes + + if attr["id"] != pcxRs.Primary.Attributes["id"] { + return fmt.Errorf( + "id is %s; want %s", + attr["id"], + pcxRs.Primary.Attributes["id"], + ) + } + + return nil + } +} + +const testAccDataSourceAwsVpcPeeringConnectionConfig = ` +provider "aws" { + region = "us-west-2" +} + +resource "aws_vpc" "foo" { + cidr_block = "10.1.0.0/16" + + tags { + Name = "terraform-testacc-vpc-peering-connection-data-source-foo" + } +} + +resource "aws_vpc" "bar" { + cidr_block = "10.2.0.0/16" + + tags { + Name = "terraform-testacc-vpc-peering-connection-data-source-bar" + } +} + +resource "aws_vpc_peering_connection" "test" { + vpc_id = "${aws_vpc.foo.id}" + peer_vpc_id = "${aws_vpc.bar.id}" + auto_accept = true + + tags { + Name = "terraform-testacc-vpc-peering-connection-data-source-foo-to-bar" + } +} + +data "aws_caller_identity" "current" {} + +data "aws_vpc_peering_connection" "test_by_id" { + id = "${aws_vpc_peering_connection.test.id}" +} + +data "aws_vpc_peering_connection" "test_by_requester_vpc_id" { + vpc_id = "${aws_vpc.foo.id}" + + depends_on = ["aws_vpc_peering_connection.test"] +} + +data "aws_vpc_peering_connection" "test_by_accepter_vpc_id" { + peer_vpc_id = "${aws_vpc.bar.id}" + + depends_on = ["aws_vpc_peering_connection.test"] +} + +data "aws_vpc_peering_connection" "test_by_requester_cidr_block" { + cidr_block = "10.1.0.0/16" + status = "active" + + depends_on = ["aws_vpc_peering_connection.test"] +} + +data "aws_vpc_peering_connection" "test_by_accepter_cidr_block" { + peer_cidr_block = "10.2.0.0/16" + status = "active" + + depends_on = ["aws_vpc_peering_connection.test"] +} + +data "aws_vpc_peering_connection" "test_by_owner_ids" { + owner_id = "${data.aws_caller_identity.current.account_id}" + peer_owner_id = "${data.aws_caller_identity.current.account_id}" + status = "active" + + depends_on = ["aws_vpc_peering_connection.test"] +} +` diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 32db8fd6c..99bf67d0a 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -171,6 +171,7 @@ func Provider() terraform.ResourceProvider { "aws_security_group": dataSourceAwsSecurityGroup(), "aws_vpc": dataSourceAwsVpc(), "aws_vpc_endpoint_service": dataSourceAwsVpcEndpointService(), + "aws_vpc_peering_connection": dataSourceAwsVpcPeeringConnection(), }, ResourcesMap: map[string]*schema.Resource{ diff --git a/website/source/docs/providers/aws/d/vpc_peering_connection.html.markdown b/website/source/docs/providers/aws/d/vpc_peering_connection.html.markdown new file mode 100644 index 000000000..fc848d963 --- /dev/null +++ b/website/source/docs/providers/aws/d/vpc_peering_connection.html.markdown @@ -0,0 +1,90 @@ +--- +layout: "aws" +page_title: "AWS: aws_vpc_peering_connection" +sidebar_current: "docs-aws-datasource-vpc-peering-connection" +description: |- + Provides details about a specific VPC peering connection. +--- + +# aws\_vpc\_peering\_connection + +The VPC Peering Connection data source provides details about +a specific VPC peering connection. + +## Example Usage + +``` +# Declare the data source +data "aws_vpc_peering_connection" "pc" { + vpc_id = "${aws_vpc.foo.id}" + peer_cidr_block = "10.0.1.0/22" +} + +# Create a route table +resource "aws_route_table" "rt" { + vpc_id = "${aws_vpc.foo.id}" +} + +# Create a route +resource "aws_route" "r" { + route_table_id = "${aws_route_table.rt.id}" + destination_cidr_block = "${data.aws_vpc_peering_connection.pc.peer_cidr_block}" + vpc_peering_connection_id = "${data.aws_vpc_peering_connection.pc.id}" +} +``` + +## Argument Reference + +The arguments of this data source act as filters for querying the available VPC peering connection. +The given filters must match exactly one VPC peering connection whose data will be exported as attributes. + +* `id` - (Optional) The ID of the specific VPC Peering Connection to retrieve. + +* `status` - (Optional) The status of the specific VPC Peering Connection to retrieve. + +* `vpc_id` - (Optional) The ID of the requester VPC of the specific VPC Peering Connection to retrieve. + +* `owner_id` - (Optional) The AWS account ID of the owner of the requester VPC of the specific VPC Peering Connection to retrieve. + +* `cidr_block` - (Optional) The CIDR block of the requester VPC of the specific VPC Peering Connection to retrieve. + +* `peer_vpc_id` - (Optional) The ID of the accepter VPC of the specific VPC Peering Connection to retrieve. + +* `peer_owner_id` - (Optional) The AWS account ID of the owner of the accepter VPC of the specific VPC Peering Connection to retrieve. + +* `peer_cidr_block` - (Optional) The CIDR block of the accepter VPC of the specific VPC Peering Connection to retrieve. + +* `filter` - (Optional) Custom filter block as described below. + +* `tags` - (Optional) A mapping of tags, each pair of which must exactly match + a pair on the desired VPC Peering Connection. + +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](http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcPeeringConnections.html). + +* `values` - (Required) Set of values that are accepted for the given field. + A VPC Peering Connection will be selected if any one of the given values matches. + +## Attributes Reference + +All of the argument attributes except `filter` are also exported as result attributes. + +* `accepter` - A configuration block that describes [VPC Peering Connection] +(http://docs.aws.amazon.com/AmazonVPC/latest/PeeringGuide) options set for the accepter VPC. + +* `requester` - A configuration block that describes [VPC Peering Connection] +(http://docs.aws.amazon.com/AmazonVPC/latest/PeeringGuide) options set for the requester VPC. + +#### Accepter and Requester Attributes Reference + +* `allow_remote_vpc_dns_resolution` - Indicates whether a local VPC can resolve public DNS hostnames to +private IP addresses when queried from instances in a peer VPC. + +* `allow_classic_link_to_remote_vpc` - Indicates whether a local ClassicLink connection can communicate +with the peer VPC over the VPC peering connection. + +* `allow_vpc_to_remote_classic_link` - Indicates whether a local VPC can communicate with a ClassicLink +connection in the peer VPC over the VPC peering connection. diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index 8d985b37e..03cf62df4 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -95,6 +95,9 @@