mcpField
T
tfc-plan-json

tfc-plan-json

github.com/laurigates云与 DevOps5963 次安装1 天前更新
代码仓库

关于 tfc-plan-json

tfc-plan-json 是用于下载并分析 Terraform Cloud 运行计划 JSON 的技能,面向需要检查资源变更的基础设施团队。它可归纳创建、更新、删除和替换操作,并查看提供程序版本及输出值。

主要功能

  1. 01下载运行计划 JSON
  2. 02汇总资源创建、更新和删除
  3. 03检查资源替换原因
  4. 04查看提供程序版本与输出值

适用场景

  1. 01审查计划中的资源变更
  2. 02将计划数据交给成本或策略工具
  3. 03核对资源替换原因
  4. 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