🥢

HCP Terraform の各 Workspace で利用されているリソースの取得方法

2024/01/05に公開

HCP Terraformの課金体系が、2023年5月にResource Under Management(以下RUM)の数に変更されました(資料によっては、Managed Resourcesと表現されている事もありますが、RUMと同じ意味になります)。
https://www.hashicorp.com/blog/terraform-cloud-updates-plans-with-an-enhanced-free-tier-and-more-flexibility

RUMの対象になるTerraformリソースは、ステートファイルでmode = managedとなっているリソースになります。

RUM対象となるTerraformリソースの一例
  {
    "mode": "managed",
    "type": "vault_mount",
    "name": "int",
    "provider": "provider[\"registry.terraform.io/hashicorp/vault\"]",
...

Terraformリソースの全てがRUMの対象となるわけではなく、データソースnull_resourceRUMの対象外となります。

HCP TerraformではWorkspace毎にステートが管理されるわけですが、Workspace毎にどの様なリソースが管理され、どの程度RUMを消費しているか一元的に確認したくなるケースもあるかと思います。BetaリリースされているExplorerを含め、現状HCP TerraformのGUIから良い感じに確認出来る方法は無さそうなので、それを実現するためにはHCP Terraform APIを利用するしか現状はなさそうです。

以下お使いのHCP TerraformのOrganization内のWorkspace毎にどの様なリソースが作成され、どの程度RUMを消費しているか確認する方法について記載します。

Resources in HCP Terraform workspace

HCP Terraformの各WorkspaceのOverviewから、そのWorkspaceでどの様なリソースが管理され、何リソース存在しているか確認して頂く事が可能です。

HCP TerraformのWorkspaceのOverview

これはRUMの数ではなく、Workspaceで管理されているステートでリソースとして定義されている数になりますので、

HCP TerraformのWorkspaceのOverviewで確認出来るリソース数 >= そのWorkspaceで消費しているRUM数

となります。

Workspace毎にどの程度RUMを消費しているか概算を把握する上ではこれでも十分かと思います。
また、WorkspaceのStates確認画面から対象となるステートを選択した上で、filterフィールドで.resources[].modeと入力し、Applyボタンをクリックすると、mode = managedとなっているリソース数を確認する事も出来ます。

WorkspaceのStateのfilterを利用して確認

ただ、HCP TerraformのOrganization内にある各Workspaceでどの程度RUMが消費され、各Workspace毎にどの様なリソースが管理されているか一元的に可視化する機能は現状無いため、その様な情報を確認したい場合、HCP Terraform APIのWorkspace Resources APIを利用して頂くと良い感じに取得出来そうです。

Get resources via HCP Terraform API

上記のAPIを利用するとサンプルレスポンスにある通り、data[].attributes.addressからWorkspaceで管理されているリソース情報を取得出来そうです。

{
  "data": [
    {
      "id": "wsr-KNYb3Jj3JTBgoBFs",
      "type": "resources",
      "attributes": {
        "address": "random_pet.animal",
        "name": "animal",
        "created-at": "2021-10-27",
        "updated-at": "2021-10-27",
        "module": "root",
        "provider": "hashicorp/random",
        "provider-type": "random_pet",
        "modified-by-state-version-id": "sv-y4pjfGHkGUBAa9AX",
        "name-index": null
      }
    },
    {
      "id": "wsr-kYsf5A3hQ1y9zFWq",
      "type": "resources",
      "attributes": {
        "address": "random_pet.animal2",
        "name": "animal2",
        "created-at": "2021-10-27",
        "updated-at": "2021-10-27",
        "module": "root",
        "provider": "hashicorp/random",
        "provider-type": "random_pet",
        "modified-by-state-version-id": "sv-y4pjfGHkGUBAa9AX",
        "name-index": null
      }
    }
  ],
  "links": {
    "self": "https://app.terraform.io/api/v2/workspaces/ws-DiTzUDRpjrArAfSS/resources?page%5Bnumber%5D=1&page%5Bsize%5D=20",
    "first": "https://app.terraform.io/api/v2/workspaces/ws-DiTzUDRpjrArAfSS/resources?page%5Bnumber%5D=1&page%5Bsize%5D=20",
    "prev": null,
    "next": null,
    "last": "https://app.terraform.io/api/v2/workspaces/ws-DiTzUDRpjrArAfSS/resources?page%5Bnumber%5D=1&page%5Bsize%5D=20"
  },
  ...
}

色々と手直ししたり、工夫したりする箇所あると思いますが、以下の様な形でスクリプトを作成し、実行して頂ければ、HCP TerraformのOrganizationで管理されているWorkspace毎のRUM数は取得頂けそうです。

get-rum.sh
#!/bin/bash

#HCP Terraform APIトークンとOrganization名を変数にセット
TFC_TOKEN=xxx
TFC_ORG_NAME=xxx

PAGE_SIZE=100

# 全てのWorkspace IDを取得
PAGE_NUMBER=1
ALL_WORKSPACES=()

while true; do
  RESPONSE=$(curl -s --header "Authorization: Bearer $TFC_TOKEN" \
                     --request GET "https://app.terraform.io/api/v2/organizations/$TFC_ORG_NAME/workspaces?page%5Bsize%5D=${PAGE_SIZE}&page%5Bnumber%5D=${PAGE_NUMBER}")

  WORKSPACES=$(echo "$RESPONSE" | jq -r '.data[].id')

  if [ -z "$WORKSPACES" ]; then
    break
  fi

  ALL_WORKSPACES+=($WORKSPACES)

  ((PAGE_NUMBER++))
done

# 各Workspaceでリソースを取得してRUM数を集計
for a in "${ALL_WORKSPACES[@]}"; do
  WORKSPACE_NAME=$(curl -s --header "Authorization: Bearer $TFC_TOKEN" --request GET https://app.terraform.io/api/v2/workspaces/${a} | jq -r '.data.attributes.name')
  PROJECT_ID=$(curl -s --header "Authorization: Bearer $TFC_TOKEN" --request GET https://app.terraform.io/api/v2/workspaces/${a} | jq -r '.data.relationships.project.data.id')
  PROJECT_NAME=$(curl -s --header "Authorization: Bearer $TFC_TOKEN" --request GET https://app.terraform.io/api/v2/projects/$PROJECT_ID | jq -r '.data.attributes.name')

  echo "###### RUM info ######"
  echo "----------"
  echo "Workspace: ${WORKSPACE_NAME}"
  echo "Project:   ${PROJECT_NAME}"
  echo "----------"

  RESOURCE_PAGE_NUMBER=1
  ALL_RESOURCES=()

  while true; do
    RESPONSE=$(curl -s --header "Authorization: Bearer $TFC_TOKEN" \
                      --request GET "https://app.terraform.io/api/v2/workspaces/${a}/resources?page%5Bsize%5D=${PAGE_SIZE}&page%5Bnumber%5D=${RESOURCE_PAGE_NUMBER}")

    RESOURCES=$(echo "$RESPONSE" | jq -r '.data[].attributes.address')

    if [ -z "$RESOURCES" ]; then
      break
    fi

    ALL_RESOURCES+=($RESOURCES)

    ((RESOURCE_PAGE_NUMBER++))
  done

  # 必要なリソースのみをフィルタリングしてRUM数を集計
  WORKSPACE_RUM=$(printf "%s\n" "${ALL_RESOURCES[@]}" | grep -vE 'data\.|null_resource' | wc -l)

  echo "RUM: ${WORKSPACE_RUM}"
  echo ""
done

出力結果は以下の様な形になります。

###### RUM info ######
----------
Workspace: dynamic-credentials-with-vault
Project:   dpc
----------
RUM:       12

###### RUM info ######
----------
Workspace: hcpvd-auth-methods
Project:   vault
----------
RUM:       35

###### RUM info ######
----------
Workspace: hcpvd-namespaces
Project:   vault
----------
RUM:        7
...

必要に応じてご活用下さい!

References

Discussion