43

I need to escape double curly braces in a code I'm working on using Ansible. The thing is I have all those parameters that needs to be transformed in variables. Basically I'm working on a template creator.

I've tried using {% raw %}{{ name-of-variable }}{% endraw %} but it did not work. When I tried /{/{ name-of-variable \}\} I almost got it, but I am trying to get rid of the backslashes too.

Here's a bit of the code:

local_action:
    module: replace
    path: "/tmp/{{ ambiance }}/{{ seed }}DEFAULT.j2"
    regexp: "{{ item.regexp1 }}"
    replace: "{{ item.replace }}"
  with_items: 
    - { regexp1: '^DBHOST.*$', replace: 'DBHOST = {% raw %}{{ databasehost }}{% endraw %}' }
    - { regexp1: '^GLOBALHOST.*$', replace: 'GLOBALHOST = {% raw %}{{ global_hostname }}{% endraw %}' }

I expect the following result:

DBHOST = {{ satabasehost }}
GLOBALHOST = {{ global_hostname }}

Any suggestions/ideas?

j-i-l
  • 10,281
  • 3
  • 53
  • 70
gr0gu3
  • 555
  • 1
  • 6
  • 11

3 Answers3

98

{% raw %}{{ databasehost }}{% endraw %} should work.

You can also use {{ '{{ databasehost }}' }} as an alternative.

blhsing
  • 91,368
  • 6
  • 71
  • 106
5

Just to avoid confusion:

With

  • ansible [core 2.14.0]
  • jinja version = 3.1.2

all options are valid from the answer suggested by @blhsing, as well as, the answer by @DustWolf.

Here is a toy example that demonstrates both the use of the approaches recommended in the official jinja docs and the use of ansible's !unsafe data type:

Consider the file test.j2:

DBHOST blabla
GLOBALHOST blablu
OTHERHOST blabli

and the play.yml:

---
- hosts: localhost
  
  tasks:
    - name: test
      local_action:
        module: replace
        path: "{{ playbook_dir}}/test.j2"
        regexp: "{{ item.regexp1 }}"
        replace: "{{ item.replace }}"
      with_items:
        - { regexp1: '^DBHOST.*$', replace: 'DBHOST = {{ "{{ databasehost }}" }}' }
        - { regexp1: '^GLOBALHOST.*$', replace: 'GLOBALHOST = {% raw %}{{ global_hostname }}{% endraw %}' }
        - { regexp1: '^OTHERHOST.*$', replace: !unsafe 'OTHERHOST = {{ other_hostname }}' }

we end up with a modified test.j2:

DBHOST = {{ databasehost }}
GLOBALHOST = {{ global_hostname }}
OTHERHOST = {{ other_hostname }}

So the fact that the {% raw %}...{% endraw %} block did not work for the OP is not because that would not be a valid approach! It is likely due to some particularity of the content of the file in which the replace is done, but that is just a guess.

j-i-l
  • 10,281
  • 3
  • 53
  • 70
  • 2
    It's worth mentioning that `{% raw %}...{% endraw %}` does not work when the jinja2 syntax is invalid, for example when you are trying to output RADIUS configuration which contains `{%` but isn't actually jinja2 syntax. In that case, only the `!unsafe` option works. – DustWolf Jan 18 '23 at 17:02
2

If you are doing this in Ansible (I realise the title only says jinja2), you can prepend !unsafe to the string. Example:

local_action:
    module: replace
    path: "/tmp/{{ ambiance }}/{{ seed }}DEFAULT.j2"
    regexp: "{{ item.regexp1 }}"
    replace: "{{ item.replace }}"
  with_items: 
    - { regexp1: '^DBHOST.*$', replace: !unsafe 'DBHOST = {{ databasehost }}' }
    - { regexp1: '^GLOBALHOST.*$', replace: !unsafe 'GLOBALHOST = {{ global_hostname }}' }

This will cause all jinja2 syntax to be ignored.

Credit: https://stackoverflow.com/a/65295792/2897386

DustWolf
  • 516
  • 7
  • 10