Skip to content

Commit 3e299e3

Browse files
Jamie-BitFlightosterman
authored andcommitted
Added optional regional s3 endpoint. Added Example (#17)
* Added the ability to specify a regional endpoint. Updated README. Created working example. * Added output in example that provided instructions for beginners * Added origin_force_destroy to all s3 buckets so that the module can be destroyed if required. * Fixed another destruction issue. * Updated for consistency * Changed the 'static' bucket * added variable for static_s3_bucket
1 parent 1537e47 commit 3e299e3

File tree

9 files changed

+135
-23
lines changed

9 files changed

+135
-23
lines changed

.gitignore

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
# Compiled files
2-
*.tfstate
3-
*.tfstate.backup
4-
*.terraform.tfstate*
2+
**/*.tfstate
3+
**/*.tfstate.backup
4+
**/*.terraform.tfstate*
55
# Module directory
6-
.terraform/
7-
86
.idea
97
*.iml
10-
8+
**/.terraform

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module "cdn" {
1616
}
1717
```
1818

19+
Full working example can be found in [example](./example) folder.
1920

2021
### Generating ACM Certificate
2122

@@ -38,7 +39,9 @@ https://docs.aws.amazon.com/acm/latest/userguide/acm-regions.html
3839
3940
This is a fundamental requirement of CloudFront, and you will need to request the certificate in `us-east-1` region.
4041

41-
42+
If there are warnings around the outputs when destroying using this module.
43+
Then you can use this method for supressing the superfluous errors.
44+
`TF_WARN_OUTPUT_ERRORS=1 terraform destroy`
4245

4346
## Variables
4447

@@ -85,6 +88,7 @@ This is a fundamental requirement of CloudFront, and you will need to request th
8588
| `origin_path` | `` | Element that causes CloudFront to request your content from a directory in your Amazon S3 bucket. Begins with `/`. CAUTION! Do not use bare `/` as `origin_path`. | No |
8689
| `parent_zone_id` | `` | ID of the hosted zone to contain this record (or specify `parent_zone_name`) | Yes |
8790
| `parent_zone_name` | `` | Name of the hosted zone to contain this record (or specify `parent_zone_id`) | Yes |
91+
| `use_regional_s3_endpoint` | `"false"` | Use a regional endpoint for the bucket instead of the global endpoint. Useful for speeding up the deploy process caused by the s3 replication latency | No |
8892

8993

9094
## Outputs
@@ -108,3 +112,7 @@ If the bucket is created in a region other than `us-east-1`, it will take a whil
108112
> All buckets have at least two REST endpoint hostnames. In eu-west-1, they are example-bucket.s3-eu-west-1.amazonaws.com and example-bucket.s3.amazonaws.com. The first one will be immediately valid when the bucket is created. The second one -- sometimes referred to as the "global endpoint" -- which is the one CloudFront uses -- will not, unless the bucket is in us-east-1. Over a period of seconds to minutes, variable by location and other factors, it becomes globally accessible as well. Before that, the 307 redirect is returned. Hence, the bucket was not ready.
109113
110114
Via: https://stackoverflow.com/questions/38706424/aws-cloudfront-returns-http-307-when-origin-is-s3-bucket
115+
116+
## Workaround for Known Issues
117+
118+
To use the regional endpoint name instead of the global bucket name in this module, set `use_regional_s3_endpoint = "true"` in the module.

example/index.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Your CDN is working</title>
6+
</head>
7+
<body>
8+
<H1>Your CDN is working!</H1>
9+
</body>
10+
</html>

example/main.tf

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
resource "aws_route53_zone" "primary" {
2+
name = "cloudposse.com"
3+
force_destroy = "true"
4+
}
5+
6+
module "cdn" {
7+
source = "../"
8+
namespace = "cp"
9+
stage = "dev"
10+
name = "app-cdn"
11+
aliases = ["assets.cloudposse.com"]
12+
parent_zone_id = "${aws_route53_zone.primary.zone_id}"
13+
use_regional_s3_endpoint = "true"
14+
origin_force_destroy = "true"
15+
}
16+
17+
resource "aws_s3_bucket_object" "index" {
18+
bucket = "${module.cdn.s3_bucket}"
19+
key = "index.html"
20+
source = "${path.module}/index.html"
21+
content_type = "text/html"
22+
etag = "${md5(file("${path.module}/index.html"))}"
23+
}

example/outputs.tf

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
output "cf_id" {
2+
value = "${module.cdn.cf_id}"
3+
}
4+
5+
output "cf_arn" {
6+
value = "${module.cdn.cf_arn}"
7+
}
8+
9+
output "cf_status" {
10+
value = "${module.cdn.cf_status}"
11+
}
12+
13+
output "cf_domain_name" {
14+
value = "${module.cdn.cf_domain_name}"
15+
}
16+
17+
output "cf_etag" {
18+
value = "${module.cdn.cf_etag}"
19+
}
20+
21+
output "cf_hosted_zone_id" {
22+
value = "${module.cdn.cf_hosted_zone_id}"
23+
}
24+
25+
output "s3_bucket" {
26+
value = "${module.cdn.s3_bucket}"
27+
}
28+
29+
output "s3_bucket_domain_name" {
30+
value = "${module.cdn.s3_bucket_domain_name}"
31+
}
32+
33+
output "details" {
34+
value = <<DOC
35+
When the `cf_status` changes to `Deployed` from `InProgress`
36+
(You can check it by doing an extra `terraform apply` every few minutes.)
37+
The site can be viewed at https://${module.cdn.cf_domain_name}
38+
DOC
39+
}

example/provider.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
provider "aws" {
2+
region = "eu-west-2"
3+
4+
# Make it faster by skipping something
5+
skip_get_ec2_platforms = true
6+
skip_metadata_api_check = true
7+
skip_region_validation = true
8+
skip_credentials_validation = true
9+
skip_requesting_account_id = true
10+
}

main.tf

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module "origin_label" {
2-
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.3.3"
2+
source = "git::https://github.com/cloudposse/terraform-terraform-label.git?ref=tags/0.1.2"
33
namespace = "${var.namespace}"
44
stage = "${var.stage}"
55
name = "${var.name}"
@@ -39,21 +39,24 @@ data "template_file" "default" {
3939

4040
vars {
4141
origin_path = "${coalesce(var.origin_path, "/")}"
42-
bucket_name = "${null_resource.default.triggers.bucket}"
42+
bucket_name = "${local.bucket}"
4343
}
4444
}
4545

4646
resource "aws_s3_bucket_policy" "default" {
47-
bucket = "${null_resource.default.triggers.bucket}"
47+
bucket = "${local.bucket}"
4848
policy = "${data.template_file.default.rendered}"
4949
}
5050

51+
data "aws_region" "current" {}
52+
5153
resource "aws_s3_bucket" "origin" {
5254
count = "${signum(length(var.origin_bucket)) == 1 ? 0 : 1}"
5355
bucket = "${module.origin_label.id}"
5456
acl = "private"
5557
tags = "${module.origin_label.tags}"
5658
force_destroy = "${var.origin_force_destroy}"
59+
region = "${data.aws_region.current.name}"
5760

5861
cors_rule {
5962
allowed_headers = "${var.cors_allowed_headers}"
@@ -65,7 +68,7 @@ resource "aws_s3_bucket" "origin" {
6568
}
6669

6770
module "logs" {
68-
source = "git::https://github.com/cloudposse/terraform-aws-s3-log-storage.git?ref=tags/0.1.3"
71+
source = "git::https://github.com/cloudposse/terraform-aws-s3-log-storage.git?ref=tags/0.2.0"
6972
namespace = "${var.namespace}"
7073
stage = "${var.stage}"
7174
name = "${var.name}"
@@ -76,10 +79,11 @@ module "logs" {
7679
standard_transition_days = "${var.log_standard_transition_days}"
7780
glacier_transition_days = "${var.log_glacier_transition_days}"
7881
expiration_days = "${var.log_expiration_days}"
82+
force_destroy = "${var.origin_force_destroy}"
7983
}
8084

8185
module "distribution_label" {
82-
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.3.3"
86+
source = "git::https://github.com/cloudposse/terraform-terraform-label.git?ref=tags/0.1.2"
8387
namespace = "${var.namespace}"
8488
stage = "${var.stage}"
8589
name = "${var.name}"
@@ -88,15 +92,15 @@ module "distribution_label" {
8892
tags = "${var.tags}"
8993
}
9094

91-
resource "null_resource" "default" {
92-
triggers {
93-
bucket = "${element(compact(concat(list(var.origin_bucket), aws_s3_bucket.origin.*.bucket)), 0)}"
94-
bucket_domain_name = "${format(var.bucket_domain_format, element(compact(concat(list(var.origin_bucket), aws_s3_bucket.origin.*.bucket)), 0))}"
95-
}
95+
data "aws_s3_bucket" "selected" {
96+
bucket = "${local.bucket == "" ? var.static_s3_bucket : local.bucket}"
97+
}
9698

97-
lifecycle {
98-
create_before_destroy = true
99-
}
99+
locals {
100+
bucket = "${join("", compact(concat(list(var.origin_bucket), concat(list(""),aws_s3_bucket.origin.*.bucket))))}"
101+
region_endpoint = "${data.aws_s3_bucket.selected.region == "us-east-1" ? "s3" : "s3-${data.aws_s3_bucket.selected.region}" }"
102+
bucket_domain_format = "${var.use_regional_s3_endpoint == "true" ? "%s.${local.region_endpoint}.amazonaws.com" : var.bucket_domain_format }"
103+
bucket_domain_name = "${format(local.bucket_domain_format, local.bucket)}"
100104
}
101105

102106
resource "aws_cloudfront_distribution" "default" {
@@ -116,7 +120,7 @@ resource "aws_cloudfront_distribution" "default" {
116120
aliases = ["${var.aliases}"]
117121

118122
origin {
119-
domain_name = "${null_resource.default.triggers.bucket_domain_name}"
123+
domain_name = "${local.bucket_domain_name}"
120124
origin_id = "${module.distribution_label.id}"
121125
origin_path = "${var.origin_path}"
122126

outputs.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ output "cf_hosted_zone_id" {
2323
}
2424

2525
output "s3_bucket" {
26-
value = "${null_resource.default.triggers.bucket}"
26+
value = "${local.bucket}"
2727
}
2828

2929
output "s3_bucket_domain_name" {
30-
value = "${null_resource.default.triggers.bucket_domain_name}"
30+
value = "${local.bucket_domain_name}"
3131
}

variables.tf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ variable "aliases" {
4646
default = []
4747
}
4848

49+
variable "use_regional_s3_endpoint" {
50+
type = "string"
51+
description = "When set to 'true' the s3 origin_bucket will use the regional endpoint address instead of the global endpoint address"
52+
default = "false"
53+
}
54+
4955
variable "origin_bucket" {
5056
default = ""
5157
}
@@ -190,3 +196,17 @@ variable "null" {
190196
description = "an empty string"
191197
default = ""
192198
}
199+
200+
variable "static_s3_bucket" {
201+
description = <<DOC
202+
aws-cli is a bucket owned by amazon that will perminantly exist
203+
It allows for the data source to be called during the destruction process without failing.
204+
It doesn't get used for anything else, this is a safe workaround for handling the fact that
205+
if a data source like the one `aws_s3_bucket.selected` gets an error, you can't continue the terraform process
206+
which also includes the 'destroy' command, where is doesn't even need this data source!
207+
Don't change this bucket name, its a variable so that we can provide this description.
208+
And this works around a problem that is an edge case.
209+
DOC
210+
211+
default = "aws-cli"
212+
}

0 commit comments

Comments
 (0)