【问题标题】:Case statement for setting var in Ansible/Jinja2在 Ansible/Jinja2 中设置 var 的 case 语句
【发布时间】:2015-08-18 15:56:23
【问题描述】:

我将 Ansible 与 Jinja2 模板一起使用,这是我无法在 Ansible 的文档中找到解决方案或在谷歌上搜索 Jinja2 示例的场景。这是我想在 Ansible 中实现的逻辑:

if {{ existing_ansible_var }} == "string1"
  new_ansible_var = "a"
else if {{ existing_ansible_var }} == "string2"
  new_ansible_var = "b"
<...>
else
  new_ansible_var = ""

我可以通过结合几种技术来做到这一点,这里的变量赋值:Set variable in jinja,这里的条件比较:http://jinja.pocoo.org/docs/dev/templates/#if-expression,以及这里的默认过滤器:https://docs.ansible.com/playbooks_filters.html#defaulting-undefined-variables

...但我觉得这有点矫枉过正。有没有更简单的方法来做到这一点?

【问题讨论】:

  • 你想达到什么目的?
  • 我正在尝试根据几个条件设置new_ansible_var,以便我可以在.j2 模板中使用new_ansible_var
  • 我知道了,但你为什么要这个?如果您说明您的实际问题是什么,我们或许可以帮助您以更好的方式解决问题。
  • 请在下面查看我的更新答案。除了简单地写出值之外,我还添加了一个定义 var 的示例。
  • @AntonisChristofides - 在我的.j2 文件中,我有一行我想看起来像这样:tags: {{ perm_tags }} {{ optional_tags}}。当且仅当{{ machine_type }} 匹配许多不同字符串之一时,optional_tags 应该有一个值。字符串比较集未来可能会增长,或者除了machine_type之外可能还有其他变量。理想情况下,我的 .j2 标记会更加通用,因此 tags: {{ my_tags }}my_tags 的行将在其他地方(即在 vars 文件中?)定义为 {{ perm_tags }}{{ optional_tags }} 连接

标签: jinja2 ansible ansible-playbook


【解决方案1】:

您不需要设置 var,因为我猜您稍后会尝试为某些条件设置 var。 只是在那里创造条件

- name: Later task
  shell: "command is here"
  when: {{ existing_ansible_var }} == "string1"

并获得利润

【讨论】:

    【解决方案2】:

    这样的东西会起作用,但它很难看。正如@podarok 在他的回答中提到的那样,这可能是不必要的,具体取决于您正在尝试做什么:

    - name: set default
      set_fact: new_ansible_var= ""
    
    - name: set to 'a'
      set_fact: new_ansible_var= "a"
      when: "{{ existing_ansible_var }} == string1"
    
    - name: set to 'b'
      set_fact: new_ansible_var= "b"
      when: "{{ existing_ansible_var }} == string2"
    

    等等

    【讨论】:

    • 这些示例的第 2 行应如下所示:set_fact: new_ansible_var= "a" 才能运行它。我进行了更改,现在运行播放时出现以下错误,这非常无用:TASK: [sbc | set to 'a'] ***************************************************** fatal: [my-machine] =&gt; error while evaluating conditional: existing_ansible_var == string1 FATAL: all hosts have already failed -- aborting
    • 我还必须使第三行看起来像:when: "{{ existing_ansible_var }} == string1"
    【解决方案3】:

    如果您只想根据existing_ansible_var 的值在模板中输出一个值,您只需使用字典并使用existing_ansible_var 提供它。

    {{ {"string1": "a", "string2": "b"}[existing_ansible_var] | default("") }}
    

    你可以用同样的方法定义一个新变量:

    {% set new_ansible_var = {"string1": "a", "string2": "b"}[existing_ansible_var] | default("") -%}
    

    如果existing_ansible_var 可能不一定被定义,您需要使用您的字典中不存在的default() 来捕获它:

    {"string1": "a", "string2": "b"}[existing_ansible_var | default("this key does not exist in the dict")] | default("")
    

    您也可以在剧本中定义它,然后在模板中使用new_ansible_var

    vars: 
       myDict:
         string1: a
         string2: b
       new_ansible_var: '{{myDict[existing_ansible_var | default("this key does not exist in the dict")] | default("") }}'
    

    【讨论】:

    • 这是一个很好的解决方案!现在我想知道如何在不使用 Jinja 的情况下在 Ansible 中做到这一点......
    • ... 或者如果我可以在剧本中使用相同的语法/结构并能够在同一剧本中访问new_ansible_var
    • 是的,这也是可能的。我在上面的答案中添加了一个示例。
    • 如果您在编写角色时需要这个,您可以将所需的字典放入角色变量文件vars/main.yml 中的变量中。通常这比包含字典数据和逻辑的一行更容易阅读,并且角色中的代码变得更加不言自明。
    猜你喜欢
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 2021-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多