From 222e1c97bed44c8c01ea366598d419ab2da525ef Mon Sep 17 00:00:00 2001
From: peay <peay@users.noreply.github.com>
Date: Tue, 17 Jan 2017 10:16:25 -0500
Subject: [PATCH] Fixes #19883: Handle INI files without ending newline
 (#20016)

---
 lib/ansible/modules/files/ini_file.py | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/lib/ansible/modules/files/ini_file.py b/lib/ansible/modules/files/ini_file.py
index 5b0ef922def..d1d2cf41f89 100644
--- a/lib/ansible/modules/files/ini_file.py
+++ b/lib/ansible/modules/files/ini_file.py
@@ -34,6 +34,8 @@ description:
        to manage the file as a whole with, say, M(template) or M(assemble). Adds missing
        sections if they don't exist.
      - Before version 2.0, comments are discarded when the source file is read, and therefore will not show up in the destination file.
+     - Since version 2.3, this module adds missing ending newlines to files to keep in line with the POSIX standard, even when
+       no modifications need to be applied.
 version_added: "0.9"
 options:
   path:
@@ -172,12 +174,18 @@ def do_ini(module, filename, section=None, option=None, value=None,
     if module._diff:
         diff['before'] = ''.join(ini_lines)
 
+    changed = False
+
+    # last line of file may not contain a trailing newline
+    if ini_lines[-1] == "" or ini_lines[-1][-1] != '\n':
+        ini_lines[-1] += '\n'
+        changed = True
+
     # append a fake section line to simplify the logic
     ini_lines.append('[')
 
     within_section = not section
     section_start = 0
-    changed = False
     msg = 'OK'
     if no_extra_spaces:
         assignment_format = '%s=%s\n'
@@ -211,11 +219,12 @@ def do_ini(module, filename, section=None, option=None, value=None,
                     # change the existing option line
                     if match_opt(option, line):
                         newline = assignment_format % (option, value)
-                        changed = ini_lines[index] != newline
-                        if changed:
+                        option_changed = ini_lines[index] != newline
+                        changed = changed or option_changed
+                        if option_changed:
                             msg = 'option changed'
                         ini_lines[index] = newline
-                        if changed:
+                        if option_changed:
                             # remove all possible option occurrences from the rest of the section
                             index = index + 1
                             while index < len(ini_lines):