Feature request: Support for ElastiCache Redis cluster mode #9419

Added support for provisioning a native redis cluster elasticache replication group.
A new TypeSet attribute `cluster_mode` has been added. It requires the following
fields:

  - `replicas_per_node_group` - The number of replica nodes in each node group
  - `num_node_groups` - The number of node groups for this Redis replication group

Notes:

  - `automatic_failover_enabled` must be set to true.
  - `number_cache_clusters` is now a optional and computed field. If `cluster_mode` is set
    its value will be computed as:
 	  ```num_node_groups + num_node_groups * replicas_per_node_group```

Below is a sample config:

  resource "aws_elasticache_replication_group" "bar" {
      replication_group_id = "tf-redis-cluser"
      replication_group_description = "test description"
      node_type = "cache.t2.micro"
      port = 6379
      parameter_group_name = "default.redis3.2.cluster.on"
      automatic_failover_enabled = true
      cluster_mode {
          replicas_per_node_group = 1
          num_node_groups = 2
      }
  }
This commit is contained in:
Derrick Petzold 2016-10-25 16:21:35 -07:00 committed by Paul Stack
parent 8622925b34
commit 55a4ce2838
3 changed files with 161 additions and 3 deletions

View File

@ -44,7 +44,8 @@ func resourceAwsElasticacheReplicationGroup() *schema.Resource {
resourceSchema["number_cache_clusters"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
Computed: true,
Optional: true,
ForceNew: true,
}
@ -58,6 +59,26 @@ func resourceAwsElasticacheReplicationGroup() *schema.Resource {
Computed: true,
}
resourceSchema["cluster_mode"] = &schema.Schema{
Type: schema.TypeSet,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"replicas_per_node_group": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
},
"num_node_groups": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
},
},
},
}
resourceSchema["engine"].Required = false
resourceSchema["engine"].Optional = true
resourceSchema["engine"].Default = "redis"
@ -88,7 +109,6 @@ func resourceAwsElasticacheReplicationGroupCreate(d *schema.ResourceData, meta i
CacheNodeType: aws.String(d.Get("node_type").(string)),
Engine: aws.String(d.Get("engine").(string)),
Port: aws.Int64(int64(d.Get("port").(int))),
NumCacheClusters: aws.Int64(int64(d.Get("number_cache_clusters").(int))),
Tags: tags,
}
@ -145,6 +165,23 @@ func resourceAwsElasticacheReplicationGroupCreate(d *schema.ResourceData, meta i
params.SnapshotName = aws.String(v.(string))
}
if a, ok := d.GetOk("cluster_mode"); ok {
clusterModeAttributes := a.(*schema.Set).List()
attributes := clusterModeAttributes[0].(map[string]interface{})
if v, ok := attributes["num_node_groups"]; ok {
params.NumNodeGroups = aws.Int64(int64(v.(int)))
}
if v, ok := attributes["replicas_per_node_group"]; ok {
params.ReplicasPerNodeGroup = aws.Int64(int64(v.(int)))
}
} else if v, ok := d.GetOk("number_cache_clusters"); ok {
params.NumCacheClusters = aws.Int64(int64(v.(int)))
} else {
return fmt.Errorf("number_cache_clusters must be set if not using cluster_mode")
}
resp, err := conn.CreateReplicationGroup(params)
if err != nil {
return fmt.Errorf("Error creating Elasticache Replication Group: %s", err)

View File

@ -238,6 +238,36 @@ func TestAccAWSElasticacheReplicationGroup_redisClusterInVpc2(t *testing.T) {
})
}
func TestAccAWSElasticacheReplicationGroup_nativeRedisCluster(t *testing.T) {
var rg elasticache.ReplicationGroup
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSElasticacheReplicationDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSElasticacheReplicationGroupNativeRedisClusterConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticacheReplicationGroupExists("aws_elasticache_replication_group.bar", &rg),
resource.TestCheckResourceAttr(
"aws_elasticache_replication_group.bar", "number_cache_clusters", "4"),
resource.TestCheckResourceAttr(
"aws_elasticache_replication_group.bar", "cluster_mode.#", "1"),
resource.TestCheckResourceAttr(
"aws_elasticache_replication_group.bar", "cluster_mode.4170186206.num_node_groups", "2"),
resource.TestCheckResourceAttr(
"aws_elasticache_replication_group.bar", "cluster_mode.4170186206.replicas_per_node_group", "1"),
resource.TestCheckResourceAttr(
"aws_elasticache_replication_group.bar", "port", "6379"),
resource.TestCheckResourceAttrSet(
"aws_elasticache_replication_group.bar", "configuration_endpoint_address"),
),
},
},
})
}
func TestResourceAWSElastiCacheReplicationGroupIdValidation(t *testing.T) {
cases := []struct {
Value string
@ -723,3 +753,70 @@ resource "aws_elasticache_replication_group" "bar" {
maintenance_window = "thu:03:00-thu:04:00"
}
`, acctest.RandInt(), acctest.RandInt(), acctest.RandInt(), acctest.RandInt(), acctest.RandString(10))
var testAccAWSElasticacheReplicationGroupNativeRedisClusterConfig = fmt.Sprintf(`
provider "aws" {
region = "us-west-2"
}
resource "aws_vpc" "foo" {
cidr_block = "192.168.0.0/16"
tags {
Name = "tf-test"
}
}
resource "aws_subnet" "foo" {
vpc_id = "${aws_vpc.foo.id}"
cidr_block = "192.168.0.0/20"
availability_zone = "us-west-2a"
tags {
Name = "tf-test-%03d"
}
}
resource "aws_subnet" "bar" {
vpc_id = "${aws_vpc.foo.id}"
cidr_block = "192.168.16.0/20"
availability_zone = "us-west-2b"
tags {
Name = "tf-test-%03d"
}
}
resource "aws_elasticache_subnet_group" "bar" {
name = "tf-test-cache-subnet-%03d"
description = "tf-test-cache-subnet-group-descr"
subnet_ids = [
"${aws_subnet.foo.id}",
"${aws_subnet.bar.id}"
]
}
resource "aws_security_group" "bar" {
name = "tf-test-security-group-%03d"
description = "tf-test-security-group-descr"
vpc_id = "${aws_vpc.foo.id}"
ingress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_elasticache_replication_group" "bar" {
replication_group_id = "tf-%s"
replication_group_description = "test description"
node_type = "cache.t2.micro"
port = 6379
subnet_group_name = "${aws_elasticache_subnet_group.bar.name}"
security_group_ids = ["${aws_security_group.bar.id}"]
parameter_group_name = "default.redis3.2.cluster.on"
automatic_failover_enabled = true
cluster_mode {
replicas_per_node_group = 1
num_node_groups = 2
}
}
`, acctest.RandInt(), acctest.RandInt(), acctest.RandInt(), acctest.RandInt(), acctest.RandString(10))

View File

@ -12,6 +12,8 @@ Provides an ElastiCache Replication Group resource.
## Example Usage
### Redis Master with One Replica
```hcl
resource "aws_elasticache_replication_group" "bar" {
replication_group_id = "tf-rep-group-1"
@ -25,6 +27,23 @@ resource "aws_elasticache_replication_group" "bar" {
}
```
### Native Redis Cluser 2 Masters 2 Replicas
```hcl
resource "aws_elasticache_replication_group" "baz" {
replication_group_id = "tf-replication-group-1"
replication_group_description = "test description"
node_type = "cache.m1.small"
port = 6379
parameter_group_name = "default.redis3.2.cluster.on"
automatic_failover_enabled = true
cluster_mode {
replicas_per_node_group = 1
num_node_groups = 2
}
}
```
~> **Note:** We currently do not support passing a `primary_cluster_id` in order to create the Replication Group.
~> **Note:** Automatic Failover is unavailable for Redis versions earlier than 2.8.6,
@ -32,7 +51,6 @@ and unavailable on T1 and T2 node types. See the [Amazon Replication with
Redis](http://docs.aws.amazon.com/en_en/AmazonElastiCache/latest/UserGuide/Replication.html) guide
for full details on using Replication Groups.
## Argument Reference
The following arguments are supported:
@ -70,6 +88,12 @@ before being deleted. If the value of SnapshotRetentionLimit is set to zero (0),
Please note that setting a `snapshot_retention_limit` is not supported on cache.t1.micro or cache.t2.* cache nodes
* `apply_immediately` - (Optional) Specifies whether any modifications are applied immediately, or during the next maintenance window. Default is `false`.
* `tags` - (Optional) A mapping of tags to assign to the resource
* `cluster_mode` - (Optional) Create a native redis cluster. `automatic_failover_enabled` must be set to true. Cluster Mode documented below.
Cluster Mode (`cluster_mode`) supports the following:
* `replicas_per_node_group` - (Required) Specify the number of replica nodes in each node group. Valid values are 0 to 5. Changing this number will force a new resource.
* `num_node_groups - (Required) Specify the number of node groups (shards) for this Redis replication group. Changing this number will force a new resource.
## Attributes Reference