Add quotes to elemens of the list in jinja2 (ansib

2020-04-02 06:32发布

问题:

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!

回答1:

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.



回答2:

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.



回答3:

try:

- hosts: localhost
  tags: s20
  gather_facts: no
  vars:
    ip:
      - 1.1.1.1
      - 2.2.2.2
      - 3.3.3.3
    joined_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.



回答4:

Following worked for me

('{{ iplist | join('\',\'') }}')

Ex:

Inventory

[ips]
1.1.1.1
2.2.2.2
3.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.



回答5:

I've developed a custom wrap filter

def wrap(value, wrapper = '"'):
  return wrapper + value + wrapper

class 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



回答6:

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: localhost
  connection: local

  vars:
    some_list:
      - Johnny
      - Joey
      - Dee Dee
      - Tommy

  tasks:
    - 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) }}" )


回答7:

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: localhost
  gather_facts: no
  vars:
    ip:
    - 1.1.1.1
    - 2.2.2.2
    - 3.3.3.3
    ip_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')


回答8:

I found the simplest way to do this with an existing Ansible filter is using regex_replace.

{{ ip | map("regex_replace","(.+)","\'\\1\'") | join(',')}}