Getting paths right in Windows

105 views
Skip to first unread message

Trond Hindenes

unread,
May 9, 2017, 4:23:36 AM5/9/17
to Ansible Project
Hope someone can help me shed some light on this one:

Since Ansible is python-based, us Windows dudes generally have to stick an extra backslash anywhere we're manipulating Windows paths. However, in some cases this causes unexpected behavior. In my current case, I need to inject a file path into a json file on a Windows box. This path is defined as such in an Ansible var:
logfiles_path: "F:\\Logs"

In my template json file I add to this path, using the following:

"FilePath":"{{ logfiles_path }}\\*",

The goal is to populate the target json with 
"F:\\Logs\\*"

However, since Ansible kicks in the resulting file contains:
"F:\Logfiles\\*"

In other words, Ansible "normalises" the part of the path that comes from a variable, but not the part "outside" of the variable.

I'm not sure what the best way to solve this is - it would be great to have some builtin filters that would do "json normalization" of a string or something. How are people solving this?

Dag Wieers

unread,
May 9, 2017, 8:30:11 AM5/9/17
to Ansible Project
I stick to using single backslashes (and not quotes) in YAML, or single
quotes if you have to. And single quotes everywhere else. I never had the
need to use double-backslashes.

I remember one issues (with YAML?), which is when using a trailing
backslash. So I taught myself not to do this for Windows paths :-)

It would be nice to document these best-practices as part of the Ansible
Windows documentation once we have determined what's best.

--
Dag

J Hawkesworth

unread,
May 15, 2017, 3:38:10 AM5/15/17
to Ansible Project
I'm not seeing the behaviour you describe - maybe my playbook isn't doing the same things as yours though?

# playbook:

$ cat trondpath.yml
---
- name: test trond observed strange path behaviour
  hosts: TENSY
  vars:
    logfiles_path: "F:\\Logs"
  connection: winrm
  gather_facts: false
  tasks:
    - name: create json file from template
      win_template:
        src: template.json
        dest: templated.json

# template file:

$ cat template.json
{
   "FilePath":"{{ logfiles_path }}\\*",
   "Stuff": otherstuff
}

contents of templated.json:

{
   "FilePath":"F:\Logs\\*",
   "Stuff": otherstuff
}

I'm using ansible 2.3 (Win 10 WSL / Ubuntu )

Dag is right though we should document this - I've put it on my list.  Better still would be to document and make some kind of automated test like the integration tests for modules.  There are probably quite a few possible combinations to work through - absolute and relative paths, paths to files, paths to dirs and then all the places you can define them - hostvars, group vars, included vars, in-playbook vars, hardcoded in playbooks, hardcoded in templates, and inside {{ }}

For info there are filters for windows style paths.
See http://docs.ansible.com/ansible/playbooks_filters.html
win_basename, win_splitdrive and win_dirname are the windows-specific ones.

Another trick you can use is to use unix style path separators - powershell is *usually* ok with this but obviously it depends on what is happening in your powershell code - if you pass a path to a native windows binary in your powershell (or ansible module code) obviously this isn't going to work.

Hope this helps,

Jon

Trond Hindenes

unread,
May 16, 2017, 6:28:50 PM5/16/17
to Ansible Project
To me it looks like you're getting the same as me (I had to zoom in my screen to be sure :-) ) - contents of templated json contains a single backslash after the drive letter (which is not valid)

These Json files might be read by applications that are not able to parse "forward-slashed" paths, so although Powershell would be fine with that format, it's not always an option to use them in json files (so essentially this is not as much a problem with the Powershell-based Ansible modules as the fact that its hard to inject valid json into json files).

I'll look into the win_* filter - I haven't spent much time with those (I kinda wish they were a bit better documented)

I'll keep this thread updated with my findings.

J Hawkesworth

unread,
May 17, 2017, 10:37:51 AM5/17/17
to Ansible Project
Sorry, trying to help too early in the morning!.  I had missed the single \ in the path.

Not tried but have noticed jinja2 has a 'tojson' filter that might help (new in 2.9 so maybe 'pip install Jinja2 --upgrade' might be needed, although I think installing ansible 2.3 from pip will drag this in, if I recall.  Also there's a 'safe' filter which might stop automatic escaping from happening.


Hope this helps,

Jon

Trond Hindenes

unread,
May 18, 2017, 6:33:02 PM5/18/17
to Ansible Project
Thanks, will check those out!
Reply all
Reply to author
Forward
0 new messages