iac_modules/terraform-hcl-standard/AGENTS.md
Haitao Pan 3a8065e6f0 refactor(vultr-vps): split declaration / shared templates / shared scripts
- config/resources/ai-workspace-hosts.yaml: resource declaration (moved from env)
- templates/: shared provider.tf, variables.tf, cloud-init.yaml + hosts.tf.j2,
  inventory.ini.j2 (render copies the .tf/config into the env workdir)
- scripts/generate.py + provision.sh: shared composition logic, parameterized
  by --resources/--workdir (no longer duplicated per env)
- envs/ai-workspace/: degraded to a terraform workdir (only README/.gitignore
  tracked; rendered artifacts + tfstate gitignored)
- AGENTS.md + terraform-yaml-render-pattern skill updated to the layered layout

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 21:21:45 +08:00

4.4 KiB
Raw Permalink Blame History

AGENTS.md —— Terraform 模块约束规范(强制)

适用范围:iac_modules/terraform-hcl-standard/**。本文件为约束性规范 在本目录下创建/修改 Terraform env 时 必须遵守。冲突时以本文件为准。

0. 核心范式MUST

新建可批量编排的 env如多主机 VPS必须采用如下数据流, 不得在 HCL 内做循环:

YAML 描述资源
   │  (Python + Jinja2 渲染,循环在此完成)
   ▼
显式 Terraform module/resource 块  ── 每个实例/资源一个独立块,不用 for_each
   │
   ▼
terraform apply
   │
   ▼
Python 合并「YAML 静态信息」+「Terraform 运行时输出」
   │
   ▼
CMDB (cmdb.json) + Ansible inventory (inventory.ini / 动态 inventory)

参考实现(基准,新 env 照此结构落地): vultr-vps/envs/ai-workspace/

配套 binding skill完整规则与自检清单 ../skills/terraform-yaml-render-pattern/SKILL.md

1. HCL 控制结构禁令MUST NOT

  • 禁止在 env 的 .tf 中使用 for_eachcountdynamic 块。
  • 禁止用 templatefile() + %{ for }/%{ if } 等 HCL 模板控制结构做渲染。
  • 允许纯函数:concatmergecoalescejsonencode 等(非控制结构)。
  • 资源的“多份”由 Python+Jinja2 在生成阶段展开为多个显式块 每台主机 / 每个 key 对应一个命名唯一的 module/resource/data 块。

理由:把循环与条件收敛到 Python/Jinja2 单一处HCL 保持“扁平、可审计、 diff 友好”,资源命名稳定,避免 for_each key 漂移导致的重建。

2. 资源描述与变量传递MUST

  • 资源信息必须config/resources/<name>-hosts.yaml(或等价 *.yaml)声明,作为唯一人工入口; 放在 env 目录里。
  • YAML 的全局段经渲染写入 terraform.auto.tfvars.json传给 variables.tf 逐实例字段由 Jinja2 展开进生成的 .tf
  • 机密API Key、私钥等禁止写入 YAML / tfvars必须走环境变量 (如 TF_VAR_vultr_api_key)。公钥可入 YAML。

3. 渲染器约定MUST

组合逻辑必须收敛到共享 scripts/generate.py--resources/--workdir 参数化, 不在每个 env 各放一份),至少含两个子命令:

  • renderconfig/resources/*.yaml → workdir 下 generated_hosts.tf + provider.tf/variables.tf/cloud-init.yaml(拷自 templates/+ terraform.auto.tfvars.json
  • inventoryterraform output(运行时事实)+ YAML静态字段cmdb.json + inventory.ini

约定:

  • 共享脚本放 scripts/,共享 .tf 与 Jinja2 模板放 templates/provider.tf/ variables.tf/cloud-init.yaml/*.j2env 仅作 terraform 运行目录; 标识符经 tf_id 过滤器净化为合法 HCL 名。
  • Terraform 仅输出 运行时才确定 的事实(如 cmdb_runtimeip / instance_id / 解析后的 os_id。静态字段os_name/plan/groups/host_vars 等)由 Python 从 YAML 合并。
  • inventory.ini 中含空格的 host_var 值必须加引号(key="a b c")。
  • 渲染产物(generated_hosts.tfterraform.auto.tfvars.jsoncmdb.jsoninventory.ini)为派生物,必须加入 .gitignore,不入库。

4. 模块复用与 OS 解析SHOULD

  • 实例复用 modules/compute 等既有模块,不在 env 内重写 provider 资源。
  • 每个使用 provider 的子模块必须声明 required_providers(含正确 source 否则 Terraform 误判为 hashicorp/<name>
  • OS data "vultr_os"os_name 解析 os_id,避免硬编码漂移 ID 解析不到时允许在 YAML 直接给 os_id

5. IaC ↔ Ansible 联动MUST

  • CMDBcmdb.json)是 IaC 与 Ansible 的契约。Ansible 侧的动态 inventory playbooks/inventory/terraform_cmdb.py消费 cmdb.json,不直接耦合 tfstate。
  • IaC 变更后必须重跑 generate.py inventory 刷新 CMDB/inventory保持二者一致。

6. 提交前自检MUST

  • terraform fmt 无 diffterraform validate 通过。
  • python3 generate.py render 能产出合法 .tfvalidate 通过)。
  • 生成的 inventory.ini 能被 ansible-inventory -i <file> --graph 正确解析。
  • 确认渲染产物已被 .gitignore 忽略、机密未入库。