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:
[ 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"
}
]
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."