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

在Ansible yaml文件中计算多行布尔语句时出现错误结果,ansible,yaml,Ansible,Yaml,使用ansible 2.7.5,我试图创建一个多行布尔参数 我首先验证了它作为一条线的预期工作情况: FOOD: apple IS_FRUIT: '{% if FOOD == "carrot" %}false{% elif FOOD == "apple" or FOOD == "banana" %}true{% endif %}' 然后是一项任务: - name: "FOOD is: {{ FOOD }}" debug: msg="FOOD is {{ FOOD }} where IS_

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

我首先验证了它作为一条线的预期工作情况:

FOOD: apple
IS_FRUIT: '{% if FOOD == "carrot" %}false{% elif FOOD == "apple" or FOOD == "banana" %}true{% endif %}'
然后是一项任务:

- name: "FOOD is: {{ FOOD }}" 
  debug: msg="FOOD is {{ FOOD }} where IS_FRUIT {{ IS_FRUIT | bool }}"
其中打印:

ok: [localhost] => {
    "msg": "FOOD is apple where IS_FRUIT [ True ]"
}
运行时如预期

基于:

然后我尝试:

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}
但这表明:

ok: [localhost] => {
    "msg": "FOOD is apple where IS_FRUIT [ False ]"
}
这是错误的。我发现这篇文章描述了一个类似的问题:

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

根据以下答案,我也尝试过:

FOOD: apple

IS_FRUIT: |
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}
但当我使用上面相同的任务运行时,我仍然得到:

ok: [localhost] => {
    "msg": "FOOD is apple where IS_FRUIT False"
}
这是错误的。

这对我来说很有用:

IS_FRUIT: |
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}
更改为|符号以使用文字多行行为

这对我很有用:

IS_FRUIT: |
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}
更改为|符号以使用文字多行行为

对发生的情况进行枯燥的解释

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

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false {% elif FOOD == "apple" or FOOD == "banana" %}true {% endif %}
IS_FRUIT: >-
 {% if FOOD == "carrot" %}false{% elif FOOD == "apple" or FOOD == "banana" %}true{% endif %}
因此,在Jinja处理之后,您将得到带有尾随空格的false或true。YAML不会将这些标量映射到布尔值,因为后面有空格

现在我猜Ansible看到它得到了一个非布尔值,它以某种方式将该非布尔值映射为布尔值。因此,您的标量计算结果为False,即使它是true,但尾部空间标记不允许我正确地呈现它

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

您可以根据clockworknet的建议使用文字块标量:

IS_FRUIT: |-
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}
这是因为现在新行不会转换为空格,而是保留新行。在Jinja处理之后,只剩下一行,最后的换行符将被-in |-

但是,如果您有更复杂的表达式,希望实际将内容拆分为多行,则这对您没有帮助。有一个更好的解决方案是:

Jinja标记上的-告诉Jinja删除此标记之前的所有空白,因此这基本上等同于

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false {% elif FOOD == "apple" or FOOD == "banana" %}true {% endif %}
IS_FRUIT: >-
 {% if FOOD == "carrot" %}false{% elif FOOD == "apple" or FOOD == "banana" %}true{% endif %}
您还可以像这样使用-%}删除标记后的所有空白。但是,请注意:Jinja处理发生在YAML处理之前,因此它可能会破坏您仔细编写的YAML缩进!例如,不要在块标量中的第一个Jinja标记上使用{%],因为Jinja会将文本放置在与|-相同的行上,这是无效的YAML!最后一个标记和-%}也是如此。

关于发生了什么的枯燥解释

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

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false {% elif FOOD == "apple" or FOOD == "banana" %}true {% endif %}
IS_FRUIT: >-
 {% if FOOD == "carrot" %}false{% elif FOOD == "apple" or FOOD == "banana" %}true{% endif %}
因此,在Jinja处理之后,您将得到带有尾随空格的false或true。YAML不会将这些标量映射到布尔值,因为后面有空格

现在我猜Ansible看到它得到了一个非布尔值,它以某种方式将该非布尔值映射为布尔值。因此,您的标量计算结果为False,即使它是true,但尾部空间标记不允许我正确地呈现它

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

您可以根据clockworknet的建议使用文字块标量:

IS_FRUIT: |-
 {% if FOOD == "carrot" %}false
 {% elif FOOD == "apple" or FOOD == "banana" %}true
 {% endif %}
这是因为现在新行不会转换为空格,而是保留新行。在Jinja处理之后,只剩下一行,最后的换行符将被-in |-

但是,如果您有更复杂的表达式,希望实际将内容拆分为多行,则这对您没有帮助。有一个更好的解决方案是:

Jinja标记上的-告诉Jinja删除此标记之前的所有空白,因此这基本上等同于

IS_FRUIT: >-
 {% if FOOD == "carrot" %}false {% elif FOOD == "apple" or FOOD == "banana" %}true {% endif %}
IS_FRUIT: >-
 {% if FOOD == "carrot" %}false{% elif FOOD == "apple" or FOOD == "banana" %}true{% endif %}

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

对@flyx所做的很好的解释

我建议不要在你的剧本中使用Jinja语句,而是使用Jinja表达式。 Still语句在文件模板中是OK的

您可以按如下方式编写vars定义:

IS_FRUIT: >-
  {{ false if FOOD == 'carrot'
     else
     (
       true if FOOD in ['apple', 'banana']
       else 'unknown'
     )
  }}

在本例中,我们只关心最后一行换行符,该换行符用>-。

很好地解释了@flyx所做的事情

我建议不要在你的剧本中使用Jinja语句,而是使用Jinja表达式。 Still语句在文件模板中是OK的

您可以按如下方式编写vars定义:

IS_FRUIT: >-
  {{ false if FOOD == 'carrot'
     else
     (
       true if FOOD in ['apple', 'banana']
       else 'unknown'
     )
  }}
在这种情况下,我们只关心最后一行换行符,该换行符用>-。

剥离。不确定是否重新发布
nt,但您应该在>-版本中删除周围的,因为它们将成为内容的一部分。对于更简单的情况,只需添加一行,即可修复错误。但是对于多行-请参阅上面更新的示例,它仍然失败。不确定是否相关,但您应该在>-版本中删除周围的,因为它们将成为内容的一部分。对于更简单的情况,只需添加一行,就可以修复错误。但对于多行-见上面更新的例子,它仍然失败。我也尝试过-见更新的帖子-但同样的错误结果。是的,对不起。误解了问题的微妙之处。你从@flyx得到了一个很好的答案,所以希望你的问题得到了解决。我也尝试过-见更新后的帖子-但同样的错误结果。是的,对不起。误解了问题的微妙之处。@flyx为您提供了一个极好的答案,希望您的问题得到解决。