hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.74k stars 9.09k forks source link

[Enhancement]: expose member_clusters in aws_elasticache_replication_group compatible with for_each #36342

Closed rohitjha941 closed 6 months ago

rohitjha941 commented 6 months ago

Description

I want to create cloud watch alarms on all of the member clusters of elastic cache. I am getting the following error.

╷
│ Error: Invalid for_each argument
│ 
│   on modules/redis/alerts.tf line 3, in resource "aws_cloudwatch_metric_alarm" "cache_memory":
│    3:   for_each = toset(tolist(flatten(aws_elasticache_replication_group.this.member_clusters)))
│     ├────────────────
│     │ aws_elasticache_replication_group.this.member_clusters is a set of string, known only after apply
│ 
│ The "for_each" set includes values derived from resource attributes that
│ cannot be determined until apply, and so Terraform cannot determine the
│ full set of keys that will identify the instances of this resource.
│ 
│ When working with unknown values in for_each, it's better to use a map
│ value where the keys are defined statically in your configuration and where
│ only the values contain apply-time results.
│ 
│ Alternatively, you could use the -target planning option to first apply
│ only the resources that the for_each value depends on, and then apply a
│ second time to fully converge.

I asked the same question in Hashicorp Forum. I got the following response

Hi @rohit.jha,

The API and AWS provider don’t seem to offer anything suitable for use in for_each to identify these objects, since the only data available is something that will be decided during the apply step.

Therefore in this particular case you will need to do what the error message describes in its last paragraph:

terraform apply -target=module.redis.aws_elasticache_replication_group. This first, to get the replication group created. Then terraform apply without extra arguments, to finish creating everything else including the cloudwatch alarms. Once the replication group exists you won’t need to use -target again unless the set of clusters associated with this replication group changes, because the set of clusters will be known.

I feel like using Target is not a good option. Ideally, I would like to have a module which would create Cache and Alarms at the same time. I would like aws providers to expose member_clusters in aws_elasticache_replication_group compatible with for_each so that we can CloudWatch alarms

Affected Resource(s) and/or Data Source(s)

aws_elasticache_replication_group

Potential Terraform Configuration

resource "aws_elasticache_replication_group" "this" {
  replication_group_id = var.replication_group_id
  description          = var.description

  port                 = var.port
  node_type            = var.node_type
  parameter_group_name = var.parameter_group_name

  security_group_ids = var.security_group_ids
  subnet_group_name  = var.subnet_group_name

  at_rest_encryption_enabled = true
  automatic_failover_enabled = true
  multi_az_enabled           = true

  num_node_groups         = var.num_node_groups
  replicas_per_node_group = var.replicas_per_node_group
}

resource "aws_cloudwatch_metric_alarm" "cache_memory" {

    for_each = toset(tolist(flatten(aws_elasticache_replication_group.this.member_clusters)))

  alarm_name          = "${each.key}-freeable-memory"
  alarm_description   = "Elasticache ${each.key} average freeable memory is less than ${var.alarm_memory_threshold_bytes} bytes"
  comparison_operator = "LessThanThreshold"
  evaluation_periods  = 1
  metric_name         = "FreeableMemory"
  namespace           = "AWS/ElastiCache"
  period              = 600
  statistic           = "Average"
  threshold           = var.alarm_memory_threshold_bytes
  alarm_actions       = var.alarm_actions

  dimensions = {
    CacheClusterId = each.key
  }
}

References

Terraform Discussion

Would you like to implement a fix?

None

github-actions[bot] commented 6 months ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

justinretzolk commented 6 months ago

Hey @rohitjha941 👋 Thank you for taking the time to raise this! As apparentlymart mentioned in the Discuss forum post, this is a situation where the API doesn't currently offer a way to determine what the value of member_clusters will be during plan time, so it's not currently possible for the AWS provider to be altered in the way that you're looking for.

If a targeted apply won't work in your case, the other option would be to break the configuration up so that one configuration is applied after the other, once the member_clusters value is know.

Since this isn't something we can currently action, I'll close this issue. If there is a change in behavior on the API side at a later time, we'd be happy to take another look.

github-actions[bot] commented 5 months ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.