diff --git a/builtin/providers/aws/resource_aws_elasticache_replication_group.go b/builtin/providers/aws/resource_aws_elasticache_replication_group.go index dcd6f0caa..ffce71ad6 100644 --- a/builtin/providers/aws/resource_aws_elasticache_replication_group.go +++ b/builtin/providers/aws/resource_aws_elasticache_replication_group.go @@ -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) diff --git a/builtin/providers/aws/resource_aws_elasticache_replication_group_test.go b/builtin/providers/aws/resource_aws_elasticache_replication_group_test.go index 60efb05a3..2cf352946 100644 --- a/builtin/providers/aws/resource_aws_elasticache_replication_group_test.go +++ b/builtin/providers/aws/resource_aws_elasticache_replication_group_test.go @@ -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)) diff --git a/website/source/docs/providers/aws/r/elasticache_replication_group.html.markdown b/website/source/docs/providers/aws/r/elasticache_replication_group.html.markdown index a14d4e855..7b908daf9 100644 --- a/website/source/docs/providers/aws/r/elasticache_replication_group.html.markdown +++ b/website/source/docs/providers/aws/r/elasticache_replication_group.html.markdown @@ -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