Merge pull request #2469 from hashicorp/f-aws-update-elasticache
provider/aws: Allow in-place updates for ElastiCache cluster
This commit is contained in:
commit
d072e8eb50
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||||
"github.com/aws/aws-sdk-go/service/elasticache"
|
"github.com/aws/aws-sdk-go/service/elasticache"
|
||||||
"github.com/aws/aws-sdk-go/service/iam"
|
"github.com/aws/aws-sdk-go/service/iam"
|
||||||
"github.com/hashicorp/terraform/helper/hashcode"
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
|
@ -32,7 +33,6 @@ func resourceAwsElasticacheCluster() *schema.Resource {
|
||||||
"engine": &schema.Schema{
|
"engine": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
|
||||||
},
|
},
|
||||||
"node_type": &schema.Schema{
|
"node_type": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
|
@ -42,13 +42,11 @@ func resourceAwsElasticacheCluster() *schema.Resource {
|
||||||
"num_cache_nodes": &schema.Schema{
|
"num_cache_nodes": &schema.Schema{
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
|
||||||
},
|
},
|
||||||
"parameter_group_name": &schema.Schema{
|
"parameter_group_name": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
ForceNew: true,
|
|
||||||
},
|
},
|
||||||
"port": &schema.Schema{
|
"port": &schema.Schema{
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
|
@ -59,7 +57,6 @@ func resourceAwsElasticacheCluster() *schema.Resource {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
ForceNew: true,
|
|
||||||
},
|
},
|
||||||
"subnet_group_name": &schema.Schema{
|
"subnet_group_name": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
|
@ -81,7 +78,6 @@ func resourceAwsElasticacheCluster() *schema.Resource {
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
ForceNew: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
Set: func(v interface{}) int {
|
Set: func(v interface{}) int {
|
||||||
return hashcode.String(v.(string))
|
return hashcode.String(v.(string))
|
||||||
|
@ -110,6 +106,15 @@ func resourceAwsElasticacheCluster() *schema.Resource {
|
||||||
},
|
},
|
||||||
|
|
||||||
"tags": tagsSchema(),
|
"tags": tagsSchema(),
|
||||||
|
|
||||||
|
// apply_immediately is used to determine when the update modifications
|
||||||
|
// take place.
|
||||||
|
// See http://docs.aws.amazon.com/AmazonElastiCache/latest/APIReference/API_ModifyCacheCluster.html
|
||||||
|
"apply_immediately": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,7 +163,7 @@ func resourceAwsElasticacheClusterCreate(d *schema.ResourceData, meta interface{
|
||||||
stateConf := &resource.StateChangeConf{
|
stateConf := &resource.StateChangeConf{
|
||||||
Pending: pending,
|
Pending: pending,
|
||||||
Target: "available",
|
Target: "available",
|
||||||
Refresh: CacheClusterStateRefreshFunc(conn, d.Id(), "available", pending),
|
Refresh: cacheClusterStateRefreshFunc(conn, d.Id(), "available", pending),
|
||||||
Timeout: 10 * time.Minute,
|
Timeout: 10 * time.Minute,
|
||||||
Delay: 10 * time.Second,
|
Delay: 10 * time.Second,
|
||||||
MinTimeout: 3 * time.Second,
|
MinTimeout: 3 * time.Second,
|
||||||
|
@ -240,6 +245,59 @@ func resourceAwsElasticacheClusterUpdate(d *schema.ResourceData, meta interface{
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req := &elasticache.ModifyCacheClusterInput{
|
||||||
|
CacheClusterID: aws.String(d.Id()),
|
||||||
|
ApplyImmediately: aws.Boolean(d.Get("apply_immediately").(bool)),
|
||||||
|
}
|
||||||
|
|
||||||
|
requestUpdate := false
|
||||||
|
if d.HasChange("security_group_ids") {
|
||||||
|
if attr := d.Get("security_group_ids").(*schema.Set); attr.Len() > 0 {
|
||||||
|
req.SecurityGroupIDs = expandStringList(attr.List())
|
||||||
|
requestUpdate = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("parameter_group_name") {
|
||||||
|
req.CacheParameterGroupName = aws.String(d.Get("parameter_group_name").(string))
|
||||||
|
requestUpdate = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("engine_version") {
|
||||||
|
req.EngineVersion = aws.String(d.Get("engine_version").(string))
|
||||||
|
requestUpdate = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("num_cache_nodes") {
|
||||||
|
req.NumCacheNodes = aws.Long(int64(d.Get("num_cache_nodes").(int)))
|
||||||
|
requestUpdate = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestUpdate {
|
||||||
|
log.Printf("[DEBUG] Modifying ElastiCache Cluster (%s), opts:\n%s", d.Id(), awsutil.StringValue(req))
|
||||||
|
_, err := conn.ModifyCacheCluster(req)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("[WARN] Error updating ElastiCache cluster (%s), error: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Waiting for update: %s", d.Id())
|
||||||
|
pending := []string{"modifying", "rebooting cache cluster nodes", "snapshotting"}
|
||||||
|
stateConf := &resource.StateChangeConf{
|
||||||
|
Pending: pending,
|
||||||
|
Target: "available",
|
||||||
|
Refresh: cacheClusterStateRefreshFunc(conn, d.Id(), "available", pending),
|
||||||
|
Timeout: 5 * time.Minute,
|
||||||
|
Delay: 5 * time.Second,
|
||||||
|
MinTimeout: 3 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, sterr := stateConf.WaitForState()
|
||||||
|
if sterr != nil {
|
||||||
|
return fmt.Errorf("Error waiting for elasticache (%s) to update: %s", d.Id(), sterr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return resourceAwsElasticacheClusterRead(d, meta)
|
return resourceAwsElasticacheClusterRead(d, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +310,7 @@ func setCacheNodeData(d *schema.ResourceData, c *elasticache.CacheCluster) error
|
||||||
|
|
||||||
for _, node := range sortedCacheNodes {
|
for _, node := range sortedCacheNodes {
|
||||||
if node.CacheNodeID == nil || node.Endpoint == nil || node.Endpoint.Address == nil || node.Endpoint.Port == nil {
|
if node.CacheNodeID == nil || node.Endpoint == nil || node.Endpoint.Address == nil || node.Endpoint.Port == nil {
|
||||||
return fmt.Errorf("Unexpected nil pointer in: %#v", node)
|
return fmt.Errorf("Unexpected nil pointer in: %s", awsutil.StringValue(node))
|
||||||
}
|
}
|
||||||
cacheNodeData = append(cacheNodeData, map[string]interface{}{
|
cacheNodeData = append(cacheNodeData, map[string]interface{}{
|
||||||
"id": *node.CacheNodeID,
|
"id": *node.CacheNodeID,
|
||||||
|
@ -288,7 +346,7 @@ func resourceAwsElasticacheClusterDelete(d *schema.ResourceData, meta interface{
|
||||||
stateConf := &resource.StateChangeConf{
|
stateConf := &resource.StateChangeConf{
|
||||||
Pending: []string{"creating", "available", "deleting", "incompatible-parameters", "incompatible-network", "restore-failed"},
|
Pending: []string{"creating", "available", "deleting", "incompatible-parameters", "incompatible-network", "restore-failed"},
|
||||||
Target: "",
|
Target: "",
|
||||||
Refresh: CacheClusterStateRefreshFunc(conn, d.Id(), "", []string{}),
|
Refresh: cacheClusterStateRefreshFunc(conn, d.Id(), "", []string{}),
|
||||||
Timeout: 10 * time.Minute,
|
Timeout: 10 * time.Minute,
|
||||||
Delay: 10 * time.Second,
|
Delay: 10 * time.Second,
|
||||||
MinTimeout: 3 * time.Second,
|
MinTimeout: 3 * time.Second,
|
||||||
|
@ -304,7 +362,7 @@ func resourceAwsElasticacheClusterDelete(d *schema.ResourceData, meta interface{
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CacheClusterStateRefreshFunc(conn *elasticache.ElastiCache, clusterID, givenState string, pending []string) resource.StateRefreshFunc {
|
func cacheClusterStateRefreshFunc(conn *elasticache.ElastiCache, clusterID, givenState string, pending []string) resource.StateRefreshFunc {
|
||||||
return func() (interface{}, string, error) {
|
return func() (interface{}, string, error) {
|
||||||
resp, err := conn.DescribeCacheClusters(&elasticache.DescribeCacheClustersInput{
|
resp, err := conn.DescribeCacheClusters(&elasticache.DescribeCacheClustersInput{
|
||||||
CacheClusterID: aws.String(clusterID),
|
CacheClusterID: aws.String(clusterID),
|
||||||
|
|
|
@ -60,6 +60,11 @@ names to associate with this cache cluster
|
||||||
* `security_group_ids` – (Optional, VPC only) One or more VPC security groups associated
|
* `security_group_ids` – (Optional, VPC only) One or more VPC security groups associated
|
||||||
with the cache cluster
|
with the cache cluster
|
||||||
|
|
||||||
|
* `apply_immediately` - (Optional) Specifies whether any database modifications
|
||||||
|
are applied immediately, or during the next maintenance window. Default is
|
||||||
|
`false`. See [Amazon ElastiCache Documentation for more information.][1]
|
||||||
|
(Available since v0.6.0)
|
||||||
|
|
||||||
* `tags` - (Optional) A mapping of tags to assign to the resource.
|
* `tags` - (Optional) A mapping of tags to assign to the resource.
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,3 +74,5 @@ The following attributes are exported:
|
||||||
|
|
||||||
* `cache_nodes` - List of node objects including `id`, `address` and `port`.
|
* `cache_nodes` - List of node objects including `id`, `address` and `port`.
|
||||||
Referenceable e.g. as `${aws_elasticache_cluster.bar.cache_nodes.0.address}`
|
Referenceable e.g. as `${aws_elasticache_cluster.bar.cache_nodes.0.address}`
|
||||||
|
|
||||||
|
[1]: http://docs.aws.amazon.com/AmazonElastiCache/latest/APIReference/API_ModifyCacheCluster.html
|
||||||
|
|
Loading…
Reference in New Issue