在Ansible,在角色中,我有这样的vars文件:
vars/
app1.yml
app2.yml
每个文件都包含特定于应用程序/网站的变量,如下所示:
name: app1
git_repo: https://github.com/philgyford/app1.git
# ...
理想情况下,如果没有预先知道哪些应用程序具有可变文件的任务,我想最终得到一个名为apps
的数组,如下所示:
apps:
- name: app1
git_repo: https://github.com/philgyford/app1.git
# ...
- name: app2
git_repo: https://github.com/philgyford/app2.git
# ...
即将文件中的变量合并为一个。
我知道我可以像这样加载所有变量文件:
- name: Load var files
with_fileglob:
- ../vars/*.yml
include_vars: '{{ item }}'
但鉴于每个文件具有相同的变量名称,它将覆盖每个先前的变量集。我无法看到加载变量并将它们放入apps
数组的方法。
我愿意稍微重新安排事情,如果这是使这样的事情成为可能的唯一方法。
答案 0 :(得分:7)
你做不到。变量将始终覆盖具有相同名称的变量。对于这个确切的设置,你唯一能做的就是write your own vars plugin读取这些文件并将它们合并到一个数组中。
如果您愿意更改应用定义的结构,则可以使用哈希和set your hash_behavior=merge
。在每个vars文件中,您将有一个如下定义:
time == '2016-02-22
2016-02-22 00:00:00
当Ansible加载两个文件时,它会自动将它们合并到:
apps:
app1:
git_repo: https://github.com/philgyford/app1.git
但请注意,apps:
app2:
git_repo: https://github.com/philgyford/app2.git
从根本上改变了Ansible在全局范围内的默认行为。确保您的所有角色都没有此设置的问题。文件提到:
除非您认为绝对需要,否则我们通常建议您不要使用此设置
如果您仍然使用Ansible 1,则可以使用我的旧插件之一:include_vars_merged。基本上,这会将apps:
app1:
git_repo: https://github.com/philgyford/app1.git
app2:
git_repo: https://github.com/philgyford/app2.git</pre>
的行为添加到单个任务中。
我还没有考虑将其迁移到Ansible 2,目前看起来我不再需要它了。
答案 1 :(得分:1)
从Ansible v2.0开始,您可以执行以下操作:
- name: merging hash_a and hash_b into hash_c
set_fact: hash_c="{{ hash_a|combine(hash_b) }}"
在Ansible过滤器下检查更多内容-组合哈希/字典(来自Jinja2)
答案 2 :(得分:1)
使用属性name并将包含的变量放入字典中。使字典的 name 满足您的需求。例如
- name: Load var files
include_vars:
file: "{{ item }}"
name: "{{ 'incl_vars_' ~ item|basename|splitext|first }}"
with_fileglob:
- vars/*.yml
然后,使用查找插件varnames(版本2.8中的新增功能),找到所有词典,然后迭代该列表。在循环中,使用查找插件var(2.5版中的新增功能)并创建列表。例如
- set_fact:
my_vars: "{{ my_vars|default([]) + [lookup('vars', item)] }}"
loop: "{{ query('varnames', '^incl_vars_(.*)$') }}"
- debug:
var: my_vars
给予
my_vars:
- git_repo: https://github.com/philgyford/app2.git
name: app2
- git_repo: https://github.com/philgyford/app1.git
name: app1
答案 3 :(得分:0)
自RewriteRule
以来,Ansible 2.2
(link)模块已经扩展了很多。
现在可以执行以下操作:
include_vars
- include_vars:
name: 'apps'
dir: '../vars'
extensions:
- 'yaml'
- 'yml'
是关键。在模块页面上:
将包含的变量分配给的变量的名称。如果省略(为空),它们将成为顶级变量。
这允许您转换:
name
app1.yml:
vars/
app1.yml
app2.yml
...
app2.yml:
name: app1
git_repo: https://github.com/philgyford/app1.git
# ...
进入...
name: app2
git_repo: https://github.com/philgyford/app2.git
# ...
答案 4 :(得分:0)
好吧,您不能直接构建数组,但是可以通过dict达到相同的效果。
假设您要构造一个数组:
[{
name: 'bob',
age: 30
}, {
name: 'alice',
age: 35
}]
您可以将每个元素放在文件中,例如:
bob:
name: bob
age: 30
alice:
name: alice
age: 35
将这些文件放在相同的目录中(例如user
),然后使用include_vars
加载整个目录:
- name: Include vars
include_vars:
name: users
dir: user
这会给你一个字典users
:
users:
alice:
name: alice
age: 35
bob:
name: bob
age: 30
使用dict2items
过滤器,您将获得所需的数组
答案 5 :(得分:0)
想要通过获取与模式匹配的变量列表来发布可能的替代解决方案,那么您就可以处理所有这些变量,进行手动合并。
以下代码块提供了一个示例,该示例提取与特定模式匹配的所有变量并进行循环。您可以合并它们来设置一个新事实,也可以简单地单独处理它们。
- name: "debug2" debug:
msg: "value is: {{ lookup('vars', item) }} "
loop: "{{ hostvars[inventory_hostname] | select('match', '^linux_hosts_entries') |list }}"
有关更多详细信息,请参见以下post。
答案 6 :(得分:0)
如果您不想更改哈希的默认行为。我建议你我的解决方案。 当Ineed合并它们时,我定义了多个变量(具有相同的正则表达式),并从hostvars中过滤掉它们。例如:
- name: Combine variables with prefix enabled_services
debug:
msg: "{{ hostvars[inventory_hostname].keys() | map('regex_search', 'enabled_services.*') | select('string') | list }}"
答案 7 :(得分:0)
我用过这个:
- name: Load data
run_once: true
set_fact:
my_data: "{{ my_data|default([]) + [lookup('file', item) | from_yaml] }}"
with_fileglob: "../data/*.yml" # relative to this file