mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 09:40:20 +00:00
fixes saltstack/salt#62953 file.symlink backupname operation can copy remote contents to local disk
This commit is contained in:
parent
c20115cc17
commit
a74dde460e
4 changed files with 49 additions and 2 deletions
1
changelog/62953.fixed
Normal file
1
changelog/62953.fixed
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix file.symlink backupname operation can copy remote contents to local disk
|
|
@ -7416,16 +7416,29 @@ def join(*args):
|
||||||
return os.path.join(*args)
|
return os.path.join(*args)
|
||||||
|
|
||||||
|
|
||||||
def move(src, dst):
|
def move(src, dst, disallow_copy_and_unlink=False):
|
||||||
"""
|
"""
|
||||||
Move a file or directory
|
Move a file or directory
|
||||||
|
|
||||||
|
disallow_copy_and_unlink
|
||||||
|
If ``True``, the operation is offloaded to the ``file.rename`` execution
|
||||||
|
module function. This will use ``os.rename`` underneath, which will fail
|
||||||
|
in the event that ``src`` and ``dst`` are on different filesystems. If
|
||||||
|
``False`` (the default), ``shutil.move`` will be used in order to fall
|
||||||
|
back on a "copy then unlink" approach, which is required for moving
|
||||||
|
across filesystems.
|
||||||
|
|
||||||
|
.. versionadded:: 3006.0
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
salt '*' file.move /path/to/src /path/to/dst
|
salt '*' file.move /path/to/src /path/to/dst
|
||||||
"""
|
"""
|
||||||
|
if disallow_copy_and_unlink:
|
||||||
|
return rename(src, dst)
|
||||||
|
|
||||||
src = os.path.expanduser(src)
|
src = os.path.expanduser(src)
|
||||||
dst = os.path.expanduser(dst)
|
dst = os.path.expanduser(dst)
|
||||||
|
|
||||||
|
|
|
@ -1536,6 +1536,7 @@ def symlink(
|
||||||
win_deny_perms=None,
|
win_deny_perms=None,
|
||||||
win_inheritance=None,
|
win_inheritance=None,
|
||||||
atomic=False,
|
atomic=False,
|
||||||
|
disallow_copy_and_unlink=False,
|
||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
|
@ -1618,6 +1619,17 @@ def symlink(
|
||||||
atomic
|
atomic
|
||||||
Use atomic file operation to create the symlink.
|
Use atomic file operation to create the symlink.
|
||||||
|
|
||||||
|
.. versionadded:: 3006.0
|
||||||
|
|
||||||
|
disallow_copy_and_unlink
|
||||||
|
Only used if ``backupname`` is used and the name of the symlink exists
|
||||||
|
and is not a symlink. If set to ``True``, the operation is offloaded to
|
||||||
|
the ``file.rename`` execution module function. This will use
|
||||||
|
``os.rename`` underneath, which will fail in the event that ``src`` and
|
||||||
|
``dst`` are on different filesystems. If ``False`` (the default),
|
||||||
|
``shutil.move`` will be used in order to fall back on a "copy then
|
||||||
|
unlink" approach, which is required for moving across filesystems.
|
||||||
|
|
||||||
.. versionadded:: 3006.0
|
.. versionadded:: 3006.0
|
||||||
"""
|
"""
|
||||||
name = os.path.expanduser(name)
|
name = os.path.expanduser(name)
|
||||||
|
@ -1820,7 +1832,9 @@ def symlink(
|
||||||
else:
|
else:
|
||||||
__salt__["file.remove"](backupname)
|
__salt__["file.remove"](backupname)
|
||||||
try:
|
try:
|
||||||
__salt__["file.move"](name, backupname)
|
__salt__["file.move"](
|
||||||
|
name, backupname, disallow_copy_and_unlink=disallow_copy_and_unlink
|
||||||
|
)
|
||||||
except Exception as exc: # pylint: disable=broad-except
|
except Exception as exc: # pylint: disable=broad-except
|
||||||
ret["changes"] = {}
|
ret["changes"] = {}
|
||||||
log.debug(
|
log.debug(
|
||||||
|
|
|
@ -589,3 +589,22 @@ def test_stats():
|
||||||
ret = filemod.stats("dummy", None, True)
|
ret = filemod.stats("dummy", None, True)
|
||||||
assert ret["mode"] == "0644"
|
assert ret["mode"] == "0644"
|
||||||
assert ret["type"] == "file"
|
assert ret["type"] == "file"
|
||||||
|
|
||||||
|
|
||||||
|
def test_file_move_disallow_copy_and_unlink():
|
||||||
|
mock_shutil_move = MagicMock()
|
||||||
|
mock_os_rename = MagicMock()
|
||||||
|
with patch("os.path.expanduser", MagicMock(side_effect=lambda path: path)), patch(
|
||||||
|
"os.path.isabs", MagicMock(return_value=True)
|
||||||
|
), patch("shutil.move", mock_shutil_move), patch("os.rename", mock_os_rename):
|
||||||
|
ret = filemod.move("source", "dest", disallow_copy_and_unlink=False)
|
||||||
|
mock_shutil_move.assert_called_once()
|
||||||
|
mock_os_rename.assert_not_called()
|
||||||
|
assert ret["result"] is True
|
||||||
|
|
||||||
|
mock_shutil_move.reset_mock()
|
||||||
|
|
||||||
|
ret = filemod.move("source", "dest", disallow_copy_and_unlink=True)
|
||||||
|
mock_os_rename.assert_called_once()
|
||||||
|
mock_shutil_move.assert_not_called()
|
||||||
|
assert ret is True
|
||||||
|
|
Loading…
Add table
Reference in a new issue