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 但是,任务仍在运行,这表明变量未被重写。似乎覆盖的范围是第二个角色的任务。我通过向两个

我不确定如何覆盖Ansible中角色之间的变量

为了简化设置,我将两个角色应用于同一台主机。第一个角色在其
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,您必须将其划分为其他角色,并将其包含在将要使用的位置

解决这一问题的一种方法是创建一个单独的角色,该角色将保留默认值,然后将其导入/包含到主角色中。使用默认配置创建的角色可以相互导入,作为从默认配置“继承”配置的一种方式,然后主角色将加载最顶层的配置角色,并按预期获取所有配置

例如,在我的例子中,我希望有一个具有“堆叠”配置级别的模板系统。。在默认情况下,它们都是从基本配置集继承的,而不是从变量继承的,否则您无法从清单中重写它

这些角色是:

  • 模板库
  • 模板配置标准
  • 模板配置性能
->模板库具有基于所选配置部署模板的全部逻辑。。这有一些逻辑,可以在任务文件中包含所选的配置角色

->template config standard在defaults/main.yml中定义了标准配置集,没有其他内容

->模板配置性能在defaults/main.yml文件上有一些额外的调整,但不重复模板配置标准中的任何内容,而只是在tasks/main.yml文件的“import_role”上使用它。。可能依赖关系仍然有效

再举一个例子:

角色模板库:

- 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不喜欢从一个角色泄露到另一个角色。