Ansible变量覆盖另一个角色中的默认值
我不确定如何覆盖Ansible中角色之间的变量 为了简化设置,我将两个角色应用于同一台主机。第一个角色在其Ansible变量覆盖另一个角色中的默认值,ansible,Ansible,我不确定如何覆盖Ansible中角色之间的变量 为了简化设置,我将两个角色应用于同一台主机。第一个角色在其default/main.yml中定义了一个变量: do_some_task: yes 并在其任务中查找该变量: - name: Some Task when: do_some_task 第二个角色覆盖其vars/main.yml中的角色,该角色应优先于默认值: do_some_task: no 但是,任务仍在运行,这表明变量未被重写。似乎覆盖的范围是第二个角色的任务。我通过向两个
default/main.yml
中定义了一个变量:
do_some_task: yes
并在其任务中查找该变量:
- name: Some Task
when: do_some_task
第二个角色覆盖其vars/main.yml
中的角色,该角色应优先于默认值:
do_some_task: no
但是,任务仍在运行,这表明变量未被重写。似乎覆盖的范围是第二个角色的任务。我通过向两个角色添加调试任务来测试这一点:
- name: Test some task
debug: "msg='do_some_task = {{ do_some_task }}'"
这确认第一个角色看到的变量值与第二个不同
TASK: [role1 | Test some task]
ok: [myhost] => {
"msg": "do_some_task = True"
}
...
TASK: [role2 | Test some task]
ok: [myhost] => {
"msg": "do_some_task = False"
}
对此的常见答案似乎是设置清单或主机变量中的变量。然而,这并不是特别枯燥:如果在不同的清单中有许多主机,那么必须在许多地方设置相同的变量
那么,是否有某种方法可以覆盖另一个角色的变量?如果要用另一个角色包装一个角色,则可以通过专门传递外部角色的变量来覆盖内部角色的变量 因此,根据您的示例,您将有一个内部角色任务:
- name: Some Task
when: do_some_task
此内部角色的变量集如下所示:
do_some_task: true
- name: outer-role
hosts: outer-role-nodes
roles:
- role: outer-role
- { role: inner role,
do_some_task: "{{ do_some_task }}" }
然后,在剧本中调用外部角色时,可以覆盖内部角色,如下所示:
do_some_task: true
- name: outer-role
hosts: outer-role-nodes
roles:
- role: outer-role
- { role: inner role,
do_some_task: "{{ do_some_task }}" }
这应该从外部角色获取
do\u some\u task
变量,并覆盖内部角色的do\u some\u task
如果您使用Ansible>=2.2,您可能可以使用包含\u角色
:
- name: Pass variables to role
include_role:
name: role1
vars:
do_some_task: "{{ role2_do_some_task }}"
您还可以使用Anslbie>=1.3的角色依赖项。编写role2/meta/main.yml
如下:
---
dependencies:
- { role: role1, do_some_task: yes }
如果两者都不需要,考虑到您不想将变量定义放在playbook中,那么定义它们的唯一合理位置是在库存中
您可以在同一组中定义需要覆盖角色1默认值的角色:
[overwrite_do_some_task]
host1
host3
[overwrite_do_some_task:vars]
do_some_task=yes
如果在运行role1之前没有给出变量值,那么预期的行为是,使用角色默认值,这是OP观察到的
注意:为角色变量添加前缀更具可读性。i、 e.使用
role1\u do\u some\u task
代替do\u some\u task
。这样做,你就不太可能迷惑自己。请参阅。TLDR:为了能够继承默认值/config,您必须将其划分为其他角色,并将其包含在将要使用的位置
解决这一问题的一种方法是创建一个单独的角色,该角色将保留默认值,然后将其导入/包含到主角色中。使用默认配置创建的角色可以相互导入,作为从默认配置“继承”配置的一种方式,然后主角色将加载最顶层的配置角色,并按预期获取所有配置
例如,在我的例子中,我希望有一个具有“堆叠”配置级别的模板系统。。在默认情况下,它们都是从基本配置集继承的,而不是从变量继承的,否则您无法从清单中重写它
这些角色是:
- 模板库
- 模板配置标准
- 模板配置性能
- files/ (contains all the template files)
- tasks/
|---- main.yml (contains the code below)
# Includes the template configuration based on the selected template
- include_role:
name: "template-config-{{ selected_template}}"
public: true # Important so that configs are exposed here
- ** Does templating work **
角色模板配置标准:
- defaults/
|---- main.yml (contains a bunch of configuration)
角色模板配置性能:
- defaults/
|---- main.yml (contains just a few config items, overriding stuff from the role above)
- tasks/
|---- main.yml (contains below code)
#Simply includes the standard configuration.. all this does is take defaults in the defaults/main.yml file from the below role
- import_role:
name: template-config-std
考虑到所需的变量继承和优先级,上述方法似乎工作得很好。很遗憾,您不能让将使用变量的角色与包含默认变量的角色竞争,因为它将始终获胜。。但无论如何,上面的例子似乎没问题:)。。如果您需要在支持角色中添加更多的内容,而不仅仅是配置,那么您必须在主角色上创建一种机制,但希望没有什么非常复杂的
祝你好运,祝你好运
PS:这种方法最重要的一个方面是,我们在配置上保持默认/优先级,这意味着库存可以在需要时覆盖它 我从未测试过这一点,但始终认为变量,尤其是默认值,只适用于它们所定义的角色。不过,应该使用
set\u fact
模块。您可能需要了解变量位置、角色默认值等。设置事实有两个缺点。首先,它只在该任务运行之后才应用,所以如果role1在role2之前运行,则它不应用。第二,如果使用标记告诉Ansible只应用第一个角色而不应用第二个角色的任务,它将不会运行该任务。include_vars
任务也是如此。为什么不在默认值中为第二个角色定义变量呢?你说的角色不是指两项任务,对吗?我尽量避免把变量放在剧本里。这个问题可以归结为一个单一的变量,因为这更容易,但在实践中,它很可能是大量的变量。我不想在几本剧本或几份清单中重复这些。我想设置一个标志——将主机分配给角色——并让它引入所有必要的配置。干得好。@Marc,你觉得有什么满意的吗?不太满意。事实上,Ansible不喜欢从一个角色泄露到另一个角色。