1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

fixed diff output to be as it was in 1.x, copy and template now use the same

functions to do difs.
This commit is contained in:
Brian Coca 2015-07-26 22:29:56 -04:00
parent c56a304ad9
commit 5d1d9f1505
6 changed files with 97 additions and 57 deletions

View file

@ -20,9 +20,11 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
from six.moves import StringIO from six.moves import StringIO
import base64
import json import json
import os import os
import random import random
import stat
import sys import sys
import tempfile import tempfile
import time import time
@ -480,3 +482,51 @@ class ActionBase:
return fnd return fnd
return None return None
def _get_diff_data(self, tmp, destination, source, task_vars, source_file=True):
diff = {}
self._display.debug("Going to peek to see if file has changed permissions")
peek_result = self._execute_module(module_name='file', module_args=dict(path=destination, diff_peek=True), task_vars=task_vars, persist_files=True)
if not('failed' in peek_result and peek_result['failed']) or peek_result.get('rc', 0) == 0:
if peek_result['state'] == 'absent':
diff['before'] = ''
elif peek_result['appears_binary']:
diff['dst_binary'] = 1
elif peek_result['size'] > C.MAX_FILE_SIZE_FOR_DIFF:
diff['dst_larger'] = C.MAX_FILE_SIZE_FOR_DIFF
else:
self._display.debug("Slurping the file %s" % source)
dest_result = self._execute_module(module_name='slurp', module_args=dict(path=destination), task_vars=task_vars, persist_files=True)
if 'content' in dest_result:
dest_contents = dest_result['content']
if dest_result['encoding'] == 'base64':
dest_contents = base64.b64decode(dest_contents)
else:
raise AnsibleError("unknown encoding in content option, failed: %s" % dest_result)
diff['before_header'] = destination
diff['before'] = dest_contents
if source_file:
self._display.debug("Reading local copy of the file %s" % source)
try:
src = open(source)
src_contents = src.read(8192)
st = os.stat(source)
except Exception as e:
raise AnsibleError("Unexpected error while reading source (%s) for diff: %s " % (source, str(e)))
if "\x00" in src_contents:
diff['src_binary'] = 1
elif st[stat.ST_SIZE] > C.MAX_FILE_SIZE_FOR_DIFF:
diff['src_larger'] = C.MAX_FILE_SIZE_FOR_DIFF
else:
diff['after_header'] = source
diff['after'] = src.read()
else:
self._display.debug("source of file passed in")
diff['after_header'] = 'dynamically generated'
diff['after'] = source
return diff

View file

@ -19,11 +19,9 @@
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
import base64
import json import json
import os import os
import pipes import pipes
import stat
import tempfile import tempfile
from ansible import constants as C from ansible import constants as C
@ -238,9 +236,6 @@ class ActionModule(ActionBase):
) )
) )
if self._play_context.check_mode:
new_module_args['CHECKMODE'] = True
# Execute the file module. # Execute the file module.
module_return = self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars, delete_remote_tmp=delete_remote_tmp) module_return = self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars, delete_remote_tmp=delete_remote_tmp)
module_executed = True module_executed = True
@ -286,42 +281,6 @@ class ActionModule(ActionBase):
f.close() f.close()
return content_tempfile return content_tempfile
def _get_diff_data(self, tmp, destination, source, task_vars):
peek_result = self._execute_module(module_name='file', module_args=dict(path=destination, diff_peek=True), task_vars=task_vars, persist_files=True)
if 'failed' in peek_result and peek_result['failed'] or peek_result.get('rc', 0) != 0:
return {}
diff = {}
if peek_result['state'] == 'absent':
diff['before'] = ''
elif peek_result['appears_binary']:
diff['dst_binary'] = 1
elif peek_result['size'] > C.MAX_FILE_SIZE_FOR_DIFF:
diff['dst_larger'] = C.MAX_FILE_SIZE_FOR_DIFF
else:
dest_result = self._execute_module(module_name='slurp', module_args=dict(path=destination), task_vars=task_vars, tmp=tmp, persist_files=True)
if 'content' in dest_result:
dest_contents = dest_result['content']
if dest_result['encoding'] == 'base64':
dest_contents = base64.b64decode(dest_contents)
else:
raise Exception("unknown encoding, failed: %s" % dest_result)
diff['before_header'] = destination
diff['before'] = dest_contents
src = open(source)
src_contents = src.read(8192)
st = os.stat(source)
if "\x00" in src_contents:
diff['src_binary'] = 1
elif st[stat.ST_SIZE] > C.MAX_FILE_SIZE_FOR_DIFF:
diff['src_larger'] = C.MAX_FILE_SIZE_FOR_DIFF
else:
src.seek(0)
diff['after_header'] = source
diff['after'] = src.read()
return diff
def _remove_tempfile_if_content_defined(self, content, content_tempfile): def _remove_tempfile_if_content_defined(self, content, content_tempfile):
if content is not None: if content is not None:

View file

@ -124,20 +124,15 @@ class ActionModule(ActionBase):
# Error from remote_checksum is a dict. Valid return is a str # Error from remote_checksum is a dict. Valid return is a str
return remote_checksum return remote_checksum
diff = {}
new_module_args = self._task.args.copy()
if local_checksum != remote_checksum: if local_checksum != remote_checksum:
dest_contents = '' dest_contents = ''
# if showing diffs, we need to get the remote value # if showing diffs, we need to get the remote value
if self._play_context.diff: if self._play_context.diff:
# using persist_files to keep the temp directory around to avoid needing to grab another diff = self._get_diff_data(tmp, dest, resultant, task_vars, source_file=False)
my_args = dict(path=dest)
dest_result = self._execute_module(module_name='slurp', module_args=my_args, task_vars=task_vars, persist_files=True)
if 'content' in dest_result:
dest_contents = dest_result['content']
if dest_result['encoding'] == 'base64':
dest_contents = base64.b64decode(dest_contents)
else:
raise Exception("unknown encoding, failed: %s" % dest_result)
if not self._play_context.check_mode: # do actual work thorugh copy if not self._play_context.check_mode: # do actual work thorugh copy
xfered = self._transfer_data(self._connection._shell.join_path(tmp, 'source'), resultant) xfered = self._transfer_data(self._connection._shell.join_path(tmp, 'source'), resultant)
@ -147,7 +142,6 @@ class ActionModule(ActionBase):
self._remote_chmod('a+r', xfered, tmp) self._remote_chmod('a+r', xfered, tmp)
# run the copy module # run the copy module
new_module_args = self._task.args.copy()
new_module_args.update( new_module_args.update(
dict( dict(
src=xfered, src=xfered,
@ -161,7 +155,8 @@ class ActionModule(ActionBase):
result=dict(changed=True) result=dict(changed=True)
if result.get('changed', False) and self._play_context.diff: if result.get('changed', False) and self._play_context.diff:
result['diff'] = dict(before=dest_contents, after=resultant, before_header=dest, after_header=source) result['diff'] = diff
# result['diff'] = dict(before=dest_contents, after=resultant, before_header=dest, after_header=source)
return result return result
@ -172,7 +167,6 @@ class ActionModule(ActionBase):
# the module to follow links. When doing that, we have to set # the module to follow links. When doing that, we have to set
# original_basename to the template just in case the dest is # original_basename to the template just in case the dest is
# a directory. # a directory.
new_module_args = self._task.args.copy()
new_module_args.update( new_module_args.update(
dict( dict(
src=None, src=None,
@ -181,8 +175,5 @@ class ActionModule(ActionBase):
), ),
) )
if self._play_context.check_mode:
new_module_args['CHECKMODE'] = True
return self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars) return self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars)

View file

@ -20,8 +20,11 @@ from __future__ import (absolute_import, division)
__metaclass__ = type __metaclass__ = type
import json import json
import difflib
import warnings
from ansible import constants as C from ansible import constants as C
from ansible.utils.unicode import to_unicode
__all__ = ["CallbackBase"] __all__ = ["CallbackBase"]
@ -54,6 +57,35 @@ class CallbackBase:
for warning in res['warnings']: for warning in res['warnings']:
self._display.warning(warning) self._display.warning(warning)
def _get_diff(self, diff):
try:
with warnings.catch_warnings():
warnings.simplefilter('ignore')
ret = []
if 'dst_binary' in diff:
ret.append("diff skipped: destination file appears to be binary\n")
if 'src_binary' in diff:
ret.append("diff skipped: source file appears to be binary\n")
if 'dst_larger' in diff:
ret.append("diff skipped: destination file size is greater than %d\n" % diff['dst_larger'])
if 'src_larger' in diff:
ret.append("diff skipped: source file size is greater than %d\n" % diff['src_larger'])
if 'before' in diff and 'after' in diff:
if 'before_header' in diff:
before_header = "before: %s" % diff['before_header']
else:
before_header = 'before'
if 'after_header' in diff:
after_header = "after: %s" % diff['after_header']
else:
after_header = 'after'
differ = difflib.unified_diff(to_unicode(diff['before']).splitlines(True), to_unicode(diff['after']).splitlines(True), before_header, after_header, '', '', 10)
for line in list(differ):
ret.append(line)
return u"".join(ret)
except UnicodeDecodeError:
return ">> the files are different, but the diff library cannot compare unicode strings"
def set_play_context(self, play_context): def set_play_context(self, play_context):
pass pass
@ -118,7 +150,7 @@ class CallbackBase:
pass pass
def on_file_diff(self, host, diff): def on_file_diff(self, host, diff):
self._display.display(self._dump_results(diff)) pass
####### V2 METHODS, by default they call v1 counterparts if possible ###### ####### V2 METHODS, by default they call v1 counterparts if possible ######
def v2_on_any(self, *args, **kwargs): def v2_on_any(self, *args, **kwargs):

View file

@ -109,3 +109,7 @@ class CallbackModule(CallbackBase):
msg = "PLAY [%s]" % name msg = "PLAY [%s]" % name
self._display.banner(msg) self._display.banner(msg)
def v2_on_file_diff(self, result):
if 'diff' in result._result:
self._display.display(self._get_diff(result._result['diff']))

View file

@ -75,3 +75,7 @@ class CallbackModule(CallbackBase):
def v2_runner_on_unreachable(self, result): def v2_runner_on_unreachable(self, result):
self._display.display("%s | UNREACHABLE!" % result._host.get_name(), color='yellow') self._display.display("%s | UNREACHABLE!" % result._host.get_name(), color='yellow')
def v2_on_file_diff(self, result):
if 'diff' in result._result:
self._display.display(self._get_diff(result._result['diff']))