J'utilise actuellement Ansible 1.7.2. J'ai le testbook suivant:
---
- hosts: localhost
tasks:
- name: set fact 1
set_fact: foo="[ 'zero' ]"
- name: set fact 2
set_fact: foo="{{ foo }} + [ 'one' ]"
- name: set fact 3
set_fact: foo="{{ foo }} + [ 'two', 'three' ]"
- name: set fact 4
set_fact: foo="{{ foo }} + [ '{{ item }}' ]"
with_items:
- four
- five
- six
- debug: var=foo
La première tâche définit un fait qui est une liste avec un élément. Les tâches suivantes s'ajoutent à cette liste avec plus de valeurs. Les trois premières tâches fonctionnent comme prévu, mais pas la dernière. Voici le résultat lorsque je lance ceci:
PLAY [localhost] **************************************************************
GATHERING FACTS ***************************************************************
ok: [localhost]
TASK: [set fact 1] ************************************************************
ok: [localhost]
TASK: [set fact 2] ************************************************************
ok: [localhost]
TASK: [set fact 3] ************************************************************
ok: [localhost]
TASK: [set fact 4] ************************************************************
ok: [localhost] => (item=four)
ok: [localhost] => (item=five)
ok: [localhost] => (item=six)
TASK: [debug var=foo] *********************************************************
ok: [localhost] => {
"foo": [
"zero",
"one",
"two",
"three",
"six"
]
}
PLAY RECAP ********************************************************************
localhost : ok=6 changed=0 unreachable=0 failed=0
Compte tenu des éléments with_items de la tâche 4 et du fait que la sortie affiche la tâche correctement itérée sur les éléments de cette liste, je me serais attendu à ce que le résultat contienne tous les nombres de zéro à six. Mais cette dernière tâche ne semble évaluer que set_fact avec le dernier élément de la liste. Est-ce éventuellement un bug dans Ansible?
Edit: Je viens également de tester cela sur ansible 1.8 et la sortie était identique.
On dirait que ce comportement est le mode de fonctionnement actuel d’Ansible, bien que l’intérêt de le réparer fonctionne comme souhaité. Il y a actuellement un demande d'extraction avec la fonctionnalité désirée, donc j'espère que cela sera éventuellement intégré à Ansible.
Il existe une solution de contournement qui peut aider. Vous pouvez "enregistrer" les résultats pour chaque itération set_fact, puis les mapper à la liste:
---
- hosts: localhost
tasks:
- name: set fact
set_fact: foo_item="{{ item }}"
with_items:
- four
- five
- six
register: foo_result
- name: make a list
set_fact: foo="{{ foo_result.results | map(attribute='ansible_facts.foo_item') | list }}"
- debug: var=foo
Sortie:
< TASK: debug var=foo >
---------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
ok: [localhost] => {
"var": {
"foo": [
"four",
"five",
"six"
]
}
}
Comme mentionné dans les commentaires d'autres personnes, la solution proposée en priorité ici ne fonctionnait pas pour moi dans Ansible 2.2, en particulier lorsque vous utilisiez également with_items
.
Il semble que l'approche envisagée par OP fonctionne maintenant avec un léger changement dans la citation de item
.
- set_fact: something="{{ something + [ item ] }}"
with_items:
- one
- two
- three
Et un exemple plus long où j'ai traité le cas initial de la liste non définie et ajouté un facultatif when
parce que cela me causait également du chagrin:
- set_fact: something="{{ something|default([]) + [ item ] }}"
with_items:
- one
- two
- three
when: item.name in allowed_things.item_list
Jinja 2.6 n'a pas la fonction de carte. Donc, une autre façon de faire serait:
set_fact: foo="{% for i in bar_result.results %}{{ i.ansible_facts.foo_item }}{%endfor%}"
Mise à jour 2018-06-08: Ma réponse précédente était un peu de bidouillage alors je suis revenu et ai regardé à nouveau. C'est une approche plus propre de Jinja2.
- name: Set fact 4
set_fact:
foo: "{% for i in foo_result.results %}{% do foo.append(i) %}{% endfor %}{{ foo }}"
J'ajoute cette réponse car la meilleure réponse actuelle pour Ansible 2.2+ ne couvre pas complètement la question initiale. Merci à Russ Huguley pour votre réponse, cela m'a permis d'aller dans la bonne direction, mais cela m'a laissé une chaîne concaténée, pas une liste. Cette solution obtient une liste mais devient encore plus compliquée. J'espère que cela sera résolu d'une manière plus propre.
- name: build foo_string
set_fact:
foo_string: "{% for i in foo_result.results %}{{ i.ansible_facts.foo_item }}{% if not loop.last %},{% endif %}{%endfor%}"
- name: set fact foo
set_fact:
foo: "{{ foo_string.split(',') }}"
Je cherchais une réponse à cette question. J'ai trouvé cela utile. Le modèle n'était pas apparent dans la documentation de with_items.
https://github.com/ansible/ansible/issues/39389
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: set_fact
set_fact:
foo: "{{ foo }} + [ '{{ item }}' ]"
with_items:
- "one"
- "two"
- "three"
vars:
foo: []
- name: Print the var
debug:
var: foo