How to iterate over all resources of same type?

Hi,

I have declared some AWS EC2 instances with terraform

resource aws_instance "server1" {
    # ...
}

resource aws_instance "server2" {
    # ...
}

resource aws_instance "server3" {
    # ...
}

Now, I want to declare some monitoring rules. But since I’m kind of lazy, I don’t want to manually declare the rules for each servers. I have found the for_each keyword, but I’m not sure how to use it.

resource "aws_cloudwatch_metric_alarm" "alarm_cpu" {
  for_each = aws_instance  # <= obviously, doesn’t work

  alarm_name = "High CPU"
  namespace = "AWS/EC2"
  metric_name = "CPUUtilization"
  dimensions = {
    InstanceId = each.key.id
  }
  period = "60"
  evaluation_periods = "3"
  datapoints_to_alarm = "3"
  statistic = "Average"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  threshold = "95"
  alarm_actions = [
    aws_sns_topic.alarms.arn]
  ok_actions = [
    aws_sns_topic.alarms.arn]
}

The for_each loop likes to know the values you intend to iterate over ahead of time, so you may be better off using count here. That said, it doesn’t massively alter what you’re trying to do.

In your case, I would consider making a middle man with a local variables block so you can easily adjust.

locals {
  instance_ids = [
    aws_instance.server1.id, 
    aws_instance.server2.id,
    aws_instance.server3.id,
  ]
}

Now you can go:

resource "aws_cloudwatch_metric_alarm" "alarm_cpu" {
  count = length(local.instance_ids)

  alarm_name = "High CPU"
  namespace = "AWS/EC2"
  metric_name = "CPUUtilization"
  dimensions = {
    InstanceId = local.instance_ids.count_index
  }
  period = "60"
  evaluation_periods = "3"
  datapoints_to_alarm = "3"
  statistic = "Average"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  threshold = "95"
  alarm_actions = [
    aws_sns_topic.alarms.arn]
  ok_actions = [
    aws_sns_topic.alarms.arn]
}

Hope that helps!

It helps. Thank you for your response!