Search code examples
amazon-web-servicestemplatesterraformamazon-cloudwatchdashboard

Terraform for loop


I've been learning terraform, and have been playing with dashboards.

I have the following file which generates a dashboard.

resource "aws_cloudwatch_dashboard" "main" {
  dashboard_name = "sample_dashboard"
  dashboard_body = <<EOF
{
  "widgets": [
    ${templatefile("${path.module}/cpu.tmpl", { ids = aws_instance.web[*].id })},
    ${templatefile("${path.module}/network.tmpl", { ids = aws_instance.web[*].id })}
  ]
}
EOF
}

Here is the cpu template file.

{
  "type": "metric",
  "x": 0,
  "y": 0,
  "width": 12,
  "height": 6,
  "properties": {
    "metrics": ${jsonencode([for id in ids : ["AWS/EC2","CPUUtilization","InstanceId", "${id}"]])},
    "period": 300,
    "stat": "Average",
    "region": "us-east-1",
    "title": "EC2 Instance CPU"
  }
}

Here have the network template file.

{
  "type": "metric",
  "x": 12,
  "y": 0,
  "width": 12,
  "height": 6,
  "properties": {
    "metrics": ${jsonencode([for id in ids :
                  ["AWS/EC2", "NetworkIn", "InstanceId", "${id}"]
                ])},
    "period": 300,
    "stat": "Average",
    "region": "us-east-1",
    "title": "EC2 Instance Network"
  }
}

Everything works as expected, and I get the following dashboard. dashboards

The problem I'm having is when trying to add another metric in the for loop I get an error.

{
  "type": "metric",
  "x": 12,
  "y": 0,
  "width": 12,
  "height": 6,
  "properties": {
    "metrics": ${jsonencode([for id in ids :
                  ["AWS/EC2", "NetworkIn", "InstanceId", "${id}"],
                  ["AWS/EC2", "NetworkOut", "InstanceId", "${id}"]
                ])},
    "period": 300,
    "stat": "Average",
    "region": "us-east-1",
    "title": "EC2 Instance Network"
  }
}

I get the following error.

Call to function "templatefile" failed: ./network.tmpl:9,70-71: Invalid 'for' expression; Extra characters after the end of the 'for' expression..

As always thanks in advance for you help.


Solution

  • One way to overcome the issue would be to concat your metrics:

    {
      "type": "metric",
      "x": 12,
      "y": 0,
      "width": 12,
      "height": 6,
      "properties": {
        "metrics": ${jsonencode(concat([for id in ids :
                       ["AWS/EC2", "NetworkIn", "InstanceId", "${id}"]
                    ], [for id in ids :                  
                       ["AWS/EC2", "NetworkOut", "InstanceId", "${id}"]
                    ]))},
        "period": 300,
        "stat": "Average",
        "region": "us-east-1",
        "title": "EC2 Instance Network"
      }
    }