mirror of
https://github.com/inspec/inspec
synced 2024-11-15 09:27:20 +00:00
Merge pull request #1458 from chef/jtimberman/packages-resource
add "packages" resource
This commit is contained in:
commit
e41ec1f2a1
5 changed files with 161 additions and 0 deletions
|
@ -107,6 +107,7 @@ require 'resources/oneget'
|
||||||
require 'resources/os'
|
require 'resources/os'
|
||||||
require 'resources/os_env'
|
require 'resources/os_env'
|
||||||
require 'resources/package'
|
require 'resources/package'
|
||||||
|
require 'resources/packages'
|
||||||
require 'resources/parse_config'
|
require 'resources/parse_config'
|
||||||
require 'resources/passwd'
|
require 'resources/passwd'
|
||||||
require 'resources/pip'
|
require 'resources/pip'
|
||||||
|
|
86
lib/resources/packages.rb
Normal file
86
lib/resources/packages.rb
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
# copyright: 2017, Chef Software, Inc. <legal@chef.io>
|
||||||
|
# author: Joshua Timberman
|
||||||
|
# author: Alex Pop
|
||||||
|
# license: All rights reserved
|
||||||
|
|
||||||
|
require 'utils/filter'
|
||||||
|
|
||||||
|
module Inspec::Resources
|
||||||
|
class Packages < Inspec.resource(1)
|
||||||
|
name 'packages'
|
||||||
|
desc 'Use the packages InSpec audit resource to test properties for multiple packages installed on the system'
|
||||||
|
example "
|
||||||
|
describe packages(/xserver-xorg.*/) do
|
||||||
|
its('entries') { should be_empty }
|
||||||
|
end
|
||||||
|
describe packages('vim').entries.length do
|
||||||
|
it { should be > 1 }
|
||||||
|
end
|
||||||
|
describe packages(/vi.+/).where { status != 'installed' } do
|
||||||
|
its('statuses') { should be_empty }
|
||||||
|
end
|
||||||
|
"
|
||||||
|
|
||||||
|
def initialize(pattern)
|
||||||
|
@pattern = pattern_regexp(pattern)
|
||||||
|
all_pkgs = package_list
|
||||||
|
@list = all_pkgs.find_all do |hm|
|
||||||
|
hm[:name] =~ pattern_regexp(pattern)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"Packages #{@pattern.class == String ? @pattern : @pattern.inspect}"
|
||||||
|
end
|
||||||
|
|
||||||
|
filter = FilterTable.create
|
||||||
|
filter.add_accessor(:where)
|
||||||
|
.add_accessor(:entries)
|
||||||
|
.add(:statuses, field: 'status', style: :simple)
|
||||||
|
.add(:names, field: 'name')
|
||||||
|
.add(:versions, field: 'version')
|
||||||
|
.connect(self, :filtered_packages)
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def pattern_regexp(p)
|
||||||
|
if p.class == String
|
||||||
|
Regexp.new(Regexp.escape(p))
|
||||||
|
elsif p.class == Regexp
|
||||||
|
p
|
||||||
|
else
|
||||||
|
fail 'invalid name argument to packages resource, please use a "string" or /regexp/'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def filtered_packages
|
||||||
|
@list
|
||||||
|
end
|
||||||
|
|
||||||
|
def package_list
|
||||||
|
os = inspec.os
|
||||||
|
|
||||||
|
if os.debian?
|
||||||
|
command = "dpkg-query -W -f='${db:Status-Abbrev} ${Package} ${Version}\\n'"
|
||||||
|
else
|
||||||
|
fail "packages resource is not yet supported on #{os.name}"
|
||||||
|
end
|
||||||
|
build_package_list(command)
|
||||||
|
end
|
||||||
|
|
||||||
|
Package = Struct.new(:status, :name, :version)
|
||||||
|
|
||||||
|
def build_package_list(command)
|
||||||
|
cmd = inspec.command(command)
|
||||||
|
all = cmd.stdout.split("\n")[1..-1]
|
||||||
|
return [] if all.nil?
|
||||||
|
all.map do |m|
|
||||||
|
a = m.split
|
||||||
|
a[0] = 'installed' if a[0] =~ /^.i/
|
||||||
|
a[2] = a[2].split(':').last
|
||||||
|
Package.new(*a)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -50,6 +50,7 @@ class MockLoader
|
||||||
ubuntu1204: { name: 'ubuntu', family: 'debian', release: '12.04', arch: 'x86_64' },
|
ubuntu1204: { name: 'ubuntu', family: 'debian', release: '12.04', arch: 'x86_64' },
|
||||||
ubuntu1404: { name: 'ubuntu', family: 'debian', release: '14.04', arch: 'x86_64' },
|
ubuntu1404: { name: 'ubuntu', family: 'debian', release: '14.04', arch: 'x86_64' },
|
||||||
ubuntu1504: { name: 'ubuntu', family: 'debian', release: '15.04', arch: 'x86_64' },
|
ubuntu1504: { name: 'ubuntu', family: 'debian', release: '15.04', arch: 'x86_64' },
|
||||||
|
ubuntu1604: { name: 'ubuntu', family: 'debian', release: '16.04', arch: 'x86_64' },
|
||||||
mint17: { name: 'linuxmint', family: 'debian', release: '17.3', arch: 'x86_64' },
|
mint17: { name: 'linuxmint', family: 'debian', release: '17.3', arch: 'x86_64' },
|
||||||
mint18: { name: 'linuxmint', family: 'debian', release: '18', arch: 'x86_64' },
|
mint18: { name: 'linuxmint', family: 'debian', release: '18', arch: 'x86_64' },
|
||||||
windows: { name: 'windows', family: 'windows', release: '6.2.9200', arch: 'x86_64' },
|
windows: { name: 'windows', family: 'windows', release: '6.2.9200', arch: 'x86_64' },
|
||||||
|
@ -249,6 +250,8 @@ class MockLoader
|
||||||
'pkginfo -l SUNWzfsr' => cmd.call('pkginfo-l-SUNWzfsr'),
|
'pkginfo -l SUNWzfsr' => cmd.call('pkginfo-l-SUNWzfsr'),
|
||||||
# solaris 11 package manager
|
# solaris 11 package manager
|
||||||
'pkg info system/file-system/zfs' => cmd.call('pkg-info-system-file-system-zfs'),
|
'pkg info system/file-system/zfs' => cmd.call('pkg-info-system-file-system-zfs'),
|
||||||
|
# dpkg-query package list
|
||||||
|
"dpkg-query -W -f='${db:Status-Abbrev} ${Package} ${Version}\\n'" => cmd.call('dpkg-query-W'),
|
||||||
# port netstat on solaris 10 & 11
|
# port netstat on solaris 10 & 11
|
||||||
'netstat -an -f inet -f inet6' => cmd.call('s11-netstat-an-finet-finet6'),
|
'netstat -an -f inet -f inet6' => cmd.call('s11-netstat-an-finet-finet6'),
|
||||||
# xinetd configuration
|
# xinetd configuration
|
||||||
|
|
12
test/unit/mock/cmd/dpkg-query-W
Normal file
12
test/unit/mock/cmd/dpkg-query-W
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
ii bash 4.3-14ubuntu1.1
|
||||||
|
rc fakeroot 1.20.2-1ubuntu1
|
||||||
|
rc libfakeroot 1.20.2-1ubuntu1
|
||||||
|
ii overlayroot 0.27ubuntu1.2
|
||||||
|
ii vim 2:7.4.1689-3ubuntu1.2
|
||||||
|
ii vim-common 2:7.4.1689-3ubuntu1.2
|
||||||
|
ii xorg 1:7.7+13ubuntu3
|
||||||
|
ii xorg-docs-core 1:1.7.1-1ubuntu1
|
||||||
|
ii xserver-common 2:1.18.4-0ubuntu0.2
|
||||||
|
ii xserver-xorg 1:7.7+13ubuntu3
|
||||||
|
ii xserver-xorg-core 2:1.18.4-0ubuntu0.2
|
||||||
|
ii xserver-xorg-input-all 1:7.7+13ubuntu3
|
59
test/unit/resources/packages_test.rb
Normal file
59
test/unit/resources/packages_test.rb
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
# author: Joshua Timberman
|
||||||
|
|
||||||
|
require 'helper'
|
||||||
|
require 'inspec/resource'
|
||||||
|
|
||||||
|
describe 'Inspec::Resources::Packages' do
|
||||||
|
it 'verify packages resource' do
|
||||||
|
resource = MockLoader.new(:ubuntu1604).load_resource('packages', /^vim$/)
|
||||||
|
_(resource.entries.length).must_equal 1
|
||||||
|
_(resource.entries[0].to_h).must_equal({
|
||||||
|
status: 'installed',
|
||||||
|
name: 'vim',
|
||||||
|
version: '7.4.1689-3ubuntu1.2',
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'package name matches with output (string)' do
|
||||||
|
resource = MockLoader.new(:ubuntu1604).load_resource('packages', 'xserver-xorg')
|
||||||
|
_(resource.to_s).must_equal 'Packages /xserver\\-xorg/'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'packages using where filters' do
|
||||||
|
resource = MockLoader.new(:ubuntu1604).load_resource('packages', /.+root$/)
|
||||||
|
_(resource.entries.length).must_equal 3
|
||||||
|
_(resource.where { status != 'installed' }.names).must_equal(['fakeroot', 'libfakeroot'])
|
||||||
|
_(resource.where { version =~ /^0\.2.+/ }.entries[0].to_h).must_equal({
|
||||||
|
status: "installed",
|
||||||
|
name: "overlayroot",
|
||||||
|
version: "0.27ubuntu1.2",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'package name matches with output (regex)' do
|
||||||
|
resource = MockLoader.new(:ubuntu1604).load_resource('packages', /vim/)
|
||||||
|
_(resource.to_s).must_equal 'Packages /vim/'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a list of packages with a wildcard' do
|
||||||
|
resource = MockLoader.new(:ubuntu1604).load_resource('packages', /^xserver-xorg.*/)
|
||||||
|
_(resource.statuses).must_equal ['installed']
|
||||||
|
_(resource.entries.length).must_equal 3
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
it 'fails on non debian platforms' do
|
||||||
|
proc {
|
||||||
|
resource = MockLoader.new(:centos6).load_resource('packages', 'bash')
|
||||||
|
resource.send(:entries, nil)
|
||||||
|
}.must_raise(RuntimeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails if the packages name is not a string or regexp' do
|
||||||
|
proc {
|
||||||
|
resources = MockLoader.new(:ubuntu1604).load_resource('packages', [:a, :b])
|
||||||
|
resources.send(:entries, nil)
|
||||||
|
}.must_raise(RuntimeError)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue