Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/elasticache_replication_group: add tags to state #12974

Merged
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 96 additions & 54 deletions aws/resource_aws_elasticache_replication_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
Expand Down Expand Up @@ -125,8 +126,9 @@ func resourceAwsElasticacheReplicationGroup() *schema.Resource {
Computed: true,
},
"notification_topic_arn": {
Type: schema.TypeString,
Optional: true,
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateArn,
},
"number_cache_clusters": {
Type: schema.TypeInt,
Expand Down Expand Up @@ -198,8 +200,11 @@ func resourceAwsElasticacheReplicationGroup() *schema.Resource {
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validateArn,
},
Set: schema.HashString,
},
"snapshot_retention_limit": {
Type: schema.TypeInt,
Expand Down Expand Up @@ -271,10 +276,8 @@ func resourceAwsElasticacheReplicationGroupCreate(d *schema.ResourceData, meta i
params.EngineVersion = aws.String(v.(string))
}

preferred_azs := d.Get("availability_zones").(*schema.Set).List()
if len(preferred_azs) > 0 {
azs := expandStringList(preferred_azs)
params.PreferredCacheClusterAZs = azs
if preferredAzs := d.Get("availability_zones").(*schema.Set); preferredAzs.Len() > 0 {
params.PreferredCacheClusterAZs = expandStringSet(preferredAzs)
}

if v, ok := d.GetOk("parameter_group_name"); ok {
Expand All @@ -289,19 +292,16 @@ func resourceAwsElasticacheReplicationGroupCreate(d *schema.ResourceData, meta i
params.CacheSubnetGroupName = aws.String(v.(string))
}

security_group_names := d.Get("security_group_names").(*schema.Set).List()
if len(security_group_names) > 0 {
params.CacheSecurityGroupNames = expandStringList(security_group_names)
if SGNames := d.Get("security_group_names").(*schema.Set); SGNames.Len() > 0 {
params.CacheSecurityGroupNames = expandStringSet(SGNames)
}

security_group_ids := d.Get("security_group_ids").(*schema.Set).List()
if len(security_group_ids) > 0 {
params.SecurityGroupIds = expandStringList(security_group_ids)
if SGIds := d.Get("security_group_ids").(*schema.Set); SGIds.Len() > 0 {
params.SecurityGroupIds = expandStringSet(SGIds)
}

snaps := d.Get("snapshot_arns").(*schema.Set).List()
if len(snaps) > 0 {
params.SnapshotArns = expandStringList(snaps)
if snaps := d.Get("snapshot_arns").(*schema.Set); snaps.Len() > 0 {
params.SnapshotArns = expandStringSet(snaps)
}

if v, ok := d.GetOk("maintenance_window"); ok {
Expand Down Expand Up @@ -366,7 +366,7 @@ func resourceAwsElasticacheReplicationGroupCreate(d *schema.ResourceData, meta i

resp, err := conn.CreateReplicationGroup(params)
if err != nil {
return fmt.Errorf("Error creating Elasticache Replication Group: %s", err)
return fmt.Errorf("Error creating Elasticache Replication Group: %w", err)
}

d.SetId(*resp.ReplicationGroup.ReplicationGroupId)
Expand All @@ -392,6 +392,8 @@ func resourceAwsElasticacheReplicationGroupCreate(d *schema.ResourceData, meta i

func resourceAwsElasticacheReplicationGroupRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).elasticacheconn
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

req := &elasticache.DescribeReplicationGroupsInput{
ReplicationGroupId: aws.String(d.Id()),
}
Expand All @@ -409,7 +411,7 @@ func resourceAwsElasticacheReplicationGroupRead(d *schema.ResourceData, meta int

var rgp *elasticache.ReplicationGroup
for _, r := range res.ReplicationGroups {
if *r.ReplicationGroupId == d.Id() {
if aws.StringValue(r.ReplicationGroupId) == d.Id() {
rgp = r
}
}
Expand All @@ -420,32 +422,32 @@ func resourceAwsElasticacheReplicationGroupRead(d *schema.ResourceData, meta int
return nil
}

if *rgp.Status == "deleting" {
if aws.StringValue(rgp.Status) == "deleting" {
log.Printf("[WARN] The Replication Group %q is currently in the `deleting` state", d.Id())
d.SetId("")
return nil
}

if rgp.AutomaticFailover != nil {
switch strings.ToLower(*rgp.AutomaticFailover) {
case "disabled", "disabling":
switch strings.ToLower(aws.StringValue(rgp.AutomaticFailover)) {
case elasticache.AutomaticFailoverStatusDisabled, elasticache.AutomaticFailoverStatusDisabling:
d.Set("automatic_failover_enabled", false)
case "enabled", "enabling":
case elasticache.AutomaticFailoverStatusEnabled, elasticache.AutomaticFailoverStatusEnabling:
d.Set("automatic_failover_enabled", true)
default:
log.Printf("Unknown AutomaticFailover state %s", *rgp.AutomaticFailover)
log.Printf("Unknown AutomaticFailover state %s", aws.StringValue(rgp.AutomaticFailover))
}
}

d.Set("kms_key_id", rgp.KmsKeyId)

d.Set("replication_group_description", rgp.Description)
d.Set("number_cache_clusters", len(rgp.MemberClusters))
if err := d.Set("member_clusters", flattenStringList(rgp.MemberClusters)); err != nil {
return fmt.Errorf("error setting member_clusters: %s", err)
if err := d.Set("member_clusters", flattenStringSet(rgp.MemberClusters)); err != nil {
return fmt.Errorf("error setting member_clusters: %w", err)
}
if err := d.Set("cluster_mode", flattenElasticacheNodeGroupsToClusterMode(aws.BoolValue(rgp.ClusterEnabled), rgp.NodeGroups)); err != nil {
return fmt.Errorf("error setting cluster_mode attribute: %s", err)
return fmt.Errorf("error setting cluster_mode attribute: %w", err)
}
d.Set("replication_group_id", rgp.ReplicationGroupId)

Expand Down Expand Up @@ -496,9 +498,27 @@ func resourceAwsElasticacheReplicationGroupRead(d *schema.ResourceData, meta int
d.Set("at_rest_encryption_enabled", c.AtRestEncryptionEnabled)
d.Set("transit_encryption_enabled", c.TransitEncryptionEnabled)

if c.AuthTokenEnabled != nil && !*c.AuthTokenEnabled {
if c.AuthTokenEnabled != nil && !aws.BoolValue(c.AuthTokenEnabled) {
d.Set("auth_token", nil)
}

arn := arn.ARN{
Partition: meta.(*AWSClient).partition,
Service: "elasticache",
Region: meta.(*AWSClient).region,
AccountID: meta.(*AWSClient).accountid,
Resource: fmt.Sprintf("cluster:%s", aws.StringValue(c.CacheClusterId)),
}.String()

tags, err := keyvaluetags.ElasticacheListTags(conn, arn)

if err != nil {
return fmt.Errorf("error listing tags for resource (%s): %w", arn, err)
}

if err := d.Set("tags", tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %w", err)
}
}

return nil
Expand Down Expand Up @@ -532,12 +552,12 @@ func resourceAwsElasticacheReplicationGroupUpdate(d *schema.ResourceData, meta i
log.Printf("[DEBUG] Modifying Elasticache Replication Group (%s) shard configuration: %s", d.Id(), input)
_, err := conn.ModifyReplicationGroupShardConfiguration(input)
if err != nil {
return fmt.Errorf("error modifying Elasticache Replication Group shard configuration: %s", err)
return fmt.Errorf("error modifying Elasticache Replication Group shard configuration: %w", err)
}

err = waitForModifyElasticacheReplicationGroup(conn, d.Id(), d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("error waiting for Elasticache Replication Group (%s) shard reconfiguration completion: %s", d.Id(), err)
return fmt.Errorf("error waiting for Elasticache Replication Group (%s) shard reconfiguration completion: %w", d.Id(), err)
}
}

Expand Down Expand Up @@ -566,15 +586,15 @@ func resourceAwsElasticacheReplicationGroupUpdate(d *schema.ResourceData, meta i
if err != nil {
// Future enhancement: we could retry creation with random ID on naming collision
// if isAWSErr(err, elasticache.ErrCodeCacheClusterAlreadyExistsFault, "") { ... }
return fmt.Errorf("error creating Elasticache Cache Cluster (adding replica): %s", err)
return fmt.Errorf("error creating Elasticache Cache Cluster (adding replica): %w", err)
}
}

// Wait for all Cache Cluster creations
for _, cacheClusterID := range addClusterIDs {
err := waitForCreateElasticacheCacheCluster(conn, cacheClusterID, d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("error waiting for Elasticache Cache Cluster (%s) to be created (adding replica): %s", cacheClusterID, err)
return fmt.Errorf("error waiting for Elasticache Cache Cluster (%s) to be created (adding replica): %w", cacheClusterID, err)
}
}
}
Expand All @@ -591,7 +611,7 @@ func resourceAwsElasticacheReplicationGroupUpdate(d *schema.ResourceData, meta i
// Future enhancement: we could retry deletion with random existing ID on missing name
// if isAWSErr(err, elasticache.ErrCodeCacheClusterNotFoundFault, "") { ... }
if !isAWSErr(err, elasticache.ErrCodeInvalidCacheClusterStateFault, "serving as primary") {
return fmt.Errorf("error deleting Elasticache Cache Cluster (%s) (removing replica): %s", cacheClusterID, err)
return fmt.Errorf("error deleting Elasticache Cache Cluster (%s) (removing replica): %w", cacheClusterID, err)
}

// Use Replication Group MemberClusters to find a new primary cache cluster ID
Expand All @@ -604,7 +624,7 @@ func resourceAwsElasticacheReplicationGroupUpdate(d *schema.ResourceData, meta i
log.Printf("[DEBUG] Reading Elasticache Replication Group: %s", describeReplicationGroupInput)
output, err := conn.DescribeReplicationGroups(describeReplicationGroupInput)
if err != nil {
return fmt.Errorf("error reading Elasticache Replication Group (%s) to determine new primary: %s", d.Id(), err)
return fmt.Errorf("error reading Elasticache Replication Group (%s) to determine new primary: %w", d.Id(), err)
}
if output == nil || len(output.ReplicationGroups) == 0 || len(output.ReplicationGroups[0].MemberClusters) == 0 {
return fmt.Errorf("error reading Elasticache Replication Group (%s) to determine new primary: missing replication group information", d.Id())
Expand Down Expand Up @@ -645,11 +665,11 @@ func resourceAwsElasticacheReplicationGroupUpdate(d *schema.ResourceData, meta i
log.Printf("[DEBUG] Modifying Elasticache Replication Group: %s", modifyReplicationGroupInput)
_, err = conn.ModifyReplicationGroup(modifyReplicationGroupInput)
if err != nil {
return fmt.Errorf("error modifying Elasticache Replication Group (%s) to set new primary: %s", d.Id(), err)
return fmt.Errorf("error modifying Elasticache Replication Group (%s) to set new primary: %sw", d.Id(), err)
}
err = waitForModifyElasticacheReplicationGroup(conn, d.Id(), d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("error waiting for Elasticache Replication Group (%s) to be available: %s", d.Id(), err)
return fmt.Errorf("error waiting for Elasticache Replication Group (%s) to be available: %w", d.Id(), err)
}
}

Expand All @@ -662,17 +682,17 @@ func resourceAwsElasticacheReplicationGroupUpdate(d *schema.ResourceData, meta i
log.Printf("[DEBUG] Modifying Elasticache Replication Group: %s", modifyReplicationGroupInput)
_, err = conn.ModifyReplicationGroup(modifyReplicationGroupInput)
if err != nil {
return fmt.Errorf("error modifying Elasticache Replication Group (%s) to set new primary: %s", d.Id(), err)
return fmt.Errorf("error modifying Elasticache Replication Group (%s) to set new primary: %w", d.Id(), err)
}
err = waitForModifyElasticacheReplicationGroup(conn, d.Id(), d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("error waiting for Elasticache Replication Group (%s) to be available: %s", d.Id(), err)
return fmt.Errorf("error waiting for Elasticache Replication Group (%s) to be available: %w", d.Id(), err)
}

// Finally retry deleting the cache cluster
err = deleteElasticacheCacheCluster(conn, cacheClusterID)
if err != nil {
return fmt.Errorf("error deleting Elasticache Cache Cluster (%s) (removing replica after setting new primary): %s", cacheClusterID, err)
return fmt.Errorf("error deleting Elasticache Cache Cluster (%s) (removing replica after setting new primary): %w", cacheClusterID, err)
}
}
}
Expand All @@ -681,7 +701,7 @@ func resourceAwsElasticacheReplicationGroupUpdate(d *schema.ResourceData, meta i
for _, cacheClusterID := range removeClusterIDs {
err := waitForDeleteElasticacheCacheCluster(conn, cacheClusterID, d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("error waiting for Elasticache Cache Cluster (%s) to be deleted (removing replica): %s", cacheClusterID, err)
return fmt.Errorf("error waiting for Elasticache Cache Cluster (%s) to be deleted (removing replica): %w", cacheClusterID, err)
}
}

Expand All @@ -695,7 +715,7 @@ func resourceAwsElasticacheReplicationGroupUpdate(d *schema.ResourceData, meta i
log.Printf("[DEBUG] Modifying Elasticache Replication Group: %s", input)
_, err := conn.ModifyReplicationGroup(input)
if err != nil {
return fmt.Errorf("error modifying Elasticache Replication Group (%s) to re-enable automatic failover: %s", d.Id(), err)
return fmt.Errorf("error modifying Elasticache Replication Group (%s) to re-enable automatic failover: %w", d.Id(), err)
}
}
}
Expand Down Expand Up @@ -724,14 +744,14 @@ func resourceAwsElasticacheReplicationGroupUpdate(d *schema.ResourceData, meta i

if d.HasChange("security_group_ids") {
if attr := d.Get("security_group_ids").(*schema.Set); attr.Len() > 0 {
params.SecurityGroupIds = expandStringList(attr.List())
params.SecurityGroupIds = expandStringSet(attr)
requestUpdate = true
}
}

if d.HasChange("security_group_names") {
if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 {
params.CacheSecurityGroupNames = expandStringList(attr.List())
params.CacheSecurityGroupNames = expandStringSet(attr)
requestUpdate = true
}
}
Expand Down Expand Up @@ -780,14 +800,35 @@ func resourceAwsElasticacheReplicationGroupUpdate(d *schema.ResourceData, meta i
if requestUpdate {
_, err := conn.ModifyReplicationGroup(params)
if err != nil {
return fmt.Errorf("error updating Elasticache Replication Group (%s): %s", d.Id(), err)
return fmt.Errorf("error updating Elasticache Replication Group (%s): %w", d.Id(), err)
}

err = waitForModifyElasticacheReplicationGroup(conn, d.Id(), d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("error waiting for Elasticache Replication Group (%s) to be updated: %s", d.Id(), err)
return fmt.Errorf("error waiting for Elasticache Replication Group (%s) to be updated: %w", d.Id(), err)
}
}

if d.HasChange("tags") {
clusters := d.Get("member_clusters").(*schema.Set).List()

for _, cluster := range clusters {

arn := arn.ARN{
Partition: meta.(*AWSClient).partition,
Service: "elasticache",
Region: meta.(*AWSClient).region,
AccountID: meta.(*AWSClient).accountid,
Resource: fmt.Sprintf("cluster:%s", cluster),
}.String()

o, n := d.GetChange("tags")
if err := keyvaluetags.ElasticacheUpdateTags(conn, arn, o, n); err != nil {
return fmt.Errorf("error updating tags: %w", err)
}
}
}

return resourceAwsElasticacheReplicationGroupRead(d, meta)
}

Expand All @@ -796,7 +837,7 @@ func resourceAwsElasticacheReplicationGroupDelete(d *schema.ResourceData, meta i

err := deleteElasticacheReplicationGroup(d.Id(), conn)
if err != nil {
return fmt.Errorf("error deleting Elasticache Replication Group (%s): %s", d.Id(), err)
return fmt.Errorf("error deleting Elasticache Replication Group (%s): %w", d.Id(), err)
}

return nil
Expand All @@ -823,8 +864,9 @@ func cacheReplicationGroupStateRefreshFunc(conn *elasticache.ElastiCache, replic

var rg *elasticache.ReplicationGroup
for _, replicationGroup := range resp.ReplicationGroups {
if *replicationGroup.ReplicationGroupId == replicationGroupId {
log.Printf("[DEBUG] Found matching ElastiCache Replication Group: %s", *replicationGroup.ReplicationGroupId)
rgId := aws.StringValue(replicationGroup.ReplicationGroupId)
if rgId == replicationGroupId {
log.Printf("[DEBUG] Found matching ElastiCache Replication Group: %s", rgId)
rg = replicationGroup
}
}
Expand All @@ -833,19 +875,19 @@ func cacheReplicationGroupStateRefreshFunc(conn *elasticache.ElastiCache, replic
return nil, "", fmt.Errorf("Error: no matching ElastiCache Replication Group for id (%s)", replicationGroupId)
}

log.Printf("[DEBUG] ElastiCache Replication Group (%s) status: %v", replicationGroupId, *rg.Status)
log.Printf("[DEBUG] ElastiCache Replication Group (%s) status: %v", replicationGroupId, aws.StringValue(rg.Status))

// return the current state if it's in the pending array
for _, p := range pending {
log.Printf("[DEBUG] ElastiCache: checking pending state (%s) for Replication Group (%s), Replication Group status: %s", pending, replicationGroupId, *rg.Status)
s := *rg.Status
log.Printf("[DEBUG] ElastiCache: checking pending state (%s) for Replication Group (%s), Replication Group status: %s", pending, replicationGroupId, aws.StringValue(rg.Status))
s := aws.StringValue(rg.Status)
if p == s {
log.Printf("[DEBUG] Return with status: %v", *rg.Status)
log.Printf("[DEBUG] Return with status: %v", aws.StringValue(rg.Status))
return s, p, nil
}
}

return rg, *rg.Status, nil
return rg, aws.StringValue(rg.Status), nil
}
}

Expand Down Expand Up @@ -879,7 +921,7 @@ func deleteElasticacheReplicationGroup(replicationGroupID string, conn *elastica
}

if err != nil {
return fmt.Errorf("error deleting Elasticache Replication Group: %s", err)
return fmt.Errorf("error deleting Elasticache Replication Group: %w", err)
}

log.Printf("[DEBUG] Waiting for deletion: %s", replicationGroupID)
Expand Down
Loading