Skip to content

Commit aa0b601

Browse files
provider/aws: aws_vpc data source
1 parent 82f958c commit aa0b601

5 files changed

Lines changed: 299 additions & 0 deletions

File tree

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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 dataSourceAwsVpc() *schema.Resource {
13+
return &schema.Resource{
14+
Read: dataSourceAwsVpcRead,
15+
16+
Schema: map[string]*schema.Schema{
17+
"cidr_block": &schema.Schema{
18+
Type: schema.TypeString,
19+
Optional: true,
20+
Computed: true,
21+
},
22+
23+
"dhcp_options_id": &schema.Schema{
24+
Type: schema.TypeString,
25+
Optional: true,
26+
Computed: true,
27+
},
28+
29+
"default": &schema.Schema{
30+
Type: schema.TypeBool,
31+
Optional: true,
32+
Computed: true,
33+
},
34+
35+
"filter": ec2CustomFiltersSchema(),
36+
37+
"id": &schema.Schema{
38+
Type: schema.TypeString,
39+
Optional: true,
40+
Computed: true,
41+
},
42+
43+
"instance_tenancy": &schema.Schema{
44+
Type: schema.TypeString,
45+
Computed: true,
46+
},
47+
48+
"state": &schema.Schema{
49+
Type: schema.TypeString,
50+
Optional: true,
51+
Computed: true,
52+
},
53+
54+
"tags": tagsSchemaComputed(),
55+
},
56+
}
57+
}
58+
59+
func dataSourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error {
60+
conn := meta.(*AWSClient).ec2conn
61+
62+
req := &ec2.DescribeVpcsInput{}
63+
64+
if id := d.Get("id"); id != "" {
65+
req.VpcIds = []*string{aws.String(id.(string))}
66+
}
67+
68+
// We specify "default" as boolean, but EC2 filters want
69+
// it to be serialized as a string. Note that setting it to
70+
// "false" here does not actually filter by it *not* being
71+
// the default, because Terraform can't distinguish between
72+
// "false" and "not set".
73+
isDefaultStr := ""
74+
if d.Get("default").(bool) {
75+
isDefaultStr = "true"
76+
}
77+
78+
req.Filters = buildEC2AttributeFilterList(
79+
map[string]string{
80+
"cidr": d.Get("cidr_block").(string),
81+
"dhcp-options-id": d.Get("dhcp_options_id").(string),
82+
"isDefault": isDefaultStr,
83+
"state": d.Get("state").(string),
84+
},
85+
)
86+
req.Filters = append(req.Filters, buildEC2TagFilterList(
87+
tagsFromMap(d.Get("tags").(map[string]interface{})),
88+
)...)
89+
req.Filters = append(req.Filters, buildEC2CustomFilterList(
90+
d.Get("filter").(*schema.Set),
91+
)...)
92+
if len(req.Filters) == 0 {
93+
// Don't send an empty filters list; the EC2 API won't accept it.
94+
req.Filters = nil
95+
}
96+
97+
log.Printf("[DEBUG] DescribeVpcs %s\n", req)
98+
resp, err := conn.DescribeVpcs(req)
99+
if err != nil {
100+
return err
101+
}
102+
if resp == nil || len(resp.Vpcs) == 0 {
103+
return fmt.Errorf("no matching VPC found")
104+
}
105+
if len(resp.Vpcs) > 1 {
106+
return fmt.Errorf("multiple VPCs matched; use additional constraints to reduce matches to a single VPC")
107+
}
108+
109+
vpc := resp.Vpcs[0]
110+
111+
d.SetId(*vpc.VpcId)
112+
d.Set("id", vpc.VpcId)
113+
d.Set("cidr_block", vpc.CidrBlock)
114+
d.Set("dhcp_options_id", vpc.DhcpOptionsId)
115+
d.Set("instance_tenancy", vpc.InstanceTenancy)
116+
d.Set("default", vpc.IsDefault)
117+
d.Set("state", vpc.State)
118+
d.Set("tags", tagsToMap(vpc.Tags))
119+
120+
return nil
121+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package aws
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform/helper/resource"
8+
"github.com/hashicorp/terraform/terraform"
9+
)
10+
11+
func TestAccDataSourceAwsVpc(t *testing.T) {
12+
resource.Test(t, resource.TestCase{
13+
PreCheck: func() { testAccPreCheck(t) },
14+
Providers: testAccProviders,
15+
Steps: []resource.TestStep{
16+
resource.TestStep{
17+
Config: testAccDataSourceAwsVpcConfig,
18+
Check: resource.ComposeTestCheckFunc(
19+
testAccDataSourceAwsVpcCheck("data.aws_vpc.by_id"),
20+
testAccDataSourceAwsVpcCheck("data.aws_vpc.by_cidr"),
21+
testAccDataSourceAwsVpcCheck("data.aws_vpc.by_tag"),
22+
testAccDataSourceAwsVpcCheck("data.aws_vpc.by_filter"),
23+
),
24+
},
25+
},
26+
})
27+
}
28+
29+
func testAccDataSourceAwsVpcCheck(name string) resource.TestCheckFunc {
30+
return func(s *terraform.State) error {
31+
rs, ok := s.RootModule().Resources[name]
32+
if !ok {
33+
return fmt.Errorf("root module has no resource called %s", name)
34+
}
35+
36+
vpcRs, ok := s.RootModule().Resources["aws_vpc.test"]
37+
if !ok {
38+
return fmt.Errorf("can't find aws_vpc.test in state")
39+
}
40+
41+
attr := rs.Primary.Attributes
42+
43+
if attr["id"] != vpcRs.Primary.Attributes["id"] {
44+
return fmt.Errorf(
45+
"id is %s; want %s",
46+
attr["id"],
47+
vpcRs.Primary.Attributes["id"],
48+
)
49+
}
50+
51+
if attr["cidr_block"] != "172.16.0.0/16" {
52+
return fmt.Errorf("bad cidr_block %s", attr["cidr_block"])
53+
}
54+
if attr["tags.Name"] != "terraform-testacc-vpc-data-source" {
55+
return fmt.Errorf("bad Name tag %s", attr["tags.Name"])
56+
}
57+
58+
return nil
59+
}
60+
}
61+
62+
const testAccDataSourceAwsVpcConfig = `
63+
provider "aws" {
64+
region = "us-west-2"
65+
}
66+
67+
resource "aws_vpc" "test" {
68+
cidr_block = "172.16.0.0/16"
69+
70+
tags {
71+
Name = "terraform-testacc-vpc-data-source"
72+
}
73+
}
74+
75+
data "aws_vpc" "by_id" {
76+
id = "${aws_vpc.test.id}"
77+
}
78+
79+
data "aws_vpc" "by_cidr" {
80+
cidr_block = "${aws_vpc.test.cidr_block}"
81+
}
82+
83+
data "aws_vpc" "by_tag" {
84+
tags {
85+
Name = "${aws_vpc.test.tags["Name"]}"
86+
}
87+
}
88+
89+
data "aws_vpc" "by_filter" {
90+
filter {
91+
name = "cidr"
92+
values = ["${aws_vpc.test.cidr_block}"]
93+
}
94+
}
95+
`

builtin/providers/aws/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ func Provider() terraform.ResourceProvider {
154154
"aws_redshift_service_account": dataSourceAwsRedshiftServiceAccount(),
155155
"aws_s3_bucket_object": dataSourceAwsS3BucketObject(),
156156
"aws_subnet": dataSourceAwsSubnet(),
157+
"aws_vpc": dataSourceAwsVpc(),
157158
},
158159

159160
ResourcesMap: map[string]*schema.Resource{
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
layout: "aws"
3+
page_title: "AWS: aws_vpc"
4+
sidebar_current: "docs-aws-datasource-vpc"
5+
description: |-
6+
Provides details about a specific VPC
7+
---
8+
9+
# aws\_vpc
10+
11+
`aws_vpc` provides details about a specific VPC.
12+
13+
This resource can prove useful when a module accepts a vpc id as
14+
an input variable and needs to, for example, determine the CIDR block of that
15+
VPC.
16+
17+
## Example Usage
18+
19+
The following example shows how one might accept a VPC id as a variable
20+
and use this data source to obtain the data necessary to create a subnet
21+
within it.
22+
23+
```
24+
variable "vpc_id" {}
25+
26+
data "aws_vpc" "selected" {
27+
id = "${var.vpc_id}"
28+
}
29+
30+
resource "aws_subnet" "example" {
31+
vpc_id = "${aws_vpc.selected.id}"
32+
availability_zone = "us-west-2a"
33+
cidr_block = "${cidrsubnet(aws_vpc.selected.cidr_block, 4, 1)}"
34+
}
35+
```
36+
37+
## Argument Reference
38+
39+
The arguments of this data source act as filters for querying the available
40+
VPCs in the current region. The given filters must match exactly one
41+
VPC whose data will be exported as attributes.
42+
43+
* `cidr_block` - (Optional) The cidr block of the desired VPC.
44+
45+
* `dhcp_options_id` - (Optional) The DHCP options id of the desired VPC.
46+
47+
* `default` - (Optional) Boolean constraint on whether the desired VPC is
48+
the default VPC for the region.
49+
50+
* `filter` - (Optional) Custom filter block as described below.
51+
52+
* `id` - (Optional) The id of the specific VPC to retrieve.
53+
54+
* `state` - (Optional) The current state of the desired VPC.
55+
Can be either `"pending"` or `"available"`.
56+
57+
* `tags` - (Optional) A mapping of tags, each pair of which must exactly match
58+
a pair on the desired VPC.
59+
60+
More complex filters can be expressed using one or more `filter` sub-blocks,
61+
which take the following arguments:
62+
63+
* `name` - (Required) The name of the field to filter by, as defined by
64+
[the underlying AWS API](http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html).
65+
66+
* `values` - (Required) Set of values that are accepted for the given field.
67+
A VPC will be selected if any one of the given values matches.
68+
69+
## Attributes Reference
70+
71+
All of the argument attributes except `filter` blocks are also exported as
72+
result attributes. This data source will complete the data by populating
73+
any fields that are not included in the configuration with the data for
74+
the selected VPC.
75+
76+
The following attribute is additionally exported:
77+
78+
* `instance_tenancy` - The allowed tenancy of instances launched into the
79+
selected VPC. May be any of `"default"`, `"dedicated"`, or `"host"`.

website/source/layouts/aws.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
<li<%= sidebar_current("docs-aws-datasource-subnet") %>>
4848
<a href="/docs/providers/aws/d/subnet.html">aws_subnet</a>
4949
</li>
50+
<li<%= sidebar_current("docs-aws-datasource-vpc") %>>
51+
<a href="/docs/providers/aws/d/vpc.html">aws_vpc</a>
52+
</li>
5053
</ul>
5154
</li>
5255

0 commit comments

Comments
 (0)