From 2f4fdc3ed9c722ffc339c47fb968682b9ff32309 Mon Sep 17 00:00:00 2001 From: Steven Danna Date: Mon, 1 Aug 2016 11:55:32 +0100 Subject: [PATCH 1/4] Set os[:family] to 'redhat' for 'centos', ensure os[:name] is set Previously the os detection on linux set os[:family] to the name of the distribution and did not set os[:name]. This meant that `os[:family]` for CentOS was `centos` despite most uses expecting it to share the same platform family identifier as other redhat based distributions. Fixes #847 Signed-off-by: Steven Danna --- lib/train/extras/os_detect_linux.rb | 57 +++++++++++++++--------- test/unit/extras/os_detect_linux_test.rb | 13 ++++++ 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/lib/train/extras/os_detect_linux.rb b/lib/train/extras/os_detect_linux.rb index b8252a21..3d5ef461 100644 --- a/lib/train/extras/os_detect_linux.rb +++ b/lib/train/extras/os_detect_linux.rb @@ -16,79 +16,94 @@ module DetectLinux # rubocop:disable Metrics/ModuleLength def detect_linux_via_config # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity if !(raw = get_config('oracle-release')).nil? - @platform[:family] = 'oracle' + @platform[:name] = 'oracle' @platform[:release] = redhatish_version(raw) elsif !(raw = get_config('/etc/enterprise-release')).nil? - @platform[:family] = 'oracle' + @platform[:name] = 'oracle' @platform[:release] = redhatish_version(raw) elsif !(raw = get_config('/etc/debian_version')).nil? case lsb[:id] when /ubuntu/i - @platform[:family] = 'ubuntu' + @platform[:name] = 'ubuntu' @platform[:release] = lsb[:release] when /linuxmint/i - @platform[:family] = 'linuxmint' + @platform[:name] = 'linuxmint' @platform[:release] = lsb[:release] else - @platform[:family] = unix_file?('/usr/bin/raspi-config') ? 'raspbian' : 'debian' + @platform[:name] = unix_file?('/usr/bin/raspi-config') ? 'raspbian' : 'debian' @platform[:release] = raw.chomp end elsif !(raw = get_config('/etc/parallels-release')).nil? - @platform[:family] = redhatish_platform(raw) + @platform[:name] = redhatish_platform(raw) @platform[:release] = raw[/(\d\.\d\.\d)/, 1] elsif !(raw = get_config('/etc/redhat-release')).nil? # TODO: Cisco # TODO: fully investigate os-release and integrate it; # here we just use it for centos - if !(osrel = get_config('/etc/os-release')).nil? && osrel =~ /centos/i - @platform[:family] = 'centos' - else - @platform[:family] = redhatish_platform(raw) - end + @platform[:name] = if !(osrel = get_config('/etc/os-release')).nil? && osrel =~ /centos/i + 'centos' + else + redhatish_platform(raw) + end + @platform[:release] = redhatish_version(raw) elsif !(raw = get_config('/etc/system-release')).nil? # Amazon Linux - @platform[:family] = redhatish_platform(raw) + @platform[:name] = redhatish_platform(raw) @platform[:release] = redhatish_version(raw) elsif !(suse = get_config('/etc/SuSE-release')).nil? version = suse.scan(/VERSION = (\d+)\nPATCHLEVEL = (\d+)/).flatten.join('.') version = suse[/VERSION = ([\d\.]{2,})/, 1] if version == '' @platform[:release] = version - @platform[:family] = 'suse' - @platform[:family] = 'opensuse' if suse =~ /^openSUSE/ + @platform[:name] = if suse =~ /^openSUSE/ + 'opensuse' + else + 'suse' + end elsif !(raw = get_config('/etc/arch-release')).nil? - @platform[:family] = 'arch' + @platform[:name] = 'arch' # Because this is a rolling release distribution, # use the kernel release, ex. 4.1.6-1-ARCH @platform[:release] = uname_r elsif !(raw = get_config('/etc/slackware-version')).nil? - @platform[:family] = 'slackware' + @platform[:name] = 'slackware' @platform[:release] = raw.scan(/(\d+|\.+)/).join elsif !(raw = get_config('/etc/exherbo-release')).nil? - @platform[:family] = 'exherbo' + @platform[:name] = 'exherbo' # Because this is a rolling release distribution, # use the kernel release, ex. 4.1.6 @platform[:release] = uname_r elsif !(raw = get_config('/etc/gentoo-release')).nil? - @platform[:family] = 'gentoo' + @platform[:name] = 'gentoo' @platform[:release] = raw.scan(/(\d+|\.+)/).join elsif !(raw = get_config('/etc/alpine-release')).nil? - @platform[:family] = 'alpine' + @platform[:name] = 'alpine' @platform[:release] = raw.strip elsif !(raw = get_config('/etc/coreos/update.conf')).nil? - @platform[:family] = 'coreos' + @platform[:name] = 'coreos' meta = lsb_config(raw) @platform[:release] = meta[:release] elsif !(os_info = fetch_os_release).nil? if os_info['ID_LIKE'] =~ /wrlinux/ - @platform[:family] = 'wrlinux' + @platform[:name] = 'wrlinux' @platform[:release] = os_info['VERSION'] end end + @platform[:family] = family_for_platform + !@platform[:family].nil? && !@platform[:release].nil? end + def family_for_platform + case @platform[:name] + when 'centos' + 'redhat' + else + @platform[:name] || @platform[:family] + end + end + def uname_s @uname_s ||= @backend.run_command('uname -s').stdout end diff --git a/test/unit/extras/os_detect_linux_test.rb b/test/unit/extras/os_detect_linux_test.rb index 0300b628..89b901d5 100644 --- a/test/unit/extras/os_detect_linux_test.rb +++ b/test/unit/extras/os_detect_linux_test.rb @@ -32,6 +32,19 @@ def initialize end end + describe "/etc/redhat-release" do + describe "and /etc/os-release" do + it "sets the correct family, name, and release on centos" do + detector.stubs(:get_config).with("/etc/redhat-release").returns("CentOS Linux release 7.2.1511 (Core) \n") + detector.stubs(:get_config).with("/etc/os-release").returns("NAME=\"CentOS Linux\"\nVERSION=\"7 (Core)\"\nID=\"centos\"\nID_LIKE=\"rhel fedora\"\n") + detector.detect_linux_via_config.must_equal(true) + detector.platform[:name].must_equal('centos') + detector.platform[:family].must_equal('redhat') + detector.platform[:release].must_equal('redhat-version') + end + end + end + describe '/etc/debian_version' do before { detector.stubs(:get_config).with('/etc/debian_version').returns('deb-version') } From b644f6fbbfe05b184747e530d87b42e116bffb78 Mon Sep 17 00:00:00 2001 From: Steven Danna Date: Mon, 1 Aug 2016 12:39:14 +0100 Subject: [PATCH 2/4] Detect arch via uname -m on Linux and OS X Fixes #772 --- lib/train/extras/os_common.rb | 1 + lib/train/extras/os_detect_darwin.rb | 4 ++++ lib/train/extras/os_detect_linux.rb | 18 ++++++++++++++++-- test/unit/extras/os_detect_linux_test.rb | 10 ++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/train/extras/os_common.rb b/lib/train/extras/os_common.rb index a82126b2..d3737930 100644 --- a/lib/train/extras/os_common.rb +++ b/lib/train/extras/os_common.rb @@ -22,6 +22,7 @@ class OSCommon include Train::Extras::DetectWindows include Train::Extras::DetectEsx + attr_accessor :backend def initialize(backend, platform = nil) @backend = backend @platform = platform || {} diff --git a/lib/train/extras/os_detect_darwin.rb b/lib/train/extras/os_detect_darwin.rb index 50ff5595..241a10e9 100644 --- a/lib/train/extras/os_detect_darwin.rb +++ b/lib/train/extras/os_detect_darwin.rb @@ -18,6 +18,9 @@ def detect_darwin # TODO: ditto on error return false if cmd.stdout.empty? + uname_m = @backend.run_command("uname -m").stdout.chomp + return false if uname_m.empty? + name = cmd.stdout[/^ProductName:\s+(.+)$/, 1] # TODO: ditto on error return false if name.nil? @@ -26,6 +29,7 @@ def detect_darwin @platform[:build] = cmd.stdout[/^BuildVersion:\s+(.+)$/, 1] # TODO: keep for now due to backwards compatibility with serverspec @platform[:family] = 'darwin' + @platform[:arch] = uname_m true end end diff --git a/lib/train/extras/os_detect_linux.rb b/lib/train/extras/os_detect_linux.rb index 3d5ef461..e1be21e3 100644 --- a/lib/train/extras/os_detect_linux.rb +++ b/lib/train/extras/os_detect_linux.rb @@ -105,17 +105,21 @@ def family_for_platform end def uname_s - @uname_s ||= @backend.run_command('uname -s').stdout + @uname_s ||= backend.run_command('uname -s').stdout end def uname_r @uname_r ||= ( - res = @backend.run_command('uname -r').stdout + res = backend.run_command('uname -r').stdout res.strip! unless res.nil? res ) end + def uname_m + @uname_m ||= backend.run_command('uname -m').stdout.chomp + end + def redhatish_platform(conf) conf[/^red hat/i] ? 'redhat' : conf[/(\w+)/i, 1].downcase end @@ -126,10 +130,20 @@ def redhatish_version(conf) conf[/release ([\d\.]+)/, 1] end + def detect_linux_architecture + if uname_m.nil? || uname_m.empty? + false + else + @platform[:arch] = uname_m + true + end + end + def detect_linux # TODO: print an error in this step of the detection return false if uname_s.nil? || uname_s.empty? return false if uname_r.nil? || uname_r.empty? + return false if !detect_linux_architecture return true if detect_linux_via_config return true if detect_linux_via_lsb diff --git a/test/unit/extras/os_detect_linux_test.rb b/test/unit/extras/os_detect_linux_test.rb index 89b901d5..3397570c 100644 --- a/test/unit/extras/os_detect_linux_test.rb +++ b/test/unit/extras/os_detect_linux_test.rb @@ -14,6 +14,16 @@ def initialize describe 'os_detect_linux' do let(:detector) { OsDetectLinuxTester.new } + describe '#detect_linux_architecture' do + it "sets the arch using uname" do + be = mock("Backend") + detector.stubs(:backend).returns(be) + be.stubs(:run_command).with("uname -m").returns(mock("Output", stdout: "x86_64\n")) + detector.detect_linux_architecture.must_equal(true) + detector.platform[:arch].must_equal("x84_64") + end + end + describe '#detect_linux_via_config' do before do From c2b2963bda1658c7ae68515f5f2d04efa8fb5e94 Mon Sep 17 00:00:00 2001 From: Steven Danna Date: Mon, 1 Aug 2016 13:24:19 +0100 Subject: [PATCH 3/4] Bring train platform data more in line with ohai's platform data This includes - `family` refers to the distribuion family while `name` refers to the spcific distribution. For example, the family attribute for ubuntu is `debian`. - The `redhat` family has been renamed `rhel` - Fedora is not listed as a `rhel` platform. --- lib/train/extras/os_common.rb | 15 +++------ lib/train/extras/os_detect_darwin.rb | 12 ++++--- lib/train/extras/os_detect_linux.rb | 42 +++++++++--------------- lib/train/extras/uname.rb | 28 ++++++++++++++++ test/unit/extras/os_common_test.rb | 3 +- test/unit/extras/os_detect_linux_test.rb | 22 ++++++++----- 6 files changed, 72 insertions(+), 50 deletions(-) create mode 100644 lib/train/extras/uname.rb diff --git a/lib/train/extras/os_common.rb b/lib/train/extras/os_common.rb index d3737930..59dbd8e8 100644 --- a/lib/train/extras/os_common.rb +++ b/lib/train/extras/os_common.rb @@ -38,15 +38,10 @@ def to_hash end OS = { # rubocop:disable Style/MutableConstant - 'redhat' => %w{ - redhat oracle centos fedora amazon scientific xenserver wrlinux - }, - 'debian' => %w{ - debian ubuntu linuxmint raspbian - }, - 'suse' => %w{ - suse opensuse - }, + 'redhat' => REDHAT_FAMILY, + 'debian' => DEBIAN_FAMILY, + 'suse' => SUSE_FAMILY, + 'fedora' => %w{fedora}, 'bsd' => %w{ freebsd netbsd openbsd darwin }, @@ -67,7 +62,7 @@ def to_hash }, } - OS['linux'] = %w{linux alpine arch coreos exherbo gentoo slackware} + OS['redhat'] + OS['debian'] + OS['suse'] + OS['linux'] = %w{linux alpine arch coreos exherbo gentoo slackware fedora} + OS['redhat'] + OS['debian'] + OS['suse'] OS['unix'] = %w{unix aix hpux} + OS['linux'] + OS['solaris'] + OS['bsd'] diff --git a/lib/train/extras/os_detect_darwin.rb b/lib/train/extras/os_detect_darwin.rb index 241a10e9..cc3287d1 100644 --- a/lib/train/extras/os_detect_darwin.rb +++ b/lib/train/extras/os_detect_darwin.rb @@ -7,9 +7,12 @@ # OHAI https://github.com/chef/ohai # by Adam Jacob, Chef Software Inc # +require 'train/extras/uname' module Train::Extras module DetectDarwin + include Train::Extras::Uname + def detect_darwin cmd = @backend.run_command('/usr/bin/sw_vers') # TODO: print an error in this step of the detection, @@ -18,9 +21,6 @@ def detect_darwin # TODO: ditto on error return false if cmd.stdout.empty? - uname_m = @backend.run_command("uname -m").stdout.chomp - return false if uname_m.empty? - name = cmd.stdout[/^ProductName:\s+(.+)$/, 1] # TODO: ditto on error return false if name.nil? @@ -29,8 +29,12 @@ def detect_darwin @platform[:build] = cmd.stdout[/^BuildVersion:\s+(.+)$/, 1] # TODO: keep for now due to backwards compatibility with serverspec @platform[:family] = 'darwin' - @platform[:arch] = uname_m + detect_darwin_arch true end + + def detect_darwin_arch + @platform[:arch] = uname_m + end end end diff --git a/lib/train/extras/os_detect_linux.rb b/lib/train/extras/os_detect_linux.rb index e1be21e3..0180e7ab 100644 --- a/lib/train/extras/os_detect_linux.rb +++ b/lib/train/extras/os_detect_linux.rb @@ -9,10 +9,16 @@ # require 'train/extras/linux_lsb' +require 'train/extras/uname' module Train::Extras module DetectLinux # rubocop:disable Metrics/ModuleLength + DEBIAN_FAMILY = %w{debian ubuntu linuxmint raspbian}.freeze + REDHAT_FAMILY = %w{centos redhat oracle scientific enterpriseenterprise xenserver cloudlinux ibm_powerkvm nexus_centos wrlinux}.freeze + SUSE_FAMILY = %w{suse opensuse}.freeze + include Train::Extras::LinuxLSB + include Train::Extras::Uname def detect_linux_via_config # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity if !(raw = get_config('oracle-release')).nil? @@ -85,7 +91,7 @@ def detect_linux_via_config # rubocop:disable Metrics/AbcSize, Metrics/Cyclomati @platform[:release] = meta[:release] elsif !(os_info = fetch_os_release).nil? if os_info['ID_LIKE'] =~ /wrlinux/ - @platform[:name] = 'wrlinux' + @platform[:name] = 'wrlinux' @platform[:release] = os_info['VERSION'] end end @@ -96,30 +102,17 @@ def detect_linux_via_config # rubocop:disable Metrics/AbcSize, Metrics/Cyclomati end def family_for_platform - case @platform[:name] - when 'centos' + if DEBIAN_FAMILY.include?(@platform[:name]) + 'debian' + elsif REDHAT_FAMILY.include?(@platform[:name]) 'redhat' + elsif SUSE_FAMILY.include?(@platform[:name]) + 'suse' else @platform[:name] || @platform[:family] end end - def uname_s - @uname_s ||= backend.run_command('uname -s').stdout - end - - def uname_r - @uname_r ||= ( - res = backend.run_command('uname -r').stdout - res.strip! unless res.nil? - res - ) - end - - def uname_m - @uname_m ||= backend.run_command('uname -m').stdout.chomp - end - def redhatish_platform(conf) conf[/^red hat/i] ? 'redhat' : conf[/(\w+)/i, 1].downcase end @@ -130,21 +123,16 @@ def redhatish_version(conf) conf[/release ([\d\.]+)/, 1] end - def detect_linux_architecture - if uname_m.nil? || uname_m.empty? - false - else - @platform[:arch] = uname_m - true - end + def detect_linux_arch + @platform[:arch] = uname_m end def detect_linux # TODO: print an error in this step of the detection return false if uname_s.nil? || uname_s.empty? return false if uname_r.nil? || uname_r.empty? - return false if !detect_linux_architecture + detect_linux_arch return true if detect_linux_via_config return true if detect_linux_via_lsb # in all other cases we failed the detection diff --git a/lib/train/extras/uname.rb b/lib/train/extras/uname.rb new file mode 100644 index 00000000..4b45abe5 --- /dev/null +++ b/lib/train/extras/uname.rb @@ -0,0 +1,28 @@ +# encoding: utf-8 +# author: Dominik Richter +# author: Christoph Hartmann +# +# This is heavily based on: +# +# OHAI https://github.com/chef/ohai +# by Adam Jacob, Chef Software Inc +# +module Train::Extras + module Uname + def uname_s + @uname_s ||= backend.run_command('uname -s').stdout + end + + def uname_r + @uname_r ||= begin + res = backend.run_command('uname -r').stdout + res.strip! unless res.nil? + res + end + end + + def uname_m + @uname_m ||= backend.run_command('uname -m').stdout.chomp + end + end +end diff --git a/test/unit/extras/os_common_test.rb b/test/unit/extras/os_common_test.rb index 71def801..054f7c67 100644 --- a/test/unit/extras/os_common_test.rb +++ b/test/unit/extras/os_common_test.rb @@ -57,7 +57,8 @@ def mock_platform(x) describe 'with platform set to fedora' do let(:os) { mock_platform('fedora') } - it { os.redhat?.must_equal(true) } + it { os.fedora?.must_equal(true) } + it { os.redhat?.must_equal(false) } it { os.debian?.must_equal(false) } it { os.suse?.must_equal(false) } it { os.linux?.must_equal(true) } diff --git a/test/unit/extras/os_detect_linux_test.rb b/test/unit/extras/os_detect_linux_test.rb index 3397570c..3eaf2303 100644 --- a/test/unit/extras/os_detect_linux_test.rb +++ b/test/unit/extras/os_detect_linux_test.rb @@ -14,13 +14,13 @@ def initialize describe 'os_detect_linux' do let(:detector) { OsDetectLinuxTester.new } - describe '#detect_linux_architecture' do + describe '#detect_linux_arch' do it "sets the arch using uname" do be = mock("Backend") detector.stubs(:backend).returns(be) be.stubs(:run_command).with("uname -m").returns(mock("Output", stdout: "x86_64\n")) - detector.detect_linux_architecture.must_equal(true) - detector.platform[:arch].must_equal("x84_64") + detector.detect_linux_arch + detector.platform[:arch].must_equal("x86_64") end end @@ -37,7 +37,8 @@ def initialize detector.stubs(:get_config).with('/etc/enterprise-release').returns('data') detector.detect_linux_via_config.must_equal(true) - detector.platform[:family].must_equal('oracle') + detector.platform[:name].must_equal('oracle') + detector.platform[:family].must_equal('redhat') detector.platform[:release].must_equal('redhat-version') end end @@ -64,7 +65,8 @@ def initialize detector.stubs(:lsb).returns({ id: 'ubuntu', release: 'ubuntu-release' }) detector.detect_linux_via_config.must_equal(true) - detector.platform[:family].must_equal('ubuntu') + detector.platform[:name].must_equal('ubuntu') + detector.platform[:family].must_equal('debian') detector.platform[:release].must_equal('ubuntu-release') end end @@ -74,7 +76,8 @@ def initialize detector.stubs(:lsb).returns({ id: 'linuxmint', release: 'mint-release' }) detector.detect_linux_via_config.must_equal(true) - detector.platform[:family].must_equal('linuxmint') + detector.platform[:name].must_equal('linuxmint') + detector.platform[:family].must_equal('debian') detector.platform[:release].must_equal('mint-release') end end @@ -85,7 +88,8 @@ def initialize detector.expects(:unix_file?).with('/usr/bin/raspi-config').returns(true) detector.detect_linux_via_config.must_equal(true) - detector.platform[:family].must_equal('raspbian') + detector.platform[:name].must_equal('raspbian') + detector.platform[:family].must_equal('debian') detector.platform[:release].must_equal('deb-version') end end @@ -96,6 +100,7 @@ def initialize detector.expects(:unix_file?).with('/usr/bin/raspi-config').returns(false) detector.detect_linux_via_config.must_equal(true) + detector.platform[:name].must_equal('debian') detector.platform[:family].must_equal('debian') detector.platform[:release].must_equal('deb-version') end @@ -125,7 +130,8 @@ def initialize detector.stubs(:fetch_os_release).returns(data) detector.detect_linux_via_config.must_equal(true) - detector.platform[:family].must_equal('wrlinux') + detector.platform[:name].must_equal('wrlinux') + detector.platform[:family].must_equal('redhat') detector.platform[:release].must_equal('cisco123') end end From a780ee2cb26cb8970ccb75e6fecc84bfd2df0f9a Mon Sep 17 00:00:00 2001 From: Steven Danna Date: Tue, 2 Aug 2016 10:11:06 +0100 Subject: [PATCH 4/4] Return true for linux? when platform is 'amazon' Signed-off-by: Steven Danna --- lib/train/extras/os_common.rb | 2 +- test/unit/extras/os_common_test.rb | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/train/extras/os_common.rb b/lib/train/extras/os_common.rb index 59dbd8e8..e2058e76 100644 --- a/lib/train/extras/os_common.rb +++ b/lib/train/extras/os_common.rb @@ -62,7 +62,7 @@ def to_hash }, } - OS['linux'] = %w{linux alpine arch coreos exherbo gentoo slackware fedora} + OS['redhat'] + OS['debian'] + OS['suse'] + OS['linux'] = %w{linux alpine arch coreos exherbo gentoo slackware fedora amazon} + OS['redhat'] + OS['debian'] + OS['suse'] OS['unix'] = %w{unix aix hpux} + OS['linux'] + OS['solaris'] + OS['bsd'] diff --git a/test/unit/extras/os_common_test.rb b/test/unit/extras/os_common_test.rb index 054f7c67..6a7f8f4d 100644 --- a/test/unit/extras/os_common_test.rb +++ b/test/unit/extras/os_common_test.rb @@ -65,6 +65,16 @@ def mock_platform(x) it { os.unix?.must_equal(true) } end + describe 'with platform set to amazon' do + let(:os) { mock_platform('amazon') } + it { os.fedora?.must_equal(false) } + it { os.redhat?.must_equal(false) } + it { os.debian?.must_equal(false) } + it { os.suse?.must_equal(false) } + it { os.linux?.must_equal(true) } + it { os.unix?.must_equal(true) } + end + describe 'with platform set to debian' do let(:os) { mock_platform('debian') } it { os.redhat?.must_equal(false) }