lineinfile - properly insert line when line exists and backrefs are enabled (#63763)

Use a separate variable for the boolean test rather than having the same variable sometimes be a boolean and sometimes be a regular expression match object

Add integration tests to cover this scenario
This commit is contained in:
Sam Doran 2019-10-22 10:01:11 -04:00 committed by GitHub
parent f6c85b7380
commit 29d4d318a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 21 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- lineinfile - properly handle inserting a line when backrefs are enabled and the line already exists in the file (https://github.com/ansible/ansible/issues/63756)

View file

@ -286,7 +286,8 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create,
# index[0] is the line num where regexp has been found
# index[1] is the line num where insertafter/insertbefore has been found
index = [-1, -1]
m = None
match = None
exact_line_match = False
b_line = to_bytes(line, errors='surrogate_or_strict')
# The module's doc says
@ -303,18 +304,17 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create,
match_found = bre_m.search(b_cur_line)
if match_found:
index[0] = lineno
m = match_found
match = match_found
if firstmatch:
break
# 2. When no match found on the previous step,
# parse for searching insertafter/insertbefore:
if not m:
if not match:
for lineno, b_cur_line in enumerate(b_lines):
match_found = b_line == b_cur_line.rstrip(b'\r\n')
if match_found:
if b_line == b_cur_line.rstrip(b'\r\n'):
index[0] = lineno
m = match_found
exact_line_match = True
elif bre_ins is not None and bre_ins.search(b_cur_line):
if insertafter:
@ -334,8 +334,8 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create,
b_linesep = to_bytes(os.linesep, errors='surrogate_or_strict')
# Exact line or Regexp matched a line in the file
if index[0] != -1:
if backrefs:
b_new_line = m.expand(b_line)
if backrefs and match:
b_new_line = match.expand(b_line)
else:
# Don't do backref expansion if not asked.
b_new_line = b_line
@ -345,7 +345,7 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create,
# If no regexp was given and no line match is found anywhere in the file,
# insert the line appropriately if using insertbefore or insertafter
if regexp is None and m is None:
if regexp is None and match is None and not exact_line_match:
# Insert lines
if insertafter and insertafter != 'EOF':

View file

@ -126,7 +126,7 @@
lineinfile:
dest: "{{ output_dir }}/test.txt"
state: present
line: "New line after line 5"
line: "New line before line 5"
insertbefore: "^This is line 5$"
register: result
@ -144,22 +144,33 @@
- name: assert test checksum matches after the insert before the last line
assert:
that:
- "result.stat.checksum == 'e1cae425403507feea4b55bb30a74decfdd4a23e'"
- "result.stat.checksum == '2e9e460ff68929e4453eb765761fd99814f6e286'"
- name: replace a line with backrefs
- name: Replace a line with backrefs
lineinfile:
dest: "{{ output_dir }}/test.txt"
state: present
line: "This is line 3"
backrefs: yes
regexp: "^(REF) .* \\1$"
register: result
register: backrefs_result1
- name: Replace a line with backrefs again
lineinfile:
dest: "{{ output_dir }}/test.txt"
state: present
line: "This is line 3"
backrefs: yes
regexp: "^(REF) .* \\1$"
register: backrefs_result2
- command: cat {{ output_dir }}/test.txt
- name: assert that the line with backrefs was changed
assert:
that:
- result is changed
- "result.msg == 'line replaced'"
- backrefs_result1 is changed
- backrefs_result2 is not changed
- "backrefs_result1.msg == 'line replaced'"
- name: stat the test after the backref line was replaced
stat:
@ -169,7 +180,7 @@
- name: assert test checksum matches after backref line was replaced
assert:
that:
- "result.stat.checksum == '2ccdf45d20298f9eaece73b713648e5489a52444'"
- "result.stat.checksum == '72f60239a735ae06e769d823f5c2b4232c634d9c'"
- name: remove the middle line
lineinfile:
@ -192,7 +203,7 @@
- name: assert test checksum matches after the middle line was removed
assert:
that:
- "result.stat.checksum == 'a6ba6865547c19d4c203c38a35e728d6d1942c75'"
- "result.stat.checksum == 'd4eeb07bdebab2d1cdb3ec4a3635afa2618ad4ea'"
- name: run a validation script that succeeds
lineinfile:
@ -216,7 +227,7 @@
- name: assert test checksum matches after the validation succeeded
assert:
that:
- "result.stat.checksum == '76955a4516a00a38aad8427afc9ee3e361024ba5'"
- "result.stat.checksum == 'ab56c210ea82839a54487464800fed4878cb2608'"
- name: run a validation script that fails
lineinfile:
@ -240,7 +251,7 @@
- name: assert test checksum matches the previous after the validation failed
assert:
that:
- "result.stat.checksum == '76955a4516a00a38aad8427afc9ee3e361024ba5'"
- "result.stat.checksum == 'ab56c210ea82839a54487464800fed4878cb2608'"
- name: use create=yes
lineinfile:
@ -351,7 +362,7 @@
- name: assert test checksum matches after inserting multiple lines
assert:
that:
- "result.stat.checksum == 'bf5b711f8f0509355aaeb9d0d61e3e82337c1365'"
- "result.stat.checksum == 'fde683229429a4f05d670e6c10afc875e1d5c489'"
- name: replace a line with backrefs included in the line
lineinfile:
@ -376,7 +387,7 @@
- name: assert test checksum matches after backref line was replaced
assert:
that:
- "result.stat.checksum == '04b7a54d0fb233a4e26c9e625325bb4874841b3c'"
- "result.stat.checksum == '981ad35c4b30b03bc3a1beedce0d1e72c491898e'"
###################################################################
# issue 8535