diff options
author | Shahul Hameed <skhajamohid1@bloomberg.net> | 2015-08-11 21:40:26 +0000 |
---|---|---|
committer | Shahul Hameed <skhajamohid1@bloomberg.net> | 2016-03-17 17:17:26 -0400 |
commit | e09d888dbea91e5ed94350057445949a39a8b16a (patch) | |
tree | 3d4a673994b9ed05b92740821337c9e83522d171 | |
parent | 80c91e74ac403959d54c9f15b1aa7a3c4fc4bd8b (diff) | |
download | ohai-e09d888dbea91e5ed94350057445949a39a8b16a.tar.gz |
Get windows packages from registry
-rw-r--r-- | lib/ohai/plugins/packages.rb | 45 | ||||
-rw-r--r-- | spec/unit/plugins/packages_spec.rb | 131 |
2 files changed, 101 insertions, 75 deletions
diff --git a/lib/ohai/plugins/packages.rb b/lib/ohai/plugins/packages.rb index b9d06451..36a5eafa 100644 --- a/lib/ohai/plugins/packages.rb +++ b/lib/ohai/plugins/packages.rb @@ -22,6 +22,12 @@ Ohai.plugin(:Packages) do provides "packages" depends "platform_family" + WINDOWS_ATTRIBUTE_ALIASES = { + "DisplayVersion" => "version", + "Publisher" => "publisher", + "InstallDate" => "installdate" + } + collect_data(:linux) do if configuration(:enabled) packages Mash.new @@ -48,24 +54,39 @@ Ohai.plugin(:Packages) do end end - collect_data(:windows) do - if configuration(:enabled) - packages Mash.new - require "wmi-lite" - - wmi = WmiLite::Wmi.new - w32_product = wmi.instances_of("Win32_Product") - - w32_product.find_all.each do |product| - name = product["name"] + def collect_programs_from_registry_key(key_path) + # from http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129(v=vs.85).aspx + if ::RbConfig::CONFIG["target_cpu"] == "i386" + reg_type = Win32::Registry::KEY_READ | 0x100 + elsif ::RbConfig::CONFIG["target_cpu"] == "x86_64" + reg_type = Win32::Registry::KEY_READ | 0x200 + else + reg_type = Win32::Registry::KEY_READ + end + Win32::Registry::HKEY_LOCAL_MACHINE.open(key_path, reg_type) do |reg| + reg.each_key do |key, _wtime| + pkg = reg.open(key) + name = pkg["DisplayName"] rescue nil + next if name.nil? package = packages[name] = Mash.new - %w{version vendor installdate}.each do |attr| - package[attr] = product[attr] + WINDOWS_ATTRIBUTE_ALIASES.each do |registry_attr, package_attr| + value = pkg[registry_attr] rescue nil + package[package_attr] = value unless value.nil? end end end end + collect_data(:windows) do + if configuration(:enabled) + require "win32/registry" + packages Mash.new + collect_programs_from_registry_key('Software\Microsoft\Windows\CurrentVersion\Uninstall') + # on 64 bit systems, 32 bit programs are stored here + collect_programs_from_registry_key('Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall') + end + end + collect_data(:aix) do if configuration(:enabled) packages Mash.new diff --git a/spec/unit/plugins/packages_spec.rb b/spec/unit/plugins/packages_spec.rb index 169eeac6..d2107319 100644 --- a/spec/unit/plugins/packages_spec.rb +++ b/spec/unit/plugins/packages_spec.rb @@ -113,7 +113,7 @@ describe Ohai::System, "plugin packages" do end context "on windows", :windows_only do - require "wmi-lite" + require "win32/registry" let(:plugin) do get_plugin("packages").tap do |plugin| @@ -121,75 +121,80 @@ describe Ohai::System, "plugin packages" do end end - let(:win32_product_output) do - [{ "assignmenttype" => 0, - "caption" => "NXLOG-CE", - "description" => "NXLOG-CE", - "helplink" => nil, - "helptelephone" => nil, - "identifyingnumber" => "{22FA28AB-3C1B-438B-A8B5-E23892C8B567}", - "installdate" => "20150511", - "installdate2" => nil, - "installlocation" => nil, - "installsource" => 'C:\\chef\\cache\\', - "installstate" => 5, - "language" => "1033", - "localpackage" => 'C:\\Windows\\Installer\\30884.msi', - "name" => "NXLOG-CE", - "packagecache" => 'C:\\Windows\\Installer\\30884.msi', - "packagecode" => "{EC3A13C4-4634-47FC-9662-DC293CB96F9F}", - "packagename" => "nexlog-ce-2.8.1248.msi", - "productid" => nil, - "regcompany" => nil, - "regowner" => nil, - "skunumber" => nil, - "transforms" => nil, - "urlinfoabout" => nil, - "urlupdateinfo" => nil, - "vendor" => "nxsec.com", - "version" => "2.8.1248", - "wordcount" => 2 }, - { "assignmenttype" => 1, - "caption" => "Chef Development Kit v0.7.0", - "description" => "Chef Development Kit v0.7.0", - "helplink" => "http://www.getchef.com/support/", - "helptelephone" => nil, - "identifyingnumber" => "{90754A33-404C-4172-8F3B-7F04CE98011C}", - "installdate" => "20150925", "installdate2" => nil, - "installlocation" => nil, - "installsource" => 'C:\\Users\\skhajamohid1\\Downloads\\', - "installstate" => 5, "language" => "1033", - "localpackage" => 'C:\\WINDOWS\\Installer\\d9e1ca7.msi', - "name" => "Chef Development Kit v0.7.0", - "packagecache" => 'C:\\WINDOWS\\Installer\\d9e1ca7.msi', - "packagecode" => "{9B82FB86-40AE-4CDF-9DE8-97574F9395B9}", - "packagename" => "chefdk-0.7.0-1 (2).msi", - "productid" => nil, - "regcompany" => nil, - "regowner" => nil, - "skunumber" => nil, - "transforms" => nil, - "urlinfoabout" => nil, - "urlupdateinfo" => nil, - "vendor" => "\"Chef Software, Inc. <maintainers@chef.io>\"", - "version" => "0.7.0.1", - "wordcount" => 2 }] + let(:win_reg_double) do + instance_double("Win32::Registry") + end + + let(:win_reg_keys) do + [ "{22FA28AB-3C1B-438B-A8B5-E23892C8B567}", + "{0D4BCDCD-6225-4BA5-91A3-54AFCECC281E}" ] + end + + let(:i386_reg_type) do + Win32::Registry::KEY_READ | 0x100 + end + + let(:x86_64_reg_type) do + Win32::Registry::KEY_READ | 0x200 + end + + let(:win_reg_output) do + [{ "DisplayName" => "NXLOG-CE", + "DisplayVersion" => "2.8.1248", + "Publisher" => "nxsec.com", + "InstallDate" => "20150511" + }, + { "DisplayName" => "Chef Development Kit v0.7.0", + "DisplayVersion" => "0.7.0.1", + "Publisher" => "\"Chef Software, Inc. <maintainers@chef.io>\"", + "InstallDate" => "20150925" }] + end + + shared_examples "windows_package_plugin" do + it "gets package info" do + plugin.run + expect(plugin[:packages]["Chef Development Kit v0.7.0"][:version]).to eq("0.7.0.1") + expect(plugin[:packages]["Chef Development Kit v0.7.0"][:publisher]).to eq("\"Chef Software, Inc. <maintainers@chef.io>\"") + expect(plugin[:packages]["Chef Development Kit v0.7.0"][:installdate]).to eq("20150925") + + expect(plugin[:packages]["NXLOG-CE"][:version]).to eq("2.8.1248") + expect(plugin[:packages]["NXLOG-CE"][:publisher]).to eq("nxsec.com") + expect(plugin[:packages]["NXLOG-CE"][:installdate]).to eq("20150511") + end end before(:each) do allow(plugin).to receive(:collect_os).and_return(:windows) - expect_any_instance_of(WmiLite::Wmi).to receive(:instances_of).with("Win32_Product").and_return(win32_product_output) - plugin.run + allow(win_reg_double).to receive(:open).with(win_reg_keys[0]).and_return(win_reg_output[0]) + allow(win_reg_double).to receive(:open).with(win_reg_keys[1]).and_return(win_reg_output[1]) + allow(win_reg_double).to receive(:each_key).and_yield(win_reg_keys[0], 0).and_yield(win_reg_keys[1], 1) end - it "gets package info" do - expect(plugin[:packages]["Chef Development Kit v0.7.0"][:version]).to eq("0.7.0.1") - expect(plugin[:packages]["Chef Development Kit v0.7.0"][:vendor]).to eq("\"Chef Software, Inc. <maintainers@chef.io>\"") - expect(plugin[:packages]["Chef Development Kit v0.7.0"][:installdate]).to eq("20150925") + describe "on 32 bit ruby" do + before do + stub_const("::RbConfig::CONFIG", { "target_cpu" => "i386" } ) + allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).with('Software\Microsoft\Windows\CurrentVersion\Uninstall', i386_reg_type).and_yield(win_reg_double) + allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).with('Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall', i386_reg_type).and_yield(win_reg_double) + end + it_behaves_like "windows_package_plugin" + end - expect(plugin[:packages]["NXLOG-CE"][:version]).to eq("2.8.1248") - expect(plugin[:packages]["NXLOG-CE"][:vendor]).to eq("nxsec.com") - expect(plugin[:packages]["NXLOG-CE"][:installdate]).to eq("20150511") + describe "on 64 bit ruby" do + before do + stub_const("::RbConfig::CONFIG", { "target_cpu" => "x86_64" } ) + allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).with('Software\Microsoft\Windows\CurrentVersion\Uninstall', x86_64_reg_type).and_yield(win_reg_double) + allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).with('Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall', x86_64_reg_type).and_yield(win_reg_double) + end + it_behaves_like "windows_package_plugin" + end + + describe "on unknown ruby" do + before do + stub_const("::RbConfig::CONFIG", { "target_cpu" => nil } ) + allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).with('Software\Microsoft\Windows\CurrentVersion\Uninstall', Win32::Registry::KEY_READ).and_yield(win_reg_double) + allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).with('Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall', Win32::Registry::KEY_READ).and_yield(win_reg_double) + end + it_behaves_like "windows_package_plugin" end end |