使用SaltStack检查Grains列表中的程序版本是否已安装
问题根源与解决方案
你的问题出在Jinja2模板变量的引用方式上——你用单引号包裹了r{{ rv }},导致Jinja2不会解析这个模板变量,而是把它当作一个字面量字符串'r{{ rv }}'来处理。
看你的grains配置里只有r1113,但判断条件里实际检查的是字符串'r{{ rv }}'是否在grains列表里,这个字符串显然不存在,所以不管循环到哪个版本(1113还是1278),条件都会成立,最终触发安装操作。
修正后的状态文件
你可以通过两种方式修复这个问题:
方式1:使用Jinja2字符串拼接运算符~
这种方式更直观,适合处理变量拼接场景:
{% set rvs = ['1113','1278'] %} {% for rv in rvs %} {% if ('r' ~ rv not in grains.get('cat12', [])) %} cat12-install-{{ rv }}: pkg.installed: - name: cat12-r{{ rv }} {% else %} cat12-{{ rv }}-already-present: test.nop: [] {% endif %} {% endfor %}
方式2:使用双引号包裹模板变量
Jinja2会解析双引号内的模板变量,所以也能达到目的:
{% set rvs = ['1113','1278'] %} {% for rv in rvs %} {% if ("r{{ rv }}" not in grains.get('cat12', [])) %} cat12-install-{{ rv }}: pkg.installed: - name: cat12-r{{ rv }} {% else %} cat12-{{ rv }}-already-present: test.nop: [] {% endif %} {% endfor %}
调试小技巧
如果以后遇到类似的模板解析问题,可以在状态里临时添加一个调试步骤,输出实际的判断值:
{% set rvs = ['1113','1278'] %} {% for rv in rvs %} debug-check-{{ rv }}: cmd.run: - name: echo "Checking for r{{ rv }}. Current grains: {{ grains.get('cat12', []) }}" {% if ('r' ~ rv not in grains.get('cat12', [])) %} # 安装步骤... {% endif %} {% endfor %}
执行salt '*' state.apply后,就能看到每个版本的判断逻辑是否符合预期了。
内容的提问来源于stack exchange,提问作者bergwiesel
相关产品推荐
相关产品推荐

