Now allow every type of locales + archlinux fix

The previous version of this code was supporting only locales using the
format "<language>_<territory>.<charset>". But all the locales that
doesn't have this format were not installable (such as "fr_FR" or
"fr_FR@euro").
Also, if an invalid locales was provided, the module kept sending a
"changed" status.

Now :
 * if the user provides an invalid locales, the module failed. Locales
   are verified using /etc/locale.gen or /usr/share/i18n/SUPPORTED if
   Ubuntu
 * Every types of valid locales are now supported.
 * The locale module was not working on Archlinux, as there's no space
   between the "#" and the locale. This is now supported. Credits goes
   to danderson189, this is his code.

This module was tested on debian jessie, ubuntu 14 LTS and last
Archlinux.
reviewable/pr18780/r1
Sterfield 10 years ago
parent 3e7da5366b
commit c9656ff3b4

@ -36,6 +36,26 @@ EXAMPLES = '''
# location module specific support methods.
#
def is_available(name, ubuntuMode):
"""Check if the given locale is available on the system. This is done by
checking either :
* if the locale is present in /etc/locales.gen
* or if the locale is present in /usr/share/i18n/SUPPORTED"""
if ubuntuMode:
__regexp = '^(?P<locale>\S+_\S+) (?P<charset>\S+)\s*$'
__locales_available = '/usr/share/i18n/SUPPORTED'
else:
__regexp = '^#{0,1}\s*(?P<locale>\S+_\S+) (?P<charset>\S+)\s*$'
__locales_available = '/etc/locale.gen'
re_compiled = re.compile(__regexp)
with open(__locales_available, 'r') as fd:
for line in fd:
result = re_compiled.match(line)
if result and result.group('locale') == name:
return True
return False
def is_present(name):
"""Checks if the given locale is currently installed."""
output = Popen(["locale", "-a"], stdout=PIPE).communicate()[0]
@ -53,32 +73,42 @@ def replace_line(existing_line, new_line):
with open("/etc/locale.gen", "w") as f:
f.write("".join(lines))
def apply_change(targetState, name, encoding):
def set_locale(name, enabled=True):
""" Sets the state of the locale. Defaults to enabled. """
search_string = '#{0,1}\s*%s (?P<charset>.+)' % name
if enabled:
new_string = '%s \g<charset>' % (name)
else:
new_string = '# %s \g<charset>' % (name)
with open("/etc/locale.gen", "r") as f:
lines = [re.sub(search_string, new_string, line) for line in f]
with open("/etc/locale.gen", "w") as f:
f.write("".join(lines))
def apply_change(targetState, name):
"""Create or remove locale.
Keyword arguments:
targetState -- Desired state, either present or absent.
name -- Name including encoding such as de_CH.UTF-8.
encoding -- Encoding such as UTF-8.
"""
if targetState=="present":
# Create locale.
replace_line("# "+name+" "+encoding, name+" "+encoding)
set_locale(name, enabled=True)
else:
# Delete locale.
replace_line(name+" "+encoding, "# "+name+" "+encoding)
set_locale(name, enabled=False)
localeGenExitValue = call("locale-gen")
if localeGenExitValue!=0:
raise EnvironmentError(localeGenExitValue, "locale.gen failed to execute, it returned "+str(localeGenExitValue))
def apply_change_ubuntu(targetState, name, encoding):
def apply_change_ubuntu(targetState, name):
"""Create or remove locale.
Keyword arguments:
targetState -- Desired state, either present or absent.
name -- Name including encoding such as de_CH.UTF-8.
encoding -- Encoding such as UTF-8.
"""
if targetState=="present":
# Create locale.
@ -90,7 +120,8 @@ def apply_change_ubuntu(targetState, name, encoding):
content = f.readlines()
with open("/var/lib/locales/supported.d/local", "w") as f:
for line in content:
if line!=(name+" "+encoding+"\n"):
locale, charset = line.split(' ')
if locale != name:
f.write(line)
# Purge locales and regenerate.
# Please provide a patch if you know how to avoid regenerating the locales to keep!
@ -113,8 +144,6 @@ def main():
)
name = module.params['name']
if not "." in name:
module.fail_json(msg="Locale does not match pattern. Did you specify the encoding?")
state = module.params['state']
if not os.path.exists("/etc/locale.gen"):
@ -126,23 +155,26 @@ def main():
else:
# We found the common way to manage locales.
ubuntuMode = False
if not is_available(name, ubuntuMode):
module.fail_json(msg="The locales you've entered is not available "
"on your system.")
prev_state = "present" if is_present(name) else "absent"
changed = (prev_state!=state)
if module.check_mode:
module.exit_json(changed=changed)
else:
encoding = name.split(".")[1]
if changed:
try:
if ubuntuMode==False:
apply_change(state, name, encoding)
apply_change(state, name)
else:
apply_change_ubuntu(state, name, encoding)
apply_change_ubuntu(state, name)
except EnvironmentError as e:
module.fail_json(msg=e.strerror, exitValue=e.errno)
module.exit_json(name=name, changed=changed, msg="OK")
# import module snippets

Loading…
Cancel
Save