Make config files obey the utf-8 input rule
When we read files from disk we always want to read them as bytes and then convert them to text ourselves. This gives us greater control over what encodings are used, what to do in case of errors decoding the bytes to text, and better resilience against problems on both Python 2 and Python 3. If we left it up to Python to do this, on Python2, this could mean that config values end up as bytes (leading to tracebacks elsewhere in the code). In Python3, it could traceback if the user's locale did not match with the encoding of the ini file or config files could be decoded as the user's locale encoding instead of as utf-8.
This commit is contained in:
parent
30da71d880
commit
204fc7becf
1 changed files with 12 additions and 2 deletions
|
@ -8,6 +8,7 @@ import os
|
|||
import sys
|
||||
import tempfile
|
||||
|
||||
import io
|
||||
from collections import namedtuple
|
||||
|
||||
from yaml import load as yaml_load
|
||||
|
@ -19,7 +20,7 @@ except ImportError:
|
|||
|
||||
from ansible.config.data import ConfigData
|
||||
from ansible.errors import AnsibleOptionsError, AnsibleError
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.six import PY3, string_types
|
||||
from ansible.module_utils.six.moves import configparser
|
||||
from ansible.module_utils._text import to_text, to_bytes, to_native
|
||||
from ansible.module_utils.parsing.convert_bool import boolean
|
||||
|
@ -215,8 +216,17 @@ class ConfigManager(object):
|
|||
if cfile is not None:
|
||||
if ftype == 'ini':
|
||||
self._parsers[cfile] = configparser.ConfigParser()
|
||||
with open(cfile, 'rb') as f:
|
||||
try:
|
||||
cfg_text = to_text(f.read(), errors='surrogate_or_strict')
|
||||
except UnicodeError:
|
||||
raise AnsibleOptionsError("Error reading config file(%s) because the config file was not utf8 encoded: %s" % (cfile, to_native(e)))
|
||||
try:
|
||||
self._parsers[cfile].read(cfile)
|
||||
if PY3:
|
||||
self._parsers[cfile].read_string(cfg_text)
|
||||
else:
|
||||
cfg_file = io.StringIO(cfg_text)
|
||||
self._parsers[cfile].readfp(cfg_file)
|
||||
except configparser.Error as e:
|
||||
raise AnsibleOptionsError("Error reading config file (%s): %s" % (cfile, to_native(e)))
|
||||
# FIXME: this should eventually handle yaml config files
|
||||
|
|
Loading…
Reference in a new issue