Skip to content
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

providers/aws: Add hosted_zone_id and region to attributes #1865

Merged
merged 5 commits into from
May 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions builtin/providers/aws/hosted_zones.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package aws

// This list is copied from
// http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_website_region_endpoints
// It currently cannot be generated from the API json.
var hostedZoneIDsMap = map[string]string{
"us-east-1": "Z3AQBSTGFYJSTF",
"us-west-2": "Z3BJ6K6RIION7M",
"us-west-1": "Z2F56UZL2M1ACD",
"eu-west-1": "Z1BKCTXD74EZPE",
"central-1": "Z21DNDUVLTQW6Q",
"ap-southeast-1": "Z3O0J2DXBE1FTB",
"ap-southeast-2": "Z1WCIGYICN2BYD",
"ap-northeast-1": "Z2M4EHUR26P7ZW",
"sa-east-1": "Z7KQH4QJS55SO",
"us-gov-west-1": "Z31GFT0UA1I2HV",
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unable to be generated from the API json. Attempted to add to aws-sdk in aws/aws-sdk-go#222, but that was rejected

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you document here the why (they're looking for a generated means, etc), and maybe a TODO so we know that this should ideally go away in the future when aws-sdk-go finally picks it up?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the docs. Will they pick it up? Doesn't seem likely, unless the API schema somehow exposes it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@justincampbell I was asking our contact at AWS about this, linking him directly to the related PR at aws-sdk-go.
He was assuring me that if these zone IDs were to change, it would most likely mean changing the domain for S3 websites and/or CloudFront global domain (unlikely to happen in one day, if ever) and more importantly if that ever happens, they would give more than enough time to users to adopt this change.

He also said they may expose it via API at some point, but from my experience, it could mean 6 months, but also 6 years, or even never. There isn't any specific ETA nor guarantee.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think your comment here is well written, I can't think of a better one.


// Returns the hosted zone ID for an S3 website endpoint region. This can be
// used as input to the aws_route53_record resource's zone_id argument.
func HostedZoneIDForRegion(region string) string {
return hostedZoneIDsMap[region]
}
19 changes: 19 additions & 0 deletions builtin/providers/aws/hosted_zones_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package aws

import (
"testing"
)

func TestHostedZoneIDForRegion(t *testing.T) {
if r := HostedZoneIDForRegion("us-east-1"); r != "Z3AQBSTGFYJSTF" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing a lookup function feels a bit unnecessary, but it's no harm :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was slightly more complex previously because it normalized "" to "us-east-1", but yes a little overkill now.

t.Fatalf("bad: %s", r)
}
if r := HostedZoneIDForRegion("ap-southeast-2"); r != "Z1WCIGYICN2BYD" {
t.Fatalf("bad: %s", r)
}

// Bad input should be empty string
if r := HostedZoneIDForRegion("not-a-region"); r != "" {
t.Fatalf("bad: %s", r)
}
}
51 changes: 47 additions & 4 deletions builtin/providers/aws/resource_aws_s3_bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ func resourceAwsS3Bucket() *schema.Resource {
},
},

"hosted_zone_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},

"region": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},

"website_endpoint": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -143,7 +155,31 @@ func resourceAwsS3BucketRead(d *schema.ResourceData, meta interface{}) error {
return err
}

// Add website_endpoint as an output
// Add the region as an attribute
location, err := s3conn.GetBucketLocation(
&s3.GetBucketLocationInput{
Bucket: aws.String(d.Id()),
},
)
if err != nil {
return err
}
var region string
if location.LocationConstraint != nil {
region = *location.LocationConstraint
}
region = normalizeRegion(region)
if err := d.Set("region", region); err != nil {
return err
}

// Add the hosted zone ID for this bucket's region as an attribute
hostedZoneID := HostedZoneIDForRegion(region)
if err := d.Set("hosted_zone_id", hostedZoneID); err != nil {
return err
}

// Add website_endpoint as an attribute
endpoint, err := websiteEndpoint(s3conn, d)
if err != nil {
return err
Expand Down Expand Up @@ -260,13 +296,20 @@ func websiteEndpoint(s3conn *s3.S3, d *schema.ResourceData) (string, error) {
region = *location.LocationConstraint
}

return WebsiteEndpointUrl(bucket, region), nil
}

func WebsiteEndpointUrl(bucket string, region string) string {
region = normalizeRegion(region)
return fmt.Sprintf("%s.s3-website-%s.amazonaws.com", bucket, region)
}

func normalizeRegion(region string) string {
// Default to us-east-1 if the bucket doesn't have a region:
// http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETlocation.html
if region == "" {
region = "us-east-1"
}

endpoint := fmt.Sprintf("%s.s3-website-%s.amazonaws.com", bucket, region)

return endpoint, nil
return region
}
4 changes: 4 additions & 0 deletions builtin/providers/aws/resource_aws_s3_bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ func TestAccAWSS3Bucket_basic(t *testing.T) {
Config: testAccAWSS3BucketConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
resource.TestCheckResourceAttr(
"aws_s3_bucket.bucket", "hosted_zone_id", HostedZoneIDForRegion("us-west-2")),
resource.TestCheckResourceAttr(
"aws_s3_bucket.bucket", "region", "us-west-2"),
resource.TestCheckResourceAttr(
"aws_s3_bucket.bucket", "website_endpoint", ""),
),
Expand Down
17 changes: 17 additions & 0 deletions builtin/providers/aws/website_endpoint_url_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package aws

import "testing"

func TestWebsiteEndpointUrl_withoutRegion(t *testing.T) {
u := WebsiteEndpointUrl("buck.et", "")
if u != "buck.et.s3-website-us-east-1.amazonaws.com" {
t.Fatalf("bad: %s", u)
}
}

func TestWebsiteEndpointUrl_withRegion(t *testing.T) {
u := WebsiteEndpointUrl("buck.et", "us-west-1")
if u != "buck.et.s3-website-us-west-1.amazonaws.com" {
t.Fatalf("bad: %s", u)
}
}
2 changes: 2 additions & 0 deletions website/source/docs/providers/aws/r/s3_bucket.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,6 @@ The website object supports the following:
The following attributes are exported:

* `id` - The name of the bucket.
* `hosted_zone_id` - The [Route 53 Hosted Zone ID](http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_website_region_endpoints) for this bucket's region.
* `region` - The AWS region this bucket resides in.
* `website_endpoint` - The website endpoint, if the bucket is configured with a website. If not, this will be an empty string.