关于 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"]- 无变更
重要说明
- 需要 Terraform 0.12+ 才能支持 JSON 输出
- 如果计划尚未完成,将返回 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