Add 'aws_vpn_gateway' data source. (#11886)

This commit is contained in:
Kit Ewbank 2017-02-13 11:24:55 -05:00 committed by Paul Stack
parent c6b21d853a
commit 64fda44b00
6 changed files with 341 additions and 38 deletions

View File

@ -0,0 +1,105 @@
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 dataSourceAwsVpnGateway() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsVpnGatewayRead,
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"state": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"attached_vpc_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"availability_zone": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"filter": ec2CustomFiltersSchema(),
"tags": tagsSchemaComputed(),
},
}
}
func dataSourceAwsVpnGatewayRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
log.Printf("[DEBUG] Reading VPN Gateways.")
req := &ec2.DescribeVpnGatewaysInput{}
if id, ok := d.GetOk("id"); ok {
req.VpnGatewayIds = aws.StringSlice([]string{id.(string)})
}
req.Filters = buildEC2AttributeFilterList(
map[string]string{
"state": d.Get("state").(string),
"availability-zone": d.Get("availability_zone").(string),
},
)
if id, ok := d.GetOk("attached_vpc_id"); ok {
req.Filters = append(req.Filters, buildEC2AttributeFilterList(
map[string]string{
"attachment.state": "attached",
"attachment.vpc-id": id.(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.DescribeVpnGateways(req)
if err != nil {
return err
}
if resp == nil || len(resp.VpnGateways) == 0 {
return fmt.Errorf("no matching VPN gateway found: %#v", req)
}
if len(resp.VpnGateways) > 1 {
return fmt.Errorf("multiple VPN gateways matched; use additional constraints to reduce matches to a single VPN gateway")
}
vgw := resp.VpnGateways[0]
d.SetId(aws.StringValue(vgw.VpnGatewayId))
d.Set("state", vgw.State)
d.Set("availability_zone", vgw.AvailabilityZone)
d.Set("tags", tagsToMap(vgw.Tags))
for _, attachment := range vgw.VpcAttachments {
if *attachment.State == "attached" {
d.Set("attached_vpc_id", attachment.VpcId)
break
}
}
return nil
}

View File

@ -0,0 +1,114 @@
// make testacc TEST=./builtin/providers/aws/ TESTARGS='-run=TestAccDataSourceAwsVpnGateway_'
package aws
import (
"fmt"
"regexp"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccDataSourceAwsVpnGateway_unattached(t *testing.T) {
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccDataSourceAwsVpnGatewayUnattachedConfig(rInt),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(
"data.aws_vpn_gateway.test_by_id", "id",
"aws_vpn_gateway.unattached", "id"),
resource.TestCheckResourceAttrPair(
"data.aws_vpn_gateway.test_by_tags", "id",
"aws_vpn_gateway.unattached", "id"),
resource.TestCheckResourceAttrSet("data.aws_vpn_gateway.test_by_id", "state"),
resource.TestCheckResourceAttr("data.aws_vpn_gateway.test_by_tags", "tags.%", "3"),
resource.TestCheckNoResourceAttr("data.aws_vpn_gateway.test_by_id", "attached_vpc_id"),
),
},
},
})
}
func TestAccDataSourceAwsVpnGateway_attached(t *testing.T) {
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccDataSourceAwsVpnGatewayAttachedConfig(rInt),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(
"data.aws_vpn_gateway.test_by_attached_vpc_id", "id",
"aws_vpn_gateway.attached", "id"),
resource.TestCheckResourceAttrPair(
"data.aws_vpn_gateway.test_by_attached_vpc_id", "attached_vpc_id",
"aws_vpc.foo", "id"),
resource.TestMatchResourceAttr("data.aws_vpn_gateway.test_by_attached_vpc_id", "state", regexp.MustCompile("(?i)available")),
),
},
},
})
}
func testAccDataSourceAwsVpnGatewayUnattachedConfig(rInt int) string {
return fmt.Sprintf(`
provider "aws" {
region = "us-west-2"
}
resource "aws_vpn_gateway" "unattached" {
tags {
Name = "terraform-testacc-vpn-gateway-data-source-unattached-%d"
ABC = "testacc-%d"
XYZ = "testacc-%d"
}
}
data "aws_vpn_gateway" "test_by_id" {
id = "${aws_vpn_gateway.unattached.id}"
}
data "aws_vpn_gateway" "test_by_tags" {
tags = "${aws_vpn_gateway.unattached.tags}"
}
`, rInt, rInt+1, rInt-1)
}
func testAccDataSourceAwsVpnGatewayAttachedConfig(rInt int) string {
return fmt.Sprintf(`
provider "aws" {
region = "us-west-2"
}
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
tags {
Name = "terraform-testacc-vpn-gateway-data-source-foo-%d"
}
}
resource "aws_vpn_gateway" "attached" {
tags {
Name = "terraform-testacc-vpn-gateway-data-source-attached-%d"
}
}
resource "aws_vpn_gateway_attachment" "vpn_attachment" {
vpc_id = "${aws_vpc.foo.id}"
vpn_gateway_id = "${aws_vpn_gateway.attached.id}"
}
data "aws_vpn_gateway" "test_by_attached_vpc_id" {
attached_vpc_id = "${aws_vpn_gateway_attachment.vpn_attachment.vpc_id}"
}
`, rInt, rInt)
}

View File

@ -177,6 +177,7 @@ func Provider() terraform.ResourceProvider {
"aws_iam_server_certificate": dataSourceAwsIAMServerCertificate(),
"aws_instance": dataSourceAwsInstance(),
"aws_ip_ranges": dataSourceAwsIPRanges(),
"aws_kms_secret": dataSourceAwsKmsSecret(),
"aws_partition": dataSourceAwsPartition(),
"aws_prefix_list": dataSourceAwsPrefixList(),
"aws_redshift_service_account": dataSourceAwsRedshiftServiceAccount(),
@ -190,7 +191,7 @@ func Provider() terraform.ResourceProvider {
"aws_vpc_endpoint": dataSourceAwsVpcEndpoint(),
"aws_vpc_endpoint_service": dataSourceAwsVpcEndpointService(),
"aws_vpc_peering_connection": dataSourceAwsVpcPeeringConnection(),
"aws_kms_secret": dataSourceAwsKmsSecret(),
"aws_vpn_gateway": dataSourceAwsVpnGateway(),
},
ResourcesMap: map[string]*schema.Resource{

View File

@ -549,15 +549,9 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc {
// know ahead of time what the values will be.
func TestCheckResourceAttrSet(name, key string) TestCheckFunc {
return func(s *terraform.State) error {
ms := s.RootModule()
rs, ok := ms.Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
is := rs.Primary
if is == nil {
return fmt.Errorf("No primary instance: %s", name)
is, err := primaryInstanceState(s, name)
if err != nil {
return err
}
if val, ok := is.Attributes[key]; ok && val != "" {
@ -568,17 +562,13 @@ func TestCheckResourceAttrSet(name, key string) TestCheckFunc {
}
}
// TestCheckResourceAttr is a TestCheckFunc which validates
// the value in state for the given name/key combination.
func TestCheckResourceAttr(name, key, value string) TestCheckFunc {
return func(s *terraform.State) error {
ms := s.RootModule()
rs, ok := ms.Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
is := rs.Primary
if is == nil {
return fmt.Errorf("No primary instance: %s", name)
is, err := primaryInstanceState(s, name)
if err != nil {
return err
}
if v, ok := is.Attributes[key]; !ok || v != value {
@ -591,7 +581,7 @@ func TestCheckResourceAttr(name, key, value string) TestCheckFunc {
name,
key,
value,
is.Attributes[key])
v)
}
return nil
@ -602,15 +592,9 @@ func TestCheckResourceAttr(name, key, value string) TestCheckFunc {
// NO value exists in state for the given name/key combination.
func TestCheckNoResourceAttr(name, key string) TestCheckFunc {
return func(s *terraform.State) error {
ms := s.RootModule()
rs, ok := ms.Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
is := rs.Primary
if is == nil {
return fmt.Errorf("No primary instance: %s", name)
is, err := primaryInstanceState(s, name)
if err != nil {
return err
}
if _, ok := is.Attributes[key]; ok {
@ -621,17 +605,13 @@ func TestCheckNoResourceAttr(name, key string) TestCheckFunc {
}
}
// TestMatchResourceAttr is a TestCheckFunc which checks that the value
// in state for the given name/key combination matches the given regex.
func TestMatchResourceAttr(name, key string, r *regexp.Regexp) TestCheckFunc {
return func(s *terraform.State) error {
ms := s.RootModule()
rs, ok := ms.Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
is := rs.Primary
if is == nil {
return fmt.Errorf("No primary instance: %s", name)
is, err := primaryInstanceState(s, name)
if err != nil {
return err
}
if !r.MatchString(is.Attributes[key]) {
@ -656,6 +636,41 @@ func TestCheckResourceAttrPtr(name string, key string, value *string) TestCheckF
}
}
// TestCheckResourceAttrPair is a TestCheckFunc which validates that the values
// in state for a pair of name/key combinations are equal.
func TestCheckResourceAttrPair(nameFirst, keyFirst, nameSecond, keySecond string) TestCheckFunc {
return func(s *terraform.State) error {
isFirst, err := primaryInstanceState(s, nameFirst)
if err != nil {
return err
}
vFirst, ok := isFirst.Attributes[keyFirst]
if !ok {
return fmt.Errorf("%s: Attribute '%s' not found", nameFirst, keyFirst)
}
isSecond, err := primaryInstanceState(s, nameSecond)
if err != nil {
return err
}
vSecond, ok := isSecond.Attributes[keySecond]
if !ok {
return fmt.Errorf("%s: Attribute '%s' not found", nameSecond, keySecond)
}
if vFirst != vSecond {
return fmt.Errorf(
"%s: Attribute '%s' expected %#v, got %#v",
nameFirst,
keyFirst,
vSecond,
vFirst)
}
return nil
}
}
// TestCheckOutput checks an output in the Terraform configuration
func TestCheckOutput(name, value string) TestCheckFunc {
return func(s *terraform.State) error {
@ -708,3 +723,19 @@ type TestT interface {
// This is set to true by unit tests to alter some behavior
var testTesting = false
// primaryInstanceState returns the primary instance state for the given resource name.
func primaryInstanceState(s *terraform.State, name string) (*terraform.InstanceState, error) {
ms := s.RootModule()
rs, ok := ms.Resources[name]
if !ok {
return nil, fmt.Errorf("Not found: %s", name)
}
is := rs.Primary
if is == nil {
return nil, fmt.Errorf("No primary instance: %s", name)
}
return is, nil
}

View File

@ -0,0 +1,49 @@
---
layout: "aws"
page_title: "AWS: aws_vpn_gateway"
sidebar_current: "docs-aws-datasource-vpn-gateway"
description: |-
Provides details about a specific VPN gateway.
---
# aws\_vpn\_gateway
The VPN Gateway data source provides details about
a specific VPN gateway.
## Example Usage
```
```
## Argument Reference
The arguments of this data source act as filters for querying the available VPN gateways.
The given filters must match exactly one VPN gateway whose data will be exported as attributes.
* `id` - (Optional) The ID of the specific VPN Gateway to retrieve.
* `state` - (Optional) The state of the specific VPN Gateway to retrieve.
* `availability_zone` - (Optional) The Availability Zone of the specific VPN Gateway to retrieve.
* `attached_vpc_id` - (Optional) The ID of a VPC attached to the specific VPN Gateway 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 VPN Gateway.
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_DescribeVpnGateways.html).
* `values` - (Required) Set of values that are accepted for the given field.
A VPN Gateway will be selected if any one of the given values matches.
## Attributes Reference
All of the argument attributes are also exported as result attributes.

View File

@ -122,6 +122,9 @@
<li<%= sidebar_current("docs-aws-datasource-vpc-peering-connection") %>>
<a href="/docs/providers/aws/d/vpc_peering_connection.html">aws_vpc_peering_connection</a>
</li>
<li<%= sidebar_current("docs-aws-datasource-vpn-gateway") %>>
<a href="/docs/providers/aws/d/vpn_gateway.html">aws_vpn_gateway</a>
</li>
</ul>
</li>