diff options
author | Nimesh-Msys <nimesh.patni@msystechnologies.com> | 2019-03-26 22:49:39 +0530 |
---|---|---|
committer | Nimesh-Msys <nimesh.patni@msystechnologies.com> | 2019-04-04 22:11:16 +0530 |
commit | 9b19748867fcb05fab550262449a1bd825db15cf (patch) | |
tree | b192ca1f69f754929a5409c856e8d3e82348d14b /lib | |
parent | 3c264946e8dd051e56418751f093eb3afa3c1387 (diff) | |
download | chef-9b19748867fcb05fab550262449a1bd825db15cf.tar.gz |
locale resource: Add support to set all LC ENV variables
- Deprecated `lc_all`
- Provided other features like generate locale if it is not available
- Removed system dependancy
- Added unit and functional test cases
- Added YARD format comments
- Ensured Chefstyle
- Fixes: MSYS-988
Signed-off-by: Nimesh-Msys <nimesh.patni@msystechnologies.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef/deprecated.rb | 5 | ||||
-rw-r--r-- | lib/chef/resource/locale.rb | 140 |
2 files changed, 100 insertions, 45 deletions
diff --git a/lib/chef/deprecated.rb b/lib/chef/deprecated.rb index 1e33fdde0a..6516366d49 100644 --- a/lib/chef/deprecated.rb +++ b/lib/chef/deprecated.rb @@ -226,6 +226,10 @@ class Chef target 26 end + class LocaleLcAll < Base + target 27 + end + class Generic < Base def url "https://docs.chef.io/chef_deprecations_client.html" @@ -235,6 +239,5 @@ class Chef "Deprecation from #{location}\n\n #{message}\n\n#{link}" end end - end end diff --git a/lib/chef/resource/locale.rb b/lib/chef/resource/locale.rb index ca6ea510c0..b16cfe7e3c 100644 --- a/lib/chef/resource/locale.rb +++ b/lib/chef/resource/locale.rb @@ -25,67 +25,119 @@ class Chef description "Use the locale resource to set the system's locale." introduced "14.5" + LC_VARIABLES = %w{LC_ADDRESS LC_COLLATE LC_CTYPE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME}.freeze + LOCALE_CONF = "/etc/locale.conf".freeze + LOCALE_REGEX = /\A\S+/.freeze + property :lang, String, - default: "en_US.utf8", - description: "Sets the default system language." + description: "Sets the default system language.", + regex: [LOCALE_REGEX], + validation_message: "The provided lang is not valid. It should be a non-empty string without any leading whitespaces." + + property :lc_env, Hash, + description: "A Hash of LC_* env variables in the form of ({ 'LC_ENV_VARIABLE' => 'VALUE' }).", + default: lazy { {} }, + coerce: proc { |h| + if h.respond_to?(:keys) + invalid_keys = h.keys - LC_VARIABLES + unless invalid_keys.empty? + error_msg = "Key of option lc_env must be equal to one of: \"#{LC_VARIABLES.join('", "')}\"! You passed \"#{invalid_keys.join(', ')}\"." + raise Chef::Exceptions::ValidationFailed, error_msg + end + end + unless h.values.all? { |x| x =~ LOCALE_REGEX } + error_msg = "Values of option lc_env should be non-empty string without any leading whitespaces." + raise Chef::Exceptions::ValidationFailed, error_msg + end + h + } - property :lc_all, String, - default: "en_US.utf8", - description: "Sets the fallback system language." + # @deprecated Use {#lc_env} instead of this property. + # {#lc_env} uses Hash with specific LC var as key. + # @raise [Chef::Deprecated] + # + def lc_all(arg = nil) + unless arg.nil? + Chef.deprecated(:locale_lc_all, "Changing LC_ALL can break Chef's parsing of command output in unexpected ways.\n Use one of the more specific LC_ properties as needed.") + end + end action :update do description "Update the system's locale." - - if node["init_package"] == "systemd" - # on systemd settings LC_ALL is (correctly) reserved only for testing and cannot be set globally - execute "localectl set-locale LANG=#{new_resource.lang}" do - # RHEL uses /etc/locale.conf - not_if { up_to_date?("/etc/locale.conf", new_resource.lang) } if ::File.exist?("/etc/locale.conf") - # Ubuntu 16.04 still uses /etc/default/locale - not_if { up_to_date?("/etc/default/locale", new_resource.lang) } if ::File.exist?("/etc/default/locale") + begin + unless up_to_date? + converge_by "Updating System Locale" do + generate_locales unless unavailable_locales.empty? + update_locale + end end - elsif ::File.exist?("/etc/sysconfig/i18n") - locale_file_path = "/etc/sysconfig/i18n" + rescue + # It might affect debugging + raise "#{node['platform']} platform is not supported by the chef locale resource. " + + "If you believe this is in error please file an issue at https://github.com/chef/chef/issues" + end + end - updated = up_to_date?(locale_file_path, new_resource.lang, new_resource.lc_all) + action_class do - file locale_file_path do - content lazy { - locale = IO.read(locale_file_path) - variables = Hash[locale.lines.map { |line| line.strip.split("=") }] - variables["LANG"] = new_resource.lang - variables["LC_ALL"] = - variables.map { |pairs| pairs.join("=") }.join("\n") + "\n" - } - not_if { updated } + # Generates the localisation files from templates using locale-gen. + # @see http://manpages.ubuntu.com/manpages/cosmic/man8/locale-gen.8.html + # @raise [Mixlib::ShellOut::ShellCommandFailed] not a supported language or locale + # + def generate_locales + bash "Generating locales: #{unavailable_locales.join(' ')}" do + code <<~CODE + if type locale-gen >/dev/null 2>&1 + then + locale-gen #{unavailable_locales.join(' ')} + fi + CODE end + end - execute "reload root's lang profile script" do - command "source /etc/sysconfig/i18n; source /etc/profile.d/lang.sh" - not_if { updated } + # Updates system locale by appropriately writing them in /etc/locale.conf + # @note This locale change won't affect the current run. At this time it is an exercise + # left to the user to restart or reboot if the locale change is required at + # later part of the client run. + # @see https://wiki.archlinux.org/index.php/locale#Setting_the_system_locale + # + def update_locale + file "Updating system locale" do + path LOCALE_CONF + content new_content end - elsif ::File.exist?("/usr/sbin/update-locale") - execute "Generate locales" do - command "locale-gen" - not_if { up_to_date?("/etc/default/locale", new_resource.lang, new_resource.lc_all) } + end + + # @return [Array<String>] Locales that user wants to set but are not available on + # the system. They are required to be generated. + # + def unavailable_locales + @unavailable_locales ||= begin + available = shell_out!("locale -a").stdout.split("\n") + required = [new_resource.lang, new_resource.lc_env.values].flatten.compact.uniq + required - available end + end - execute "Update locale" do - command "update-locale LANG=#{new_resource.lang} LC_ALL=#{new_resource.lc_all}" - not_if { up_to_date?("/etc/default/locale", new_resource.lang, new_resource.lc_all) } + # @return [String] Contents that are required to be + # updated in /etc/locale.conf + # + def new_content + @new_content ||= begin + content = {} + content = new_resource.lc_env.dup if new_resource.lc_env + content["LANG"] = new_resource.lang if new_resource.lang + content.sort.map { |t| t.join("=") }.join("\n") + "\n" end - else - raise "#{node["platform"]} platform not supported by the chef locale resource." end - end - action_class do - def up_to_date?(file_path, lang, lc_all = nil) - locale = IO.read(file_path) - locale.include?("LANG=#{lang}") && - (node["init_package"] == "systemd" || lc_all.nil? || locale.include?("LC_ALL=#{lc_all}")) + # @return [Boolean] Whether any modification is required in /etc/locale.conf + # + def up_to_date? + old_content = ::File.read(LOCALE_CONF) + new_content == old_content rescue - false + false # We need to create the file if it is not present end end end |