Подтвердить что ты не робот

Можно ли сгладить списки списков с помощью Ansible/Jinja2?

Моя основная проблема заключается в том, что при создании набора aws-серверов я хочу настроить их, чтобы они знали друг о друге.

После создания каждого сервера их данные сохраняются в зарегистрированном "сервере" var (показано ниже). То, что я действительно хочу сделать после создания, запускает такую ​​задачу:

- name: Add servers details to all other servers
  lineinfile:
    dest: /path/to/configfile
    line: "servername={{ item.1.private_ip }}"
  delegate_to: "{{ item.0.public_dns_name }}"
  with_nested:
    - list_of_servers
    - list_of_servers

Присвоение списка дважды "to_nested" имеет важное значение.

Получение списка списка достаточно просто:

"{{ servers.results | map(attribute='tagged_instances') | list }}"

который возвращает:

[ 
  [ { "private_ip": "ip1", "public_dns_name": "dns1" } , { ... }],
  [ { ... }, { ... } ]
]

но как бы вы превратили это в:

[
  { "private_ip": "ip1", "public_dns_name": "dns1" },
  { ... },
  { ... }, 
  { ... }
]

Зарегистрированный "сервер" var выглядит следующим образом:

"servers": {
    "changed": true,
    "msg": "All items completed",
    "results": [
        {
            ...
            "tagged_instances": [
                {
                    ...
                    "private_ip": "ip1",
                    "public_dns_name": "dns1",
                    ...
                },
                {
                    ...
                    "private_ip": "ip2",
                    "public_dns_name": "dns2",
                    ...
                }
            ]
        },
        {
            ...
            "tagged_instances": [
                {
                    ...
                    "private_ip": "ip3",
                    "public_dns_name": "dn3",
                    ...
                },
                {
                    ...
                    "private_ip": "ip4",
                    "public_dns_name": "dns4",
                    ...
                }
            ]
        },
        ...
    ]
}

Примечание. У меня есть довольно уродливое решение, используя "with_flattened" и инструкцию debug для создания нового зарегистрированного var 'flattened_servers', который затем я снова сопоставляю. Но я надеюсь на более элегантное решение:)

4b9b3361

Ответ 1

Вы можете сделать представление списка, чтобы преобразовать его в список dicts.

Например:

- name: Convert
  shell: python -c "print [x for b in {{ servers }}['servers']['results'] for x in b['tagged_instances']]"
  register: my_list_of_dicts

Предполагая, что переменная {{ servers }} содержит весь словарь (не json).

Ответ 2

Jinja2 поставляется со встроенным фильтром sum, который можно использовать как:

{{ servers.results | sum(attribute='tagged_instances', start=[]) }}

Ответ 3

Просто хотел перечислить "уродливое" обходное решение, поскольку код python не работал у меня

  - debug: var=item
    with_flattened:
      - "{{ servers.results|map(attribute='tagged_instances')|list }}"
    register: servers_instances_tmp
    no_log: True

  - set_fact: servers_instances="{{ servers_instances_tmp.results|map(attribute='item')|list }}"

  - debug: var=servers_instances