-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
data-source/aws_region: Remove EC2 API call, default to current if no endpoint or name specified #3157
data-source/aws_region: Remove EC2 API call, default to current if no endpoint or name specified #3157
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
) | ||
|
||
|
@@ -36,48 +35,74 @@ func dataSourceAwsRegion() *schema.Resource { | |
} | ||
|
||
func dataSourceAwsRegionRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
currentRegion := meta.(*AWSClient).region | ||
|
||
req := &ec2.DescribeRegionsInput{} | ||
var matchingRegion *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) | ||
for _, partition := range endpoints.DefaultPartitions() { | ||
for _, region := range partition.Regions() { | ||
regionEndpointEc2, err := region.ResolveEndpoint(endpoints.Ec2ServiceID) | ||
if err != nil { | ||
return err | ||
} | ||
if strings.TrimPrefix(regionEndpointEc2.URL, "https://") == endpoint { | ||
matchingRegion = ®ion | ||
break | ||
} | ||
} | ||
} | ||
if matchingRegion == nil { | ||
return fmt.Errorf("region not found for endpoint: %s", endpoint) | ||
} | ||
} | ||
|
||
if d.Get("current").(bool) { | ||
req.RegionNames = append(req.RegionNames, aws.String(currentRegion)) | ||
if v, ok := d.GetOk("name"); ok { | ||
name := v.(string) | ||
for _, partition := range endpoints.DefaultPartitions() { | ||
for _, region := range partition.Regions() { | ||
if region.ID() == name { | ||
if matchingRegion != nil && (*matchingRegion).ID() != name { | ||
return fmt.Errorf("multiple regions matched; use additional constraints to reduce matches to a single region") | ||
} | ||
matchingRegion = ®ion | ||
break | ||
} | ||
} | ||
} | ||
if matchingRegion == nil { | ||
return fmt.Errorf("region not found for name: %s", name) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likewise - how do you feel about extracting this into There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 👍 |
||
} | ||
|
||
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 | ||
current := d.Get("current").(bool) | ||
for _, partition := range endpoints.DefaultPartitions() { | ||
for _, region := range partition.Regions() { | ||
if region.ID() == currentRegion { | ||
if matchingRegion == nil { | ||
matchingRegion = ®ion | ||
break | ||
} | ||
if current && (*matchingRegion).ID() != currentRegion { | ||
return fmt.Errorf("multiple regions matched; use additional constraints to reduce matches to a single region") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any reason we can't just error out here regardless of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ha, I think I was trying to make it so it could support current being false or something. I'm on board with deprecating the |
||
} | ||
} | ||
} | ||
} | ||
|
||
log.Printf("[DEBUG] Reading Region: %s", req) | ||
resp, err := conn.DescribeRegions(req) | ||
region := *matchingRegion | ||
|
||
d.SetId(region.ID()) | ||
d.Set("current", region.ID() == currentRegion) | ||
|
||
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://")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just out of curiosity: What is the reason for the trimming here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Previously, the EC2 API response was returning just the hostname (see example here: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeRegions.html), however the SDK |
||
|
||
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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,20 +10,18 @@ description: |- | |
|
||
`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. | ||
As well as validating a given region name 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. | ||
|
||
```hcl | ||
data "aws_region" "current" { | ||
current = true | ||
} | ||
data "aws_region" "current" {} | ||
``` | ||
|
||
## Argument Reference | ||
|
@@ -35,12 +33,9 @@ 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`.) | ||
in the provider. Defaults to `true` if `endpoint` or `name` is not given. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm curious what is the value of |
||
|
||
* `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. | ||
* `endpoint` - (Optional) The EC2 endpoint of the region to select. | ||
|
||
## Attributes Reference | ||
|
||
|
@@ -51,4 +46,4 @@ The following attributes are exported: | |
* `current` - `true` if the selected region is the one configured on the | ||
provider, or `false` otherwise. | ||
|
||
* `endpoint` - The endpoint for the selected region. | ||
* `endpoint` - The EC2 endpoint for the selected region. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you! 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It took me a while to understand what this block of code does. 😅 Would you mind extracting it into something like
matchingRegion, err := findRegionByEndpoint(endpoint)
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great idea! Let me implement that.