tfc-plan-json について
tfc-plan-jsonは、Terraform Cloudの実行プランJSONをダウンロードして分析するスキルです。リソース変更を確認するインフラチーム向けに、変更操作や置換理由、プロバイダーバージョン、出力値を調べられます。
主な機能
- 01実行プランJSONのダウンロード
- 02リソースの作成・更新・削除の集計
- 03リソース置換理由の確認
- 04プロバイダーバージョンと出力値の確認
活用シーン
- 01予定されたリソース変更のレビュー
- 02プランデータのコスト・ポリシーツールへの連携
- 03リソース置換理由の確認
- 04プランで使われるプロバイダーバージョンの検証
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ laurigates/ claude-plugins --skill tfc-plan-jsonインストール後、Claude Code で/tfc-plan-jsonを入力して読み込まれたか確認します。
詳細
Terraform Cloud Plan JSON
Terraform Cloud の実行から構造化されたプラン JSON 出力をダウンロードして分析し、リソースの変更を詳細に確認します。
このスキルを使用する場合
| このスキルを使用する場合... | 代わりに関連スキルを使用する場合... |
|---|---|
| プランで作成、更新、削除されるリソースをプログラムで差分比較する場合 | 人間が読めるプラン/適用ログを読む場合(tfc-run-logs) |
| 実行で使用されたプロバイダーのバージョンや、プランで予定されている出力値を調べる場合 | 実行の成功/失敗ステータスのみを確認する場合(tfc-run-status) |
| プラン全体でリソースが置き換えられる理由を監査する場合 | 複数の実行を一覧表示して適切な実行 ID を探す場合(tfc-list-runs) |
| プラン JSON を後続のツール(コスト、ポリシー、ドリフト)に渡す場合 | ショートカットを使って FVH 固有のワークスペース実行を参照する場合(tfc-workspace-runs) |
前提条件
export TFE_TOKEN="your-api-token" # User or team token with admin workspace access
export TFE_ADDRESS="app.terraform.io" # Optional
主なコマンド
プラン JSON をダウンロードする
#!/bin/bash
set -euo pipefail
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="${1:?Usage: $0 <run-id> [output-file]}"
OUTPUT="${2:-plan.json}"
# Download with redirect following (API returns 307)
curl -Lsf --header "Authorization: Bearer $TOKEN" \
-o "$OUTPUT" \
"$BASE_URL/runs/$RUN_ID/plan/json-output"
echo "Plan JSON saved to: $OUTPUT"
プラン ID を指定してダウンロードする
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
PLAN_ID="plan-xyz789"
curl -Lsf --header "Authorization: Bearer $TOKEN" \
-o plan.json \
"https://app.terraform.io/api/v2/plans/$PLAN_ID/json-output"
分析コマンド
リソース変更の概要
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq '{
terraform_version: .terraform_version,
format_version: .format_version,
summary: {
create: [.resource_changes[] | select(.change.actions | contains(["create"]))] | length,
update: [.resource_changes[] | select(.change.actions | contains(["update"]))] | length,
delete: [.resource_changes[] | select(.change.actions | contains(["delete"]))] | length,
replace: [.resource_changes[] | select(.change.actions | contains(["delete", "create"]))] | length,
read: [.resource_changes[] | select(.change.actions | contains(["read"]))] | length,
no_op: [.resource_changes[] | select(.change.actions == ["no-op"])] | length
}
}'
作成されるリソースを一覧表示する
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq -r '.resource_changes[] | select(.change.actions | contains(["create"])) | .address'
削除されるリソースを一覧表示する
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq -r '.resource_changes[] | select(.change.actions | contains(["delete"])) | .address'
更新されるリソースを一覧表示する
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq -r '.resource_changes[] | select(.change.actions | contains(["update"])) | .address'
置き換えられるリソース
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq -r '.resource_changes[] | select(.change.actions | contains(["delete", "create"])) |
"\(.address) (replace due to: \(.action_reason // "unknown"))"'
リソースの変更詳細
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq '.resource_changes[] | select(.change.actions != ["no-op"]) | {
address: .address,
actions: .change.actions,
before: .change.before,
after: .change.after
}'
特定のリソースで変更される内容を確認する
RESOURCE="aws_instance.web"
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq --arg addr "$RESOURCE" '
.resource_changes[] | select(.address == $addr) | {
address: .address,
actions: .change.actions,
before: .change.before,
after: .change.after,
after_unknown: .change.after_unknown
}'
使用されているプロバイダーのバージョン
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq '.configuration.provider_config | to_entries | map({
provider: .key,
version: .value.version_constraint
})'
出力値
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq '.output_changes | to_entries | map({
name: .key,
actions: .value.actions,
sensitive: .value.after_sensitive
})'
使用されている変数
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq '.variables | keys'
完全な分析スクリプト
#!/bin/bash
set -euo pipefail
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
RUN_ID="${1:?Usage: $0 <run-id>}"
PLAN=$(curl -Lsf --header "Authorization: Bearer $TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output")
echo "=== Plan Analysis for $RUN_ID ==="
echo ""
echo "Terraform Version: $(echo "$PLAN" | jq -r '.terraform_version')"
echo ""
echo "Resource Changes:"
echo " Create: $(echo "$PLAN" | jq '[.resource_changes[] | select(.change.actions | contains(["create"]))] | length')"
echo " Update: $(echo "$PLAN" | jq '[.resource_changes[] | select(.change.actions | contains(["update"]))] | length')"
echo " Delete: $(echo "$PLAN" | jq '[.resource_changes[] | select(.change.actions | contains(["delete"]))] | length')"
echo " Replace: $(echo "$PLAN" | jq '[.resource_changes[] | select(.change.actions | contains(["delete", "create"]))] | length')"
echo ""
echo "Resources to Create:"
echo "$PLAN" | jq -r '.resource_changes[] | select(.change.actions | contains(["create"])) | " - " + .address'
echo ""
echo "Resources to Destroy:"
echo "$PLAN" | jq -r '.resource_changes[] | select(.change.actions | contains(["delete"])) | " - " + .address'
echo ""
echo "Resources to Update:"
echo "$PLAN" | jq -r '.resource_changes[] | select(.change.actions | contains(["update"])) | " - " + .address'
プラン JSON の構造
プラン JSON 出力は、Terraform の JSON プラン形式に従います。
{
"format_version": "1.2",
"terraform_version": "1.5.0",
"planned_values": { ... },
"resource_changes": [
{
"address": "aws_instance.web",
"mode": "managed",
"type": "aws_instance",
"name": "web",
"provider_name": "registry.terraform.io/hashicorp/aws",
"change": {
"actions": ["create"],
"before": null,
"after": { ... },
"after_unknown": { ... },
"before_sensitive": false,
"after_sensitive": { ... }
}
}
],
"output_changes": { ... },
"configuration": { ... },
"variables": { ... }
}
変更アクション
["create"]- リソースが作成されます["delete"]- リソースが削除されます["update"]- リソースがインプレースで更新されます["delete", "create"]- リソースが置き換えられます["read"]- データソースが読み取られます["no-op"]- 変更はありません
重要な注意事項
- JSON 出力のサポートには Terraform 0.12 以降が必要です
- プランがまだ完了していない場合、204 No Content が返されます
- リダイレクトに従ってください - API は一時的なダウンロード URL に HTTP 307 でリダイレクトします
- 一時 URL - ダウンロード URL の有効期間は約 1 分です
- 管理者アクセスが必要です - ワークスペースに対する管理者権限が必要です
エラー処理
204 No Content
プランがまだ完了していません。最初に実行ステータスを確認してください。
401 Unauthorized
トークンにワークスペースの管理者アクセス権がないか、無効です。
404 Not Found
実行が存在しないか、アクセス権がありません。
関連項目
tfc-run-logs:プラン/適用ログを取得します(人間が読める形式)tfc-run-status:実行ステータスをすばやく確認しますtfc-list-runs:ワークスペース内の最近の実行を一覧表示します
コメント
Markdown 対応