mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 17:50:20 +00:00
* port PR #48989 to master * fix pylint literal-comparison * fix test for windows due to check_perms differences Co-authored-by: Daniel Wozniak <dwozniak@saltstack.com>
This commit is contained in:
parent
c10a6f0c4a
commit
1f70709318
3 changed files with 192 additions and 21 deletions
|
@ -2743,6 +2743,8 @@ def blockreplace(
|
|||
dry_run=False,
|
||||
show_changes=True,
|
||||
append_newline=False,
|
||||
insert_before_match=None,
|
||||
insert_after_match=None,
|
||||
):
|
||||
"""
|
||||
.. versionadded:: 2014.1.0
|
||||
|
@ -2785,6 +2787,17 @@ def blockreplace(
|
|||
If markers are not found and set to ``True`` then, the markers and
|
||||
content will be prepended to the file.
|
||||
|
||||
insert_before_match
|
||||
If markers are not found, this parameter can be set to a regex which will
|
||||
insert the block before the first found occurrence in the file.
|
||||
|
||||
.. versionadded:: Sodium
|
||||
|
||||
insert_after_match
|
||||
If markers are not found, this parameter can be set to a regex which will
|
||||
insert the block after the first found occurrence in the file.
|
||||
|
||||
.. versionadded:: Sodium
|
||||
|
||||
backup
|
||||
The file extension to use for a backup of the file if any edit is made.
|
||||
|
@ -2823,9 +2836,16 @@ def blockreplace(
|
|||
'#-- end managed zone foobar --' $'10.0.1.1 foo.foobar\\n10.0.1.2 bar.foobar' True
|
||||
|
||||
"""
|
||||
if append_if_not_found and prepend_if_not_found:
|
||||
exclusive_params = [
|
||||
append_if_not_found,
|
||||
prepend_if_not_found,
|
||||
bool(insert_before_match),
|
||||
bool(insert_after_match),
|
||||
]
|
||||
if sum(exclusive_params) > 1:
|
||||
raise SaltInvocationError(
|
||||
"Only one of append and prepend_if_not_found is permitted"
|
||||
"Only one of append_if_not_found, prepend_if_not_found,"
|
||||
" insert_before_match, and insert_after_match is permitted"
|
||||
)
|
||||
|
||||
path = os.path.expanduser(path)
|
||||
|
@ -2844,6 +2864,18 @@ def blockreplace(
|
|||
"Cannot perform string replacements on a binary file: {0}".format(path)
|
||||
)
|
||||
|
||||
if insert_before_match or insert_after_match:
|
||||
if insert_before_match:
|
||||
if not isinstance(insert_before_match, six.string_types):
|
||||
raise CommandExecutionError(
|
||||
"RegEx expected in insert_before_match parameter."
|
||||
)
|
||||
elif insert_after_match:
|
||||
if not isinstance(insert_after_match, six.string_types):
|
||||
raise CommandExecutionError(
|
||||
"RegEx expected in insert_after_match parameter."
|
||||
)
|
||||
|
||||
if append_newline is None and not content.endswith((os.linesep, "\n")):
|
||||
append_newline = True
|
||||
|
||||
|
@ -2966,12 +2998,26 @@ def blockreplace(
|
|||
block_found = True
|
||||
elif append_if_not_found:
|
||||
# Make sure we have a newline at the end of the file
|
||||
if 0 != len(new_file):
|
||||
if new_file:
|
||||
if not new_file[-1].endswith(linesep):
|
||||
new_file[-1] += linesep
|
||||
# add the markers and content at the end of file
|
||||
_add_content(linesep, lines=new_file)
|
||||
block_found = True
|
||||
elif insert_before_match or insert_after_match:
|
||||
match_regex = insert_before_match or insert_after_match
|
||||
match_idx = [
|
||||
i for i, item in enumerate(orig_file) if re.search(match_regex, item)
|
||||
]
|
||||
if match_idx:
|
||||
match_idx = match_idx[0]
|
||||
for line in _add_content(linesep):
|
||||
if insert_after_match:
|
||||
match_idx += 1
|
||||
new_file.insert(match_idx, line)
|
||||
if insert_before_match:
|
||||
match_idx += 1
|
||||
block_found = True
|
||||
else:
|
||||
raise CommandExecutionError(
|
||||
"Cannot edit marked block. Markers were not found in file."
|
||||
|
@ -3008,34 +3054,57 @@ def blockreplace(
|
|||
mode=perms["mode"],
|
||||
)
|
||||
|
||||
# write new content in the file while avoiding partial reads
|
||||
try:
|
||||
fh_ = salt.utils.atomicfile.atomic_open(path, "wb")
|
||||
for line in new_file:
|
||||
fh_.write(
|
||||
salt.utils.stringutils.to_bytes(line, encoding=file_encoding)
|
||||
)
|
||||
finally:
|
||||
fh_.close()
|
||||
if not block_found:
|
||||
raise CommandExecutionError(
|
||||
"Cannot edit marked block. Markers were not found in file."
|
||||
)
|
||||
|
||||
# this may have overwritten file attrs
|
||||
diff = __utils__["stringutils.get_diff"](orig_file, new_file)
|
||||
has_changes = diff != ""
|
||||
if has_changes and not dry_run:
|
||||
# changes detected
|
||||
# backup file attrs
|
||||
perms = {}
|
||||
perms["user"] = get_user(path)
|
||||
perms["group"] = get_group(path)
|
||||
perms["mode"] = salt.utils.files.normalize_mode(get_mode(path))
|
||||
|
||||
# backup old content
|
||||
if backup is not False:
|
||||
backup_path = "{0}{1}".format(path, backup)
|
||||
shutil.copy2(path, backup_path)
|
||||
# copy2 does not preserve ownership
|
||||
if salt.utils.platform.is_windows():
|
||||
# This function resides in win_file.py and will be available
|
||||
# on Windows. The local function will be overridden
|
||||
# pylint: disable=E1120,E1123
|
||||
check_perms(path=path, ret=None, owner=perms["user"])
|
||||
check_perms(path=backup_path, ret=None, owner=perms["user"])
|
||||
# pylint: enable=E1120,E1123
|
||||
else:
|
||||
check_perms(
|
||||
path,
|
||||
ret=None,
|
||||
user=perms["user"],
|
||||
group=perms["group"],
|
||||
mode=perms["mode"],
|
||||
backup_path, None, perms["user"], perms["group"], perms["mode"]
|
||||
)
|
||||
|
||||
if show_changes:
|
||||
return diff
|
||||
# write new content in the file while avoiding partial reads
|
||||
try:
|
||||
fh_ = salt.utils.atomicfile.atomic_open(path, "wb")
|
||||
for line in new_file:
|
||||
fh_.write(salt.utils.stringutils.to_bytes(line, encoding=file_encoding))
|
||||
finally:
|
||||
fh_.close()
|
||||
|
||||
# this may have overwritten file attrs
|
||||
if salt.utils.platform.is_windows():
|
||||
# This function resides in win_file.py and will be available
|
||||
# on Windows. The local function will be overridden
|
||||
# pylint: disable=E1120,E1123
|
||||
check_perms(path=path, ret=None, owner=perms["user"])
|
||||
# pylint: enable=E1120,E1123
|
||||
else:
|
||||
check_perms(path, None, perms["user"], perms["group"], perms["mode"])
|
||||
|
||||
if show_changes:
|
||||
return diff
|
||||
|
||||
return has_changes
|
||||
|
||||
|
|
|
@ -5574,6 +5574,8 @@ def blockreplace(
|
|||
backup=".bak",
|
||||
show_changes=True,
|
||||
append_newline=None,
|
||||
insert_before_match=None,
|
||||
insert_after_match=None,
|
||||
):
|
||||
"""
|
||||
Maintain an edit in a file in a zone delimited by two line markers
|
||||
|
@ -5700,6 +5702,18 @@ def blockreplace(
|
|||
If markers are not found and this option is set to ``True``, the
|
||||
content block will be prepended to the file.
|
||||
|
||||
insert_before_match
|
||||
If markers are not found, this parameter can be set to a regex which will
|
||||
insert the block before the first found occurrence in the file.
|
||||
|
||||
.. versionadded:: Sodium
|
||||
|
||||
insert_after_match
|
||||
If markers are not found, this parameter can be set to a regex which will
|
||||
insert the block after the first found occurrence in the file.
|
||||
|
||||
.. versionadded:: Sodium
|
||||
|
||||
backup
|
||||
The file extension to use for a backup of the file if any edit is made.
|
||||
Set this to ``False`` to skip making a backup.
|
||||
|
@ -5830,6 +5844,8 @@ def blockreplace(
|
|||
content=content,
|
||||
append_if_not_found=append_if_not_found,
|
||||
prepend_if_not_found=prepend_if_not_found,
|
||||
insert_before_match=insert_before_match,
|
||||
insert_after_match=insert_after_match,
|
||||
backup=backup,
|
||||
dry_run=__opts__["test"],
|
||||
show_changes=show_changes,
|
||||
|
|
|
@ -486,6 +486,49 @@ class FileBlockReplaceTestCase(TestCase, LoaderModuleMockMixin):
|
|||
fp.read(),
|
||||
)
|
||||
|
||||
def test_replace_insert_after(self):
|
||||
new_content = "Well, I didn't vote for you."
|
||||
|
||||
self.assertRaises(
|
||||
CommandExecutionError,
|
||||
filemod.blockreplace,
|
||||
self.tfile.name,
|
||||
marker_start="#-- START BLOCK 2",
|
||||
marker_end="#-- END BLOCK 2",
|
||||
content=new_content,
|
||||
insert_after_match="not in the text",
|
||||
backup=False,
|
||||
)
|
||||
with salt.utils.files.fopen(self.tfile.name, "r") as fp:
|
||||
self.assertNotIn(
|
||||
"#-- START BLOCK 2" + "\n" + new_content + "#-- END BLOCK 2",
|
||||
salt.utils.stringutils.to_unicode(fp.read()),
|
||||
)
|
||||
|
||||
if salt.utils.platform.is_windows():
|
||||
check_perms_patch = win_file.check_perms
|
||||
else:
|
||||
check_perms_patch = filemod.check_perms
|
||||
with patch.object(filemod, "check_perms", check_perms_patch):
|
||||
filemod.blockreplace(
|
||||
self.tfile.name,
|
||||
marker_start="#-- START BLOCK 2",
|
||||
marker_end="#-- END BLOCK 2",
|
||||
content=new_content,
|
||||
backup=False,
|
||||
insert_after_match="malesuada",
|
||||
)
|
||||
|
||||
with salt.utils.files.fopen(self.tfile.name, "rb") as fp:
|
||||
self.assertIn(
|
||||
salt.utils.stringutils.to_bytes(
|
||||
os.linesep.join(
|
||||
["#-- START BLOCK 2", "{0}#-- END BLOCK 2".format(new_content)]
|
||||
)
|
||||
),
|
||||
fp.read(),
|
||||
)
|
||||
|
||||
def test_replace_append_newline_at_eof(self):
|
||||
"""
|
||||
Check that file.blockreplace works consistently on files with and
|
||||
|
@ -592,6 +635,49 @@ class FileBlockReplaceTestCase(TestCase, LoaderModuleMockMixin):
|
|||
)
|
||||
)
|
||||
|
||||
def test_replace_insert_before(self):
|
||||
new_content = "Well, I didn't vote for you."
|
||||
|
||||
self.assertRaises(
|
||||
CommandExecutionError,
|
||||
filemod.blockreplace,
|
||||
self.tfile.name,
|
||||
marker_start="#-- START BLOCK 2",
|
||||
marker_end="#-- END BLOCK 2",
|
||||
content=new_content,
|
||||
insert_before_match="not in the text",
|
||||
backup=False,
|
||||
)
|
||||
with salt.utils.files.fopen(self.tfile.name, "r") as fp:
|
||||
self.assertNotIn(
|
||||
"#-- START BLOCK 2" + "\n" + new_content + "#-- END BLOCK 2",
|
||||
salt.utils.stringutils.to_unicode(fp.read()),
|
||||
)
|
||||
|
||||
if salt.utils.platform.is_windows():
|
||||
check_perms_patch = win_file.check_perms
|
||||
else:
|
||||
check_perms_patch = filemod.check_perms
|
||||
with patch.object(filemod, "check_perms", check_perms_patch):
|
||||
filemod.blockreplace(
|
||||
self.tfile.name,
|
||||
marker_start="#-- START BLOCK 2",
|
||||
marker_end="#-- END BLOCK 2",
|
||||
content=new_content,
|
||||
backup=False,
|
||||
insert_before_match="malesuada",
|
||||
)
|
||||
|
||||
with salt.utils.files.fopen(self.tfile.name, "rb") as fp:
|
||||
self.assertIn(
|
||||
salt.utils.stringutils.to_bytes(
|
||||
os.linesep.join(
|
||||
["#-- START BLOCK 2", "{0}#-- END BLOCK 2".format(new_content)]
|
||||
)
|
||||
),
|
||||
fp.read(),
|
||||
)
|
||||
|
||||
def test_replace_partial_marked_lines(self):
|
||||
if salt.utils.platform.is_windows():
|
||||
check_perms_patch = win_file.check_perms
|
||||
|
|
Loading…
Add table
Reference in a new issue