Need to convert filenames to byte strings before using them in APIs

Under a non-utf-8 locale (for instance, LC_ALL=C), passing a non-ascii
filename to many APIs will traceback.  Fix that by explicitly converting
to byte strings before passing to external APIs.

May fix #27262

(cherry picked from commit 2976b653ce)

Add a changelog for filename encoding in template action fix

(cherry picked from commit d90c36e320)
pull/39358/merge
Toshio Kuratomi 7 years ago
parent b5a5211cd4
commit e7aa8bc0e3

@ -0,0 +1,5 @@
---
bugfixes:
- template action plugin - fix the encoding of filenames to avoid tracebacks on
Python2 when characters that are not present in the user's locale are
present. (https://github.com/ansible/ansible/pull/39424)

@ -80,11 +80,12 @@ class ActionModule(ActionBase):
tmp_source = self._loader.get_real_file(source)
except AnsibleFileNotFound as e:
raise AnsibleActionFail("could not find src=%s, %s" % (source, to_text(e)))
b_tmp_source = to_bytes(tmp_source, errors='surrogate_or_strict')
# template the source data locally & get ready to transfer
try:
with open(tmp_source, 'r') as f:
template_data = to_text(f.read())
with open(b_tmp_source, 'rb') as f:
template_data = to_text(f.read(), errors='surrogate_or_strict')
# set jinja2 internal search path for includes
searchpath = task_vars.get('ansible_search_path', [])
@ -124,7 +125,7 @@ class ActionModule(ActionBase):
except Exception as e:
raise AnsibleActionFail("%s: %s" % (type(e).__name__, to_text(e)))
finally:
self._loader.cleanup_tmp_file(tmp_source)
self._loader.cleanup_tmp_file(b_tmp_source)
new_task = self._task.copy()
new_task.args.pop('newline_sequence', None)
@ -138,7 +139,7 @@ class ActionModule(ActionBase):
try:
result_file = os.path.join(local_tempdir, os.path.basename(source))
with open(result_file, 'wb') as f:
with open(to_bytes(result_file, errors='surrogate_or_strict'), 'wb') as f:
f.write(to_bytes(resultant, errors='surrogate_or_strict'))
new_task.args.update(
@ -157,7 +158,7 @@ class ActionModule(ActionBase):
shared_loader_obj=self._shared_loader_obj)
result.update(copy_action.run(task_vars=task_vars))
finally:
shutil.rmtree(local_tempdir)
shutil.rmtree(to_bytes(local_tempdir, errors='surrogate_or_strict'))
except AnsibleAction as e:
result.update(e.result)

Loading…
Cancel
Save