news 2026/9/17 3:14:08

Velero 开发指南:生成文件、单元测试与依赖管理实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Velero 开发指南:生成文件、单元测试与依赖管理实战

Velero 开发指南:生成文件、单元测试与依赖管理实战

【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero

Velero(VMware Tanzu Velero)是 Kubernetes 生态中用于备份、恢复与迁移集群应用及持久化卷的开源工具,其仓库同时托管着 CLI、server、插件 gRPC 接口与 CRD 定义等多类代码资产。本文基于 site/content/docs/v1.1.0/development.md 展开,系统梳理 Velero 开发工作流中"生成文件(Generated Files)— 单元测试 — 依赖管理"三条核心主线:何时必须重新生成代码、如何一键更新、如何用make verify校验产物一致性、如何跑通make test,以及如何正确增删改第三方依赖。读完本文,你将能快速上手 Velero 的本地开发闭环,并在提交 PR 前准确执行仓库约定的检查流程。

一、为什么 Velero 需要"生成文件"

Velero 是一个典型的 Kubernetes Go 项目,大量代码不是手写的,而是由工具从"单一事实来源"(source of truth)自动生成:

  • clientset / listers / shared informers:由 Kubernetes 代码生成器(code-generator)根据pkg/apis/velero/v1pkg/apis/velero/v2alpha1等 API 类型定义生成,是访问 Velero 自定义资源(Backup、Restore、Schedule、BackupStorageLocation 等)的类型安全客户端;
  • 文档:CLI 命令帮助与站点文档中的一部分内容由源码生成;
  • Protobuf / gRPC 类型:插件系统(pkg/plugin/proto下的BackupItemAction.protoRestoreItemAction.protoObjectStore.protoVolumeSnapshotter.protoPluginLister.protoShared.proto等)的消息与服务定义,通过 protoc 编译为pkg/plugin/generated下的 Go 代码。

因此,改动这些"事实来源"后,必须同步重新生成产物,否则客户端、文档与 gRPC 代码会与实际类型定义脱节。开发文档在 site/content/docs/v1.1.0/development.md 中明确给出了需要触发重新生成的三种情形。

二、何时需要运行make update

按开发文档约定,当你做出以下任意一类改动后,必须运行make update重新生成文件:

改动类型示例
新增 / 修改 / 删除命令行 flag 及其帮助文本velero backup create增加一个新参数
新增 / 修改 / 删除命令或子命令新增一个子命令或调整cmd/cli下的命令结构
新增 API 类型pkg/apis/velero/v1(或v2alpha1)中新增自定义资源类型及字段

make update内部到底做了什么

从仓库根目录 Makefile 看,update目标实际是在构建容器内执行 hack/update-all.sh:

update: ## Run all update scripts @$(MAKE) shell CMD="-c 'hack/update-all.sh'"

而 hack/update-all.sh 会依次执行hack/下所有update-*.sh脚本,当前仓库包含:

  • hack/update-1fmt.sh:对所有 Go 文件执行gofmt -s,并用goimports -local github.com/vmware-tanzu/velero统一 import 分组;
  • hack/update-2proto.sh:调用 protoc,将pkg/plugin/proto下的.proto定义编译到pkg/plugin/generated(含--go_out--go-grpc_out两路输出);
  • hack/update-3generated-crd-code.sh:使用controller-gen生成 v1、v2alpha1 两套 CRD 到config/crd/v1/basesconfig/crd/v2alpha1/bases,并生成 RBAC(rbac:roleName=velero-perms);
  • hack/update-4generated-issue-template.sh:编译 hack/issue-template-gen/main.go 并生成 GitHub issue 模板。

其中 proto 脚本对工具链版本有明确要求:需要 protoc(Protocol Buffers 编译器)以及protoc-gen-go插件 v1.0.0。开发文档特别强调,只有当你"新增 / 修改 / 删除 protobuf 消息或服务定义"时,才需要走这条独立的 generate-proto.sh 流程(该脚本已被封装进update-*.sh链路)。

实用提示:仓库还提供了make update-crd快捷目标,仅执行 hack/update-3generated-crd-code.sh,用于只改 CRD 时快速迭代(见 Makefile 中注释"for development purpose only")。

与当前源码结构的印证

从当前仓库结构看,生成产物的输入与输出清晰对应:

  • 输入:API 类型定义位于 pkg/apis/velero(v1/v2alpha1/shared/),插件 proto 定义位于 pkg/plugin/proto;
  • 输出:CRD 清单位于 config/crd(v1/v2alpha1/下的bases),生成代码位于 pkg/plugin/generated 等目录。

这些生成目录在 hack/update-1fmt.sh 中被显式排除(-not -path '*/generated/*' -not -name 'zz_generated*' -not -path '*/mocks/*'),说明格式化脚本只处理手写代码,生成代码保持工具输出原样,进一步印证了"生成物不得手改"的工程约定。

三、用make verify校验生成产物是否最新

如果担心本地改动后忘记重新生成,或者想检查一份补丁里生成文件是否与源码一致,开发文档给出的答案是:

make verify

make verify在构建容器内执行 hack/verify-all.sh,该脚本会运行hack/下所有verify-*.sh,当前仓库的核心校验包括:

  • hack/verify-fmt.sh:以--verify模式调用update-1fmt.sh,即gofmt -dgoimports -d做差异比对而非写入;
  • 对应的 CRD 一致性校验:通过重新生成后与仓库中现有产物 diff,确保 clientset、listers、shared informers、CRD 与文档全部处于最新状态。

一旦校验失败,脚本会提示Please run 'make update'(参见 hack/update-1fmt.sh 中的失败分支)。这也是 Velero CI 的守门环节之一——Makefile 中的ci目标依次执行verify-modulesverifyalltest,将生成物一致性检查放在测试之前。

四、运行单元测试:make test

开发文档给出的测试命令极其简洁:

make test

但背后是一条完整、可复现的测试链路。从 Makefile 看:

test: build-dirs ## Run unit tests ifneq ($(SKIP_TESTS), 1) @$(MAKE) shell CMD="-c 'hack/test.sh $(WHAT)'" endif

其中make shell会以当前用户身份(-u $$(id -u):$$(id -g))在 Velero 构建镜像中挂载仓库目录运行,隔离了宿主机 Go 工具链差异;$(WHAT)变量可传参限定测试范围。

实际执行 hack/test.sh 时:

  1. 设置CGO_ENABLED=0,保证静态编译、测试环境纯净;
  2. 默认收集./pkg/..../internal/..../cmd/...下所有包,并排除pkg/builderpkg/apispkg/testpkg/generatedpkg/plugin/generatedmocksinternal/restartabletest等纯辅助/生成目录;
  3. 执行go test -vet="atomic,bool,buildtags,directive,errorsas,ifaceassert,nilfunc,stringintconv,tests" -installsuffix "static" -short -timeout 1200s -coverprofile=coverage.out,即短模式测试 + 1200 秒超时 + 覆盖率输出coverage.out

脚本注释中还记录了一个有价值的工程细节:升级 controller-runtime 后,在容器内以非 root 用户跑 envtest 会因/目录不可写而 panic,因此通过XDG_CACHE_HOME=/tmp/规避缓存目录权限问题。这解释了为什么测试必须通过构建镜像执行,而不是直接go test ./...

本地测试变体

  • make test WHAT=./pkg/controller/...:把WHAT传给hack/test.sh,仅测试指定包(例如只跑 backup controller 相关测试);
  • make test-local:不经容器、直接在宿主机调用hack/test.sh $(WHAT),适合已配置好 Go 环境的机器;
  • make lint/make local-lint:执行 hack/lint.sh,与测试互补。

仓库中每个核心包都配有同名_test.go,例如 pkg/controller/backup_controller_test.go、pkg/backup/backup_test.go、pkg/restore 下的测试文件,覆盖了 Backup/Restore 状态机、item 收集与插件调用等核心逻辑,可作为理解"什么行为算被测试覆盖"的参考样例。

五、Vendor 依赖管理

开发文档将依赖管理单列一节,指向 v1.1.0 时代的配套文档 vendoring-dependencies.md。该文档说明当时 Velero 使用dep(golang/dep)管理 vendor 依赖:

  • 新增依赖:运行dep ensure(可加-v查看详细输出);
  • 更新既有依赖:运行dep ensure -update <pkg> [<pkg> ...],可同时更新一个或多个包。

需要说明的是,这是 v1.1.0 文档所对应的历史事实。从当前仓库根目录 go.mod 与 go.sum 的存在可以推断,项目后续已迁移到 Go Modules 体系:现在由make modules(即go mod tidy)整理依赖,Makefile 中的verify-modules目标会校验go.modgo.sum是否有未提交的变更。因此,在当前版本上开发时应优先使用 Go Modules 工作流,历史文档中的dep命令仅作版本演进参考。

六、一条完整的本地开发闭环

综合开发文档与 Makefile,一次典型的 Velero 本地开发与提交流程如下:

# 1. 修改代码(API 类型 / CLI flag / 命令 / proto 定义) # 2. 重新生成所有派生文件 make update # 3. 校验生成产物、格式与依赖是否一致 make verify make verify-modules # 4. 运行单元测试 make test # 5. (可选)在构建容器内执行完整 CI 检查 make ci

这套流程与make civerify-modules verify all test)的顺序一一对应,保证提交前所有自动生成的文件、格式、依赖与测试均处于绿色状态。对只改了 CRD 的快速迭代,可先用make update-crd缩小范围;对只需本地快速验证格式的场景,可用make local-lint跳过容器。

七、结语

Velero 的development.md用四段话定义了生成、校验、测试与依赖四条开发纪律:make update负责把 API/CLI/proto 的改动同步到生成代码,make verify负责守门,make test提供可复现的单元测试环境,依赖管理则由dep演进为 Go Modules。理解这四条纪律背后的脚本链路(hack/update-all.sh、hack/verify-all.sh、hack/test.sh),就等于掌握了 Velero 仓库协作的"隐性约定",无论是提交新功能还是修复 Bug,都能以最小摩擦通过 CI 检查。

【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 3:12:39

Coze高阶版核心价值:从AI玩具到生产级工作流的跃迁

1. 这不是“要不要充会员”的选择题&#xff0c;而是你用扣子&#xff08;Coze&#xff09;到底想解决什么问题的判断题最近两周&#xff0c;我连续被6个不同行业的朋友问到同一个问题&#xff1a;“扣子&#xff08;Coze&#xff09;值得付费吗&#xff1f;”——注意&#xf…

作者头像 李华
网站建设 2026/9/17 3:12:32

int8量化与FLOPs/TOPS解析:AI模型边缘部署核心指标

1. 这些缩写不是“黑话”&#xff0c;是AI落地现场每天要掰开揉碎算的账int8、FLOPS、FLOPs、TOPS——这四个词&#xff0c;你可能在模型部署文档里扫过一眼&#xff0c;在芯片参数表上瞥过一回&#xff0c;在同事抱怨“量化后精度掉太多”时听到过一次。但它们真不是术语堆砌出…

作者头像 李华
网站建设 2026/9/17 3:11:55

用Spirent TestCenter做RFC2544时延测试:原理、配置与避坑指南

做网络设备测试这些年&#xff0c;RFC2544这四个字几乎天天挂在嘴边。吞吐量、时延、丢包率、背靠背&#xff0c;一套跑完基本能给交换机、路由器甚至是防火墙写一份“体检报告”。四个测试项里面&#xff0c;我最开始最不当回事的就是时延&#xff0c;觉得它又不直接决定“合格…

作者头像 李华
网站建设 2026/9/17 3:11:46

嵌入式OTA防砖核心:A/B分区与Ping-Pong回滚机制详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 3:11:27

Redis五大核心数据类型详解:从选型到实战的完全指南

如果你刚接触Redis&#xff0c;最先要弄明白的就是它的数据类型。我遇到过很多同学&#xff0c;装好Redis就只会SET/GET&#xff0c;把对象序列化成一个JSON字符串塞进去&#xff0c;等要查某个字段的时候&#xff0c;只能整个取出来再反序列化&#xff0c;内存和性能都被浪费了…

作者头像 李华
网站建设 2026/9/17 3:10:59

UWB脉冲无线电测距:从物理原理到厘米级工程落地

1. UWB不是新东西&#xff0c;但它现在重新变得值钱如果你最近拆过一个新款的手机、钥匙或者跟踪器&#xff0c;很可能在里面看到过一颗不起眼的芯片&#xff0c;丝印上写着某个型号&#xff0c;旁边绕着细细的PCB天线。这东西大概率就是一颗超宽带脉冲无线电&#xff08;Ultra…

作者头像 李华