Je veux ajouter des clés à un dictionnaire lorsque j'utilise set_fact avec with_items. C'est un petit POC qui m'aidera à compléter d'autres travaux. J'ai essayé de généraliser le POC afin d'en supprimer tous les détails non pertinents.
Lorsque j'exécute le code suivant, il affiche un dictionnaire avec une seule clé qui correspond au dernier élément du paramètre with_items. Il semble qu’il recrée un nouveau dictionnaire ou remplace un dictionnaire existant pour chaque élément des éléments with_items. Je veux un seul dictionnaire avec toutes les clés.
Code:
---
- hosts: localhost
connection: local
vars:
some_value: 12345
dict: {}
tasks:
- set_fact: {
dict: "{
{{ item }}: {{ some_value }}
}"
}
with_items:
- 1
- 2
- 3
- debug: msg="{{ dict }}"
Utilisez un plugin filter .
Commencez par créer un nouveau fichier dans votre répertoire de base ansible appelé filter_plugins/makedict.py
.
Créez maintenant une nouvelle fonction appelée "makedict" (ou ce que vous voulez) qui prend une valeur et une liste et renvoie un nouveau dictionnaire dans lequel les clés sont les éléments de la liste et la valeur est toujours la même.
class FilterModule(object):
def filters(self):
return { 'makedict': lambda _val, _list: { k: _val for k in _list } }
Maintenant, vous pouvez utiliser le nouveau filtre dans le livre de lecture pour obtenir le résultat souhaité:
- 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}}"
Vous pouvez personnaliser l'emplacement du plugin de filtre en utilisant l'option filter_plugins
dans ansible.cfg
.
Cela peut aussi être fait sans avoir recours à des plugins, testés dans 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 }}"
Alternativement, cela peut être écrit sans le one-liner complexe avec un fichier d'inclusion.
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 ) }}"
Sortie:
TASK [debug]
*******************************************************************
ok: [localhost] => {
"msg": {
"1": "12345",
"2": "12345",
"3": "12345"
}
}
Des guillemets simples '
autour de {{ some_value }}
sont nécessaires pour stocker explicitement les valeurs de chaîne.
Cette syntaxe peut également être utilisée pour ajouter un élément dict
à l'aide de with_dict
en faisant référence à item.key
et item.value
.
Des manipulations telles que l’ajout de préfixes et postfixes ou de hachages peuvent être effectuées à la même étape, par exemple
set_fact:
dict: "{{ dict | combine( { item.key + key_postfix: item.value + '_' + item.value | hash('md5') } ) }}"
cela ne semble plus fonctionner sur ansible 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 }}"
ne renvoie que la dernière valeur {"dict":{"3": "some value"}}
Je vous suggère de faire ceci:
- set_fact:
__dict: |
{% for item in [1,2,3] %}
{{item}}: "value"
{% endfor %}
- set_fact:
final_dict: "{{__dict|from_yaml}}"
- debug:
var: final_dict