Terraform 如何用 go generate 与 make protobuf 重新生成代码
2026/9/9 14:08:37 网站建设 项目流程

Terraform 如何用 go generate 与 make protobuf 重新生成代码

【免费下载链接】terraformTerraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.项目地址: https://gitcode.com/GitHub_Trending/te/terraform

在修改 Terraform 核心源码时,你会遇到一类不能手写的文件:它们由生成工具产出,提交前需要按项目约定重新生成,否则代码与源定义不一致。Terraform 仓库把这类生成步骤分成两条独立路径:绝大多数生成文件通过标准的go generate指令维护,而 Protocol Buffers 桩代码(provider 插件协议、RPC API 等)则通过make protobuf单独处理。本文说明如何判断该走哪条路径、两条路径各自的执行命令,以及如何验证生成结果符合预期。

适用前提:你已在本地克隆 Terraform 仓库并准备修改其中含生成代码的部分(例如修改了.proto接口定义,或需要更新stringermockgen生成的文件)。仓库的 CONTRIBUTING 文档 说明 Terraform 开发环境目前只针对 Linux 和 Mac OS X 系统(单元测试套件含 Unix 特有的路径假设)。

判断该用哪条生成路径

仓库根目录的 Makefile 对两条路径有明确注释:generate目标运行go generate来构建所有动态生成的源文件,除了 protobuf 桩文件,后者用make protobuf构建。分离的原因是:Terraform 大多数开发任务不涉及修改 protobuf 文件,而protoc不是go get能装的 Go 依赖,手动安装不便。

具体到文件:

  • go generate路径:源码中带有//go:generate指令的文件。这类指令大量使用golang.org/x/tools/cmd/stringer(为枚举类型生成String()方法,产出如*_string.go文件)和go.uber.org/mock/mockgen(生成 mock 实现,例如 internal/plugin/mock_proto/generate.go)。工具依赖由 tools/tools.go 统一声明,通过go tool调用。
  • make protobuf路径:各目录下的.proto定义文件及对应的*.pb.go/*_grpc.pb.go桩代码,例如 internal/tfplugin5/tfplugin5.proto、internal/plans/planproto/planfile.proto、internal/rpcapi/terraform1/terraform1.proto。

只有当你的改动触及相应源定义(.proto文件、被stringer/mockgen覆盖的类型)时才需要重新生成;普通的业务代码改动不需要执行这些命令。

准备条件

按 BUILDING.md 与 CONTRIBUTING.md 的说明:

  1. 安装 Go 编译器。当前 go.mod 声明的最低兼容版本为go 1.26.4;自 Go 1.21 起,go命令会自动安装go.mod指定的较新工具链。仓库另以.go-version文件记录生产构建实际使用的版本,可参照该文件选择本地版本。
  2. 用 Git 克隆仓库到一个你选择的位置。Terraform 使用 Go Modules,不要克隆到GOPATH内部。
  3. 开始改动前,先运行单元测试套件确认环境初始是通过的(CONTRIBUTING.md 的建议):
go test ./...

路径一:用 go generate 重新生成普通生成文件

在仓库根目录执行:

go generate ./...

或等价的 Make 目标:

make generate

两者执行的是同一条命令。go generate会扫描所有包中的//go:generate指令并逐条执行,例如:

//go:generate go tool golang.org/x/tools/cmd/stringer -type=ResourceMode //go:generate go tool go.uber.org/mock/mockgen -destination mock.go github.com/hashicorp/terraform/internal/tfplugin5 ProviderClient,...

这些指令使用go tool调用工具,工具版本由 Go 模块体系(go.mod 与 tools/tools.go)决定,不需要你单独安装。执行完成后用git diff检查改动是否为预期结果(CONTRIBUTING.md 明确要求这一步)。

路径二:用 make protobuf 重新生成 protobuf 桩代码

在仓库根目录执行:

make protobuf

该目标实际运行go run ./tools/protobuf-compile .(见 Makefile)。从 tools/protobuf-compile/protobuf-compile.go 的实现可以看到它做了三件事:

  1. 准备 protoc:源码中固定常量protocVersion = "29.3",对应 protoc v5.29.3(与 terraform-plugin-go 当前使用的版本一致)。首次运行会通过 go-getter 从 protoc 官方 release 下载对应平台的压缩包,解压到tools/protobuf-compile/.workdir/protoc-v29.3/;已存在则直接复用。
  2. 构建 Go 插件:用go build从当前go.mod的版本构建google.golang.org/protobuf/cmd/protoc-gen-gogoogle.golang.org/grpc/cmd/protoc-gen-go-grpc两个可执行文件。注释说明:想升级这两个工具时,按 Go 模块的常规方式升级模块即可。
  3. 逐目录运行 protoc:内置一张protocSteps列表,对每个.proto文件用本地化的 protoc 加对应的--go_out/--go-grpc_out参数重新生成桩代码,覆盖internal/tfplugin5internal/tfplugin6internal/rpcapi/terraform1(及其setupdependenciesstackspackages子目录)、internal/plans/planprotointernal/stacks/tfstackdata1internal/cloudplugin/cloudproto1internal/stacksplugin/stacksproto1internal/policy/proto等目录。生成结果写在各.proto文件同目录下(*.pb.go*_grpc.pb.go)。

注意一个文档表述与实际执行差异:CONTRIBUTING.md 的 "Generated Code" 一节的说法是 protobuf 生成 "requires that you've already installed a suitable version ofprotoc",但make protobuf真正执行的 wrapper 工具会自行下载并固定使用 protoc v29.3,不依赖你系统上已安装的 protoc。以实际执行路径为准即可,无需手动安装 protoc。

验证结果

两条路径生成完成后,按文档给出的方式核对:

  1. 检查 diff:运行git diff,确认变更只落在预期的生成文件中(*_string.gomock.go*.pb.go等),且内容符合你对源定义的修改预期。CONTRIBUTING.md 明确建议 "Usegit diffafterwards to inspect the changes and ensure that they are what you expected"。
  2. 跑单元测试:重新执行go test ./...;如果只改了特定包,可以缩小范围加快循环,例如:
go test ./internal/addrs

CONTRIBUTING.md 要求在改动过程中持续保持测试套件通过,改动接口导致测试失效时需要先修复测试再提交。

限制与失败处理

  • 平台限制protoc官方 release 只覆盖了部分平台,wrapper 工具只支持linux_amd64linux_arm64darwin_amd64darwin_arm64(安装 x86_64 包并依赖 Rosetta 转译)、windows_amd64。源码注释 说明:在这些以外的平台上工具会失败,此时要么换到受支持的平台运行,要么自行编译安装 protoc 后手动复现 wrapper 工具所执行的步骤。
  • 单步失败不会中断:工具对每一步 protoc 的执行失败只记录failed to compile日志并继续后续步骤,所以执行结束后要自己用git diff和测试确认所有目标文件都已正确更新。
  • Make 不支持并行:Makefile 用.NOTPARALLEL禁用了-j并行,因为部分构建命令会创建在并行下互相冲突的临时文件,运行make generate/make protobuf时不要加-j

下一步

生成结果通过 diff 检查和测试验证后,就按 CONTRIBUTING.md 的 PR 流程提交;如果改动是面向用户的,还需按该文档用npx changie new创建 change file。

【免费下载链接】terraformTerraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.项目地址: https://gitcode.com/GitHub_Trending/te/terraform

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询