
运维配置管理后端【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址https://gitcode.com/gh_mirrors/sa/salt点击查看免费下载本文以 Salt 官方 API 文档 doc/ref/modules/all/salt.modules.slsutil.rst 为核心骨架结合 salt/modules/slsutil.py 源码及其单元测试 tests/pytests/unit/modules/test_slsutil.py系统讲解slsutil执行模块的每一个函数。读完本文你将掌握在 Jinja 模板与 SLS 状态文件中递归合并/更新数据结构、选用不同合并策略、调用渲染器管道渲染文件或字符串、跨格式序列化与反序列化、生成标准化的“本文件由 Salt 管理”注释横幅、把布尔值转换为任意字符串以及在 state tree 中探测文件/目录是否存在并向上逐级查找文件——这些都是编写复杂 Salt 公式Formula时高频使用的实战能力。slsutilSLS utility是 Salt 中一组“供 SLS 文件内部使用”的通用工具函数。它不直接管理系统资源而是为状态文件和 Jinja 模板提供数据处理能力是 Salt 公式开发者的“瑞士军刀”。一、模块概览slsutil能做什么从 salt/modules/slsutil.py 的源码看slsutil一共提供了 10 个公开函数可以归为四类分类函数核心用途数据合并update、merge、merge_all递归合并/更新字典支持多种合并策略渲染renderer将文件或字符串送入 Salt 渲染器管道renderer pipe处理序列化serialize、deserialize调用 Salt 的序列化器在 Python 对象与字符串/流之间转换模板辅助banner、boolstr生成注释横幅、把布尔值输出为指定字符串文件探测file_exists、dir_exists、path_exists、findup在 state tree 中检查文件/目录存在性并沿祖先目录查找其中_set_context版本 3004 起与_get_serialize_fn是内部辅助函数公开 API 文档不会单独列出但它们是file_exists/dir_exists缓存机制与序列化函数查找的实现基础。二、数据合并update、merge与merge_all2.1update递归版本的dict.updateslsutil.update(dest, upd, recursive_updateTrue, merge_listsFalse)将upd递归合并进destsalt * slsutil.update {foo: Foo} {bar: Bar} # 结果: {foo: Foo, bar: Bar}关键参数recursive_update默认True表示递归合并嵌套字典设为False则退化为经典dict.update行为整体覆盖。merge_lists默认False。仅在recursive_updateTrue时生效设为True后两个列表将按“追加”方式聚合dest[key] upd[key]且自 2016.11.6 起重复值会被去重。从 salt/utils/dictupdate.py 的底层实现可见其精确语义当dest与upd的键完全不相交时会自动降级为非递归更新recursive_updateFalse提升性能双方均为Mapping时递归进入双方均为list且merge_listsTrue时upd中不存在的元素才被追加进深拷贝后的dest列表自 3008.0 起当merge_listsTrue且试图用映射覆盖列表时strictTrue场景会抛出TypeError避免隐式数据丢失。单元测试 test_update 验证了键合并与merge_listsFalse时的覆盖行为。2.2merge按策略合并slsutil.merge(obj_a, obj_b, strategysmart, rendereryaml, merge_listsFalse)允许通过strategy显式选择合并方式salt * slsutil.merge {foo: Foo} {bar: Bar}支持的合并策略定义于 salt/utils/dictupdate.py策略行为smart默认依据renderer参数自动选择若渲染器以yamlex结尾或以yamlex_开头则用aggregate否则用recurserecurse深拷贝obj_a后递归合并obj_baggregate使用 yamlex 序列化器的merge_recursive进行“聚合”式合并层级合并可处理列表语义list相同键的值组合成列表[obj_a[key], obj_b[key]]overwrite仅当键存在于obj_a时用obj_b的值覆盖再递归合并none不真正合并用于单 pillar 场景行为等同 recurse其他未知值记录 warning 日志后回退为recurse测试用例 test_merge 展示了各种策略的典型差异例如strategylist时{foo: Foo}与{foo: Bar}合并为{foo: [Foo, Bar]}。2.3merge_all按顺序合并一组对象slsutil.merge_all(lst, strategysmart, rendereryaml, merge_listsFalse)版本 2019.2.0 起依次将列表中的每个对象合并进结果字典后合并的值覆盖先合并的值salt-call --outputtxt slsutil.merge_all [{foo: Foo}, {foo: Bar}] local: {ufoo: uBar}其实现就是循环调用salt.utils.dictupdate.merge(ret, obj, ...)strategy、renderer、merge_lists三个参数与merge完全一致。这在合并多层 pillar 数据、或把多个 map 文件的结果叠加时非常有用。三、renderer把文件/字符串送入渲染器管道slsutil.renderer(pathNone, stringNone, default_rendererjinja|yaml, **kwargs)是模块中功能最开放的函数。它利用 Salt 的“渲染器管道”renderer pipes机制将文件或内联字符串依次通过多个渲染器处理最终返回处理结果。自 2018.3.0 起支持 Salt fileserver URI如salt://path/to/file。salt * slsutil.renderer salt://path/to/file salt * slsutil.renderer /path/to/file salt * slsutil.renderer /path/to/file.jinja default_rendererjinja salt * slsutil.renderer /path/to/file.sls default_rendererjinja|yaml salt * slsutil.renderer stringInline template! {{ saltenv }} salt * slsutil.renderer stringHello, {{ name }}. nameworld参数语义path可以是 Salt fileserver 上的任意 URI支持cp.get_url支持的所有 URI 形式也可以是本地文件系统路径string内联字符串。注意并非所有渲染器都支持字符串输入——例如py渲染器就要求文件default_renderer默认渲染管道会被文件开头的 shebang如#!jinja|yaml覆盖kwargs透传给compile_template()的关键字参数如nameworld会作为模板变量注入。典型实战场景解耦 map 文件的渲染器。Salt 公式中常见的 map 文件通常与使用它的 SLS 采用相同渲染器但通过slsutil.renderer可以打破这一限制——map 文件用 Python 渲染器编写而引用它的 SLS 依然使用默认的jinja|yaml。官方文档给出了两个功能等价的 map 文件示例jinja|yaml版本#!jinja|yaml头#!jinja|yaml {% set apache saltgrains.filter_by) %} {{ apache | yaml() }}py版本#!py头#!py def run(): apache __salt__grains.filter_by) return apache无论使用哪个版本其他任何 SLS 文件都能用同一行 Jinja 调用它{% set apache saltslsutil.renderer %}实现原理salt/modules/slsutil.py只传path或string之一同时传或不传都会抛出SaltInvocationError通过salt.loader.render(__opts__, __salt__)加载全部渲染器对path使用__salt__cp.get_url)获取本地路径对string使用特殊占位:string:并把字符串放入kwargs[input_data]调用salt.template.compile_template(path_or_string, renderers, default_renderer, __opts__[renderer_blacklist], __opts__[renderer_whitelist], **kwargs)最后根据stringio.is_readable判断返回 StringIO 内容还是原始返回值。注意其中会遵守__opts__中的renderer_blacklist/renderer_whitelist配置即 master/minion 配置里对渲染器的黑白名单在此同样生效。选择渲染管道时的一个关键提醒不同渲染器的产出类型不同——Jinja 处理文本并产生字符串而 YAML 渲染器处理文本后产生的是数据结构。因此在管道中选择渲染器时要始终清楚自己期望得到字符串还是字典/列表。单元测试 test_renderer 覆盖了字符串渲染、缺参报错、path/string 同时传入报错以及文件渲染四种情形。四、序列化与反序列化serialize与deserializeslsutil.serialize(serializer, obj, **mod_kwargs)使用 Salt 已加载的序列化器将 Python 对象序列化为字符串slsutil.deserialize(serializer, stream_or_string, **mod_kwargs)则相反。# 注意 --no-parseobj 防止命令行参数被提前解析 salt * --no-parseobj slsutil.serialize json obj{foo: Foo!} salt * slsutil.deserialize json {foo: Foo!} salt * --no-parsestream_or_string slsutil.deserialize json \ stream_or_string{foo: Foo!}Jinja 中的用法{% set json_string saltslsutil.serialize %} {% set python_object saltslsutil.deserialize %}从 salt/serializers/ 目录可以看到当前仓库内置的序列化器configparser、json、msgpack、tomlmod、yaml、yamlex。serializer参数即取其中的名称例如slsutil.serialize(yaml, obj)。实现细节_get_serialize_fnsalt/modules/slsutil.py通过salt.loader.serializers(__opts__)加载序列化器若序列化器不存在抛出CommandExecutionError(Serializer name not found.)若对应函数未实现则抛出CommandExecutionError(Serializer name does not implement fn.)。测试 test__get_serializer_fn 对这两种报错路径都有验证。五、模板辅助banner与boolstr5.1banner标准化注释横幅配置管理的一个常见做法是在被管理的文件中插入“此文件由 Salt 管理请勿手动修改”的注释块。slsutil.banner()让这一操作标准化、可定制{{ salt[slsutil.banner]() }}输出默认width72commentchar#borderchar######################################################################### # # # THIS FILE IS MANAGED BY SALT - DO NOT EDIT # # # # The contents of this file are managed by Salt. Any changes to this # # file may be overwritten automatically and without warning. # ########################################################################参数说明参数默认值说明width72横幅宽度字符数commentchar#每行行首的注释字符支持//等多字符序列若文件语法不支持行注释如 XML改用blockstart/blockendborderchar#上下边框字符必须是单个字符blockstartNone块注释起始序列需与blockend配合如/*blockendNone块注释结束序列如*/titleTHIS FILE IS MANAGED BY SALT - DO NOT EDIT居中显示在方框顶部text固定的警告文本左对齐显示在方框底部newlineFalse是否在横幅末尾追加换行符Javadoc 风格示例{{ saltslsutil.banner }}/** *********************************************************************** * * * THIS FILE IS MANAGED BY SALT - DO NOT EDIT * * * * The contents of this file are managed by Salt. Any changes to this * * file may be overwritten automatically and without warning. * *********************************************************************** */自定义标题与正文示例{{ set copyrightThis file may not be copied or distributed without permission of VMware, Inc. }} {{ saltslsutil.banner }}实现上banner使用textwrap.TextWrapper对标题与正文按width自动折行并通过os.linesep拼接各行若width过小导致内容宽度为负会抛出ArgumentValueError。单元测试 test_banner 断言了每一行的长度恰好等于width、以commentchar开头并以commentchar.strip()结尾以及 blockstart/blockend 出现在首尾行。5.2boolstr布尔值转任意字符串slsutil.boolstr(value, truetrue, falsefalse)把布尔值映射为模板所需的字符串常用于把 Pillar/Grains 中的布尔配置输出为特定文件语法要求的取值如yes/no{% set encrypted saltpillar.get %} use_tls: {{ saltslsutil.boolstr }}当 pillar 中smtp:encrypted为True时输出use_tls: yes。默认true/false参数值分别是字符串true与false也可以传任意其他取值。测试 test_boolstr 验证了yes/no映射。六、state tree 文件探测file_exists、dir_exists、path_exists与findup这四个函数自版本 3004 起用于在 Salt fileserver 的 state tree 中探测路径适合在状态文件中根据文件是否存在做条件渲染。6.1 存在性检查salt * slsutil.file_exists nginx/defaults.yaml salt * slsutil.dir_exists nginx/files salt * slsutil.path_exists nginx/defaults.yamlfile_exists(path, saltenvbase)文件是否存在dir_exists(path, saltenvbase)目录是否存在path_exists(path, saltenvbase)文件或目录是否存在即前两者的或。三个函数都接受saltenv参数指定 fileserver 环境默认base。path_exists的实现就是file_exists(...) or dir_exists(...)。性能设计file_exists与dir_exists通过_set_context把cp.list_master(saltenv)/cp.list_master_dirs(saltenv)的结果缓存在__context__[slsutil][saltenv]下CONTEXT_BASE slsutil同一次 minion 运行内重复探测不会反复拉取文件列表。_set_context会按需逐级创建字典路径并支持force参数强制刷新缓存。6.2findup沿祖先目录向上查找slsutil.findup(startpath, filenames, saltenvbase)从指定目录开始逐级向上到 state tree 根查找文件名/目录名返回第一个匹配的完整路径。salt * slsutil.findup formulas/shared/nginx map.jinjaJinja 中最典型的用法是配合tplfile当前正在处理的模板文件路径从当前状态文件所在目录向上找到最近的defaults.yaml{{ saltslsutil.findup }}行为细节salt/modules/slsutil.pystartpath为空字符串或None时从 state tree 根开始查找filenames接受单个字符串或字符串列表也支持目录名起始路径本身必须存在于 state tree否则抛出SaltInvocationError一路向上到根仍未找到抛出CommandExecutionError(File pattern(s) not found in path ancestry)。单元测试 test_findup 验证了向上查找、多文件名优先级、根目录查找以及各类异常路径。七、在 SLS 与 Jinja 中的综合实战示例将以上能力组合可以实现非常灵活的公式编写模式。例如一个 nginx 公式的状态文件可以这样写{%- set tplroot tpldir.split(/)[0] %} {%- set sls_pillar saltpillar.get %} {%- set defaults saltslsutil.renderer, default_rendererjinja|yaml ) %} {%- set settings saltslsutil.merge %} # 合并后的配置通过 serialize 输出为 JSON供其他工具消费 {%- set json_conf saltslsutil.serialize %} nginx: pkg.installed: [] service.running: [] file.managed: - name: /etc/nginx/nginx.conf - source: salt://{{ tplroot }}/files/nginx.conf.jinja - template: jinja - context: settings: {{ settings | json }}其中findup负责“找到离当前状态文件最近的 defaults.yaml”renderer负责以指定渲染管道读取它merge负责把 pillar 覆盖值合并进去serialize负责把最终结果导出为其他格式——这正是四个核心函数在同一场景下的协同工作。八、API 文档与测试的对应关系API 文档slsutil的官方文档入口位于 doc/ref/modules/all/salt.modules.slsutil.rst通过automodule指令从源码 docstring 自动生成因此在 salt/modules/slsutil.py 中各函数的 docstring 即文档本体单元测试tests/pytests/unit/modules/test_slsutil.py 覆盖update/merge/merge_all/renderer/serialize/deserialize/banner/boolstr/file_exists/dir_exists/path_exists/findup及两个内部辅助函数是理解各函数精确行为的最佳补充材料底层依赖合并逻辑的核心实现在 salt/utils/dictupdate.py序列化依赖 salt/serializers/ 下各序列化器集成测试slsutil在 SSH 模式salt-ssh下同样可用相关测试见 tests/pytests/integration/ssh/test_slsutil.py 与 tests/pytests/unit/client/ssh/wrapper/test_slsutil.py。结语slsutil是一组“小而精”的工具update/merge/merge_all解决了 SLS 开发中最常见的数据合并问题renderer打破了 map 文件与 SLS 渲染器之间的耦合serialize/deserialize打通了对象与文本格式之间的转换banner/boolstr简化了模板输出而file_exists/dir_exists/path_exists/findup让状态文件具备基于 state tree 实际内容的感知能力。掌握这组函数可以让你的 Salt 公式更健壮、更灵活也更易于维护。赞分享运维配置管理后端【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址https://gitcode.com/gh_mirrors/sa/salt点击查看免费下载相关推荐Salt locate 执行模块完全指南用 Salt 远程调用 locate/updatedb 进行文件检索与数据库管理Salt locate 执行模块完全指南用 Salt 远程调用 locate/updatedb 进行文件检索与数据库管理 导读 本文围绕 Salt 执行模块运维配置管理后端Salt hosts 执行模块全指南用 salt * hosts.* 管理 hosts 文件中的 IP 与主机名映射Salt hosts 执行模块全指南用 salt hosts. 管理 hosts 文件中的 IP 与主机名映射 本篇技术指南围绕 Salt 内置的 h运维配置管理后端Salt 中 FreeBSD pkgng 软件包管理执行模块完全指南Salt 中 FreeBSD pkgng 软件包管理执行模块完全指南 本文档基于 Salt 开源仓库中 salt/modules/pkgng.py https:运维配置管理后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考