Salt 执行模块链式调用中的__salt__与__pillar__可用性权威指南【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址: https://gitcode.com/gh_mirrors/sa/salt本文以变更记录 changelog/58420.fixed.md 为切入点系统梳理 Salt 官方开发文档对链式执行模块调用中__salt__与__pillar__可用性的完整约定__salt__在任何函数被调用时已完全填充、同一实例贯穿整条调用链但在__virtual__()内与模块导入阶段并不可靠。读者读完本文将掌握 dunder 字典的生命周期边界、双 Loader 架构的底层成因以及编写可安全复用其他执行模块的开发规范。变更记录背景一次面向模块开发者的文档补全58420.fixed.md记录的是一次纯文档docs-only变更其内容非常聚焦在 doc/topics/development/modules/developing.rst 中正式文档化了__salt__与__pillar__在链式执行模块调用中的可用性约定并明确了一条核心规则——__salt__在任何函数被调用时已完全填充但在__virtual__内部以及模块导入import时刻并不可靠。这条规则看似简单却直接决定了 Salt 模块开发者在什么位置可以安全地调用其他执行模块。本文将从该文档的完整章节出发逐层展开其约束与实现原理。dunder 字典Salt 模块的全局上下文在深入链式调用之前需要先建立对 Salt dunder 字典的基本认知。Salt 通过一组以双下划线包裹的特殊字典向模块注入运行时上下文__opts__、__context__、__grains__、__pillar__、__salt__等均属此类详见 doc/topics/development/modules/developing.rst 的 Dunder Dictionaries 章节。其中与本文主题最相关的两个__salt__包含全部执行模块函数的字典允许模块间互相调用。在 Auth、Beacons、Engines、Execution、Executors、Outputters、Pillars、Proxies、Renderers、Returners、Runners、SDB、SSH Wrappers、State、Thorium 等模块类型中均有定义。典型用法__salt__cmd.run __salt__[network.ip_addrs]()注意在 runner 或 outputter 中__salt__指向的是其他 runner/outputter 模块而非执行模块。__pillar__包含目标 minion 的 pillar 数据。在 Execution、Renderer、Returner、SSH Wrapper、State 模块中被填充。__pillar__与__grains__对所有模块类型都已定义但只在部分模块类型中被实际填充。__opts__包含 master 或 minion 配置文件中的所有选项在所有模块中定义。官方文档建议通过__salt__config.get这类 get 函数读取配置以支持*:*分隔符的字典路径遍历。链式__salt__调用何时完全填充developing.rst中 Chained__salt__calls 一节给出的核心结论是到任意执行模块函数被调用时__salt__已经是一个完全填充fully populated的 loader 字典。这意味着从执行模块内部调用其他执行模块是安全的并且这种调用是**可传递transitively**的# 在某个执行模块内部 __salt__pkg.install上述调用自身又可以依赖pkg.install内部继续调用__salt__[cmd.run]。之所以安全是因为执行 loader 是可重入reentrant的同一个__salt__实例在整条调用链上共享。也就是说链式调用不会创建半初始化的中间状态——__salt__[a.func]()里再调用__salt__[b.func]()两个函数拿到的是同一个字典对象b.func中再次调用__salt__[c.func]()依然成立。两个不可靠的禁区__virtual__内部与 import 时刻文档明确指出有两个场景__salt__不可用且两者都发生在 loader 完成自我填充populate之前__virtual__内部此时 loader 正在决定该模块是否加载、以什么虚拟名加载其他模块可能尚未加载完毕。此阶段__pillar__与__grains__可用但__salt__不可靠。模块级 import 代码文件中任何函数之外的顶层语句这些代码在模块被 import 时执行同样早于 loader 填充完成。正确做法是将此类逻辑移入函数体或封装在由普通函数调用的辅助函数中延迟到真正执行时再访问__salt__。同时文档给出两个明确的安全区mod_init内部对 state 模块而言在mod_init中__salt__完全可用。renderer 与 pillar 模块中在 render 或 pillar 编译进行期间__salt__与__pillar__同时可用因此可以在 Jinja 模板中安全调用执行模块并读取其他 pillar 值{{ saltcmd.run }} {{ pillar.get(mysql:password) }}注意一个语义细节传给 renderer 的 pillar 是编译到当前时刻为止的 pillar如果某个 key 是由其他 ext pillar 之后才添加的在 renderer 中不能假设它一定存在。源码级佐证双 Loader 模型与pack_self__salt__上述完全填充 全链共享的保证并非文档空谈在 loader 实现中有着清晰的结构化支撑。执行模块加载入口是 salt/loader/init.py 的minion_mods()其核心是一个双 Loader 模型外层 Loaderwire dispatch按whitelistwhitelist_modules配置过滤负责面向线缆分发的函数集合内层salt_dunder不做过滤unfiltered并通过pack_self__salt__打包进每个加载的模块见 salt/loader/init.py。源码注释明确解释了这一设计动机被白名单过滤的模块依然可以通过__salt__[...]组合调用非白名单模块。当未设置 whitelist 时两个 Loader 加载相同的模块集合LazyLoader 会复用已存在的 per-moduleLoaderContext使两个 Loader 共享同一NamedLoaderContext绑定与 per-module 的__context__状态——这正是同一__salt__实例贯穿整条调用链的机制基础。pack_self__salt__的实际打包逻辑位于 salt/loader/lazy.py在模块初始化完成后Loader 将命名上下文NamedLoaderContextsetattr 到模块对象上run()则通过contextvars.copy_context()在 loader 的上下文中执行目标函数参见 salt/loader/lazy.py。源码级佐证__virtual__为什么不可靠模块是否加载由_process_virtual()决定实现在 salt/loader/lazy.py。加载时序是模块被 import__init__钩子执行见 salt/loader/lazy.py_process_virtual()调用__virtual__()根据返回值决定模块是否加载、虚拟名是什么只有__virtual__返回True或字符串虚拟名之后模块函数才进入__salt__字典。也就是说当__virtual__()正在执行时当前模块自己都还没被登记进 loader遑论其他可能尚未被扫描到的模块。因此文档中__virtual__内__salt__不可靠的结论与_process_virtual的执行顺序完全一致。这也解释了为何_process_virtual对__virtual__返回None、异常、返回字符串与__virtualname__不匹配等场景都有专门处理分别给出警告或错误日志——__virtual__阶段的运行环境本身就是受限的。此外salt/loader/lazy.py 表明__virtual__处理失败时模块会被记录到missing_modules并返回False模块整体不加载其内部对__salt__的任何依赖自然也不成立。测试印证内层 Loader 与__pillar__的同步仓库测试 tests/pytests/unit/loader/test_subsystem_whitelist_dunder.py 从另一角度印证了这套模型test_minion_mods_returns_shared_inner_loader验证salt.loader.minion_mods返回的外层 wire loader 与内层salt_dunder是共享的该文件中的pillar_refresh相关测试验证了__pillar__必须同时镜像进外层 wire loader 与内层_dunder_salt的pack[__pillar__]见 tests/pytests/unit/loader/test_subsystem_whitelist_dunder.py并断言minion.py中的 pillar 刷新逻辑同时 rebind 两个 loader 的__pillar__同文件 tests/pytests/unit/loader/test_subsystem_whitelist_dunder.py。这些测试表明链式调用场景下__pillar__的可用性同样有测试保障——它在外层与内层 loader 中保持一致因此在任意执行模块函数内部读取__pillar__都是可靠的。开发规范小结如何安全使用__salt__/__pillar__综合 doc/topics/development/modules/developing.rst 与源码结构模块开发者应遵守以下边界位置__salt____pillar__说明执行模块函数体含链式调用✅ 完全填充✅ 可用同一实例贯穿整条调用链可重入state 模块mod_init✅ 完全可用✅ 可用文档明确安全renderer / pillar 编译期间✅ 可用✅ 可用截至当前编译点可在 Jinja 中salt[...]、pillar.get(...)__virtual__()内部❌ 不可靠✅ 可用连同__grains__loader 尚未完成填充模块顶层 import 代码❌ 不可用❌ 不可靠移入函数体或延迟到函数调用时访问实际编写时的两条硬性建议任何需要访问__salt__的逻辑都必须放在函数内部执行不要放在模块顶层需要启动即执行的场景使用__init__钩子或惰性初始化而不是 import 副作用。在__virtual__()中做平台/依赖判断时只依赖__grains__、__pillar__与标准库探测不要试图调用其他执行模块来判断能力需要调用执行模块的探测逻辑应推迟到首次函数调用时完成。延伸阅读模块开发完整指南doc/topics/development/modules/developing.rst含 Loader 交互式调试、Loader Context、__virtualname__/__virtual_aliases__/__proxyenabled__等特殊模块内容Loader 实现入口salt/loader/init.pyminion_mods()双 Loader 模型Loader 核心机制salt/loader/lazy.py_process_virtual、pack_self、run上下文dunder 上下文实现salt/loader/context.py相关测试tests/pytests/unit/loader/test_subsystem_whitelist_dunder.py【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址: https://gitcode.com/gh_mirrors/sa/salt创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
图解原理:3步搞懂贡湖湾湿地公园项目中的证书变更与晋升路径 图解原理:3步搞懂贡湖湾湿地公园项目中的证书变更与晋升路径 官方文档堆砌法规条文,新人读三遍仍不知如何下手?别慌。 本文用 图解原理 拆解贡湖湾湿地公园实战项目,直击证书变更与职业晋升痛点。 项目目标… · 2026/9/23 14:15:16
AQG 324 车规功率模块认证指南:测试框架、实操与失效分析 简介:ECPE Guideline AQG 324 是面向汽车电力电子领域工程师、功率模块设计与测试人员的技术认证规范文档,聚焦机动车辆电力电子转换器单元中功率模块的资格认证要求。该指南由 ECPE 汽车功率模块认证工作组编制,源自德国车企与供应商联合制定… · 2026/9/23 14:15:10
STM32开源项目:代码、原理图、仿真三件套完整闭环 1. 为什么一个STM32项目值得把代码、原理图和仿真三件套一起开源做过嵌入式的人大概都有这种体会:从网上找到一个STM32项目,代码能跑,但想看硬件怎么接的,没有原理图;或者拿到一份原理图,想验证逻辑对不对&… · 2026/9/23 16:21:40
Prisma 数据建模指南:用 GraphQL SDL 设计数据模型(Data Modelling) 后端数据库GraphQL 【免费下载链接】prisma1 💾 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL & MongoDB) [deprecated] 项目地址: https://gitcode.com/gh_mirrors/pr/prisma1 点击查看 免费下载 导读
本文以 Prisma 服务… · 2026/9/23 16:21:33
Formily 单选框(Radio)组件完全指南:三种 Schema 写法与源码级原理剖析 前端UI组件 【免费下载链接】formily 📱🚀 🧩 Cross Device & High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3 项目地址: https://gitcode.com/gh_mirrors… · 2026/9/23 16:21:33
壶之贵人高频面试题解析:3招搞定底层原理 壶之贵人高频面试题解析:3招搞定底层原理 看了一堆教程还是不会写项目?别慌,这不是你的错。很多开发者卡在“懂原理”和“会落地”之间的鸿沟,尤其是面对 高频面试题… · 2026/9/23 16:21:27
DeepSeek微调实战:用LoRA与风格迁移生成影视剧本 简介:《影视剧本创作:DeepSeek行业语料微调与风格迁移技术》是一份面向影视编剧、AI应用开发者与内容创作者的实操型技术文档,旨在借助DeepSeek大模型解决传统剧本创作中效率偏低、题材同质化、市场适应性弱等痛点,适合希望掌握专… · 2026/9/23 16:21:20
RT-Thread VANGOV85XXP-EVAL 板级支持包详解:从编译烧写到驱动移植 RT-Thread VANGOV85XXP-EVAL 板级支持包详解:从编译烧写到驱动移植 【免费下载链接】rt-thread RT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/ 项目地址: https://gitcode.com/gh_mirrors/rt/rt-t… · 2026/9/23 16:21:14
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29