我有一个 Ansible 任务,它循环遍历列表,并为列表中的每个项目运行一个角色,使用include_role
。对于循环的每次迭代,我想传递一组不同的变量。目前,我正尝试通过将列表创建为字典列表来实现这一点,该列表可以--extra-vars
在运行时使用来指定。
例如我有任务:
- name: Run the test role
include_role:
name: test_role
loop: '{{ input_list }}'
还有input_list
:
input_list:
- var1: foo
var2: bar
var3: baz
- var1: hello
var3: world
但此时我该如何将当前的变量集传递给角色?我最初尝试分别定义每个变量:
- name: Run the test role
include_role:
name: test_role
vars:
var1: '{{ item.var1 }}'
var2: '{{ item.var2 }}'
var3: '{{ item.var3 }}'
loop: '{{ input_list }}'
这可以工作,但如果缺少一个变量input_list
(即应该回退到角色默认值中指定的默认值或剧本开头的变量值),剧本将失败。所以我尝试使用 Jinja2 的default
过滤器:
- name: Run the test role
include_role:
name: test_role
vars:
var1: '{{ item.var1 | default('foo') }}'
var2: '{{ item.var2 | default('bar') }}'
var3: '{{ item.var3 | default('baz') }}'
loop: '{{ input_list }}'
同样,这种方法可行,但有点混乱,因为每个变量都需要定义,而且它不使用角色的默认值。有没有更好的方法来实现这样的效果?
答案1
其中一个选项是创建替代默认值。例如,创建一个用于测试的最小角色
shell> cat roles/test_role/defaults/main.yml
var1: default_1
var2: default_2
var3: default_3
shell> cat roles/test_role/tasks/main.yml
- debug:
msg: "{{ var1 }} {{ var2 }} {{ var3 }}"
任务
- include_role:
name: test_role
给出
msg: default_1 default_2 default_3
让我们创建替代默认值,例如
shell> cat roles/test_role/defaults/alt.yml
var1: "{{ alt.var1|default('default_1') }}"
var2: "{{ alt.var2|default('default_2') }}"
var3: "{{ alt.var3|default('default_3') }}"
并在包含中使用它。下面的任务给出了相同的结果
- include_role:
name: test_role
defaults_from: alt.yml
现在,让我们用备用默认值定义字典
- include_role:
name: test_role
defaults_from: alt.yml
loop: '{{ input_list }}'
vars:
alt: "{{ item }}"
给出
msg: foo bar baz
msg: hello default_2 world
下一个选项是创建和使用替代变量
shell> cat roles/test_role/vars/alt.yml
var1: "{{ alt.var1|default('default_1') }}"
var2: "{{ alt.var2|default('default_2') }}"
var3: "{{ alt.var3|default('default_3') }}"
例如,下面的任务给出了相同的结果。唯一的区别是优先权。
- include_role:
name: test_role
vars_from: alt.yml
loop: '{{ input_list }}'
vars:
alt: "{{ item }}"