如何在Ansible清单文件中将列表值指定为变量?

62

我需要类似于(Ansible清单文件)的东西:

[example]
127.0.0.1 timezone="Europe/Amsterdam" locales="en_US","nl_NL"

然而,ansible不会将'locales'识别为列表。

7个回答

106

您可以像这样传递列表或对象:

[example]
127.0.0.1 timezone="Europe/Amsterdam" locales='["en_US", "nl_NL"]'

11
@ryanyuyu,这不仅不是与问题中的代码相同,而且还是原帖作者正在寻找的确切解决方案。你测试过了吗?Ryler和我都测试过:它是有效的。这应该是被采纳的答案,而不是被点踩的。 - udondan
6
是的,我也可以确认这个方法是有效的。例如在使用“with_items”语句时非常有用。你甚至可以像这样创建类似于字典的对象。我使用它来在清单文件中定义nginx身份验证用户和密码:nginx_auth='[ {"user": "user1", "pass": "pass1"}, {"user": "user2", "pass": "pass2"}]' - Will Harris
这是ini文件的最简洁解决方案吗?如果您有20多个项目和5个主机需要进行配置,该怎么办?很高兴知道,但现在它能够工作。 - JohnnyQ
1
@WillHarris,你能否将多个项目放在一个键中吗?例如:{"user":["user1","user2"]} - JohnnyQ
@WillHarris 我不确定如何使用Jinja2实现这个,因为它只是用于模板化的目的,具体我想要实现的内容在这里:http://stackoverflow.com/questions/37486972/how-to-iterate-through-n-level-children-of-hosts-using-ansible-playbook。 - JohnnyQ
显示剩余3条评论

33

复杂变量最好在host_vars文件中定义,而不是在inventory文件中定义,因为host_vars文件支持YAML语法。

尝试创建一个host_vars/127.0.0.1文件,并将以下内容加入其中:

---
timezone: Europe/Amsterdam
locales:
  - en_US
  - nl_NL

2
谢谢,那是我当前的工作方式 :) 您的回答是否意味着您无法在清单文件(和--extra-vars)中指定列表变量? - rmuller
@rmuller 我不知道在ini文件或命令行中是否可以指定列表变量。如果您在ansible邮件列表上提问,可能会更快获得答复。 - Lorin Hochstein
@rmuller 我也建议加入 #ansible IRC 频道,那里的人通常很快就能提供帮助 :-) - jabclab
我认为在库存中不可能实现。我尝试了带有破折号前缀列表的xyz=,但是出现了错误“ERROR:分配给组的变量必须采用key=value形式”。 - mahemoff
我也考虑过使用这种方法,但它很繁琐。特别是如果你有很多站点要配置的话。 - JohnnyQ

20

Ryler的回答在这种特定情况下是好的,但我在使用模板模块的其他变体时遇到了问题。

[example]
127.0.0.1 timezone="Europe/Amsterdam" locales='["en_US", "nl_NL"]'

他的原始示例代码可以正常运行。

以下变量适用于模板。基本上,如果是字符串,则必须记得使用内部双引号,否则整个结构将解析为单个字符串。如果只有数字或“True”或“False”(不是“yes”),则没问题。在这种情况下,如果它有外部引号,则无法将其与模板一起使用。

除了模板模块之外,我还没有对它们在哪些内部使用情况下会出现问题进行全面检查。

我正在使用Ansible 2.2.1。

[example:vars]
# these work
myvar1=["foo", "bar"]
myvar2=[1,2]
myvar3=[True,False]

# These fail, they get interpreted as a single string.
myvar4=[yes, no]
myvar5=[foo,bar]
myvar6='["foo", "bar"]'

这个额外的信息帮助我解决了一个非常难以理解的变量解析问题。谢谢! - immortal squish
1
一些额外的信息:我认为差异是由于不同的解析路线造成的。在[group:vars]中,所有内容都直接传递为INI_PARSER->YAML_PARSER,包括双引号。因此,YAML解析器将其解释为字符串。在主机名之后,它通过类似于用于模块“等式样式”参数的解析器的类似解析器:INI_PARSER->ANSIBLE_ARG_PARSER->YAML_PARSER。在后一种情况下,ANSIBLE_ARG_PARSER解释双引号字符串并将内容(不带引号)传递给YAML解析器。 - Sparky

7
你可以尝试使用Split函数。
#inventory file
[example]
127.0.0.1 timezone="Europe/Amsterdam" locales="en_US","nl_NL"

#role file
---
- debug: msg="{{ item }}"
  with_items: locales.split(',')

0

带有变量的INI文件如下所示

$ cat ./vars/vars.yml

lvol_names=['2g-1','2g-2','2g-3']

该变量表示列表类型

 lvol_names:
       - 2g-1
       - 2g-2
       - 2g-3

变量可以通过查找在playbook中读取: $ cat ./play.yml
- name: play1
  hosts: kub2_data_nodes
  become: yes


  vars:
 
     - lvol_names: "{{ lookup('ini', 'lvol_names type=properties file=./vars/vars.yml') }}"
     

0
我认为问题在于您定义变量的位置。
如果它在以下位置:
[host:vars] var=["a", "b"]
否则:
[hosts] host1 var='["a", "b"]'

-2

您可以自定义一个过滤器,将字符串分割成列表

Github ansible example展示了如何创建自定义过滤器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接