diff --git a/builtin/providers/aws/resource_aws_elasticache_cluster.go b/builtin/providers/aws/resource_aws_elasticache_cluster.go index cffcdab2d..c7686f5f3 100644 --- a/builtin/providers/aws/resource_aws_elasticache_cluster.go +++ b/builtin/providers/aws/resource_aws_elasticache_cluster.go @@ -395,8 +395,18 @@ func resourceAwsElasticacheClusterUpdate(d *schema.ResourceData, meta interface{ } if d.HasChange("num_cache_nodes") { + oraw, nraw := d.GetChange("num_cache_nodes") + o := oraw.(int) + n := nraw.(int) + if n < o { + log.Printf("[INFO] Cluster %s is marked for Decreasing cache nodes from %d to %d", d.Id(), o, n) + nodesToRemove := getCacheNodesToRemove(d, o, o-n) + req.CacheNodeIdsToRemove = nodesToRemove + } + req.NumCacheNodes = aws.Int64(int64(d.Get("num_cache_nodes").(int))) requestUpdate = true + } if requestUpdate { @@ -426,6 +436,16 @@ func resourceAwsElasticacheClusterUpdate(d *schema.ResourceData, meta interface{ return resourceAwsElasticacheClusterRead(d, meta) } +func getCacheNodesToRemove(d *schema.ResourceData, oldNumberOfNodes int, cacheNodesToRemove int) []*string { + nodesIdsToRemove := []*string{} + for i := oldNumberOfNodes; i > oldNumberOfNodes-cacheNodesToRemove && i > 0; i-- { + s := fmt.Sprintf("%04d", i) + nodesIdsToRemove = append(nodesIdsToRemove, &s) + } + + return nodesIdsToRemove +} + func setCacheNodeData(d *schema.ResourceData, c *elasticache.CacheCluster) error { sortedCacheNodes := make([]*elasticache.CacheNode, len(c.CacheNodes)) copy(sortedCacheNodes, c.CacheNodes) diff --git a/builtin/providers/aws/resource_aws_elasticache_cluster_test.go b/builtin/providers/aws/resource_aws_elasticache_cluster_test.go index a17c5d9b1..88504e0f2 100644 --- a/builtin/providers/aws/resource_aws_elasticache_cluster_test.go +++ b/builtin/providers/aws/resource_aws_elasticache_cluster_test.go @@ -72,6 +72,41 @@ func TestAccAWSElasticacheCluster_snapshotsWithUpdates(t *testing.T) { }) } +func TestAccAWSElasticacheCluster_decreasingCacheNodes(t *testing.T) { + var ec elasticache.CacheCluster + + ri := genRandInt() + preConfig := fmt.Sprintf(testAccAWSElasticacheClusterConfigDecreasingNodes, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAWSElasticacheClusterConfigDecreasingNodes_update, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSElasticacheClusterDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSElasticacheSecurityGroupExists("aws_elasticache_security_group.bar"), + testAccCheckAWSElasticacheClusterExists("aws_elasticache_cluster.bar", &ec), + resource.TestCheckResourceAttr( + "aws_elasticache_cluster.bar", "num_cache_nodes", "3"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSElasticacheSecurityGroupExists("aws_elasticache_security_group.bar"), + testAccCheckAWSElasticacheClusterExists("aws_elasticache_cluster.bar", &ec), + resource.TestCheckResourceAttr( + "aws_elasticache_cluster.bar", "num_cache_nodes", "1"), + ), + }, + }, + }) +} + func TestAccAWSElasticacheCluster_vpc(t *testing.T) { var csg elasticache.CacheSubnetGroup var ec elasticache.CacheCluster @@ -260,6 +295,71 @@ resource "aws_elasticache_cluster" "bar" { } ` +var testAccAWSElasticacheClusterConfigDecreasingNodes = ` +provider "aws" { + region = "us-east-1" +} +resource "aws_security_group" "bar" { + name = "tf-test-security-group-%03d" + description = "tf-test-security-group-descr" + ingress { + from_port = -1 + to_port = -1 + protocol = "icmp" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_elasticache_security_group" "bar" { + name = "tf-test-security-group-%03d" + description = "tf-test-security-group-descr" + security_group_names = ["${aws_security_group.bar.name}"] +} + +resource "aws_elasticache_cluster" "bar" { + cluster_id = "tf-test-%03d" + engine = "memcached" + node_type = "cache.m1.small" + num_cache_nodes = 3 + port = 11211 + parameter_group_name = "default.memcached1.4" + security_group_names = ["${aws_elasticache_security_group.bar.name}"] +} +` + +var testAccAWSElasticacheClusterConfigDecreasingNodes_update = ` +provider "aws" { + region = "us-east-1" +} +resource "aws_security_group" "bar" { + name = "tf-test-security-group-%03d" + description = "tf-test-security-group-descr" + ingress { + from_port = -1 + to_port = -1 + protocol = "icmp" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_elasticache_security_group" "bar" { + name = "tf-test-security-group-%03d" + description = "tf-test-security-group-descr" + security_group_names = ["${aws_security_group.bar.name}"] +} + +resource "aws_elasticache_cluster" "bar" { + cluster_id = "tf-test-%03d" + engine = "memcached" + node_type = "cache.m1.small" + num_cache_nodes = 1 + port = 11211 + parameter_group_name = "default.memcached1.4" + security_group_names = ["${aws_elasticache_security_group.bar.name}"] + apply_immediately = true +} +` + var testAccAWSElasticacheClusterInVPCConfig = fmt.Sprintf(` resource "aws_vpc" "foo" { cidr_block = "192.168.0.0/16"