mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
fixes saltstack/salt#64665 add follow_symlinks to file.symlink exec module
This commit is contained in:
parent
c2779df50c
commit
ebd645a4fe
4 changed files with 191 additions and 167 deletions
1
changelog/64665.added.md
Normal file
1
changelog/64665.added.md
Normal file
|
@ -0,0 +1 @@
|
|||
Add follow_symlinks to file.symlink exec module to switch to os.path.lexists when False
|
|
@ -435,7 +435,7 @@ def set_mode(path, mode):
|
|||
if not mode:
|
||||
mode = "0"
|
||||
if not os.path.exists(path):
|
||||
raise CommandExecutionError("{}: File not found".format(path))
|
||||
raise CommandExecutionError(f"{path}: File not found")
|
||||
try:
|
||||
os.chmod(path, int(mode, 8))
|
||||
except Exception: # pylint: disable=broad-except
|
||||
|
@ -678,14 +678,14 @@ def chattr(*files, **kwargs):
|
|||
cmd = ["chattr"]
|
||||
|
||||
if operator == "add":
|
||||
attrs = "+{}".format(attributes)
|
||||
attrs = f"+{attributes}"
|
||||
elif operator == "remove":
|
||||
attrs = "-{}".format(attributes)
|
||||
attrs = f"-{attributes}"
|
||||
|
||||
cmd.append(attrs)
|
||||
|
||||
if flags is not None:
|
||||
cmd.append("-{}".format(flags))
|
||||
cmd.append(f"-{flags}")
|
||||
|
||||
if version is not None:
|
||||
cmd.extend(["-v", version])
|
||||
|
@ -828,12 +828,7 @@ def get_source_sum(
|
|||
"following are supported hash types and lengths: {}.".format(
|
||||
source_hash,
|
||||
", ".join(salt.utils.files.VALID_PROTOS),
|
||||
", ".join(
|
||||
[
|
||||
"{} ({})".format(HASHES_REVMAP[x], x)
|
||||
for x in sorted(HASHES_REVMAP)
|
||||
]
|
||||
),
|
||||
", ".join([f"{HASHES_REVMAP[x]} ({x})" for x in sorted(HASHES_REVMAP)]),
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -849,7 +844,7 @@ def get_source_sum(
|
|||
)
|
||||
if not hash_fn:
|
||||
raise CommandExecutionError(
|
||||
"Source hash file {} not found".format(source_hash)
|
||||
f"Source hash file {source_hash} not found"
|
||||
)
|
||||
else:
|
||||
if proto != "":
|
||||
|
@ -879,7 +874,7 @@ def get_source_sum(
|
|||
_invalid_source_hash_format()
|
||||
except ValueError:
|
||||
# No hash type, try to figure out by hash length
|
||||
if not re.match("^[{}]+$".format(string.hexdigits), source_hash):
|
||||
if not re.match(f"^[{string.hexdigits}]+$", source_hash):
|
||||
_invalid_source_hash_format()
|
||||
ret["hsum"] = source_hash
|
||||
source_hash_len = len(source_hash)
|
||||
|
@ -964,10 +959,7 @@ def check_hash(path, file_hash):
|
|||
file_hash,
|
||||
hash_len,
|
||||
", ".join(
|
||||
[
|
||||
"{} ({})".format(HASHES_REVMAP[x], x)
|
||||
for x in sorted(HASHES_REVMAP)
|
||||
]
|
||||
[f"{HASHES_REVMAP[x]} ({x})" for x in sorted(HASHES_REVMAP)]
|
||||
),
|
||||
)
|
||||
)
|
||||
|
@ -1097,7 +1089,7 @@ def find(path, *args, **kwargs):
|
|||
try:
|
||||
finder = salt.utils.find.Finder(kwargs)
|
||||
except ValueError as ex:
|
||||
return "error: {}".format(ex)
|
||||
return f"error: {ex}"
|
||||
|
||||
ret = [
|
||||
item
|
||||
|
@ -1192,11 +1184,11 @@ def sed(
|
|||
options = options.replace("-r", "-E")
|
||||
|
||||
cmd = ["sed"]
|
||||
cmd.append("-i{}".format(backup) if backup else "-i")
|
||||
cmd.append(f"-i{backup}" if backup else "-i")
|
||||
cmd.extend(salt.utils.args.shlex_split(options))
|
||||
cmd.append(
|
||||
r"{limit}{negate_match}s/{before}/{after}/{flags}".format(
|
||||
limit="/{}/ ".format(limit) if limit else "",
|
||||
limit=f"/{limit}/ " if limit else "",
|
||||
negate_match="!" if negate_match else "",
|
||||
before=before,
|
||||
after=after,
|
||||
|
@ -1240,9 +1232,9 @@ def sed_contains(path, text, limit="", flags="g"):
|
|||
cmd.extend(salt.utils.args.shlex_split(options))
|
||||
cmd.append(
|
||||
r"{limit}s/{before}/$/{flags}".format(
|
||||
limit="/{}/ ".format(limit) if limit else "",
|
||||
limit=f"/{limit}/ " if limit else "",
|
||||
before=before,
|
||||
flags="p{}".format(flags),
|
||||
flags=f"p{flags}",
|
||||
)
|
||||
)
|
||||
cmd.append(path)
|
||||
|
@ -1323,10 +1315,10 @@ def psed(
|
|||
# The pattern to replace with does not need to be escaped
|
||||
limit = _sed_esc(limit, escape_all)
|
||||
|
||||
shutil.copy2(path, "{}{}".format(path, backup))
|
||||
shutil.copy2(path, f"{path}{backup}")
|
||||
|
||||
with salt.utils.files.fopen(path, "w") as ofile:
|
||||
with salt.utils.files.fopen("{}{}".format(path, backup), "r") as ifile:
|
||||
with salt.utils.files.fopen(f"{path}{backup}", "r") as ifile:
|
||||
if multi is True:
|
||||
for line in ifile.readline():
|
||||
ofile.write(
|
||||
|
@ -1509,12 +1501,12 @@ def comment_line(path, regex, char="#", cmnt=True, backup=".bak"):
|
|||
|
||||
# Make sure the file exists
|
||||
if not os.path.isfile(path):
|
||||
raise SaltInvocationError("File not found: {}".format(path))
|
||||
raise SaltInvocationError(f"File not found: {path}")
|
||||
|
||||
# Make sure it is a text file
|
||||
if not __utils__["files.is_text"](path):
|
||||
raise SaltInvocationError(
|
||||
"Cannot perform string replacements on a binary file: {}".format(path)
|
||||
f"Cannot perform string replacements on a binary file: {path}"
|
||||
)
|
||||
|
||||
# First check the whole file, determine whether to make the replacement
|
||||
|
@ -1536,14 +1528,12 @@ def comment_line(path, regex, char="#", cmnt=True, backup=".bak"):
|
|||
# Load lines into dictionaries, set found to True
|
||||
orig_file.append(line)
|
||||
if cmnt:
|
||||
new_file.append("{}{}".format(char, line))
|
||||
new_file.append(f"{char}{line}")
|
||||
else:
|
||||
new_file.append(line.lstrip(char))
|
||||
found = True
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError(
|
||||
"Unable to open file '{}'. Exception: {}".format(path, exc)
|
||||
)
|
||||
raise CommandExecutionError(f"Unable to open file '{path}'. Exception: {exc}")
|
||||
|
||||
# We've searched the whole file. If we didn't find anything, return False
|
||||
if not found:
|
||||
|
@ -1558,7 +1548,7 @@ def comment_line(path, regex, char="#", cmnt=True, backup=".bak"):
|
|||
try:
|
||||
temp_file = _mkstemp_copy(path=path, preserve_inode=False)
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError("Exception: {}".format(exc))
|
||||
raise CommandExecutionError(f"Exception: {exc}")
|
||||
|
||||
try:
|
||||
# Open the file in write mode
|
||||
|
@ -1577,7 +1567,7 @@ def comment_line(path, regex, char="#", cmnt=True, backup=".bak"):
|
|||
if re.match(regex, line):
|
||||
# Write the new line
|
||||
if cmnt:
|
||||
wline = "{}{}".format(char, line)
|
||||
wline = f"{char}{line}"
|
||||
else:
|
||||
wline = line.lstrip(char)
|
||||
else:
|
||||
|
@ -1593,13 +1583,13 @@ def comment_line(path, regex, char="#", cmnt=True, backup=".bak"):
|
|||
"Exception: {}".format(path, temp_file, exc)
|
||||
)
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError("Exception: {}".format(exc))
|
||||
raise CommandExecutionError(f"Exception: {exc}")
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError("Exception: {}".format(exc))
|
||||
raise CommandExecutionError(f"Exception: {exc}")
|
||||
|
||||
if backup:
|
||||
# Move the backup file to the original directory
|
||||
backup_name = "{}{}".format(path, backup)
|
||||
backup_name = f"{path}{backup}"
|
||||
try:
|
||||
shutil.move(temp_file, backup_name)
|
||||
except OSError as exc:
|
||||
|
@ -1686,9 +1676,7 @@ def _mkstemp_copy(path, preserve_inode=True):
|
|||
try:
|
||||
temp_file = salt.utils.files.mkstemp(prefix=salt.utils.files.TEMPFILE_PREFIX)
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError(
|
||||
"Unable to create temp file. Exception: {}".format(exc)
|
||||
)
|
||||
raise CommandExecutionError(f"Unable to create temp file. Exception: {exc}")
|
||||
# use `copy` to preserve the inode of the
|
||||
# original file, and thus preserve hardlinks
|
||||
# to the inode. otherwise, use `move` to
|
||||
|
@ -1727,7 +1715,7 @@ def _regex_to_static(src, regex):
|
|||
compiled = re.compile(regex, re.DOTALL)
|
||||
src = [line for line in src if compiled.search(line) or line.count(regex)]
|
||||
except Exception as ex: # pylint: disable=broad-except
|
||||
raise CommandExecutionError("{}: '{}'".format(_get_error_message(ex), regex))
|
||||
raise CommandExecutionError(f"{_get_error_message(ex)}: '{regex}'")
|
||||
|
||||
return src
|
||||
|
||||
|
@ -1748,7 +1736,7 @@ def _assert_occurrence(probe, target, amount=1):
|
|||
|
||||
if msg:
|
||||
raise CommandExecutionError(
|
||||
'Found {} expected occurrences in "{}" expression'.format(msg, target)
|
||||
f'Found {msg} expected occurrences in "{target}" expression'
|
||||
)
|
||||
|
||||
return occ
|
||||
|
@ -1859,7 +1847,7 @@ def _set_line(
|
|||
"Mode was not defined. How to process the file?"
|
||||
)
|
||||
else:
|
||||
raise CommandExecutionError("Unknown mode: {}".format(mode))
|
||||
raise CommandExecutionError(f"Unknown mode: {mode}")
|
||||
|
||||
if mode != "delete" and content is None:
|
||||
raise CommandExecutionError("Content can only be empty if mode is delete")
|
||||
|
@ -2235,7 +2223,7 @@ def line(
|
|||
if not os.path.isfile(path):
|
||||
if not quiet:
|
||||
raise CommandExecutionError(
|
||||
'File "{}" does not exists or is not a file.'.format(path)
|
||||
f'File "{path}" does not exists or is not a file.'
|
||||
)
|
||||
return False # No changes had happened
|
||||
|
||||
|
@ -2246,7 +2234,7 @@ def line(
|
|||
"Mode was not defined. How to process the file?"
|
||||
)
|
||||
else:
|
||||
raise CommandExecutionError('Unknown mode: "{}"'.format(mode))
|
||||
raise CommandExecutionError(f'Unknown mode: "{mode}"')
|
||||
|
||||
# We've set the content to be empty in the function params but we want to make sure
|
||||
# it gets passed when needed. Feature #37092
|
||||
|
@ -2494,11 +2482,11 @@ def replace(
|
|||
if ignore_if_missing:
|
||||
return False
|
||||
else:
|
||||
raise SaltInvocationError("File not found: {}".format(path))
|
||||
raise SaltInvocationError(f"File not found: {path}")
|
||||
|
||||
if not __utils__["files.is_text"](path):
|
||||
raise SaltInvocationError(
|
||||
"Cannot perform string replacements on a binary file: {}".format(path)
|
||||
f"Cannot perform string replacements on a binary file: {path}"
|
||||
)
|
||||
|
||||
if search_only and (append_if_not_found or prepend_if_not_found):
|
||||
|
@ -2577,7 +2565,7 @@ def replace(
|
|||
# content if it was pre/appended in a previous run.
|
||||
if re.search(
|
||||
salt.utils.stringutils.to_bytes(
|
||||
"^{}($|(?=\r\n))".format(re.escape(content))
|
||||
f"^{re.escape(content)}($|(?=\r\n))"
|
||||
),
|
||||
r_data,
|
||||
flags=re_flags,
|
||||
|
@ -2595,9 +2583,7 @@ def replace(
|
|||
has_changes = False
|
||||
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError(
|
||||
"Unable to open file '{}'. Exception: {}".format(path, exc)
|
||||
)
|
||||
raise CommandExecutionError(f"Unable to open file '{path}'. Exception: {exc}")
|
||||
finally:
|
||||
if r_data and isinstance(r_data, mmap.mmap):
|
||||
r_data.close()
|
||||
|
@ -2608,7 +2594,7 @@ def replace(
|
|||
# Create a copy to read from and to use as a backup later
|
||||
temp_file = _mkstemp_copy(path=path, preserve_inode=preserve_inode)
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError("Exception: {}".format(exc))
|
||||
raise CommandExecutionError(f"Exception: {exc}")
|
||||
|
||||
r_data = None
|
||||
try:
|
||||
|
@ -2636,12 +2622,12 @@ def replace(
|
|||
"Exception: {}".format(path, temp_file, exc)
|
||||
)
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError("Exception: {}".format(exc))
|
||||
raise CommandExecutionError(f"Exception: {exc}")
|
||||
finally:
|
||||
if r_data and isinstance(r_data, mmap.mmap):
|
||||
r_data.close()
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError("Exception: {}".format(exc))
|
||||
raise CommandExecutionError(f"Exception: {exc}")
|
||||
|
||||
if not found and (append_if_not_found or prepend_if_not_found):
|
||||
if not_found_content is None:
|
||||
|
@ -2667,7 +2653,7 @@ def replace(
|
|||
# Create a copy to read from and for later use as a backup
|
||||
temp_file = _mkstemp_copy(path=path, preserve_inode=preserve_inode)
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError("Exception: {}".format(exc))
|
||||
raise CommandExecutionError(f"Exception: {exc}")
|
||||
# write new content in the file while avoiding partial reads
|
||||
try:
|
||||
fh_ = salt.utils.atomicfile.atomic_open(path, "wb")
|
||||
|
@ -2679,7 +2665,7 @@ def replace(
|
|||
if backup and has_changes and not dry_run:
|
||||
# keep the backup only if it was requested
|
||||
# and only if there were any changes
|
||||
backup_name = "{}{}".format(path, backup)
|
||||
backup_name = f"{path}{backup}"
|
||||
try:
|
||||
shutil.move(temp_file, backup_name)
|
||||
except OSError as exc:
|
||||
|
@ -2689,8 +2675,8 @@ def replace(
|
|||
"Exception: {}".format(path, temp_file, exc)
|
||||
)
|
||||
if symlink:
|
||||
symlink_backup = "{}{}".format(given_path, backup)
|
||||
target_backup = "{}{}".format(target_path, backup)
|
||||
symlink_backup = f"{given_path}{backup}"
|
||||
target_backup = f"{target_path}{backup}"
|
||||
# Always clobber any existing symlink backup
|
||||
# to match the behaviour of the 'backup' option
|
||||
try:
|
||||
|
@ -2709,7 +2695,7 @@ def replace(
|
|||
os.remove(temp_file)
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError(
|
||||
"Unable to delete temp file '{}'. Exception: {}".format(temp_file, exc)
|
||||
f"Unable to delete temp file '{temp_file}'. Exception: {exc}"
|
||||
)
|
||||
|
||||
if not dry_run and not salt.utils.platform.is_windows():
|
||||
|
@ -2848,7 +2834,7 @@ def blockreplace(
|
|||
path = os.path.expanduser(path)
|
||||
|
||||
if not os.path.exists(path):
|
||||
raise SaltInvocationError("File not found: {}".format(path))
|
||||
raise SaltInvocationError(f"File not found: {path}")
|
||||
|
||||
try:
|
||||
file_encoding = __utils__["files.get_encoding"](path)
|
||||
|
@ -2858,7 +2844,7 @@ def blockreplace(
|
|||
if __utils__["files.is_binary"](path):
|
||||
if not file_encoding:
|
||||
raise SaltInvocationError(
|
||||
"Cannot perform string replacements on a binary file: {}".format(path)
|
||||
f"Cannot perform string replacements on a binary file: {path}"
|
||||
)
|
||||
|
||||
if insert_before_match or insert_after_match:
|
||||
|
@ -2970,7 +2956,7 @@ def blockreplace(
|
|||
new_file.append(line)
|
||||
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError("Failed to read from {}: {}".format(path, exc))
|
||||
raise CommandExecutionError(f"Failed to read from {path}: {exc}")
|
||||
finally:
|
||||
if linesep is None:
|
||||
# If the file was empty, we will not have set linesep yet. Assume
|
||||
|
@ -3035,7 +3021,7 @@ def blockreplace(
|
|||
|
||||
# backup old content
|
||||
if backup is not False:
|
||||
backup_path = "{}{}".format(path, backup)
|
||||
backup_path = f"{path}{backup}"
|
||||
shutil.copy2(path, backup_path)
|
||||
# copy2 does not preserve ownership
|
||||
if salt.utils.platform.is_windows():
|
||||
|
@ -3070,7 +3056,7 @@ def blockreplace(
|
|||
|
||||
# backup old content
|
||||
if backup is not False:
|
||||
backup_path = "{}{}".format(path, backup)
|
||||
backup_path = f"{path}{backup}"
|
||||
shutil.copy2(path, backup_path)
|
||||
# copy2 does not preserve ownership
|
||||
if salt.utils.platform.is_windows():
|
||||
|
@ -3403,11 +3389,9 @@ def append(path, *args, **kwargs):
|
|||
# Append lines in text mode
|
||||
with salt.utils.files.fopen(path, "a") as ofile:
|
||||
for new_line in args:
|
||||
ofile.write(
|
||||
salt.utils.stringutils.to_str("{}{}".format(new_line, os.linesep))
|
||||
)
|
||||
ofile.write(salt.utils.stringutils.to_str(f"{new_line}{os.linesep}"))
|
||||
|
||||
return 'Wrote {} lines to "{}"'.format(len(args), path)
|
||||
return f'Wrote {len(args)} lines to "{path}"'
|
||||
|
||||
|
||||
def prepend(path, *args, **kwargs):
|
||||
|
@ -3461,12 +3445,12 @@ def prepend(path, *args, **kwargs):
|
|||
|
||||
preface = []
|
||||
for line in args:
|
||||
preface.append("{}\n".format(line))
|
||||
preface.append(f"{line}\n")
|
||||
|
||||
with salt.utils.files.fopen(path, "w") as ofile:
|
||||
contents = preface + contents
|
||||
ofile.write(salt.utils.stringutils.to_str("".join(contents)))
|
||||
return 'Prepended {} lines to "{}"'.format(len(args), path)
|
||||
return f'Prepended {len(args)} lines to "{path}"'
|
||||
|
||||
|
||||
def write(path, *args, **kwargs):
|
||||
|
@ -3511,10 +3495,10 @@ def write(path, *args, **kwargs):
|
|||
|
||||
contents = []
|
||||
for line in args:
|
||||
contents.append("{}\n".format(line))
|
||||
contents.append(f"{line}\n")
|
||||
with salt.utils.files.fopen(path, "w") as ofile:
|
||||
ofile.write(salt.utils.stringutils.to_str("".join(contents)))
|
||||
return 'Wrote {} lines to "{}"'.format(len(contents), path)
|
||||
return f'Wrote {len(contents)} lines to "{path}"'
|
||||
|
||||
|
||||
def touch(name, atime=None, mtime=None):
|
||||
|
@ -3675,7 +3659,7 @@ def link(src, path):
|
|||
os.link(src, path)
|
||||
return True
|
||||
except OSError as E:
|
||||
raise CommandExecutionError("Could not create '{}': {}".format(path, E))
|
||||
raise CommandExecutionError(f"Could not create '{path}': {E}")
|
||||
return False
|
||||
|
||||
|
||||
|
@ -3715,7 +3699,7 @@ def is_link(path):
|
|||
return os.path.islink(os.path.expanduser(path))
|
||||
|
||||
|
||||
def symlink(src, path, force=False, atomic=False):
|
||||
def symlink(src, path, force=False, atomic=False, follow_symlinks=True):
|
||||
"""
|
||||
Create a symbolic link (symlink, soft link) to a file
|
||||
|
||||
|
@ -3733,6 +3717,11 @@ def symlink(src, path, force=False, atomic=False):
|
|||
Use atomic file operations to create the symlink
|
||||
.. versionadded:: 3006.0
|
||||
|
||||
follow_symlinks (bool):
|
||||
If set to ``False``, use ``os.path.lexists()`` for existence checks
|
||||
instead of ``os.path.exists()``.
|
||||
.. versionadded:: 3007.0
|
||||
|
||||
Returns:
|
||||
bool: ``True`` if successful, otherwise raises ``CommandExecutionError``
|
||||
|
||||
|
@ -3744,8 +3733,13 @@ def symlink(src, path, force=False, atomic=False):
|
|||
"""
|
||||
path = os.path.expanduser(path)
|
||||
|
||||
if follow_symlinks:
|
||||
exists = os.path.exists
|
||||
else:
|
||||
exists = os.path.lexists
|
||||
|
||||
if not os.path.isabs(path):
|
||||
raise SaltInvocationError("Link path must be absolute: {}".format(path))
|
||||
raise SaltInvocationError(f"Link path must be absolute: {path}")
|
||||
|
||||
if os.path.islink(path):
|
||||
try:
|
||||
|
@ -3758,14 +3752,14 @@ def symlink(src, path, force=False, atomic=False):
|
|||
pass
|
||||
|
||||
if not force and not atomic:
|
||||
msg = "Found existing symlink: {}".format(path)
|
||||
msg = f"Found existing symlink: {path}"
|
||||
raise CommandExecutionError(msg)
|
||||
|
||||
if os.path.exists(path) and not force and not atomic:
|
||||
msg = "Existing path is not a symlink: {}".format(path)
|
||||
if exists(path) and not force and not atomic:
|
||||
msg = f"Existing path is not a symlink: {path}"
|
||||
raise CommandExecutionError(msg)
|
||||
|
||||
if (os.path.islink(path) or os.path.exists(path)) and force and not atomic:
|
||||
if (os.path.islink(path) or exists(path)) and force and not atomic:
|
||||
os.unlink(path)
|
||||
elif atomic:
|
||||
link_dir = os.path.dirname(path)
|
||||
|
@ -3782,13 +3776,13 @@ def symlink(src, path, force=False, atomic=False):
|
|||
return True
|
||||
except OSError:
|
||||
os.remove(temp_link)
|
||||
raise CommandExecutionError("Could not create '{}'".format(path))
|
||||
raise CommandExecutionError(f"Could not create '{path}'")
|
||||
|
||||
try:
|
||||
os.symlink(src, path)
|
||||
return True
|
||||
except OSError:
|
||||
raise CommandExecutionError("Could not create '{}'".format(path))
|
||||
raise CommandExecutionError(f"Could not create '{path}'")
|
||||
|
||||
|
||||
def rename(src, dst):
|
||||
|
@ -3811,7 +3805,7 @@ def rename(src, dst):
|
|||
os.rename(src, dst)
|
||||
return True
|
||||
except OSError:
|
||||
raise CommandExecutionError("Could not rename '{}' to '{}'".format(src, dst))
|
||||
raise CommandExecutionError(f"Could not rename '{src}' to '{dst}'")
|
||||
return False
|
||||
|
||||
|
||||
|
@ -3849,7 +3843,7 @@ def copy(src, dst, recurse=False, remove_existing=False):
|
|||
raise SaltInvocationError("File path must be absolute.")
|
||||
|
||||
if not os.path.exists(src):
|
||||
raise CommandExecutionError("No such file or directory '{}'".format(src))
|
||||
raise CommandExecutionError(f"No such file or directory '{src}'")
|
||||
|
||||
if not salt.utils.platform.is_windows():
|
||||
pre_user = get_user(src)
|
||||
|
@ -3872,7 +3866,7 @@ def copy(src, dst, recurse=False, remove_existing=False):
|
|||
else:
|
||||
shutil.copyfile(src, dst)
|
||||
except OSError:
|
||||
raise CommandExecutionError("Could not copy '{}' to '{}'".format(src, dst))
|
||||
raise CommandExecutionError(f"Could not copy '{src}' to '{dst}'")
|
||||
|
||||
if not salt.utils.platform.is_windows():
|
||||
check_perms(dst, None, pre_user, pre_group, pre_mode)
|
||||
|
@ -4014,10 +4008,10 @@ def readlink(path, canonicalize=False):
|
|||
path = os.path.expandvars(path)
|
||||
|
||||
if not os.path.isabs(path):
|
||||
raise SaltInvocationError("Path to link must be absolute: {}".format(path))
|
||||
raise SaltInvocationError(f"Path to link must be absolute: {path}")
|
||||
|
||||
if not os.path.islink(path):
|
||||
raise SaltInvocationError("A valid link was not specified: {}".format(path))
|
||||
raise SaltInvocationError(f"A valid link was not specified: {path}")
|
||||
|
||||
if canonicalize:
|
||||
return os.path.realpath(path)
|
||||
|
@ -4026,7 +4020,7 @@ def readlink(path, canonicalize=False):
|
|||
return salt.utils.path.readlink(path)
|
||||
except OSError as exc:
|
||||
if exc.errno == errno.EINVAL:
|
||||
raise CommandExecutionError("Not a symbolic link: {}".format(path))
|
||||
raise CommandExecutionError(f"Not a symbolic link: {path}")
|
||||
raise CommandExecutionError(exc.__str__())
|
||||
|
||||
|
||||
|
@ -4090,7 +4084,7 @@ def statvfs(path):
|
|||
)
|
||||
}
|
||||
except OSError:
|
||||
raise CommandExecutionError("Could not statvfs '{}'".format(path))
|
||||
raise CommandExecutionError(f"Could not statvfs '{path}'")
|
||||
return False
|
||||
|
||||
|
||||
|
@ -4118,7 +4112,7 @@ def stats(path, hash_type=None, follow_symlinks=True):
|
|||
# message in this exception. Any changes made to the message for this
|
||||
# exception will reflect the file.directory state as well, and will
|
||||
# likely require changes there.
|
||||
raise CommandExecutionError("Path not found: {}".format(path))
|
||||
raise CommandExecutionError(f"Path not found: {path}")
|
||||
else:
|
||||
if follow_symlinks:
|
||||
pstat = os.stat(path)
|
||||
|
@ -4260,7 +4254,7 @@ def remove(path, **kwargs):
|
|||
path = os.path.expanduser(path)
|
||||
|
||||
if not os.path.isabs(path):
|
||||
raise SaltInvocationError("File path must be absolute: {}".format(path))
|
||||
raise SaltInvocationError(f"File path must be absolute: {path}")
|
||||
|
||||
try:
|
||||
if os.path.islink(path) or (os.path.exists(path) and not os.path.isdir(path)):
|
||||
|
@ -4270,7 +4264,7 @@ def remove(path, **kwargs):
|
|||
shutil.rmtree(path)
|
||||
return True
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError("Could not remove '{}': {}".format(path, exc))
|
||||
raise CommandExecutionError(f"Could not remove '{path}': {exc}")
|
||||
return False
|
||||
|
||||
|
||||
|
@ -4352,7 +4346,7 @@ def get_selinux_context(path):
|
|||
if cmd_ret["retcode"] == 0:
|
||||
ret = cmd_ret["stdout"]
|
||||
else:
|
||||
ret = "No selinux context information is available for {}".format(path)
|
||||
ret = f"No selinux context information is available for {path}"
|
||||
|
||||
return ret
|
||||
|
||||
|
@ -4388,9 +4382,7 @@ def set_selinux_context(
|
|||
)
|
||||
if fcontext_result.get("retcode", None) != 0:
|
||||
# Problem setting fcontext policy
|
||||
raise CommandExecutionError(
|
||||
"Problem setting fcontext: {}".format(fcontext_result)
|
||||
)
|
||||
raise CommandExecutionError(f"Problem setting fcontext: {fcontext_result}")
|
||||
|
||||
cmd = ["chcon"]
|
||||
if user:
|
||||
|
@ -4420,7 +4412,7 @@ def source_list(source, source_hash, saltenv):
|
|||
|
||||
salt '*' file.source_list salt://http/httpd.conf '{hash_type: 'md5', 'hsum': <md5sum>}' base
|
||||
"""
|
||||
contextkey = "{}_|-{}_|-{}".format(source, source_hash, saltenv)
|
||||
contextkey = f"{source}_|-{source_hash}_|-{saltenv}"
|
||||
if contextkey in __context__:
|
||||
return __context__[contextkey]
|
||||
|
||||
|
@ -4700,12 +4692,12 @@ def get_managed(
|
|||
if parsed_scheme == "":
|
||||
parsed_path = sfn = source
|
||||
if not os.path.exists(sfn):
|
||||
msg = "Local file source {} does not exist".format(sfn)
|
||||
msg = f"Local file source {sfn} does not exist"
|
||||
return "", {}, msg
|
||||
elif parsed_scheme == "file":
|
||||
sfn = parsed_path
|
||||
if not os.path.exists(sfn):
|
||||
msg = "Local file source {} does not exist".format(sfn)
|
||||
msg = f"Local file source {sfn} does not exist"
|
||||
return "", {}, msg
|
||||
|
||||
if parsed_scheme and parsed_scheme.lower() in string.ascii_lowercase:
|
||||
|
@ -4718,7 +4710,7 @@ def get_managed(
|
|||
return (
|
||||
"",
|
||||
{},
|
||||
"Source file {} not found in saltenv '{}'".format(source, saltenv),
|
||||
f"Source file {source} not found in saltenv '{saltenv}'",
|
||||
)
|
||||
elif not source_hash and unix_local_source:
|
||||
source_sum = _get_local_file_source_sum(parsed_path)
|
||||
|
@ -4782,13 +4774,13 @@ def get_managed(
|
|||
# A 404 or other error code may raise an exception, catch it
|
||||
# and return a comment that will fail the calling state.
|
||||
_source = salt.utils.url.redact_http_basic_auth(source)
|
||||
return "", {}, "Failed to cache {}: {}".format(_source, exc)
|
||||
return "", {}, f"Failed to cache {_source}: {exc}"
|
||||
|
||||
# If cache failed, sfn will be False, so do a truth check on sfn first
|
||||
# as invoking os.path.exists() on a bool raises a TypeError.
|
||||
if not sfn or not os.path.exists(sfn):
|
||||
_source = salt.utils.url.redact_http_basic_auth(source)
|
||||
return sfn, {}, "Source file '{}' not found".format(_source)
|
||||
return sfn, {}, f"Source file '{_source}' not found"
|
||||
if sfn == name:
|
||||
raise SaltInvocationError("Source file cannot be the same as destination")
|
||||
|
||||
|
@ -4817,7 +4809,7 @@ def get_managed(
|
|||
return (
|
||||
sfn,
|
||||
{},
|
||||
"Specified template format {} is not supported".format(template),
|
||||
f"Specified template format {template} is not supported",
|
||||
)
|
||||
|
||||
if data["result"]:
|
||||
|
@ -4890,7 +4882,7 @@ def extract_hash(
|
|||
hash_type,
|
||||
)
|
||||
hash_type = ""
|
||||
hash_len_expr = "{},{}".format(min(HASHES_REVMAP), max(HASHES_REVMAP))
|
||||
hash_len_expr = f"{min(HASHES_REVMAP)},{max(HASHES_REVMAP)}"
|
||||
else:
|
||||
hash_len_expr = str(hash_len)
|
||||
|
||||
|
@ -5195,7 +5187,7 @@ def check_perms(
|
|||
ret["changes"]["user"] = user
|
||||
else:
|
||||
ret["result"] = False
|
||||
ret["comment"].append("Failed to change user to {}".format(user))
|
||||
ret["comment"].append(f"Failed to change user to {user}")
|
||||
elif "cuser" in perms:
|
||||
ret["changes"]["user"] = user
|
||||
|
||||
|
@ -5211,7 +5203,7 @@ def check_perms(
|
|||
ret["changes"]["group"] = group
|
||||
else:
|
||||
ret["result"] = False
|
||||
ret["comment"].append("Failed to change group to {}".format(group))
|
||||
ret["comment"].append(f"Failed to change group to {group}")
|
||||
elif "cgroup" in perms:
|
||||
ret["changes"]["group"] = group
|
||||
|
||||
|
@ -5224,7 +5216,7 @@ def check_perms(
|
|||
ret["changes"]["mode"] = mode
|
||||
else:
|
||||
ret["result"] = False
|
||||
ret["comment"].append("Failed to change mode to {}".format(mode))
|
||||
ret["comment"].append(f"Failed to change mode to {mode}")
|
||||
elif "cmode" in perms:
|
||||
ret["changes"]["mode"] = mode
|
||||
|
||||
|
@ -5257,9 +5249,7 @@ def check_perms(
|
|||
cmp_attrs = _cmp_attrs(name, attrs)
|
||||
if any(attr for attr in cmp_attrs):
|
||||
ret["result"] = False
|
||||
ret["comment"].append(
|
||||
"Failed to change attributes to {}".format(attrs)
|
||||
)
|
||||
ret["comment"].append(f"Failed to change attributes to {attrs}")
|
||||
changes["new"] = "".join(lsattr(name)[name])
|
||||
else:
|
||||
changes["new"] = attrs
|
||||
|
@ -5314,17 +5304,17 @@ def check_perms(
|
|||
selinux_change_new = ""
|
||||
selinux_change_orig = ""
|
||||
if requested_seuser:
|
||||
selinux_change_new += "User: {} ".format(requested_seuser)
|
||||
selinux_change_orig += "User: {} ".format(current_seuser)
|
||||
selinux_change_new += f"User: {requested_seuser} "
|
||||
selinux_change_orig += f"User: {current_seuser} "
|
||||
if requested_serole:
|
||||
selinux_change_new += "Role: {} ".format(requested_serole)
|
||||
selinux_change_orig += "Role: {} ".format(current_serole)
|
||||
selinux_change_new += f"Role: {requested_serole} "
|
||||
selinux_change_orig += f"Role: {current_serole} "
|
||||
if requested_setype:
|
||||
selinux_change_new += "Type: {} ".format(requested_setype)
|
||||
selinux_change_orig += "Type: {} ".format(current_setype)
|
||||
selinux_change_new += f"Type: {requested_setype} "
|
||||
selinux_change_orig += f"Type: {current_setype} "
|
||||
if requested_serange:
|
||||
selinux_change_new += "Range: {} ".format(requested_serange)
|
||||
selinux_change_orig += "Range: {} ".format(current_serange)
|
||||
selinux_change_new += f"Range: {requested_serange} "
|
||||
selinux_change_orig += f"Range: {current_serange} "
|
||||
|
||||
if __opts__["test"]:
|
||||
ret["comment"] = "File {} selinux context to be updated".format(
|
||||
|
@ -5364,9 +5354,7 @@ def check_perms(
|
|||
selinux_error = True
|
||||
|
||||
if not selinux_error:
|
||||
ret["comment"].append(
|
||||
"The file {} is set to be changed".format(name)
|
||||
)
|
||||
ret["comment"].append(f"The file {name} is set to be changed")
|
||||
|
||||
if requested_seuser:
|
||||
if current_seuser != requested_seuser:
|
||||
|
@ -5498,9 +5486,9 @@ def check_managed(
|
|||
if changes:
|
||||
log.info(changes)
|
||||
comments = ["The following values are set to be changed:\n"]
|
||||
comments.extend("{}: {}\n".format(key, val) for key, val in changes.items())
|
||||
comments.extend(f"{key}: {val}\n" for key, val in changes.items())
|
||||
return None, "".join(comments)
|
||||
return True, "The file {} is in the correct state".format(name)
|
||||
return True, f"The file {name} is in the correct state"
|
||||
|
||||
|
||||
def check_managed_changes(
|
||||
|
@ -6148,7 +6136,7 @@ def manage_file(
|
|||
# File is not present, cache it
|
||||
sfn = __salt__["cp.cache_file"](source, saltenv, verify_ssl=verify_ssl)
|
||||
if not sfn:
|
||||
return _error(ret, "Source file '{}' not found".format(source))
|
||||
return _error(ret, f"Source file '{source}' not found")
|
||||
htype = source_sum.get("hash_type", __opts__["hash_type"])
|
||||
# Recalculate source sum now that file has been cached
|
||||
source_sum = {"hash_type": htype, "hsum": get_hash(sfn, form=htype)}
|
||||
|
@ -6185,7 +6173,7 @@ def manage_file(
|
|||
source, saltenv, verify_ssl=verify_ssl, use_etag=use_etag
|
||||
)
|
||||
if not sfn:
|
||||
return _error(ret, "Source file '{}' not found".format(source))
|
||||
return _error(ret, f"Source file '{source}' not found")
|
||||
# If the downloaded file came from a non salt server or local
|
||||
# source, and we are not skipping checksum verification, then
|
||||
# verify that it matches the specified checksum.
|
||||
|
@ -6227,7 +6215,7 @@ def manage_file(
|
|||
)
|
||||
except OSError as io_error:
|
||||
__clean_tmp(sfn)
|
||||
return _error(ret, "Failed to commit change: {}".format(io_error))
|
||||
return _error(ret, f"Failed to commit change: {io_error}")
|
||||
|
||||
if contents is not None:
|
||||
# Write the static contents to a temporary file
|
||||
|
@ -6258,7 +6246,7 @@ def manage_file(
|
|||
|
||||
except CommandExecutionError as exc:
|
||||
ret.setdefault("warnings", []).append(
|
||||
"Failed to detect changes to file: {}".format(exc.strerror)
|
||||
f"Failed to detect changes to file: {exc.strerror}"
|
||||
)
|
||||
differences = ""
|
||||
|
||||
|
@ -6275,7 +6263,7 @@ def manage_file(
|
|||
)
|
||||
except OSError as io_error:
|
||||
__clean_tmp(tmp)
|
||||
return _error(ret, "Failed to commit change: {}".format(io_error))
|
||||
return _error(ret, f"Failed to commit change: {io_error}")
|
||||
__clean_tmp(tmp)
|
||||
|
||||
# Check for changing symlink to regular file here
|
||||
|
@ -6283,7 +6271,7 @@ def manage_file(
|
|||
if not sfn:
|
||||
sfn = __salt__["cp.cache_file"](source, saltenv, verify_ssl=verify_ssl)
|
||||
if not sfn:
|
||||
return _error(ret, "Source file '{}' not found".format(source))
|
||||
return _error(ret, f"Source file '{source}' not found")
|
||||
# If the downloaded file came from a non salt server source verify
|
||||
# that it matches the intended sum value
|
||||
if check_web_source_hash:
|
||||
|
@ -6307,7 +6295,7 @@ def manage_file(
|
|||
)
|
||||
except OSError as io_error:
|
||||
__clean_tmp(sfn)
|
||||
return _error(ret, "Failed to commit change: {}".format(io_error))
|
||||
return _error(ret, f"Failed to commit change: {io_error}")
|
||||
|
||||
ret["changes"]["diff"] = "Replace symbolic link with regular file"
|
||||
|
||||
|
@ -6341,7 +6329,7 @@ def manage_file(
|
|||
)
|
||||
|
||||
if ret["changes"]:
|
||||
ret["comment"] = "File {} updated".format(salt.utils.data.decode(name))
|
||||
ret["comment"] = f"File {salt.utils.data.decode(name)} updated"
|
||||
|
||||
elif not ret["changes"] and ret["result"]:
|
||||
ret["comment"] = "File {} is in the correct state".format(
|
||||
|
@ -6359,7 +6347,7 @@ def manage_file(
|
|||
drive, _ = os.path.splitdrive(name)
|
||||
if drive and not os.path.exists(drive):
|
||||
__clean_tmp(sfn)
|
||||
return _error(ret, "{} drive not present".format(drive))
|
||||
return _error(ret, f"{drive} drive not present")
|
||||
if dir_mode is None and mode is not None:
|
||||
# Add execute bit to each nonzero digit in the mode, if
|
||||
# dir_mode was not specified. Otherwise, any
|
||||
|
@ -6392,7 +6380,7 @@ def manage_file(
|
|||
if not sfn:
|
||||
sfn = __salt__["cp.cache_file"](source, saltenv, verify_ssl=verify_ssl)
|
||||
if not sfn:
|
||||
return _error(ret, "Source file '{}' not found".format(source))
|
||||
return _error(ret, f"Source file '{source}' not found")
|
||||
# If the downloaded file came from a non salt server source verify
|
||||
# that it matches the intended sum value
|
||||
if check_web_source_hash:
|
||||
|
@ -6433,16 +6421,16 @@ def manage_file(
|
|||
if contents is None:
|
||||
if not __opts__["test"]:
|
||||
if touch(name):
|
||||
ret["changes"]["new"] = "file {} created".format(name)
|
||||
ret["changes"]["new"] = f"file {name} created"
|
||||
ret["comment"] = "Empty file"
|
||||
else:
|
||||
return _error(ret, "Empty file {} not created".format(name))
|
||||
return _error(ret, f"Empty file {name} not created")
|
||||
else:
|
||||
if not __opts__["test"]:
|
||||
if touch(name):
|
||||
ret["changes"]["diff"] = "New file"
|
||||
else:
|
||||
return _error(ret, "File {} not created".format(name))
|
||||
return _error(ret, f"File {name} not created")
|
||||
|
||||
if contents is not None:
|
||||
# Write the static contents to a temporary file
|
||||
|
@ -6575,12 +6563,12 @@ def makedirs_(path, user=None, group=None, mode=None):
|
|||
|
||||
if os.path.isdir(dirname):
|
||||
# There's nothing for us to do
|
||||
msg = "Directory '{}' already exists".format(dirname)
|
||||
msg = f"Directory '{dirname}' already exists"
|
||||
log.debug(msg)
|
||||
return msg
|
||||
|
||||
if os.path.exists(dirname):
|
||||
msg = "The path '{}' already exists and is not a directory".format(dirname)
|
||||
msg = f"The path '{dirname}' already exists and is not a directory"
|
||||
log.debug(msg)
|
||||
return msg
|
||||
|
||||
|
@ -6634,7 +6622,7 @@ def makedirs_perms(name, user=None, group=None, mode="0755"):
|
|||
if tail == os.curdir: # xxx/newdir/. exists if xxx/newdir exists
|
||||
return
|
||||
os.mkdir(name)
|
||||
check_perms(name, None, user, group, int("{}".format(mode)) if mode else None)
|
||||
check_perms(name, None, user, group, int(f"{mode}") if mode else None)
|
||||
|
||||
|
||||
def get_devmm(name):
|
||||
|
@ -6704,7 +6692,7 @@ def mknod_chrdev(name, major, minor, user=None, group=None, mode="0660"):
|
|||
)
|
||||
try:
|
||||
if __opts__["test"]:
|
||||
ret["changes"] = {"new": "Character device {} created.".format(name)}
|
||||
ret["changes"] = {"new": f"Character device {name} created."}
|
||||
ret["result"] = None
|
||||
else:
|
||||
if (
|
||||
|
@ -6715,7 +6703,7 @@ def mknod_chrdev(name, major, minor, user=None, group=None, mode="0660"):
|
|||
)
|
||||
is None
|
||||
):
|
||||
ret["changes"] = {"new": "Character device {} created.".format(name)}
|
||||
ret["changes"] = {"new": f"Character device {name} created."}
|
||||
ret["result"] = True
|
||||
except OSError as exc:
|
||||
# be happy it is already there....however, if you are trying to change the
|
||||
|
@ -6723,9 +6711,9 @@ def mknod_chrdev(name, major, minor, user=None, group=None, mode="0660"):
|
|||
if exc.errno != errno.EEXIST:
|
||||
raise
|
||||
else:
|
||||
ret["comment"] = "File {} exists and cannot be overwritten".format(name)
|
||||
ret["comment"] = f"File {name} exists and cannot be overwritten"
|
||||
# quick pass at verifying the permissions of the newly created character device
|
||||
check_perms(name, None, user, group, int("{}".format(mode)) if mode else None)
|
||||
check_perms(name, None, user, group, int(f"{mode}") if mode else None)
|
||||
return ret
|
||||
|
||||
|
||||
|
@ -6777,7 +6765,7 @@ def mknod_blkdev(name, major, minor, user=None, group=None, mode="0660"):
|
|||
)
|
||||
try:
|
||||
if __opts__["test"]:
|
||||
ret["changes"] = {"new": "Block device {} created.".format(name)}
|
||||
ret["changes"] = {"new": f"Block device {name} created."}
|
||||
ret["result"] = None
|
||||
else:
|
||||
if (
|
||||
|
@ -6788,7 +6776,7 @@ def mknod_blkdev(name, major, minor, user=None, group=None, mode="0660"):
|
|||
)
|
||||
is None
|
||||
):
|
||||
ret["changes"] = {"new": "Block device {} created.".format(name)}
|
||||
ret["changes"] = {"new": f"Block device {name} created."}
|
||||
ret["result"] = True
|
||||
except OSError as exc:
|
||||
# be happy it is already there....however, if you are trying to change the
|
||||
|
@ -6796,9 +6784,9 @@ def mknod_blkdev(name, major, minor, user=None, group=None, mode="0660"):
|
|||
if exc.errno != errno.EEXIST:
|
||||
raise
|
||||
else:
|
||||
ret["comment"] = "File {} exists and cannot be overwritten".format(name)
|
||||
ret["comment"] = f"File {name} exists and cannot be overwritten"
|
||||
# quick pass at verifying the permissions of the newly created block device
|
||||
check_perms(name, None, user, group, int("{}".format(mode)) if mode else None)
|
||||
check_perms(name, None, user, group, int(f"{mode}") if mode else None)
|
||||
return ret
|
||||
|
||||
|
||||
|
@ -6844,20 +6832,20 @@ def mknod_fifo(name, user=None, group=None, mode="0660"):
|
|||
log.debug("Creating FIFO name: %s", name)
|
||||
try:
|
||||
if __opts__["test"]:
|
||||
ret["changes"] = {"new": "Fifo pipe {} created.".format(name)}
|
||||
ret["changes"] = {"new": f"Fifo pipe {name} created."}
|
||||
ret["result"] = None
|
||||
else:
|
||||
if os.mkfifo(name, int(str(mode).lstrip("0Oo"), 8)) is None:
|
||||
ret["changes"] = {"new": "Fifo pipe {} created.".format(name)}
|
||||
ret["changes"] = {"new": f"Fifo pipe {name} created."}
|
||||
ret["result"] = True
|
||||
except OSError as exc:
|
||||
# be happy it is already there
|
||||
if exc.errno != errno.EEXIST:
|
||||
raise
|
||||
else:
|
||||
ret["comment"] = "File {} exists and cannot be overwritten".format(name)
|
||||
ret["comment"] = f"File {name} exists and cannot be overwritten"
|
||||
# quick pass at verifying the permissions of the newly created fifo
|
||||
check_perms(name, None, user, group, int("{}".format(mode)) if mode else None)
|
||||
check_perms(name, None, user, group, int(f"{mode}") if mode else None)
|
||||
return ret
|
||||
|
||||
|
||||
|
@ -6939,9 +6927,9 @@ def list_backups(path, limit=None):
|
|||
]:
|
||||
if salt.utils.platform.is_windows():
|
||||
# ':' is an illegal filesystem path character on Windows
|
||||
strpfmt = "{}_%a_%b_%d_%H-%M-%S_%f_%Y".format(basename)
|
||||
strpfmt = f"{basename}_%a_%b_%d_%H-%M-%S_%f_%Y"
|
||||
else:
|
||||
strpfmt = "{}_%a_%b_%d_%H:%M:%S_%f_%Y".format(basename)
|
||||
strpfmt = f"{basename}_%a_%b_%d_%H:%M:%S_%f_%Y"
|
||||
try:
|
||||
timestamp = datetime.datetime.strptime(fname, strpfmt)
|
||||
except ValueError:
|
||||
|
@ -7017,7 +7005,7 @@ def list_backups_dir(path, limit=None):
|
|||
for x in sorted(ff):
|
||||
basename = x.split("_")[0]
|
||||
if i == basename:
|
||||
strpfmt = "{}_%a_%b_%d_%H:%M:%S_%f_%Y".format(basename)
|
||||
strpfmt = f"{basename}_%a_%b_%d_%H:%M:%S_%f_%Y"
|
||||
try:
|
||||
timestamp = datetime.datetime.strptime(x, strpfmt)
|
||||
except ValueError:
|
||||
|
@ -7067,7 +7055,7 @@ def restore_backup(path, backup_id):
|
|||
|
||||
# Note: This only supports minion backups, so this function will need to be
|
||||
# modified if/when master backups are implemented.
|
||||
ret = {"result": False, "comment": "Invalid backup_id '{}'".format(backup_id)}
|
||||
ret = {"result": False, "comment": f"Invalid backup_id '{backup_id}'"}
|
||||
try:
|
||||
if len(str(backup_id)) == len(str(int(backup_id))):
|
||||
backup = list_backups(path)[int(backup_id)]
|
||||
|
@ -7076,7 +7064,7 @@ def restore_backup(path, backup_id):
|
|||
except ValueError:
|
||||
return ret
|
||||
except KeyError:
|
||||
ret["comment"] = "backup_id '{}' does not exist for {}".format(backup_id, path)
|
||||
ret["comment"] = f"backup_id '{backup_id}' does not exist for {path}"
|
||||
return ret
|
||||
|
||||
salt.utils.files.backup_minion(path, _get_bkroot())
|
||||
|
@ -7126,7 +7114,7 @@ def delete_backup(path, backup_id):
|
|||
"""
|
||||
path = os.path.expanduser(path)
|
||||
|
||||
ret = {"result": False, "comment": "Invalid backup_id '{}'".format(backup_id)}
|
||||
ret = {"result": False, "comment": f"Invalid backup_id '{backup_id}'"}
|
||||
try:
|
||||
if len(str(backup_id)) == len(str(int(backup_id))):
|
||||
backup = list_backups(path)[int(backup_id)]
|
||||
|
@ -7135,7 +7123,7 @@ def delete_backup(path, backup_id):
|
|||
except ValueError:
|
||||
return ret
|
||||
except KeyError:
|
||||
ret["comment"] = "backup_id '{}' does not exist for {}".format(backup_id, path)
|
||||
ret["comment"] = f"backup_id '{backup_id}' does not exist for {path}"
|
||||
return ret
|
||||
|
||||
try:
|
||||
|
@ -7253,9 +7241,9 @@ def open_files(by_pid=False):
|
|||
# Then we look at the open files for each PID
|
||||
files = {}
|
||||
for pid in pids:
|
||||
ppath = "/proc/{}".format(pid)
|
||||
ppath = f"/proc/{pid}"
|
||||
try:
|
||||
tids = os.listdir("{}/task".format(ppath))
|
||||
tids = os.listdir(f"{ppath}/task")
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
|
@ -7267,17 +7255,17 @@ def open_files(by_pid=False):
|
|||
# except Exception: # pylint: disable=broad-except
|
||||
# pass
|
||||
|
||||
for fpath in os.listdir("{}/fd".format(ppath)):
|
||||
fd_.append("{}/fd/{}".format(ppath, fpath))
|
||||
for fpath in os.listdir(f"{ppath}/fd"):
|
||||
fd_.append(f"{ppath}/fd/{fpath}")
|
||||
|
||||
for tid in tids:
|
||||
try:
|
||||
fd_.append(os.path.realpath("{}/task/{}/exe".format(ppath, tid)))
|
||||
fd_.append(os.path.realpath(f"{ppath}/task/{tid}/exe"))
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
for tpath in os.listdir("{}/task/{}/fd".format(ppath, tid)):
|
||||
fd_.append("{}/task/{}/fd/{}".format(ppath, tid, tpath))
|
||||
for tpath in os.listdir(f"{ppath}/task/{tid}/fd"):
|
||||
fd_.append(f"{ppath}/task/{tid}/fd/{tpath}")
|
||||
|
||||
fd_ = sorted(set(fd_))
|
||||
|
||||
|
@ -7454,15 +7442,13 @@ def move(src, dst, disallow_copy_and_unlink=False):
|
|||
|
||||
ret = {
|
||||
"result": True,
|
||||
"comment": "'{}' moved to '{}'".format(src, dst),
|
||||
"comment": f"'{src}' moved to '{dst}'",
|
||||
}
|
||||
|
||||
try:
|
||||
shutil.move(src, dst)
|
||||
except OSError as exc:
|
||||
raise CommandExecutionError(
|
||||
"Unable to move '{}' to '{}': {}".format(src, dst, exc)
|
||||
)
|
||||
raise CommandExecutionError(f"Unable to move '{src}' to '{dst}': {exc}")
|
||||
|
||||
return ret
|
||||
|
||||
|
|
|
@ -1542,6 +1542,7 @@ def symlink(
|
|||
atomic=False,
|
||||
disallow_copy_and_unlink=False,
|
||||
inherit_user_and_group=False,
|
||||
follow_symlinks=False,
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
|
@ -1647,6 +1648,13 @@ def symlink(
|
|||
override this behavior.
|
||||
|
||||
.. versionadded:: 3006.0
|
||||
|
||||
follow_symlinks (bool):
|
||||
If set to ``False``, the underlying ``file.symlink`` execution module
|
||||
and any checks in this state will use ``os.path.lexists()`` for
|
||||
existence checks instead of ``os.path.exists()``.
|
||||
|
||||
.. versionadded:: 3007.0
|
||||
"""
|
||||
name = os.path.expanduser(name)
|
||||
|
||||
|
@ -1654,6 +1662,11 @@ def symlink(
|
|||
if not name:
|
||||
return _error(ret, "Must provide name to file.symlink")
|
||||
|
||||
if follow_symlinks:
|
||||
exists = os.path.exists
|
||||
else:
|
||||
exists = os.path.lexists
|
||||
|
||||
# Make sure that leading zeros stripped by YAML loader are added back
|
||||
mode = salt.utils.files.normalize_mode(mode)
|
||||
|
||||
|
@ -1834,7 +1847,7 @@ def symlink(
|
|||
)
|
||||
return ret
|
||||
|
||||
elif os.path.exists(name):
|
||||
elif exists(name):
|
||||
# It is not a link, but a file, dir, socket, FIFO etc.
|
||||
if backupname is not None:
|
||||
if not os.path.isabs(backupname):
|
||||
|
@ -1892,7 +1905,9 @@ def symlink(
|
|||
)
|
||||
|
||||
try:
|
||||
__salt__["file.symlink"](target, name, force=force, atomic=atomic)
|
||||
__salt__["file.symlink"](
|
||||
target, name, force=force, atomic=atomic, follow_symlinks=follow_symlinks
|
||||
)
|
||||
except (CommandExecutionError, OSError) as exc:
|
||||
ret["result"] = False
|
||||
ret["comment"] = "Unable to create new symlink {} -> {}: {}".format(
|
||||
|
|
|
@ -272,3 +272,25 @@ def test_source_list_for_list_returns_local_file_proto_from_dict(myfile):
|
|||
):
|
||||
ret = filemod.source_list([{"file://" + myfile: ""}], "filehash", "base")
|
||||
assert list(ret) == ["file://" + myfile, "filehash"]
|
||||
|
||||
|
||||
def test_symlink_lexists_called_follow_symlinks_false():
|
||||
tfile = "/tmp/file-basics-test-file"
|
||||
a_link = "/tmp/a_link"
|
||||
|
||||
exists = MagicMock(return_value=False)
|
||||
lexists = MagicMock(return_value=False)
|
||||
|
||||
with patch("os.path.exists", exists), patch("os.path.lexists", lexists), patch(
|
||||
"os.symlink", MagicMock(return_value=True)
|
||||
):
|
||||
filemod.symlink(tfile, a_link)
|
||||
lexists.assert_not_called()
|
||||
exists.assert_called()
|
||||
|
||||
lexists.reset_mock()
|
||||
exists.reset_mock()
|
||||
|
||||
filemod.symlink(tfile, a_link, follow_symlinks=False)
|
||||
lexists.assert_called()
|
||||
exists.assert_not_called()
|
||||
|
|
Loading…
Add table
Reference in a new issue