在 Ansible yaml 文件中评估多行布尔语句时出现错误结果

u12*_*123 1 yaml ansible

使用 ansible 2.7.5 我试图创建一个多行布尔参数。

我首先验证它是否按预期单行工作:

FOOD: apple
IS_FRUIT: '{% if FOOD == "carrot" %}false{% elif FOOD == "apple" or FOOD == "banana" %}true{% endif %}'
Run Code Online (Sandbox Code Playgroud)

然后是一个任务:

- name: "FOOD is: {{ FOOD }}" 
  debug: msg="FOOD is {{ FOOD }} where IS_FRUIT {{ IS_FRUIT | bool }}"
Run Code Online (Sandbox Code Playgroud)

打印:

ok: [localhost] => {
    "msg": "FOOD is apple where IS_FRUIT [ True ]"
}
Run Code Online (Sandbox Code Playgroud)

运行时如预期。

基于:

在 YAML 中,如何将字符串分成多行?

然后我尝试过:

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}
Run Code Online (Sandbox Code Playgroud)

但打印出:

ok: [localhost] => {
    "msg": "FOOD is apple where IS_FRUIT [ False ]"
}
Run Code Online (Sandbox Code Playgroud)

这是错误的。我发现这篇文章描述了类似的问题: https ://github.com/ansible/ansible/issues/18142

但它并没有真正提供解决方案。关于如何在 Ansible 中创建多行布尔变量有什么建议吗?

基于下面的答案我也尝试过:

FOOD: apple

IS_FRUIT: |
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}
Run Code Online (Sandbox Code Playgroud)

但是当我用上面相同的任务运行它时,我仍然得到:

ok: [localhost] => {
    "msg": "FOOD is apple where IS_FRUIT False"
}
Run Code Online (Sandbox Code Playgroud)

这是错误的。

fly*_*lyx 5

关于发生的事情的无聊解释

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}
Run Code Online (Sandbox Code Playgroud)

请注意,在 YAML 中,折叠块标量(以 开头>)用空格替换单个换行符(以及用少一个换行符替换多个换行符)。所以上面的代码相当于

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false {% elif FOOD == "apple" or FOOD == "banana" %}true {% endif %}
Run Code Online (Sandbox Code Playgroud)

因此,在 Jinja 处理之后,您将得到falseor 并true 带有尾随空格。由于尾随空格,YAML 不会将这些标量映射到布尔值。

现在我猜想Ansible 会看到它获得一个非布尔值,并以某种方式将该非布尔值映射到布尔值。因此,False即使你的标量true带有尾随空格,其计算结果也是如此(markdown 不允许我正确渲染它)。


关于如何修复它的重要部分

您可以使用文字块标量来代替(基于clockworknet的建议):

IS_FRUIT: |-
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为现在换行符不会转换为空格,而是保留换行符。-Jinja 处理后,只剩下一行,最后的换行符将被in去掉|-

但是,如果您有更复杂的表达式并且您想要将内容实际拆分为多行,则这对您没有帮助。有一个更好的解决方案,那就是Jinja 空白控制

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false
 {%- elif FOOD == "apple" or FOOD == "banana" %}true
 {%- endif %}
Run Code Online (Sandbox Code Playgroud)

Jinja 标签上-的 告诉 Jinja 删除该标签之前的所有空格,所以这基本上相当于

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false{% elif FOOD == "apple" or FOOD == "banana" %}true{% endif %}
Run Code Online (Sandbox Code Playgroud)

您还可以像这样使用它-%}来删除标签后的所有空格。但是,请注意:Jinja 处理发生在 YAML 处理之前,因此它可能会搞乱您精心编写的 YAML 缩进!例如,不要{%-在块标量中的第一个 Jinja 标记上使用,因为 Jinja 会将文本放在与|-无效 YAML 相同的行上!最后一个标签 和 也是如此-%}