Skip to content

Commit

Permalink
Merge pull request #3157 from terraform-providers/f-aws_region-no-api…
Browse files Browse the repository at this point in the history
…-current-default

data-source/aws_region: Remove EC2 API call, default to current if no endpoint or name specified
  • Loading branch information
bflad authored Feb 9, 2018
2 parents 8ad0da4 + 1cc81c9 commit 2f001b5
Show file tree
Hide file tree
Showing 3 changed files with 313 additions and 78 deletions.
100 changes: 64 additions & 36 deletions aws/data_source_aws_region.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package aws

import (
"fmt"
"log"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/hashicorp/terraform/helper/schema"
)

Expand All @@ -21,9 +20,10 @@ func dataSourceAwsRegion() *schema.Resource {
},

"current": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Type: schema.TypeBool,
Optional: true,
Computed: true,
Deprecated: "Defaults to current provider region if no other filtering is enabled",
},

"endpoint": {
Expand All @@ -36,48 +36,76 @@ func dataSourceAwsRegion() *schema.Resource {
}

func dataSourceAwsRegionRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
currentRegion := meta.(*AWSClient).region
providerRegion := meta.(*AWSClient).region

req := &ec2.DescribeRegionsInput{}
var region *endpoints.Region

req.RegionNames = make([]*string, 0, 2)
if name := d.Get("name").(string); name != "" {
req.RegionNames = append(req.RegionNames, aws.String(name))
if v, ok := d.GetOk("endpoint"); ok {
endpoint := v.(string)
matchingRegion, err := findRegionByEc2Endpoint(endpoint)
if err != nil {
return err
}
region = matchingRegion
}

if d.Get("current").(bool) {
req.RegionNames = append(req.RegionNames, aws.String(currentRegion))
if v, ok := d.GetOk("name"); ok {
name := v.(string)
matchingRegion, err := findRegionByName(name)
if err != nil {
return err
}
if region != nil && region.ID() != matchingRegion.ID() {
return fmt.Errorf("multiple regions matched; use additional constraints to reduce matches to a single region")
}
region = matchingRegion
}

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
// Default to provider current region if no other filters matched
if region == nil {
matchingRegion, err := findRegionByName(providerRegion)
if err != nil {
return err
}
region = matchingRegion
}

log.Printf("[DEBUG] Reading Region: %s", req)
resp, err := conn.DescribeRegions(req)
d.SetId(region.ID())
d.Set("current", region.ID() == providerRegion)

regionEndpointEc2, err := region.ResolveEndpoint(endpoints.Ec2ServiceID)
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.Set("endpoint", strings.TrimPrefix(regionEndpointEc2.URL, "https://"))

d.SetId(*region.RegionName)
d.Set("name", region.RegionName)
d.Set("endpoint", region.Endpoint)
d.Set("current", *region.RegionName == currentRegion)
d.Set("name", region.ID())

return nil
}

func findRegionByEc2Endpoint(endpoint string) (*endpoints.Region, error) {
for _, partition := range endpoints.DefaultPartitions() {
for _, region := range partition.Regions() {
regionEndpointEc2, err := region.ResolveEndpoint(endpoints.Ec2ServiceID)
if err != nil {
return nil, err
}
if strings.TrimPrefix(regionEndpointEc2.URL, "https://") == endpoint {
return &region, nil
}
}
}
return nil, fmt.Errorf("region not found for endpoint: %s", endpoint)
}

func findRegionByName(name string) (*endpoints.Region, error) {
for _, partition := range endpoints.DefaultPartitions() {
for _, region := range partition.Regions() {
if region.ID() == name {
return &region, nil
}
}
}
return nil, fmt.Errorf("region not found for name: %s", name)
}
Loading

0 comments on commit 2f001b5

Please sign in to comment.