summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToshio Kuratomi <a.badger@gmail.com>2017-02-24 10:01:21 -0800
committerToshio Kuratomi <a.badger@gmail.com>2017-02-24 12:19:28 -0800
commitd45f2d3288b89145679d63b1fa6534547d6aa151 (patch)
tree4692852887c6799d8bb92e92a0663d766bb92dcf
parente9e39e4fd6ebd04bcd0a00603946e185758a2060 (diff)
downloadansible-d45f2d3288b89145679d63b1fa6534547d6aa151.tar.gz
Fix for traceback when we encounter non-utf8 characters in diff
We can diff non-utf8 files (as part of copy, for instance) but when we try to turn the bytes into text for display, the characters cause a traceback. Since diff output is only informational, we can replace those problematic bytes with replacement characters. We do not want to do this to other fields because those fields may be used inside of the playbook (for templating another variable or matching in a conditional). Fixes #21803 Fixes #21804 (cherry picked from commit 49db03c384b63ba7a299263cdae63857fe46ef1f)
-rw-r--r--lib/ansible/executor/task_executor.py17
1 files changed, 13 insertions, 4 deletions
diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py
index 59759245a8..21a29052d1 100644
--- a/lib/ansible/executor/task_executor.py
+++ b/lib/ansible/executor/task_executor.py
@@ -130,17 +130,26 @@ class TaskExecutor:
if 'changed' not in res:
res['changed'] = False
- def _clean_res(res):
+ def _clean_res(res, errors='surrogate_or_strict'):
if isinstance(res, UnsafeProxy):
return res._obj
elif isinstance(res, binary_type):
- return to_text(res, errors='surrogate_or_strict')
+ return to_text(res, errors=errors)
elif isinstance(res, dict):
for k in res:
- res[k] = _clean_res(res[k])
+ try:
+ res[k] = _clean_res(res[k], errors=errors)
+ except UnicodeError:
+ if k == 'diff':
+ # If this is a diff, substitute a replacement character if the value
+ # is undecodable as utf8. (Fix #21804)
+ display.warning("We were unable to decode all characters, replaced some in an effort to return as much as possible")
+ res[k] = _clean_res(res[k], errors='surrogate_then_replace')
+ else:
+ raise
elif isinstance(res, list):
for idx,item in enumerate(res):
- res[idx] = _clean_res(item)
+ res[idx] = _clean_res(item, errors=errors)
return res
display.debug("dumping result to json")