ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Istio 测试数据集(pkg/test/datasets)完全指南:目录结构、命名约定与配置校验测试实战

Istio 测试数据集(pkg/test/datasets)完全指南:目录结构、命名约定与配置校验测试实战 Istio 测试数据集pkg/test/datasets完全指南目录结构、命名约定与配置校验测试实战【免费下载链接】istioConnect, secure, control, and observe services.项目地址: https://gitcode.com/GitHub_Trending/is/istioIstio 源码仓库中维护着一套专用于测试的数据集test data set它以目录 约定式文件命名的方式组织输入与期望输出让配置解析、校验类测试可以脱离繁琐的逐条硬编码用例以数据驱动的方式声明式展开。本文围绕仓库内 pkg/test/datasets/Readme.md 展开系统讲解这套数据集的目录结构、文件命名约定、阶段化stages扩展机制、期望文件格式以及如何新增一套测试数据同时结合当前仓库中真实的消费方Pilot 集成测试、validation 数据集说明其在 Istio 校验体系中的实际落地方式。读完本文你将掌握向 Istio 仓库贡献校验类测试数据、理解其约束与触发流程的完整方法。说明原文档自述部分内容已过时仅为参考保留但数据集本身仍在使用。本文在忠实继承原约定Input/Golden 思想的同时会以当前仓库实际状态为准澄清哪些约定仍有效、哪些已被新机制取代。一、数据集的设计初衷以输入/输出视角测试配置逻辑原文档开宗明义地指出Galley 测试数据集设计为从输入/输出inputs/outputs的视角测试配置处理链路。其核心做法是在仓库中内嵌一组输入文件input files与期望输出文件golden files即 golden 文件用于和实际输出做精确比对测试程序遍历这些文件运行待测逻辑后与 golden 结果比对从而完成自动化测试。这种做法的好处非常明显测试即文档一个testname.yaml配一个testname_expected.json本身就是一组输入—期望输出的可读用例审查者无需阅读代码即可判断测试意图新增用例零代码成本贡献者只需新增一对文件而无需改动任何 Go 测试代码回归覆盖天然累积每修复一个 bug即可沉淀一组新的输入/输出文件防止同类问题再次出现。值得注意的是原文中提到的galley/testdatasets/area/dataset/...结构对应的 Galley 组件在历史演进中已不再作为独立目录存在。从当前仓库结构看原数据集机制最直接、仍然活跃的继承者是 pkg/test/datasets/validation其下包含dataset/目录与dataset.go入口以及引用它的 tests/integration/pilot/validation_test.go。本文后续章节会详细对应讲解。二、数据集目录结构原约定与当前形态对照原文档给出的通用目录/文件结构如下# Area specific test data set. galley/testdatasets/area/dataset/... # Custom entry-point code for the data set, in a given area. galley/testdatasets/area/dataset.go # Generated Go file for test assets galley/testdatasets/area/dataset.gen.go各组成部分的含义dataset/目录存放某测试区域area专属的数据文件是测试用例的原料库dataset.go该数据集的自定义入口代码负责把dataset/下的资源暴露给测试程序dataset.gen.go原设计下用于打包测试资产的生成式 Go 文件早期通过代码生成把 YAML 资源嵌入二进制。在当前仓库中这一结构演进为pkg/test/datasets/validation/ ├── dataset.go # 数据集入口使用 go:embed 嵌入 dataset/* └── dataset/ ├── networking-v1-VirtualService.yaml ├── security-v1beta1-AuthorizationPolicy.yaml ├── telemetry-v1-Telemetry.yaml └── ... # 共 32 个 YAML按 group-version-Kind 命名其中 dataset.go 的实现非常简洁核心仅有一行 go:embed 指令package validation import embed // FS embeds the manifests // //go:embed dataset/* var FS embed.FS关键演进点原约定中需要由make go-gen生成dataset.gen.go才能把资源编译进测试程序而当前仓库改用 Go 标准库embed包在编译期直接把dataset/目录下的全部文件打包进validation.FS一个embed.FS不再需要生成步骤。测试代码通过validation.FS.ReadFile(path.Join(dataset, ...))与validation.FS.ReadDir(dataset)读取资源。这说明目录 入口文件的组织思想得以保留生成式 Go 文件这一步已被 go:embed 取代。三、校验类测试数据的文件格式与命名约定原文档以 Conversion Test Data 为例定义了一组测试数据文件集fileset的标准格式。虽然文档聚焦 Conversion转换场景但其约定同样适用于后续的 Validation校验数据集其核心规则如下# Input file for the test输入文件必备 .../dataset/**/testname.yaml # Optional Mesh Config Input file可选网格配置输入 .../dataset/**/testname_meshconfig.yaml # Required expected resources file.必备期望输出资源 .../dataset/**/testname_expected.json各文件职责文件后缀是否必需作用测试输入testname.yaml✅ 必需单个或多个配置资源YAML作为待测逻辑的输入网格配置testname_meshconfig.yaml⚪ 可选提供该用例专属的 Mesh 全局配置如协议、流量策略默认值等影响配置解析结果期望输出testname_expected.json✅ 必需golden 文件声明测试通过时应得到的最终资源集合3.1 多阶段multi-stage测试原文档指出测试文件结构支持多阶段执行以_stageNo数字后缀标识执行顺序。这对同一个输入经过多次变更最终收敛的测试场景非常有用# Input file for the test .../dataset/**/testname_stageNo.yaml .../dataset/**/testname_stageNo_meshconfig.yaml .../dataset/**/testname_stageNo_expected.json示例某测试foo分两个阶段执行——# 第一阶段文件。meshconfig 会延续到下一阶段carries over to the next stage .../dataset/**/foo_0.yaml .../dataset/**/foo_0_meshconfig.yaml .../dataset/**/foo_0_expected.json # 第二阶段文件 .../dataset/**/foo_1.yaml .../dataset/**/foo_1_expected.json多阶段约定的关键语义阶段按_0、_1……编号递增执行前一阶段的输出作为后一阶段的输入上下文MeshConfig 具有延续性注释明确指出Meshconfig carries over to the next stage即若第二阶段未提供新的_meshconfig.yaml则沿用第一阶段设定的网格配置——这正是把foo_1阶段省略 meshconfig 文件的原因期望输出逐阶段独立声明用于精确断言每一步转换/校验后的中间态与终态。3.2 忽略测试.skip并非所有用例都需要永远执行。原文档规定只需在同目录下新增一个与输入文件同名的.skip文件即可跳过该测试# Input file for the test .../dataset/**/testname.yaml # Optional file, indicating that the test should be skipped. .../dataset/**/testname.skip该机制的价值在于当某个用例因外部依赖如依赖的组件未就绪、行为尚未实现暂时无法通过时可以保留用例文件但不让它阻塞 CI待条件满足后删除.skip文件即可一键恢复避免删用例丢覆盖的两难。四、期望文件golden的 JSON 结构原文档给出了期望输出文件的规范结构。它顶层是一个名为collection的数组每个元素含Metadata与Body两个字段{ collection: [ { Metadata: { name: output-resource-1 }, Body: {} }, { Metadata: { name: outout-resource-2 }, Body: {} } ] }字段语义解析collection期望输出的资源集合测试程序会将实际输出与collection中声明的资源逐一比对Metadata.name期望资源的名称用于将实际输出与期望条目一一对应Body资源的完整主体内容在原文档中为空对象占位当Body写全时它实际上就是对资源完整 spec 的 golden 快照测试据此做深度比对从而捕获任何意料之外的字段级变更。五、如何新增一套测试数据原流程与现代做法原文档给出的新增测试数据文件集三步流程如下Create a new, appropriately named folder underdataset.Create the input, expected, and (optionally) the mesh config files.RunBUILD_WITH_CONTAINER1 make go-genfrom the repository root.即在dataset/下新建一个命名恰当的目录对应新的测试场景创建输入文件、期望文件以及可选的meshconfig 文件从仓库根目录执行BUILD_WITH_CONTAINER1 make go-gen重新生成测试资产 Go 文件。对照当前仓库第 3 步已发生变化。仓库根 Makefile.core.mk 中go-gen目标依然存在本质是go generate ./...但 validation 数据集不再需要任何生成产物——go:embed会在编译期自动把新增 YAML 文件纳入validation.FS。因此现代新增流程简化为在 pkg/test/datasets/validation/dataset 下新建或编辑文件按group-version-Kind.yaml命名内容为一条合法且能通过校验的 Istio 配置资源直接运行消费方测试参见第六节无需执行代码生成命令。六、当前仓库中数据集的真实消费者Webhook 校验集成测试原文档所述输入/输出视角测试的思路在当前仓库中最具代表性的落地是 tests/integration/pilot/validation_test.go。该文件位于tests/integration/pilot目录带//go:build integ构建标签属于集成测试是validation 数据集的实际消费方测试的是配置校验 Webhook 与 Kubernetes 的真实集成。6.1 数据集如何被加载测试代码定义了一个testData类型通过validation.FS读取文件func (t testData) load() (string, error) { by, err : validation.FS.ReadFile(path.Join(dataset, string(t))) if err ! nil { return , err } return string(by), nil } func loadTestData(t framework.TestContext) []testData { entries, err : validation.FS.ReadDir(dataset) ... for _, e : range entries { result append(result, testData(e.Name())) } return result }从源码可以看出测试启动时会自动遍历dataset/目录下的全部 YAML 文件无需在测试代码里枚举用例名——新增一个数据集文件即自动获得一个测试用例这正是数据驱动的体现。6.2 每个数据文件会跑两个用例TestValidation的核心逻辑是对目录中每一个数据文件分别以validtrue与validfalse两个子测试执行 dry-run 与 wet-runfor _, valid : range []bool{true, false} { t.NewSubTest(string(d) - fmt.Sprint(valid)).Run(...) }validtrue子测试名...-true直接应用原始 YAML期望 dry-run 校验通过validfalse子测试名...-false先给 YAML 打上一个特殊内部注解再期望 dry-run 被拒绝if !valid { ym, err yml.ApplyAnnotation(ym, constants.AlwaysReject, true) ... } dryRunErr : cluster.ApplyYAMLFilesDryRun(ns.Name(), applyFiles...)这里的constants.AlwaysReject定义在 pkg/config/constants/constants.go是一个始终会被校验 Webhook 拒绝的特殊内部注解// AlwaysReject is a special internal annotation that is always rejected in the validation webhook. This is used for // ... AlwaysReject internal.istio.io/webhook-always-reject其拒绝逻辑位于 pkg/config/validation/validation.go一旦在配置注解中发现该 key立即返回错误拒绝。结合测试可以发现一个精妙设计validation 数据集中的每个 YAML 本身都是合法配置确保合法资源一定放行这一半边而 拒绝 半边则靠AlwaysReject注解强制触发从而在不引入大量非法 YAML 的前提下双向验证 Webhook 的准入判定链路可放行的未被误伤、带拒绝标记的必然被拒。6.3 拒绝原因与 dry-run/wet-run 一致性断言测试对拒绝原因的校验同样严谨。由于 Webhook 返回的错误并非 K8s 类型化错误断言只匹配字符串字面量denied the request并明确注释this explicitly does NOT catch OpenAPI schema rejections - only validating webhook rejections即刻意不捕获 OpenAPI schema 拒绝只验证 Webhook 自身拒绝denied : func(err error) bool { if err nil { return false } return strings.Contains(err.Error(), denied the request) }随后按四种组合逐一断言场景断言dry-run 出错 且validtrue若被denied(...)捕获 → 合法配置被误拒Faildry-run 成功 且validfalse非法配置竟被放行Faildry-run 出错 且validfalse必须是 Webhook 的denied拒绝否则 Faildry-run 与 wet-run 结果不一致dry-run 报错而 wet-run 通过或反之均 Fail最终还会执行真实的 wet-runcluster.ApplyYAMLFiles并做资源清理确保 dry-run 的判定结果与真实下发结果保持一致杜绝dry-run 通过、真正 apply 失败或相反的情况逃过测试。6.4 CRD 覆盖完整性守护TestEnsureNoMissingCRDs除执行校验外validation_test.go 中还有一个机制性极强的测试TestEnsureNoMissingCRDs它保证Pilot 已知的每一个 CRD 都有对应的校验测试数据从collections.Pilot.All()收集 Pilot 认识的全部资源group/version/kind并合入GroupVersionAliasKinds()提供的别名应对多版本 API 兼容场景剔除在 Istio 之外校验的 Gateway API 资源gateway.networking.k8s.io/v1|v1beta1下的 Gateway/GatewayClass/HTTPRoute/TCPRoute/TLSRoute/ReferenceGrant 等以及 K8s 原生资源Endpoints、Pod、Service、Deployment、CRD 本身等ignoredCRDs反向解析所有数据集文件里的apiVersion与kind构造tested集合双向比对既有 CRD 缺少测试数据、或存在不属于任何已知 CRD 的多余测试数据都会直接Errorf失败。其注释给出了明确的工作指引If youre breaking this test, it is likely that you need to update validation tests by either adding new/missing test cases, or removing test cases for types that are no longer supported.即当新增/移除 API 时本测试会强制提醒同步更新 validation 数据集从机制上防止 CRD 校验覆盖出现缺口。七、validation 数据集的真实内容一览当前 pkg/test/datasets/validation/dataset 目录共包含32 个 YAML 文件覆盖 Istio 配置模型的主流 API 组与版本例如API 组版本Kind示例networking.istio.iov1 / v1alpha3 / v1beta1VirtualService、DestinationRule、Gateway、ServiceEntry、Sidecar、WorkloadEntry、WorkloadGroup、EnvoyFilter、ProxyConfigsecurity.istio.iov1 / v1beta1AuthorizationPolicy、PeerAuthentication、RequestAuthenticationextensions.istio.iov1alpha1WasmPlugin、TrafficExtensiontelemetry.istio.iov1 / v1alpha1Telemetry以 networking-v1-VirtualService.yaml 为例数据集中的文件是简洁、合法、可被校验通过的配置样例apiVersion: networking.istio.io/v1 kind: VirtualService metadata: name: valid-virtual-service spec: hosts: - c http: - route: - destination: host: c subset: v1 weight: 75 - destination: host: c subset: v2 weight: 25这类样例同时具备三重身份Webhook 校验集成测试的输入、CRD 覆盖守卫的证据、以及供开发者快速查阅的最小可用 API 示例不同版本的相同 Kind 并排存放也便于对比 v1 / v1beta1 / v1alpha3 之间的字段演进。八、给贡献者的实操清单综合原文档约定与当前仓库实现向 Istio 仓库贡献校验类测试数据时可按以下清单操作仓库为只读以下仅为本地开发/提交前自检流程确认位置当前数据集根目录为 pkg/test/datasets/validation/dataset不再使用旧的galley/testdatasets路径遵循命名使用group-version-Kind.yaml连字符分隔命名文件例如networking-v1beta1-ProxyConfig.yaml保证内容合法文件内为一条可通过校验的合法配置参见 networking-v1-VirtualService.yaml 的书写风格版本对齐如需覆盖新 API/新版本/新 Kind同时补充对应文件否则TestEnsureNoMissingCRDs会报CRD does not have a validation test若移除不再支持的 API也应同步删除对应测试数据避免报Unrecognized validation test data found无需生成步骤新增文件后直接运行tests/integration/pilot下带integ标签的校验测试即可文件会被go:embed自动打包并自动生成-true/-false两个子测试参考历史约定若开发面向的是历史上 Galley 输入/输出视角的测试基建应遵循testname.yaml_expected.json可选_meshconfig.yaml的配套格式、_stageNo多阶段与 meshconfig 跨阶段延续语义、以及同名.skip文件忽略机制——这些约定仍保留在 pkg/test/datasets/Readme.md 中作为权威参考。结语Istio 的测试数据集是一套以文件为用例、以约定为框架的轻量测试基建从 Galley 时代的 Input/Golden 输入输出比对到今天go:embed驱动的 Webhook 校验集成测试其内核始终是把测试意图沉淀为可读的 YAML/JSON 资源让覆盖范围随文件自然生长。理解 pkg/test/datasets/Readme.md 中记载的命名约定与结构规范再对照 validation_test.go 的消费逻辑你就能既写出规范的数据集又清楚每一份数据最终会在哪条校验链路上发挥作用。【免费下载链接】istioConnect, secure, control, and observe services.项目地址: https://gitcode.com/GitHub_Trending/is/istio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表