jqでDatadogの特定タグ毎のホスト情報を抽出する


経緯

Datadog AgentがVer7をリリースし、EOLを迎えるPython2からPython3へ完全移行するという事だったので、Ver6以下のAgentをアップデートするべく、ホストの内訳をjqで整理したメモ。

datadog agent ver.7 release
python2 eol

DatadogのWebコンソールからも見れるけど、対象一覧としてチェックシート化したい思いもあったので。

やった事概要

  • DatadogのAPIでInfrastructure Listの内容を出力
  • jqで整形、CSV化

Datadog APIでホスト一覧を取得

どこのエンドポイントが良さそうかサポートに問い合わせたところ、Infrastructure Listが良さそうとの事。

Infrastructure ListのエンドポイントはWebコンソールの下の方にJSON API permalinkがあったのでこれを利用。

Datadog API Referenceに従ってcurlで実行。

$ curl "https://app.datadoghq.com/hogehoge \
              -H "DD-API-KEY: $DD_API_KEY" \
              -H "DD-APPLICATION-KEY: $DD_APPLICATION_KEY" | jq

こういう感じのJsonが取得できる(1ホストあたり)。

{
  "rows": [
    {
      "display_name": "prd-hogehoge",
      "name": "prd-hogehoge",
      "aws_id": "prd-hogehoge",
      "is_muted": false,
      "mute_timeout": null,
      "apps": [
        "nginx",
        "agent",
        "ecs"
      ],
      "tags_by_source": {
        "Datadog": [
          "env:prd",
          "name:prd-web-api",
          "project:hogehoge",
          "role:web-api"
        ]
      },
      "up": true,
      "metrics": [],
      "sources": [
        "agent"
      ],
      "meta": {
        "socket-hostname": "3f3e09526d9a",
        "nixV": [
          "debian",
          "buster/sid",
          ""
        ],
        "agent_checks": [
          [
            "ecs_fargate",
            "ecs_fargate",
            "ecs_fargate:46910d4f2b2fec0d",
            "OK",
            "",
            ""
          ],
        "machine": "amd64",
        "platform": "linux",
        "host_id": 730898351,
        "pythonV": "2.7.15",
        "processor": "Intel(R) Xeon(R) CPU E5-2666 v3 @ 2.90GHz",
        "socket-fqdn": "269593f3d0ea",
        "agent_version": "6.6.0"
      },
      "host_name": "prd-hogehoge",
      "has_metrics": false,
      "aliases": [
        "prd-hogehoge"
      ],
      "id": 378019538,
      "last_seen": 1005887865
    },

出力したJsonをjqで整形

とりあえず皮むき

$ jq ' .rows[] '

そしてこのAPIで出力されるホストはどうもパブリッククラウドのインテグレーションで検知したものも含まれているようでした。
つまり、Datadog Agentが入っていないホストも含まれているっぽい。

Agentが入っているやつだけを抽出

$ jq ' .rows[] | select ( .apps | tostring | contains("agent")) '

これで必要なホストだけが出力された状態になりました。

必要そうな項目を抽出

対象の識別のためにnametags_by_source-projectの値は必要そうかなー
aws_idも基本はnameと被りそうだけど一応取得しておこう。
この項目はAWS以外の環境でもaws_idっぽいです。

tags_by_sourceの値を取得しようとして気付いたのですが、
これ対象のサービス側で付与されているタグ情報っぽいですが、
key:valueの形式でなく合わせて一つのstringにされているみたいでした。

抽出する時にkeyで引っ掛けれないからちょっとめんどくさくなってますね。。。
walkifを組み合わせて要素内の文字列を検索する形で引っ張ってくる。
もっと良さげなやり方はありそう。

あとはDatadog Agentのバージョンっぽいagent_versionも拾っておく。

jq ' .rows[] | select ( .apps | tostring | contains("agent")) | .display_name,  .aws_id, (.tags_by_source[][] | walk(if startswith("project") then . else empty end)), .meta.agent_version '
"prd-hogehoge"
"prd-hogehoge"
"project:hogehoge"
"6.6.0"

おお、なんかそれっぽい感じに出てきました。

+αの処理

このままだとなんの値かわからないので項目を追加。
後々、CSVに出力する事を想定してオブジェクト化。
などなどを対応していきました。

最終的に下記の感じに。

curl "https://app.datadoghq.com/hogehoge"  \
              -H "DD-API-KEY: $DD_API_KEY" \
              -H "DD-APPLICATION-KEY: $DD_APPLICATION_KEY" \
| jq ' .rows[] | select ( .apps | tostring | contains("agent")) | \
{ "display_name": .display_name,  "server_id": .aws_id,  "project": (.tags_by_source[][] | walk(if startswith("project") and (test("project:olg-pf-recibo-api")|not) then . else empty end)), "agent_version": .meta.agent_version } \ | 
"\(.display_name),\(.aws_id),\(.project)\(.agent_version)"' -r

{
  "display_name": "prd-hogehoge",
  "server_id": "prd-hogehoge",
  "project": "project:hogehoge",
  "agent_version": "6.6.0"
}

もうちょっとなんとかなりそうだけどとりあえずこんな感じで。