首页 / 资讯中心 / 文章详情

深入解析 Wing 语言中的 CDKTF 集成:从 `bring_cdktf.test.w` 编译快照看三方 Terraform 库的引入机制

深入解析 Wing 语言中的 CDKTF 集成:从 `bring_cdktf.test.w` 编译快照看三方 Terraform 库的引入机制 ★ FEATURED ARTICLE
编程语言编译器云原生语言运行时【免费下载链接】wingA programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡项目地址https://gitcode.com/gh_mirrors/wi/wing点击查看免费下载导读Wing 语言winglang的一大核心能力是直接复用现有 JavaScript/TypeScript 生态中的 jsii 库其中就包括 HashiCorp 的 CDK for TerraformCDKTF及其 AWS provider 绑定。本文以仓库中 bring_cdktf.test.w 编译快照 为解剖对象逐层拆解一个同时引入cdktf与cdktf/provider-aws的 Wing 程序在tf-aws目标下编译产出的preflight.cjs、main.tf.json与inflight文件并深入源码解释bring机制、ClassFactory资源实例化、nodeof可视化元数据以及 CDKTF 非标准构造如S3Backend的兼容处理。读完本文你将掌握 Wing 程序如何桥接 CDKTF 生态、其合成产物为何如此组织以及 Hangar 快照测试如何验证这一过程。一、测试用例全景一份同时桥接 CDKTF 与 AWS Provider 的 Wing 程序快照的源头是仓库中的 tests/valid/bring_cdktf.test.w完整源码如下bring cdktf/provider-aws as aws; bring cdktf as cdktf; let bucket new aws.s3Bucket.S3Bucket( bucketPrefix: hello, versioning: { enabled: true, mfaDelete: true, }, ) as Bucket; nodeof(bucket).color pink; class Foo { new() { // Test importing a non-standard Construct that doesnt have a scope/id property pair as its first two arguments // Some of cdktfs backend constructs are like this. new cdktf.S3Backend(this, cdktf.S3BackendConfig {bucket: foo, key: bar}); } }这份 19 行的程序涵盖了 Wing 与 CDKTF 集成的四个关键点代码片段技术点bring cdktf/provider-aws as aws;引入 jsii 三方库并为其命名空间起别名bring cdktf as cdktf;同时引入 CDKTF 核心库new aws.s3Bucket.S3Bucket(...)直接实例化 AWS provider 中的原生 Terraform 资源构造nodeof(bucket).color pink;通过nodeof设置构造在可视化界面中的显示颜色new cdktf.S3Backend(this, cdktf.S3BackendConfig {...})在自定义类中实例化不符合标准(scope, id)签名的 CDKTF 后端构造该文件位于tests/valid/目录属于 Wing 编译器与 SDK 的合法用例valid corpus其命名以.test.w结尾说明它同时是 Hangar 测试的入口文件entrypoint会同时被wing compile -t tf-aws与wing test -t sim两条测试路径覆盖。二、快照的来龙去脉Hangar 测试框架如何生成这份编译快照要读懂快照首先要明白快照本身是怎么被制造出来的。2.1 Hangar 是 Wing 的端到端测试套件Hangar 位于 tools/hangar是 Wing 工具链的端到端测试套件。它的工作方式是把tests/valid、tests/sdk_tests、tests/doc_examples中的每个.w文件生成一个对应的 vitest 用例分别执行wing compile -t tf-aws编译到 AWS Terraform 目标wing test -t sim在模拟器目标上运行测试生成用例的逻辑在 tools/hangar/src/generate_tests.ts其中对每个.w文件生成的测试骨架如下test(wing compile -t tf-aws, async () { await compileTest(${sourceDir}, ${filename}, ${env}, ${includeJavaScriptInSnapshots}, ${skipMarkdownSnapshot}, ${args}); }); test(wing test -t sim, async () { await testTest(${sourceDir}, ${filename}, ${env}, ${skipMarkdownSnapshot}); });2.2 快照的收集与落盘流程真正执行编译并收集产物的是 tools/hangar/src/generated_test_targets.ts 中的compileTest在源码目录下以wing compile -t tf-aws file执行编译产物落入target/basename.tfaws/收集main.tf.json经sanitize_json_paths清洗删除terraform字段、抹掉绝对路径与 CDKTF 版本号遍历.wing目录仅保留preflight.、inflight.、extern/、proc、.Struct.js开头的文件并排除.map源码映射文件还会校验产物中不存在绝对路径的require见 generated_test_targets.ts防止快照被本机绝对路径污染。随后 tools/hangar/src/utils.ts 的createMarkdownSnapshot把这些文件按名称排序写入以文件名_用例_目标.md命名的 Markdown 快照即本篇文章的核心文档# [bring_cdktf.test.w](https://link.gitcode.com/i/80fafe007adb7e1f4be90791d01264b0) | compile | tf-aws其标题格式为[wing 文件] | 用例类型 | 目标平台文档内按## 文件名组织各产物内容。这份快照的姊妹篇是 bring_cdktf.test.w_test_sim.md记录了wing test -t sim的输出pass ─ bring_cdktf.test.wsim (no tests)说明该用例没有定义 test 块。三、产物逐个解剖一次 CDKTF 编译究竟生成了什么快照共包含三个产物覆盖了 Wing 编译到tf-aws目标时的典型输出形态。3.1inflight.Foo-1.cjs飞行态类的最小化封装use strict; const $helpers require(winglang/sdk/lib/helpers); const $macros require(winglang/sdk/lib/macros); module.exports function({ }) { class Foo { } return Foo; } //# sourceMappingURLinflight.Foo-1.cjs.map这个文件值得注意的细节空的捕获列表function({ })中的花括号表示该飞行态类没有捕获任何预飞态数据。源程序中的Foo类仅在new()构造中创建了S3Backend构造属于预飞行为因此飞行态类体为空CommonJS 封装产物以 CJS 模块导出工厂函数运行时由 SDK 的 helpers 按需加载配合源码映射文件sourceMappingURL快照中不保留 map 本体命名规则inflight.Foo-1.cjs中的-1是编译器为同名 inflight 类生成的序号后缀用于在同一个preflight.cjs作用域内区分不同捕获闭包。3.2main.tf.json可被 Terraform 直接消费的合成配置{ //: { metadata: { backend: local, stackName: root }, outputs: {} }, provider: { aws: [ {} ] }, resource: { aws_s3_bucket: { Bucket: { //: { metadata: { path: root/Default/Default/Bucket, uniqueId: Bucket } }, bucket_prefix: hello, versioning: { enabled: true, mfa_delete: true } } } } }对照源程序的参数可以清楚看到 Wing 的命名习惯到 Terraform 属性的映射Wing 源码main.tf.json 中的形态bucketPrefix: hellobucket_prefix: hellocamelCase → snake_caseversioning.enabled: trueversioning: {enabled: true}versioning.mfaDelete: truemfa_delete: trueas Bucket资源逻辑 IDBucket且uniqueId与之一致—自动生成path: root/Default/Default/Bucket反映构造树路径几点深层解读provider.aws的空对象配置来自 target-tf-aws/app.tsApp构造器会无条件new AwsProvider(this, aws, {})这也是每个 tf-aws 应用都自带 AWS provider 的原因bucket_prefix而不是bucket这里直接透传了用户指定的bucketPrefix与 SDK 内置cloud.Bucket的自动命名策略不同——后者会通过ResourceNames.generateName生成随机前缀见 target-tf-aws/bucket.ts而原生 CDKTF 资源完全由用户控制参数元数据//块是 CDKTF 合成产物Synth 输出的固有格式其中uniqueId用于 Terraform 状态文件中的资源寻址。3.3preflight.cjs预飞代码的完整编译形态快照中这段产物是最有价值的部分它把 Wing 源码翻译成了可直接运行的 Node.js 程序use strict; const $stdlib require(winglang/sdk); const $macros require(winglang/sdk/lib/macros); const $platforms ((s) !s ? [] : s.split(;))(process.env.WING_PLATFORMS); const $outdir process.env.WING_SYNTH_DIR ?? .; const $wing_is_test process.env.WING_IS_TEST true; const std $stdlib.std; const $helpers $stdlib.helpers; const $extern $helpers.createExternRequire(__dirname); const $types require(./types.cjs); const $PlatformManager new $stdlib.platform.PlatformManager({platformPaths: $platforms});这段头部揭示了 Wing 预飞程序的运行时契约环境变量驱动WING_PLATFORMS平台列表以分号分隔、WING_SYNTH_DIR合成输出目录、WING_IS_TEST是否为测试环境、WING_SOURCE_DIR源码目录、WING_ROOT_ID根 ID共同决定了程序的运行上下文PlatformManager从platformPaths加载平台实现并创建ClassFactory。随后是核心的资源创建逻辑const aws require(cdktf/provider-aws); const cdktf require(cdktf); class Foo extends $stdlib.std.Resource { constructor($scope, $id, ) { super($scope, $id); globalThis.$ClassFactory.new(cdktf.S3Backend, cdktf.S3Backend, this, ({bucket: foo, key: bar})); } static _toInflightType() { return require(${$helpers.normalPath(__dirname)}/inflight.Foo-1.cjs)({ }) ; } get _liftMap() { return ({ $inflight_init: [], }); } } const bucket globalThis.$ClassFactory.new(cdktf/provider-aws.s3Bucket.S3Bucket, aws.s3Bucket.S3Bucket, this, Bucket, { bucketPrefix: hello, versioning: ({enabled: true, mfaDelete: true}) }); $helpers.nodeof(bucket).color pink;preflight.cjs的尾部通过PlatformManager.createApp(...)创建 App 并调用synth()最终把构造树落盘为main.tf.json。四、源码级原理$ClassFactory如何桥接 Wing 与 CDKTF 构造preflight.cjs中反复出现的globalThis.$ClassFactory.new(...)是 Wing 接入三方构造的关键管道其实现位于 packages/winglang/sdk/src/core/class-factory.ts。4.1 ClassFactory 的角色public new(fqn: string, ctor: any, scope: Construct, id: string, ...args: any[]): any { const instance this.tryNewInstance(fqn, scope, id, ...args); if (instance) { return instance; } if (ctor) { return new ctor(scope, id, ...args); } throw new NotImplementedError(Unsupported resource type: ${fqn}); }它的职责是先询问当前平台是否对某个 FQN完全限定名提供了覆盖实现override如果没有则退回到构造函数直接实例化。这正是 Wing 中平台可替换资源机制的底层实现——例如同一个cloud.Bucket在sim平台由模拟器实现在tf-aws平台则映射到 S3。4.2 平台的注入点ClassFactory由 platform-manager.ts 的createClassFactory()构建平台实例可以提供newInstance与resolveType两个回调收集后逆序排列使最后一个平台的方法最先被尝试。而createApp会检查globalThis.$ClassFactory只能定义一次见 platform-manager.ts并把工厂注入 App。4.3 两类资源在工厂中的不同路径回到本快照的两个new调用可以看到两种典型路径CDKTF 原生资源$ClassFactory.new(cdktf/provider-aws.s3Bucket.S3Bucket, aws.s3Bucket.S3Bucket, this, Bucket, {...})——FQN 前缀是cdktf/provider-aws平台没有覆盖于是走new ctor(scope, id, ...args)分支直接实例化Wing 的参数命名被逐字透传给 CDKTF 构造CDKTF 后端构造$ClassFactory.new(cdktf.S3Backend, cdktf.S3Backend, this, ({bucket: foo, key: bar}))——注意这里没有传id而是把整个配置对象作为第三个参数。第二种调用揭示了源码注释中的关键设计CDKTF 的S3Backend并不符合 Construct 的(scope, id)前两参签名它的构造签名是(scope, config)。Wing 编译器识别到这一点后在生成的代码里不再强加id参数而是原样传递配置对象——这正是测试引入一个不以scope/id对作为前两个参数的非标准 Construct这句话的落地形态。ClassFactory.new的...args透传设计让这类异构构造得以无缝接入。五、nodeof与可视化元数据Wing 构造树的美化接口源码中的nodeof(bucket).color pink;编译后变为$helpers.nodeof(bucket).color pink;其语义来自 SDK 内部的Node类见 packages/winglang/sdk/src/std/node.ts 的Node.of与 node.ts 的color字段。该color字段的文档注释列出了支持的取值orange、sky、emerald、lime、pink、amber、cyan、purple、red、violet、slate。此外Node还支持title、description、sourceModule、hidden、icon、expanded等可视化属性。这些属性并不影响 Terraform 合成结果快照的main.tf.json中没有任何颜色信息它们的消费方是 Wing Console 等树形可视化工具开发者可以用nodeof(...)在 Wing 代码里直接为应用树中的任意构造标注颜色、标题或图标从而让整个资源树在控制台中更易辨识。这也解释了为何快照的preflight.cjs中会保留这一赋值——它是应用模型Application Tree的一部分只是不进入 IaC 产物。六、从快照反推的可复用实战模式6.1 在 Wing 中引入 CDKTF 库的最小三步安装依赖确保cdktf与目标 provider如cdktf/provider-aws作为 npm 依赖可用Wing 编译器会像解析 jsii 库一样解析它们声明引入bring cdktf/provider-aws as aws; bring cdktf as cdktf;实例化资源直接new aws.s3Bucket.S3Bucket(...)并透传 CDKTF 参数camelCase或new cdktf.S3Backend(this, cdktf.S3BackendConfig {...})创建非标准构造。6.2 对参数映射保持清醒Wing 源码使用 camelCasebucketPrefix、mfaDeleteCDKTF 构造本身也接受 camelCase但合成后的main.tf.json会转换为 Terraform 的 snake_casebucket_prefix、mfa_deleteas Bucket指定的是构造 ID会同时反映到main.tf.json的uniqueId与构造树路径root/Default/Default/Bucket中自定义类中的 CDKTF 构造会被编译进preflight.cjs而该类对应的飞行态形态被剥离成独立的inflight.*.cjs文件捕获列表为空时该文件几乎只剩类骨架。6.3 用快照验证自己的集成如果希望为新的 CDKTF 集成编写类似的回归验证可以直接复用 Hangar 的既有机制把用例放入tests/valid/在 tools/hangar 运行测试生成新的快照createMarkdownSnapshot会按test_corpus/valid/file_compile_tf-aws.md的路径规则落盘。快照中的元数据约定//块、uniqueId、path以及sanitize_json_paths的清洗规则剥离绝对路径、CDKTF 版本号保证了产物在不同机器上的可复现性。七、小结通过这份名为bring_cdktf.test.w_compile_tf-aws.md的快照我们完整还原了一条链路Wing 源码 → wingc 编译 → preflight.cjs inflight 文件 → CDKTF App 合成 → main.tf.json。三个产物各司其职preflight.cjs记录预飞逻辑并通过$ClassFactory桥接 CDKTF 生态inflight.*.cjs承载飞行态类的最小封装main.tf.json则是最终可交付给 Terraform 的 IaC 配置。对开发者而言这份快照既是Wing × CDKTF 互操作的规范示例也是Hangar 快照测试体系的活教材它证明了 Wing 不仅能消费 jsii 库中的标准 Construct也能容忍S3Backend这类不符合常规签名的构造同时借助nodeof让外部资源无缝融入 Wing 的可视化应用树。相关源码与测试均可从本文引用路径在仓库中继续深挖。赞分享编程语言编译器云原生语言运行时【免费下载链接】wingA programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡项目地址https://gitcode.com/gh_mirrors/wi/wing点击查看免费下载相关推荐深入解读 Wing 语言 math.toRadix 的 tf-aws 编译快照从 API 用法到 Hangar 快照测试机制深入解读 Wing 语言 math.toRadix 的 tf aws 编译快照从 API 用法到 Hangar 快照测试机制 本文以仓库快照文档 toradi编程语言编译器云原生语言运行时Wing 语言 bring 别名机制详解从 bring_alias 测试与 tf-aws 编译快照看模块导入Wing 语言 bring 别名机制详解从 bring_alias 测试与 tf aws 编译快照看模块导入 本篇基于 Wing 开源仓库中的 bring_a编程语言编译器云原生语言运行时Wing cloud.Bucket 的 tf-aws 编译产物深度解析从 put.test.w 看 Terraform 快照配置Wing cloud.Bucket 的 tf aws 编译产物深度解析从 put.test.w 看 Terraform 快照配置 本文以 Wing 官方测试框编程语言编译器云原生语言运行时上一篇Apache OpenWhisk 生态模块全景从核心平台到运行时与工具链的模块化架构指南下一篇Qwen2.5-1.5B代码生成实践基于Python的AI编程助手应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站