Day-to-day the memorandum

やったことのメモ書きです。

TerraformでCloudWatch Dashboardを作る

TerraformでCloudWatch Dashboardを作る機会があったので、それのメモです。

Terraformのバージョン

terraform {
  required_version = "= 0.12.29"

  required_providers [
    aws = "= 2.70.0"
  ]
}

バージョン低すぎるのは許して...

Terraform Resource

ドキュメントを見るとwidgetsの設定をJSONで渡してあげるようです。
https://registry.terraform.io/providers/hashicorp/aws/2.70.0/docs/resources/cloudwatch_dashboard

ですが、共通項目などがあったりするのでまとめたくなりました。

そこでtemplate_fileを使ってよしなにやってみようと思います。
https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file

ソースコード

  • main.tf
locals {
  dashboard_name = "sample"

  dashboard_widgets = [
    {
      metrics: [ "AWS/ECS", "CPUUtilization", "ServiceName", "sample", "ClusterName", "sample" ]
      title: "cpu utilization"
      stat: "Average"
    },
    {
      metrics: [ "AWS/ECS", "MemoryUtilization", "ServiceName", "sample", "ClusterName", "sample" ]
      title: "memory utilization"
      stat: "Sum"
    },
    {
      metrics: [ "AWS/RDS", "CPUUtilization", "DBInstanceIdentifier", "dbinstance" ]
      title: "db cpu utilization"
      stat: "Average"
    },
    {
      metrics: [ "AWS/RDS", "DatabaseConnections", "DBInstanceIdentifier", "dbinstance" ]
      title: "db connection"
      stat: "Sum"
    },
  ]
}

data "template_file" "dashboard" {
  template = file(./templates/dashboard.tpl")

  vars = {
    widgets = jsonencode(local.dashboard_widgets)
  }
}

resource "aws_cloudwatch_dashboard" "main" {
  dashboard_name = local.dashboard_name

  dashboard_body = data.template_file.dashboard.rendered
}
{
  "widgets": ${jsonencode([
    for index, widget in jsondecode(widgets) : {
      type = "metric"
      x =  index % 4 * 6
      y =  floor(index / 4) * 6
      width = 6
      height = 6
      properties = {
        metrics = [
          widget.metrics
        ]
        view = "timeSeries"
        stacked = false
        region = "ap-northeast-1"
        title = widget.title
        period = 60
        stat = widget.stat
      }
    }
  ])}
}

本来ならModule化してVariableで渡すと思うのですが、ここではlocalsで定義してます。

template_fileに変数を渡すときは、型がstringのみなのでjsonencodeJSON文字列に変えてテンプレートファイルに渡しています。

stringにしてしまうと変数として扱えないので、テンプレートファイルの中でjsondecodeで戻しています。

そして、JSONの配列の最後だけは,がいらないので、それに対応するためにまたjsonencodeをつかって、配列の最後だったら,がつかないようにしています。

最後に

jsonencode -> jsondecode -> jsonencodeしているので、なんだかスマートじゃないように見えますが、ほかにいい方法があったら教えてください。