Skip to content

Commit d5bed72

Browse files
ewbankkitstack72
authored andcommitted
Add 'aws_vpn_gateway' data source. (hashicorp#11886)
1 parent 61745c9 commit d5bed72

6 files changed

Lines changed: 341 additions & 38 deletions

File tree

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package aws
2+
3+
import (
4+
"fmt"
5+
"log"
6+
7+
"github.com/aws/aws-sdk-go/aws"
8+
"github.com/aws/aws-sdk-go/service/ec2"
9+
"github.com/hashicorp/terraform/helper/schema"
10+
)
11+
12+
func dataSourceAwsVpnGateway() *schema.Resource {
13+
return &schema.Resource{
14+
Read: dataSourceAwsVpnGatewayRead,
15+
16+
Schema: map[string]*schema.Schema{
17+
"id": {
18+
Type: schema.TypeString,
19+
Optional: true,
20+
Computed: true,
21+
},
22+
"state": {
23+
Type: schema.TypeString,
24+
Optional: true,
25+
Computed: true,
26+
},
27+
"attached_vpc_id": {
28+
Type: schema.TypeString,
29+
Optional: true,
30+
Computed: true,
31+
},
32+
"availability_zone": {
33+
Type: schema.TypeString,
34+
Optional: true,
35+
Computed: true,
36+
},
37+
"filter": ec2CustomFiltersSchema(),
38+
"tags": tagsSchemaComputed(),
39+
},
40+
}
41+
}
42+
43+
func dataSourceAwsVpnGatewayRead(d *schema.ResourceData, meta interface{}) error {
44+
conn := meta.(*AWSClient).ec2conn
45+
46+
log.Printf("[DEBUG] Reading VPN Gateways.")
47+
48+
req := &ec2.DescribeVpnGatewaysInput{}
49+
50+
if id, ok := d.GetOk("id"); ok {
51+
req.VpnGatewayIds = aws.StringSlice([]string{id.(string)})
52+
}
53+
54+
req.Filters = buildEC2AttributeFilterList(
55+
map[string]string{
56+
"state": d.Get("state").(string),
57+
"availability-zone": d.Get("availability_zone").(string),
58+
},
59+
)
60+
if id, ok := d.GetOk("attached_vpc_id"); ok {
61+
req.Filters = append(req.Filters, buildEC2AttributeFilterList(
62+
map[string]string{
63+
"attachment.state": "attached",
64+
"attachment.vpc-id": id.(string),
65+
},
66+
)...)
67+
}
68+
req.Filters = append(req.Filters, buildEC2TagFilterList(
69+
tagsFromMap(d.Get("tags").(map[string]interface{})),
70+
)...)
71+
req.Filters = append(req.Filters, buildEC2CustomFilterList(
72+
d.Get("filter").(*schema.Set),
73+
)...)
74+
if len(req.Filters) == 0 {
75+
// Don't send an empty filters list; the EC2 API won't accept it.
76+
req.Filters = nil
77+
}
78+
79+
resp, err := conn.DescribeVpnGateways(req)
80+
if err != nil {
81+
return err
82+
}
83+
if resp == nil || len(resp.VpnGateways) == 0 {
84+
return fmt.Errorf("no matching VPN gateway found: %#v", req)
85+
}
86+
if len(resp.VpnGateways) > 1 {
87+
return fmt.Errorf("multiple VPN gateways matched; use additional constraints to reduce matches to a single VPN gateway")
88+
}
89+
90+
vgw := resp.VpnGateways[0]
91+
92+
d.SetId(aws.StringValue(vgw.VpnGatewayId))
93+
d.Set("state", vgw.State)
94+
d.Set("availability_zone", vgw.AvailabilityZone)
95+
d.Set("tags", tagsToMap(vgw.Tags))
96+
97+
for _, attachment := range vgw.VpcAttachments {
98+
if *attachment.State == "attached" {
99+
d.Set("attached_vpc_id", attachment.VpcId)
100+
break
101+
}
102+
}
103+
104+
return nil
105+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// make testacc TEST=./builtin/providers/aws/ TESTARGS='-run=TestAccDataSourceAwsVpnGateway_'
2+
package aws
3+
4+
import (
5+
"fmt"
6+
"regexp"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform/helper/acctest"
10+
"github.com/hashicorp/terraform/helper/resource"
11+
)
12+
13+
func TestAccDataSourceAwsVpnGateway_unattached(t *testing.T) {
14+
rInt := acctest.RandInt()
15+
16+
resource.Test(t, resource.TestCase{
17+
PreCheck: func() { testAccPreCheck(t) },
18+
Providers: testAccProviders,
19+
Steps: []resource.TestStep{
20+
resource.TestStep{
21+
Config: testAccDataSourceAwsVpnGatewayUnattachedConfig(rInt),
22+
Check: resource.ComposeTestCheckFunc(
23+
resource.TestCheckResourceAttrPair(
24+
"data.aws_vpn_gateway.test_by_id", "id",
25+
"aws_vpn_gateway.unattached", "id"),
26+
resource.TestCheckResourceAttrPair(
27+
"data.aws_vpn_gateway.test_by_tags", "id",
28+
"aws_vpn_gateway.unattached", "id"),
29+
resource.TestCheckResourceAttrSet("data.aws_vpn_gateway.test_by_id", "state"),
30+
resource.TestCheckResourceAttr("data.aws_vpn_gateway.test_by_tags", "tags.%", "3"),
31+
resource.TestCheckNoResourceAttr("data.aws_vpn_gateway.test_by_id", "attached_vpc_id"),
32+
),
33+
},
34+
},
35+
})
36+
}
37+
38+
func TestAccDataSourceAwsVpnGateway_attached(t *testing.T) {
39+
rInt := acctest.RandInt()
40+
41+
resource.Test(t, resource.TestCase{
42+
PreCheck: func() { testAccPreCheck(t) },
43+
Providers: testAccProviders,
44+
Steps: []resource.TestStep{
45+
resource.TestStep{
46+
Config: testAccDataSourceAwsVpnGatewayAttachedConfig(rInt),
47+
Check: resource.ComposeTestCheckFunc(
48+
resource.TestCheckResourceAttrPair(
49+
"data.aws_vpn_gateway.test_by_attached_vpc_id", "id",
50+
"aws_vpn_gateway.attached", "id"),
51+
resource.TestCheckResourceAttrPair(
52+
"data.aws_vpn_gateway.test_by_attached_vpc_id", "attached_vpc_id",
53+
"aws_vpc.foo", "id"),
54+
resource.TestMatchResourceAttr("data.aws_vpn_gateway.test_by_attached_vpc_id", "state", regexp.MustCompile("(?i)available")),
55+
),
56+
},
57+
},
58+
})
59+
}
60+
61+
func testAccDataSourceAwsVpnGatewayUnattachedConfig(rInt int) string {
62+
return fmt.Sprintf(`
63+
provider "aws" {
64+
region = "us-west-2"
65+
}
66+
67+
resource "aws_vpn_gateway" "unattached" {
68+
tags {
69+
Name = "terraform-testacc-vpn-gateway-data-source-unattached-%d"
70+
ABC = "testacc-%d"
71+
XYZ = "testacc-%d"
72+
}
73+
}
74+
75+
data "aws_vpn_gateway" "test_by_id" {
76+
id = "${aws_vpn_gateway.unattached.id}"
77+
}
78+
79+
data "aws_vpn_gateway" "test_by_tags" {
80+
tags = "${aws_vpn_gateway.unattached.tags}"
81+
}
82+
`, rInt, rInt+1, rInt-1)
83+
}
84+
85+
func testAccDataSourceAwsVpnGatewayAttachedConfig(rInt int) string {
86+
return fmt.Sprintf(`
87+
provider "aws" {
88+
region = "us-west-2"
89+
}
90+
91+
resource "aws_vpc" "foo" {
92+
cidr_block = "10.1.0.0/16"
93+
94+
tags {
95+
Name = "terraform-testacc-vpn-gateway-data-source-foo-%d"
96+
}
97+
}
98+
99+
resource "aws_vpn_gateway" "attached" {
100+
tags {
101+
Name = "terraform-testacc-vpn-gateway-data-source-attached-%d"
102+
}
103+
}
104+
105+
resource "aws_vpn_gateway_attachment" "vpn_attachment" {
106+
vpc_id = "${aws_vpc.foo.id}"
107+
vpn_gateway_id = "${aws_vpn_gateway.attached.id}"
108+
}
109+
110+
data "aws_vpn_gateway" "test_by_attached_vpc_id" {
111+
attached_vpc_id = "${aws_vpn_gateway_attachment.vpn_attachment.vpc_id}"
112+
}
113+
`, rInt, rInt)
114+
}

builtin/providers/aws/provider.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ func Provider() terraform.ResourceProvider {
179179
"aws_iam_server_certificate": dataSourceAwsIAMServerCertificate(),
180180
"aws_instance": dataSourceAwsInstance(),
181181
"aws_ip_ranges": dataSourceAwsIPRanges(),
182+
"aws_kms_secret": dataSourceAwsKmsSecret(),
182183
"aws_partition": dataSourceAwsPartition(),
183184
"aws_prefix_list": dataSourceAwsPrefixList(),
184185
"aws_redshift_service_account": dataSourceAwsRedshiftServiceAccount(),
@@ -192,7 +193,7 @@ func Provider() terraform.ResourceProvider {
192193
"aws_vpc_endpoint": dataSourceAwsVpcEndpoint(),
193194
"aws_vpc_endpoint_service": dataSourceAwsVpcEndpointService(),
194195
"aws_vpc_peering_connection": dataSourceAwsVpcPeeringConnection(),
195-
"aws_kms_secret": dataSourceAwsKmsSecret(),
196+
"aws_vpn_gateway": dataSourceAwsVpnGateway(),
196197
},
197198

198199
ResourcesMap: map[string]*schema.Resource{

helper/resource/testing.go

Lines changed: 68 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -549,15 +549,9 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc {
549549
// know ahead of time what the values will be.
550550
func TestCheckResourceAttrSet(name, key string) TestCheckFunc {
551551
return func(s *terraform.State) error {
552-
ms := s.RootModule()
553-
rs, ok := ms.Resources[name]
554-
if !ok {
555-
return fmt.Errorf("Not found: %s", name)
556-
}
557-
558-
is := rs.Primary
559-
if is == nil {
560-
return fmt.Errorf("No primary instance: %s", name)
552+
is, err := primaryInstanceState(s, name)
553+
if err != nil {
554+
return err
561555
}
562556

563557
if val, ok := is.Attributes[key]; ok && val != "" {
@@ -568,17 +562,13 @@ func TestCheckResourceAttrSet(name, key string) TestCheckFunc {
568562
}
569563
}
570564

565+
// TestCheckResourceAttr is a TestCheckFunc which validates
566+
// the value in state for the given name/key combination.
571567
func TestCheckResourceAttr(name, key, value string) TestCheckFunc {
572568
return func(s *terraform.State) error {
573-
ms := s.RootModule()
574-
rs, ok := ms.Resources[name]
575-
if !ok {
576-
return fmt.Errorf("Not found: %s", name)
577-
}
578-
579-
is := rs.Primary
580-
if is == nil {
581-
return fmt.Errorf("No primary instance: %s", name)
569+
is, err := primaryInstanceState(s, name)
570+
if err != nil {
571+
return err
582572
}
583573

584574
if v, ok := is.Attributes[key]; !ok || v != value {
@@ -591,7 +581,7 @@ func TestCheckResourceAttr(name, key, value string) TestCheckFunc {
591581
name,
592582
key,
593583
value,
594-
is.Attributes[key])
584+
v)
595585
}
596586

597587
return nil
@@ -602,15 +592,9 @@ func TestCheckResourceAttr(name, key, value string) TestCheckFunc {
602592
// NO value exists in state for the given name/key combination.
603593
func TestCheckNoResourceAttr(name, key string) TestCheckFunc {
604594
return func(s *terraform.State) error {
605-
ms := s.RootModule()
606-
rs, ok := ms.Resources[name]
607-
if !ok {
608-
return fmt.Errorf("Not found: %s", name)
609-
}
610-
611-
is := rs.Primary
612-
if is == nil {
613-
return fmt.Errorf("No primary instance: %s", name)
595+
is, err := primaryInstanceState(s, name)
596+
if err != nil {
597+
return err
614598
}
615599

616600
if _, ok := is.Attributes[key]; ok {
@@ -621,17 +605,13 @@ func TestCheckNoResourceAttr(name, key string) TestCheckFunc {
621605
}
622606
}
623607

608+
// TestMatchResourceAttr is a TestCheckFunc which checks that the value
609+
// in state for the given name/key combination matches the given regex.
624610
func TestMatchResourceAttr(name, key string, r *regexp.Regexp) TestCheckFunc {
625611
return func(s *terraform.State) error {
626-
ms := s.RootModule()
627-
rs, ok := ms.Resources[name]
628-
if !ok {
629-
return fmt.Errorf("Not found: %s", name)
630-
}
631-
632-
is := rs.Primary
633-
if is == nil {
634-
return fmt.Errorf("No primary instance: %s", name)
612+
is, err := primaryInstanceState(s, name)
613+
if err != nil {
614+
return err
635615
}
636616

637617
if !r.MatchString(is.Attributes[key]) {
@@ -656,6 +636,41 @@ func TestCheckResourceAttrPtr(name string, key string, value *string) TestCheckF
656636
}
657637
}
658638

639+
// TestCheckResourceAttrPair is a TestCheckFunc which validates that the values
640+
// in state for a pair of name/key combinations are equal.
641+
func TestCheckResourceAttrPair(nameFirst, keyFirst, nameSecond, keySecond string) TestCheckFunc {
642+
return func(s *terraform.State) error {
643+
isFirst, err := primaryInstanceState(s, nameFirst)
644+
if err != nil {
645+
return err
646+
}
647+
vFirst, ok := isFirst.Attributes[keyFirst]
648+
if !ok {
649+
return fmt.Errorf("%s: Attribute '%s' not found", nameFirst, keyFirst)
650+
}
651+
652+
isSecond, err := primaryInstanceState(s, nameSecond)
653+
if err != nil {
654+
return err
655+
}
656+
vSecond, ok := isSecond.Attributes[keySecond]
657+
if !ok {
658+
return fmt.Errorf("%s: Attribute '%s' not found", nameSecond, keySecond)
659+
}
660+
661+
if vFirst != vSecond {
662+
return fmt.Errorf(
663+
"%s: Attribute '%s' expected %#v, got %#v",
664+
nameFirst,
665+
keyFirst,
666+
vSecond,
667+
vFirst)
668+
}
669+
670+
return nil
671+
}
672+
}
673+
659674
// TestCheckOutput checks an output in the Terraform configuration
660675
func TestCheckOutput(name, value string) TestCheckFunc {
661676
return func(s *terraform.State) error {
@@ -708,3 +723,19 @@ type TestT interface {
708723

709724
// This is set to true by unit tests to alter some behavior
710725
var testTesting = false
726+
727+
// primaryInstanceState returns the primary instance state for the given resource name.
728+
func primaryInstanceState(s *terraform.State, name string) (*terraform.InstanceState, error) {
729+
ms := s.RootModule()
730+
rs, ok := ms.Resources[name]
731+
if !ok {
732+
return nil, fmt.Errorf("Not found: %s", name)
733+
}
734+
735+
is := rs.Primary
736+
if is == nil {
737+
return nil, fmt.Errorf("No primary instance: %s", name)
738+
}
739+
740+
return is, nil
741+
}

0 commit comments

Comments
 (0)