OpenTofu 开发者指南从环境搭建、源码构建到调试、测试与贡献提交的完整实战手册【免费下载链接】opentofuOpenTofu lets you declaratively manage your cloud infrastructure.项目地址: https://gitcode.com/gh_mirrors/op/opentofuOpenTofu 是一个以声明式方式管理云基础设施的开源项目本文基于仓库内 contributing/DEVELOPING.md 编写面向想要为 OpenTofu 提交代码的开发者。你将掌握一整套可落地的开发流程搭建 Go 开发环境、用go build与go test完成编译和测试、借助 dlv 与 IDE 配置进行交互式调试、通过 DCO 签名与版权规范安全地提交 PR并了解验收测试、集成测试、代码生成、依赖合规与版本反向移植等高级主题。快速开始从零到提交 PR 的 8 个步骤如果你已经迫不及待地想动手写代码这里是精简版流程搭建开发环境准备好带 Git 的 Go 开发环境详见下文搭建开发环境一节。注意版权合规请先阅读 DCODeveloper Certificate of Origin代码必须由你自己编写避免复制粘贴在 OpenTofu 场景下请关闭 AI 编码助手原因详见关于版权的说明一节。运行测试在你正在工作的包内执行go test验证改动。构建 OpenTofu通过go build ./cmd/tofu生成二进制。更新变更日志在仓库根目录的 CHANGELOG.md 中补充你的变更条目。提交时签名使用git commit -s为提交附加 DCO 签名。提交 PR提交 Pull Request并完整填写模板中的检查清单。等待评审当 PR 标记为 ready to review 后维护者会开始评审。搭建开发环境OpenTofu 的开发可以在任意平台进行但官方推荐Linux含 Windows 上的 WSL或 macOS构建环境。你至少需要安装Go建议安装最新可用版本然后让 Go 工具链根据go.mod中的指令自动选择合适的语言与工具版本。以当前仓库为例go.mod 声明了module github.com/opentofu/opentofu与go 1.27.1同时通过godebug指令对个别 Go 新特性做了显式开关例如tlsmlkem0这是上游在评估新特性稳定性后给出的兼容策略。Git用于版本管理与提交。IDE推荐带有代码补全与代码质量警告能力的 IDE。使用 devcontainer 一键搭建环境如果你使用Visual Studio Code或Goland/IntelliJ并且本机装有 Docker 或 Podman可以直接复用仓库根目录的 .devcontainer.jsonVSCode安装 Remote Containers 扩展后重新打开项目会弹出激活 devcontainer 的提示。Goland/IntelliJ打开.devcontainer.json文件点击行号旁边出现的紫色立方体图标即可激活 dev container。激活后你就相当于在一个干净的 Linux 环境中工作可以直接按下文构建 OpenTofu的方式继续操作无需在本机再折腾 Go 工具链。构建 OpenTofu在源码目录下执行go build ./cmd/tofu该命令会在当前目录生成一个tofu可执行文件验证方式./tofu --version提示交叉编译如需为其他平台构建可附加GOOS与GOARCH环境变量指定目标平台例如GOOSlinux GOARCHarm64 go build ./cmd/tofu。更多信息可查阅 Go 官方文档中关于编译与运行 Go 程序的部分。从源码结构看CLI 的主入口位于 cmd/tofu/main.gopackage main负责初始化日志、终端、tracing 等基础设施并进入命令分发模块内的其余文件如commands.go、command_main.go、plugins.go共同构成了 OpenTofu 的完整 CLI 层。当你需要深入某个子命令如plan、apply的实现时可以在 internal/command 目录中找到对应文件例如 internal/command/plan.go 与 internal/command/apply.go。运行测试与构建类似测试同样使用 Go 标准工具链# 运行全部测试 go test ./... # 只测试当前正在工作的包 go test ./internal/command/... go test ./internal/addrs推荐在开发时聚焦运行你正在修改的那个包的测试速度快且反馈及时。Go 的go test会自动识别包内的_test.go文件并执行其中的测试函数仓库中每个核心包都带有配套测试例如 internal/addrs、internal/configs 等目录下的*_test.go文件。调试 OpenTofu推荐方式交互式调试器大多数 IDE 内置了 Go 调试能力也可以使用 dlvGo 调试器在远程机器上进行调试。仓库提供了开箱即用的调试脚本 scripts/debug-opentofu其核心行为是exec dlv debug github.com/opentofu/opentofu --headless --listen :2345 --log -- $即以 headless无头模式启动 OpenTofu 的调试会话监听 2345 端口等待远程连接并透传所有命令行参数。启动后你可以用以下命令或其等价的前端操作连接dlv connect 127.0.0.1:2345注意该脚本会直接启动源码包进行调试OpenTofu 二进制并不在$GOPATH/bin中因此依赖该目录安装 provider 的场景可能找不到 provider调试时请留意。VSCode 调试配置为方便调试可以在.vscode/launch.json中添加如下配置三种典型场景{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid830387 version: 0.2.0, configurations: [ { name: tofu init, type: go, request: launch, mode: debug, program: ${workspaceFolder}/cmd/tofu, // You can update the environment variables here env: { TF_LOG: trace }, // You can update your arguments for init command here // Comment out the following line and update your workdir to target // args: [-chdirWORKDIR, init] args: [init] }, { name: tofu plan, type: go, request: launch, mode: debug, program: ${workspaceFolder}/cmd/tofu, env: { TF_LOG: trace }, // You can update your arguments for plan command here // Comment out the following line and update your workdir to target // args: [-chdirWORKDIR, plan] args: [plan] }, { name: opentofu test run, type: go, request: launch, mode: test, program: ${workspaceFolder}/internal/lang/evalchecks/eval_for_each_test.go, // You can update your arguments for go test command here // args: [-test.run, TestName/sub_test] // or to run a whole test // args: [-test.run, TestName] args: [-test.run, TestEvaluateForEachExpression_errors/set_containing_marked_values] } ] }配置要点说明mode: debug表示以调试模式启动cmd/tofu主程序通过args传入要调试的子命令如init、plan。通过env: { TF_LOG: trace }开启 OpenTofu 的详细日志输出便于在调试时观察内部执行轨迹。第三个配置mode: test演示了单测调试直接指定一个测试文件示例为 internal/lang/evalchecks/eval_for_each_test.go并用-test.run精确过滤到某个测试或子测试。Goland/IntelliJ 调试配置同样地你可以在.idea/runConfigurations目录下添加如下 XML 配置以tofu init与tofu plan为例!-- .idea/runConfigurations/tofu_init.xml -- component nameProjectRunConfigurationManager configuration defaultfalse nametofu init typeGoApplicationRunConfiguration factoryNameGo Application module nameopentofu / working_directory value$PROJECT_DIR$ / parameters valueinit / kind valueDIRECTORY / package valuegithub.com/opentofu/opentofu/cmd/tofu / directory value$PROJECT_DIR$/cmd/tofu / filePath value$PROJECT_DIR$ / method v2 / /configuration /component!-- .idea/runConfigurations/tofu_plan.xml -- component nameProjectRunConfigurationManager configuration defaultfalse nametofu plan typeGoApplicationRunConfiguration factoryNameGo Application module nameopentofu / working_directory value$PROJECT_DIR$ / parameters valueplan / kind valueDIRECTORY / package valuegithub.com/opentofu/opentofu/cmd/tofu / directory value$PROJECT_DIR$/cmd/tofu / filePath value$PROJECT_DIR$ / method v2 / /configuration /component关键元素说明package指向github.com/opentofu/opentofu/cmd/tofu与go.mod中的模块名一致parameters传入要调试的子命令参数working_directory设为项目根目录。数据结构的可视化输出除了交互式调试还可以使用 go-spew 中的变更描述时的实用工具。为提交添加 DCO 签名OpenTofu 要求所有贡献代码附带Developer Certificate of OriginDCO签名。请先仔细阅读 DCO 全文并且只提交你自己编写的代码如果希望加入并非自己从零编写的代码请先在相关 issue 中讨论。最简单的签名方式是在 commit 时使用-s参数git commit -s -m My commit message重要请确保 Git 的user.name与user.email设置和你的 GitHub 账号信息一致。这样自动化 DCO 检查才能通过避免合并 PR 时产生不必要的延误。提示如果忘了签名点击失败的 DCO 检查上的 details 按钮会有指引教你如何修复。关于版权的说明OpenTofu 项目对版权与知识产权问题非常重视几条快速规则值得牢记提交 PR 时你要为其中的代码负责签名即表示接受 DCO。如果 PR 中包含并非你本人编写的代码必须确保获得原作者许可获得许可后务必在提交中添加Co-authored-by签名标明代码原作者。警惕 AI 编码助手基于大语言模型LLM的编码助手如 ChatGPT、GitHub Copilot本身是优秀的工具但就 OpenTofu 而言其训练数据可能包含BSL 许可的 Terraform 代码。由于 OpenTofu/Terraform 代码库非常特殊LLM 缺乏其他训练来源很可能输出受版权保护的代码。因此请避免使用基于 LLM 的编码助手。从 OpenTofu 内部复制/粘贴代码时务必明确标注来源这有助于后续问题排查。从外部来源复制代码前确认其许可证允许并满足署名等许可要求有疑问先询问。切勿从 Terraform 仓库或他人提交给该仓库的 PR 中复制代码——这些代码基于 BSL 许可与 OpenTofu 不兼容。只要两个 PR 都由你本人撰写你可以向 Terraform 和 OpenTofu 同时提交相同内容。警告为保护 OpenTofu 项目免受法律问题困扰违反上述规则将导致你的 PR 立即失去合并资格并失去在该代码区域的后续工作权限屡次违规可能被禁止继续为 OpenTofu 贡献。高级主题验收测试测试与外部服务的交互上文提到的go test只运行不依赖外部服务的自包含测试。而 OpenTofu CLI 代码库中还有一类可选的、确实会与外部服务交互的测试统称为验收测试acceptance tests。启用方式运行测试时设置环境变量TF_ACC1。建议只对你正在工作的那个包开启一方面测试运行更快另一方面也不容易因为与你目标无关的系统中出现漂移drift而导致失败TF_ACC1 go test ./internal/initwd集成测试测试与外部后端的交互OpenTofu 支持多种 backends远程状态后端项目会针对它们运行集成测试以确保使用 OpenTofu 时不产生副作用。首先列出所有可用的集成测试命令make list-integration-tests该目标在 Makefile 中实现本质是通过 grep 与 awk 从 Makefile 自身提取所有带##注释的测试目标及其说明从而动态生成可用命令清单。从清单中挑选与你打算测试的后端相关的命令执行即可。例如运行 s3 后端的集成测试make test-s3从 Makefile 的实现可以了解test-s3的实际前置条件与执行内容前置条件配置好 AWS 凭证支持配置文件与环境变量两种方式在us-west-2区域具备 IAM 权限——对符合tofu-test-*模式命名的 S3 bucket 的 CRUD 操作以及对名为dynamoTable的 DynamoDB 表的 CRUD 操作。执行内容设置TF_S3_TEST1后运行go test ./internal/backend/remote-state/s3/...。仓库中还提供了其他后端的集成测试目标如test-gcp、test-pg、test-consul、test-kubernetes等以及一键运行全部集成测试的integration-tests目标具体以make list-integration-tests输出为准。生成代码OpenTofu CLI 代码库中存在部分生成文件。多数情况下通过go generate更新这是 Go 代码库中封装代码生成步骤的标准方式go generate ./...生成完成后用git diff检查变更确认是否符合预期。对应的 Makefile 目标为 Makefile 中的generate执行go generate ./...。其中有一类特殊的生成代码Terraform provider 插件协议的 Go stub它基于 Protocol Buffers 定义协议定义文件位于 docs/plugin-protocol 与 internal/tfplugin5、internal/tfplugin6。由于 Protocol Buffers 工具并非 Go 编写无法通过go get自动安装因此需要先安装合适版本的protoc再执行make protobuf该目标在 Makefile 中通过go tool protobuf-compile .实现其设计意图正如 Makefile 注释所言protobuf 生成被单独拆分因为绝大多数开发任务不涉及修改 protobuf 文件而protoc又不是一个可通过go get安装的依赖单独安装比较麻烦。添加或更新依赖如果新增或更新依赖必须确保它们只使用已批准且兼容的许可证。批准清单定义在仓库根目录的 .licensei.toml目前包含apache-2.0、bsd-2-clause、bsd-3-clause、isc、mpl-2.0、mit。本地开发与 CI 中项目使用 licensei 开源工具辅助校验。修改go.mod或go.sum之后可手动运行export GITHUB_TOKENchangeme make license-check注意必须将GITHUB_TOKEN环境变量设置为有效的 GitHub personal access token否则licensei在通过 GitHub API 探测依赖许可证时会触发限流。从 Makefile 的实现可以看到license-check的完整流程先go mod vendor生成 vendor 目录然后依次执行licensei cache缓存许可证信息、licensei check校验依赖许可证、licensei header校验文件头版权声明最后清理 vendor 目录并通过git diff --exit-code确保没有任何残留改动。反向移植Backporting默认情况下所有改动都应进入main分支。当某个修复足够重要时它会被反向移植到版本分支并在下一个次要版本发布时随版本发布。反向移植流程确保工作副本中的main分支与目标版本分支都是最新的。查找到目标提交的 commit ID。切换到目标版本分支并从中创建新的分支git checkout -b backports/ISSUE_NUMBER将目标提交 cherry-pick 到反向移植分支-s同样会附加 DCO 签名git cherry-pick -s COMMIT_ID_HERE最后额外创建一个提交来更新 CHANGELOG.md保持与仓库现有的 changelog 结构一致在对应版本标题下列出UPGRADE NOTES、BUG FIXES等分类条目然后提交 PR。写在最后一份高质量的 OpenTofu 贡献离不开环境就绪 → 构建验证 → 测试覆盖 → 合规签名这条完整链路。从 cmd/tofu/main.go 的入口到 internal/command 的命令实现、internal/backend/remote-state 的后端测试仓库内的源码与 Makefile 都为你提供了可验证的参考。遵循本文的流程你就能顺畅地完成从git commit -s到 PR 合并的每一步。【免费下载链接】opentofuOpenTofu lets you declaratively manage your cloud infrastructure.项目地址: https://gitcode.com/gh_mirrors/op/opentofu创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
