1# test code for the lineinfile module
2# (c) 2014, James Cammarata <jcammarata@ansible.com>
3
4# This file is part of Ansible
5#
6# Ansible is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# Ansible is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
18
19- name: deploy the test file for lineinfile
20  copy:
21    src: test.txt
22    dest: "{{ output_dir }}/test.txt"
23  register: result
24
25- name: assert that the test file was deployed
26  assert:
27    that:
28      - result is changed
29      - "result.checksum == '5feac65e442c91f557fc90069ce6efc4d346ab51'"
30      - "result.state == 'file'"
31
32- name: insert a line at the beginning of the file, and back it up
33  lineinfile:
34    dest: "{{ output_dir }}/test.txt"
35    state: present
36    line: "New line at the beginning"
37    insertbefore: "BOF"
38    backup: yes
39  register: result1
40
41- name: insert a line at the beginning of the file again
42  lineinfile:
43    dest: "{{ output_dir }}/test.txt"
44    state: present
45    line: "New line at the beginning"
46    insertbefore: "BOF"
47  register: result2
48
49- name: assert that the line was inserted at the head of the file
50  assert:
51    that:
52      - result1 is changed
53      - result2 is not changed
54      - result1.msg == 'line added'
55      - result1.backup != ''
56
57- name: stat the backup file
58  stat:
59    path: "{{ result1.backup }}"
60  register: result
61
62- name: assert the backup file matches the previous hash
63  assert:
64    that:
65      - "result.stat.checksum == '5feac65e442c91f557fc90069ce6efc4d346ab51'"
66
67- name: stat the test after the insert at the head
68  stat:
69    path: "{{ output_dir }}/test.txt"
70  register: result
71
72- name: assert test hash is what we expect for the file with the insert at the head
73  assert:
74    that:
75      - "result.stat.checksum == '7eade4042b23b800958fe807b5bfc29f8541ec09'"
76
77- name: insert a line at the end of the file
78  lineinfile:
79    dest: "{{ output_dir }}/test.txt"
80    state: present
81    line: "New line at the end"
82    insertafter: "EOF"
83  register: result
84
85- name: assert that the line was inserted at the end of the file
86  assert:
87    that:
88      - result is changed
89      - "result.msg == 'line added'"
90
91- name: stat the test after the insert at the end
92  stat:
93    path: "{{ output_dir }}/test.txt"
94  register: result
95
96- name: assert test checksum matches after the insert at the end
97  assert:
98    that:
99      - "result.stat.checksum == 'fb57af7dc10a1006061b000f1f04c38e4bef50a9'"
100
101- name: insert a line after the first line
102  lineinfile:
103    dest: "{{ output_dir }}/test.txt"
104    state: present
105    line: "New line after line 1"
106    insertafter: "^This is line 1$"
107  register: result
108
109- name: assert that the line was inserted after the first line
110  assert:
111    that:
112      - result is changed
113      - "result.msg == 'line added'"
114
115- name: stat the test after insert after the first line
116  stat:
117    path: "{{ output_dir }}/test.txt"
118  register: result
119
120- name: assert test checksum matches after the insert after the first line
121  assert:
122    that:
123      - "result.stat.checksum == '5348da605b1bc93dbadf3a16474cdf22ef975bec'"
124
125- name: insert a line before the last line
126  lineinfile:
127    dest: "{{ output_dir }}/test.txt"
128    state: present
129    line: "New line before line 5"
130    insertbefore: "^This is line 5$"
131  register: result
132
133- name: assert that the line was inserted before the last line
134  assert:
135    that:
136      - result is changed
137      - "result.msg == 'line added'"
138
139- name: stat the test after the insert before the last line
140  stat:
141    path: "{{ output_dir }}/test.txt"
142  register: result
143
144- name: assert test checksum matches after the insert before the last line
145  assert:
146    that:
147      - "result.stat.checksum == '2e9e460ff68929e4453eb765761fd99814f6e286'"
148
149- name: Replace a line with backrefs
150  lineinfile:
151    dest: "{{ output_dir }}/test.txt"
152    state: present
153    line: "This is line 3"
154    backrefs: yes
155    regexp: "^(REF) .* \\1$"
156  register: backrefs_result1
157
158- name: Replace a line with backrefs again
159  lineinfile:
160    dest: "{{ output_dir }}/test.txt"
161    state: present
162    line: "This is line 3"
163    backrefs: yes
164    regexp: "^(REF) .* \\1$"
165  register: backrefs_result2
166- command: cat {{ output_dir }}/test.txt
167
168- name: assert that the line with backrefs was changed
169  assert:
170    that:
171      - backrefs_result1 is changed
172      - backrefs_result2 is not changed
173      - "backrefs_result1.msg == 'line replaced'"
174
175- name: stat the test after the backref line was replaced
176  stat:
177    path: "{{ output_dir }}/test.txt"
178  register: result
179
180- name: assert test checksum matches after backref line was replaced
181  assert:
182    that:
183      - "result.stat.checksum == '72f60239a735ae06e769d823f5c2b4232c634d9c'"
184
185- name: remove the middle line
186  lineinfile:
187    dest: "{{ output_dir }}/test.txt"
188    state: absent
189    regexp: "^This is line 3$"
190  register: result
191
192- name: assert that the line was removed
193  assert:
194    that:
195      - result is changed
196      - "result.msg == '1 line(s) removed'"
197
198- name: stat the test after the middle line was removed
199  stat:
200    path: "{{ output_dir }}/test.txt"
201  register: result
202
203- name: assert test checksum matches after the middle line was removed
204  assert:
205    that:
206      - "result.stat.checksum == 'd4eeb07bdebab2d1cdb3ec4a3635afa2618ad4ea'"
207
208- name: run a validation script that succeeds
209  lineinfile:
210    dest: "{{ output_dir }}/test.txt"
211    state: absent
212    regexp: "^This is line 5$"
213    validate: "true %s"
214  register: result
215
216- name: assert that the file validated after removing a line
217  assert:
218    that:
219      - result is changed
220      - "result.msg == '1 line(s) removed'"
221
222- name: stat the test after the validation succeeded
223  stat:
224    path: "{{ output_dir }}/test.txt"
225  register: result
226
227- name: assert test checksum matches after the validation succeeded
228  assert:
229    that:
230      - "result.stat.checksum == 'ab56c210ea82839a54487464800fed4878cb2608'"
231
232- name: run a validation script that fails
233  lineinfile:
234    dest: "{{ output_dir }}/test.txt"
235    state: absent
236    regexp: "^This is line 1$"
237    validate: "/bin/false %s"
238  register: result
239  ignore_errors: yes
240
241- name: assert that the validate failed
242  assert:
243    that:
244      - "result.failed == true"
245
246- name: stat the test after the validation failed
247  stat:
248    path: "{{ output_dir }}/test.txt"
249  register: result
250
251- name: assert test checksum matches the previous after the validation failed
252  assert:
253    that:
254      - "result.stat.checksum == 'ab56c210ea82839a54487464800fed4878cb2608'"
255
256- name: use create=yes
257  lineinfile:
258    dest: "{{ output_dir }}/new_test.txt"
259    create: yes
260    insertbefore: BOF
261    state: present
262    line: "This is a new file"
263  register: result
264
265- name: assert that the new file was created
266  assert:
267    that:
268      - result is changed
269      - "result.msg == 'line added'"
270
271- name: validate that the newly created file exists
272  stat:
273    path: "{{ output_dir }}/new_test.txt"
274  register: result
275  ignore_errors: yes
276
277- name: assert the newly created test checksum matches
278  assert:
279    that:
280      - "result.stat.checksum == '038f10f9e31202451b093163e81e06fbac0c6f3a'"
281
282- name: Create a file without a path
283  lineinfile:
284    dest: file.txt
285    create: yes
286    line: Test line
287  register: create_no_path_test
288
289- name: Stat the file
290  stat:
291    path: file.txt
292  register: create_no_path_file
293
294- name: Ensure file was created
295  assert:
296    that:
297      - create_no_path_test is changed
298      - create_no_path_file.stat.exists
299
300# Test EOF in cases where file has no newline at EOF
301- name: testnoeof deploy the file for lineinfile
302  copy:
303    src: testnoeof.txt
304    dest: "{{ output_dir }}/testnoeof.txt"
305  register: result
306
307- name: testnoeof insert a line at the end of the file
308  lineinfile:
309    dest: "{{ output_dir }}/testnoeof.txt"
310    state: present
311    line: "New line at the end"
312    insertafter: "EOF"
313  register: result
314
315- name: testempty assert that the line was inserted at the end of the file
316  assert:
317    that:
318      - result is changed
319      - "result.msg == 'line added'"
320
321- name: insert a multiple lines at the end of the file
322  lineinfile:
323    dest: "{{ output_dir }}/test.txt"
324    state: present
325    line: "This is a line\nwith \\n character"
326    insertafter: "EOF"
327  register: result
328
329- name: assert that the multiple lines was inserted
330  assert:
331    that:
332      - result is changed
333      - "result.msg == 'line added'"
334
335- name: testnoeof stat the no newline EOF test after the insert at the end
336  stat:
337    path: "{{ output_dir }}/testnoeof.txt"
338  register: result
339
340- name: testnoeof assert test checksum matches after the insert at the end
341  assert:
342    that:
343      - "result.stat.checksum == 'f9af7008e3cb67575ce653d094c79cabebf6e523'"
344
345# Test EOF with empty file to make sure no unnecessary newline is added
346- name: testempty deploy the testempty file for lineinfile
347  copy:
348    src: testempty.txt
349    dest: "{{ output_dir }}/testempty.txt"
350  register: result
351
352- name: testempty insert a line at the end of the file
353  lineinfile:
354    dest: "{{ output_dir }}/testempty.txt"
355    state: present
356    line: "New line at the end"
357    insertafter: "EOF"
358  register: result
359
360- name: testempty assert that the line was inserted at the end of the file
361  assert:
362    that:
363      - result is changed
364      - "result.msg == 'line added'"
365
366- name: testempty stat the test after the insert at the end
367  stat:
368    path: "{{ output_dir }}/testempty.txt"
369  register: result
370
371- name: testempty assert test checksum matches after the insert at the end
372  assert:
373    that:
374      - "result.stat.checksum == 'f440dc65ea9cec3fd496c1479ddf937e1b949412'"
375
376- stat:
377    path: "{{ output_dir }}/test.txt"
378  register: result
379
380- name: assert test checksum matches after inserting multiple lines
381  assert:
382    that:
383      - "result.stat.checksum == 'fde683229429a4f05d670e6c10afc875e1d5c489'"
384
385- name: replace a line with backrefs included in the line
386  lineinfile:
387    dest: "{{ output_dir }}/test.txt"
388    state: present
389    line: "New \\1 created with the backref"
390    backrefs: yes
391    regexp: "^This is (line 4)$"
392  register: result
393
394- name: assert that the line with backrefs was changed
395  assert:
396    that:
397      - result is changed
398      - "result.msg == 'line replaced'"
399
400- name: stat the test after the backref line was replaced
401  stat:
402    path: "{{ output_dir }}/test.txt"
403  register: result
404
405- name: assert test checksum matches after backref line was replaced
406  assert:
407    that:
408      - "result.stat.checksum == '981ad35c4b30b03bc3a1beedce0d1e72c491898e'"
409
410###################################################################
411# issue 8535
412
413- name: create a new file for testing quoting issues
414  file:
415    dest: "{{ output_dir }}/test_quoting.txt"
416    state: touch
417  register: result
418
419- name: assert the new file was created
420  assert:
421    that:
422    - result is changed
423
424- name: use with_items to add code-like strings to the quoting txt file
425  lineinfile:
426    dest: "{{ output_dir }}/test_quoting.txt"
427    line: "{{ item }}"
428    insertbefore: BOF
429  with_items:
430    - "'foo'"
431    - "dotenv.load();"
432    - "var dotenv = require('dotenv');"
433  register: result
434
435- name: assert the quote test file was modified correctly
436  assert:
437    that:
438      - result.results|length == 3
439      - result.results[0] is changed
440      - result.results[0].item == "'foo'"
441      - result.results[1] is changed
442      - result.results[1].item == "dotenv.load();"
443      - result.results[2] is changed
444      - result.results[2].item == "var dotenv = require('dotenv');"
445
446- name: stat the quote test file
447  stat:
448    path: "{{ output_dir }}/test_quoting.txt"
449  register: result
450
451- name: assert test checksum matches after backref line was replaced
452  assert:
453    that:
454    - "result.stat.checksum == '7dc3cb033c3971e73af0eaed6623d4e71e5743f1'"
455
456- name: insert a line into the quoted file with a single quote
457  lineinfile:
458    dest: "{{ output_dir }}/test_quoting.txt"
459    line: "import g'"
460  register: result
461
462- name: assert that the quoted file was changed
463  assert:
464    that:
465    - result is changed
466
467- name: stat the quote test file
468  stat:
469    path: "{{ output_dir }}/test_quoting.txt"
470  register: result
471
472- name: assert test checksum matches after backref line was replaced
473  assert:
474    that:
475    - "result.stat.checksum == '73b271c2cc1cef5663713bc0f00444b4bf9f4543'"
476
477- name: insert a line into the quoted file with many double quotation strings
478  lineinfile:
479    dest: "{{ output_dir }}/test_quoting.txt"
480    line: "\"quote\" and \"unquote\""
481  register: result
482
483- name: assert that the quoted file was changed
484  assert:
485    that:
486    - result is changed
487
488- name: stat the quote test file
489  stat:
490    path: "{{ output_dir }}/test_quoting.txt"
491  register: result
492
493- name: assert test checksum matches after backref line was replaced
494  assert:
495    that:
496    - "result.stat.checksum == 'b10ab2a3c3b6492680c8d0b1d6f35aa6b8f9e731'"
497
498###################################################################
499# Issue 28721
500
501- name: Deploy the testmultiple file
502  copy:
503    src: testmultiple.txt
504    dest: "{{ output_dir }}/testmultiple.txt"
505  register: result
506
507- name: Assert that the testmultiple file was deployed
508  assert:
509    that:
510      - result is changed
511      - result.checksum == '3e0090a34fb641f3c01e9011546ff586260ea0ea'
512      - result.state == 'file'
513
514# Test insertafter
515- name: Write the same line to a file inserted after different lines
516  lineinfile:
517    path: "{{ output_dir }}/testmultiple.txt"
518    insertafter: "{{ item.regex }}"
519    line: "{{ item.replace }}"
520  register: _multitest_1
521  with_items: "{{ test_regexp }}"
522
523- name: Assert that the line is added once only
524  assert:
525    that:
526      - _multitest_1.results.0 is changed
527      - _multitest_1.results.1 is not changed
528      - _multitest_1.results.2 is not changed
529      - _multitest_1.results.3 is not changed
530
531- name: Do the same thing again to check for changes
532  lineinfile:
533    path: "{{ output_dir }}/testmultiple.txt"
534    insertafter: "{{ item.regex }}"
535    line: "{{ item.replace }}"
536  register: _multitest_2
537  with_items: "{{ test_regexp }}"
538
539- name: Assert that the line is not added anymore
540  assert:
541    that:
542      - _multitest_2.results.0 is not changed
543      - _multitest_2.results.1 is not changed
544      - _multitest_2.results.2 is not changed
545      - _multitest_2.results.3 is not changed
546
547- name: Stat the insertafter file
548  stat:
549    path: "{{ output_dir }}/testmultiple.txt"
550  register: result
551
552- name: Assert that the insertafter file matches expected checksum
553  assert:
554    that:
555      - result.stat.checksum == 'c6733b6c53ddd0e11e6ba39daa556ef8f4840761'
556
557# Test insertbefore
558
559- name: Deploy the testmultiple file
560  copy:
561    src: testmultiple.txt
562    dest: "{{ output_dir }}/testmultiple.txt"
563  register: result
564
565- name: Assert that the testmultiple file was deployed
566  assert:
567    that:
568      - result is changed
569      - result.checksum == '3e0090a34fb641f3c01e9011546ff586260ea0ea'
570      - result.state == 'file'
571
572- name: Write the same line to a file inserted before different lines
573  lineinfile:
574    path: "{{ output_dir }}/testmultiple.txt"
575    insertbefore: "{{ item.regex }}"
576    line: "{{ item.replace }}"
577  register: _multitest_3
578  with_items: "{{ test_regexp }}"
579
580- name: Assert that the line is added once only
581  assert:
582    that:
583      - _multitest_3.results.0 is changed
584      - _multitest_3.results.1 is not changed
585      - _multitest_3.results.2 is not changed
586      - _multitest_3.results.3 is not changed
587
588- name: Do the same thing again to check for changes
589  lineinfile:
590    path: "{{ output_dir }}/testmultiple.txt"
591    insertbefore: "{{ item.regex }}"
592    line: "{{ item.replace }}"
593  register: _multitest_4
594  with_items: "{{ test_regexp }}"
595
596- name: Assert that the line is not added anymore
597  assert:
598    that:
599      - _multitest_4.results.0 is not changed
600      - _multitest_4.results.1 is not changed
601      - _multitest_4.results.2 is not changed
602      - _multitest_4.results.3 is not changed
603
604- name: Stat the insertbefore file
605  stat:
606    path: "{{ output_dir }}/testmultiple.txt"
607  register: result
608
609- name: Assert that the insertbefore file matches expected checksum
610  assert:
611    that:
612      - result.stat.checksum == '5d298651fbc377b45257da10308a9dc2fe1f8be5'
613
614###################################################################
615# Issue 36156
616# Test insertbefore and insertafter with regexp
617
618- name: Deploy the test.conf file
619  copy:
620    src: test.conf
621    dest: "{{ output_dir }}/test.conf"
622  register: result
623
624- name: Assert that the test.conf file was deployed
625  assert:
626    that:
627      - result is changed
628      - result.checksum == '6037f13e419b132eb3fd20a89e60c6c87a6add38'
629      - result.state == 'file'
630
631# Test instertafter
632- name: Insert lines after with regexp
633  lineinfile:
634    path: "{{ output_dir }}/test.conf"
635    regexp: "{{ item.regexp }}"
636    line: "{{ item.line }}"
637    insertafter: "{{ item.after }}"
638  with_items: "{{ test_befaf_regexp }}"
639  register: _multitest_5
640
641- name: Do the same thing again and check for changes
642  lineinfile:
643    path: "{{ output_dir }}/test.conf"
644    regexp: "{{ item.regexp }}"
645    line: "{{ item.line }}"
646    insertafter: "{{ item.after }}"
647  with_items: "{{ test_befaf_regexp }}"
648  register: _multitest_6
649
650- name: Assert that the file was changed the first time but not the second time
651  assert:
652    that:
653      - item.0 is changed
654      - item.1 is not changed
655  with_together:
656    - "{{ _multitest_5.results }}"
657    - "{{ _multitest_6.results }}"
658
659- name: Stat the file
660  stat:
661    path: "{{ output_dir }}/test.conf"
662  register: result
663
664- name: Assert that the file contents match what is expected
665  assert:
666    that:
667      - result.stat.checksum == '06e2c456e5028dd7bcd0b117b5927a1139458c82'
668
669- name: Do the same thing a third time without regexp and check for changes
670  lineinfile:
671    path: "{{ output_dir }}/test.conf"
672    line: "{{ item.line }}"
673    insertafter: "{{ item.after }}"
674  with_items: "{{ test_befaf_regexp }}"
675  register: _multitest_7
676
677- name: Stat the file
678  stat:
679    path: "{{ output_dir }}/test.conf"
680  register: result
681
682- name: Assert that the file was changed when no regexp was provided
683  assert:
684    that:
685      - item is not changed
686  with_items: "{{ _multitest_7.results }}"
687
688- name: Stat the file
689  stat:
690    path: "{{ output_dir }}/test.conf"
691  register: result
692
693- name: Assert that the file contents match what is expected
694  assert:
695    that:
696      - result.stat.checksum == '06e2c456e5028dd7bcd0b117b5927a1139458c82'
697
698# Test insertbefore
699- name: Deploy the test.conf file
700  copy:
701    src: test.conf
702    dest: "{{ output_dir }}/test.conf"
703  register: result
704
705- name: Assert that the test.conf file was deployed
706  assert:
707    that:
708      - result is changed
709      - result.checksum == '6037f13e419b132eb3fd20a89e60c6c87a6add38'
710      - result.state == 'file'
711
712- name: Insert lines before with regexp
713  lineinfile:
714    path: "{{ output_dir }}/test.conf"
715    regexp: "{{ item.regexp }}"
716    line: "{{ item.line }}"
717    insertbefore: "{{ item.before }}"
718  with_items: "{{ test_befaf_regexp }}"
719  register: _multitest_8
720
721- name: Do the same thing again and check for changes
722  lineinfile:
723    path: "{{ output_dir }}/test.conf"
724    regexp: "{{ item.regexp }}"
725    line: "{{ item.line }}"
726    insertbefore: "{{ item.before }}"
727  with_items: "{{ test_befaf_regexp }}"
728  register: _multitest_9
729
730- name: Assert that the file was changed the first time but not the second time
731  assert:
732    that:
733      - item.0 is changed
734      - item.1 is not changed
735  with_together:
736    - "{{ _multitest_8.results }}"
737    - "{{ _multitest_9.results }}"
738
739- name: Stat the file
740  stat:
741    path: "{{ output_dir }}/test.conf"
742  register: result
743
744- name: Assert that the file contents match what is expected
745  assert:
746    that:
747      - result.stat.checksum == 'c3be9438a07c44d4c256cebfcdbca15a15b1db91'
748
749- name: Do the same thing a third time without regexp and check for changes
750  lineinfile:
751    path: "{{ output_dir }}/test.conf"
752    line: "{{ item.line }}"
753    insertbefore: "{{ item.before }}"
754  with_items: "{{ test_befaf_regexp }}"
755  register: _multitest_10
756
757- name: Stat the file
758  stat:
759    path: "{{ output_dir }}/test.conf"
760  register: result
761
762- name: Assert that the file was changed when no regexp was provided
763  assert:
764    that:
765      - item is not changed
766  with_items: "{{ _multitest_10.results }}"
767
768- name: Stat the file
769  stat:
770    path: "{{ output_dir }}/test.conf"
771  register: result
772
773- name: Assert that the file contents match what is expected
774  assert:
775    that:
776      - result.stat.checksum == 'c3be9438a07c44d4c256cebfcdbca15a15b1db91'
777
778- name: Copy empty file to test with insertbefore
779  copy:
780    src: testempty.txt
781    dest: "{{ output_dir }}/testempty.txt"
782
783- name: Add a line to empty file with insertbefore
784  lineinfile:
785    path: "{{ output_dir }}/testempty.txt"
786    line: top
787    insertbefore: '^not in the file$'
788  register: oneline_insbefore_test1
789
790- name: Add a line to file with only one line using insertbefore
791  lineinfile:
792    path: "{{ output_dir }}/testempty.txt"
793    line: top
794    insertbefore: '^not in the file$'
795  register: oneline_insbefore_test2
796
797- name: Stat the file
798  stat:
799    path:  "{{ output_dir }}/testempty.txt"
800  register: oneline_insbefore_file
801
802- name: Assert that insertebefore worked properly with a one line file
803  assert:
804    that:
805      - oneline_insbefore_test1 is changed
806      - oneline_insbefore_test2 is not changed
807      - oneline_insbefore_file.stat.checksum == '4dca56d05a21f0d018cd311f43e134e4501cf6d9'
808
809###################################################################
810# Issue 29443
811# When using an empty regexp, replace the last line (since it matches every line)
812# but also provide a warning.
813
814- name: Deploy the test file for lineinfile
815  copy:
816    src: test.txt
817    dest: "{{ output_dir }}/test.txt"
818  register: result
819
820- name: Assert that the test file was deployed
821  assert:
822    that:
823      - result is changed
824      - result.checksum == '5feac65e442c91f557fc90069ce6efc4d346ab51'
825      - result.state == 'file'
826
827- name: Insert a line in the file using an empty string as a regular expression
828  lineinfile:
829    path: "{{ output_dir }}/test.txt"
830    regexp: ''
831    line: This is line 6
832  register: insert_empty_regexp
833
834- name: Stat the file
835  stat:
836    path: "{{ output_dir }}/test.txt"
837  register: result
838
839- name: Assert that the file contents match what is expected and a warning was displayed
840  assert:
841    that:
842      - insert_empty_regexp is changed
843      - warning_message in insert_empty_regexp.warnings
844      - result.stat.checksum == '23555a98ceaa88756b4c7c7bba49d9f86eed868f'
845  vars:
846    warning_message: >-
847      The regular expression is an empty string, which will match every line in the file.
848      This may have unintended consequences, such as replacing the last line in the file rather than appending.
849      If this is desired, use '^' to match every line in the file and avoid this warning.
850
851###################################################################
852## Issue #58923
853## Using firstmatch with insertafter and ensure multiple lines are not inserted
854
855- name: Deploy the firstmatch test file
856  copy:
857    src: firstmatch.txt
858    dest: "{{ output_dir }}/firstmatch.txt"
859  register: result
860
861- name: Assert that the test file was deployed
862  assert:
863    that:
864      - result is changed
865      - result.checksum == '1d644e5e2e51c67f1bd12d7bbe2686017f39923d'
866      - result.state == 'file'
867
868- name: Insert a line before an existing line using firstmatch
869  lineinfile:
870    path: "{{ output_dir }}/firstmatch.txt"
871    line: INSERT
872    insertafter: line1
873    firstmatch: yes
874  register: insertafter1
875
876- name: Insert a line before an existing line using firstmatch again
877  lineinfile:
878    path: "{{ output_dir }}/firstmatch.txt"
879    line: INSERT
880    insertafter: line1
881    firstmatch: yes
882  register: insertafter2
883
884- name: Stat the file
885  stat:
886    path: "{{ output_dir }}/firstmatch.txt"
887  register: result
888
889- name: Assert that the file was modified appropriately
890  assert:
891    that:
892      - insertafter1 is changed
893      - insertafter2 is not changed
894      - result.stat.checksum == '114aae024073a3ee8ec8db0ada03c5483326dd86'
895
896########################################################################################
897# Tests of fixing the same issue as above (#58923) by @Andersson007 <aaklychkov@mail.ru>
898# and @samdoran <sdoran@redhat.com>:
899
900# Test insertafter with regexp
901- name: Deploy the test file
902  copy:
903    src: test_58923.txt
904    dest: "{{ output_dir }}/test_58923.txt"
905  register: initial_file
906
907- name: Assert that the test file was deployed
908  assert:
909    that:
910      - initial_file is changed
911      - initial_file.checksum == 'b6379ba43261c451a62102acb2c7f438a177c66e'
912      - initial_file.state == 'file'
913
914# Regarding the documentation:
915# If regular expressions are passed to both regexp and
916# insertafter, insertafter is only honored if no match for regexp is found.
917# Therefore,
918# when regular expressions are passed to both regexp and insertafter, then:
919# 1. regexp was found -> ignore insertafter, replace the founded line
920# 2. regexp was not found -> insert the line after 'insertafter' line
921
922# Regexp is not present in the file, so the line must be inserted after ^#!/bin/sh
923- name: Add the line using firstmatch, regexp, and insertafter
924  lineinfile:
925    path: "{{ output_dir }}/test_58923.txt"
926    insertafter: '^#!/bin/sh'
927    regexp: ^export FISHEYE_OPTS
928    firstmatch: true
929    line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m"
930  register: insertafter_test1
931
932- name: Stat the file
933  stat:
934    path: "{{ output_dir }}/test_58923.txt"
935  register: insertafter_test1_file
936
937- name: Add the line using firstmatch, regexp, and insertafter again
938  lineinfile:
939    path: "{{ output_dir }}/test_58923.txt"
940    insertafter: '^#!/bin/sh'
941    regexp: ^export FISHEYE_OPTS
942    firstmatch: true
943    line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m"
944  register: insertafter_test2
945
946# Check of the prev step.
947# We tried to add the same line with the same playbook,
948# so nothing has been added:
949- name: Stat the file again
950  stat:
951    path: "{{ output_dir }}/test_58923.txt"
952  register: insertafter_test2_file
953
954- name: Assert insertafter tests gave the expected results
955  assert:
956    that:
957      - insertafter_test1 is changed
958      - insertafter_test1_file.stat.checksum == '9232aed6fe88714964d9e29d13e42cd782070b08'
959      - insertafter_test2 is not changed
960      - insertafter_test2_file.stat.checksum == '9232aed6fe88714964d9e29d13e42cd782070b08'
961
962# Test insertafter without regexp
963- name: Deploy the test file
964  copy:
965    src: test_58923.txt
966    dest: "{{ output_dir }}/test_58923.txt"
967  register: initial_file
968
969- name: Assert that the test file was deployed
970  assert:
971    that:
972      - initial_file is changed
973      - initial_file.checksum == 'b6379ba43261c451a62102acb2c7f438a177c66e'
974      - initial_file.state == 'file'
975
976- name: Insert the line using firstmatch and insertafter without regexp
977  lineinfile:
978    path: "{{ output_dir }}/test_58923.txt"
979    insertafter: '^#!/bin/sh'
980    firstmatch: true
981    line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m"
982  register: insertafter_test3
983
984- name: Stat the file
985  stat:
986    path: "{{ output_dir }}/test_58923.txt"
987  register: insertafter_test3_file
988
989- name: Insert the line using firstmatch and insertafter without regexp again
990  lineinfile:
991    path: "{{ output_dir }}/test_58923.txt"
992    insertafter: '^#!/bin/sh'
993    firstmatch: true
994    line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m"
995  register: insertafter_test4
996
997- name: Stat the file again
998  stat:
999    path: "{{ output_dir }}/test_58923.txt"
1000  register: insertafter_test4_file
1001
1002- name: Assert insertafter without regexp tests gave the expected results
1003  assert:
1004    that:
1005      - insertafter_test3 is changed
1006      - insertafter_test3_file.stat.checksum == '9232aed6fe88714964d9e29d13e42cd782070b08'
1007      - insertafter_test4 is not changed
1008      - insertafter_test4_file.stat.checksum == '9232aed6fe88714964d9e29d13e42cd782070b08'
1009
1010
1011# Test insertbefore with regexp
1012- name: Deploy the test file
1013  copy:
1014    src: test_58923.txt
1015    dest: "{{ output_dir }}/test_58923.txt"
1016  register: initial_file
1017
1018- name: Assert that the test file was deployed
1019  assert:
1020    that:
1021      - initial_file is changed
1022      - initial_file.checksum == 'b6379ba43261c451a62102acb2c7f438a177c66e'
1023      - initial_file.state == 'file'
1024
1025- name: Add the line using regexp, firstmatch, and insertbefore
1026  lineinfile:
1027    path: "{{ output_dir }}/test_58923.txt"
1028    insertbefore: '^#!/bin/sh'
1029    regexp: ^export FISHEYE_OPTS
1030    firstmatch: true
1031    line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m"
1032  register: insertbefore_test1
1033
1034- name: Stat the file
1035  stat:
1036    path: "{{ output_dir }}/test_58923.txt"
1037  register: insertbefore_test1_file
1038
1039- name: Add the line using regexp, firstmatch, and insertbefore again
1040  lineinfile:
1041    path: "{{ output_dir }}/test_58923.txt"
1042    insertbefore: '^#!/bin/sh'
1043    regexp: ^export FISHEYE_OPTS
1044    firstmatch: true
1045    line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m"
1046  register: insertbefore_test2
1047
1048- name: Stat the file again
1049  stat:
1050    path: "{{ output_dir }}/test_58923.txt"
1051  register: insertbefore_test2_file
1052
1053- name: Assert insertbefore with regexp tests gave the expected results
1054  assert:
1055    that:
1056      - insertbefore_test1 is changed
1057      - insertbefore_test1_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7'
1058      - insertbefore_test2 is not changed
1059      - insertbefore_test2_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7'
1060
1061
1062# Test insertbefore without regexp
1063- name: Deploy the test file
1064  copy:
1065    src: test_58923.txt
1066    dest: "{{ output_dir }}/test_58923.txt"
1067  register: initial_file
1068
1069- name: Assert that the test file was deployed
1070  assert:
1071    that:
1072      - initial_file is changed
1073      - initial_file.checksum == 'b6379ba43261c451a62102acb2c7f438a177c66e'
1074      - initial_file.state == 'file'
1075
1076- name: Add the line using insertbefore and firstmatch
1077  lineinfile:
1078    path: "{{ output_dir }}/test_58923.txt"
1079    insertbefore: '^#!/bin/sh'
1080    firstmatch: true
1081    line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m"
1082  register: insertbefore_test3
1083
1084- name: Stat the file
1085  stat:
1086    path: "{{ output_dir }}/test_58923.txt"
1087  register: insertbefore_test3_file
1088
1089- name: Add the line using insertbefore and firstmatch again
1090  lineinfile:
1091    path: "{{ output_dir }}/test_58923.txt"
1092    insertbefore: '^#!/bin/sh'
1093    firstmatch: true
1094    line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m"
1095  register: insertbefore_test4
1096
1097- name: Stat the file again
1098  stat:
1099    path: "{{ output_dir }}/test_58923.txt"
1100  register: insertbefore_test4_file
1101
1102# Test when the line is presented in the file but
1103# not in the before/after spot and it does match the regexp:
1104- name: >
1105    Add the line using insertbefore and firstmatch when the regexp line
1106    is presented but not close to insertbefore spot
1107  lineinfile:
1108    path: "{{ output_dir }}/test_58923.txt"
1109    insertbefore: '   Darwin\*\) if \[ -z \"\$JAVA_HOME\" \] ; then'
1110    firstmatch: true
1111    line: export FISHEYE_OPTS="-Xmx4096m -Xms2048m"
1112  register: insertbefore_test5
1113
1114- name: Stat the file again
1115  stat:
1116    path: "{{ output_dir }}/test_58923.txt"
1117  register: insertbefore_test5_file
1118
1119- name: Assert insertbefore with regexp tests gave the expected results
1120  assert:
1121    that:
1122      - insertbefore_test3 is changed
1123      - insertbefore_test3_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7'
1124      - insertbefore_test4 is not changed
1125      - insertbefore_test4_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7'
1126      - insertbefore_test5 is not changed
1127      - insertbefore_test5_file.stat.checksum == '3c6630b9d44f561ea9ad999be56a7504cadc12f7'
1128
1129
1130# Test inserting a line at the end of the file using regexp with insertafter
1131# https://github.com/ansible/ansible/issues/63684
1132- name: Create a file by inserting a line
1133  lineinfile:
1134    path: "{{ output_dir }}/testend.txt"
1135    create: yes
1136    line: testline
1137  register: testend1
1138
1139- name: Insert a line at the end of the file
1140  lineinfile:
1141    path: "{{ output_dir }}/testend.txt"
1142    insertafter: testline
1143    regexp: line at the end
1144    line: line at the end
1145  register: testend2
1146
1147- name: Stat the file
1148  stat:
1149    path: "{{ output_dir }}/testend.txt"
1150  register: testend_file
1151
1152- name: Assert inserting at the end gave the expected results.
1153  assert:
1154    that:
1155      - testend1 is changed
1156      - testend2 is changed
1157      - testend_file.stat.checksum == 'ef36116966836ce04f6b249fd1837706acae4e19'
1158