ansiblejinja2

Quote being escaped in Jinja2


The below code fails due to the \\" in the ternary. Escaping the backslash results in too many backslashes being added to the path.

- name: Copy files to required directory
  ansible.windows.win_copy:
    src: '{{ hotfix_backout |
             ternary(hotfix_temp_dir ~ "\hotfix\backup\" ~ item,
                     hotfix_temp_dir ~ "\hotfix\" ~ item) }}'
    dest: C:\Program Files\app\
    remote_src: true
  loop:
    - One.dll
    - Two.dll

This code works.

- name: Copy files to required directory
  ansible.windows.win_copy:
    src: '{{ hotfix_backout |
             ternary(hotfix_temp_dir ~ "\hotfix\backup" ~ sep ~ item,
                     hotfix_temp_dir ~ "\hotfix" ~ sep ~ item) }}'
    dest: C:\Program Files\app\
    remote_src: true
  loop:
    - One.dll
    - Two.dll
  vars:
    sep: \

My question is why is the backslash only causing issues when in front of the ", and what are my options other than using the sep var above?


Solution

  • A way around this issue, is using the format filter of Jinja.

    So, instead of having

    hotfix_temp_dir ~ "\hotfix\backup\" ~ item
    

    You could write

    "%s\hotfix\backup\%s" | format(hotfix_temp_dir, item)
    

    Where the %s would be replaced but the content of the variables provided to the format filter, in order of their apparence.


    Also note that, having a double backslash, is not always a bad thing when speaking about Windows path, the Ansible manual does actually have a section related to it: Path Formatting for Windows.

    Here is an extract of this chapter:

    Here are some examples on how to write Windows paths:

    GOOD
    tempdir: C:\Windows\Temp
    
    WORKS
    tempdir: 'C:\Windows\Temp'
    tempdir: "C:\\Windows\\Temp"
    
    BAD, BUT SOMETIMES WORKS
    tempdir: C:\\Windows\\Temp
    tempdir: 'C:\\Windows\\Temp'
    tempdir: C:/Windows/Temp
    

    For exemple, the task:

    - debug:
        msg: '{{ "%s\hotfix\backup\%s" | format(hotfix_temp_dir, item) }}'
      loop:
        - One.dll
        - Two.dll
      vars:
        hotfix_temp_dir: C:\Windows\Temp
    

    Would yield, as expected:

    ok: [localhost] => (item=One.dll) => 
      msg: C:\Windows\Temp\hotfix\backup\One.dll
    ok: [localhost] => (item=Two.dll) => 
      msg: C:\Windows\Temp\hotfix\backup\Two.dll