Ansible变量覆盖默认为另一个角色

时间:2015-12-16 14:16:57

标签: ansible

我不确定如何在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" 
}

这个问题的常见答案似乎是设置清单或主机变量中的变量。然而,这并不特别干:如果你有不同库存的许多主机,你必须在很多地方设置相同的变量。

那么是否有某种方法可以覆盖另一个角色的变量?

3 个答案:

答案 0 :(得分:1)

如果您使用Ansible> = 2.2,则可以使用include_roles

  - 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中,定义它们的唯一明智的地方是库存。

您可以在同一组中定义需要覆盖role1默认值的那些:

  [overwrite_do_some_task]
  host1
  host3

  [overwrite_do_some_task:vars]
  do_some_task=yes

如果在运行role1之前没有给出变量值,那么预期的行为是,使用角色默认值,这是OP观察到的。

注意:为角色变量添加前缀更具可读性。即使用role1_do_some_task代替do_some_task。这样做,你不太可能混淆自己。请参阅Ansible Best Practices: The Essentials

答案 1 :(得分:0)

如果要将角色包装为其他角色,则可以通过从外部角色专门传递变量来覆盖内部角色的变量。

因此,根据您的示例,您将拥有以下内部角色任务:

- 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变量并覆盖内部角色do_some_task

答案 2 :(得分:0)

TLDR:为了能够继承默认值/配置,你必须将它分离到其他角色中,并将它包含在将要使用的地方

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

例如,在我的情况下,我想要一个模板系统,它具有“堆叠”级别的配置..所有这些都继承自默认配置的基本配置集,而不是变量,否则您无法覆盖它来自库存。

这些是角色:

  • 模板库
  • 模板配置标准
  • 模板配置性能

-> Template-base 具有基于所选配置部署模板的整个逻辑.. 这有一些逻辑将所选配置角色包含在任务文件中

-> template-config-standard 具有在 defaults/main.yml 中定义的标准配置集,仅此而已

-> template-config-performance 对 defaults/main.yml 文件进行了一些额外的调整,但没有重复 template-config-standard 中的任何内容,而是简单地在任务/main 的“import_role”上使用它。 yml 文件.. 可能依赖项仍然有效

以更详细的方式:

角色模板库:

- 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:这种方法最重要的方面之一是我们保持配置的默认/优先级,这意味着库存可以在需要时覆盖它!