Skip to content

Commit ac42cd3

Browse files
authored
Merge pull request #3 from pbs/feature/adding_dns
Adding DNS record when creating cluster
2 parents 6e15689 + 56b8c80 commit ac42cd3

22 files changed

+413
-23
lines changed

.tflint.hcl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
plugin "aws" {
22
enabled = true
3-
version = "0.15.0"
3+
version = "0.17.1"
44
source = "github.com/terraform-linters/tflint-ruleset-aws"
55
}
66

.tool-versions

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
terraform 1.2.7
2-
golang 1.18.5
1+
terraform 1.3.1
2+
golang 1.19.2
33
ripgrep 13.0.0
4-
tflint 0.39.3
5-
github-cli 2.14.4
4+
tflint 0.41.0
5+
github-cli 2.17.0
66
fd 8.4.0
77
terraform-docs 0.16.0

README-HEADER.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Provisions an Elasticache Redis cluster (with Cluster Mode Disabled).
2222
2323
By default, it will provision one writer and one reader node, but that can be adjusted by setting the `nodes` variable to a different value.
2424

25+
This module also assumes that connections are established through a private DNS record created in Route53. This makes it so that replacement of the ElastiCache cluster can be made in a fashion that is transparent to application configurations. This can be adjusted by setting `create_dns` to `false`.
26+
2527
Integrate this module like so:
2628

2729
```hcl

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
Use this URL for the source of the module. See the usage examples below for more details.
88

99
```hcl
10-
github.com/pbs/terraform-aws-elasticache-redis-standalone-module?ref=0.0.2
10+
github.com/pbs/terraform-aws-elasticache-redis-standalone-module?ref=x.y.z
1111
```
1212

1313
### Alternative Installation Methods
@@ -22,11 +22,13 @@ Provisions an Elasticache Redis cluster (with Cluster Mode Disabled).
2222
2323
By default, it will provision one writer and one reader node, but that can be adjusted by setting the `nodes` variable to a different value.
2424

25+
This module also assumes that connections are established through a private DNS record created in Route53. This makes it so that replacement of the ElastiCache cluster can be made in a fashion that is transparent to application configurations. This can be adjusted by setting `create_dns` to `false`.
26+
2527
Integrate this module like so:
2628

2729
```hcl
2830
module "elasticache-redis-standalone" {
29-
source = "github.com/pbs/terraform-aws-elasticache-redis-standalone-module?ref=0.0.2"
31+
source = "github.com/pbs/terraform-aws-elasticache-redis-standalone-module?ref=x.y.z"
3032
3133
# Tagging Parameters
3234
organization = var.organization
@@ -42,7 +44,7 @@ module "elasticache-redis-standalone" {
4244

4345
If this repo is added as a subtree, then the version of the module should be close to the version shown here:
4446

45-
`0.0.2`
47+
`x.y.z`
4648

4749
Note, however that subtrees can be altered as desired within repositories.
4850

@@ -78,8 +80,11 @@ No modules.
7880
| [aws_elasticache_parameter_group.parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_parameter_group) | resource |
7981
| [aws_elasticache_replication_group.replication_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_replication_group) | resource |
8082
| [aws_elasticache_subnet_group.subnet_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_subnet_group) | resource |
83+
| [aws_route53_record.primary_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
84+
| [aws_route53_record.reader_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
8185
| [aws_security_group.sg](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
8286
| [aws_security_group_rule.egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
87+
| [aws_route53_zone.private_hosted_zone](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source |
8388
| [aws_subnets.private_subnets](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source |
8489
| [aws_vpc.vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source |
8590

@@ -96,7 +101,10 @@ No modules.
96101
| <a name="input_auth_token"></a> [auth\_token](#input\_auth\_token) | Password used to access a password protected server. Can be specified only if transit\_encryption\_enabled = true. | `string` | `null` | no |
97102
| <a name="input_auto_minor_version_upgrade"></a> [auto\_minor\_version\_upgrade](#input\_auto\_minor\_version\_upgrade) | Specifies whether minor version engine upgrades will be applied automatically to the underlying nodes during the maintenance window. Only supported for engine type "redis" and if the engine version is 6 or higher. | `bool` | `true` | no |
98103
| <a name="input_automatic_failover_enabled"></a> [automatic\_failover\_enabled](#input\_automatic\_failover\_enabled) | Specifies whether a read-only replica will be automatically promoted to read/write primary if the existing primary fails. If null, will be enabled if `nodes` > 1. If true, `nodes` must be greater than 1. | `bool` | `null` | no |
104+
| <a name="input_cname"></a> [cname](#input\_cname) | The value to use for the CNAME record if `create_dns` is true. The primary endpoint will be <cname>.<private\_hosted\_zone>, and the reader endpoint will be <cname>-ro.<private\_hosted\_zone>. If null, the name variable will be used instead. | `string` | `null` | no |
105+
| <a name="input_create_dns"></a> [create\_dns](#input\_create\_dns) | Whether to create DNS records for the primary and reader endpoints. | `bool` | `true` | no |
99106
| <a name="input_data_tiering_enabled"></a> [data\_tiering\_enabled](#input\_data\_tiering\_enabled) | Enables data tiering. Data tiering is only supported for replication groups using the r6gd node type. This parameter must be set to true when using r6gd nodes. | `bool` | `false` | no |
107+
| <a name="input_dns_ttl"></a> [dns\_ttl](#input\_dns\_ttl) | TTL for DNS records. | `number` | `300` | no |
100108
| <a name="input_egress_cidr_blocks"></a> [egress\_cidr\_blocks](#input\_egress\_cidr\_blocks) | List of CIDR blocks to assign to the egress rule of the security group. If null, `egress_security_group_ids` must be used. | `list(string)` | <pre>[<br> "10.0.0.0/8"<br>]</pre> | no |
101109
| <a name="input_egress_source_sg_id"></a> [egress\_source\_sg\_id](#input\_egress\_source\_sg\_id) | List of security group ID to assign to the egress rule of the security group. If null, `egress_cidr_blocks` must be used. | `string` | `null` | no |
102110
| <a name="input_engine_version"></a> [engine\_version](#input\_engine\_version) | Version number of the cache engine to be used. If not set, defaults to the latest version. See Describe Cache Engine Versions in the AWS Documentation for supported versions. When engine is redis and the version is 6 or higher, the major and minor version can be set, e.g., 6.2, or the minor version can be unspecified which will use the latest version at creation time, e.g., 6.x. Otherwise, specify the full version desired, e.g., 5.0.6. | `string` | `null` | no |
@@ -114,6 +122,7 @@ No modules.
114122
| <a name="input_parameters"></a> [parameters](#input\_parameters) | Additional parameters that will be added to parameter group. | `list(map(any))` | `[]` | no |
115123
| <a name="input_port"></a> [port](#input\_port) | The port number on which each of the cache nodes will accept connections. Cannot be provided with replication\_group\_id. Changing this value will re-create the resource. | `number` | `6379` | no |
116124
| <a name="input_preferred_cache_cluster_azs"></a> [preferred\_cache\_cluster\_azs](#input\_preferred\_cache\_cluster\_azs) | List of availability zones in which to create cluster. | `list(string)` | `null` | no |
125+
| <a name="input_private_hosted_zone"></a> [private\_hosted\_zone](#input\_private\_hosted\_zone) | Private hosted zone to create DNS records in. If null, `create_dns` must be set to false. | `string` | `null` | no |
117126
| <a name="input_replication_group_description"></a> [replication\_group\_description](#input\_replication\_group\_description) | Description of the replication group to be created. If null, one will be generated using the name of the nodes. | `string` | `null` | no |
118127
| <a name="input_replication_group_id"></a> [replication\_group\_id](#input\_replication\_group\_id) | Replication group identifier. This parameter is stored as a lowercase string. If null, the name of the nodes will be used. | `string` | `null` | no |
119128
| <a name="input_security_group_ids"></a> [security\_group\_ids](#input\_security\_group\_ids) | One or more VPC security groups associated with the nodes. If null, use the one provided by this module. | `list(string)` | `null` | no |

data.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,9 @@ data "aws_subnets" "private_subnets" {
1313
}
1414
}
1515
}
16+
17+
data "aws_route53_zone" "private_hosted_zone" {
18+
count = var.create_dns ? 1 : 0
19+
name = "${var.private_hosted_zone}."
20+
private_zone = true
21+
}

dns.tf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
resource "aws_route53_record" "primary_endpoint" {
2+
count = var.create_dns ? 1 : 0
3+
zone_id = local.private_hosted_zone
4+
name = local.cname
5+
type = "CNAME"
6+
ttl = var.dns_ttl
7+
records = [aws_elasticache_replication_group.replication_group.primary_endpoint_address]
8+
}
9+
10+
resource "aws_route53_record" "reader_endpoint" {
11+
count = var.create_dns ? 1 : 0
12+
zone_id = local.private_hosted_zone
13+
name = "${local.cname}-ro"
14+
type = "CNAME"
15+
ttl = var.dns_ttl
16+
records = [aws_elasticache_replication_group.replication_group.reader_endpoint_address]
17+
}
18+

examples/basic/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
module "redis" {
22
source = "../.."
33

4+
private_hosted_zone = var.private_hosted_zone
5+
46
organization = var.organization
57
environment = var.environment
68
product = var.product

examples/basic/vars.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
variable "private_hosted_zone" {
2+
type = string
3+
description = "Private hosted zone for this ElastiCache Cluster. Populate `TF_VAR_private_hosted_zone` before running any tests to have this value populated."
4+
}

examples/lambda/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ module "lambda" {
2323
module "redis" {
2424
source = "../.."
2525

26+
private_hosted_zone = var.private_hosted_zone
27+
2628
organization = var.organization
2729
environment = var.environment
2830
product = var.product

examples/lambda/vars.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
variable "private_hosted_zone" {
2+
type = string
3+
description = "Private hosted zone for this ElastiCache Cluster. Populate `TF_VAR_private_hosted_zone` before running any tests to have this value populated."
4+
}

examples/no-dns/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
backend.tf
2+
provider.tf

examples/no-dns/.terraform.lock.hcl

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/no-dns/main.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module "redis" {
2+
source = "../.."
3+
4+
create_dns = false
5+
6+
organization = var.organization
7+
environment = var.environment
8+
product = var.product
9+
repo = var.repo
10+
}

examples/no-dns/outputs.tf

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
output "name" {
2+
description = "The name of the ElastiCache replication group"
3+
value = module.redis.name
4+
}
5+
6+
output "arn" {
7+
description = "The ARN of the ElastiCache replication group"
8+
value = module.redis.arn
9+
}
10+
11+
output "sg_ids" {
12+
description = "The security group ids"
13+
value = module.redis.sg_ids
14+
}
15+
16+
output "engine_version_actual" {
17+
description = "Because ElastiCache pulls the latest minor or patch for a version, this attribute returns the running version of the cache engine."
18+
value = module.redis.engine_version_actual
19+
}
20+
21+
output "member_clusters" {
22+
description = "Identifiers of all the nodes that are part of this replication group."
23+
value = module.redis.member_clusters
24+
}
25+
26+
output "primary_endpoint_address" {
27+
description = "Address of the endpoint for the primary node in the replication group."
28+
value = module.redis.primary_endpoint_address
29+
}
30+
31+
output "reader_endpoint_address" {
32+
description = "Address of the endpoint for the reader node in the replication group."
33+
value = module.redis.reader_endpoint_address
34+
}
35+
36+
output "tags" {
37+
description = "The tags"
38+
value = module.redis.tags
39+
}

examples/no-dns/sample-backend.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# terraform {
2+
# backend "s3" {
3+
# bucket = "my-bucket-tfstate"
4+
# key = "example-terraform-aws-elasticache-redis-standalone-no-dns"
5+
# profile = "my-profile"
6+
# region = "us-east-1"
7+
# dynamodb_table = "terraform-lock"
8+
# }
9+
# }

examples/no-dns/sample-provider.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# provider "aws" {
2+
# region = "us-east-1"
3+
# profile = "my-profile"
4+
# default_tags {
5+
# tags = {
6+
# product = var.product
7+
# environment = var.environment
8+
# repo = var.repo
9+
# organization = var.organization
10+
# }
11+
# }
12+
# }

examples/no-dns/tags.tf

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
variable "environment" {
2+
description = "Environment (sharedtools, dev, staging, prod)"
3+
type = string
4+
5+
default = "sharedtools"
6+
7+
validation {
8+
condition = contains(["sharedtools", "dev", "staging", "prod"], var.environment)
9+
error_message = "The environment variable must be one of [sharedtools, dev, staging, prod]."
10+
}
11+
}
12+
13+
variable "product" {
14+
description = "Tag used to group resources according to application"
15+
16+
default = "ex-tf-redis-no-dns"
17+
18+
validation {
19+
condition = can(regex("[a-z\\-]+", var.product))
20+
error_message = "The product variable violates approved regex."
21+
}
22+
}
23+
24+
variable "repo" {
25+
description = "Tag used to point to the repo using this module"
26+
27+
default = "https://github.com/pbs/terraform-elasticache-redis-standalone-module.git"
28+
29+
validation {
30+
condition = can(regex("(?:git|ssh|https?|git@[-\\w.]+):(\\/\\/)?(.*?)(\\.git)(\\/?|\\#[-\\d\\w._]+?)$", var.repo))
31+
error_message = "The repo variable violates approved regex."
32+
}
33+
}
34+
35+
variable "organization" {
36+
description = "Organization using this module. Used to prefix tags so that they are easily identified as being from your organization"
37+
type = string
38+
39+
default = "example"
40+
41+
validation {
42+
condition = can(regex("[a-z\\-]+", var.organization))
43+
error_message = "The organization variable violates approved regex."
44+
}
45+
}

locals.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ locals {
55
vpc_id = var.vpc_id != null ? var.vpc_id : data.aws_vpc.vpc[0].id
66
subnets = var.subnets != null ? var.subnets : data.aws_subnets.private_subnets[0].ids
77
parameter_group_name = var.parameter_group_name != null ? var.parameter_group_name : aws_elasticache_parameter_group.parameter_group.id
8+
cname = var.cname != null ? var.cname : "${local.name}-cache"
9+
private_hosted_zone = var.create_dns ? data.aws_route53_zone.private_hosted_zone[0].zone_id : null
810

911
vpc_data_lookup_tags = var.vpc_data_lookup_tags != null ? var.vpc_data_lookup_tags : {
1012
"environment" : var.environment

optional.tf

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,27 @@ variable "egress_source_sg_id" {
225225
default = null
226226
type = string
227227
}
228+
229+
variable "cname" {
230+
description = "The value to use for the CNAME record if `create_dns` is true. The primary endpoint will be <cname>.<private_hosted_zone>, and the reader endpoint will be <cname>-ro.<private_hosted_zone>. If null, the name variable will be used instead."
231+
default = null
232+
type = string
233+
}
234+
235+
variable "create_dns" {
236+
description = "Whether to create DNS records for the primary and reader endpoints."
237+
default = true
238+
type = bool
239+
}
240+
241+
variable "dns_ttl" {
242+
description = "TTL for DNS records."
243+
default = 300
244+
type = number
245+
}
246+
247+
variable "private_hosted_zone" {
248+
description = "Private hosted zone to create DNS records in. If null, `create_dns` must be set to false."
249+
default = null
250+
type = string
251+
}

outputs.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ output "member_clusters" {
2525

2626
output "primary_endpoint_address" {
2727
description = "Address of the endpoint for the primary node in the replication group."
28-
value = aws_elasticache_replication_group.replication_group.primary_endpoint_address
28+
value = var.create_dns ? aws_route53_record.primary_endpoint[0].fqdn : aws_elasticache_replication_group.replication_group.primary_endpoint_address
2929
}
3030

3131
output "reader_endpoint_address" {
3232
description = "Address of the endpoint for the reader node in the replication group."
33-
value = aws_elasticache_replication_group.replication_group.reader_endpoint_address
33+
value = var.create_dns ? aws_route53_record.reader_endpoint[0].fqdn : aws_elasticache_replication_group.replication_group.reader_endpoint_address
3434
}
3535

3636
output "tags" {

tests/go.mod

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,36 @@ module github.com/pbs/terraform-aws-elasticache-redis-standalone-module
33
go 1.13
44

55
require (
6-
cloud.google.com/go v0.103.0 // indirect
7-
cloud.google.com/go/compute v1.8.0 // indirect
8-
cloud.google.com/go/storage v1.25.0 // indirect
9-
github.com/aws/aws-sdk-go v1.44.76 // indirect
6+
cloud.google.com/go/compute v1.10.0 // indirect
7+
cloud.google.com/go/iam v0.5.0 // indirect
8+
cloud.google.com/go/storage v1.27.0 // indirect
9+
github.com/aws/aws-sdk-go v1.44.113
1010
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
1111
github.com/golang/snappy v0.0.4 // indirect
12+
github.com/google/go-cmp v0.5.9 // indirect
13+
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
1214
github.com/googleapis/gax-go/v2 v2.5.1 // indirect
13-
github.com/gruntwork-io/terratest v0.40.19
15+
github.com/gruntwork-io/terratest v0.40.22
1416
github.com/hashicorp/errwrap v1.1.0 // indirect
1517
github.com/hashicorp/go-getter v1.6.2 // indirect
1618
github.com/hashicorp/go-multierror v1.1.1 // indirect
1719
github.com/hashicorp/go-version v1.6.0 // indirect
18-
github.com/hashicorp/hcl/v2 v2.13.0 // indirect
20+
github.com/hashicorp/hcl/v2 v2.14.1 // indirect
1921
github.com/hashicorp/terraform-json v0.14.0 // indirect
2022
github.com/jinzhu/copier v0.3.5 // indirect
21-
github.com/klauspost/compress v1.15.9 // indirect
23+
github.com/klauspost/compress v1.15.11 // indirect
2224
github.com/mattn/go-zglob v0.0.3 // indirect
2325
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
2426
github.com/stretchr/testify v1.8.0
2527
github.com/tmccombs/hcl2json v0.3.4 // indirect
2628
github.com/ulikunitz/xz v0.5.10 // indirect
27-
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
28-
golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect
29-
golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7 // indirect
30-
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
31-
google.golang.org/api v0.92.0 // indirect
32-
google.golang.org/genproto v0.0.0-20220812140447-cec7f5303424 // indirect
29+
github.com/zclconf/go-cty v1.11.0 // indirect
30+
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b // indirect
31+
golang.org/x/net v0.0.0-20221004154528-8021a29435af // indirect
32+
golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1 // indirect
33+
golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 // indirect
34+
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
35+
google.golang.org/api v0.98.0 // indirect
36+
google.golang.org/genproto v0.0.0-20220930163606-c98284e70a91 // indirect
37+
google.golang.org/grpc v1.50.0 // indirect
3338
)

0 commit comments

Comments
 (0)