Search code examples
ansibleyamljinja2multilinemultilinestring

Ansible multiline string with multiple quotes


I am trying to configure a Mikrotik router using Ansible - as part of that task, I need to generate the actual command that is sent to the router. And somehow, some of the quotes simply... disappear from my string after Ansible parses it.

[ Edit - this seems to be related to jinja2_native. See the end of the question for the details ]

The minimum example I was able to build that showcases the problem is this:

- hosts: localhost
  gather_facts: false
  tasks:
  - vars:
      port: 20200
      cmd: >
        add chain=dstnat && dst-port="{{port}}"
        comment="%TR% - {{ansible_host}} - SSH for {{inventory_hostname}}" 
        dst-port="{{ port }}" protocol=tcp 
        }'
    debug:
      msg: "{{cmd}}"

When running this playbook, here is the result:

# ansible-playbook test.yml 
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *****************************************************************************************************************

TASK [debug] *********************************************************************************************************************
Wednesday 29 April 2020  23:07:52 +0300 (0:00:00.052)       0:00:00.052 ******* 
ok: [localhost] => {
    "msg": "add chain=dstnat && dst-port=\"20200\" comment=\"%TR% - 127.0.0.1 - SSH for localhost  dst-port=20200\" protocol=tcp  }'\n"
}

Notice how some of the quotes are gone, and as a result the number of arguments in the command has totally changed. (and, of course, I noticed this only after spending several hours troubleshooting and wondering why the command was failing...)

Interestingly enough, if I change the text a bit, other quotes disappear:

- hosts: localhost
  gather_facts: false
  tasks:
  - vars:
      port: 20200
      cmd: >
        add chain=dstnat && dst-port="{{port}}"
        comment="{{ansible_host}} - SSH for {{inventory_hostname}}" 
        dst-port="{{ port }}" protocol=tcp 
        }'
    debug:
      msg: "{{cmd}}"
    tags: 
    - networking

# ansible-playbook test.yml 
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *****************************************************************************************************************

TASK [debug] *********************************************************************************************************************
Wednesday 29 April 2020  23:12:12 +0300 (0:00:00.031)       0:00:00.031 ******* 
ok: [localhost] => {
    "msg": "add chain=dstnat && dst-port=\"20200 comment=127.0.0.1 - SSH for localhost  dst-port=20200\" protocol=tcp  }'\n"
}

It seems that whenever I have a sequence like }}" text_here "{{, the quotes are gone...

My questions are:

  1. Can anyone tell me why this happens?
  2. Can someone advise me on how I can avoid this issue? I have tried multiline strings (with double quotes, single quotes, > folding, etc) - same result...

[ Edit: when going through all the recent changes that might have caused this, I remembered enabling jinja2_native . And true enough, after setting jinja2_native back to False in ansible.cfg, the problem goes away...

# ansible-playbook test.yml 
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *****************************************************************************************************************

TASK [debug] *********************************************************************************************************************
Wednesday 29 April 2020  23:55:29 +0300 (0:00:00.029)       0:00:00.029 ******* 
ok: [localhost] => {
    "msg": "add chain=dstnat && dst-port=\"20200\" comment=\"127.0.0.1 - SSH for localhost \"  dst-port=\"20200\" protocol=tcp  }'\n"
}

]


Solution

  • I was able to get an answer on github - a big thanks to sivel for that!

    I am also posting it here, for reference.

    "The[re] was an issue with upstream jinja2, that was resolved in jinja2 2.11."

    Some more links relevant to the issue: see here and here.