Skip to content

共享包

四个一方包 packages/dn42_* 是 Control Server 与 Node Agent 共用的地基:协议模型、渲染、文件产物、公共工具。本文讲它们的分层、依赖方向与各自职责。字段细节见 ../reference/desired-state.md

依赖方向

dn42_common 是无上游依赖的叶子。dn42_schemas 只依赖 common。dn42_templates 依赖三者(产出 RenderedFile)。无循环依赖。Python 温备控制面(apps/control-server)用 schemas(校验/合成);Node Agent 用全部四个(渲染 + 规划 + 执行)。主控制面(TS 面)不消费这些包,见下文

dn42_schemas —— 协议模型

所有跨组件传输的数据结构,基于 Pydantic v2。基类 StrictModelbase.py):extra="forbid"(拒未知字段)+ frozen=True(不可变)+ canonical_json() / canonical_sha256()(稳定序列化,用于内容寻址)。

文件内容
desired_state.pyDesiredState 顶层 + validate_references + 四个 _normalize_* 钩子(端口发布、bird socket、DNS runtime、DNS anycast)
network.pyNodeSpec(含 link_local 单源)、InterfaceSpecWireGuardPeerSpec
routing.pyBgpSessionSpecBfdSpecBird2ConfigSpecInternalTopologySpecBirdHostSpecDummyInterfaceSpecBgpLargeCommunitySpec
dns.pyDnsSpecDnsZoneSpecDnsRecordSpecDnsForwardSpec
runtime.pyRouterRuntimeSpecRuntimeServiceSpecUnderlayNetworkSpecPortPublishSpecWireGuardPortRangeSpecRpkiSpec 等容器编排模型
agent.pyAgent 协议:注册请求/响应、RuntimeSnapshotReconciliationReportApplyResult、各 Observed*
enums.pyInterfaceKindServiceRoleAddressFamilyApplyStatusBootstrapStatusNodeHealthObservationStatus
testing.py示例 builder(hkg1、本地多节点),供测试与渲染 golden 用

DesiredState 的字段、校验规则、normalize 钩子是单独的参考主题,见 ../reference/desired-state.md

dn42_templates —— 渲染

DesiredState 渲染为节点上的配置文件与脚本。入口 render_desired_state(state) -> list[RenderedFile]desired_state.py)。

产出模板
bird/*.confconfig-bird2/(community_filters、custom_filters、rpki、anycast_services、bird.conf、dn42_peers、ibgp、ospf、ospf_interfaces)
wireguard/<iface>.confconfig-wireguard/interface.conf.j2
coredns/Corefile + coredns/zones/db.<zone>config-coredns/(DNS 启用时)
scripts/bird/*scripts/wg/*config-scripts/(apply / start 脚本)

bird2.pybuild_config_bird2_contextDesiredState 翻译成 BIRD 模板上下文(ownipownnets*_ipsetbird_hostswg_peerslarge_communitiesroute_collectorsrpki_ip 等)——这里就是"loopback / prefixes → OWNIP / ipset"等派生发生的地方(见 ../reference/addressing-model.md)。Jinja 环境用 StrictUndefined(缺变量即报错)+ shell_quote / yaml_quote 过滤器。

router 容器的 Dockerfile 不渲染成文件,由 agent 在内存里从 runtime.router_dockerfile 经 Docker Engine API 生成。

dn42_runtime —— 文件产物与 Dockerfile

文件内容
types.pyRenderedFile(不可变;路径强校验:禁 ..、NUL、绝对路径、Windows 盘符)
docker.pyrender_router_dockerfile()(多阶段 router 镜像模板)
paths.py模板目录发现

写盘计划的执行(原子写 + 删除)由此包提供,被 agent 的 writer 调用。

dn42_common —— 公共工具

无上游依赖的叶子,被其余三包与两个 app 共用。

模块内容
validators/IP / 网络 / link-local、DN42 地址空间(172.20.0.0/14fd00::/8、anycast 段)、ASN、WireGuard key / endpoint、域名、ISO8601、agent token
labels.py容器/网络 label 单源:dn42.manageddn42.node_iddn42.config_hashdn42.component
naming.pynode_project_nameservice_container_name<project>-<service>-1)、agent_id_for
communities.pyDN42 origin region community 编码、国家代码映射
serialization.pycanonical_json_dumps / canonical_sha256_hex(内容寻址哈希)
jinja.pycreate_environmentshell_quoteyaml_quote
io.pyatomic_write_text / atomic_write_json
crypto.pyWireGuard 密钥生成、恢复密钥 seal / unseal(escrow)

labels.pyserialization.py 一起支撑了内容寻址:容器 config_hash 来自容器定义 payload 的 canonical SHA-256,是最小扰动设计的基础(见 architecture.md)。

TS 面的平行再实现

主控制面(TS 面,apps/control-server-ts,Cloudflare Workers)不消费任何 packages/dn42_*——Workers 运行时装不进 Python 包,其所需的校验、模型与哈希是平行再实现:

TS 实现对齐目标
src/validators.tsdn42_common.validators(域名、agent token 形状、拨测目标白名单;错误消息对齐 Python ValueError
src/schemas.tsdn42_schemas 写校验子集的 zod 移植(InterfaceSpec / BgpSessionSpec / WireGuardPeerSpec / DnsRecordSpec 等)
src/crypto.tstoken 哈希与内容摘要(Web Crypto SHA-256,对齐 hash_token 与 wheel 完整性校验)
src/ip.ts前缀规范化(normalizePrefix / isAddressInPrefix
src/services/naming.tsdn42_common/naming.pyagentIdFor 等命名派生)

维护约束:修改 dn42_common / dn42_schemas 的校验或哈希规则时,必须同步修改 TS 侧对应实现,否则两面对同一输入的接受集与摘要口径会分叉。一致性由 apps/control-server-ts/parity/ 的对拍 harness 护航(parity_py.py / parity_ts.mts:两面各自组装 DesiredState 快照,归一化后逐字节 diff)。