-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feature] Add aws-redis-replication-group (#267)
### Summary This module is similar to [aws-redis-node](https://github.com/chanzuckerberg/cztack/tree/main/aws-redis-node), however it creates a Elasticache Redis cluster using a replication group. The motivation to create this module is because encryption options (in-transit and at rest) are only available when you create your cluster using a replication group. ### Test Plan - Manual tests (already applied to IDseq) - Unit tests ### References (Optional) Additional links to provide more context.
- Loading branch information
1 parent
68ab717
commit 1b53806
Showing
7 changed files
with
288 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Redis Replication Group | ||
|
||
This module creates a Elasticache Redis cluster using | ||
a replication group with the given parameters. | ||
|
||
<!-- START --> | ||
## Requirements | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| aws | < 3.0.0 | | ||
|
||
## Providers | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| aws | < 3.0.0 | | ||
|
||
## Inputs | ||
|
||
| Name | Description | Type | Default | Required | | ||
|------|-------------|------|---------|:--------:| | ||
| at\_rest\_encryption\_enabled | Whether to enable encryption at rest. | `bool` | `false` | no | | ||
| apply\_immediately | Whether changes should be applied immediately or during the next maintenance window. | `bool` | `true` | no | | ||
| availability\_zone | Availability zone in which this instance should run. | `string` | `null` | no | | ||
| engine\_version | The version of Redis to run. See [supported versions](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/supported-engine-versions.html) | `string` | `"5.0.5"` | no | | ||
| env | Env for tagging and naming. See [doc](../README.md#consistent-tagging). | `string` | n/a | yes | | ||
| ingress\_security\_group\_ids | Source security groups which should be able to contact this instance. | `list(string)` | n/a | yes | | ||
| instance\_type | The type of instance to run. See [supported node types](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/CacheNodes.SupportedTypes.html) | `string` | `"cache.m5.large"` | no | | ||
| number_cache_clusters | Number of cache clusters. | `number` | 1 | no | | ||
| owner | Owner for tagging and naming. See [doc](../README.md#consistent-tagging). | `string` | n/a | yes | | ||
| parameter\_group\_name | Parameter group to use for this Redis cache. | `string` | `"default.redis5.0"` | no | | ||
| port | Port to host Redis on. | `number` | `6379` | no | | ||
| project | Project for tagging and naming. See [doc](../README.md#consistent-tagging) | `string` | n/a | yes | | ||
| replication\_group\_description | A user-created description for the replication group. | `string` | n/a | yes | | ||
| resource\_name | If not set, name will be [var.project]-[var.env]-[var.name]. | `string` | `""` | no | | ||
| service | Service for tagging and naming. See [doc](../README.md#consistent-tagging) | `string` | `"redis"` | no | | ||
| subnets | List of subnets to which this EC instance should be attached. They should probably be private. | `list(string)` | n/a | yes | | ||
| transit\_encryption\_enabled | Whether to enable encryption in transit. | `bool` | `false` | no | | ||
| vpc\_id | VPC where the cache will be deployed. | `string` | n/a | yes | | ||
|
||
## Outputs | ||
|
||
| Name | Description | | ||
|------|-------------| | ||
| primary_endpoint_address | The endpoint of the primary node in this node group (shard). | | ||
| configuration_endpoint_address | The configuration endpoint address to allow host discovery. | | ||
| port | Redis TCP port. | | ||
|
||
<!-- END --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
locals { | ||
name = "${var.project}-${var.env}-${var.service}" | ||
|
||
tags = { | ||
managedBy = "terraform" | ||
Name = "${var.project}-${var.env}-${var.service}" | ||
project = var.project | ||
env = var.env | ||
service = var.service | ||
owner = var.owner | ||
} | ||
} | ||
|
||
module "sg" { | ||
source = "terraform-aws-modules/security-group/aws" | ||
version = "3.12.0" | ||
name = local.name | ||
description = "Allow traffic to Redis." | ||
vpc_id = var.vpc_id | ||
tags = local.tags | ||
|
||
ingress_with_source_security_group_id = [ | ||
for sg in var.ingress_security_group_ids : { | ||
from_port = var.port | ||
to_port = var.port | ||
protocol = "tcp" | ||
description = "Redis port" | ||
source_security_group_id = sg | ||
} | ||
] | ||
|
||
egress_rules = ["all-all"] | ||
} | ||
|
||
resource "aws_elasticache_subnet_group" "default" { | ||
name = var.resource_name != "" ? var.resource_name : local.name | ||
subnet_ids = var.subnets | ||
} | ||
|
||
resource "aws_elasticache_replication_group" "default" { | ||
replication_group_id = var.resource_name != "" ? var.resource_name : local.name | ||
replication_group_description = var.replication_group_description | ||
engine = "redis" | ||
engine_version = var.engine_version | ||
node_type = var.instance_type | ||
port = var.port | ||
number_cache_clusters = var.number_cache_clusters | ||
parameter_group_name = var.parameter_group_name | ||
subnet_group_name = aws_elasticache_subnet_group.default.name | ||
security_group_ids = [module.sg.this_security_group_id] | ||
apply_immediately = var.apply_immediately | ||
at_rest_encryption_enabled = var.at_rest_encryption_enabled | ||
transit_encryption_enabled = var.transit_encryption_enabled | ||
availability_zones = var.availability_zones | ||
tags = local.tags | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package test | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"os" | ||
"testing" | ||
|
||
"github.com/chanzuckerberg/go-misc/tftest" | ||
"github.com/gruntwork-io/terratest/modules/terraform" | ||
) | ||
|
||
func TestAWSRedisReplicationGroup(t *testing.T) { | ||
test := tftest.Test{ | ||
|
||
Setup: func(t *testing.T) *terraform.Options { | ||
privateSubnets := tftest.ListEnvVar("PRIVATE_SUBNETS") | ||
log.Printf("subnets %#v\n", privateSubnets) | ||
log.Printf("subnets %#v\n", os.Getenv("PRIVATE_SUBNETS")) | ||
vpc := tftest.EnvVar(tftest.EnvVPCID) | ||
|
||
sg := tftest.CreateSecurityGroup(t, tftest.DefaultRegion, vpc) | ||
|
||
project := tftest.UniqueID() | ||
env := tftest.UniqueID() | ||
service := tftest.UniqueID() | ||
owner := tftest.UniqueID() | ||
replication_group_description := tftest.UniqueID() | ||
transit_encryption_enabled := true | ||
at_rest_encryption_enabled := true | ||
|
||
az := fmt.Sprintf("%sa", tftest.DefaultRegion) | ||
|
||
return tftest.Options(tftest.DefaultRegion, | ||
map[string]interface{}{ | ||
"project": project, | ||
"env": env, | ||
"service": service, | ||
"owner": owner, | ||
|
||
"availability_zones": []string{az}, | ||
"subnets": privateSubnets, | ||
"ingress_security_group_ids": []string{sg}, | ||
"vpc_id": vpc, | ||
|
||
"replication_group_description": replication_group_description, | ||
"transit_encryption_enabled": transit_encryption_enabled, | ||
"at_rest_encryption_enabled": at_rest_encryption_enabled, | ||
}, | ||
) | ||
}, | ||
Validate: func(t *testing.T, options *terraform.Options) {}, | ||
|
||
Cleanup: func(t *testing.T, options *terraform.Options) { | ||
tftest.DeleteSecurityGroup(t, tftest.DefaultRegion, options.Vars["ingress_security_group_ids"].([]interface{})[0].(string)) | ||
}, | ||
} | ||
|
||
test.Run(t) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
output "primary_endpoint_address" { | ||
description = "The endpoint of the primary node in this node group (shard)." | ||
value = aws_elasticache_replication_group.default.primary_endpoint_address | ||
} | ||
|
||
output "configuration_endpoint_address" { | ||
description = "The configuration endpoint address to allow host discovery." | ||
value = aws_elasticache_replication_group.default.configuration_endpoint_address | ||
} | ||
|
||
output "port" { | ||
description = "Redis TCP port." | ||
value = var.port | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
terraform { | ||
required_providers { | ||
aws = "< 3.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
variable "project" { | ||
type = string | ||
description = "Project for tagging and naming. See [doc](../README.md#consistent-tagging)" | ||
} | ||
|
||
variable "env" { | ||
type = string | ||
description = "Env for tagging and naming. See [doc](../README.md#consistent-tagging)." | ||
} | ||
|
||
variable "service" { | ||
type = string | ||
description = "Service for tagging and naming. See [doc](../README.md#consistent-tagging)" | ||
default = "redis" | ||
} | ||
|
||
variable "owner" { | ||
type = string | ||
description = "Owner for tagging and naming. See [doc](../README.md#consistent-tagging)." | ||
} | ||
|
||
variable "subnets" { | ||
type = list(string) | ||
description = "List of subnets to which this EC instance should be attached. They should probably be private." | ||
} | ||
|
||
variable "availability_zones" { | ||
type = list(string) | ||
description = "Availability zone in which this instance should run." | ||
default = null | ||
} | ||
|
||
variable "ingress_security_group_ids" { | ||
type = list(string) | ||
description = "Source security groups which should be able to contact this instance." | ||
} | ||
|
||
variable "port" { | ||
type = number | ||
description = "Port to host Redis on." | ||
default = 6379 | ||
} | ||
|
||
variable "instance_type" { | ||
type = string | ||
description = "The type of instance to run. See [supported node types](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/CacheNodes.SupportedTypes.html)" | ||
default = "cache.m5.large" | ||
} | ||
|
||
variable "parameter_group_name" { | ||
type = string | ||
description = "Parameter group to use for this Redis cache." | ||
default = "default.redis5.0" | ||
} | ||
|
||
variable "engine_version" { | ||
type = string | ||
description = "The version of Redis to run. See [supported versions](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/supported-engine-versions.html)" | ||
default = "5.0.5" | ||
} | ||
|
||
variable "apply_immediately" { | ||
type = bool | ||
description = "Whether changes should be applied immediately or during the next maintenance window." | ||
default = true | ||
} | ||
|
||
# This is to get a around a limitation where the elasticache cluster id can be | ||
# only 20 characters long. Use it only if you get that error. | ||
variable "resource_name" { | ||
description = "If not set, name will be [var.project]-[var.env]-[var.name]." | ||
type = string | ||
default = "" | ||
} | ||
|
||
variable "vpc_id" { | ||
type = string | ||
description = "VPC where the cache will be deployed." | ||
} | ||
|
||
variable "number_cache_clusters" { | ||
type = number | ||
description = "Number of cache clusters. Default 1." | ||
default = 1 | ||
} | ||
|
||
variable "at_rest_encryption_enabled" { | ||
type = bool | ||
description = "Whether to enable encryption at rest. Default: false." | ||
default = false | ||
} | ||
|
||
variable "transit_encryption_enabled" { | ||
type = bool | ||
description = "Whether to enable encryption in transit. Default: false." | ||
default = false | ||
} | ||
|
||
variable "replication_group_description" { | ||
type = string | ||
description = "A user-created description for the replication group." | ||
} |