# test code for the lineinfile module # (c) 2014, James Cammarata # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . - name: deploy the test file for lineinfile copy: src: test.txt dest: "{{ remote_tmp_dir }}/test.txt" register: result - name: assert that the test file was deployed assert: that: - result is changed - "result.checksum == '5feac65e442c91f557fc90069ce6efc4d346ab51'" - "result.state == 'file'" - name: "create a file that does not yet exist with `create: yes` and produce diff" lineinfile: dest: "{{ remote_tmp_dir }}/a/a.txt" state: present line: "First line" create: yes diff: yes register: result1 - name: assert that a diff was returned assert: that: - result1.diff | length > 0 - name: stat the new file stat: path: "{{ remote_tmp_dir }}/a/a.txt" register: result - name: assert that the file exists assert: that: - result.stat.exists - block: - name: "EXPECTED FAILURE - test source file does not exist w/o `create: yes`" lineinfile: path: "/some/where/that/doesnotexist.txt" state: present line: "Doesn't matter" - fail: msg: "Should not get here" rescue: - name: Validate failure assert: that: - "'Destination /some/where/that/doesnotexist.txt does not exist !' in ansible_failed_result.msg" - block: - name: EXPECTED FAILURE - test invalid `validate` value lineinfile: path: "{{ remote_tmp_dir }}/test.txt" state: present line: "Doesn't matter" validate: '/some/path' - fail: msg: "Should not get here" rescue: - name: Validate failure assert: that: - "'validate must contain %s: /some/path' in ansible_failed_result.msg" - name: insert a line at the beginning of the file, and back it up lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: present line: "New line at the beginning" insertbefore: "BOF" backup: yes register: result1 - name: insert a line at the beginning of the file again lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: present line: "New line at the beginning" insertbefore: "BOF" register: result2 - name: assert that the line was inserted at the head of the file assert: that: - result1 is changed - result2 is not changed - result1.msg == 'line added' - result1.backup != '' - name: stat the backup file stat: path: "{{ result1.backup }}" register: result - name: assert the backup file matches the previous hash assert: that: - "result.stat.checksum == '5feac65e442c91f557fc90069ce6efc4d346ab51'" - name: stat the test after the insert at the head stat: path: "{{ remote_tmp_dir }}/test.txt" register: result - name: assert test hash is what we expect for the file with the insert at the head assert: that: - "result.stat.checksum == '7eade4042b23b800958fe807b5bfc29f8541ec09'" - name: insert a line at the end of the file lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: present line: "New line at the end" insertafter: "EOF" register: result - name: assert that the line was inserted at the end of the file assert: that: - result is changed - "result.msg == 'line added'" - name: stat the test after the insert at the end stat: path: "{{ remote_tmp_dir }}/test.txt" register: result - name: assert test checksum matches after the insert at the end assert: that: - "result.stat.checksum == 'fb57af7dc10a1006061b000f1f04c38e4bef50a9'" - name: insert a line after the first line lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: present line: "New line after line 1" insertafter: "^This is line 1$" register: result - name: assert that the line was inserted after the first line assert: that: - result is changed - "result.msg == 'line added'" - name: stat the test after insert after the first line stat: path: "{{ remote_tmp_dir }}/test.txt" register: result - name: assert test checksum matches after the insert after the first line assert: that: - "result.stat.checksum == '5348da605b1bc93dbadf3a16474cdf22ef975bec'" - name: insert a line before the last line lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: present line: "New line before line 5" insertbefore: "^This is line 5$" register: result - name: assert that the line was inserted before the last line assert: that: - result is changed - "result.msg == 'line added'" - name: stat the test after the insert before the last line stat: path: "{{ remote_tmp_dir }}/test.txt" register: result - name: assert test checksum matches after the insert before the last line assert: that: - "result.stat.checksum == '2e9e460ff68929e4453eb765761fd99814f6e286'" - name: Replace a line with backrefs lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: present line: "This is line 3" backrefs: yes regexp: "^(REF) .* \\1$" register: backrefs_result1 - name: Replace a line with backrefs again lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: present line: "This is line 3" backrefs: yes regexp: "^(REF) .* \\1$" register: backrefs_result2 - command: cat {{ remote_tmp_dir }}/test.txt - name: assert that the line with backrefs was changed assert: that: - 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: path: "{{ remote_tmp_dir }}/test.txt" register: result - name: assert test checksum matches after backref line was replaced assert: that: - "result.stat.checksum == '72f60239a735ae06e769d823f5c2b4232c634d9c'" - name: remove the middle line lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: absent regexp: "^This is line 3$" register: result - name: assert that the line was removed assert: that: - result is changed - "result.msg == '1 line(s) removed'" - name: stat the test after the middle line was removed stat: path: "{{ remote_tmp_dir }}/test.txt" register: result - name: assert test checksum matches after the middle line was removed assert: that: - "result.stat.checksum == 'd4eeb07bdebab2d1cdb3ec4a3635afa2618ad4ea'" - name: run a validation script that succeeds lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: absent regexp: "^This is line 5$" validate: "true %s" register: result - name: assert that the file validated after removing a line assert: that: - result is changed - "result.msg == '1 line(s) removed'" - name: stat the test after the validation succeeded stat: path: "{{ remote_tmp_dir }}/test.txt" register: result - name: assert test checksum matches after the validation succeeded assert: that: - "result.stat.checksum == 'ab56c210ea82839a54487464800fed4878cb2608'" - name: run a validation script that fails lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: absent regexp: "^This is line 1$" validate: "/bin/false %s" register: result ignore_errors: yes - name: assert that the validate failed assert: that: - "result.failed == true" - name: stat the test after the validation failed stat: path: "{{ remote_tmp_dir }}/test.txt" register: result - name: assert test checksum matches the previous after the validation failed assert: that: - "result.stat.checksum == 'ab56c210ea82839a54487464800fed4878cb2608'" - import_tasks: test_string01.yml - name: use create=yes lineinfile: dest: "{{ remote_tmp_dir }}/new_test.txt" create: yes insertbefore: BOF state: present line: "This is a new file" register: result - name: assert that the new file was created assert: that: - result is changed - "result.msg == 'line added'" - name: validate that the newly created file exists stat: path: "{{ remote_tmp_dir }}/new_test.txt" register: result ignore_errors: yes - name: assert the newly created test checksum matches assert: that: - "result.stat.checksum == '038f10f9e31202451b093163e81e06fbac0c6f3a'" - name: Create a file without a path lineinfile: dest: file.txt create: yes line: Test line register: create_no_path_test - name: Stat the file stat: path: file.txt register: create_no_path_file - name: Ensure file was created assert: that: - create_no_path_test is changed - create_no_path_file.stat.exists # Test EOF in cases where file has no newline at EOF - name: testnoeof deploy the file for lineinfile copy: src: testnoeof.txt dest: "{{ remote_tmp_dir }}/testnoeof.txt" register: result - name: testnoeof insert a line at the end of the file lineinfile: dest: "{{ remote_tmp_dir }}/testnoeof.txt" state: present line: "New line at the end" insertafter: "EOF" register: result - name: testempty assert that the line was inserted at the end of the file assert: that: - result is changed - "result.msg == 'line added'" - name: insert a multiple lines at the end of the file lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: present line: "This is a line\nwith \\n character" insertafter: "EOF" register: result - name: assert that the multiple lines was inserted assert: that: - result is changed - "result.msg == 'line added'" - name: testnoeof stat the no newline EOF test after the insert at the end stat: path: "{{ remote_tmp_dir }}/testnoeof.txt" register: result - name: testnoeof assert test checksum matches after the insert at the end assert: that: - "result.stat.checksum == 'f9af7008e3cb67575ce653d094c79cabebf6e523'" # Test EOF with empty file to make sure no unnecessary newline is added - name: testempty deploy the testempty file for lineinfile copy: src: testempty.txt dest: "{{ remote_tmp_dir }}/testempty.txt" register: result - name: testempty insert a line at the end of the file lineinfile: dest: "{{ remote_tmp_dir }}/testempty.txt" state: present line: "New line at the end" insertafter: "EOF" register: result - name: testempty assert that the line was inserted at the end of the file assert: that: - result is changed - "result.msg == 'line added'" - name: testempty stat the test after the insert at the end stat: path: "{{ remote_tmp_dir }}/testempty.txt" register: result - name: testempty assert test checksum matches after the insert at the end assert: that: - "result.stat.checksum == 'f440dc65ea9cec3fd496c1479ddf937e1b949412'" - stat: path: "{{ remote_tmp_dir }}/test.txt" register: result - name: assert test checksum matches after inserting multiple lines assert: that: - "result.stat.checksum == 'fde683229429a4f05d670e6c10afc875e1d5c489'" - name: replace a line with backrefs included in the line lineinfile: dest: "{{ remote_tmp_dir }}/test.txt" state: present line: "New \\1 created with the backref" backrefs: yes regexp: "^This is (line 4)$" register: result - name: assert that the line with backrefs was changed assert: that: - result is changed - "result.msg == 'line replaced'" - name: stat the test after the backref line was replaced stat: path: "{{ remote_tmp_dir }}/test.txt" register: result - name: assert test checksum matches after backref line was replaced assert: that: - "result.stat.checksum == '981ad35c4b30b03bc3a1beedce0d1e72c491898e'" ################################################################### # issue 8535 - name: create a new file for testing quoting issues file: dest: "{{ remote_tmp_dir }}/test_quoting.txt" state: touch register: result - name: assert the new file was created assert: that: - result is changed - name: use with_items to add code-like strings to the quoting txt file lineinfile: dest: "{{ remote_tmp_dir }}/test_quoting.txt" line: "{{ item }}" insertbefore: BOF with_items: - "'foo'" - "dotenv.load();" - "var dotenv = require('dotenv');" register: result - name: assert the quote test file was modified correctly assert: that: - result.results|length == 3 - result.results[0] is changed - result.results[0].item == "'foo'" - result.results[1] is changed - result.results[1].item == "dotenv.load();" - result.results[2] is changed - result.results[2].item == "var dotenv = require('dotenv');" - name: stat the quote test file stat: path: "{{ remote_tmp_dir }}/test_quoting.txt" register: result - name: assert test checksum matches after backref line was replaced assert: that: - "result.stat.checksum == '7dc3cb033c3971e73af0eaed6623d4e71e5743f1'" - name: insert a line into the quoted file with a single quote lineinfile: dest: "{{ remote_tmp_dir }}/test_quoting.txt" line: "import g'" register: result - name: assert that the quoted file was changed assert: that: - result is changed - name: stat the quote test file stat: path: "{{ remote_tmp_dir }}/test_quoting.txt" register: result - name: assert test checksum matches after backref line was replaced assert: that: - "result.stat.checksum == '73b271c2cc1cef5663713bc0f00444b4bf9f4543'" - name: insert a line into the quoted file with many double quotation strings lineinfile: dest: "{{ remote_tmp_dir }}/test_quoting.txt" line: "\"quote\" and \"unquote\"" register: result - name: assert that the quoted file was changed assert: that: - result is changed - name: stat the quote test file stat: path: "{{ remote_tmp_dir }}/test_quoting.txt" register: result - name: assert test checksum matches after backref line was replaced assert: that: - "result.stat.checksum == 'b10ab2a3c3b6492680c8d0b1d6f35aa6b8f9e731'" ################################################################### # Issue 28721 - name: Deploy the testmultiple file copy: src: testmultiple.txt dest: "{{ remote_tmp_dir }}/testmultiple.txt" register: result - name: Assert that the testmultiple file was deployed assert: that: - result is changed - result.checksum == '3e0090a34fb641f3c01e9011546ff586260ea0ea' - result.state == 'file' # Test insertafter - name: Write the same line to a file inserted after different lines lineinfile: path: "{{ remote_tmp_dir }}/testmultiple.txt" insertafter: "{{ item.regex }}" line: "{{ item.replace }}" 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: "{{ remote_tmp_dir }}/testmultiple.txt" insertafter: "{{ item.regex }}" line: "{{ item.replace }}" register: _multitest_2 with_items: "{{ test_regexp }}" - name: Assert that the line is not added anymore assert: that: - _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: path: "{{ remote_tmp_dir }}/testmultiple.txt" register: result - name: Assert that the insertafter file matches expected checksum assert: that: - result.stat.checksum == 'c6733b6c53ddd0e11e6ba39daa556ef8f4840761' # Test insertbefore - name: Deploy the testmultiple file copy: src: testmultiple.txt dest: "{{ remote_tmp_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: "{{ remote_tmp_dir }}/testmultiple.txt" insertbefore: "{{ item.regex }}" line: "{{ item.replace }}" 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: "{{ remote_tmp_dir }}/testmultiple.txt" insertbefore: "{{ item.regex }}" line: "{{ item.replace }}" register: _multitest_4 with_items: "{{ test_regexp }}" - name: Assert that the line is not added anymore assert: that: - _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: path: "{{ remote_tmp_dir }}/testmultiple.txt" register: result - name: Assert that the insertbefore file matches expected checksum assert: that: - result.stat.checksum == '5d298651fbc377b45257da10308a9dc2fe1f8be5' ################################################################### # Issue 36156 # Test insertbefore and insertafter with regexp - name: Deploy the test.conf file copy: src: test.conf dest: "{{ remote_tmp_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: "{{ remote_tmp_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: "{{ remote_tmp_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: "{{ remote_tmp_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: "{{ remote_tmp_dir }}/test.conf" line: "{{ item.line }}" insertafter: "{{ item.after }}" with_items: "{{ test_befaf_regexp }}" register: _multitest_7 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/test.conf" register: result - name: Assert that the file was changed when no regexp was provided assert: that: - item is not changed with_items: "{{ _multitest_7.results }}" - name: Stat the file stat: path: "{{ remote_tmp_dir }}/test.conf" register: result - name: Assert that the file contents match what is expected assert: that: - result.stat.checksum == '06e2c456e5028dd7bcd0b117b5927a1139458c82' # Test insertbefore - name: Deploy the test.conf file copy: src: test.conf dest: "{{ remote_tmp_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: "{{ remote_tmp_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: "{{ remote_tmp_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: "{{ remote_tmp_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: "{{ remote_tmp_dir }}/test.conf" line: "{{ item.line }}" insertbefore: "{{ item.before }}" with_items: "{{ test_befaf_regexp }}" register: _multitest_10 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/test.conf" register: result - name: Assert that the file was changed when no regexp was provided assert: that: - item is not changed with_items: "{{ _multitest_10.results }}" - name: Stat the file stat: path: "{{ remote_tmp_dir }}/test.conf" register: result - name: Assert that the file contents match what is expected assert: that: - result.stat.checksum == 'c3be9438a07c44d4c256cebfcdbca15a15b1db91' - name: Copy empty file to test with insertbefore copy: src: testempty.txt dest: "{{ remote_tmp_dir }}/testempty.txt" - name: Add a line to empty file with insertbefore lineinfile: path: "{{ remote_tmp_dir }}/testempty.txt" line: top insertbefore: '^not in the file$' register: oneline_insbefore_test1 - name: Add a line to file with only one line using insertbefore lineinfile: path: "{{ remote_tmp_dir }}/testempty.txt" line: top insertbefore: '^not in the file$' register: oneline_insbefore_test2 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/testempty.txt" register: oneline_insbefore_file - name: Assert that insertebefore worked properly with a one line file assert: that: - oneline_insbefore_test1 is changed - oneline_insbefore_test2 is not changed - oneline_insbefore_file.stat.checksum == '4dca56d05a21f0d018cd311f43e134e4501cf6d9' - import_tasks: test_string02.yml # Issue 29443 # When using an empty regexp, replace the last line (since it matches every line) # but also provide a warning. - name: Deploy the test file for lineinfile copy: src: test.txt dest: "{{ remote_tmp_dir }}/test.txt" register: result - name: Assert that the test file was deployed assert: that: - result is changed - result.checksum == '5feac65e442c91f557fc90069ce6efc4d346ab51' - result.state == 'file' - name: Insert a line in the file using an empty string as a regular expression lineinfile: path: "{{ remote_tmp_dir }}/test.txt" regexp: '' line: This is line 6 register: insert_empty_regexp - name: Stat the file stat: path: "{{ remote_tmp_dir }}/test.txt" register: result - name: Assert that the file contents match what is expected and a warning was displayed assert: that: - insert_empty_regexp is changed - warning_message in insert_empty_regexp.warnings - result.stat.checksum == '23555a98ceaa88756b4c7c7bba49d9f86eed868f' vars: warning_message: >- The regular expression is an empty string, which will match every line in the file. This may have unintended consequences, such as replacing the last line in the file rather than appending. If this is desired, use '^' to match every line in the file and avoid this warning. ################################################################### # When using an empty search string, replace the last line (since it matches every line) # but also provide a warning. - name: Deploy the test file for lineinfile copy: src: teststring.txt dest: "{{ remote_tmp_dir }}/teststring.txt" register: result - name: Assert that the test file was deployed assert: that: - result is changed - result.checksum == '481c2b73fe062390afdd294063a4f8285d69ac85' - result.state == 'file' - name: Insert a line in the file using an empty string as a search string lineinfile: path: "{{ remote_tmp_dir }}/teststring.txt" search_string: '' line: This is line 6 register: insert_empty_literal - name: Stat the file stat: path: "{{ remote_tmp_dir }}/teststring.txt" register: result - name: Assert that the file contents match what is expected and a warning was displayed assert: that: - insert_empty_literal is changed - warning_message in insert_empty_literal.warnings - result.stat.checksum == 'eaa79f878557d4bd8d96787a850526a0facab342' vars: warning_message: >- The search string is an empty string, which will match every line in the file. This may have unintended consequences, such as replacing the last line in the file rather than appending. - name: meta meta: end_play ################################################################### ## Issue #58923 ## Using firstmatch with insertafter and ensure multiple lines are not inserted - name: Deploy the firstmatch test file copy: src: firstmatch.txt dest: "{{ remote_tmp_dir }}/firstmatch.txt" register: result - name: Assert that the test file was deployed assert: that: - result is changed - result.checksum == '1d644e5e2e51c67f1bd12d7bbe2686017f39923d' - result.state == 'file' - name: Insert a line before an existing line using firstmatch lineinfile: path: "{{ remote_tmp_dir }}/firstmatch.txt" line: INSERT insertafter: line1 firstmatch: yes register: insertafter1 - name: Insert a line before an existing line using firstmatch again lineinfile: path: "{{ remote_tmp_dir }}/firstmatch.txt" line: INSERT insertafter: line1 firstmatch: yes register: insertafter2 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/firstmatch.txt" register: result - name: Assert that the file was modified appropriately assert: that: - insertafter1 is changed - insertafter2 is not changed - result.stat.checksum == '114aae024073a3ee8ec8db0ada03c5483326dd86' ######################################################################################## # Tests of fixing the same issue as above (#58923) by @Andersson007 # and @samdoran : # Test insertafter with regexp - name: Deploy the test file copy: src: test_58923.txt dest: "{{ remote_tmp_dir }}/test_58923.txt" register: initial_file - name: Assert that the test file was deployed assert: that: - initial_file is changed - initial_file.checksum == 'b6379ba43261c451a62102acb2c7f438a177c66e' - initial_file.state == 'file' # Regarding the documentation: # If regular expressions are passed to both regexp and # insertafter, insertafter is only honored if no match for regexp is found. # Therefore, # when regular expressions are passed to both regexp and insertafter, then: # 1. regexp was found -> ignore insertafter, replace the founded line # 2. regexp was not found -> insert the line after 'insertafter' line # Regexp is not present in the file, so the line must be inserted after ^#!/bin/sh - name: Add the line using firstmatch, regexp, and insertafter lineinfile: path: "{{ remote_tmp_dir }}/test_58923.txt" insertafter: '^#!/bin/sh' regexp: ^export FISHEYE_OPTS firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertafter_test1 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/test_58923.txt" register: insertafter_test1_file - name: Add the line using firstmatch, regexp, and insertafter again lineinfile: path: "{{ remote_tmp_dir }}/test_58923.txt" insertafter: '^#!/bin/sh' regexp: ^export FISHEYE_OPTS firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertafter_test2 # Check of the prev step. # We tried to add the same line with the same playbook, # so nothing has been added: - name: Stat the file again stat: path: "{{ remote_tmp_dir }}/test_58923.txt" register: insertafter_test2_file - name: Assert insertafter tests gave the expected results assert: that: - insertafter_test1 is changed - insertafter_test1_file.stat.checksum == '9232aed6fe88714964d9e29d13e42cd782070b08' - insertafter_test2 is not changed - insertafter_test2_file.stat.checksum == '9232aed6fe88714964d9e29d13e42cd782070b08' # Test insertafter without regexp - name: Deploy the test file copy: src: test_58923.txt dest: "{{ remote_tmp_dir }}/test_58923.txt" register: initial_file - name: Assert that the test file was deployed assert: that: - initial_file is changed - initial_file.checksum == 'b6379ba43261c451a62102acb2c7f438a177c66e' - initial_file.state == 'file' - name: Insert the line using firstmatch and insertafter without regexp lineinfile: path: "{{ remote_tmp_dir }}/test_58923.txt" insertafter: '^#!/bin/sh' firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertafter_test3 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/test_58923.txt" register: insertafter_test3_file - name: Insert the line using firstmatch and insertafter without regexp again lineinfile: path: "{{ remote_tmp_dir }}/test_58923.txt" insertafter: '^#!/bin/sh' firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertafter_test4 - name: Stat the file again stat: path: "{{ remote_tmp_dir }}/test_58923.txt" register: insertafter_test4_file - name: Assert insertafter without regexp tests gave the expected results assert: that: - insertafter_test3 is changed - insertafter_test3_file.stat.checksum == '9232aed6fe88714964d9e29d13e42cd782070b08' - insertafter_test4 is not changed - insertafter_test4_file.stat.checksum == '9232aed6fe88714964d9e29d13e42cd782070b08' # Test insertbefore with regexp - name: Deploy the test file copy: src: test_58923.txt dest: "{{ remote_tmp_dir }}/test_58923.txt" register: initial_file - name: Assert that the test file was deployed assert: that: - initial_file is changed - initial_file.checksum == 'b6379ba43261c451a62102acb2c7f438a177c66e' - initial_file.state == 'file' - name: Add the line using regexp, firstmatch, and insertbefore lineinfile: path: "{{ remote_tmp_dir }}/test_58923.txt" insertbefore: '^#!/bin/sh' regexp: ^export FISHEYE_OPTS firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertbefore_test1 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/test_58923.txt" register: insertbefore_test1_file - name: Add the line using regexp, firstmatch, and insertbefore again lineinfile: path: "{{ remote_tmp_dir }}/test_58923.txt" insertbefore: '^#!/bin/sh' regexp: ^export FISHEYE_OPTS firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertbefore_test2 - name: Stat the file again stat: path: "{{ remote_tmp_dir }}/test_58923.txt" register: insertbefore_test2_file - name: Assert insertbefore with regexp tests gave the expected results assert: that: - insertbefore_test1 is changed - insertbefore_test1_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7' - insertbefore_test2 is not changed - insertbefore_test2_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7' # Test insertbefore without regexp - name: Deploy the test file copy: src: test_58923.txt dest: "{{ remote_tmp_dir }}/test_58923.txt" register: initial_file - name: Assert that the test file was deployed assert: that: - initial_file is changed - initial_file.checksum == 'b6379ba43261c451a62102acb2c7f438a177c66e' - initial_file.state == 'file' - name: Add the line using insertbefore and firstmatch lineinfile: path: "{{ remote_tmp_dir }}/test_58923.txt" insertbefore: '^#!/bin/sh' firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertbefore_test3 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/test_58923.txt" register: insertbefore_test3_file - name: Add the line using insertbefore and firstmatch again lineinfile: path: "{{ remote_tmp_dir }}/test_58923.txt" insertbefore: '^#!/bin/sh' firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertbefore_test4 - name: Stat the file again stat: path: "{{ remote_tmp_dir }}/test_58923.txt" register: insertbefore_test4_file # Test when the line is presented in the file but # not in the before/after spot and it does match the regexp: - name: > Add the line using insertbefore and firstmatch when the regexp line is presented but not close to insertbefore spot lineinfile: path: "{{ remote_tmp_dir }}/test_58923.txt" insertbefore: ' Darwin\*\) if \[ -z \"\$JAVA_HOME\" \] ; then' firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertbefore_test5 - name: Stat the file again stat: path: "{{ remote_tmp_dir }}/test_58923.txt" register: insertbefore_test5_file - name: Assert insertbefore with regexp tests gave the expected results assert: that: - insertbefore_test3 is changed - insertbefore_test3_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7' - insertbefore_test4 is not changed - insertbefore_test4_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7' - insertbefore_test5 is not changed - insertbefore_test5_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7' ######################################################################################## # Same tests for literal # Test insertafter with literal - name: Deploy the test file copy: src: teststring_58923.txt dest: "{{ remote_tmp_dir }}/teststring_58923.txt" register: initial_file - name: Assert that the test file was deployed assert: that: - initial_file is changed - initial_file.checksum == 'b6379ba43261c451a62102acb2c7f438a177c66e' - initial_file.state == 'file' # Regarding the documentation: # If the search string is passed to both search_string and # insertafter, insertafter is only honored if no match for search_string is found. # Therefore, # when search_string expressions are passed to both search_string and insertafter, then: # 1. search_string was found -> ignore insertafter, replace the founded line # 2. search_string was not found -> insert the line after 'insertafter' line # literal is not present in the file, so the line must be inserted after ^#!/bin/sh - name: Add the line using firstmatch, regexp, and insertafter lineinfile: path: "{{ remote_tmp_dir }}/teststring_58923.txt" insertafter: '^#!/bin/sh' search_string: export FISHEYE_OPTS firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertafter_test1 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/teststring_58923.txt" register: insertafter_test1_file - name: Add the line using firstmatch, literal, and insertafter again lineinfile: path: "{{ remote_tmp_dir }}/teststring_58923.txt" insertafter: '^#!/bin/sh' search_string: export FISHEYE_OPTS firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertafter_test2 # Check of the prev step. # We tried to add the same line with the same playbook, # so nothing has been added: - name: Stat the file again stat: path: "{{ remote_tmp_dir }}/teststring_58923.txt" register: insertafter_test2_file - name: Assert insertafter tests gave the expected results assert: that: - insertafter_test1 is changed - insertafter_test1_file.stat.checksum == '9232aed6fe88714964d9e29d13e42cd782070b08' - insertafter_test2 is not changed - insertafter_test2_file.stat.checksum == '9232aed6fe88714964d9e29d13e42cd782070b08' # Test insertbefore with literal - name: Deploy the test file copy: src: teststring_58923.txt dest: "{{ remote_tmp_dir }}/teststring_58923.txt" register: initial_file - name: Assert that the test file was deployed assert: that: - initial_file is changed - initial_file.checksum == 'b6379ba43261c451a62102acb2c7f438a177c66e' - initial_file.state == 'file' - name: Add the line using literal, firstmatch, and insertbefore lineinfile: path: "{{ remote_tmp_dir }}/teststring_58923.txt" insertbefore: '^#!/bin/sh' search_string: export FISHEYE_OPTS firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertbefore_test1 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/teststring_58923.txt" register: insertbefore_test1_file - name: Add the line using literal, firstmatch, and insertbefore again lineinfile: path: "{{ remote_tmp_dir }}/teststring_58923.txt" insertbefore: '^#!/bin/sh' search_string: export FISHEYE_OPTS firstmatch: true line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m" register: insertbefore_test2 - name: Stat the file again stat: path: "{{ remote_tmp_dir }}/teststring_58923.txt" register: insertbefore_test2_file - name: Assert insertbefore with literal tests gave the expected results assert: that: - insertbefore_test1 is changed - insertbefore_test1_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7' - insertbefore_test2 is not changed - insertbefore_test2_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7' # Test inserting a line at the end of the file using regexp with insertafter # https://github.com/ansible/ansible/issues/63684 - name: Create a file by inserting a line lineinfile: path: "{{ remote_tmp_dir }}/testend.txt" create: yes line: testline register: testend1 - name: Insert a line at the end of the file lineinfile: path: "{{ remote_tmp_dir }}/testend.txt" insertafter: testline regexp: line at the end line: line at the end register: testend2 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/testend.txt" register: testend_file - name: Assert inserting at the end gave the expected results. assert: that: - testend1 is changed - testend2 is changed - testend_file.stat.checksum == 'ef36116966836ce04f6b249fd1837706acae4e19' # Test inserting a line at the end of the file using search_string with insertafter - name: Create a file by inserting a line lineinfile: path: "{{ remote_tmp_dir }}/testendliteral.txt" create: yes line: testline register: testend1 - name: Insert a line at the end of the file lineinfile: path: "{{ remote_tmp_dir }}/testendliteral.txt" insertafter: testline search_string: line at the end line: line at the end register: testend2 - name: Stat the file stat: path: "{{ remote_tmp_dir }}/testendliteral.txt" register: testend_file - name: Assert inserting at the end gave the expected results. assert: that: - testend1 is changed - testend2 is changed - testend_file.stat.checksum == 'ef36116966836ce04f6b249fd1837706acae4e19'