mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Merge pull request #6819 from hashicorp/f-aws-vpc-data-sources
provider/aws: data sources for AWS network planning
This commit is contained in:
commit
46ee2ef51a
89
builtin/providers/aws/data_source_aws_availability_zone.go
Normal file
89
builtin/providers/aws/data_source_aws_availability_zone.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
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 dataSourceAwsAvailabilityZone() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Read: dataSourceAwsAvailabilityZoneRead,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"region": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"name_suffix": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"state": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dataSourceAwsAvailabilityZoneRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
req := &ec2.DescribeAvailabilityZonesInput{}
|
||||||
|
|
||||||
|
if name := d.Get("name"); name != "" {
|
||||||
|
req.ZoneNames = []*string{aws.String(name.(string))}
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Filters = buildEC2AttributeFilterList(
|
||||||
|
map[string]string{
|
||||||
|
"state": d.Get("state").(string),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if len(req.Filters) == 0 {
|
||||||
|
// Don't send an empty filters list; the EC2 API won't accept it.
|
||||||
|
req.Filters = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] DescribeAvailabilityZones %s\n", req)
|
||||||
|
resp, err := conn.DescribeAvailabilityZones(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if resp == nil || len(resp.AvailabilityZones) == 0 {
|
||||||
|
return fmt.Errorf("no matching AZ found")
|
||||||
|
}
|
||||||
|
if len(resp.AvailabilityZones) > 1 {
|
||||||
|
return fmt.Errorf("multiple AZs matched; use additional constraints to reduce matches to a single AZ")
|
||||||
|
}
|
||||||
|
|
||||||
|
az := resp.AvailabilityZones[0]
|
||||||
|
|
||||||
|
// As a convenience when working with AZs generically, we expose
|
||||||
|
// the AZ suffix alone, without the region name.
|
||||||
|
// This can be used e.g. to create lookup tables by AZ letter that
|
||||||
|
// work regardless of region.
|
||||||
|
nameSuffix := (*az.ZoneName)[len(*az.RegionName):]
|
||||||
|
|
||||||
|
d.SetId(*az.ZoneName)
|
||||||
|
d.Set("id", az.ZoneName)
|
||||||
|
d.Set("name", az.ZoneName)
|
||||||
|
d.Set("name_suffix", nameSuffix)
|
||||||
|
d.Set("region", az.RegionName)
|
||||||
|
d.Set("state", az.State)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccDataSourceAwsAvailabilityZone(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccDataSourceAwsAvailabilityZoneConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccDataSourceAwsAvailabilityZoneCheck("data.aws_availability_zone.by_name"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccDataSourceAwsAvailabilityZoneCheck(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)
|
||||||
|
}
|
||||||
|
|
||||||
|
attr := rs.Primary.Attributes
|
||||||
|
|
||||||
|
if attr["name"] != "us-west-2a" {
|
||||||
|
return fmt.Errorf("bad name %s", attr["name"])
|
||||||
|
}
|
||||||
|
if attr["name_suffix"] != "a" {
|
||||||
|
return fmt.Errorf("bad name_suffix %s", attr["name_suffix"])
|
||||||
|
}
|
||||||
|
if attr["region"] != "us-west-2" {
|
||||||
|
return fmt.Errorf("bad region %s", attr["region"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccDataSourceAwsAvailabilityZoneConfig = `
|
||||||
|
provider "aws" {
|
||||||
|
region = "us-west-2"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_availability_zone" "by_name" {
|
||||||
|
name = "us-west-2a"
|
||||||
|
}
|
||||||
|
`
|
84
builtin/providers/aws/data_source_aws_region.go
Normal file
84
builtin/providers/aws/data_source_aws_region.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
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 dataSourceAwsRegion() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Read: dataSourceAwsRegionRead,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"current": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"endpoint": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dataSourceAwsRegionRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
currentRegion := meta.(*AWSClient).region
|
||||||
|
|
||||||
|
req := &ec2.DescribeRegionsInput{}
|
||||||
|
|
||||||
|
req.RegionNames = make([]*string, 0, 2)
|
||||||
|
if name := d.Get("name").(string); name != "" {
|
||||||
|
req.RegionNames = append(req.RegionNames, aws.String(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Get("current").(bool) {
|
||||||
|
req.RegionNames = append(req.RegionNames, aws.String(currentRegion))
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Filters = buildEC2AttributeFilterList(
|
||||||
|
map[string]string{
|
||||||
|
"endpoint": d.Get("endpoint").(string),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if len(req.Filters) == 0 {
|
||||||
|
// Don't send an empty filters list; the EC2 API won't accept it.
|
||||||
|
req.Filters = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] DescribeRegions %s\n", req)
|
||||||
|
resp, err := conn.DescribeRegions(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if resp == nil || len(resp.Regions) == 0 {
|
||||||
|
return fmt.Errorf("no matching regions found")
|
||||||
|
}
|
||||||
|
if len(resp.Regions) > 1 {
|
||||||
|
return fmt.Errorf("multiple regions matched; use additional constraints to reduce matches to a single region")
|
||||||
|
}
|
||||||
|
|
||||||
|
region := resp.Regions[0]
|
||||||
|
|
||||||
|
d.SetId(*region.RegionName)
|
||||||
|
d.Set("id", region.RegionName)
|
||||||
|
d.Set("name", region.RegionName)
|
||||||
|
d.Set("endpoint", region.Endpoint)
|
||||||
|
d.Set("current", *region.RegionName == currentRegion)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
64
builtin/providers/aws/data_source_aws_region_test.go
Normal file
64
builtin/providers/aws/data_source_aws_region_test.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccDataSourceAwsRegion(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccDataSourceAwsRegionConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccDataSourceAwsRegionCheck("data.aws_region.by_name_current", "us-west-2", "true"),
|
||||||
|
testAccDataSourceAwsRegionCheck("data.aws_region.by_name_other", "us-west-1", "false"),
|
||||||
|
testAccDataSourceAwsRegionCheck("data.aws_region.by_current", "us-west-2", "true"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccDataSourceAwsRegionCheck(name, region, current 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
attr := rs.Primary.Attributes
|
||||||
|
|
||||||
|
if attr["name"] != region {
|
||||||
|
return fmt.Errorf("bad name %s", attr["name"])
|
||||||
|
}
|
||||||
|
if attr["current"] != current {
|
||||||
|
return fmt.Errorf("bad current %s; want %s", attr["current"], current)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccDataSourceAwsRegionConfig = `
|
||||||
|
provider "aws" {
|
||||||
|
region = "us-west-2"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_region" "by_name_current" {
|
||||||
|
name = "us-west-2"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_region" "by_name_other" {
|
||||||
|
name = "us-west-1"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_region" "by_current" {
|
||||||
|
current = true
|
||||||
|
}
|
||||||
|
`
|
123
builtin/providers/aws/data_source_aws_subnet.go
Normal file
123
builtin/providers/aws/data_source_aws_subnet.go
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
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 dataSourceAwsSubnet() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Read: dataSourceAwsSubnetRead,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"availability_zone": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"cidr_block": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"default_for_az": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"filter": ec2CustomFiltersSchema(),
|
||||||
|
|
||||||
|
"id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"state": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"tags": tagsSchemaComputed(),
|
||||||
|
|
||||||
|
"vpc_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dataSourceAwsSubnetRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
req := &ec2.DescribeSubnetsInput{}
|
||||||
|
|
||||||
|
if id := d.Get("id"); id != "" {
|
||||||
|
req.SubnetIds = []*string{aws.String(id.(string))}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We specify default_for_az as boolean, but EC2 filters want
|
||||||
|
// it to be serialized as a string. Note that setting it to
|
||||||
|
// "false" here does not actually filter by it *not* being
|
||||||
|
// the default, because Terraform can't distinguish between
|
||||||
|
// "false" and "not set".
|
||||||
|
defaultForAzStr := ""
|
||||||
|
if d.Get("default_for_az").(bool) {
|
||||||
|
defaultForAzStr = "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Filters = buildEC2AttributeFilterList(
|
||||||
|
map[string]string{
|
||||||
|
"availabilityZone": d.Get("availability_zone").(string),
|
||||||
|
"cidrBlock": d.Get("cidr_block").(string),
|
||||||
|
"defaultForAz": defaultForAzStr,
|
||||||
|
"state": d.Get("state").(string),
|
||||||
|
"vpc-id": d.Get("vpc_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
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] DescribeSubnets %s\n", req)
|
||||||
|
resp, err := conn.DescribeSubnets(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if resp == nil || len(resp.Subnets) == 0 {
|
||||||
|
return fmt.Errorf("no matching subnet found")
|
||||||
|
}
|
||||||
|
if len(resp.Subnets) > 1 {
|
||||||
|
return fmt.Errorf("multiple subnets matched; use additional constraints to reduce matches to a single subnet")
|
||||||
|
}
|
||||||
|
|
||||||
|
subnet := resp.Subnets[0]
|
||||||
|
|
||||||
|
d.SetId(*subnet.SubnetId)
|
||||||
|
d.Set("id", subnet.SubnetId)
|
||||||
|
d.Set("vpc_id", subnet.VpcId)
|
||||||
|
d.Set("availability_zone", subnet.AvailabilityZone)
|
||||||
|
d.Set("cidr_block", subnet.CidrBlock)
|
||||||
|
d.Set("default_for_az", subnet.DefaultForAz)
|
||||||
|
d.Set("state", subnet.State)
|
||||||
|
d.Set("tags", tagsToMap(subnet.Tags))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
125
builtin/providers/aws/data_source_aws_subnet_test.go
Normal file
125
builtin/providers/aws/data_source_aws_subnet_test.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccDataSourceAwsSubnet(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccDataSourceAwsSubnetConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccDataSourceAwsSubnetCheck("data.aws_subnet.by_id"),
|
||||||
|
testAccDataSourceAwsSubnetCheck("data.aws_subnet.by_cidr"),
|
||||||
|
testAccDataSourceAwsSubnetCheck("data.aws_subnet.by_tag"),
|
||||||
|
testAccDataSourceAwsSubnetCheck("data.aws_subnet.by_vpc"),
|
||||||
|
testAccDataSourceAwsSubnetCheck("data.aws_subnet.by_filter"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccDataSourceAwsSubnetCheck(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)
|
||||||
|
}
|
||||||
|
|
||||||
|
vpcRs, ok := s.RootModule().Resources["aws_vpc.test"]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("can't find aws_vpc.test in state")
|
||||||
|
}
|
||||||
|
subnetRs, ok := s.RootModule().Resources["aws_subnet.test"]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("can't find aws_subnet.test in state")
|
||||||
|
}
|
||||||
|
|
||||||
|
attr := rs.Primary.Attributes
|
||||||
|
|
||||||
|
if attr["id"] != subnetRs.Primary.Attributes["id"] {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"id is %s; want %s",
|
||||||
|
attr["id"],
|
||||||
|
subnetRs.Primary.Attributes["id"],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr["vpc_id"] != vpcRs.Primary.Attributes["id"] {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"vpc_id is %s; want %s",
|
||||||
|
attr["vpc_id"],
|
||||||
|
vpcRs.Primary.Attributes["id"],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr["cidr_block"] != "172.16.123.0/24" {
|
||||||
|
return fmt.Errorf("bad cidr_block %s", attr["cidr_block"])
|
||||||
|
}
|
||||||
|
if attr["availability_zone"] != "us-west-2a" {
|
||||||
|
return fmt.Errorf("bad availability_zone %s", attr["availability_zone"])
|
||||||
|
}
|
||||||
|
if attr["tags.Name"] != "terraform-testacc-subnet-data-source" {
|
||||||
|
return fmt.Errorf("bad Name tag %s", attr["tags.Name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccDataSourceAwsSubnetConfig = `
|
||||||
|
provider "aws" {
|
||||||
|
region = "us-west-2"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpc" "test" {
|
||||||
|
cidr_block = "172.16.0.0/16"
|
||||||
|
|
||||||
|
tags {
|
||||||
|
Name = "terraform-testacc-subnet-data-source"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_subnet" "test" {
|
||||||
|
vpc_id = "${aws_vpc.test.id}"
|
||||||
|
cidr_block = "172.16.123.0/24"
|
||||||
|
availability_zone = "us-west-2a"
|
||||||
|
|
||||||
|
tags {
|
||||||
|
Name = "terraform-testacc-subnet-data-source"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_subnet" "by_id" {
|
||||||
|
id = "${aws_subnet.test.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_subnet" "by_cidr" {
|
||||||
|
cidr_block = "${aws_subnet.test.cidr_block}"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_subnet" "by_tag" {
|
||||||
|
tags {
|
||||||
|
Name = "${aws_subnet.test.tags["Name"]}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_subnet" "by_vpc" {
|
||||||
|
vpc_id = "${aws_subnet.test.vpc_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_subnet" "by_filter" {
|
||||||
|
filter {
|
||||||
|
name = "vpc-id"
|
||||||
|
values = ["${aws_subnet.test.vpc_id}"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
121
builtin/providers/aws/data_source_aws_vpc.go
Normal file
121
builtin/providers/aws/data_source_aws_vpc.go
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
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 dataSourceAwsVpc() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Read: dataSourceAwsVpcRead,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"cidr_block": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"dhcp_options_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"default": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"filter": ec2CustomFiltersSchema(),
|
||||||
|
|
||||||
|
"id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"instance_tenancy": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"state": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"tags": tagsSchemaComputed(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dataSourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
req := &ec2.DescribeVpcsInput{}
|
||||||
|
|
||||||
|
if id := d.Get("id"); id != "" {
|
||||||
|
req.VpcIds = []*string{aws.String(id.(string))}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We specify "default" as boolean, but EC2 filters want
|
||||||
|
// it to be serialized as a string. Note that setting it to
|
||||||
|
// "false" here does not actually filter by it *not* being
|
||||||
|
// the default, because Terraform can't distinguish between
|
||||||
|
// "false" and "not set".
|
||||||
|
isDefaultStr := ""
|
||||||
|
if d.Get("default").(bool) {
|
||||||
|
isDefaultStr = "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Filters = buildEC2AttributeFilterList(
|
||||||
|
map[string]string{
|
||||||
|
"cidr": d.Get("cidr_block").(string),
|
||||||
|
"dhcp-options-id": d.Get("dhcp_options_id").(string),
|
||||||
|
"isDefault": isDefaultStr,
|
||||||
|
"state": d.Get("state").(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
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] DescribeVpcs %s\n", req)
|
||||||
|
resp, err := conn.DescribeVpcs(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if resp == nil || len(resp.Vpcs) == 0 {
|
||||||
|
return fmt.Errorf("no matching VPC found")
|
||||||
|
}
|
||||||
|
if len(resp.Vpcs) > 1 {
|
||||||
|
return fmt.Errorf("multiple VPCs matched; use additional constraints to reduce matches to a single VPC")
|
||||||
|
}
|
||||||
|
|
||||||
|
vpc := resp.Vpcs[0]
|
||||||
|
|
||||||
|
d.SetId(*vpc.VpcId)
|
||||||
|
d.Set("id", vpc.VpcId)
|
||||||
|
d.Set("cidr_block", vpc.CidrBlock)
|
||||||
|
d.Set("dhcp_options_id", vpc.DhcpOptionsId)
|
||||||
|
d.Set("instance_tenancy", vpc.InstanceTenancy)
|
||||||
|
d.Set("default", vpc.IsDefault)
|
||||||
|
d.Set("state", vpc.State)
|
||||||
|
d.Set("tags", tagsToMap(vpc.Tags))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
95
builtin/providers/aws/data_source_aws_vpc_test.go
Normal file
95
builtin/providers/aws/data_source_aws_vpc_test.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccDataSourceAwsVpc(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccDataSourceAwsVpcConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccDataSourceAwsVpcCheck("data.aws_vpc.by_id"),
|
||||||
|
testAccDataSourceAwsVpcCheck("data.aws_vpc.by_cidr"),
|
||||||
|
testAccDataSourceAwsVpcCheck("data.aws_vpc.by_tag"),
|
||||||
|
testAccDataSourceAwsVpcCheck("data.aws_vpc.by_filter"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccDataSourceAwsVpcCheck(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)
|
||||||
|
}
|
||||||
|
|
||||||
|
vpcRs, ok := s.RootModule().Resources["aws_vpc.test"]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("can't find aws_vpc.test in state")
|
||||||
|
}
|
||||||
|
|
||||||
|
attr := rs.Primary.Attributes
|
||||||
|
|
||||||
|
if attr["id"] != vpcRs.Primary.Attributes["id"] {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"id is %s; want %s",
|
||||||
|
attr["id"],
|
||||||
|
vpcRs.Primary.Attributes["id"],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr["cidr_block"] != "172.16.0.0/16" {
|
||||||
|
return fmt.Errorf("bad cidr_block %s", attr["cidr_block"])
|
||||||
|
}
|
||||||
|
if attr["tags.Name"] != "terraform-testacc-vpc-data-source" {
|
||||||
|
return fmt.Errorf("bad Name tag %s", attr["tags.Name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccDataSourceAwsVpcConfig = `
|
||||||
|
provider "aws" {
|
||||||
|
region = "us-west-2"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpc" "test" {
|
||||||
|
cidr_block = "172.16.0.0/16"
|
||||||
|
|
||||||
|
tags {
|
||||||
|
Name = "terraform-testacc-vpc-data-source"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_vpc" "by_id" {
|
||||||
|
id = "${aws_vpc.test.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_vpc" "by_cidr" {
|
||||||
|
cidr_block = "${aws_vpc.test.cidr_block}"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_vpc" "by_tag" {
|
||||||
|
tags {
|
||||||
|
Name = "${aws_vpc.test.tags["Name"]}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_vpc" "by_filter" {
|
||||||
|
filter {
|
||||||
|
name = "cidr"
|
||||||
|
values = ["${aws_vpc.test.cidr_block}"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
153
builtin/providers/aws/ec2_filters.go
Normal file
153
builtin/providers/aws/ec2_filters.go
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
// buildEC2AttributeFilterList takes a flat map of scalar attributes (most
|
||||||
|
// likely values extracted from a *schema.ResourceData on an EC2-querying
|
||||||
|
// data source) and produces a []*ec2.Filter representing an exact match
|
||||||
|
// for each of the given non-empty attributes.
|
||||||
|
//
|
||||||
|
// The keys of the given attributes map are the attribute names expected
|
||||||
|
// by the EC2 API, which are usually either in camelcase or with dash-separated
|
||||||
|
// words. We conventionally map these to underscore-separated identifiers
|
||||||
|
// with the same words when presenting these as data source query attributes
|
||||||
|
// in Terraform.
|
||||||
|
//
|
||||||
|
// It's the callers responsibility to transform any non-string values into
|
||||||
|
// the appropriate string serialization required by the AWS API when
|
||||||
|
// encoding the given filter. Any attributes given with empty string values
|
||||||
|
// are ignored, assuming that the user wishes to leave that attribute
|
||||||
|
// unconstrained while filtering.
|
||||||
|
//
|
||||||
|
// The purpose of this function is to create values to pass in
|
||||||
|
// for the "Filters" attribute on most of the "Describe..." API functions in
|
||||||
|
// the EC2 API, to aid in the implementation of Terraform data sources that
|
||||||
|
// retrieve data about EC2 objects.
|
||||||
|
func buildEC2AttributeFilterList(attrs map[string]string) []*ec2.Filter {
|
||||||
|
filters := make([]*ec2.Filter, 0, len(attrs))
|
||||||
|
|
||||||
|
for filterName, value := range attrs {
|
||||||
|
if value == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
filters = append(filters, &ec2.Filter{
|
||||||
|
Name: aws.String(filterName),
|
||||||
|
Values: []*string{aws.String(value)},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildEC2TagFilterList takes a []*ec2.Tag and produces a []*ec2.Filter that
|
||||||
|
// represents exact matches for all of the tag key/value pairs given in
|
||||||
|
// the tag set.
|
||||||
|
//
|
||||||
|
// The purpose of this function is to create values to pass in for
|
||||||
|
// the "Filters" attribute on most of the "Describe..." API functions
|
||||||
|
// in the EC2 API, to implement filtering by tag values e.g. in Terraform
|
||||||
|
// data sources that retrieve data about EC2 objects.
|
||||||
|
//
|
||||||
|
// It is conventional for an EC2 data source to include an attribute called
|
||||||
|
// "tags" which conforms to the schema returned by the tagsSchema() function.
|
||||||
|
// The value of this can then be converted to a tags slice using tagsFromMap,
|
||||||
|
// and the result finally passed in to this function.
|
||||||
|
//
|
||||||
|
// In Terraform configuration this would then look like this, to constrain
|
||||||
|
// results by name:
|
||||||
|
//
|
||||||
|
// tags {
|
||||||
|
// Name = "my-awesome-subnet"
|
||||||
|
// }
|
||||||
|
func buildEC2TagFilterList(tags []*ec2.Tag) []*ec2.Filter {
|
||||||
|
filters := make([]*ec2.Filter, len(tags))
|
||||||
|
|
||||||
|
for i, tag := range tags {
|
||||||
|
filters[i] = &ec2.Filter{
|
||||||
|
Name: aws.String(fmt.Sprintf("tag:%s", *tag.Key)),
|
||||||
|
Values: []*string{tag.Value},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters
|
||||||
|
}
|
||||||
|
|
||||||
|
// ec2CustomFiltersSchema returns a *schema.Schema that represents
|
||||||
|
// a set of custom filtering criteria that a user can specify as input
|
||||||
|
// to a data source that wraps one of the many "Describe..." API calls
|
||||||
|
// in the EC2 API.
|
||||||
|
//
|
||||||
|
// It is conventional for an attribute of this type to be included
|
||||||
|
// as a top-level attribute called "filter". This is the "catch all" for
|
||||||
|
// filter combinations that are not possible to express using scalar
|
||||||
|
// attributes or tags. In Terraform configuration, the custom filter blocks
|
||||||
|
// then look like this:
|
||||||
|
//
|
||||||
|
// filter {
|
||||||
|
// name = "availabilityZone"
|
||||||
|
// values = ["us-west-2a", "us-west-2b"]
|
||||||
|
// }
|
||||||
|
func ec2CustomFiltersSchema() *schema.Schema {
|
||||||
|
return &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"values": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Required: true,
|
||||||
|
Elem: &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildEC2CustomFilterList takes the set value extracted from a schema
|
||||||
|
// attribute conforming to the schema returned by ec2CustomFiltersSchema,
|
||||||
|
// and transforms it into a []*ec2.Filter representing the same filter
|
||||||
|
// expressions which is ready to pass into the "Filters" attribute on most
|
||||||
|
// of the "Describe..." functions in the EC2 API.
|
||||||
|
//
|
||||||
|
// This function is intended only to be used in conjunction with
|
||||||
|
// ec2CustomFitlersSchema. See the docs on that function for more details
|
||||||
|
// on the configuration pattern this is intended to support.
|
||||||
|
func buildEC2CustomFilterList(filterSet *schema.Set) []*ec2.Filter {
|
||||||
|
if filterSet == nil {
|
||||||
|
return []*ec2.Filter{}
|
||||||
|
}
|
||||||
|
|
||||||
|
customFilters := filterSet.List()
|
||||||
|
filters := make([]*ec2.Filter, len(customFilters))
|
||||||
|
|
||||||
|
for filterIdx, customFilterI := range customFilters {
|
||||||
|
customFilterMapI := customFilterI.(map[string]interface{})
|
||||||
|
name := customFilterMapI["name"].(string)
|
||||||
|
valuesI := customFilterMapI["values"].(*schema.Set).List()
|
||||||
|
values := make([]*string, len(valuesI))
|
||||||
|
for valueIdx, valueI := range valuesI {
|
||||||
|
values[valueIdx] = aws.String(valueI.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
filters[filterIdx] = &ec2.Filter{
|
||||||
|
Name: &name,
|
||||||
|
Values: values,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters
|
||||||
|
}
|
158
builtin/providers/aws/ec2_filters_test.go
Normal file
158
builtin/providers/aws/ec2_filters_test.go
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBuildEC2AttributeFilterList(t *testing.T) {
|
||||||
|
type TestCase struct {
|
||||||
|
Attrs map[string]string
|
||||||
|
Expected []*ec2.Filter
|
||||||
|
}
|
||||||
|
testCases := []TestCase{
|
||||||
|
{
|
||||||
|
map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
"baz": "boo",
|
||||||
|
},
|
||||||
|
[]*ec2.Filter{
|
||||||
|
{
|
||||||
|
Name: aws.String("foo"),
|
||||||
|
Values: []*string{aws.String("bar")},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: aws.String("baz"),
|
||||||
|
Values: []*string{aws.String("boo")},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
"baz": "",
|
||||||
|
},
|
||||||
|
[]*ec2.Filter{
|
||||||
|
{
|
||||||
|
Name: aws.String("foo"),
|
||||||
|
Values: []*string{aws.String("bar")},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, testCase := range testCases {
|
||||||
|
result := buildEC2AttributeFilterList(testCase.Attrs)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(result, testCase.Expected) {
|
||||||
|
t.Errorf(
|
||||||
|
"test case %d: got %#v, but want %#v",
|
||||||
|
i, result, testCase.Expected,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildEC2TagFilterList(t *testing.T) {
|
||||||
|
type TestCase struct {
|
||||||
|
Tags []*ec2.Tag
|
||||||
|
Expected []*ec2.Filter
|
||||||
|
}
|
||||||
|
testCases := []TestCase{
|
||||||
|
{
|
||||||
|
[]*ec2.Tag{
|
||||||
|
{
|
||||||
|
Key: aws.String("foo"),
|
||||||
|
Value: aws.String("bar"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: aws.String("baz"),
|
||||||
|
Value: aws.String("boo"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]*ec2.Filter{
|
||||||
|
{
|
||||||
|
Name: aws.String("tag:foo"),
|
||||||
|
Values: []*string{aws.String("bar")},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: aws.String("tag:baz"),
|
||||||
|
Values: []*string{aws.String("boo")},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, testCase := range testCases {
|
||||||
|
result := buildEC2TagFilterList(testCase.Tags)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(result, testCase.Expected) {
|
||||||
|
t.Errorf(
|
||||||
|
"test case %d: got %#v, but want %#v",
|
||||||
|
i, result, testCase.Expected,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildEC2CustomFilterList(t *testing.T) {
|
||||||
|
|
||||||
|
// We need to get a set with the appropriate hash function,
|
||||||
|
// so we'll use the schema to help us produce what would
|
||||||
|
// be produced in the normal case.
|
||||||
|
filtersSchema := ec2CustomFiltersSchema()
|
||||||
|
|
||||||
|
// The zero value of this schema will be an interface{}
|
||||||
|
// referring to a new, empty *schema.Set with the
|
||||||
|
// appropriate hash function configured.
|
||||||
|
filters := filtersSchema.ZeroValue().(*schema.Set)
|
||||||
|
|
||||||
|
// We also need an appropriately-configured set for
|
||||||
|
// the list of values.
|
||||||
|
valuesSchema := filtersSchema.Elem.(*schema.Resource).Schema["values"]
|
||||||
|
valuesSet := func(vals ...string) *schema.Set {
|
||||||
|
ret := valuesSchema.ZeroValue().(*schema.Set)
|
||||||
|
for _, val := range vals {
|
||||||
|
ret.Add(val)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
filters.Add(map[string]interface{}{
|
||||||
|
"name": "foo",
|
||||||
|
"values": valuesSet("bar", "baz"),
|
||||||
|
})
|
||||||
|
filters.Add(map[string]interface{}{
|
||||||
|
"name": "pizza",
|
||||||
|
"values": valuesSet("cheese"),
|
||||||
|
})
|
||||||
|
|
||||||
|
expected := []*ec2.Filter{
|
||||||
|
// These are produced in the deterministic order guaranteed
|
||||||
|
// by schema.Set.List(), which happens to produce them in
|
||||||
|
// the following order for our current input. If this test
|
||||||
|
// evolves with different input data in future then they
|
||||||
|
// will likely be emitted in a different order, which is fine.
|
||||||
|
{
|
||||||
|
Name: aws.String("pizza"),
|
||||||
|
Values: []*string{aws.String("cheese")},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: aws.String("foo"),
|
||||||
|
Values: []*string{aws.String("bar"), aws.String("baz")},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
result := buildEC2CustomFilterList(filters)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(result, expected) {
|
||||||
|
t.Errorf(
|
||||||
|
"got %#v, but want %#v",
|
||||||
|
result, expected,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -144,6 +144,7 @@ func Provider() terraform.ResourceProvider {
|
|||||||
|
|
||||||
DataSourcesMap: map[string]*schema.Resource{
|
DataSourcesMap: map[string]*schema.Resource{
|
||||||
"aws_ami": dataSourceAwsAmi(),
|
"aws_ami": dataSourceAwsAmi(),
|
||||||
|
"aws_availability_zone": dataSourceAwsAvailabilityZone(),
|
||||||
"aws_availability_zones": dataSourceAwsAvailabilityZones(),
|
"aws_availability_zones": dataSourceAwsAvailabilityZones(),
|
||||||
"aws_billing_service_account": dataSourceAwsBillingServiceAccount(),
|
"aws_billing_service_account": dataSourceAwsBillingServiceAccount(),
|
||||||
"aws_caller_identity": dataSourceAwsCallerIdentity(),
|
"aws_caller_identity": dataSourceAwsCallerIdentity(),
|
||||||
@ -153,7 +154,10 @@ func Provider() terraform.ResourceProvider {
|
|||||||
"aws_iam_policy_document": dataSourceAwsIamPolicyDocument(),
|
"aws_iam_policy_document": dataSourceAwsIamPolicyDocument(),
|
||||||
"aws_ip_ranges": dataSourceAwsIPRanges(),
|
"aws_ip_ranges": dataSourceAwsIPRanges(),
|
||||||
"aws_redshift_service_account": dataSourceAwsRedshiftServiceAccount(),
|
"aws_redshift_service_account": dataSourceAwsRedshiftServiceAccount(),
|
||||||
|
"aws_region": dataSourceAwsRegion(),
|
||||||
"aws_s3_bucket_object": dataSourceAwsS3BucketObject(),
|
"aws_s3_bucket_object": dataSourceAwsS3BucketObject(),
|
||||||
|
"aws_subnet": dataSourceAwsSubnet(),
|
||||||
|
"aws_vpc": dataSourceAwsVpc(),
|
||||||
},
|
},
|
||||||
|
|
||||||
ResourcesMap: map[string]*schema.Resource{
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
|
@ -22,6 +22,14 @@ func tagsSchema() *schema.Schema {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tagsSchemaComputed() *schema.Schema {
|
||||||
|
return &schema.Schema{
|
||||||
|
Type: schema.TypeMap,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func setElbV2Tags(conn *elbv2.ELBV2, d *schema.ResourceData) error {
|
func setElbV2Tags(conn *elbv2.ELBV2, d *schema.ResourceData) error {
|
||||||
if d.HasChange("tags") {
|
if d.HasChange("tags") {
|
||||||
oraw, nraw := d.GetChange("tags")
|
oraw, nraw := d.GetChange("tags")
|
||||||
|
3
examples/aws-networking/.gitignore
vendored
Normal file
3
examples/aws-networking/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
terraform.tfstate
|
||||||
|
terraform.tfstate.backup
|
||||||
|
.terraform/*
|
11
examples/aws-networking/README.md
Normal file
11
examples/aws-networking/README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# AWS Networking Example
|
||||||
|
|
||||||
|
This example creates AWS VPC resources, making a VPC in each of two regions and
|
||||||
|
then two subnets in each VPC in two different availability zones.
|
||||||
|
|
||||||
|
This example also demonstrates the use of modules to create several copies of
|
||||||
|
the same resource set with different arguments. The child modules in this
|
||||||
|
directory are:
|
||||||
|
|
||||||
|
* `region`: container module for all of the network resources within a region. This is instantiated once per region.
|
||||||
|
* `subnet`: represents a subnet within a given availability zone. This is instantiated twice per region, using the first two availability zones supported within the target AWS account.
|
27
examples/aws-networking/numbering/variables.tf
Normal file
27
examples/aws-networking/numbering/variables.tf
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
variable "region_numbers" {
|
||||||
|
default = {
|
||||||
|
us-east-1 = 1
|
||||||
|
us-west-1 = 2
|
||||||
|
us-west-2 = 3
|
||||||
|
eu-west-1 = 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "az_numbers" {
|
||||||
|
default = {
|
||||||
|
a = 1
|
||||||
|
b = 2
|
||||||
|
c = 3
|
||||||
|
d = 4
|
||||||
|
e = 5
|
||||||
|
f = 6
|
||||||
|
g = 7
|
||||||
|
h = 8
|
||||||
|
i = 9
|
||||||
|
j = 10
|
||||||
|
k = 11
|
||||||
|
l = 12
|
||||||
|
m = 13
|
||||||
|
n = 14
|
||||||
|
}
|
||||||
|
}
|
1
examples/aws-networking/region/numbering.tf
Symbolic link
1
examples/aws-networking/region/numbering.tf
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../numbering/variables.tf
|
11
examples/aws-networking/region/outputs.tf
Normal file
11
examples/aws-networking/region/outputs.tf
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
output "vpc_id" {
|
||||||
|
value = "${aws_vpc.main.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "primary_subnet_id" {
|
||||||
|
value = "${module.primary_subnet.subnet_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "secondary_subnet_id" {
|
||||||
|
value = "${module.secondary_subnet.subnet_id}"
|
||||||
|
}
|
25
examples/aws-networking/region/security_group.tf
Normal file
25
examples/aws-networking/region/security_group.tf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
resource "aws_security_group" "region" {
|
||||||
|
name = "region"
|
||||||
|
description = "Open access within this region"
|
||||||
|
vpc_id = "${aws_vpc.main.id}"
|
||||||
|
|
||||||
|
ingress {
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
protocol = -1
|
||||||
|
cidr_blocks = ["${aws_vpc.main.cidr_block}"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group" "internal-all" {
|
||||||
|
name = "internal-all"
|
||||||
|
description = "Open access within the full internal network"
|
||||||
|
vpc_id = "${aws_vpc.main.id}"
|
||||||
|
|
||||||
|
ingress {
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
protocol = -1
|
||||||
|
cidr_blocks = ["${var.base_cidr_block}"]
|
||||||
|
}
|
||||||
|
}
|
14
examples/aws-networking/region/subnets.tf
Normal file
14
examples/aws-networking/region/subnets.tf
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
data "aws_availability_zones" "all" {
|
||||||
|
}
|
||||||
|
|
||||||
|
module "primary_subnet" {
|
||||||
|
source = "../subnet"
|
||||||
|
vpc_id = "${aws_vpc.main.id}"
|
||||||
|
availability_zone = "${data.aws_availability_zones.all.names[0]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
module "secondary_subnet" {
|
||||||
|
source = "../subnet"
|
||||||
|
vpc_id = "${aws_vpc.main.id}"
|
||||||
|
availability_zone = "${data.aws_availability_zones.all.names[1]}"
|
||||||
|
}
|
9
examples/aws-networking/region/variables.tf
Normal file
9
examples/aws-networking/region/variables.tf
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
variable "region" {
|
||||||
|
description = "The name of the AWS region to set up a network within"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "base_cidr_block" {}
|
||||||
|
|
||||||
|
provider "aws" {
|
||||||
|
region = "${var.region}"
|
||||||
|
}
|
7
examples/aws-networking/region/vpc.tf
Normal file
7
examples/aws-networking/region/vpc.tf
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
resource "aws_vpc" "main" {
|
||||||
|
cidr_block = "${cidrsubnet(var.base_cidr_block, 4, lookup(var.region_numbers, var.region))}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_internet_gateway" "main" {
|
||||||
|
vpc_id = "${aws_vpc.main.id}"
|
||||||
|
}
|
11
examples/aws-networking/regions.tf
Normal file
11
examples/aws-networking/regions.tf
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module "us-east-1" {
|
||||||
|
source = "./region"
|
||||||
|
region = "us-east-1"
|
||||||
|
base_cidr_block = "${var.base_cidr_block}"
|
||||||
|
}
|
||||||
|
|
||||||
|
module "us-west-2" {
|
||||||
|
source = "./region"
|
||||||
|
region = "us-west-2"
|
||||||
|
base_cidr_block = "${var.base_cidr_block}"
|
||||||
|
}
|
1
examples/aws-networking/subnet/numbering.tf
Symbolic link
1
examples/aws-networking/subnet/numbering.tf
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../numbering/variables.tf
|
3
examples/aws-networking/subnet/outputs.tf
Normal file
3
examples/aws-networking/subnet/outputs.tf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
output "subnet_id" {
|
||||||
|
value = "${aws_subnet.main.id}"
|
||||||
|
}
|
12
examples/aws-networking/subnet/security_group.tf
Normal file
12
examples/aws-networking/subnet/security_group.tf
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
resource "aws_security_group" "az" {
|
||||||
|
name = "az-${data.aws_availability_zone.target.name}"
|
||||||
|
description = "Open access within the AZ ${data.aws_availability_zone.target.name}"
|
||||||
|
vpc_id = "${var.vpc_id}"
|
||||||
|
|
||||||
|
ingress {
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
protocol = -1
|
||||||
|
cidr_blocks = ["${aws_subnet.main.cidr_block}"]
|
||||||
|
}
|
||||||
|
}
|
13
examples/aws-networking/subnet/subnet.tf
Normal file
13
examples/aws-networking/subnet/subnet.tf
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
resource "aws_subnet" "main" {
|
||||||
|
cidr_block = "${cidrsubnet(data.aws_vpc.target.cidr_block, 4, lookup(var.az_numbers, data.aws_availability_zone.target.name_suffix))}"
|
||||||
|
vpc_id = "${var.vpc_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_route_table" "main" {
|
||||||
|
vpc_id = "${var.vpc_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_route_table_association" "main" {
|
||||||
|
subnet_id = "${aws_subnet.main.id}"
|
||||||
|
route_table_id = "${aws_route_table.main.id}"
|
||||||
|
}
|
11
examples/aws-networking/subnet/variables.tf
Normal file
11
examples/aws-networking/subnet/variables.tf
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
variable "vpc_id" {}
|
||||||
|
|
||||||
|
variable "availability_zone" {}
|
||||||
|
|
||||||
|
data "aws_availability_zone" "target" {
|
||||||
|
name = "${var.availability_zone}"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_vpc" "target" {
|
||||||
|
id = "${var.vpc_id}"
|
||||||
|
}
|
3
examples/aws-networking/variables.tf
Normal file
3
examples/aws-networking/variables.tf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
variable "base_cidr_block" {
|
||||||
|
default = "10.0.0.0/12"
|
||||||
|
}
|
@ -47,14 +47,17 @@ func (n *EvalReadDataDiff) Eval(ctx EvalContext) (interface{}, error) {
|
|||||||
diff = new(InstanceDiff)
|
diff = new(InstanceDiff)
|
||||||
}
|
}
|
||||||
|
|
||||||
// id is always computed, because we're always "creating a new resource"
|
// if id isn't explicitly set then it's always computed, because we're
|
||||||
|
// always "creating a new resource".
|
||||||
diff.init()
|
diff.init()
|
||||||
diff.SetAttribute("id", &ResourceAttrDiff{
|
if _, ok := diff.Attributes["id"]; !ok {
|
||||||
Old: "",
|
diff.SetAttribute("id", &ResourceAttrDiff{
|
||||||
NewComputed: true,
|
Old: "",
|
||||||
RequiresNew: true,
|
NewComputed: true,
|
||||||
Type: DiffAttrOutput,
|
RequiresNew: true,
|
||||||
})
|
Type: DiffAttrOutput,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.Hook(func(h Hook) (HookAction, error) {
|
err = ctx.Hook(func(h Hook) (HookAction, error) {
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_availability_zone"
|
||||||
|
sidebar_current: "docs-aws-datasource-availability-zone"
|
||||||
|
description: |-
|
||||||
|
Provides details about a specific availability zone
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_availability\_zone
|
||||||
|
|
||||||
|
`aws_availability_zone` provides details about a specific availablity zone (AZ)
|
||||||
|
in the current region.
|
||||||
|
|
||||||
|
This can be used both to validate an availability zone given in a variable
|
||||||
|
and to split the AZ name into its component parts of an AWS region and an
|
||||||
|
AZ identifier letter. The latter may be useful e.g. for implementing a
|
||||||
|
consistent subnet numbering scheme across several regions by mapping both
|
||||||
|
the region and the subnet letter to network numbers.
|
||||||
|
|
||||||
|
This is different from the `aws_availability_zones` (plural) data source,
|
||||||
|
which provides a list of the available zones.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
The following example shows how this data source might be used to derive
|
||||||
|
VPC and subnet CIDR prefixes systematically for an availability zone.
|
||||||
|
|
||||||
|
```
|
||||||
|
variable "region_number" {
|
||||||
|
# Arbitrary mapping of region name to number to use in
|
||||||
|
# a VPC's CIDR prefix.
|
||||||
|
default = {
|
||||||
|
us-east-1 = 1
|
||||||
|
us-west-1 = 2
|
||||||
|
us-west-2 = 3
|
||||||
|
eu-central-1 = 4
|
||||||
|
ap-northeast-1 = 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "az_number" {
|
||||||
|
# Assign a number to each AZ letter used in our configuration
|
||||||
|
default = {
|
||||||
|
a = 1
|
||||||
|
b = 2
|
||||||
|
c = 3
|
||||||
|
d = 4
|
||||||
|
e = 5
|
||||||
|
f = 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Retrieve the AZ where we want to create network resources
|
||||||
|
# This must be in the region selected on the AWS provider.
|
||||||
|
data "aws_availability_zone" "example" {
|
||||||
|
name = "eu-central-1a"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a VPC for the region associated with the AZ
|
||||||
|
resource "aws_vpc" "example" {
|
||||||
|
cidr_block = "${cidrsubnet("10.0.0.0/8", 4, var.region_number[data.aws_availability_zone.example.region])}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a subnet for the AZ within the regional VPC
|
||||||
|
resource "aws_subnet" "example" {
|
||||||
|
vpc_id = "${aws_vpc.example.id}"
|
||||||
|
cidr_block = "${cidrsubnet(aws_vpc.example.cidr_block, 4, var.az_number[data.aws_availability_zone.name_suffix])}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The arguments of this data source act as filters for querying the available
|
||||||
|
availability zones. The given filters must match exactly one availability
|
||||||
|
zone whose data will be exported as attributes.
|
||||||
|
|
||||||
|
* `name` - (Optional) The full name of the availability zone to select.
|
||||||
|
|
||||||
|
* `state` - (Optional) A specific availability zone state to require. May
|
||||||
|
be any of `"available"`, `"information"`, `"impaired"` or `"available"`.
|
||||||
|
|
||||||
|
All reasonable uses of this data source will specify `name`, since `state`
|
||||||
|
alone would match a single AZ only in a region that itself has only one AZ.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `name` - The name of the selected availability zone.
|
||||||
|
|
||||||
|
* `region` - The region where the selected availability zone resides.
|
||||||
|
This is always the region selected on the provider, since this data source
|
||||||
|
searches only within that region.
|
||||||
|
|
||||||
|
* `name_suffix` - The part of the AZ name that appears after the region name,
|
||||||
|
uniquely identifying the AZ within its region.
|
||||||
|
|
||||||
|
* `state` - The current state of the AZ.
|
@ -12,6 +12,9 @@ The Availability Zones data source allows access to the list of AWS
|
|||||||
Availability Zones which can be accessed by an AWS account within the region
|
Availability Zones which can be accessed by an AWS account within the region
|
||||||
configured in the provider.
|
configured in the provider.
|
||||||
|
|
||||||
|
This is different from the `aws_availability_zone` (singular) data source,
|
||||||
|
which provides some details about a specific availability zone.
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
|
54
website/source/docs/providers/aws/d/region.html.markdown
Normal file
54
website/source/docs/providers/aws/d/region.html.markdown
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_region"
|
||||||
|
sidebar_current: "docs-aws-datasource-region"
|
||||||
|
description: |-
|
||||||
|
Provides details about a specific service region
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_region
|
||||||
|
|
||||||
|
`aws_region` provides details about a specific AWS region.
|
||||||
|
|
||||||
|
As well as validating a given region name (and optionally obtaining its
|
||||||
|
endpoint) this resource can be used to discover the name of the region
|
||||||
|
configured within the provider. The latter can be useful in a child module
|
||||||
|
which is inheriting an AWS provider configuration from its parent module.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
The following example shows how the resource might be used to obtain
|
||||||
|
the name of the AWS region configured on the provider.
|
||||||
|
|
||||||
|
```
|
||||||
|
data "aws_region" "current" {
|
||||||
|
current = true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The arguments of this data source act as filters for querying the available
|
||||||
|
regions. The given filters must match exactly one region whose data will be
|
||||||
|
exported as attributes.
|
||||||
|
|
||||||
|
* `name` - (Optional) The full name of the region to select.
|
||||||
|
|
||||||
|
* `current` - (Optional) Set to `true` to match only the region configured
|
||||||
|
in the provider. (It is not meaningful to set this to `false`.)
|
||||||
|
|
||||||
|
* `endpoint` - (Optional) The endpoint of the region to select.
|
||||||
|
|
||||||
|
At least one of the above attributes should be provided to ensure that only
|
||||||
|
one region is matched.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `name` - The name of the selected region.
|
||||||
|
|
||||||
|
* `current` - `true` if the selected region is the one configured on the
|
||||||
|
provider, or `false` otherwise.
|
||||||
|
|
||||||
|
* `endpoint` - The endpoint for the selected region.
|
81
website/source/docs/providers/aws/d/subnet.html.markdown
Normal file
81
website/source/docs/providers/aws/d/subnet.html.markdown
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_subnet"
|
||||||
|
sidebar_current: "docs-aws-datasource-subnet"
|
||||||
|
description: |-
|
||||||
|
Provides details about a specific VPC subnet
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_subnet
|
||||||
|
|
||||||
|
`aws_subnet` provides details about a specific VPC subnet.
|
||||||
|
|
||||||
|
This resource can prove useful when a module accepts a subnet id as
|
||||||
|
an input variable and needs to, for example, determine the id of the
|
||||||
|
VPC that the subnet belongs to.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
The following example shows how one might accept a subnet id as a variable
|
||||||
|
and use this data source to obtain the data necessary to create a security
|
||||||
|
group that allows connections from hosts in that subnet.
|
||||||
|
|
||||||
|
```
|
||||||
|
variable "subnet_id" {}
|
||||||
|
|
||||||
|
data "aws_subnet" "selected" {
|
||||||
|
id = "${var.subnet_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group" "subnet" {
|
||||||
|
vpc_id = "${aws_subnet.selected.vpc_id}"
|
||||||
|
|
||||||
|
ingress {
|
||||||
|
cidr_blocks = ["${aws_subnet.selected.cidr_block}"]
|
||||||
|
from_port = 80
|
||||||
|
to_port = 80
|
||||||
|
protocol = "tcp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The arguments of this data source act as filters for querying the available
|
||||||
|
subnets in the current region. The given filters must match exactly one
|
||||||
|
subnet whose data will be exported as attributes.
|
||||||
|
|
||||||
|
* `availability_zone` - (Optional) The availability zone where the
|
||||||
|
subnet must reside.
|
||||||
|
|
||||||
|
* `cidr_block` - (Optional) The cidr block of the desired subnet.
|
||||||
|
|
||||||
|
* `default_for_az` - (Optional) Boolean constraint for whether the desired
|
||||||
|
subnet must be the default subnet for its associated availability zone.
|
||||||
|
|
||||||
|
* `filter` - (Optional) Custom filter block as described below.
|
||||||
|
|
||||||
|
* `id` - (Optional) The id of the specific subnet to retrieve.
|
||||||
|
|
||||||
|
* `state` - (Optional) The state that the desired subnet must have.
|
||||||
|
|
||||||
|
* `tags` - (Optional) A mapping of tags, each pair of which must exactly match
|
||||||
|
a pair on the desired subnet.
|
||||||
|
|
||||||
|
* `vpc_id` - (Optional) The id of the VPC that the desired subnet belongs to.
|
||||||
|
|
||||||
|
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_DescribeSubnets.html).
|
||||||
|
|
||||||
|
* `values` - (Required) Set of values that are accepted for the given field.
|
||||||
|
A subnet will be selected if any one of the given values matches.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
All of the argument attributes except `filter` blocks 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 subnet.
|
79
website/source/docs/providers/aws/d/vpc.html.markdown
Normal file
79
website/source/docs/providers/aws/d/vpc.html.markdown
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_vpc"
|
||||||
|
sidebar_current: "docs-aws-datasource-vpc"
|
||||||
|
description: |-
|
||||||
|
Provides details about a specific VPC
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_vpc
|
||||||
|
|
||||||
|
`aws_vpc` provides details about a specific VPC.
|
||||||
|
|
||||||
|
This resource can prove useful when a module accepts a vpc id as
|
||||||
|
an input variable and needs to, for example, determine the CIDR block of that
|
||||||
|
VPC.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
The following example shows how one might accept a VPC id as a variable
|
||||||
|
and use this data source to obtain the data necessary to create a subnet
|
||||||
|
within it.
|
||||||
|
|
||||||
|
```
|
||||||
|
variable "vpc_id" {}
|
||||||
|
|
||||||
|
data "aws_vpc" "selected" {
|
||||||
|
id = "${var.vpc_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_subnet" "example" {
|
||||||
|
vpc_id = "${aws_vpc.selected.id}"
|
||||||
|
availability_zone = "us-west-2a"
|
||||||
|
cidr_block = "${cidrsubnet(aws_vpc.selected.cidr_block, 4, 1)}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The arguments of this data source act as filters for querying the available
|
||||||
|
VPCs in the current region. The given filters must match exactly one
|
||||||
|
VPC whose data will be exported as attributes.
|
||||||
|
|
||||||
|
* `cidr_block` - (Optional) The cidr block of the desired VPC.
|
||||||
|
|
||||||
|
* `dhcp_options_id` - (Optional) The DHCP options id of the desired VPC.
|
||||||
|
|
||||||
|
* `default` - (Optional) Boolean constraint on whether the desired VPC is
|
||||||
|
the default VPC for the region.
|
||||||
|
|
||||||
|
* `filter` - (Optional) Custom filter block as described below.
|
||||||
|
|
||||||
|
* `id` - (Optional) The id of the specific VPC to retrieve.
|
||||||
|
|
||||||
|
* `state` - (Optional) The current state of the desired VPC.
|
||||||
|
Can be either `"pending"` or `"available"`.
|
||||||
|
|
||||||
|
* `tags` - (Optional) A mapping of tags, each pair of which must exactly match
|
||||||
|
a pair on the desired VPC.
|
||||||
|
|
||||||
|
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_DescribeVpcs.html).
|
||||||
|
|
||||||
|
* `values` - (Required) Set of values that are accepted for the given field.
|
||||||
|
A VPC will be selected if any one of the given values matches.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
All of the argument attributes except `filter` blocks 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 VPC.
|
||||||
|
|
||||||
|
The following attribute is additionally exported:
|
||||||
|
|
||||||
|
* `instance_tenancy` - The allowed tenancy of instances launched into the
|
||||||
|
selected VPC. May be any of `"default"`, `"dedicated"`, or `"host"`.
|
@ -17,6 +17,9 @@
|
|||||||
<li<%= sidebar_current("docs-aws-datasource-ami") %>>
|
<li<%= sidebar_current("docs-aws-datasource-ami") %>>
|
||||||
<a href="/docs/providers/aws/d/ami.html">aws_ami</a>
|
<a href="/docs/providers/aws/d/ami.html">aws_ami</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li<%= sidebar_current("docs-aws-datasource-availability-zone") %>>
|
||||||
|
<a href="/docs/providers/aws/d/availability_zone.html">aws_availability_zone</a>
|
||||||
|
</li>
|
||||||
<li<%= sidebar_current("docs-aws-datasource-availability-zones") %>>
|
<li<%= sidebar_current("docs-aws-datasource-availability-zones") %>>
|
||||||
<a href="/docs/providers/aws/d/availability_zones.html">aws_availability_zones</a>
|
<a href="/docs/providers/aws/d/availability_zones.html">aws_availability_zones</a>
|
||||||
</li>
|
</li>
|
||||||
@ -38,12 +41,21 @@
|
|||||||
<li<%= sidebar_current("docs-aws-datasource-ip_ranges") %>>
|
<li<%= sidebar_current("docs-aws-datasource-ip_ranges") %>>
|
||||||
<a href="/docs/providers/aws/d/ip_ranges.html">aws_ip_ranges</a>
|
<a href="/docs/providers/aws/d/ip_ranges.html">aws_ip_ranges</a>
|
||||||
</li>
|
</li>
|
||||||
<li<%= sidebar_current("docs-aws-datasource-redshift-service-account") %>>
|
<li<%= sidebar_current("docs-aws-datasource-redshift-service-account") %>>
|
||||||
<a href="/docs/providers/aws/d/redshift_service_account.html">aws_redshift_service_account</a>
|
<a href="/docs/providers/aws/d/redshift_service_account.html">aws_redshift_service_account</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li<%= sidebar_current("docs-aws-datasource-region") %>>
|
||||||
|
<a href="/docs/providers/aws/d/region.html">aws_region</a>
|
||||||
|
</li>
|
||||||
<li<%= sidebar_current("docs-aws-datasource-s3-bucket-object") %>>
|
<li<%= sidebar_current("docs-aws-datasource-s3-bucket-object") %>>
|
||||||
<a href="/docs/providers/aws/d/s3_bucket_object.html">aws_s3_bucket_object</a>
|
<a href="/docs/providers/aws/d/s3_bucket_object.html">aws_s3_bucket_object</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li<%= sidebar_current("docs-aws-datasource-subnet") %>>
|
||||||
|
<a href="/docs/providers/aws/d/subnet.html">aws_subnet</a>
|
||||||
|
</li>
|
||||||
|
<li<%= sidebar_current("docs-aws-datasource-vpc") %>>
|
||||||
|
<a href="/docs/providers/aws/d/vpc.html">aws_vpc</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user