Skip to content

Commit

Permalink
fix(utils/url): handle Windows relative path backslash when caching file
Browse files Browse the repository at this point in the history
Fix #61040.

Jinja imports with relative paths was introduced in #47490.

Unfortunately, relative imports have never been working on Windows.
That's due to backslashes being unhandled by the `cache_file` function:

* https://github.com/saltstack/salt/blob/7275ecf073197faed26f3a571c25fcd59bfbfd60/salt/utils/jinja.py#L114

Instead of getting:

* `salt://packages/map.jinja`

We're ending up with:

* `salt://packages\map.jinja`

Thus, the file isn't cached from the master.

There's actually a `FIXME` note about it:

* https://github.com/saltstack/salt/blob/7275ecf073197faed26f3a571c25fcd59bfbfd60/salt/utils/jinja.py#L136

And the replacement is actually done for setting `tpldir`:

* https://github.com/saltstack/salt/blob/7275ecf073197faed26f3a571c25fcd59bfbfd60/salt/utils/jinja.py#L165

This commit ensures the replacement is also done when caching files.
  • Loading branch information
myii committed Apr 8, 2022
1 parent deeeaa3 commit 080da38
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 2 deletions.
1 change: 1 addition & 0 deletions changelog/61829.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ensure that `salt://` URIs never contain backslashes, converting them to forward slashes instead. A specific situation to handle is caching files on Windows minions, where Jinja relative imports introduce a backslash into the path.
1 change: 1 addition & 0 deletions salt/utils/url.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def create(path, saltenv=None):
"""
join `path` and `saltenv` into a 'salt://' URL.
"""
path = path.replace("\\", "/")
if salt.utils.platform.is_windows():
path = salt.utils.path.sanitize_win_path(path)
path = salt.utils.data.decode(path)
Expand Down
4 changes: 2 additions & 2 deletions tests/pytests/unit/utils/jinja/test_salt_cache_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ def test_relative_import(
result = tmpl.render()
assert result == "Hey world !a b !"
assert len(fc.requests) == 3
assert fc.requests[0]["path"] == os.path.join("salt://relative", "rhello")
assert fc.requests[1]["path"] == os.path.join("salt://relative", "rmacro")
assert fc.requests[0]["path"] == "salt://relative/rhello"
assert fc.requests[1]["path"] == "salt://relative/rmacro"
assert fc.requests[2]["path"] == "salt://macro"
# This must fail when rendered: attempts to import from outside file root
template = jinja.get_template("relative/rescape")
Expand Down
26 changes: 26 additions & 0 deletions tests/unit/utils/test_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,32 @@ def test_create_url_saltenv(self):

self.assertEqual(salt.utils.url.create(path, saltenv), url)

def test_create_url_with_backslash_in_path(self):
"""
Test creating a 'salt://' URL
"""
src_path = r"? interesting\&path.filetype"
tgt_path = "? interesting/&path.filetype"
url = "salt://" + tgt_path
if salt.utils.platform.is_windows():
url = "salt://_ interesting/&path.filetype"

self.assertEqual(salt.utils.url.create(src_path), url)

def test_create_url_saltenv_with_backslash_in_path(self):
"""
Test creating a 'salt://' URL with a saltenv
"""
saltenv = "raumklang"
src_path = r"? interesting\&path.filetype"
tgt_path = "? interesting/&path.filetype"
if salt.utils.platform.is_windows():
tgt_path = "_ interesting/&path.filetype"

url = "salt://" + tgt_path + "?saltenv=" + saltenv

self.assertEqual(salt.utils.url.create(src_path, saltenv), url)

# is_escaped tests

def test_is_escaped_windows(self):
Expand Down

0 comments on commit 080da38

Please sign in to comment.