diff --git a/.gitignore b/.gitignore index c84de37..4e7a3c8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.tfstate *.tfstate.backup .terraform +.terraform.lock.hcl diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9729b21..e1b851b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,10 +1,10 @@ repos: - repo: git://github.com/antonbabenko/pre-commit-terraform - rev: v1.21.0 + rev: v1.30.0 hooks: - id: terraform_fmt - id: terraform_docs - repo: git://github.com/pre-commit/pre-commit-hooks - rev: v2.4.0 + rev: v3.1.0 hooks: - id: check-merge-conflict diff --git a/README.md b/README.md index 9d286ab..ae1bfae 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A terraform module providing a Redis ElastiCache cluster in AWS. -This module +This module is forked from [tf_aws_elasticache_redis Communitiy module](https://github.com/terraform-community-modules/tf_aws_elasticache_redis) and performs the following tasks: - Creates Redis ElastiCache clusters - Creates, manages, and exports a security group @@ -11,14 +11,13 @@ This module Terraform 0.12. Pin module version to `~> v2.0`. Submit pull-requests to `master` branch. -Terraform 0.11. Pin module version to `~> v1.0`. +Terraform 0.11. Pin module version to `~> v1.0`. Submit pull-requests to `terraform011` branch. ## Usage ```hcl module "redis" { - source = "github.com/terraform-community-modules/tf_aws_elasticache_redis.git" - version = "~> 2.0" + source = "github.com/flywirecorp/tf_aws_elasticache_redis.git?ref=v2.2.0" env = "dev" name = "thtest" @@ -41,41 +40,83 @@ module "redis" { ``` +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.12 | +| [aws](#requirement\_aws) | ~> 4.12 | +| [random](#requirement\_random) | ~> 3.1 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 4.12 | +| [random](#provider\_random) | ~> 3.1 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_elasticache_parameter_group.redis_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_parameter_group) | resource | +| [aws_elasticache_replication_group.redis](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_replication_group) | resource | +| [aws_elasticache_subnet_group.redis_subnet_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_subnet_group) | resource | +| [aws_security_group.redis_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group_rule.redis_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.redis_networks_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.redis_replication_egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [random_id.salt](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | +| [aws_vpc.vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source | + ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|:----:|:-----:|:-----:| -| alarm\_actions | | list | n/a | yes | -| alarm\_cpu\_threshold | These vars would be used by cloudwatch.tf and should be uncommented if we decide to use them. | string | `"75"` | no | -| alarm\_memory\_threshold | | string | `"10000000"` | no | -| allowed\_cidr | A list of Security Group ID's to allow access to. | list(string) | `[ "127.0.0.1/32" ]` | no | -| allowed\_security\_groups | A list of Security Group ID's to allow access to. | list(string) | `[]` | no | -| apply\_immediately | Specifies whether any modifications are applied immediately, or during the next maintenance window. Default is false. | bool | `"false"` | no | -| env | env to deploy into, should typically dev/staging/prod | string | n/a | yes | -| name | Name for the Redis replication group i.e. UserObject | string | n/a | yes | -| redis\_clusters | Number of Redis cache clusters (nodes) to create | string | n/a | yes | -| redis\_failover | | bool | `"false"` | no | -| redis\_maintenance\_window | Specifies the weekly time range for when maintenance on the cache cluster is performed. The format is ddd:hh24:mi-ddd:hh24:mi (24H Clock UTC). The minimum maintenance window is a 60 minute period | string | `"fri:08:00-fri:09:00"` | no | -| redis\_node\_type | Instance type to use for creating the Redis cache clusters | string | `"cache.m3.medium"` | no | -| redis\_parameters | additional parameters modifyed in parameter group | list(map(any)) | `[]` | no | -| redis\_port | | number | `"6379"` | no | -| redis\_snapshot\_retention\_limit | The number of days for which ElastiCache will retain automatic cache cluster snapshots before deleting them. For example, if you set SnapshotRetentionLimit to 5, then a snapshot that was taken today will be retained for 5 days before being deleted. If the value of SnapshotRetentionLimit is set to zero (0), backups are turned off. Please note that setting a snapshot_retention_limit is not supported on cache.t1.micro or cache.t2.* cache nodes | number | `"0"` | no | -| redis\_snapshot\_window | The daily time range (in UTC) during which ElastiCache will begin taking a daily snapshot of your cache cluster. The minimum snapshot window is a 60 minute period | string | `"06:30-07:30"` | no | -| redis\_version | Redis version to use, defaults to 3.2.10 | string | `"3.2.10"` | no | -| subnets | List of VPC Subnet IDs for the cache subnet group | list(string) | n/a | yes | -| tags | Tags for redis nodes | map(string) | `{}` | no | -| vpc\_id | VPC ID | string | n/a | yes | +|------|-------------|------|---------|:--------:| +| [env](#input\_env) | env to deploy into, should typically dev/staging/prod | `string` | n/a | yes | +| [name](#input\_name) | Name for the Redis replication group i.e. UserObject | `string` | n/a | yes | +| [redis\_clusters](#input\_redis\_clusters) | Number of Redis cache clusters (nodes) to create | `string` | n/a | yes | +| [subnets](#input\_subnets) | List of VPC Subnet IDs for the cache subnet group | `list(string)` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | VPC ID | `string` | n/a | yes | +| [allowed\_cidr](#input\_allowed\_cidr) | A list of Security Group ID's to allow access to. | `list(string)` |
[| no | +| [allowed\_security\_groups](#input\_allowed\_security\_groups) | A list of Security Group ID's to allow access to. | `list(string)` | `[]` | no | +| [apply\_immediately](#input\_apply\_immediately) | Specifies whether any modifications are applied immediately, or during the next maintenance window. Default is false. | `bool` | `false` | no | +| [at\_rest\_encryption\_enabled](#input\_at\_rest\_encryption\_enabled) | Whether to enable encryption at rest | `bool` | `false` | no | +| [auth\_token](#input\_auth\_token) | The password used to access a password protected server. Can be specified only if transit\_encryption\_enabled = true. If specified must contain from 16 to 128 alphanumeric characters or symbols | `string` | `null` | no | +| [auto\_minor\_version\_upgrade](#input\_auto\_minor\_version\_upgrade) | Specifies whether a minor engine upgrades will be applied automatically to the underlying Cache Cluster instances during the maintenance window | `bool` | `true` | no | +| [availability\_zones](#input\_availability\_zones) | A list of EC2 availability zones in which the replication group's cache clusters will be created. The order of the availability zones in the list is not important | `list(string)` | `[]` | no | +| [is\_migration\_cluster](#input\_is\_migration\_cluster) | Specifies whether this is a cluster for replicating other EC2 redis. Useful for migrations. | `bool` | `false` | no | +| [kms\_key\_id](#input\_kms\_key\_id) | The ARN of the key that you wish to use if encrypting at rest. If not supplied, uses service managed encryption. Can be specified only if at\_rest\_encryption\_enabled = true | `string` | `""` | no | +| [multi\_az\_enabled](#input\_multi\_az\_enabled) | Specifies whether to enable Multi-AZ Support for the replication group | `bool` | `false` | no | +| [notification\_topic\_arn](#input\_notification\_topic\_arn) | An Amazon Resource Name (ARN) of an SNS topic to send ElastiCache notifications to. Example: arn:aws:sns:us-east-1:012345678999:my\_sns\_topic | `string` | `""` | no | +| [redis\_failover](#input\_redis\_failover) | Specifies whether a read-only replica will be automatically promoted to read/write primary if the existing primary fails | `bool` | `false` | no | +| [redis\_maintenance\_window](#input\_redis\_maintenance\_window) | Specifies the weekly time range for when maintenance on the cache cluster is performed. The format is ddd:hh24:mi-ddd:hh24:mi (24H Clock UTC). The minimum maintenance window is a 60 minute period | `string` | `"fri:08:00-fri:09:00"` | no | +| [redis\_node\_type](#input\_redis\_node\_type) | Instance type to use for creating the Redis cache clusters | `string` | `"cache.m3.medium"` | no | +| [redis\_parameters](#input\_redis\_parameters) | additional parameters modifyed in parameter group | `list(map(any))` | `[]` | no | +| [redis\_port](#input\_redis\_port) | n/a | `number` | `6379` | no | +| [redis\_snapshot\_retention\_limit](#input\_redis\_snapshot\_retention\_limit) | The number of days for which ElastiCache will retain automatic cache cluster snapshots before deleting them. For example, if you set SnapshotRetentionLimit to 5, then a snapshot that was taken today will be retained for 5 days before being deleted. If the value of SnapshotRetentionLimit is set to zero (0), backups are turned off. Please note that setting a snapshot\_retention\_limit is not supported on cache.t1.micro or cache.t2.* cache nodes | `number` | `0` | no | +| [redis\_snapshot\_window](#input\_redis\_snapshot\_window) | The daily time range (in UTC) during which ElastiCache will begin taking a daily snapshot of your cache cluster. The minimum snapshot window is a 60 minute period | `string` | `"06:30-07:30"` | no | +| [redis\_version](#input\_redis\_version) | Redis version to use, defaults to 3.2.10 | `string` | `"3.2.10"` | no | +| [security\_group\_names](#input\_security\_group\_names) | A list of cache security group names to associate with this replication group | `list(string)` | `[]` | no | +| [snapshot\_arns](#input\_snapshot\_arns) | A single-element string list containing an Amazon Resource Name (ARN) of a Redis RDB snapshot file stored in Amazon S3. Example: arn:aws:s3:::my\_bucket/snapshot1.rdb | `list(string)` | `[]` | no | +| [snapshot\_name](#input\_snapshot\_name) | The name of a snapshot from which to restore data into the new node group. Changing the snapshot\_name forces a new resource | `string` | `""` | no | +| [tags](#input\_tags) | Tags for redis nodes | `map(string)` | `{}` | no | +| [transit\_encryption\_enabled](#input\_transit\_encryption\_enabled) | Whether to enable encryption in transit. Requires 3.2.6 or >=4.0 redis\_version | `bool` | `false` | no | ## Outputs | Name | Description | |------|-------------| -| endpoint | | -| id | | -| parameter\_group | | -| port | | -| redis\_security\_group\_id | | -| redis\_subnet\_group\_name | | +| [endpoint](#output\_endpoint) | Redis endpoint address | +| [id](#output\_id) | ID of the Redis replication group | +| [parameter\_group](#output\_parameter\_group) | ID of the Parameter Group to control the runtime properties of Redis nodes and clusters | +| [port](#output\_port) | Redis port (default is 6379) | +| [redis\_security\_group\_id](#output\_redis\_security\_group\_id) | ID of the managed Security Group generated for Redis | +| [redis\_subnet\_group\_name](#output\_redis\_subnet\_group\_name) | Name of the Redis subnet | @@ -83,6 +124,8 @@ module "redis" { Created by [Tim Hartmann](https://github.com/tfhartmann). Maintained by [Anton Babenko](https://github.com/antonbabenko) and [these awesome contributors](https://github.com/terraform-community-modules/tf_aws_elasticache_redis/graphs/contributors). +This fork is possible thanks to [these contributors](https://github.com/flywirecorp/tf_aws_elasticache_redis/graphs/contributors) + ## License [MIT License](LICENSE) diff --git a/cloudwatch.tf b/cloudwatch.tf index 75bbea9..3cedca1 100644 --- a/cloudwatch.tf +++ b/cloudwatch.tf @@ -6,7 +6,7 @@ resource "aws_cloudwatch_metric_alarm" "cache_cpu" { count = "${var.redis_clusters}" - alarm_name = "alarm-${var.name}-${data.aws_vpc.vpc.tags["Name"]}-CacheCluster00${count.index + 1}CPUUtilization" + alarm_name = "alarm-${var.name}-${local.vpc_name}-CacheCluster00${count.index + 1}CPUUtilization" alarm_description = "Redis cluster CPU utilization" comparison_operator = "GreaterThanThreshold" evaluation_periods = "1" @@ -27,7 +27,7 @@ resource "aws_cloudwatch_metric_alarm" "cache_cpu" { resource "aws_cloudwatch_metric_alarm" "cache_memory" { count = "${var.redis_clusters}" - alarm_name = "alarm-${var.name}-${data.aws_vpc.vpc.tags["Name"]}-CacheCluster00${count.index + 1}FreeableMemory" + alarm_name = "alarm-${var.name}-${local.vpc_name}-CacheCluster00${count.index + 1}FreeableMemory" alarm_description = "Redis cluster freeable memory" comparison_operator = "LessThanThreshold" evaluation_periods = "1" diff --git a/main.tf b/main.tf index 0192f51..00bea21 100644 --- a/main.tf +++ b/main.tf @@ -2,6 +2,12 @@ data "aws_vpc" "vpc" { id = var.vpc_id } +locals { + vpc_name = lookup(data.aws_vpc.vpc.tags, "Name", var.vpc_id) + major_redis_version = parseint(substr(var.redis_version, 0, 1), 10) + parameter_group_family = local.major_redis_version < 6 ? "redis${replace(var.redis_version, "/\\.[\\d]+$/", "")}" : local.major_redis_version == 6 ? "redis${replace(var.redis_version, "/\\.[\\d|x]+$/", "")}.x" : "redis${local.major_redis_version}" +} + resource "random_id" "salt" { keepers = { redis_version = "${var.redis_version}" @@ -10,31 +16,42 @@ resource "random_id" "salt" { } resource "aws_elasticache_replication_group" "redis" { - replication_group_id = format("%.20s", "${var.name}-${var.env}") - replication_group_description = "Terraform-managed ElastiCache replication group for ${var.name}-${var.env}-${data.aws_vpc.vpc.tags["Name"]}" - number_cache_clusters = var.redis_clusters - node_type = var.redis_node_type - automatic_failover_enabled = var.redis_failover - multi_az_enabled = var.multi_az_enabled - engine_version = var.redis_version - port = var.redis_port - parameter_group_name = aws_elasticache_parameter_group.redis_parameter_group.id - subnet_group_name = aws_elasticache_subnet_group.redis_subnet_group.id - security_group_ids = [aws_security_group.redis_security_group.id] - apply_immediately = var.apply_immediately - maintenance_window = var.redis_maintenance_window - snapshot_window = var.redis_snapshot_window - snapshot_retention_limit = var.redis_snapshot_retention_limit - tags = merge(map("Name", format("tf-elasticache-%s-%s", var.name, lookup(data.aws_vpc.vpc.tags, "Name", ""))), var.tags) + replication_group_id = format("%.20s", "${var.name}-${var.env}") + description = "Terraform-managed ElastiCache replication group for ${var.name}-${var.env}-${local.vpc_name}" + num_cache_clusters = var.redis_clusters + node_type = var.redis_node_type + automatic_failover_enabled = var.redis_failover + auto_minor_version_upgrade = var.auto_minor_version_upgrade + preferred_cache_cluster_azs = var.availability_zones + multi_az_enabled = var.multi_az_enabled + engine = "redis" + at_rest_encryption_enabled = var.at_rest_encryption_enabled + kms_key_id = var.kms_key_id + transit_encryption_enabled = var.transit_encryption_enabled + auth_token = var.transit_encryption_enabled ? var.auth_token : null + engine_version = var.redis_version + port = var.redis_port + parameter_group_name = aws_elasticache_parameter_group.redis_parameter_group.id + subnet_group_name = aws_elasticache_subnet_group.redis_subnet_group.id + security_group_names = var.security_group_names + security_group_ids = [aws_security_group.redis_security_group.id] + snapshot_arns = var.snapshot_arns + snapshot_name = var.snapshot_name + apply_immediately = var.apply_immediately + maintenance_window = var.redis_maintenance_window + notification_topic_arn = var.notification_topic_arn + snapshot_window = var.redis_snapshot_window + snapshot_retention_limit = var.redis_snapshot_retention_limit + tags = merge(tomap({ "Name" = format("tf-elasticache-%s-%s", var.name, local.vpc_name) }), var.tags) } resource "aws_elasticache_parameter_group" "redis_parameter_group" { - name = replace(format("%.255s", lower(replace("tf-redis-${var.name}-${var.env}-${data.aws_vpc.vpc.tags["Name"]}-${random_id.salt.hex}", "_", "-"))), "/\\s/", "-") + name = replace(format("%.255s", lower(replace("tf-redis-${var.name}-${var.env}-${local.vpc_name}-${random_id.salt.hex}", "_", "-"))), "/\\s/", "-") - description = "Terraform-managed ElastiCache parameter group for ${var.name}-${var.env}-${data.aws_vpc.vpc.tags["Name"]}" + description = "Terraform-managed ElastiCache parameter group for ${var.name}-${var.env}-${local.vpc_name}" # Strip the patch version from redis_version var - family = "redis${replace(var.redis_version, "/\\.[\\d]+$/", "")}" + family = local.parameter_group_family dynamic "parameter" { for_each = var.redis_parameters content { @@ -49,6 +66,6 @@ resource "aws_elasticache_parameter_group" "redis_parameter_group" { } resource "aws_elasticache_subnet_group" "redis_subnet_group" { - name = replace(format("%.255s", lower(replace("tf-redis-${var.name}-${var.env}-${data.aws_vpc.vpc.tags["Name"]}", "_", "-"))), "/\\s/", "-") + name = replace(format("%.255s", lower(replace("tf-redis-${var.name}-${var.env}-${local.vpc_name}", "_", "-"))), "/\\s/", "-") subnet_ids = var.subnets } diff --git a/outputs.tf b/outputs.tf index a4507c9..ffa3a73 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,23 +1,30 @@ output "redis_security_group_id" { - value = aws_security_group.redis_security_group.id + value = aws_security_group.redis_security_group.id + description = "ID of the managed Security Group generated for Redis" } output "parameter_group" { - value = aws_elasticache_parameter_group.redis_parameter_group.id + value = aws_elasticache_parameter_group.redis_parameter_group.id + description = "ID of the Parameter Group to control the runtime properties of Redis nodes and clusters" } output "redis_subnet_group_name" { - value = aws_elasticache_subnet_group.redis_subnet_group.name + value = aws_elasticache_subnet_group.redis_subnet_group.name + description = "Name of the Redis subnet" + } output "id" { - value = aws_elasticache_replication_group.redis.id + value = aws_elasticache_replication_group.redis.id + description = "ID of the Redis replication group" } output "port" { - value = var.redis_port + value = var.redis_port + description = "Redis port (default is 6379)" } output "endpoint" { - value = aws_elasticache_replication_group.redis.primary_endpoint_address + value = aws_elasticache_replication_group.redis.primary_endpoint_address + description = "Redis endpoint address" } diff --git a/security_groups.tf b/security_groups.tf index 8fe8b9e..db8d2db 100644 --- a/security_groups.tf +++ b/security_groups.tf @@ -1,10 +1,10 @@ resource "aws_security_group" "redis_security_group" { - name = format("%.255s", "tf-sg-ec-${var.name}-${var.env}-${data.aws_vpc.vpc.tags["Name"]}") - description = "Terraform-managed ElastiCache security group for ${var.name}-${var.env}-${data.aws_vpc.vpc.tags["Name"]}" + name = format("%.255s", "tf-sg-ec-${var.name}-${var.env}-${local.vpc_name}") + description = "Terraform-managed ElastiCache security group for ${var.name}-${var.env}-${local.vpc_name}" vpc_id = data.aws_vpc.vpc.id tags = { - Name = "tf-sg-ec-${var.name}-${var.env}-${data.aws_vpc.vpc.tags["Name"]}" + Name = "tf-sg-ec-${var.name}-${var.env}-${local.vpc_name}" } } diff --git a/variables.tf b/variables.tf index 31b254c..5e53b33 100644 --- a/variables.tf +++ b/variables.tf @@ -49,20 +49,20 @@ variable "redis_clusters" { variable "multi_az_enabled" { description = "Specifies whether to enable Multi-AZ Support for the replication group" - type = bool - default = false + type = bool + default = false } variable "redis_failover" { description = "Specifies whether a read-only replica will be automatically promoted to read/write primary if the existing primary fails" - type = bool - default = false + type = bool + default = false } variable "is_migration_cluster" { description = "Specifies whether this is a cluster for replicating other EC2 redis. Useful for migrations." - type = bool - default = false + type = bool + default = false } variable "redis_node_type" { @@ -122,3 +122,63 @@ variable "tags" { type = map(string) default = {} } + +variable "auto_minor_version_upgrade" { + description = "Specifies whether a minor engine upgrades will be applied automatically to the underlying Cache Cluster instances during the maintenance window" + type = bool + default = true +} + +variable "availability_zones" { + description = "A list of EC2 availability zones in which the replication group's cache clusters will be created. The order of the availability zones in the list is not important" + type = list(string) + default = [] +} + +variable "at_rest_encryption_enabled" { + description = "Whether to enable encryption at rest" + type = bool + default = false +} + +variable "kms_key_id" { + description = "The ARN of the key that you wish to use if encrypting at rest. If not supplied, uses service managed encryption. Can be specified only if at_rest_encryption_enabled = true" + type = string + default = "" +} + +variable "transit_encryption_enabled" { + description = "Whether to enable encryption in transit. Requires 3.2.6 or >=4.0 redis_version" + type = bool + default = false +} + +variable "auth_token" { + description = "The password used to access a password protected server. Can be specified only if transit_encryption_enabled = true. If specified must contain from 16 to 128 alphanumeric characters or symbols" + type = string + default = null +} + +variable "security_group_names" { + description = "A list of cache security group names to associate with this replication group" + type = list(string) + default = [] +} + +variable "snapshot_arns" { + description = "A single-element string list containing an Amazon Resource Name (ARN) of a Redis RDB snapshot file stored in Amazon S3. Example: arn:aws:s3:::my_bucket/snapshot1.rdb" + type = list(string) + default = [] +} + +variable "snapshot_name" { + description = " The name of a snapshot from which to restore data into the new node group. Changing the snapshot_name forces a new resource" + type = string + default = "" +} + +variable "notification_topic_arn" { + description = "An Amazon Resource Name (ARN) of an SNS topic to send ElastiCache notifications to. Example: arn:aws:sns:us-east-1:012345678999:my_sns_topic" + type = string + default = "" +} diff --git a/versions.tf b/versions.tf index 8f89837..ea31388 100644 --- a/versions.tf +++ b/versions.tf @@ -1,11 +1,13 @@ terraform { required_version = ">= 0.12" -} - -provider "aws" { - version = "~> 4.12" -} - -provider "random" { - version = "~> 3.1" -} + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.12" + } + random = { + source = "hashicorp/random" + version = "~> 3.1" + } + } +} \ No newline at end of file
"127.0.0.1/32"
]