DatadogのDashboardやMonitorをTerraform化する


初めに断っておくと、ほとんどGitHubのリンク貼るだけの記事です。日本語の記事があったほうが利用者増えるかも、ぐらいの気持ちで書いてます。

概要

DatadogのTimeboard、Screenboard、Monitorなどは便利ですが、手動でポチポチ作るとその後の管理も大変なのでやはりコード化しておきたくなります。そこでTerraformを調べるとDatadog用のProviderがある事が分かります。
https://www.terraform.io/docs/providers/datadog/index.html

ただ自分でTerraformで書くのも面倒だし現在のDatadogの設定からTerraform生成してくれる方が嬉しいよね、という内容です。

最初に結論を書いておくと、↓使ったら結構便利になりました。
https://github.com/amnk/dd2tf

詳細

Datadog用のProviderはあるものの、これを使うと解決!というわけでもなくて特にScreenboardは苦行です。

https://www.terraform.io/docs/providers/datadog/r/screenboard.html
上記を見てもらうと分かりますが、Widgetのところはxやyを指定するところがあり自分で座標を指定する必要があります。これの指定の仕方を最初理解するのがまず大変です。また、微調整するたびにx,yの値を変えて terraform apply とか想像するだけで苦行なことが分かるかと思います。Datadogの画面からならマウスで適当に配置するだけで出来上がるのにTerraform化しようとすると一気に大変になります。

そこでDatadogの設定からTerraformのHCL生成してくれるやつないかなと調べて見つけたのが dd2tf です。
https://github.com/amnk/dd2tf

使い方はREADMEにもありますが、以下のようにコマンドを打つとScreenboardのHCLを吐いてくれます。

$ DATADOG_API_KEY=xxx DATADOG_APP_KEY=xxx ./dd2tf screenboards --all

実装はとてもシンプルで、DatadogのAPIを叩くとScreenboardの詳細がJSONで返ってくるのでそれをテンプレートにひたすら埋め込んでいってます。
https://github.com/amnk/dd2tf/blob/master/tmpl/screenboard.tmpl

正直かなり力技感があり、GoのStructからHCLにMarshalするやつとかあるんじゃないのかな...という気もしますが、そこは気にせず使わせてもらっています。x,yなどの座標もAPIが返してくるので自分で値を意識する必要はないです。これのおかげでScreenboardとかの管理はかなり楽になりました。

とは言ったものの当初はテンプレート結構バグってて動かなかったので色々直したりしました。
https://github.com/amnk/dd2tf/pull/13

DashboardだけでなくMonitorでも使えるので便利です。ただ自分の利用範囲のバグしか直してないので、他にも直すべき箇所あるかもしれません。その場合は直していきましょう。

注意

もしかしたらScreenboardのdump時などにエラーが出るかもしれません。

FATA[0001] json: cannot unmarshal string into Go struct field Screenboard.width of type int

これはwidthがintで定義されてるのにstringになってるぞ、ということですが何でこんな事が起きるのかなとDatadogのAPIを叩いてみました。

$ curl -G "https://app.datadoghq.com/api/v1/screen/XXXXXX" -d "api_key=$DATADOG_API_KEY" -d "application_key=$DATADOG_APP_KEY" | jq . | grep width
 "width": "100%",

確かにstringになっています。別のScreenboardを叩いてみます。

$ curl -G "https://app.datadoghq.com/api/v1/screen/YYYYYY" -d "api_key=$DATADOG_API_KEY" -d "application_key=$DATADOG_APP_KEY" | jq . | grep width
  "width": 424,

intになっています。どうやらDatadogのAPIがintだったりstringだったりを返してくることがあるらしく、使っているDatadogクライアントの go-datadog-api がwidthをintで定義しているのでエラーになっているようです。他にもそういう箇所は多いらしくjson.Numberで回避していたりします。
https://github.com/zorkian/go-datadog-api/blob/1df5bda80d16ccfa8e99c543dbeb731665acbfca/dashboards.go#L45-L47

dd-agentとかもGoなのにDatadogさんは何でこんな設計にしちゃったんだろう...という気持ちなのですが、文句を言ってもしょうがないのでgo-datadog-api側に修正投げました。
https://github.com/zorkian/go-datadog-api/pull/218

破壊的変更になっちゃいますし、開発がそこまで活発ではないので修正が取り込まれるかは分かりませんが、現時点で回避したい場合はScreenboard全体のサイズをいじると良いです。自分の実験した感じでは新規作成されたままの状態だと100%になっちゃいます。ですが、一度サイズを変えるとintになりました。ただたまにstringに戻ったりしてよく分からないです。完全にWorkaroundという感じです。

全然関係ないですが、DatadogのAPI叩いてたらcamel caseとsnake caseが両方返されていたりして、厳しい戦いの幕開けを感じさせました。

"title_text": "",
"titleText": "title",

まとめ

DatadogはGUIでポチポチ作ってTerraform化すれば結構捗る