在Ansible中有条件地合并主词典和辅助词典

在Ansible中有条件地合并主词典和辅助词典,ansible,jinja2,Ansible,Jinja2,我正在尝试合并包含许多应用程序设置的两个词典。在连接到各个主机的主字典中,它包含特定于该服务器的内容(例如,与应用程序的git repo相关的版本): 项目/host\u vars/host\u name.yml 然后,第二个包含特定于应用程序的所有设置: 项目/group_vars/apps.yml 根据这些,我想构建一个字典,将两者的值结合起来,但前提是应用程序存在于“installed_apps”(已安装的应用程序)中,以便ansible拥有它需要在特定服务器上安装的所有应用程序的所有详细

我正在尝试合并包含许多应用程序设置的两个词典。在连接到各个主机的主字典中,它包含特定于该服务器的内容(例如,与应用程序的git repo相关的版本):

项目/host\u vars/host\u name.yml 然后,第二个包含特定于应用程序的所有设置:

项目/group_vars/apps.yml 根据这些,我想构建一个字典,将两者的值结合起来,但前提是应用程序存在于“installed_apps”(已安装的应用程序)中,以便ansible拥有它需要在特定服务器上安装的所有应用程序的所有详细信息:

new_dict:
  pineapple:
    version: master
    setting1: blah
    setting2: di
    setting3: blah
  pear:
    version: "1.1"
    setting3: there
在Python中,它将是这样的:

installed_apps = {
    "pineapple": {"version": "master"},
    "pear": {"version": "1.1"}
}

all_apps = {
    'pineapple': {'setting1': 'blah', 'setting2': 'di', 'setting3': 'blah'},
    'apple': {'setting1': 'hi'},
    'pear': {'setting3': 'there'}
}

new_dict = dict()
for k, v in all_apps.items():
    if k in installed_apps:
        new_dict[k] = v
        new_dict[k].update(installed_apps[k])

但我无法用Ansible解决这个问题。

你可以用Ansible的过滤器解决这个问题

以下示例假设如下:

- hosts: localhost
  gather_facts: false
  vars:
    installed_apps:
      pineapple:
        version: master
      pear:
        version: "1.1"
    all_apps:
        pineapple:
          setting1: blah
          setting2: di
          setting3: blah
        apple:
          setting1: hi
        pear:
          setting3: there
首先,我们创建一个新字典(
installed\u app\u settings
),该字典包含
所有\u apps
中的项目,这些项目在
installed\u apps
中具有匹配的键:

- set_fact:
    installed_app_settings: >
      {{ (installed_app_settings|default([])) + [{item: all_apps[item]}] }}
  with_items: "{{ installed_apps }}"

- debug:
    var: installed_app_settings
现在我们使用它来更新
installed_apps
变量,并使用在上一个
set_fact
任务中提取的值:

- set_fact:
    installed_apps: >
      {{ installed_apps|combine(item, recursive=True) }}
  with_items: "{{ installed_app_settings }}"

- debug:
    var: installed_apps
其结果是:

ok: [localhost] => {
    "installed_apps": {
        "pear": {
            "setting3": "there", 
            "version": "1.1"
        }, 
        "pineapple": {
            "setting1": "blah", 
            "setting2": "di", 
            "setting3": "blah", 
            "version": "master"
        }
    }
}

…我想这就是你想要的。

太棒了!非常感谢。我只添加了一个循环控件
标签:“{{item.keys()}}”
,位于第二个集合上,这样它就不会对所有设置发送垃圾邮件。
- set_fact:
    installed_apps: >
      {{ installed_apps|combine(item, recursive=True) }}
  with_items: "{{ installed_app_settings }}"

- debug:
    var: installed_apps
ok: [localhost] => {
    "installed_apps": {
        "pear": {
            "setting3": "there", 
            "version": "1.1"
        }, 
        "pineapple": {
            "setting1": "blah", 
            "setting2": "di", 
            "setting3": "blah", 
            "version": "master"
        }
    }
}