在 Ansible/Jinja2 中设置 var 的 case 语句

Posted

技术标签:

【中文标题】在 Ansible/Jinja2 中设置 var 的 case 语句【英文标题】:Case statement for setting var in Ansible/Jinja2 【发布时间】: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 连接 【参考方案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 中的变量中。通常这比包含字典数据和逻辑的一行更容易阅读,并且角色中的代码变得更加不言自明。

以上是关于在 Ansible/Jinja2 中设置 var 的 case 语句的主要内容,如果未能解决你的问题,请参考以下文章

使用条件在 smarty 中设置 var

在 geometryReader 中设置 @State var

如何在HTML标签和JS中设置CSS3 var变量

自动化运维工具-Ansible Jinja2模板

ansible-playbook模板化(jinja2)

在 Firebase 完成块中设置 @Published var 不更新 SwiftUI 视图