mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10: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,
|
dry_run=False,
|
||||||
show_changes=True,
|
show_changes=True,
|
||||||
append_newline=False,
|
append_newline=False,
|
||||||
|
insert_before_match=None,
|
||||||
|
insert_after_match=None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
.. versionadded:: 2014.1.0
|
.. versionadded:: 2014.1.0
|
||||||
|
@ -2785,6 +2787,17 @@ def blockreplace(
|
||||||
If markers are not found and set to ``True`` then, the markers and
|
If markers are not found and set to ``True`` then, the markers and
|
||||||
content will be prepended to the file.
|
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
|
backup
|
||||||
The file extension to use for a backup of the file if any edit is made.
|
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
|
'#-- 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(
|
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)
|
path = os.path.expanduser(path)
|
||||||
|
@ -2844,6 +2864,18 @@ def blockreplace(
|
||||||
"Cannot perform string replacements on a binary file: {0}".format(path)
|
"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")):
|
if append_newline is None and not content.endswith((os.linesep, "\n")):
|
||||||
append_newline = True
|
append_newline = True
|
||||||
|
|
||||||
|
@ -2966,12 +2998,26 @@ def blockreplace(
|
||||||
block_found = True
|
block_found = True
|
||||||
elif append_if_not_found:
|
elif append_if_not_found:
|
||||||
# Make sure we have a newline at the end of the file
|
# 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):
|
if not new_file[-1].endswith(linesep):
|
||||||
new_file[-1] += linesep
|
new_file[-1] += linesep
|
||||||
# add the markers and content at the end of file
|
# add the markers and content at the end of file
|
||||||
_add_content(linesep, lines=new_file)
|
_add_content(linesep, lines=new_file)
|
||||||
block_found = True
|
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:
|
else:
|
||||||
raise CommandExecutionError(
|
raise CommandExecutionError(
|
||||||
"Cannot edit marked block. Markers were not found in file."
|
"Cannot edit marked block. Markers were not found in file."
|
||||||
|
@ -3008,34 +3054,57 @@ def blockreplace(
|
||||||
mode=perms["mode"],
|
mode=perms["mode"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# write new content in the file while avoiding partial reads
|
if not block_found:
|
||||||
try:
|
raise CommandExecutionError(
|
||||||
fh_ = salt.utils.atomicfile.atomic_open(path, "wb")
|
"Cannot edit marked block. Markers were not found in file."
|
||||||
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
|
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():
|
if salt.utils.platform.is_windows():
|
||||||
# This function resides in win_file.py and will be available
|
# This function resides in win_file.py and will be available
|
||||||
# on Windows. The local function will be overridden
|
# on Windows. The local function will be overridden
|
||||||
# pylint: disable=E1120,E1123
|
# 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
|
# pylint: enable=E1120,E1123
|
||||||
else:
|
else:
|
||||||
check_perms(
|
check_perms(
|
||||||
path,
|
backup_path, None, perms["user"], perms["group"], perms["mode"]
|
||||||
ret=None,
|
|
||||||
user=perms["user"],
|
|
||||||
group=perms["group"],
|
|
||||||
mode=perms["mode"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if show_changes:
|
# write new content in the file while avoiding partial reads
|
||||||
return diff
|
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
|
return has_changes
|
||||||
|
|
||||||
|
|
|
@ -5574,6 +5574,8 @@ def blockreplace(
|
||||||
backup=".bak",
|
backup=".bak",
|
||||||
show_changes=True,
|
show_changes=True,
|
||||||
append_newline=None,
|
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
|
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
|
If markers are not found and this option is set to ``True``, the
|
||||||
content block will be prepended to the file.
|
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
|
backup
|
||||||
The file extension to use for a backup of the file if any edit is made.
|
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.
|
Set this to ``False`` to skip making a backup.
|
||||||
|
@ -5830,6 +5844,8 @@ def blockreplace(
|
||||||
content=content,
|
content=content,
|
||||||
append_if_not_found=append_if_not_found,
|
append_if_not_found=append_if_not_found,
|
||||||
prepend_if_not_found=prepend_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,
|
backup=backup,
|
||||||
dry_run=__opts__["test"],
|
dry_run=__opts__["test"],
|
||||||
show_changes=show_changes,
|
show_changes=show_changes,
|
||||||
|
|
|
@ -486,6 +486,49 @@ class FileBlockReplaceTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
fp.read(),
|
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):
|
def test_replace_append_newline_at_eof(self):
|
||||||
"""
|
"""
|
||||||
Check that file.blockreplace works consistently on files with and
|
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):
|
def test_replace_partial_marked_lines(self):
|
||||||
if salt.utils.platform.is_windows():
|
if salt.utils.platform.is_windows():
|
||||||
check_perms_patch = win_file.check_perms
|
check_perms_patch = win_file.check_perms
|
||||||
|
|
Loading…
Add table
Reference in a new issue