From 1caf9be109a9fafec904f52069246bb30b6e08fc Mon Sep 17 00:00:00 2001 From: Ahti Kitsik Date: Mon, 9 Jun 2014 19:58:45 +0300 Subject: [PATCH] Bugfix to lineinfile to properly handle files with no newline at EOF when using insertafter=EOF. Looks like #6881 is also affected by this bug. Currently when using lineinfile insertafter=EOF for a file that has no newline then the added line is not prefixed with a newline. As a concrete example, ubuntu distro default /etc/ssh/sshd_config has no newline so lineinfile module cannot be used to add a new line to the end of the file. --- library/files/lineinfile | 10 +++- .../roles/test_lineinfile/files/testempty.txt | 0 .../roles/test_lineinfile/files/testnoeof.txt | 2 + .../roles/test_lineinfile/tasks/main.yml | 47 +++++++++++++++++++ 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 test/integration/roles/test_lineinfile/files/testempty.txt create mode 100644 test/integration/roles/test_lineinfile/files/testnoeof.txt diff --git a/library/files/lineinfile b/library/files/lineinfile index be6209e2b7b..3f81d048950 100644 --- a/library/files/lineinfile +++ b/library/files/lineinfile @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # (c) 2012, Daniel Hokka Zakrisson +# (c) 2014, Ahti Kitsik # # This file is part of Ansible # @@ -25,7 +26,7 @@ import tempfile DOCUMENTATION = """ --- module: lineinfile -author: Daniel Hokka Zakrisson +author: Daniel Hokka Zakrisson, Ahti Kitsik short_description: Ensure a particular line is in a file, or replace an existing line using a back-referenced regular expression. description: @@ -110,7 +111,7 @@ options: validate: required: false description: - - validation to run before copying into place. The command is passed + - validation to run before copying into place. The command is passed securely so shell features like expansion and pipes won't work. required: false default: None @@ -251,6 +252,11 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create, # if insertafter=/insertbefore didn't match anything # (so default behaviour is to add at the end) elif insertafter == 'EOF': + + # If the file is not empty then ensure there's a newline before the added line + if len(lines)>0 and not (lines[-1].endswith('\n') or lines[-1].endswith('\r')): + lines.append(os.linesep) + lines.append(line + os.linesep) msg = 'line added' changed = True diff --git a/test/integration/roles/test_lineinfile/files/testempty.txt b/test/integration/roles/test_lineinfile/files/testempty.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/integration/roles/test_lineinfile/files/testnoeof.txt b/test/integration/roles/test_lineinfile/files/testnoeof.txt new file mode 100644 index 00000000000..152780b9ff0 --- /dev/null +++ b/test/integration/roles/test_lineinfile/files/testnoeof.txt @@ -0,0 +1,2 @@ +This is line 1 +This is line 2 \ No newline at end of file diff --git a/test/integration/roles/test_lineinfile/tasks/main.yml b/test/integration/roles/test_lineinfile/tasks/main.yml index f59979473b9..4b4dfb98e40 100644 --- a/test/integration/roles/test_lineinfile/tasks/main.yml +++ b/test/integration/roles/test_lineinfile/tasks/main.yml @@ -209,3 +209,50 @@ that: - "result.stat.md5 == 'fef1d487711facfd7aa2c87d788c19d9'" +# Test EOF in cases where file has no newline at EOF +- name: testnoeof deploy the file for lineinfile + copy: src=testnoeof.txt dest={{output_dir}}/testnoeof.txt + register: result + +- name: testnoeof insert a line at the end of the file + lineinfile: dest={{output_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.changed == true" + - "result.msg == 'line added'" + +- name: testnoeof stat the no newline EOF test after the insert at the end + stat: path={{output_dir}}/testnoeof.txt + register: result + +- name: testnoeof assert test md5 matches after the insert at the end + assert: + that: + - "result.stat.md5 == 'f75c9d51f45afd7295000e63ce655220'" + +# Test EOF with empty file to make sure no unneccessary newline is added +- name: testempty deploy the testempty file for lineinfile + copy: src=testempty.txt dest={{output_dir}}/testempty.txt + register: result + +- name: testempty insert a line at the end of the file + lineinfile: dest={{output_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.changed == true" + - "result.msg == 'line added'" + +- name: testempty stat the test after the insert at the end + stat: path={{output_dir}}/testempty.txt + register: result + +- name: testempty assert test md5 matches after the insert at the end + assert: + that: + - "result.stat.md5 == '357dcbee8dfb4436f63bab00a235c45a'"