From cbe9be4571f89295397cb57b3bf452695cf2dd18 Mon Sep 17 00:00:00 2001 From: John Engelman Date: Wed, 3 Jun 2015 10:10:17 -0500 Subject: [PATCH] Add website_domain for S3 buckets. --- .../aws/resource_aws_route53_record_test.go | 42 +++++++++++++++++++ .../providers/aws/resource_aws_s3_bucket.go | 40 +++++++++++++----- .../aws/website_endpoint_url_test.go | 6 +-- .../providers/aws/r/s3_bucket.html.markdown | 1 + 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/builtin/providers/aws/resource_aws_route53_record_test.go b/builtin/providers/aws/resource_aws_route53_record_test.go index 08f824ccb..0435dffb1 100644 --- a/builtin/providers/aws/resource_aws_route53_record_test.go +++ b/builtin/providers/aws/resource_aws_route53_record_test.go @@ -155,6 +155,22 @@ func TestAccAWSRoute53Record_alias(t *testing.T) { }) } +func TestAccAWSRoute53Record_s3_alias(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRoute53RecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccRoute53S3AliasRecord, + Check: resource.ComposeTestCheckFunc( + testAccCheckRoute53RecordExists("aws_route53_record.alias"), + ), + }, + }, + }) +} + func TestAccAWSRoute53Record_weighted_alias(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -449,6 +465,32 @@ resource "aws_route53_record" "alias" { } ` +const testAccRoute53S3AliasRecord = ` +resource "aws_route53_zone" "main" { + name = "notexample.com" +} + +resource "aws_s3_bucket" "website" { + bucket = "website.notexample.com" + acl = "public-read" + website { + index_document = "index.html" + } +} + +resource "aws_route53_record" "alias" { + zone_id = "${aws_route53_zone.main.zone_id}" + name = "www" + type = "A" + + alias { + zone_id = "${aws_s3_bucket.website.hosted_zone_id}" + name = "${aws_s3_bucket.website.website_domain}" + evaluate_target_health = true + } +} +` + const testAccRoute53WeightedElbAliasRecord = ` resource "aws_route53_zone" "main" { name = "notexample.com" diff --git a/builtin/providers/aws/resource_aws_s3_bucket.go b/builtin/providers/aws/resource_aws_s3_bucket.go index 93bf24390..af60e2214 100644 --- a/builtin/providers/aws/resource_aws_s3_bucket.go +++ b/builtin/providers/aws/resource_aws_s3_bucket.go @@ -77,12 +77,16 @@ func resourceAwsS3Bucket() *schema.Resource { Optional: true, Computed: true, }, - "website_endpoint": &schema.Schema{ Type: schema.TypeString, Optional: true, Computed: true, }, + "website_domain": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, "tags": tagsSchema(), @@ -237,12 +241,17 @@ func resourceAwsS3BucketRead(d *schema.ResourceData, meta interface{}) error { } // Add website_endpoint as an attribute - endpoint, err := websiteEndpoint(s3conn, d) + websiteEndpoint, err := websiteEndpoint(s3conn, d) if err != nil { return err } - if err := d.Set("website_endpoint", endpoint); err != nil { - return err + if websiteEndpoint != nil { + if err := d.Set("website_endpoint", websiteEndpoint.Endpoint); err != nil { + return err + } + if err := d.Set("website_domain", websiteEndpoint.Domain); err != nil { + return err + } } tagSet, err := getTagSetS3(s3conn, d.Id()) @@ -405,11 +414,11 @@ func resourceAwsS3BucketWebsiteDelete(s3conn *s3.S3, d *schema.ResourceData) err return nil } -func websiteEndpoint(s3conn *s3.S3, d *schema.ResourceData) (string, error) { +func websiteEndpoint(s3conn *s3.S3, d *schema.ResourceData) (*S3Website, error) { // If the bucket doesn't have a website configuration, return an empty // endpoint if _, ok := d.GetOk("website"); !ok { - return "", nil + return nil, nil } bucket := d.Get("bucket").(string) @@ -421,26 +430,31 @@ func websiteEndpoint(s3conn *s3.S3, d *schema.ResourceData) (string, error) { }, ) if err != nil { - return "", err + return nil, err } var region string if location.LocationConstraint != nil { region = *location.LocationConstraint } - return WebsiteEndpointUrl(bucket, region), nil + return WebsiteEndpoint(bucket, region), nil } -func WebsiteEndpointUrl(bucket string, region string) string { +func WebsiteEndpoint(bucket string, region string) *S3Website { + domain := WebsiteDomainUrl(region) + return &S3Website{Endpoint: fmt.Sprintf("%s.%s", bucket, domain), Domain: domain} +} + +func WebsiteDomainUrl(region string) string { region = normalizeRegion(region) // Frankfurt(and probably future) regions uses different syntax for website endpoints // http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteEndpoints.html if region == "eu-central-1" { - return fmt.Sprintf("%s.s3-website.%s.amazonaws.com", bucket, region) + return fmt.Sprintf("s3-website.%s.amazonaws.com", region) } - return fmt.Sprintf("%s.s3-website-%s.amazonaws.com", bucket, region) + return fmt.Sprintf("s3-website-%s.amazonaws.com", region) } func normalizeJson(jsonString interface{}) string { @@ -465,3 +479,7 @@ func normalizeRegion(region string) string { return region } + +type S3Website struct { + Endpoint, Domain string +} diff --git a/builtin/providers/aws/website_endpoint_url_test.go b/builtin/providers/aws/website_endpoint_url_test.go index 2f4ce5249..bbe282e2c 100644 --- a/builtin/providers/aws/website_endpoint_url_test.go +++ b/builtin/providers/aws/website_endpoint_url_test.go @@ -20,9 +20,9 @@ var websiteEndpoints = []struct { func TestWebsiteEndpointUrl(t *testing.T) { for _, tt := range websiteEndpoints { - s := WebsiteEndpointUrl("bucket-name", tt.in) - if s != tt.out { - t.Errorf("WebsiteEndpointUrl(\"bucket-name\", %q) => %q, want %q", tt.in, s, tt.out) + s := WebsiteEndpoint("bucket-name", tt.in) + if s.Endpoint != tt.out { + t.Errorf("WebsiteEndpointUrl(\"bucket-name\", %q) => %q, want %q", tt.in, s.Endpoint, tt.out) } } } diff --git a/website/source/docs/providers/aws/r/s3_bucket.html.markdown b/website/source/docs/providers/aws/r/s3_bucket.html.markdown index 4f367d4f8..f30c153c5 100644 --- a/website/source/docs/providers/aws/r/s3_bucket.html.markdown +++ b/website/source/docs/providers/aws/r/s3_bucket.html.markdown @@ -67,3 +67,4 @@ The following attributes are exported: * `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. +* `website_domain` - The domain of the website endpoint, if the bucket is configured with a website. If not, this will be an empty string. This is used to create Route 53 alias records.