This is part of the series "The Horrors of Ansible Complex Variables." The results below were achieved with Ansible version 2.8.0.
Save this as lists.yml:
---
- name: lists
hosts: localhost
connection: local
vars:
# how not to do it:
users:
alice
bob
charles
giles
# this works well:
files:
- file_a
- file_b
- file_c
- file_g
# indentation needs to be precise - this breaks:
colours:
- red
- green
- blue
- octarine
# the variable name cannot contain spaces, but items can:
Beatles_Albums:
- "Rubber Soul"
- "Magical Mystery Tour"
- "Abbey Road"
- "A Hard Day's Night"
tasks:
- name: print out the users variable via YML
debug:
msg: '{{ item }}'
with_items: '{{ users }}'
- name: print out the files variable via YML
debug:
msg: '{{ item }}'
with_items: '{{ files }}'
- name: print out the colours variable via YML
debug:
msg: '{{ item }}'
with_items: '{{ colours }}'
- name: print out the Beatles albums via YML
debug:
msg: '{{ item }}'
with_items: '{{ Beatles_Albums }}'
- name: template with the lists
template:
src=template.j2
dest=template.txt
Save this template file as template.j2 in the same folder as the Ansible script:
{% for user in users %}
{{ user }}
{% endfor %}
delete: {% for file in files %}{{ file }}, {% endfor %}
watch for: {% for colour in colours %}{{ colour }}, {% endfor %}
listen to: {% for album in "Beatles_Albums" %}{{ album }}, {% endfor %}
listen to: {{ Beatles_Albums|join(', ') }}
The output of the run:
$ ansible-playbook lists.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the
implicit localhost does not match 'all'
PLAY [lists] *******************************************************************************
TASK [Gathering Facts] *********************************************************************
ok: [localhost]
TASK [print out the users variable via YML] ************************************************
ok: [localhost] => (item=alice bob charles giles) => {
"msg": "alice bob charles giles"
}
TASK [print out the files variable via YML] ************************************************
ok: [localhost] => (item=file_a) => {
"msg": "file_a"
}
ok: [localhost] => (item=file_b) => {
"msg": "file_b"
}
ok: [localhost] => (item=file_c) => {
"msg": "file_c"
}
ok: [localhost] => (item=file_g) => {
"msg": "file_g"
}
TASK [print out the colours variable via YML] **********************************************
ok: [localhost] => (item=red) => {
"msg": "red"
}
ok: [localhost] => (item=green) => {
"msg": "green"
}
ok: [localhost] => (item=blue - octarine) => {
"msg": "blue - octarine"
}
TASK [print out the Beatles albums via YML] ************************************************
ok: [localhost] => (item=Rubber Soul) => {
"msg": "Rubber Soul"
}
ok: [localhost] => (item=Magical Mystery Tour) => {
"msg": "Magical Mystery Tour"
}
ok: [localhost] => (item=Abbey Road) => {
"msg": "Abbey Road"
}
ok: [localhost] => (item=A Hard Day's Night) => {
"msg": "A Hard Day's Night"
}
TASK [template with the lists] *************************************************************
ok: [localhost]
PLAY RECAP *********************************************************************************
localhost : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
And the resulting template.txt file:
a l i c e b o b c h a r l e s g i l e s delete: file_a, file_b, file_c, file_g, watch for: red, green, blue - octarine, listen to: B, e, a, t, l, e, s, _, A, l, b, u, m, s, listen to: Rubber Soul, Magical Mystery Tour, Abbey Road, A Hard Day's Night
Conclusions
- you need dashes to make a list: both Ansible and Jinja2 templates misinterpret a list without dashes - although in different ways
- if you mis-indent something, you're in trouble - this doesn't seem unreasonable (so many other things about Ansible variables are)
- don't quote variable names in a Jinja2 template - they're then treated as a string
- for making a comma-separated list, the Jinja2
join
filter is both more concise and produces better results (no trailing comma):{{ Beatles_Albums|join(', ') }}