tutorial tower source open logo hat ansible

tower - Usando set_facts y with_items juntos en Ansible



ansible tutorial (6)

Actualizado 2018-06-08: mi respuesta anterior fue un poco de pirateo, así que volví y miré esto nuevamente. Este es un enfoque más limpio de Jinja2.

- name: Set fact 4 set_fact: foo: "{% for i in foo_result.results %}{% do foo.append(i) %}{% endfor %}{{ foo }}"

Estoy agregando esta respuesta como la mejor respuesta actual para Ansible 2.2+ no cubre completamente la pregunta original. Gracias a Russ Huguley por su respuesta, esto me llevó en la dirección correcta, pero me dejó con una cadena concatenada, no una lista. Esta solución obtiene una lista pero se vuelve aún más hacky. Espero que esto se resuelva de una manera más limpia.

- 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('','') }}"

Actualmente estoy usando Ansible 1.7.2. Tengo el siguiente libro de jugadas de prueba:

--- - 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 primera tarea establece un hecho que es una lista con un elemento. Las tareas posteriores se agregan a esa lista con más valores. Las primeras tres tareas funcionan como se esperaba, pero la última no. Aquí está la salida cuando ejecuto esto:

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

Dados los elementos with_items en la tarea 4 y el hecho de que la salida muestra la tarea correctamente iterada sobre los elementos de esa lista, hubiera esperado que el resultado contuviera todos los números del cero al seis. Pero esa última tarea parece solo evaluar set_fact con el último elemento de la lista. ¿Es esto posiblemente un error en Ansible?

Editar: También acabo de probar esto en ansible 1.8 y la salida fue idéntica.


Como se mencionó en los comentarios de otras personas, la solución principal dada aquí no funcionaba para mí en Ansible 2.2, particularmente cuando también usaba with_items .

Parece que el enfoque previsto de OP funciona ahora con un ligero cambio en la cita del item .

- set_fact: something="{{ something + [ item ] }}" with_items: - one - two - three

Y un ejemplo más largo en el que manejé el caso inicial de que la lista no esté definida y agregué un opcional when porque eso también me estaba causando dolor:

- set_fact: something="{{ something|default([]) + [ item ] }}" with_items: - one - two - three when: item.name in allowed_things.item_list


Estaba buscando una respuesta a esta pregunta. Encontré esto útil. El patrón no era aparente en la documentación 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


Hay una solución alternativa que puede ayudar. Puede "registrar" resultados para cada iteración set_fact y luego asignar esos resultados a la lista:

--- - 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

Salida:

< TASK: debug var=foo > --------------------- / ^__^ / (oo)/_______ (__)/ )/// ||----w | || || ok: [localhost] => { "var": { "foo": [ "four", "five", "six" ] } }


Jinja 2.6 no tiene la función de mapa. Entonces, una forma alternativa de hacer esto sería:

set_fact: foo="{% for i in bar_result.results %}{{ i.ansible_facts.foo_item }}{%endfor%}"


Parece que este comportamiento es el funcionamiento actual de Ansible, aunque hay mucho interés en arreglarlo para que funcione según lo deseado. Actualmente hay una solicitud de extracción con la funcionalidad deseada, así que espero que eventualmente se incorpore a Ansible.