From 2fb9b46752cbd8118da787ead9bea64d0b263e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Lecour?= Date: Mon, 17 Dec 2018 22:42:24 +0100 Subject: [PATCH] Lineinfile must not insert lines multiples times with insertbefore/insertafter (#49409) * 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. * Implement the change in behaviour mentioned in the previous commit * Fix comment to reflect what the code does * Set the correct return message. In these cases, the lines are added, not replaced. * Add a changelog --- ...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 451f3de94d3..635ac74336a 100644 --- a/lib/ansible/modules/files/lineinfile.py +++ b/lib/ansible/modules/files/lineinfile.py @@ -302,7 +302,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) @@ -313,9 +313,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': @@ -342,12 +342,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: