Datadogでuser tagをまとめて操作する

Datadogでホストをグループ単位で管理する場合、必ず使うのがタグです。Zabbixではテンプレートを種別ごとに用意して、テンプレートにホストグループを紐づける事で基本の監視(死活とかリソースとか)はすべてのホストグループに割り当てて、機能監視(WebとかDBとか)は個別のホストグループに…という設定でグループ化が出来ましたが、Datadogはテンプレートもホストグループもありません。これを最初に知った時にはちょっと驚いた覚えがあります。

必然的にタグでグループ分けするしかないですが、事前に設計で決まっているのであれば基本的にはdatadog.yamlにタグ情報を書いてあげるべきです。ただし実際の運用上では「設計上のグルーピングにはマッチしないけど、一時的にグループ情報を付与してまとめて操作したい…」というような状況はそれなりにあると思います(Webサーバの一部だけ監視を全Muteしたいとか)

そんな時に使えるのが"User Tags"の機能です。手っ取り早く言うとdatadog.yamlに書いたりDatadogで自動設定されたりするのが"Host Tags"で、後からGUIやAPIで追加できるのがUser Tags"になります。設定方法は違っても扱いは同じなので、monitorのクエリなどにも普通に書くことができます。付与対象が数台であればGUIから手動でポチポチやっても問題ないですが、数十台規模になるとちょっと辛いので[公式doc](https://docs.datadoghq.com/ja/api/latest/tags/)を元にAPI操作するスクリプトを作ってみました。

### 前提と注意点

* API KEYとAPP KEYは事前に準備して、スクリプトの変数に上書きする
* Datadogに通信可能な環境(インターネット経由)で実行する
* addやupdateは追加/更新結果が返却されますが、たまに空白で返ってくる時があります（一応sleepとか挟んでますがあまり効果ないような？）
* SaaS画面への反映はタイムタグがあります。API経由のgetであれば即反映されるので、確認する時はこっちで

#### ホストに設定されているタグ情報を取得する(get)

* ホスト名をスクリプトの引数として実行すると、そのホストに設定されているタグ情報を返します
* テキスト形式で返却されるので、別途jqとかをパイプしてあげると良いかも

```bash:gethosttags.sh
#!/bin/sh

# Path parameters
export DD_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export DD_APP_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
echo $1

# Curl command
curl -X GET "https://api.datadoghq.com/api/v1/tags/hosts/$1" \
-H "Content-Type: application/json" \
-H "DD-API-KEY: ${DD_API_KEY}" \
-H "DD-APPLICATION-KEY: ${DD_APP_KEY}"
```
#### ホストにタグを追加する(add)

* スクリプト内の"TAG_KEY"と"TAG_VALUE"に設定したいタグのKey:Valueを記入します
* 実行するディレクトリに別途"list.txt"を用意し、タグを付与したいホスト名を記述します
* スクリプトはlist.txtを読み込んで、対象ホストに対して順次タグ追加を行います
* 複数のタグを追加したい場合は、1個目が追加された後にスクリプト内タグを書き換えて再実行すれば、2個目が追加できます

```bash:addhosttags.sh
#!/bin/sh

# Path parameters
export DD_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export DD_APP_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export TAG_KEY="tag-key"
export TAG_VALUE="tag-value"
export TAG=$TAG_KEY":"$TAG_VALUE

# read list
cat list.txt | while read host_name
do
        echo -n '{"'$host_name'"}'

# curl command
curl -X POST "https://api.datadoghq.com/api/v1/tags/hosts/${host_name}" \
-H "Content-Type: application/json" \
-H "DD-API-KEY: ${DD_API_KEY}" \
-H "DD-APPLICATION-KEY: ${DD_APP_KEY}" \
-d @- << EOF
{
  "host": "'$host_name'",
  "tags": [
    "'$TAG'"
  ]
}
EOF
echo -e "\n";sleep 1s

done
```

#### ホストのタグを更新する(update)

* スクリプト内の"TAG_KEY"と"TAG_VALUE"に設定したいタグのKey:Valueを記入します
* 実行するディレクトリに別途"list.txt"を用意し、タグを付与したいホスト名を記述します
* スクリプトはlist.txtを読み込んで、対象ホストに対して順次タグ更新を行います
* "更新"なので対象ホストに複数タグがあった場合、 **keyが一致するものだけを更新してくれる？** のかと思ってましたが、単にPUTしたタグの内容で"すべて上書き"されます（具体的に言うとタグが2個あるホストに対して実行すると、更新した1個しか残りません、片方は消えます）
* そんな訳であまり使えない気がします…

```bash:updatehosttags.sh
#!/bin/sh

# Path parameters
export DD_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export DD_APP_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export TAG_KEY="tag-key"
export TAG_VALUE="tag-value"
export TAG=$TAG_KEY":"$TAG_VALUE

# read list
cat list.txt | while read host_name
do
        echo -n '{"'$host_name'"}'

# curl command
curl -X PUT "https://api.datadoghq.com/api/v1/tags/hosts/${host_name}" \
-H "Content-Type: application/json" \
-H "DD-API-KEY: ${DD_API_KEY}" \
-H "DD-APPLICATION-KEY: ${DD_APP_KEY}" \
-d @- << EOF
{
  "host": "'$host_name'",
  "tags": [
    "'$TAG'"
  ]
}
EOF
echo -e "\n";sleep 1s

done
```

#### ホストのタグを削除する(remove)

* 実行するディレクトリに別途"list.txt"を用意し、タグを付与したいホスト名を記述します
* スクリプトはlist.txtを読み込んで、対象ホストに対して順次タグ削除（全削除）を行います
* 削除されるのはあくまで"User Tags"のみです、"Host Tags"には影響しません

```bash:removehosttags.sh
#!/bin/sh

# Path parameters
export DD_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export DD_APP_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# list read
cat list.txt | while read host_name
do
        echo $host_name

# Curl command
curl -X DELETE "https://api.datadoghq.com/api/v1/tags/hosts/${host_name}" \
-H "Content-Type: application/json" \
-H "DD-API-KEY: ${DD_API_KEY}" \
-H "DD-APPLICATION-KEY: ${DD_APP_KEY}"
sleep 1s
done
```

### 少し苦労したところ
* addがメインな訳ですが、公式のdocをちゃんと読まずに最初はtag情報だけをPOSTしていて、json内にhostも必要なのを見落としていました
* curlの中でhostを渡しているので、jsonにはtagだけで良いだろうと勝手に思い込んでいました（これで2時間ぐらい余計に悩んだ…公式って大事）

### 最後に
* 一つのOrganization内に数百台のホストが登録されている…など、どうやって管理するのか怖くなるような環境を相手にしているエンジニアの方であれば、それなりに用途はあるのではないでしょうか