Skip to content

Commit

Permalink
Use Security Group rules instead of inline rule blocks. Fix example. …
Browse files Browse the repository at this point in the history
…Fix README. Update to latest versions of modules. Change region for tests (#54)

* Use Security Group rules instead of inline rule blocks. Fix example. Fix README. Update to latest versions of modules. Change region for tests

* Use Security Group rules instead of inline rule blocks. Fix example. Fix README. Update to latest versions of modules. Change region for tests

* Use Security Group rules instead of inline rule blocks. Fix example. Fix README. Update to latest versions of modules. Change region for tests
  • Loading branch information
aknysh authored Dec 25, 2019
1 parent 94f19dd commit d27d632
Show file tree
Hide file tree
Showing 12 changed files with 326 additions and 178 deletions.
229 changes: 151 additions & 78 deletions README.md

Large diffs are not rendered by default.

86 changes: 55 additions & 31 deletions README.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,38 +49,62 @@ description: |-
# How to use this project
usage: |-
For a complete example, see [examples/complete](examples/complete).
For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) (which tests and deploys the example on AWS), see [test](test).
```hcl
// Generate a random string for auth token, no special chars
resource "random_string" "auth_token" {
length = 64
special = false
}
module "example_redis" {
source = "git::https://github.com/cloudposse/terraform-aws-elasticache-redis.git?ref=master"
namespace = "eg"
stage = "dev"
name = "redis"
zone_id = var.route53_zone_id
security_groups = [var.security_group_id]
auth_token = random_string.auth_token.result
vpc_id = var.vpc_id
subnets = var.private_subnets
maintenance_window = "wed:03:00-wed:04:00"
cluster_size = 2
instance_type = "cache.t2.micro"
engine_version = "4.0.10"
alarm_cpu_threshold_percent = var.cache_alarm_cpu_threshold_percent
alarm_memory_threshold_bytes = var.cache_alarm_memory_threshold_bytes
apply_immediately = true
availability_zones = var.availability_zones
automatic_failover = false
}
output "auth_token" {
value = random_string.auth_token.result
}
provider "aws" {
region = var.region
}
module "vpc" {
source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.1"
namespace = var.namespace
stage = var.stage
name = var.name
cidr_block = "172.16.0.0/16"
}
module "subnets" {
source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.18.1"
availability_zones = var.availability_zones
namespace = var.namespace
stage = var.stage
name = var.name
vpc_id = module.vpc.vpc_id
igw_id = module.vpc.igw_id
cidr_block = module.vpc.vpc_cidr_block
nat_gateway_enabled = true
nat_instance_enabled = false
}
module "redis" {
source = "git::https://github.com/cloudposse/terraform-aws-elasticache-redis.git?ref=master"
availability_zones = var.availability_zones
namespace = var.namespace
stage = var.stage
name = var.name
zone_id = var.zone_id
vpc_id = module.vpc.vpc_id
allowed_security_groups = [module.vpc.vpc_default_security_group_id]
subnets = module.subnets.private_subnet_ids
cluster_size = var.cluster_size
instance_type = var.instance_type
apply_immediately = true
automatic_failover = false
engine_version = var.engine_version
family = var.family
at_rest_encryption_enabled = var.at_rest_encryption_enabled
transit_encryption_enabled = var.transit_encryption_enabled
parameter = [
{
name = "notify-keyspace-events"
value = "lK"
}
]
}
```
examples: |-
Expand Down
17 changes: 12 additions & 5 deletions docs/terraform.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,23 @@
| alarm_actions | Alarm action list | list(string) | `<list>` | no |
| alarm_cpu_threshold_percent | CPU threshold alarm level | number | `75` | no |
| alarm_memory_threshold_bytes | Ram threshold alarm level | number | `10000000` | no |
| allowed_cidr_blocks | List of CIDR blocks that are allowed ingress to the cluster's Security Group created in the module | list(string) | `<list>` | no |
| allowed_security_groups | List of Security Group IDs that are allowed ingress to the cluster's Security Group created in the module | list(string) | `<list>` | no |
| apply_immediately | Apply changes immediately | bool | `true` | no |
| at_rest_encryption_enabled | Enable encryption at rest | bool | `false` | no |
| attributes | Additional attributes (_e.g._ "1") | list(string) | `<list>` | no |
| auth_token | Auth token for password protecting redis, `transit_encryption_enabled` must be set to `true`. Password must be longer than 16 chars | string | `` | no |
| automatic_failover | Automatic failover (Not available for T1/T2 instances) | bool | `false` | no |
| auth_token | Auth token for password protecting redis, `transit_encryption_enabled` must be set to `true`. Password must be longer than 16 chars | string | `null` | no |
| automatic_failover_enabled | Automatic failover (Not available for T1/T2 instances) | bool | `false` | no |
| availability_zones | Availability zone IDs | list(string) | `<list>` | no |
| cluster_size | Count of nodes in cluster | number | `1` | no |
| cluster_mode_enabled | Flag to enable/disable creation of a native redis cluster. `automatic_failover_enabled` must be set to `true`. Only 1 `cluster_mode` block is allowed | bool | `false` | no |
| cluster_mode_num_node_groups | Number of node groups (shards) for this Redis replication group. Changing this number will trigger an online resizing operation before other settings modifications | number | `0` | no |
| cluster_mode_replicas_per_node_group | Number of replica nodes in each node group. Valid values are 0 to 5. Changing this number will force a new resource | number | `0` | no |
| cluster_size | Number of nodes in cluster | number | `1` | no |
| delimiter | Delimiter between `name`, `namespace`, `stage` and `attributes` | string | `-` | no |
| elasticache_subnet_group_name | Subnet group name for the ElastiCache instance | string | `` | no |
| enabled | Set to false to prevent the module from creating any resources | bool | `true` | no |
| engine_version | Redis engine version | string | `4.0.10` | no |
| existing_security_groups | List of existing Security Group IDs to place the cluster into. Set `use_existing_security_groups` to `true` to enable using `existing_security_groups` as Security Groups for the cluster | list(string) | `<list>` | no |
| family | Redis family | string | `redis4.0` | no |
| instance_type | Elastic cache instance type | string | `cache.t2.micro` | no |
| maintenance_window | Maintenance window | string | `wed:03:00-wed:04:00` | no |
Expand All @@ -26,21 +32,22 @@
| parameter | A list of Redis parameters to apply. Note that parameters may differ from one Redis family to another | object | `<list>` | no |
| port | Redis port | number | `6379` | no |
| replication_group_id | Replication group ID with the following constraints: A name must contain from 1 to 20 alphanumeric characters or hyphens. The first character must be a letter. A name cannot end with a hyphen or contain two consecutive hyphens. | string | `` | no |
| security_groups | Security Group IDs | list(string) | `<list>` | no |
| snapshot_retention_limit | The number of days for which ElastiCache will retain automatic cache cluster snapshots before deleting them. | number | `0` | no |
| snapshot_window | The daily time range (in UTC) during which ElastiCache will begin taking a daily snapshot of your cache cluster. | string | `06:30-07:30` | no |
| stage | Stage (e.g. `prod`, `dev`, `staging`) | string | `` | no |
| subnets | Subnet IDs | list(string) | `<list>` | no |
| tags | Additional tags (_e.g._ map("BusinessUnit","ABC") | map(string) | `<map>` | no |
| transit_encryption_enabled | Enable TLS | bool | `true` | no |
| use_existing_security_groups | Flag to enable/disable creation of Security Group in the module. Set to `true` to disable Security Group creation and provide a list of existing security Group IDs in `existing_security_groups` to place the cluster into | bool | `false` | no |
| vpc_id | VPC ID | string | - | yes |
| zone_id | Route53 DNS Zone ID | string | `` | no |

## Outputs

| Name | Description |
|------|-------------|
| host | Redis host |
| endpoint | Redis primary endpoint |
| host | Redis hostname |
| id | Redis cluster ID |
| port | Redis port |
| security_group_id | Security group ID |
Expand Down
22 changes: 0 additions & 22 deletions examples/basic/main.tf

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
region = "us-west-1"
region = "us-east-2"

availability_zones = ["us-west-1b", "us-west-1c"]
availability_zones = ["us-east-2a", "us-east-2b"]

namespace = "eg"

Expand Down
8 changes: 4 additions & 4 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ provider "aws" {
}

module "vpc" {
source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.7.0"
source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.1"
namespace = var.namespace
stage = var.stage
name = var.name
cidr_block = "172.16.0.0/16"
}

module "subnets" {
source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.16.0"
source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.18.1"
availability_zones = var.availability_zones
namespace = var.namespace
stage = var.stage
Expand All @@ -31,12 +31,12 @@ module "redis" {
name = var.name
zone_id = var.zone_id
vpc_id = module.vpc.vpc_id
security_groups = [module.vpc.vpc_default_security_group_id]
allowed_security_groups = [module.vpc.vpc_default_security_group_id]
subnets = module.subnets.private_subnet_ids
cluster_size = var.cluster_size
instance_type = var.instance_type
apply_immediately = true
automatic_failover = false
automatic_failover_enabled = false
engine_version = var.engine_version
family = var.family
at_rest_encryption_enabled = var.at_rest_encryption_enabled
Expand Down
7 changes: 6 additions & 1 deletion examples/complete/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ output "cluster_security_group_id" {
description = "Cluster Security Group ID"
}

output "cluster_endpoint" {
value = module.redis.endpoint
description = "Redis primary endpoint"
}

output "cluster_host" {
value = module.redis.host
description = "Redis host"
description = "Redis hostname"
}
2 changes: 1 addition & 1 deletion examples/complete/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ variable "name" {

variable "cluster_size" {
type = number
description = "Count of nodes in cluster"
description = "Number of nodes in cluster"
}

variable "instance_type" {
Expand Down
62 changes: 44 additions & 18 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module "label" {
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.14.1"
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.16.0"
enabled = var.enabled
namespace = var.namespace
name = var.name
Expand All @@ -13,25 +13,43 @@ module "label" {
# Security Group Resources
#
resource "aws_security_group" "default" {
count = var.enabled ? 1 : 0
count = var.enabled && var.use_existing_security_groups == false ? 1 : 0
vpc_id = var.vpc_id
name = module.label.id
tags = module.label.tags
}

ingress {
from_port = var.port # Redis
to_port = var.port
protocol = "tcp"
security_groups = var.security_groups
}
resource "aws_security_group_rule" "egress" {
count = var.enabled && var.use_existing_security_groups == false ? 1 : 0
description = "Allow all egress traffic"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = join("", aws_security_group.default.*.id)
type = "egress"
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "ingress_security_groups" {
count = var.enabled && var.use_existing_security_groups == false ? length(var.allowed_security_groups) : 0
description = "Allow inbound traffic from existing Security Groups"
from_port = var.port
to_port = var.port
protocol = "tcp"
source_security_group_id = var.allowed_security_groups[count.index]
security_group_id = join("", aws_security_group.default.*.id)
type = "ingress"
}

tags = module.label.tags
resource "aws_security_group_rule" "ingress_cidr_blocks" {
count = var.enabled && var.use_existing_security_groups == false && length(var.allowed_cidr_blocks) > 0 ? 1 : 0
description = "Allow inbound traffic from CIDR blocks"
from_port = var.port
to_port = var.port
protocol = "tcp"
cidr_blocks = var.allowed_cidr_blocks
security_group_id = join("", aws_security_group.default.*.id)
type = "ingress"
}

locals {
Expand Down Expand Up @@ -61,17 +79,17 @@ resource "aws_elasticache_parameter_group" "default" {
resource "aws_elasticache_replication_group" "default" {
count = var.enabled ? 1 : 0

auth_token = var.auth_token
auth_token = var.transit_encryption_enabled ? var.auth_token : null
replication_group_id = var.replication_group_id == "" ? module.label.id : var.replication_group_id
replication_group_description = module.label.id
node_type = var.instance_type
number_cache_clusters = var.cluster_size
port = var.port
parameter_group_name = join("", aws_elasticache_parameter_group.default.*.name)
availability_zones = slice(var.availability_zones, 0, var.cluster_size)
automatic_failover_enabled = var.automatic_failover
automatic_failover_enabled = var.automatic_failover_enabled
subnet_group_name = local.elasticache_subnet_group_name
security_group_ids = [join("", aws_security_group.default.*.id)]
security_group_ids = var.use_existing_security_groups ? var.existing_security_groups : [join("", aws_security_group.default.*.id)]
maintenance_window = var.maintenance_window
notification_topic_arn = var.notification_topic_arn
engine_version = var.engine_version
Expand All @@ -81,6 +99,14 @@ resource "aws_elasticache_replication_group" "default" {
snapshot_retention_limit = var.snapshot_retention_limit

tags = module.label.tags

dynamic "cluster_mode" {
for_each = var.cluster_mode_enabled ? ["true"] : []
content {
replicas_per_node_group = var.cluster_mode_replicas_per_node_group
num_node_groups = var.cluster_mode_num_node_groups
}
}
}

#
Expand Down
15 changes: 7 additions & 8 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ output "port" {
description = "Redis port"
}

output "endpoint" {
value = join("", aws_elasticache_replication_group.default.*.primary_endpoint_address)
description = "Redis primary endpoint"
}

output "host" {
value = coalesce(
module.dns.hostname,
join(
"",
aws_elasticache_replication_group.default.*.primary_endpoint_address
)
)
description = "Redis host"
value = module.dns.hostname
description = "Redis hostname"
}
6 changes: 3 additions & 3 deletions test/src/examples_complete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestExamplesComplete(t *testing.T) {
TerraformDir: "../../examples/complete",
Upgrade: true,
// Variables to pass to our Terraform code using -var-file options
VarFiles: []string{"fixtures.us-west-1.tfvars"},
VarFiles: []string{"fixtures.us-east-2.tfvars"},
}

// At the end of the test, run `terraform destroy` to clean up any resources that were created
Expand All @@ -33,12 +33,12 @@ func TestExamplesComplete(t *testing.T) {
// Run `terraform output` to get the value of an output variable
privateSubnetCidrs := terraform.OutputList(t, terraformOptions, "private_subnet_cidrs")
// Verify we're getting back the outputs we expect
assert.Equal(t, []string{"172.16.0.0/18", "172.16.64.0/18"}, privateSubnetCidrs)
assert.Equal(t, []string{"172.16.0.0/19", "172.16.32.0/19"}, privateSubnetCidrs)

// Run `terraform output` to get the value of an output variable
publicSubnetCidrs := terraform.OutputList(t, terraformOptions, "public_subnet_cidrs")
// Verify we're getting back the outputs we expect
assert.Equal(t, []string{"172.16.128.0/18", "172.16.192.0/18"}, publicSubnetCidrs)
assert.Equal(t, []string{"172.16.96.0/19", "172.16.128.0/19"}, publicSubnetCidrs)

// Run `terraform output` to get the value of an output variable
clusterHost := terraform.Output(t, terraformOptions, "cluster_host")
Expand Down
Loading

0 comments on commit d27d632

Please sign in to comment.