Check for regexp match when using insertbefore or insertafter (#36474)

Add tests to cover this scenario
Fixes #36156

(cherry picked from commit 723daf3e3a)

# Conflicts:
#	lib/ansible/modules/files/lineinfile.py
This commit is contained in:
Sam Doran 2018-02-21 17:03:38 -05:00 committed by Sam Doran
parent 0231cd9c93
commit 23289bd2f2
4 changed files with 221 additions and 30 deletions

View file

@ -44,10 +44,10 @@ options:
version_added: 1.7
description:
- The regular expression to look for in every line of the file. For
C(state=present), the pattern to replace if found; only the last line
C(state=present), the pattern to replace if found. Only the last line
found will be replaced. For C(state=absent), the pattern of the line(s)
to remove. Uses Python regular expressions; see
U(http://docs.python.org/2/library/re.html).
to remove. Uses Python regular expressions.
See U(http://docs.python.org/2/library/re.html).
state:
required: false
choices: [ present, absent ]
@ -177,8 +177,8 @@ EXAMPLES = r"""
validate: '/usr/sbin/visudo -cf %s'
"""
import re
import os
import re
import tempfile
# import module snippets
@ -275,7 +275,7 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create,
# + 1 for the next line
index[1] = lineno + 1
if insertbefore:
# + 1 for the previous line
# index[1] for the previous line
index[1] = lineno
msg = ''
@ -292,44 +292,49 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create,
if not b_new_line.endswith(b_linesep):
b_new_line += b_linesep
# Add lines when the regexp match already exists somewhere else in the file
if insertafter and insertafter != 'EOF':
# If a regexp is specified and a match is found anywhere in the file, do
# not insert the line before or after.
if regexp is None and m:
# Ensure there is a line separator after the found string
# at the end of the file.
if b_lines and not b_lines[-1][-1:] in (b('\n'), b('\r')):
b_lines[-1] = b_lines[-1] + b_linesep
# Insert lines
if insertafter and insertafter != 'EOF':
# If the line to insert after is at the end of the file
# use the appropriate index value.
if len(b_lines) == index[1]:
if b_lines[index[1] - 1].rstrip(b('\r\n')) != b_line:
b_lines.append(b_line + b_linesep)
# Ensure there is a line separator after the found string
# at the end of the file.
if b_lines and not b_lines[-1][-1:] in (b('\n'), b('\r')):
b_lines[-1] = b_lines[-1] + b_linesep
# If the line to insert after is at the end of the file
# use the appropriate index value.
if len(b_lines) == index[1]:
if b_lines[index[1] - 1].rstrip(b('\r\n')) != b_line:
b_lines.append(b_line + b_linesep)
msg = 'line added'
changed = True
elif b_lines[index[1]].rstrip(b('\r\n')) != b_line:
b_lines.insert(index[1], b_line + b_linesep)
msg = 'line added'
changed = True
elif b_lines[index[1]].rstrip(b('\r\n')) != b_line:
b_lines.insert(index[1], b_line + b_linesep)
msg = 'line added'
changed = True
elif insertbefore:
# If the line to insert before is at the beginning of the file
# use the appropriate index value.
if index[1] == 0:
if b_lines[index[1]].rstrip(b('\r\n')) != b_line:
elif insertbefore:
# If the line to insert before is at the beginning of the file
# use the appropriate index value.
if index[1] == 0:
if b_lines[index[1]].rstrip(b('\r\n')) != b_line:
b_lines.insert(index[1], b_line + b_linesep)
msg = 'line replaced'
changed = True
elif b_lines[index[1] - 1].rstrip(b('\r\n')) != b_line:
b_lines.insert(index[1], b_line + b_linesep)
msg = 'line replaced'
changed = True
elif b_lines[index[1] - 1].rstrip(b('\r\n')) != b_line:
b_lines.insert(index[1], b_line + b_linesep)
msg = 'line replaced'
changed = True
elif b_lines[index[0]] != b_new_line:
b_lines[index[0]] = b_new_line
msg = 'line replaced'
changed = True
elif backrefs:
# Do absolutely nothing, since it's not safe generating the line
# without the regexp matching to populate the backrefs.

View file

@ -0,0 +1,5 @@
[section_one]
[section_two]
[section_three]

View file

@ -544,3 +544,167 @@
assert:
that:
- result.stat.checksum == 'a8452bb3643be8d18ba3fc212632b1633bd9f885'
###################################################################
# Issue 36156
# Test insertbefore and insertafter with regexp
- name: Deploy the test.conf file
copy:
src: test.conf
dest: "{{ output_dir }}/test.conf"
register: result
- name: Assert that the test.conf file was deployed
assert:
that:
- result is changed
- result.checksum == '6037f13e419b132eb3fd20a89e60c6c87a6add38'
- result.state == 'file'
# Test instertafter
- name: Insert lines after with regexp
lineinfile:
path: "{{ output_dir }}/test.conf"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
insertafter: "{{ item.after }}"
with_items: "{{ test_befaf_regexp }}"
register: _multitest_5
- name: Do the same thing again and check for changes
lineinfile:
path: "{{ output_dir }}/test.conf"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
insertafter: "{{ item.after }}"
with_items: "{{ test_befaf_regexp }}"
register: _multitest_6
- name: Assert that the file was changed the first time but not the second time
assert:
that:
- item.0 is changed
- item.1 is not changed
with_together:
- "{{ _multitest_5.results }}"
- "{{ _multitest_6.results }}"
- name: Stat the file
stat:
path: "{{ output_dir }}/test.conf"
register: result
- name: Assert that the file contents match what is expected
assert:
that:
- result.stat.checksum == '06e2c456e5028dd7bcd0b117b5927a1139458c82'
- name: Do the same thing a third time without regexp and check for changes
lineinfile:
path: "{{ output_dir }}/test.conf"
line: "{{ item.line }}"
insertafter: "{{ item.after }}"
with_items: "{{ test_befaf_regexp }}"
register: _multitest_7
- name: Stat the file
stat:
path: "{{ output_dir }}/test.conf"
register: result
- name: Assert that the file was changed when no regexp was provided
assert:
that:
- item is changed
with_items: "{{ _multitest_7.results }}"
- name: Stat the file
stat:
path: "{{ output_dir }}/test.conf"
register: result
- name: Assert that the file contents match what is expected
assert:
that:
- result.stat.checksum == '5bf50f3d74afd20de4010ca5c04bc7037b062d30'
# Test insertbefore
- name: Deploy the test.conf file
copy:
src: test.conf
dest: "{{ output_dir }}/test.conf"
register: result
- name: Assert that the test.conf file was deployed
assert:
that:
- result is changed
- result.checksum == '6037f13e419b132eb3fd20a89e60c6c87a6add38'
- result.state == 'file'
- name: Insert lines before with regexp
lineinfile:
path: "{{ output_dir }}/test.conf"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
insertbefore: "{{ item.before }}"
with_items: "{{ test_befaf_regexp }}"
register: _multitest_8
- name: Do the same thing again and check for changes
lineinfile:
path: "{{ output_dir }}/test.conf"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
insertbefore: "{{ item.before }}"
with_items: "{{ test_befaf_regexp }}"
register: _multitest_9
- name: Assert that the file was changed the first time but not the second time
assert:
that:
- item.0 is changed
- item.1 is not changed
with_together:
- "{{ _multitest_8.results }}"
- "{{ _multitest_9.results }}"
- name: Stat the file
stat:
path: "{{ output_dir }}/test.conf"
register: result
- name: Assert that the file contents match what is expected
assert:
that:
- result.stat.checksum == 'c3be9438a07c44d4c256cebfcdbca15a15b1db91'
- name: Do the same thing a third time without regexp and check for changes
lineinfile:
path: "{{ output_dir }}/test.conf"
line: "{{ item.line }}"
insertbefore: "{{ item.before }}"
with_items: "{{ test_befaf_regexp }}"
register: _multitest_10
- name: Stat the file
stat:
path: "{{ output_dir }}/test.conf"
register: result
- name: Assert that the file was changed when no regexp was provided
assert:
that:
- item is changed
with_items: "{{ _multitest_10.results }}"
- name: Stat the file
stat:
path: "{{ output_dir }}/test.conf"
register: result
- name: Assert that the file contents match what is expected
assert:
that:
- result.stat.checksum == 'eca8d8ea089d4ea57a3b87d4091599ca8b60dfd2'

View file

@ -10,3 +10,20 @@ test_regexp:
- regex: '4'
replace: 'bar'
test_befaf_regexp:
- before: section_three
after: section_one
regexp: option_one=
line: option_one=1
- before: section_three
after: section_one
regexp: option_two=
line: option_two=2
- before: section_three
after: section_one
regexp: option_three=
line: option_three=3