The problem: | |
I wanted to use the jinja 'map' filter to modify each item in a string, in this simple | |
example, adding '.conf' to each item. | |
The 'format' filter in jinja takes arguments (value, *args, **kwargs). Unfortunately, | |
it uses 'value' as the pattern. When called inside map 'value' is the current item in | |
the list, or in other words *args as far as format is concerned. So it's the wrong way | |
around. | |
The following example creates a simple filter that has the format args in an order we | |
can use when calling 'map'. Note this is extremely simplestic, and only allows for | |
adding a prefix or suffix to an item. i.e. prefix%s or %ssuffix. You can't do more | |
advanced ones like '%s - %s' with this example as that requires passing the current | |
item as an array and (at least in python 2x), variable length args have to come after | |
named args. | |
_Note: A better approach might be to use the ansible regex_replace filter within map, | |
but when I tried that, it returned \u0001.conf, so I'm guessing that there's some | |
unicode foo (or lack thereof) happening. i.e. I tried | |
mylist2: "{{ mylist | map('regex_replace', '^(.*)$', '\\1.conf' ) | list }}" |
# plugins/filter/map_format.py (check path in ansible.cfg) | |
# This code is essentially a direct copy of the jinja 'format' filter with | |
# some minor mods to the args and their use, see do_format in | |
# https://github.com/mitsuhiko/jinja2/blob/master/jinja2/filters.py | |
# for the original | |
from jinja2.utils import soft_unicode | |
def map_format(value, pattern): | |
""" | |
Apply python string formatting on an object: | |
.. sourcecode:: jinja | |
{{ "%s - %s"|format("Hello?", "Foo!") }} | |
-> Hello? - Foo! | |
""" | |
return soft_unicode(pattern) % (value) | |
class FilterModule(object): | |
''' jinja2 filters ''' | |
def filters(self): | |
return { | |
'map_format': map_format, | |
} |
--- | |
- hosts: all | |
remote_user: vagrant | |
sudo: true | |
vars: | |
mylist: | |
- Alice | |
- Bob | |
- Carol | |
mylist2: "{{ mylist | map('map_format', '%s.conf' ) | list }}" | |
tasks: | |
- debug: var=mylist2 |
This comment has been minimized.
This comment has been minimized.
gingerwizard
commented
Jan 25, 2016
example
|
This comment has been minimized.
This comment has been minimized.
EddyP23
commented
Nov 7, 2017
I think I managed to achieve a similar thing doing this:
Looks ugly, but given |
This comment has been minimized.
This comment has been minimized.
MlleDelphine
commented
Mar 25, 2018
Doubling double back-slash worked for me :)
|
This comment has been minimized.
This comment has been minimized.
fninja
commented
Jul 10, 2018
•
@EddyP23 excellent solution! This way it becomes a bit more obvious what the |
This comment has been minimized.
This comment has been minimized.
ReSearchITEng
commented
Sep 14, 2018
When there is a need to add both prefix and suffix (and making everything a list), look at:
What is does: takes the list of all machines in the group etcd, extracts the ipv4 address, adds a prefix of 'https://' and a suffix of ':2379'. |
This comment has been minimized.
ChineduUzoka commentedDec 14, 2015
I needed this to work and discovered that running the following using 2 backward slashes works for me when rendering within a jinja template "however" when running the following code it outputs correctly to stdout when using 4 backward slashes -