mirror of
https://github.com/inspec/inspec
synced 2024-11-27 15:10:44 +00:00
Merge pull request #970 from chef/ksubrama/package
Speed up windows package lookup
This commit is contained in:
commit
8825b71412
6 changed files with 58 additions and 18 deletions
|
@ -184,14 +184,27 @@ module Inspec::Resources
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Determines the installed packages on Windows
|
# Determines the installed packages on Windows using the Windows package registry entries.
|
||||||
# Currently we use 'Get-WmiObject -Class Win32_Product' as a detection method
|
|
||||||
# TODO: evaluate if alternative methods as proposed by Microsoft are still valid:
|
|
||||||
# @see: http://blogs.technet.com/b/heyscriptingguy/archive/2013/11/15/use-powershell-to-find-installed-software.aspx
|
# @see: http://blogs.technet.com/b/heyscriptingguy/archive/2013/11/15/use-powershell-to-find-installed-software.aspx
|
||||||
class WindowsPkg < PkgManagement
|
class WindowsPkg < PkgManagement
|
||||||
def info(package_name)
|
def info(package_name)
|
||||||
|
search_paths = [
|
||||||
|
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
|
||||||
|
'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
|
||||||
|
]
|
||||||
|
|
||||||
|
# add 64 bit search paths
|
||||||
|
if inspec.os.arch == 'x86_64'
|
||||||
|
search_paths << 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
|
||||||
|
search_paths << 'HKCU:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
|
||||||
|
end
|
||||||
|
|
||||||
# Find the package
|
# Find the package
|
||||||
cmd = inspec.command("Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -eq '#{package_name}'} | Select-Object -Property Name,Version,Vendor,PackageCode,Caption,Description | ConvertTo-Json")
|
cmd = inspec.command <<-EOF.gsub(/^\s*/, '')
|
||||||
|
Get-ItemProperty (@("#{search_paths.join('", "')}") | Where-Object { Test-Path $_ }) |
|
||||||
|
Where-Object { $_.DisplayName -like "#{package_name}*" -or $_.PSChildName -like "#{package_name}" } |
|
||||||
|
Select-Object -Property DisplayName,DisplayVersion | ConvertTo-Json
|
||||||
|
EOF
|
||||||
|
|
||||||
begin
|
begin
|
||||||
package = JSON.parse(cmd.stdout)
|
package = JSON.parse(cmd.stdout)
|
||||||
|
@ -199,10 +212,13 @@ module Inspec::Resources
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# What if we match multiple packages? just pick the first one for now.
|
||||||
|
package = package[0] if package.is_a?(Array)
|
||||||
|
|
||||||
{
|
{
|
||||||
name: package['Name'],
|
name: package['DisplayName'],
|
||||||
installed: true,
|
installed: true,
|
||||||
version: package['Version'],
|
version: package['DisplayVersion'],
|
||||||
type: 'windows',
|
type: 'windows',
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -173,7 +173,7 @@ class MockLoader
|
||||||
# ports on freebsd
|
# ports on freebsd
|
||||||
'sockstat -46l' => cmd.call('sockstat'),
|
'sockstat -46l' => cmd.call('sockstat'),
|
||||||
# packages on windows
|
# packages on windows
|
||||||
"Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -eq 'Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.6161'} | Select-Object -Property Name,Version,Vendor,PackageCode,Caption,Description | ConvertTo-Json" => cmd.call('win32_product'),
|
'f18912b2e36924b367a110c31da6b835a1c217cd10014c7312b7435bf79a601c' => cmd.call('get-item-property-package'),
|
||||||
# service status upstart on ubuntu
|
# service status upstart on ubuntu
|
||||||
'initctl status ssh' => cmd.call('initctl-status-ssh'),
|
'initctl status ssh' => cmd.call('initctl-status-ssh'),
|
||||||
# service config for upstart on ubuntu
|
# service config for upstart on ubuntu
|
||||||
|
|
|
@ -28,3 +28,31 @@ end
|
||||||
describe package('nginx') do
|
describe package('nginx') do
|
||||||
it { should_not be_installed }
|
it { should_not be_installed }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# the following test will iterate over all packages retrieved via WMI and verifies that the
|
||||||
|
# optimized package implementation is returning the same results
|
||||||
|
if os.windows?
|
||||||
|
# compare optimized version with wmi results
|
||||||
|
packages = powershell("Get-WmiObject -Class Win32_Product | % { $_.Name }").stdout.strip.split("\n")
|
||||||
|
|
||||||
|
packages.each { |pkg|
|
||||||
|
package_name = pkg.strip
|
||||||
|
# get wmi package information
|
||||||
|
cmd = powershell("Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -eq '#{package_name}'} | Select-Object -Property Name,Version,Vendor,PackageCode,Caption,Description | ConvertTo-Json")
|
||||||
|
wmi_package = JSON.parse(cmd.stdout)
|
||||||
|
wmi_info = {
|
||||||
|
name: wmi_package['Name'],
|
||||||
|
installed: true,
|
||||||
|
version: wmi_package['Version'],
|
||||||
|
type: 'windows',
|
||||||
|
}
|
||||||
|
|
||||||
|
# get registry package information
|
||||||
|
info = package(package_name).info
|
||||||
|
|
||||||
|
# compare results
|
||||||
|
describe wmi_info do
|
||||||
|
it { should eq info}
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
4
test/unit/mock/cmd/get-item-property-package
Normal file
4
test/unit/mock/cmd/get-item-property-package
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"DisplayName": "Chef Client v12.12.15",
|
||||||
|
"DisplayVersion": "12.12.15.1"
|
||||||
|
}
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"Name": "Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.6161",
|
|
||||||
"Version": "9.0.30729.6161",
|
|
||||||
"Vendor": "Microsoft Corporation",
|
|
||||||
"PackageCode": "{9C7D912C-6EDE-47A4-962E-7A83663440BA}",
|
|
||||||
"Caption": "Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.6161",
|
|
||||||
"Description": "Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.6161"
|
|
||||||
}
|
|
|
@ -53,10 +53,10 @@ describe 'Inspec::Resources::Package' do
|
||||||
|
|
||||||
# windows
|
# windows
|
||||||
it 'verify windows package parsing' do
|
it 'verify windows package parsing' do
|
||||||
resource = MockLoader.new(:windows).load_resource('package', 'Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.6161')
|
resource = MockLoader.new(:windows).load_resource('package', 'Chef Client v12.12.15')
|
||||||
pkg = { name: 'Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.6161', installed: true, version: '9.0.30729.6161', type: 'windows' }
|
pkg = { name: 'Chef Client v12.12.15', installed: true, version: '12.12.15.1', type: 'windows' }
|
||||||
_(resource.installed?).must_equal true
|
_(resource.installed?).must_equal true
|
||||||
_(resource.version).must_equal '9.0.30729.6161'
|
_(resource.version).must_equal '12.12.15.1'
|
||||||
_(resource.info).must_equal pkg
|
_(resource.info).must_equal pkg
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue