How to prepend every string in a list with a prefix in Ansible
Let’s say you have an external dict (hostvars) where you take one element by a key (f.e. hostvars[host].foobar). This element is a list. You need to keep it as list and prepend (add at front) a string. Moreover, you need to join those lists together.
Here my answer. To simplify our task we will have: hv
as imitation of hostvars
, and, a list of keys for hv, imitation of groups.groupname
. We want to join all foobar
s from hv
with keys from gr
, prepending every element with a fixed prefix prefix
.
My solution:
---
- hosts: localhost
gather_facts: false
tasks:
-set_fact:
x: '{{ x|d([]) + [p]|product(hv[item].foo)|map("join")|list }}'
with_items: '{{ gr }}'
- debug: var=x
vars:
hv:
host1:
foobar:
- element one
- element two
junk:
- to annoy you
host2:
foobar:
- element 42
host3:
foobar: []
junk: to annoy you
host4:
- should be ignored
gr:
- host1
- host2
- host3
p: 'The '
Output is:
ok: [localhost] => {
"output": [
"The element one",
"The element two",
"The element 42"
]
}
Explanation
hv[item].foo
is an imitation of a normalhostvars[item].foo
[p]|product(any_list)
produces pairs ofp
and the next each next element ofany_list
(Cartesian product). (I use ‘p
’ for prefix to fit the expression on the one line).map(“join”)|list
apply join function to each pair, producing a string “{p}{element}” (it is applied to each pair from step 2). Additionally,list
converts from generator to list.x|d([]) + everything else
uses d (default) filter to assign x to empty list if x is undefined and adds every next expression into it.
Word of caution
You should be really careful with such tricks. Putting too many filters in one line makes code unreadable.