From 99ba594f0a3dba7cb57d5dcb5916ddf41f1545bc Mon Sep 17 00:00:00 2001 From: Tobias Wolf Date: Wed, 27 Jan 2016 12:33:24 +0100 Subject: [PATCH] Add diff for both file contents and file attributes to lineinfile Using the difflist feature added in ansible/ansible@c337293 we can add two diffs to the `diff` dict returned as JSON: A `before` and `after` pair of changed file contents and the diff of the file attributes. n.b.: the difflist handling from the above commit is logically broken. PR will follow. Example output: TASK [change line and mode] ************************************************************ changed: [localhost] --- before: /tmp/sshd_config (content) +++ after: /tmp/sshd_config (content) @@ -65,21 +65,21 @@ X11DisplayOffset 10 PrintMotd no PrintLastLog yes TCPKeepAlive yes #UseLogin no #MaxStartups 10:30:60 #Banner /etc/issue.net # Allow client to pass locale environment variables -AcceptEnv LANG LC_* +AcceptEnv LANG LC_* GF_ENV_* Subsystem sftp /usr/lib/openssh/sftp-server # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will # be allowed through the ChallengeResponseAuthentication and # PasswordAuthentication. Depending on your PAM configuration, # PAM authentication via ChallengeResponseAuthentication may bypass # the setting of "PermitRootLogin without-password". # If you just want the PAM account and session checks to run without --- before: /tmp/sshd_config (file attributes) +++ after: /tmp/sshd_config (file attributes) @@ -1,3 +1,3 @@ { - "mode": "0700" + "mode": "0644" } --- files/lineinfile.py | 52 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/files/lineinfile.py b/files/lineinfile.py index 45dd12ec135..e2dd6440a77 100644 --- a/files/lineinfile.py +++ b/files/lineinfile.py @@ -167,10 +167,10 @@ def write_changes(module,lines,dest): if valid: module.atomic_move(tmpfile, os.path.realpath(dest)) -def check_file_attrs(module, changed, message): +def check_file_attrs(module, changed, message, diff): file_args = module.load_file_common_arguments(module.params) - if module.set_fs_attributes_if_different(file_args, False): + if module.set_fs_attributes_if_different(file_args, False, diff=diff): if changed: message += " and " @@ -183,6 +183,11 @@ def check_file_attrs(module, changed, message): def present(module, dest, regexp, line, insertafter, insertbefore, create, backup, backrefs): + diff = {'before': '', + 'after': '', + 'before_header': '%s (content)' % dest, + 'after_header': '%s (content)' % dest} + if not os.path.exists(dest): if not create: module.fail_json(rc=257, msg='Destination %s does not exist !' % dest) @@ -195,7 +200,8 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create, lines = f.readlines() f.close() - msg = "" + if module._diff: + diff['before'] = ''.join(lines) if regexp is not None: mre = re.compile(regexp) @@ -271,6 +277,9 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create, msg = 'line added' changed = True + if module._diff: + diff['after'] = ''.join(lines) + backupdest = "" if changed and not module.check_mode: if backup and os.path.exists(dest): @@ -278,10 +287,16 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create, write_changes(module, lines, dest) if module.check_mode and not os.path.exists(dest): - module.exit_json(changed=changed, msg=msg, backup=backupdest) + module.exit_json(changed=changed, msg=msg, backup=backupdest, diff=diff) - msg, changed = check_file_attrs(module, changed, msg) - module.exit_json(changed=changed, msg=msg, backup=backupdest) + attr_diff = {} + msg, changed = check_file_attrs(module, changed, msg, attr_diff) + + attr_diff['before_header'] = '%s (file attributes)' % dest + attr_diff['after_header'] = '%s (file attributes)' % dest + + difflist = [diff, attr_diff] + module.exit_json(changed=changed, msg=msg, backup=backupdest, diff=difflist) def absent(module, dest, regexp, line, backup): @@ -289,11 +304,19 @@ def absent(module, dest, regexp, line, backup): if not os.path.exists(dest): module.exit_json(changed=False, msg="file not present") - msg = "" + msg = '' + diff = {'before': '', + 'after': '', + 'before_header': '%s (content)' % dest, + 'after_header': '%s (content)' % dest} f = open(dest, 'rb') lines = f.readlines() f.close() + + if module._diff: + diff['before'] = ''.join(lines) + if regexp is not None: cre = re.compile(regexp) found = [] @@ -309,6 +332,10 @@ def absent(module, dest, regexp, line, backup): lines = filter(matcher, lines) changed = len(found) > 0 + + if module._diff: + diff['after'] = ''.join(lines) + backupdest = "" if changed and not module.check_mode: if backup: @@ -318,8 +345,15 @@ def absent(module, dest, regexp, line, backup): if changed: msg = "%s line(s) removed" % len(found) - msg, changed = check_file_attrs(module, changed, msg) - module.exit_json(changed=changed, found=len(found), msg=msg, backup=backupdest) + attr_diff = {} + msg, changed = check_file_attrs(module, changed, msg, attr_diff) + + attr_diff['before_header'] = '%s (file attributes)' % dest + attr_diff['after_header'] = '%s (file attributes)' % dest + + difflist = [diff, attr_diff] + + module.exit_json(changed=changed, found=len(found), msg=msg, backup=backupdest, diff=difflist) def main():