附加到 group_vars 中的 Ansible 字典而不使用 hash_behaviour = merge

EM0*_*EM0 7 ansible

我想定义一个字典变量,各个主机组可以将自己的密钥添加到group_vars 中(不使用set_fact)。例如这样的事情:

group_vars\ftp_servers.yml:

important_ports:
    ftp: 21
Run Code Online (Sandbox Code Playgroud)

group_vars\web_servers.yml:

important_ports:
    http: 80
Run Code Online (Sandbox Code Playgroud)

这样,当在具有这两个角色的服务器上运行时,字典就会组合起来,即important_ports=

{
    ftp: 21,
    http: 80
}
Run Code Online (Sandbox Code Playgroud)

这正是hash_behaviour = merge所做的,但它已被弃用,并将在 Ansible 2.13 中删除。如果没有它,我如何实现同样的目标?

我见过的唯一推荐的解决方案是使用combine过滤器:

set_fact:
  important_ports: "{{ important_ports | combine({ http: 80 }) }}"
Run Code Online (Sandbox Code Playgroud)

这在任务中有效set_fact,但在 group_vars 中失败,并显示“在模板字符串中检测到递归循环:{{ important_ports | merge({ http: 80 }) }}

我什至尝试将group_vars/all中的变量初始化为空字典 ( important_ports: {}) ,该变量应该在其他 group_vars 之前进行评估,但它仍然给出相同的错误。

Zei*_*tor 5

针对这个特定问题的(不太干净......)可能的解决方案。这是基于您在特定组端口的 var 名称中使用组名称的约定。

请注意,如果您使用不同的值重新定义相同的端口名称,则最新加载的组将获胜。

鉴于以下一体式库存inventories/mergegroups/hosts.yml

---
all:
  vars:
    ansible_connection: local
    important_ports: >-
      {%- set result={} -%}
      {%- for group in groups -%}
      {{ result.update(lookup('vars', group + '_important_ports', default={})) }}
      {%- endfor -%}
      {{ result }}

ftp_servers:
  vars:
    ftp_servers_important_ports:
      ftp: 21
  hosts:
    a:
    b:

web_servers:
  vars:
    web_servers_important_ports:
      http: 80
  hosts:
    a:

other_group:
  vars:
    other_group_important_ports:
      mysql: 3306
  hosts:
    a:
    b:

no_port_group:
  # as you can see no port definition here.
  hosts:
    a:
    b:
    c:
Run Code Online (Sandbox Code Playgroud)

我们得到 3 个不同主机的以下结果:

$ ansible -i inventories/mergegroups/ a -m debug -a msg="{{ important_ports }}"
a | SUCCESS => {
    "msg": {
        "ftp": 21,
        "http": 80,
        "mysql": 3306
    }
}
$ ansible -i inventories/mergegroups/ b -m debug -a msg="{{ important_ports }}"
b | SUCCESS => {
    "msg": {
        "ftp": 21,
        "mysql": 3306
    }
}
$ ansible -i inventories/mergegroups/ c -m debug -a msg="{{ important_ports }}"
c | SUCCESS => {
    "msg": {}
}

Run Code Online (Sandbox Code Playgroud)