Ansible - Как сохранить новые ключи в словаре при использовании модуля set_fact с with_items?
Я хочу добавить ключи к словарю при использовании set_fact с with_items. Это небольшой POC, который поможет мне выполнить некоторые другие работы. Я попытался обобщить POC, чтобы удалить из него все несущественные детали.
Когда я выполняю следующий код, он показывает словарь с одним ключом, который соответствует последнему элементу with_items. Кажется, что он воссоздает новый словарь или может переопределять существующий словарь для каждого элемента in_items. Я хочу один словарь со всеми ключами.
код:
---
- hosts: localhost
connection: local
vars:
some_value: 12345
dict: {}
tasks:
- set_fact: {
dict: "{
{{ item }}: {{ some_value }}
}"
}
with_items:
- 1
- 2
- 3
- debug: msg="{{ dict }}"
Ответы
Ответ 1
Используйте плагин фильтра.
Во-первых, создайте новый файл в вашей доступной директории под названием filter_plugins/makedict.py
.
Теперь создайте новую функцию с именем "makedict" (или что угодно), которая принимает значение и список и возвращает новый словарь, ключи которого являются элементами списка, а значение всегда одинаково.
class FilterModule(object):
def filters(self):
return { 'makedict': lambda _val, _list: { k: _val for k in _list } }
Теперь вы можете использовать новый фильтр в Playbook для достижения желаемого результата:
- hosts: 127.0.0.1
connection: local
vars:
my_value: 12345
my_keys: [1, 2, 3]
tasks:
- set_fact: my_dict="{{ my_value | makedict(my_keys) }}"
- debug: msg="{{ item.key }}={{ item.value }}"
with_dict: "{{my_dict}}"
Вы можете настроить местоположение плагина фильтра, используя опцию filter_plugins
в ansible.cfg
.
Ответ 2
Это также можно сделать, не прибегая к плагинам, проверенным в Ansible 2.2.
---
- hosts: localhost
connection: local
vars:
some_value: 12345
dict: {}
tasks:
- set_fact:
dict: "{{ dict | combine( { item: some_value } ) }}"
with_items:
- 1
- 2
- 3
- debug: msg="{{ dict }}"
В качестве альтернативы это можно записать без сложного однострочного файла с включенным файлом.
tasks:
- include: append_dict.yml
with_items: [1, 2, 3]
append_dict.yml:
- name: "Append dict: define helper variable"
set_fact:
_append_dict: "{ '{{ item }}': {{ some_value }} }"
- name: "Append dict: execute append"
set_fact:
dict: "{{ dict | combine( _append_dict ) }}"
Вывод:
TASK [debug]
*******************************************************************
ok: [localhost] => {
"msg": {
"1": "12345",
"2": "12345",
"3": "12345"
}
}
Одиночные кавычки '
вокруг {{ some_value }}
необходимы для хранения строковых значений явно.
Этот синтаксис также можно использовать для добавления из dict
по элементам с помощью with_dict
, ссылаясь на item.key
и item.value
.
Манипуляции, такие как добавление pre- и postfixes или хешей, могут выполняться на одном и том же этапе, например
set_fact:
dict: "{{ dict | combine( { item.key + key_postfix: item.value + '_' + item.value | hash('md5') } ) }}"
Ответ 3
кажется, это не работает больше на ANSIB 2.5
---
- hosts: localhost
connection: local
vars:
some_value: 12345
dict: {}
tasks:
- set_fact:
dict: "{{ dict | combine( { item: some_value } ) }}"
with_items:
- 1
- 2
- 3
- debug: msg="{{ dict }}"
возвращает только последнее значение {"dict":{"3": "some value"}}
Я предлагаю вам сделать это:
- set_fact:
__dict: |
{% for item in [1,2,3] %}
{{item}}: "value"
{% endfor %}
- set_fact:
final_dict: "{{__dict|from_yaml}}"
- debug:
var: final_dict