summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaire McQuin <mcquin@users.noreply.github.com>2014-10-16 11:37:08 -0700
committerClaire McQuin <mcquin@users.noreply.github.com>2014-10-16 11:37:08 -0700
commit33b198b6b954742c313a84b40610ab8f842e5735 (patch)
tree414b0ef8478ea421b66c5356a8707849184eb043
parent63d0d19723b77c6e29a01f897ffed34432a35584 (diff)
parent4916e377f8e421efabd4a52c12448a8b1ee6541c (diff)
downloadchef-33b198b6b954742c313a84b40610ab8f842e5735.tar.gz
Merge pull request #2222 from opscode/mcquin/centos-locale-a
Better handling of locale -a output
-rw-r--r--CHANGELOG.md1
-rw-r--r--lib/chef/config.rb28
-rw-r--r--spec/unit/config_spec.rb89
3 files changed, 111 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 86ad521ee6..2795a4126c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -200,6 +200,7 @@
* Removed dependencies on the 'json' gem, replaced with ffi-yajl. Use Chef::JSONCompat library for parsing and printing.
* Restore the deprecation logic of #valid_actions in LWRPs until Chef 13.
* Now that we don't allow unforked chef-client interval runs, remove the reloading of previously defined LWRPs.
+* Use shell_out to determine Chef::Config[:internal_locale], fix CentOS locale detection bug.
## Last Release: 11.14.2
diff --git a/lib/chef/config.rb b/lib/chef/config.rb
index 107b50ee85..9a8117d2c2 100644
--- a/lib/chef/config.rb
+++ b/lib/chef/config.rb
@@ -25,11 +25,13 @@ require 'mixlib/config'
require 'chef/util/selinux'
require 'chef/util/path_helper'
require 'pathname'
+require 'chef/mixin/shell_out'
class Chef
class Config
extend Mixlib::Config
+ extend Chef::Mixin::ShellOut
PathHelper = Chef::Util::PathHelper
@@ -604,25 +606,37 @@ class Chef
# available English UTF-8 locale. However, all modern POSIXen should support 'locale -a'.
default :internal_locale do
begin
- locales = `locale -a`.split
+ # https://github.com/opscode/chef/issues/2181
+ # Some systems have the `locale -a` command, but the result has
+ # invalid characters for the default encoding.
+ #
+ # For example, on CentOS 6 with ENV['LANG'] = "en_US.UTF-8",
+ # `locale -a`.split fails with ArgumentError invalid UTF-8 encoding.
+ locales = shell_out_with_systems_locale("locale -a").stdout.split
case
when locales.include?('C.UTF-8')
'C.UTF-8'
- when locales.include?('en_US.UTF-8')
+ when locales.include?('en_US.UTF-8'), locales.include?('en_US.utf8')
'en_US.UTF-8'
when locales.include?('en.UTF-8')
'en.UTF-8'
- when guesses = locales.select { |l| l =~ /^en_.*UTF-8$'/ }
- guesses.first
else
- Chef::Log.warn "Please install an English UTF-8 locale for Chef to use, falling back to C locale and disabling UTF-8 support."
- 'C'
+ # Will match en_ZZ.UTF-8, en_ZZ.utf-8, en_ZZ.UTF8, en_ZZ.utf8
+ guesses = locales.select { |l| l =~ /^en_.*UTF-?8$/i }
+ unless guesses.empty?
+ guessed_locale = guesses.first
+ # Transform into the form en_ZZ.UTF-8
+ guessed_locale.gsub(/UTF-?8$/i, "UTF-8")
+ else
+ Chef::Log.warn "Please install an English UTF-8 locale for Chef to use, falling back to C locale and disabling UTF-8 support."
+ 'C'
+ end
end
rescue
if Chef::Platform.windows?
Chef::Log.debug "Defaulting to locale en_US.UTF-8 on Windows, until it matters that we do something else."
else
- Chef::Log.warn "No usable locale -a command found, assuming you have en_US.UTF-8 installed."
+ Chef::Log.debug "No usable locale -a command found, assuming you have en_US.UTF-8 installed."
end
'en_US.UTF-8'
end
diff --git a/spec/unit/config_spec.rb b/spec/unit/config_spec.rb
index 41411669e6..cc83ca3c45 100644
--- a/spec/unit/config_spec.rb
+++ b/spec/unit/config_spec.rb
@@ -417,6 +417,95 @@ describe Chef::Config do
end
end
end
+
+ describe "Chef::Config[:internal_locale]" do
+ let(:shell_out) do
+ double("Chef::Mixin::ShellOut double", :exitstatus => 0, :stdout => locales)
+ end
+
+ let(:locales) { locale_array.join("\n") }
+
+ before do
+ allow(Chef::Config).to receive(:shell_out_with_systems_locale).with("locale -a").and_return(shell_out)
+ end
+
+ shared_examples_for "a suitable locale" do
+ it "returns an English UTF-8 locale" do
+ expect(Chef::Log).to_not receive(:warn).with(/Please install an English UTF-8 locale for Chef to use/)
+ expect(Chef::Log).to_not receive(:debug).with(/Defaulting to locale en_US.UTF-8 on Windows/)
+ expect(Chef::Log).to_not receive(:debug).with(/No usable locale -a command found/)
+ expect(Chef::Config[:internal_locale]).to eq expected_locale
+ end
+ end
+
+ context "when the result includes 'C.UTF-8'" do
+ include_examples "a suitable locale" do
+ let(:locale_array) { [expected_locale, "en_US.UTF-8"] }
+ let(:expected_locale) { "C.UTF-8" }
+ end
+ end
+
+ context "when the result includes 'en_US.UTF-8'" do
+ include_examples "a suitable locale" do
+ let(:locale_array) { ["en_CA.UTF-8", expected_locale, "en_NZ.UTF-8"] }
+ let(:expected_locale) { "en_US.UTF-8" }
+ end
+ end
+
+ context "when the result includes 'en_US.utf8'" do
+ include_examples "a suitable locale" do
+ let(:locale_array) { ["en_CA.utf8", "en_US.utf8", "en_NZ.utf8"] }
+ let(:expected_locale) { "en_US.UTF-8" }
+ end
+ end
+
+ context "when the result includes 'en.UTF-8'" do
+ include_examples "a suitable locale" do
+ let(:locale_array) { ["en.ISO8859-1", expected_locale] }
+ let(:expected_locale) { "en.UTF-8" }
+ end
+ end
+
+ context "when the result includes 'en_*.UTF-8'" do
+ include_examples "a suitable locale" do
+ let(:locale_array) { [expected_locale, "en_CA.UTF-8", "en_GB.UTF-8"] }
+ let(:expected_locale) { "en_AU.UTF-8" }
+ end
+ end
+
+ context "when the result includes 'en_*.utf8'" do
+ include_examples "a suitable locale" do
+ let(:locale_array) { ["en_AU.utf8", "en_CA.utf8", "en_GB.utf8"] }
+ let(:expected_locale) { "en_AU.UTF-8" }
+ end
+ end
+
+ context "when the result does not include 'en_*.UTF-8'" do
+ let(:locale_array) { ["af_ZA", "af_ZA.ISO8859-1", "af_ZA.ISO8859-15", "af_ZA.UTF-8"] }
+
+ it "should fall back to C locale" do
+ expect(Chef::Log).to receive(:warn).with("Please install an English UTF-8 locale for Chef to use, falling back to C locale and disabling UTF-8 support.")
+ expect(Chef::Config[:internal_locale]).to eq 'C'
+ end
+ end
+
+ context "on error" do
+ let(:locale_array) { [] }
+
+ before do
+ allow(Chef::Config).to receive(:shell_out_with_systems_locale).and_raise("THIS IS AN ERROR")
+ end
+
+ it "should default to 'en_US.UTF-8'" do
+ if is_windows
+ expect(Chef::Log).to receive(:debug).with("Defaulting to locale en_US.UTF-8 on Windows, until it matters that we do something else.")
+ else
+ expect(Chef::Log).to receive(:debug).with("No usable locale -a command found, assuming you have en_US.UTF-8 installed.")
+ end
+ expect(Chef::Config[:internal_locale]).to eq "en_US.UTF-8"
+ end
+ end
+ end
end
end
end