Объедините вложенные словари в ansible - PullRequest
0 голосов
/ 21 января 2020

У меня есть 2 разных словаря, которые содержат информацию о приложении, которую мне нужно объединить.

landscape_dictionary:

{
  "app_1": {
    "Category": "application",
    "SolutionID": "194833",
    "Availability": null,
    "Environment": "stage",
    "Vendor/Manufacturer": null
  },
  "app_2": false
}

app_info_dictionary:

{
  "app_1": {
    "app_id": "6886817",
    "owner": "owner1@nomail.com",
    "prod": [
      "server1"
    ],
    "stage": []
  },
  "app_2": {
    "app_id": "3415012",
    "owner": "owner2@nomail.com",
    "prod": [
      "server2"
    ],
    "stage": [
      "server3"
    ]
  }
}

Это код Я использую для объединения обоих словарей

- set_fact:
    uber_dict: "{{app_info_dictionary}}"

- set_fact:
    uber_dict: "{{ uber_dict | default ({}) | combine(new_item, recursive=true) }}"
  vars:
    new_item: "{ '{{item.key}}' : { 'landscape': '{{landscape_dictionary[item.key]|default(false)}}' } }"
  with_dict: "{{ uber_dict }}"

- debug:
    msg: "{{item.key}}: {{item.value}}"
  with_dict: "{{uber_dict}}"

Если значение в landscape_dictionary равно false, оно добавит его в uber_dict без проблем. Но если значение содержит информацию, произойдет сбой.

Это ошибка:

fatal: [127.0.0.1]: FAILED! => {"msg": "|combine expects dictionaries, got u\"{ 'app_1' : { 'landscape': '{u'Category': u'application', u'SolutionID': u'194820', u'Availability': None, u'Environment': 'stage', u'Vendor/Manufacturer': None}' } }\""}

В чем может быть проблема?
Нужно ли выполнять дополнительное объединение, когда я задаю переменная в set_fact?

Спасибо

1 Ответ

0 голосов
/ 21 января 2020

Этот синтаксис недопустим или, по крайней мере, не выполняет то, что вы думаете:

new_item: "{ '{{item.key}}' : { 'landscape': '{{landscape_dictionary[item.key]|default(false)}}' } }"

Foremost, ansible будет только автоматически приводить JSON строк в dict, но вы использовали синтаксис python.

Во-вторых, способ динамического построения dict состоит не в том, чтобы использовать jinja2 для построения текста, а скорее используйте тот факт, что jinja2 - это почти язык программирования:

new_item: "{{
  {
    item.key: {
      'landscape': landscape_dictionary[item.key]|default(false)
    }
  }
}}"

Каждый раз, когда вы сталкиваетесь с вложенными блоками интерполяции jinja2, это запах кода, который вы слишком много думаете о проблеме, как текст (под вложенным я имею в виду {{ something {{nested}} else }})

...