inspec/lib/resources/packages.rb

110 lines
3.2 KiB
Ruby
Raw Normal View History

add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
# encoding: utf-8
# copyright: 2017, Chef Software, Inc. <legal@chef.io>
require 'utils/filter'
module Inspec::Resources
class Packages < Inspec.resource(1)
name 'packages'
supports platform: 'unix'
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
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)
os = inspec.os
if os.debian?
@pkgs = Debs.new(inspec)
elsif os.redhat? || %w{suse amazon fedora}.include?(os[:family])
@pkgs = Rpms.new(inspec)
else
return skip_resource "The packages resource is not yet supported on OS #{inspec.os.name}"
end
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
@pattern = pattern_regexp(pattern)
all_pkgs = @pkgs.build_package_list
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
@list = all_pkgs.find_all do |hm|
hm[:name] =~ @pattern
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
end
end
def to_s
"Packages #{@pattern.class == String ? @pattern : @pattern.inspect}"
end
filter = FilterTable.create
filter.register_column(:statuses, field: 'status', style: :simple)
.register_column(:names, field: 'name')
.register_column(:versions, field: 'version')
.register_column(:architectures, field: 'architecture')
.install_filter_methods_on_resource(self, :filtered_packages)
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
private
def pattern_regexp(p)
if p.class == String
Regexp.new(Regexp.escape(p))
elsif p.class == Regexp
p
else
raise 'Invalid name argument to packages resource, please use a "string" or /regexp/'
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
end
end
def filtered_packages
warn "The packages resource is not yet supported on OS #{inspec.os.name}" if resource_skipped?
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
@list
end
end
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
class PkgsManagement
PackageStruct = Struct.new(:status, :name, :version, :architecture)
attr_reader :inspec
def initialize(inspec)
@inspec = inspec
end
end
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
# Debian / Ubuntu
class Debs < PkgsManagement
def build_package_list
# use two spaces as delimiter in case any of the fields has a space in it
command = "dpkg-query -W -f='${db:Status-Abbrev} ${Package} ${Version} ${Architecture}\\n'"
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
cmd = inspec.command(command)
all = cmd.stdout.split("\n")
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
return [] if all.nil?
all.map do |m|
a = m.split(/ {2,}/)
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
a[0] = 'installed' if a[0] =~ /^.i/
a[2] = a[2].split(':').last
PackageStruct.new(*a)
end
end
end
# RedHat family
class Rpms < PkgsManagement
def build_package_list
# use two spaces as delimiter in case any of the fields has a space in it
command = "rpm -qa --queryformat '%{NAME} %{VERSION}-%{RELEASE} %{ARCH}\\n'" # rubocop:disable Style/FormatStringToken
cmd = inspec.command(command)
all = cmd.stdout.split("\n")
return [] if all.nil?
all.map do |m|
a = m.split(' ')
a.unshift('installed')
PackageStruct.new(*a)
add "packages" resource This pull request adds a packages resource so that we can check for pattern matches against all the packages on a system. This initially implements only dpkg support for debian-based platforms so we can cover this use case: ```ruby describe packages(/^xserver-xorg.*/) do its("list") { should be_empty } end ``` This uses FilterTable so we can supply additional queries, too. ```ruby describe packages(/vi.+/).where { status != 'installed' } do its('statuses') { should be_empty } end ``` Users can specify the name as a string or a regular expression. If it is a string, we will escape it and convert it to a regular expression to use in matching against the full returned list of packages. If it is a regular expression, we take that as is and use it to filter the results. While some package management systems such as `dpkg` can take a shell glob argument to filter their results, we eschew this and require a regular expression to match multiple package names because we will need this to work across other platforms in the future. This means that the following: ```ruby packages("vim") ``` Will return *all* the "vim" packages on the system. The `packages` resource will take `"vim"`, turn it into `/vim/`, and greedily match anything with "vim" in the name. To match only a single package named `vim`, it needs to be an anchored regular expression. ```ruby packages(/^vim$/) ``` Signed-off-by: Joshua Timberman <joshua@chef.io> Use entries instead of list Added a few more tests and non installed package in output Signed-off-by: Alex Pop <apop@chef.io> fix lint Signed-off-by: Alex Pop <apop@chef.io> Signed-off-by: Joshua Timberman <joshua@chef.io>
2017-02-03 20:42:55 +00:00
end
end
end
end