I have very simple line in the template:
ip={{ip|join(', ')}}
And I have list for ip:
ip:- 1.1.1.1- 2.2.2.2- 3.3.3.3
But application wants IPs with quotes (ip='1.1.1.1', '2.2.2.2').
I can do it like this:
ip:- "'1.1.1.1'"- "'2.2.2.2'"- "'3.3.3.3'"
But it is very ugly. Is any nice way to add quotes on each element of the list in ansible?
Thanks!
Best Answer
This will work :
ip={{ '\"' + ip|join('\", \"') + '\"' }}
A custom filter plugin will also work. In ansible.cfg uncomment filter_plugins and give it a path, where we put this
def wrap(list):return [ '"' + x + '"' for x in list]class FilterModule(object):def filters(self):return {'wrap': wrap}
in a file called core.py. Like this. Then you can simply use
ip|wrap|join(', ')
And it should produce comma seperated list with each ip wrapped in quotes.
Actually there is a very simple method to achieve this:
{{ mylist | map('quote') | join(', ') }}
The filter map
iterates over every item and let quote
process it. Afterwards you can easily join
them together.
try:
- hosts: localhosttags: s20gather_facts: novars:ip:- 1.1.1.1- 2.2.2.2- 3.3.3.3joined_ip: "'{{ \"', '\".join(ip)}}'"tasks:- debug: msg="(ip={{joined_ip}})"
PS: ansible supports a bit of python code execution within {{}}
, which is what i'm misusing here.
Following worked for me
('{{ iplist | join('\',\'') }}')
Ex:
Inventory[ips]1.1.1.12.2.2.23.3.3.3#cat temp.sh.j2 "ips": (ip='{{ groups['zoo'] | join('\',\'') }}') result:#cat temp.sh"ips": (ip='1.1.1.1','2.2.2.2','3.3.3.3')
Hope it would help someone.
As mentioned in this blog: https://medium.com/opsops/how-enquote-list-elements-faab833e25fe
Use to_json filter. This will double quote every string of the list:
list_of_string | map("to_json")
The problem with the "quote" filter is that it does not quote elements that dont need to be quoted from a bash perspective (no space in the string). But for windows commands sometimes strings must be quoted anyway.
NOTE This is similar to Kashyap's answer, but i needed a slightly different version: Using it to double quote each items in a bash array), eg. result should be:
SOME_LIST=( "Johnny" "Joey" "Dee Dee" "Tommy" )
projects/ansible/expand_list.yml
---- hosts: localhostconnection: localvars:some_list:- Johnny- Joey- Dee Dee- Tommytasks:- name: "Expand the ramones band members list."template:src: "templates/expand_list.conf.j2"dest: "/var/tmp/ramones.conf"
projects/ansible/templates/expand_list.conf.j2
SOME_LIST=( "{{ '" "'.join(some_list) }}" )
I found the simplest way to do this with an existing Ansible filter is using regex_replace
.
{{ ip | map("regex_replace","(.+)","\'\\1\'") | join(',')}}
I've developed a custom wrap
filter
def wrap(value, wrapper = '"'):return wrapper + value + wrapperclass FilterModule(object):def filters(self):return {'wrap': wrap}
As you can see wrapper is customizable and defaults to "
You can use it this way
ip={{ ip | map('wrap') | join(', ') }}
Disclaimer: I'm a python and ansible newbie
You can use regex_replace
, f.e. in a j2 template file:
(ip={{ip | map('regex_replace', '(.*)', "'\\1'") | join(',')}})
If you do this inline in a play, do not forget to escape the double quotes. Here is a full example:
- hosts: localhostgather_facts: novars:ip:- 1.1.1.1- 2.2.2.2- 3.3.3.3ip_result: "{{ip | map('regex_replace', '(.*)', \"'\\1'\") | join(',')}}"tasks:- debug: msg="(ip={{ip_result}})"- copy: content="(ip={{ip_result}})" dest=./ip_result.txt
Content of ip_result.txt:
$ cat ip_result.txt(ip='1.1.1.1','2.2.2.2','3.3.3.3')