ARTICLE DETAIL

资讯详情

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

Salt SLS 模板变量完全指南:`sls`、`slspath`、`tpldir` 等上下文变量的使用与原理

Salt SLS 模板变量完全指南:`sls`、`slspath`、`tpldir` 等上下文变量的使用与原理 运维配置管理后端【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址https://gitcode.com/gh_mirrors/sa/salt点击查看免费下载SaltSaltStack在渲染 SLS 状态文件与文件模板时会向模板引擎注入一批上下文变量context variables例如salt、opts、pillar、grains以及仅对 SLS 状态文件可见的sls、slspath、tpldir、sls_path等路径派生变量。本篇指南以官方参考文档 SLS Template Variable Reference 为骨架结合仓库源码salt/utils/templates.py、salt/utils/jinja.py、salt/renderers/jinja.py深入剖析每个变量的来源、作用域与底层生成逻辑。读完本文你将能够在 SLS 中安全地引用这些变量、正确生成基于当前 SLS 目录的相对salt://路径并规避 Salt 3005 版本对sls_path、tplfile、tpldir行为的破坏性变更。模板上下文变量从哪里来渲染管线概览在深入每个变量之前先理清 Salt 的模板渲染调用链。SLS 文件首先由 salt/template.py 中的compile_template()按 shebang如#!jinja|yaml选出渲染管线render pipe随后每个 renderer如 Jinja以saltenv、sls等关键字参数被调用ret render(input_data, saltenv, sls, **render_kwargs)以 Jinja renderer 为例salt/renderers/jinja.py 的render()会一次性注入salt、grains、opts、pillar、saltenv、sls、proxy、context、tmplpath等上下文并调用salt.utils.templates.JINJA即wrap_tmpl_func(render_jinja_tmpl)。而wrap_tmpl_func会进一步调用 generate_sls_context() 生成slspath、sls_path、slsdotpath、slscolonpath、tplpath、tplfile、tpldir、tpldot这一组 SLS 路径变量并通过context.setdefault(key, value)合入模板上下文见 salt/utils/templates.py。因此所有变量本质上都是渲染期render-time通过上下文字典注入的下文将按“全局可用”与“仅 SLS 可用”两个维度逐一讲解。全局模板变量在任何模板中均可使用以下变量在所有 Salt 模板SLS 状态文件、file.managed管理的 Jinja 模板、pillar、top文件等中均可直接引用。salt调用 minion 上所有函数的字典salt变量抽象了 Salt 库函数本质是一个 Python 字典包含运行中 minion 可用的全部执行模块函数可在所有 Salt 模板中使用。最典型的用途是在模板中动态收集系统信息并生成状态声明{% for file in saltcmd.run.splitlines() %} /opt/to_remove/{{ file }}: file.absent {% endfor %}源码细节在 wrap_tmpl_func() 中salt会被包装为AliasedLoader将cmd.run别名到cmd.shell从而让模板内的命令调用默认以python_shellTrue执行即 shell 语法直接可用。Jinja renderer 还会通过_split_module_dicts()同时支持saltcmd.run与salt.cmd.run(...)两种调用语法见 salt/renderers/jinja.py。optsminion 配置字典opts变量将 minion 配置文件/etc/salt/minion的内容直接暴露给模板它是一个字典在所有模板中可用{{ opts[cachedir] }}注意config.get函数也会在opts字典中查找取值因此opts与saltconfig.get的数据来源是相通的。pillarpillar 数据字典pillar字典可以直接引用并在所有模板中可用{{ pillar[key] }}官方更推荐通过salt变量调用pillar.get函数原因是它可以安全地设置默认值当 pillar 中不存在该键时不会抛异常并且可以直接用冒号分隔符遍历嵌套字典{{ saltpillar.get }} {{ saltpillar.get }}grainsminion 的 grains 字典grains字典直接暴露 minion 的静态与动态 grains 信息在所有模板中可用{{ grains[os] }}同样地grains.get函数可以深入嵌套结构并设置默认值{{ saltgrains.get }}saltenv当前环境file root名称saltenv变量表示当前正在从中获取 SLS 的环境如base、dev、prod。它只在从某个环境收集 SLS 文件时可用{{ saltenv }}当不存在saltenv时例如本地文件模板场景Jinja renderer 会退化为使用FileSystemLoader而非 Salt 的SaltCacheLoader见 salt/utils/templates.py。仅 SLS 文件可用的变量SLS Only Variables以下变量只在处理 SLS 状态文件时注入。如果你在其他模板如file.managed的源模板中也需要这些信息通常需要把它们作为模板上下文context或defaults显式传入。slsSLS 引用值sls变量保存当前 SLS 的引用值reference value即你在 top 文件中引用它、或通过include:选项包含它时使用的名称点分隔形式。它只在实际的 SLS 文件本身中可用而不会出现在该 SLS 引用的其他文件例如被file.managed管理的模板中{{ sls }}例如top.sls中写- webserver.nginx那么在渲染webserver/nginx.sls时sls的值就是webserver.nginx。slspath当前 SLS 所在目录斜杠分隔slspath包含当前 SLS 文件所在目录的路径。当当前 SLS 位于 file roots 根目录时其值为。它的取值与引用方式有关对于 Jinja{% include %}模板级包含slspath是当前文件所在目录的路径对于 Saltinclude:状态级包含slspath是被包含文件所在目录的路径。{{ slspath }}sls_path下划线分隔的slspathsls_path是slspath的变体用下划线_代替路径分隔符/。例如slspath为path/to/state则sls_path为path_to_state{{ sls_path }}slsdotpath点分隔的slspathslsdotpath用点.代替路径分隔符。例如slspath为path/to/state则slsdotpath为path.to.state。当sls指向一个目录即隐式init.sls时slsdotpath与sls相同{{ slsdotpath }}slscolonpath冒号分隔的slspathslscolonpath用冒号:代替路径分隔符例如path/to/state对应path:to:state{{ slscolonpath }}tplpath模板在本地磁盘上的完整路径tplpath是被处理的 SLS 模板文件在本地磁盘上的完整路径通常指向缓存目录中的副本且为操作系统特定格式Windows 与 POSIX 不同。官方文档明确提示“最好别用它”It is probably best not to use this.因为它的值依赖缓存布局不具备可移植性{{ tplpath }}tplfile相对于 file roots 的模板路径tplfile是当前被处理的 SLS 模板文件相对于 file roots 的路径例如foo/bar.sls{{ tplfile }}tpldir当前 SLS 所在目录相对 file rootstpldir是当前 SLS 文件相对于 file roots 的目录。与slspath的区别仅在于当 SLS 位于 file roots 根目录时tpldir返回.点而slspath返回空字符串。其余情况下二者通常相同。tpldir最经典的实战用途是生成相对salt://的源路径使状态文件可以在不同目录结构间迁移而不写死绝对路径my-file: file.managed: source: salt://{{ tpldir }}/files/my-templatetpldot点分隔的tpldirtpldot用点代替tpldir中的斜杠例如tpldir为path/to/state则tpldot为path.to.state。注意如果tpldir是.则tpldot被置为{{ tpldot }}slspath与tpldir何时被填充状态编译器 vs 渲染器文档特别澄清了slspath与tpldir的注入时机。它们是模板渲染期变量由 Salt 的**状态编译器state compiler**在把 SLS 渲染为状态数据时注入。由此可以总结出三条明确的边界规则被填充的场景所有被当作状态数据渲染的 SLS 文件——包括 top 文件、被include:包含的 SLS、以及正在被 apply 的 SLS 本身——内部都有slspath与tpldir。不被填充的场景通过file.managedtemplate: jinja渲染的非状态文件模板中这两个变量不存在。因为此时模板由渲染器子系统renderer subsystem渲染而非状态编译器状态专属变量不在作用域内。需要在非状态模板中取 SLS 路径怎么办通过defaults或context显式传入。官方文档给出的标准做法是configure-app: file.managed: - name: /etc/app.conf - source: salt://app/files/app.conf.j2 - template: jinja - defaults: sls_dir: {{ slspath }}在app.conf.j2内部即可使用{{ sls_dir }}拿到 SLS 所在目录。两类 include 的行为差异在 SLS 文件中使用 Jinja 的{% include %}被包含的模板继承当前的 SLS 渲染上下文因此slspath与tpldir仍指向发起包含的那个 SLS。在 SLS 文件顶部使用 Salt 的include:指令引入其他 SLS每个 SLS 在自身被渲染期间看到的是各自的slspath。源码级原理generate_sls_context()如何推导这些变量这些路径变量的推导逻辑集中在 salt/utils/templates.py 的generate_sls_context(tmplpath, sls)函数中关键步骤包括先把点分隔的sls引用值规范化为路径形式并去掉尾部斜杠slspath sls.replace(., /).rstrip(/)根据tmplpath与slspath的匹配关系剥离出模板名处理xxx.sls、xxx/init.sls与无法匹配的非 SLS 文件三种分支见 salt/utils/templates.py。从剥离后的模板路径中计算tplfile、tpldir空目录时回退为.与tpldot。最后基于slspath一次性派生四个变体slsdotpath slspath.replace(/, .) slscolonpath slspath.replace(/, :) sls_path slspath.replace(/, _)单元测试 tests/pytests/unit/utils/templates/test_jinja.py 完整覆盖了这些推导行为可以直接当作速查表使用输入 SLSslsslspathtpldirsls_pathslsdotpathslscolonpathtpldotfoo/bar.slsfoo.barfoofoofoofoofoofoofoo/init.slsfoofoofoofoofoofoofooa/b/c.slsa.b.ca/ba/ba_ba.ba:ba.bfoo.sls根级foo.以上断言对应 test_jinja.py 中的四个用例根级行为的另一个实现见 test_wrap_tmpl_func.py。用户自定义值优先Issue #68754 的修复语义在wrap_tmpl_func()中由generate_sls_context()计算出的变量通过context.setdefault(key, value)合并进上下文salt/utils/templates.py这意味着调用方显式提供的值例如file.managed上的defaults/context优先于从sls推导出的值不会被静默覆盖。这是对 Issue #68754 的修复。对应回归测试 test_wrap_tmpl_func.py 验证了当用户在defaults/context中同时给出sls及其派生变量slspath、sls_path、slsdotpath、slscolonpath、tpldir等时最终渲染上下文中的这些值必须保持为用户提供的内容。这为上文“在file.managed中用defaults传递slspath”的推荐做法提供了实现级保证。实战组合构建目录感知的公式formula综合以上变量可以写出一个“目录感知”的 SLS 与模板协作模式# salt://myapp/init.sls {% set config_dir saltpillar.get %} myapp-config: file.managed: - name: /etc/myapp.conf - source: salt://{{ tpldir }}/files/myapp.conf.j2 - template: jinja - defaults: sls_dir: {{ slspath }} app_env: {{ saltenv }} # myapp/files/myapp.conf.j2 内部 base_dir {{ sls_dir }} environment {{ app_env }}这里tpldir、slspath、saltenv都取自当前 SLS通过defaults传递后模板内部不再依赖任何 SLS 上下文变量从而避免了“非状态模板中tpldir未定义”的坑。此外salt/modules/slsutil.py 提供的slsutil.findup也能借助tplfile在公式目录树中向上查找共享的map.jinja/defaults.yaml{% set defaults saltslsutil.findup %}兼容性警示3005 版本对sls_path、tplfile、tpldir的改进官方文档开篇即给出警告在 Salt 3005 版本中sls_path、tplfile与tpldir得到了重大改进这些改进可能破坏依赖旧行为的状态文件。结合源码可以推断旧行为与新行为的差异点3005 之前的实现可能把tplpath本地磁盘缓存路径错误地当作tplfile/tpldir的来源导致 Windows 与 POSIX 行为不一致新实现generate_sls_context()统一以sls引用值为基准推导路径变量并明确区分“SLS 被渲染为状态数据”与“模板被渲染为非状态文件”两种场景根级 SLS 的边界值也被规范化tpldir .、slspath 、tpldot 。如果你维护的公式依赖这些变量且尚未适配 3005建议用salt --versions确认 minion / master 版本在根级 SLS 中不要假设tpldir/slspath有非空值尽量用defaults/context显式传递路径而非依赖模板内部隐式可见性。小结变量作用域含义典型用途salt所有模板minion 全部执行模块函数的字典动态收集数据、生成声明opts所有模板minion 配置字典读取cachedir等配置pillar所有模板pillar 数据字典读取配置数据推荐pillar.getgrains所有模板minion grains 字典按系统信息分支推荐grains.getsaltenvSLS从环境获取时当前环境名称环境相关逻辑sls仅 SLS 本身SLS 引用值自引用、日志slspath仅 SLS当前 SLS 目录斜杠分隔根级为构造相对路径sls_path仅 SLS下划线分隔的slspath生成唯一标识符slsdotpath仅 SLS点分隔的slspath与sls引用值互转slscolonpath仅 SLS冒号分隔的slspath与pillar.get的键格式对齐tplpath仅 SLS模板本地磁盘完整路径不推荐使用tplfile仅 SLS相对 file roots 的模板路径配合slsutil.findup查找共享文件tpldir仅 SLS当前 SLS 目录根级为.生成salt://{{ tpldir }}/...相对源tpldot仅 SLS点分隔的tpldir根级为模板标识理解这些变量的作用域与推导规则是编写健壮、可移植 SLS 状态文件的基础。更多官方描述可查阅 doc/ref/states/vars.rst推导逻辑的实现细节可深入阅读 salt/utils/templates.py、salt/utils/jinja.py 及对应的单元测试 test_jinja.py 与 test_wrap_tmpl_func.py。赞分享运维配置管理后端【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址https://gitcode.com/gh_mirrors/sa/salt点击查看免费下载相关推荐Salt SLS 模板变量slspath、tpldir 等的作用域边界与正确传递方式Salt SLS 模板变量slspath、tpldir 等的作用域边界与正确传递方式 Salt 状态系统内置了一组仅在 SLS 渲染期有效的模板变量 sl运维配置管理后端Salt 的 Mako 渲染器salt.renderers.mako实战指南模板管线、上下文变量与源码原理Salt 的 Mako 渲染器salt.renderers.mako实战指南模板管线、上下文变量与源码原理 导读 本文围绕 Salt 官方 API 参考文运维配置管理后端Salt slsutil 执行模块完全指南SLS 文件与模板中的数据处理、渲染与文件探测工具Salt slsutil 执行模块完全指南SLS 文件与模板中的数据处理、渲染与文件探测工具 本文以 Salt 官方 API 文档 doc/ref/modul运维配置管理后端上一篇Visdom能源消耗监控实时数据与优化建议下一篇如何轻松备份微信聊天记录WeChatMsg完整指南让珍贵对话永不丢失创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表