1# Test code for the win_lineinfile module, adapted from the standard lineinfile module tests
2#
3# This file is part of Ansible
4#
5# Ansible is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# Ansible is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17
18
19- name: deploy the test file for lineinfile
20  win_copy: src=test.txt dest={{win_output_dir}}/test.txt
21  register: result
22
23- name: assert that the test file was deployed
24  assert:
25    that:
26    - "result.changed == true"
27
28- name: stat the test file
29  win_stat: path={{win_output_dir}}/test.txt
30  register: result
31
32- name: check win_stat file result
33  assert:
34    that:
35      - "result.stat.exists"
36      - "not result.stat.isdir"
37      - "result.stat.checksum == '5feac65e442c91f557fc90069ce6efc4d346ab51'"
38      - "result is not failed"
39      - "result is not changed"
40
41
42- name: insert a line at the beginning of the file, and back it up
43  win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="New line at the beginning" insertbefore="BOF" backup=yes
44  register: result
45
46- name: check backup_file
47  win_stat:
48    path: '{{ result.backup_file }}'
49  register: backup_file
50
51- name: assert that the line was inserted at the head of the file
52  assert:
53    that:
54    - result.changed == true
55    - result.msg == 'line added'
56    - backup_file.stat.exists == true
57
58- name: stat the backup file
59  win_stat: path={{result.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  win_stat: path={{win_output_dir}}/test.txt
69  register: result
70
71- name: assert test hash is what we expect for the file with the insert at the head
72  assert:
73    that:
74    - "result.stat.checksum == 'b526e2e044defc64dfb0fad2f56e105178f317d8'"
75
76- name: insert a line at the end of the file
77  win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="New line at the end" insertafter="EOF"
78  register: result
79
80- name: assert that the line was inserted at the end of the file
81  assert:
82    that:
83    - "result.changed == true"
84    - "result.msg == 'line added'"
85
86- name: stat the test after the insert at the end
87  win_stat: path={{win_output_dir}}/test.txt
88  register: result
89
90- name: assert test checksum matches after the insert at the end
91  assert:
92    that:
93    - "result.stat.checksum == 'dd5e207e28ce694ab18e41c2b16deb74fde93b14'"
94
95- name: insert a line after the first line
96  win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="New line after line 1" insertafter="^This is line 1$"
97  register: result
98
99- name: assert that the line was inserted after the first line
100  assert:
101    that:
102    - "result.changed == true"
103    - "result.msg == 'line added'"
104
105- name: stat the test after insert after the first line
106  win_stat: path={{win_output_dir}}/test.txt
107  register: result
108
109- name: assert test checksum matches after the insert after the first line
110  assert:
111    that:
112    - "result.stat.checksum == '604b17405f2088e6868af9680b7834087acdc8f4'"
113
114- name: insert a line before the last line
115  win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="New line before line 5" insertbefore="^This is line 5$"
116  register: result
117
118- name: assert that the line was inserted before the last line
119  assert:
120    that:
121    - "result.changed == true"
122    - "result.msg == 'line added'"
123
124- name: stat the test after the insert before the last line
125  win_stat: path={{win_output_dir}}/test.txt
126  register: result
127
128- name: assert test checksum matches after the insert before the last line
129  assert:
130    that:
131    - "result.stat.checksum == '8f5b30e8f01578043d782e5a68d4c327e75a6e34'"
132
133- name: replace a line with backrefs
134  win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="This is line 3" backrefs=yes regexp="^(REF).*$"
135  register: result
136
137- name: assert that the line with backrefs was changed
138  assert:
139    that:
140    - "result.changed == true"
141    - "result.msg == 'line replaced'"
142
143- name: stat the test after the backref line was replaced
144  win_stat: path={{win_output_dir}}/test.txt
145  register: result
146
147- name: assert test checksum matches after backref line was replaced
148  assert:
149    that:
150    - "result.stat.checksum == 'ef6b02645908511a2cfd2df29d50dd008897c580'"
151
152- name: remove the middle line
153  win_lineinfile: dest={{win_output_dir}}/test.txt state=absent regexp="^This is line 3$"
154  register: result
155
156- name: assert that the line was removed
157  assert:
158    that:
159    - "result.changed == true"
160    - "result.msg == '1 line(s) removed'"
161
162- name: stat the test after the middle line was removed
163  win_stat: path={{win_output_dir}}/test.txt
164  register: result
165
166- name: assert test checksum matches after the middle line was removed
167  assert:
168    that:
169    - "result.stat.checksum == '11695efa472be5c31c736bc43e055f8ac90eabdf'"
170
171- name: run a validation script that succeeds
172  win_lineinfile: dest={{win_output_dir}}/test.txt state=absent regexp="^This is line 5$" validate="sort.exe %s"
173  register: result
174
175- name: assert that the file validated after removing a line
176  assert:
177    that:
178    - "result.changed == true"
179    - "result.msg == '1 line(s) removed'"
180
181- name: stat the test after the validation succeeded
182  win_stat: path={{win_output_dir}}/test.txt
183  register: result
184
185- name: assert test checksum matches after the validation succeeded
186  assert:
187    that:
188    - "result.stat.checksum == '39c38a30aa6ac6af9ec41f54c7ed7683f1249347'"
189
190- name: run a validation script that fails
191  win_lineinfile: dest={{win_output_dir}}/test.txt state=absent regexp="^This is line 1$" validate="sort.exe %s.foo"
192  register: result
193  ignore_errors: yes
194
195- name: assert that the validate failed
196  assert:
197    that:
198    - "result.failed == true"
199
200- name: stat the test after the validation failed
201  win_stat: path={{win_output_dir}}/test.txt
202  register: result
203
204- name: assert test checksum matches the previous after the validation failed
205  assert:
206    that:
207    - "result.stat.checksum == '39c38a30aa6ac6af9ec41f54c7ed7683f1249347'"
208
209- name: use create=yes
210  win_lineinfile: dest={{win_output_dir}}/new_test.txt create=yes insertbefore=BOF state=present line="This is a new file"
211  register: result
212
213- name: assert that the new file was created
214  assert:
215    that:
216    - "result.changed == true"
217    - "result.msg == 'line added'"
218
219- name: validate that the newly created file exists
220  win_stat: path={{win_output_dir}}/new_test.txt
221  register: result
222  ignore_errors: yes
223
224- name: assert the newly created test checksum matches
225  assert:
226    that:
227    - "result.stat.checksum == '84faac1183841c57434693752fc3debc91b9195d'"
228
229# Test EOF in cases where file has no newline at EOF
230- name: testnoeof deploy the file for lineinfile
231  win_copy: src=testnoeof.txt dest={{win_output_dir}}/testnoeof.txt
232  register: result
233
234- name: testnoeof insert a line at the end of the file
235  win_lineinfile: dest={{win_output_dir}}/testnoeof.txt state=present line="New line at the end" insertafter="EOF"
236  register: result
237
238- name: testempty assert that the line was inserted at the end of the file
239  assert:
240    that:
241    - "result.changed == true"
242    - "result.msg == 'line added'"
243
244- name: testnoeof stat the no newline EOF test after the insert at the end
245  win_stat: path={{win_output_dir}}/testnoeof.txt
246  register: result
247
248- name: testnoeof assert test checksum matches after the insert at the end
249  assert:
250    that:
251    - "result.stat.checksum == '229852b09f7e9921fbcbb0ee0166ba78f7f7f261'"
252
253- name: add multiple lines at the end of the file
254  win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="This is a line\r\nwith newline character" insertafter="EOF"
255  register: result
256
257- name: assert that the multiple lines was inserted
258  assert:
259    that:
260    - "result.changed == true"
261    - "result.msg == 'line added'"
262
263- name: stat file after adding multiple lines
264  win_stat: path={{win_output_dir}}/test.txt
265  register: result
266
267- name: assert test checksum matches after inserting multiple lines
268  assert:
269    that:
270    - "result.stat.checksum == '1401413cd4eac732be66cd6aceddd334c4240f86'"
271
272
273
274# Test EOF with empty file to make sure no unnecessary newline is added
275- name: testempty deploy the testempty file for lineinfile
276  win_copy: src=testempty.txt dest={{win_output_dir}}/testempty.txt
277  register: result
278
279- name: testempty insert a line at the end of the file
280  win_lineinfile: dest={{win_output_dir}}/testempty.txt state=present line="New line at the end" insertafter="EOF"
281  register: result
282
283- name: testempty assert that the line was inserted at the end of the file
284  assert:
285    that:
286    - "result.changed == true"
287    - "result.msg == 'line added'"
288
289- name: testempty stat the test after the insert at the end
290  win_stat: path={{win_output_dir}}/testempty.txt
291  register: result
292
293- name: testempty assert test checksum matches after the insert at the end
294  assert:
295    that:
296    - "result.stat.checksum == 'd3d34f11edda51be7ca5dcb0757cf3e1257c0bfe'"
297
298
299
300- name: replace a line with backrefs included in the line
301  win_lineinfile: dest={{win_output_dir}}/test.txt state=present line="New $1 created with the backref" backrefs=yes regexp="^This is (line 4)$"
302  register: result
303
304- name: assert that the line with backrefs was changed
305  assert:
306    that:
307    - "result.changed == true"
308    - "result.msg == 'line replaced'"
309
310- name: stat the test after the backref line was replaced
311  win_stat: path={{win_output_dir}}/test.txt
312  register: result
313
314- name: assert test checksum matches after backref line was replaced
315  assert:
316    that:
317    - "result.stat.checksum == 'e6ff42e926dac2274c93dff0b8a323e07ae09149'"
318
319###################################################################
320# issue 8535
321
322- name: create a new file for testing quoting issues
323  win_copy: src=test_quoting.txt dest={{win_output_dir}}/test_quoting.txt
324  register: result
325
326- name: assert the new file was created
327  assert:
328    that:
329    - result.changed
330
331- name: use with_items to add code-like strings to the quoting txt file
332  win_lineinfile: >
333    dest={{win_output_dir}}/test_quoting.txt
334    line="{{ item }}"
335    insertbefore="BOF"
336  with_items:
337    - "'foo'"
338    - "dotenv.load();"
339    - "var dotenv = require('dotenv');"
340  register: result
341
342- name: assert the quote test file was modified correctly
343  assert:
344    that:
345    - result.results|length == 3
346    - result.results[0].changed
347    - result.results[0].item == "'foo'"
348    - result.results[1].changed
349    - result.results[1].item == "dotenv.load();"
350    - result.results[2].changed
351    - result.results[2].item == "var dotenv = require('dotenv');"
352
353- name: stat the quote test file
354  win_stat: path={{win_output_dir}}/test_quoting.txt
355  register: result
356
357- name: assert test checksum matches for quote test file
358  assert:
359    that:
360    - "result.stat.checksum == 'f3bccdbdfa1d7176c497ef87d04957af40ab48d2'"
361
362- name: append a line into the quoted file with a single quote
363  win_lineinfile: dest={{win_output_dir}}/test_quoting.txt line="import g'"
364  register: result
365
366- name: assert that the quoted file was changed
367  assert:
368    that:
369    - result.changed
370
371- name: stat the quote test file
372  win_stat: path={{win_output_dir}}/test_quoting.txt
373  register: result
374
375- name: assert test checksum matches adding line with single quote
376  assert:
377    that:
378    - "result.stat.checksum == 'dabf4cbe471e1797d8dcfc773b6b638c524d5237'"
379
380- name: insert a line into the quoted file with many double quotation strings
381  win_lineinfile: dest={{win_output_dir}}/test_quoting.txt line='"quote" and "unquote"'
382  register: result
383
384- name: assert that the quoted file was changed
385  assert:
386    that:
387    - result.changed
388
389- name: stat the quote test file
390  win_stat: path={{win_output_dir}}/test_quoting.txt
391  register: result
392
393- name: assert test checksum matches quoted line added
394  assert:
395    that:
396    - "result.stat.checksum == '9dc1fc1ff19942e2936564102ad37134fa83b91d'"
397
398
399# Windows vs. Unix line separator test cases
400
401- name: Create windows test file with initial line
402  win_lineinfile: dest={{win_output_dir}}/test_windows_sep.txt create=yes insertbefore=BOF state=present line="This is a new file"
403  register: result
404
405- name: assert that the new file was created
406  assert:
407    that:
408    - "result.changed == true"
409    - "result.msg == 'line added'"
410
411- name: validate that the newly created file exists
412  win_stat: path={{win_output_dir}}/test_windows_sep.txt
413  register: result
414
415- name: assert the newly created file checksum matches
416  assert:
417    that:
418    - "result.stat.checksum == '84faac1183841c57434693752fc3debc91b9195d'"
419
420- name: Test appending to the file using the default (windows) line separator
421  win_lineinfile: dest={{win_output_dir}}/test_windows_sep.txt insertbefore=EOF state=present line="This is the last line"
422  register: result
423
424- name: assert that the new line was added
425  assert:
426    that:
427    - "result.changed == true"
428    - "result.msg == 'line added'"
429
430- name: stat the file
431  win_stat: path={{win_output_dir}}/test_windows_sep.txt
432  register: result
433
434- name: assert the file checksum matches expected checksum
435  assert:
436    that:
437    - "result.stat.checksum == '71a17ddd1d57ed7c7912e4fd11ecb2ead0b27033'"
438
439
440- name: Create unix test file with initial line
441  win_lineinfile: dest={{win_output_dir}}/test_unix_sep.txt create=yes insertbefore=BOF state=present line="This is a new file"
442  register: result
443
444- name: assert that the new file was created
445  assert:
446    that:
447    - "result.changed == true"
448    - "result.msg == 'line added'"
449
450- name: validate that the newly created file exists
451  win_stat: path={{win_output_dir}}/test_unix_sep.txt
452  register: result
453
454- name: assert the newly created file checksum matches
455  assert:
456    that:
457    - "result.stat.checksum == '84faac1183841c57434693752fc3debc91b9195d'"
458
459- name: Test appending to the file using unix line separator
460  win_lineinfile: dest={{win_output_dir}}/test_unix_sep.txt insertbefore=EOF state=present line="This is the last line" newline="unix"
461  register: result
462
463- name: assert that the new line was added
464  assert:
465    that:
466    - "result.changed == true"
467    - "result.msg == 'line added'"
468
469- name: stat the file
470  win_stat: path={{win_output_dir}}/test_unix_sep.txt
471  register: result
472
473- name: assert the file checksum matches expected checksum
474  assert:
475    that:
476    - "result.stat.checksum == 'f1f634a37ab1c73efb77a71a5ad2cc87b61b17ae'"
477
478
479# Encoding management test cases
480
481# Default (auto) encoding should use utf-8 with no BOM
482- name: Test create file without explicit encoding results in utf-8 without BOM
483  win_lineinfile: dest={{win_output_dir}}/test_auto_utf8.txt create=yes insertbefore=BOF state=present line="This is a new utf-8 file"
484  register: result
485
486- name: assert that the new file was created
487  assert:
488    that:
489    - "result.changed == true"
490    - "result.msg == 'line added'"
491    - "result.encoding == 'utf-8'"
492
493- name: validate that the newly created file exists
494  win_stat: path={{win_output_dir}}/test_auto_utf8.txt
495  register: result
496
497- name: assert the newly created file checksum matches
498  assert:
499    that:
500    - "result.stat.checksum == 'b69fcbacca8291a4668f57fba91d7c022f1c3dc7'"
501
502- name: Test appending to the utf-8 without BOM file - should autodetect UTF-8 no BOM
503  win_lineinfile: dest={{win_output_dir}}/test_auto_utf8.txt insertbefore=EOF state=present line="This is the last line"
504  register: result
505
506- name: assert that the new line was added and encoding did not change
507  assert:
508    that:
509    - "result.changed == true"
510    - "result.msg == 'line added'"
511    - "result.encoding == 'utf-8'"
512
513- name: stat the file
514  win_stat: path={{win_output_dir}}/test_auto_utf8.txt
515  register: result
516
517- name: assert the file checksum matches
518  assert:
519    that:
520    - "result.stat.checksum == '64d747f1ebf8c9d793dbfd27126e4152d39a3848'"
521
522
523# UTF-8 explicit (with BOM)
524- name: Test create file with explicit utf-8 encoding results in utf-8 with a BOM
525  win_lineinfile: dest={{win_output_dir}}/test_utf8.txt create=yes encoding="utf-8" insertbefore=BOF state=present line="This is a new utf-8 file"
526  register: result
527
528- name: assert that the new file was created
529  assert:
530    that:
531    - "result.changed == true"
532    - "result.msg == 'line added'"
533    - "result.encoding == 'utf-8'"
534
535- name: validate that the newly created file exists
536  win_stat: path={{win_output_dir}}/test_utf8.txt
537  register: result
538
539- name: assert the newly created file checksum matches
540  assert:
541    that:
542    - "result.stat.checksum == 'd45344b2b3bf1cf90eae851b40612f5f37a88bbb'"
543
544- name: Test appending to the utf-8 with BOM file - should autodetect utf-8 with BOM encoding
545  win_lineinfile: dest={{win_output_dir}}/test_utf8.txt insertbefore=EOF state=present line="This is the last line"
546  register: result
547
548- name: assert that the new line was added and encoding did not change
549  assert:
550    that:
551    - "result.changed == true"
552    - "result.msg == 'line added'"
553    - "result.encoding == 'utf-8'"
554
555- name: stat the file
556  win_stat: path={{win_output_dir}}/test_utf8.txt
557  register: result
558
559- name: assert the file checksum matches
560  assert:
561    that:
562    - "result.stat.checksum == '9b84254489f40f258871a4c6573cacc65895ee1a'"
563
564
565# UTF-16 explicit
566- name: Test create file with explicit utf-16 encoding
567  win_lineinfile: dest={{win_output_dir}}/test_utf16.txt create=yes encoding="utf-16" insertbefore=BOF state=present line="This is a new utf-16 file"
568  register: result
569
570- name: assert that the new file was created
571  assert:
572    that:
573    - "result.changed == true"
574    - "result.msg == 'line added'"
575    - "result.encoding == 'utf-16'"
576
577- name: validate that the newly created file exists
578  win_stat: path={{win_output_dir}}/test_utf16.txt
579  register: result
580
581- name: assert the newly created file checksum matches
582  assert:
583    that:
584    - "result.stat.checksum == '785b0693cec13b60e2c232782adeda2f8a967434'"
585
586- name: Test appending to the utf-16 file - should autodetect utf-16 encoding
587  win_lineinfile: dest={{win_output_dir}}/test_utf16.txt insertbefore=EOF state=present line="This is the last line"
588  register: result
589
590- name: assert that the new line was added and encoding did not change
591  assert:
592    that:
593    - "result.changed == true"
594    - "result.msg == 'line added'"
595    - "result.encoding == 'utf-16'"
596
597- name: stat the file
598  win_stat: path={{win_output_dir}}/test_utf16.txt
599  register: result
600
601- name: assert the file checksum matches
602  assert:
603    that:
604    - "result.stat.checksum == '70e4eb3ba795e1ba94d262db47e4fd17c64b2e73'"
605
606# UTF-32 explicit
607- name: Test create file with explicit utf-32 encoding
608  win_lineinfile: dest={{win_output_dir}}/test_utf32.txt create=yes encoding="utf-32" insertbefore=BOF state=present line="This is a new utf-32 file"
609  register: result
610
611- name: assert that the new file was created
612  assert:
613    that:
614    - "result.changed == true"
615    - "result.msg == 'line added'"
616    - "result.encoding == 'utf-32'"
617
618- name: validate that the newly created file exists
619  win_stat: path={{win_output_dir}}/test_utf32.txt
620  register: result
621
622- name: assert the newly created file checksum matches
623  assert:
624    that:
625    - "result.stat.checksum == '7a6e3f3604c0def431aaa813173a4ddaa10fd1fb'"
626
627- name: Test appending to the utf-32 file - should autodetect utf-32 encoding
628  win_lineinfile: dest={{win_output_dir}}/test_utf32.txt insertbefore=EOF state=present line="This is the last line"
629  register: result
630
631- name: assert that the new line was added and encoding did not change
632  assert:
633    that:
634    - "result.changed == true"
635    - "result.msg == 'line added'"
636    - "result.encoding == 'utf-32'"
637
638- name: stat the file
639  win_stat: path={{win_output_dir}}/test_utf32.txt
640  register: result
641
642- name: assert the file checksum matches
643  assert:
644    that:
645    - "result.stat.checksum == '66a72e71f42c4775f4326da95cfe82c8830e5022'"
646
647#########################################################################
648# issue #33858
649# \r\n causes line break instead of printing literally which breaks paths.
650
651- name: create testing file
652  win_copy:
653    src: test_linebreak.txt
654    dest: "{{win_output_dir}}/test_linebreak.txt"
655
656- name: stat the test file
657  win_stat:
658    path: "{{win_output_dir}}/test_linebreak.txt"
659  register: result
660
661# (Get-FileHash -path C:\ansible\test\integration\targets\win_lineinfile\files\test_linebreak.txt -Algorithm sha1).hash.tolower()
662- name: check win_stat file result
663  assert:
664    that:
665      - result.stat.exists
666      - not result.stat.isdir
667      - result.stat.checksum == 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
668      - result is not failed
669      - result is not changed
670
671- name: insert path c:\return\new to test file
672  win_lineinfile:
673    dest: "{{win_output_dir}}/test_linebreak.txt"
674    line: c:\return\new
675  register: result_literal
676
677- name: insert path "c:\return\new" to test file, will cause line breaks
678  win_lineinfile:
679    dest: "{{win_output_dir}}/test_linebreak.txt"
680    line: "c:\return\new"
681  register: result_expand
682
683- name: assert that the lines were inserted
684  assert:
685    that:
686    - result_literal.changed == true
687    - result_literal.msg == 'line added'
688    - result_expand.changed == true
689    - result_expand.msg == 'line added'
690
691- name: stat the test file
692  win_stat:
693    path: "{{win_output_dir}}/test_linebreak.txt"
694  register: result
695
696- debug:
697    var: result
698    verbosity: 1
699
700# expect that the file looks like this:
701# c:\return\new
702# c:
703# eturn
704# ew #or c:eturnew  on windows
705- name: assert that one line is literal and the other has breaks
706  assert:
707    that:
708    - result.stat.checksum == 'd2dfd11bc70526ff13a91153c76a7ae5595a845b'
709