From f9dcf40de59c433e4b7ed04b07e3d6467c6e243a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Lecour?= Date: Tue, 15 Jan 2019 02:52:18 +0100 Subject: [PATCH] [backport 2.6] Lineinfile must not insert lines multiples times with insertbefore/insertafter (#50086) * Change test suite to fit expected behaviour This reverts some changes from ansible/ansible@723daf3 If a line is found in the file, exactly or via regexp matching, it must not be added again. insertafter/insertbefore options are used only when a line is to be inserted, to specify where it must be added. (cherry picked from commit 31c11de2af000972ba13f584e82001a2bc9c062a) (cherry picked from commit eb92ce3d6f036be24fee1bad479daa4e6bc33221) * Implement the change in behaviour mentioned in the previous commit (cherry picked from commit a4141cfa2e49973310bba8c0962ef82d66c35f29) (cherry picked from commit 6afe25d93e9bfe8059e7aa013b412984e272529d) * Fix comment to reflect what the code does (cherry picked from commit 150f5cb232f10e38509823cb5864a9fd800b6df5) (cherry picked from commit 1a13bf06a3b6920c2c99094980bc85ae53e661cd) * Set the correct return message. In these cases, the lines are added, not replaced. (cherry picked from commit 3216c31401d15906e2435422e71dfb96e30678c4) (cherry picked from commit 5bd04bd5d57dd283de46ae3049dde6e97cdcf0e0) * Add a changelog (cherry picked from commit c39cf6b33269eac35c3c769de41e7c3dea642b68) (cherry picked from commit fc071636b47c6982eb9b5a508545f78ad8e70e96) --- ...es_times_with_insertbefore_insertafter.yml | 3 + lib/ansible/modules/files/lineinfile.py | 10 +-- .../targets/lineinfile/tasks/main.yml | 64 +++++++++++++------ 3 files changed, 54 insertions(+), 23 deletions(-) create mode 100644 changelogs/fragments/49409-lineinfile_must_not_insert_lines_multiples_times_with_insertbefore_insertafter.yml diff --git a/changelogs/fragments/49409-lineinfile_must_not_insert_lines_multiples_times_with_insertbefore_insertafter.yml b/changelogs/fragments/49409-lineinfile_must_not_insert_lines_multiples_times_with_insertbefore_insertafter.yml new file mode 100644 index 00000000000..ff92a0670c4 --- /dev/null +++ b/changelogs/fragments/49409-lineinfile_must_not_insert_lines_multiples_times_with_insertbefore_insertafter.yml @@ -0,0 +1,3 @@ +--- +bugfixes: + - "This reverts some changes from commit 723daf3. If a line is found in the file, exactly or via regexp matching, it must not be added again. `insertafter`/`insertbefore` options are used only when a line is to be inserted, to specify where it must be added." diff --git a/lib/ansible/modules/files/lineinfile.py b/lib/ansible/modules/files/lineinfile.py index 66969cb3d6c..0cf7f4c3ef3 100644 --- a/lib/ansible/modules/files/lineinfile.py +++ b/lib/ansible/modules/files/lineinfile.py @@ -295,7 +295,7 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create, msg = '' changed = False b_linesep = to_bytes(os.linesep, errors='surrogate_or_strict') - # Regexp matched a line in the file + # Exact line or Regexp matched a line in the file if index[0] != -1: if backrefs: b_new_line = m.expand(b_line) @@ -306,9 +306,9 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create, if not b_new_line.endswith(b_linesep): b_new_line += b_linesep - # If no regexp was given and a line match is found anywhere in the file, + # 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: + if regexp is None and m is None: # Insert lines if insertafter and insertafter != 'EOF': @@ -335,12 +335,12 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create, 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' + msg = 'line added' 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' + msg = 'line added' changed = True elif b_lines[index[0]] != b_new_line: diff --git a/test/integration/targets/lineinfile/tasks/main.yml b/test/integration/targets/lineinfile/tasks/main.yml index 680394f4267..7aa37f15a83 100644 --- a/test/integration/targets/lineinfile/tasks/main.yml +++ b/test/integration/targets/lineinfile/tasks/main.yml @@ -491,6 +491,14 @@ register: _multitest_1 with_items: "{{ test_regexp }}" +- name: Assert that the line is added once only + assert: + that: + - _multitest_1.results.0 is changed + - _multitest_1.results.1 is not changed + - _multitest_1.results.2 is not changed + - _multitest_1.results.3 is not changed + - name: Do the same thing again to check for changes lineinfile: path: "{{ output_dir }}/testmultiple.txt" @@ -499,14 +507,13 @@ register: _multitest_2 with_items: "{{ test_regexp }}" -- name: Assert that the file was changed the first time but not the second time +- name: Assert that the line is not added anymore assert: that: - - item.0 is changed - - item.1 is not changed - with_together: - - "{{ _multitest_1.results }}" - - "{{ _multitest_2.results }}" + - _multitest_2.results.0 is not changed + - _multitest_2.results.1 is not changed + - _multitest_2.results.2 is not changed + - _multitest_2.results.3 is not changed - name: Stat the insertafter file stat: @@ -516,9 +523,23 @@ - name: Assert that the insertafter file matches expected checksum assert: that: - - result.stat.checksum == '282fedf460b3ed7357667a9c8b457ec67b53b6ea' + - result.stat.checksum == 'c6733b6c53ddd0e11e6ba39daa556ef8f4840761' # Test insertbefore + +- name: Deploy the testmultiple file + copy: + src: testmultiple.txt + dest: "{{ output_dir }}/testmultiple.txt" + register: result + +- name: Assert that the testmultiple file was deployed + assert: + that: + - result is changed + - result.checksum == '3e0090a34fb641f3c01e9011546ff586260ea0ea' + - result.state == 'file' + - name: Write the same line to a file inserted before different lines lineinfile: path: "{{ output_dir }}/testmultiple.txt" @@ -527,6 +548,14 @@ register: _multitest_3 with_items: "{{ test_regexp }}" +- name: Assert that the line is added once only + assert: + that: + - _multitest_3.results.0 is changed + - _multitest_3.results.1 is not changed + - _multitest_3.results.2 is not changed + - _multitest_3.results.3 is not changed + - name: Do the same thing again to check for changes lineinfile: path: "{{ output_dir }}/testmultiple.txt" @@ -535,14 +564,13 @@ register: _multitest_4 with_items: "{{ test_regexp }}" -- name: Assert that the file was changed the first time but not the second time +- name: Assert that the line is not added anymore assert: that: - - item.0 is changed - - item.1 is not changed - with_together: - - "{{ _multitest_3.results }}" - - "{{ _multitest_4.results }}" + - _multitest_4.results.0 is not changed + - _multitest_4.results.1 is not changed + - _multitest_4.results.2 is not changed + - _multitest_4.results.3 is not changed - name: Stat the insertbefore file stat: @@ -552,7 +580,7 @@ - name: Assert that the insertbefore file matches expected checksum assert: that: - - result.stat.checksum == 'a8452bb3643be8d18ba3fc212632b1633bd9f885' + - result.stat.checksum == '5d298651fbc377b45257da10308a9dc2fe1f8be5' ################################################################### # Issue 36156 @@ -625,7 +653,7 @@ - name: Assert that the file was changed when no regexp was provided assert: that: - - item is changed + - item is not changed with_items: "{{ _multitest_7.results }}" - name: Stat the file @@ -636,7 +664,7 @@ - name: Assert that the file contents match what is expected assert: that: - - result.stat.checksum == '5bf50f3d74afd20de4010ca5c04bc7037b062d30' + - result.stat.checksum == '06e2c456e5028dd7bcd0b117b5927a1139458c82' # Test insertbefore - name: Deploy the test.conf file @@ -705,7 +733,7 @@ - name: Assert that the file was changed when no regexp was provided assert: that: - - item is changed + - item is not changed with_items: "{{ _multitest_10.results }}" - name: Stat the file @@ -716,7 +744,7 @@ - name: Assert that the file contents match what is expected assert: that: - - result.stat.checksum == 'eca8d8ea089d4ea57a3b87d4091599ca8b60dfd2' + - result.stat.checksum == 'c3be9438a07c44d4c256cebfcdbca15a15b1db91' - name: Copy empty file to test with insertbefore copy: