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!

9

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