Skip to content

Commit

Permalink
Merge pull request #6819 from hashicorp/f-aws-vpc-data-sources
Browse files Browse the repository at this point in the history
provider/aws: data sources for AWS network planning
  • Loading branch information
catsby authored Oct 13, 2016
2 parents 25e38f8 + 0e3256b commit 46ee2ef
Show file tree
Hide file tree
Showing 35 changed files with 1,583 additions and 10 deletions.
89 changes: 89 additions & 0 deletions builtin/providers/aws/data_source_aws_availability_zone.go
Original file line number Diff line number Diff line change
@@ -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
}
57 changes: 57 additions & 0 deletions builtin/providers/aws/data_source_aws_availability_zone_test.go
Original file line number Diff line number Diff line change
@@ -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 changes: 84 additions & 0 deletions builtin/providers/aws/data_source_aws_region.go
Original file line number Diff line number Diff line change
@@ -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 changes: 64 additions & 0 deletions builtin/providers/aws/data_source_aws_region_test.go
Original file line number Diff line number Diff line change
@@ -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
}
`
Loading

0 comments on commit 46ee2ef

Please sign in to comment.