summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2016-05-03 10:24:15 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2016-05-03 11:16:10 -0700
commitc564889f5fda607185ba7b7ceebeaa15888a97cd (patch)
treeecd579c9b45d0c38bf6bd8e5328f959850dcb37c
parent98ead2710216d29774c50a0d80fca050919a67a2 (diff)
downloadchef-c564889f5fda607185ba7b7ceebeaa15888a97cd.tar.gz
multipackage apt provider
-rw-r--r--lib/chef/provider/package.rb2
-rw-r--r--lib/chef/provider/package/apt.rb63
-rw-r--r--spec/unit/provider/package/apt_spec.rb54
-rw-r--r--spec/unit/provider/package_spec.rb14
4 files changed, 73 insertions, 60 deletions
diff --git a/lib/chef/provider/package.rb b/lib/chef/provider/package.rb
index ca9b526920..73a5d36bab 100644
--- a/lib/chef/provider/package.rb
+++ b/lib/chef/provider/package.rb
@@ -558,7 +558,7 @@ class Chef
# @param args [String] variable number of string arguments
# @return [String] nicely concatenated string or empty string
def a_to_s(*args)
- args.reject { |i| i.nil? || i == "" }.join(" ")
+ args.flatten.reject { |i| i.nil? || i == "" }.join(" ")
end
end
end
diff --git a/lib/chef/provider/package/apt.rb b/lib/chef/provider/package/apt.rb
index ac730202b8..cfaac0addb 100644
--- a/lib/chef/provider/package/apt.rb
+++ b/lib/chef/provider/package/apt.rb
@@ -17,13 +17,13 @@
#
require "chef/provider/package"
-require "chef/mixin/command"
-require "chef/resource/package"
+require "chef/resource/apt_package"
class Chef
class Provider
class Package
class Apt < Chef::Provider::Package
+ use_multipackage_api
provides :package, platform_family: "debian"
provides :apt_package, os: "linux"
@@ -37,24 +37,24 @@ class Chef
end
def load_current_resource
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
- check_all_packages_state(@new_resource.package_name)
- @current_resource
+ @current_resource = Chef::Resource::AptPackage.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
+ check_all_packages_state(new_resource.package_name)
+ current_resource
end
def define_resource_requirements
super
requirements.assert(:all_actions) do |a|
- a.assertion { !@new_resource.source }
+ a.assertion { !new_resource.source }
a.failure_message(Chef::Exceptions::Package, "apt package provider cannot handle source attribute. Use dpkg provider instead")
end
end
def default_release_options
# Use apt::Default-Release option only if provider supports it
- "-o APT::Default-Release=#{@new_resource.default_release}" if @new_resource.respond_to?(:default_release) && @new_resource.default_release
+ "-o APT::Default-Release=#{new_resource.default_release}" if new_resource.respond_to?(:default_release) && new_resource.default_release
end
def check_package_state(pkg)
@@ -63,15 +63,15 @@ class Chef
installed_version = nil
candidate_version = nil
- shell_out_with_timeout!("apt-cache#{expand_options(default_release_options)} policy #{pkg}").stdout.each_line do |line|
+ run_noninteractive("apt-cache", default_release_options, "policy", pkg).stdout.each_line do |line|
case line
when /^\s{2}Installed: (.+)$/
installed_version = $1
if installed_version == "(none)"
- Chef::Log.debug("#{@new_resource} current version is nil")
+ Chef::Log.debug("#{new_resource} current version is nil")
installed_version = nil
else
- Chef::Log.debug("#{@new_resource} current version is #{installed_version}")
+ Chef::Log.debug("#{new_resource} current version is #{installed_version}")
installed = true
end
when /^\s{2}Candidate: (.+)$/
@@ -79,7 +79,7 @@ class Chef
if candidate_version == "(none)"
# This may not be an appropriate assumption, but it shouldn't break anything that already worked -- btm
is_virtual_package = true
- showpkg = shell_out_with_timeout!("apt-cache showpkg #{pkg}").stdout
+ showpkg = run_noninteractive("apt-cache showpkg", pkg).stdout
providers = Hash.new
showpkg.rpartition(/Reverse Provides: ?#{$/}/)[2].each_line do |line|
provider, version = line.split
@@ -87,16 +87,16 @@ class Chef
end
# Check if the package providing this virtual package is installed
num_providers = providers.length
- raise Chef::Exceptions::Package, "#{@new_resource.package_name} has no candidate in the apt-cache" if num_providers == 0
+ raise Chef::Exceptions::Package, "#{new_resource.package_name} has no candidate in the apt-cache" if num_providers == 0
# apt will only install a virtual package if there is a single providing package
- raise Chef::Exceptions::Package, "#{@new_resource.package_name} is a virtual package provided by #{num_providers} packages, you must explicitly select one to install" if num_providers > 1
+ raise Chef::Exceptions::Package, "#{new_resource.package_name} is a virtual package provided by #{num_providers} packages, you must explicitly select one to install" if num_providers > 1
# Check if the package providing this virtual package is installed
- Chef::Log.info("#{@new_resource} is a virtual package, actually acting on package[#{providers.keys.first}]")
+ Chef::Log.info("#{new_resource} is a virtual package, actually acting on package[#{providers.keys.first}]")
ret = check_package_state(providers.keys.first)
installed = ret[:installed]
installed_version = ret[:installed_version]
else
- Chef::Log.debug("#{@new_resource} candidate version is #{$1}")
+ Chef::Log.debug("#{new_resource} candidate version is #{$1}")
end
end
end
@@ -126,23 +126,21 @@ class Chef
@candidate_version = []
final_installed_version = []
[package].flatten.each do |pkg|
- @candidate_version << candidate_version[pkg]
+ candidate_version << candidate_version[pkg]
final_installed_version << installed_version[pkg]
end
- @current_resource.version(final_installed_version)
+ current_resource.version(final_installed_version)
else
@candidate_version = candidate_version[package]
- @current_resource.version(installed_version[package])
+ current_resource.version(installed_version[package])
end
end
def install_package(name, version)
- name_array = [ name ].flatten
- version_array = [ version ].flatten
- package_name = name_array.zip(version_array).map do |n, v|
+ package_name = name.zip(version).map do |n, v|
is_virtual_package[n] ? n : "#{n}=#{v}"
end.join(" ")
- run_noninteractive("apt-get -q -y#{expand_options(default_release_options)}#{expand_options(@new_resource.options)} install #{package_name}")
+ run_noninteractive("apt-get -q -y", default_release_options, new_resource.options, "install", package_name)
end
def upgrade_package(name, version)
@@ -150,24 +148,21 @@ class Chef
end
def remove_package(name, version)
- package_name = [ name ].flatten.join(" ")
- run_noninteractive("apt-get -q -y#{expand_options(@new_resource.options)} remove #{package_name}")
+ run_noninteractive("apt-get -q -y", new_resource.options, "remove", name)
end
def purge_package(name, version)
- package_name = [ name ].flatten.join(" ")
- run_noninteractive("apt-get -q -y#{expand_options(@new_resource.options)} purge #{package_name}")
+ run_noninteractive("apt-get -q -y", new_resource.options, "purge", name)
end
def preseed_package(preseed_file)
- Chef::Log.info("#{@new_resource} pre-seeding package installation instructions")
- run_noninteractive("debconf-set-selections #{preseed_file}")
+ Chef::Log.info("#{new_resource} pre-seeding package installation instructions")
+ run_noninteractive("debconf-set-selections", preseed_file)
end
def reconfig_package(name, version)
- package_name = [ name ].flatten.join(" ")
- Chef::Log.info("#{@new_resource} reconfiguring")
- run_noninteractive("dpkg-reconfigure #{package_name}")
+ Chef::Log.info("#{new_resource} reconfiguring")
+ run_noninteractive("dpkg-reconfigure", name)
end
private
@@ -175,8 +170,8 @@ class Chef
# Runs command via shell_out with magic environment to disable
# interactive prompts. Command is run with default localization rather
# than forcing locale to "C", so command output may not be stable.
- def run_noninteractive(command)
- shell_out_with_timeout!(command, :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil })
+ def run_noninteractive(*args)
+ shell_out_with_timeout!(a_to_s(*args), :env => { "DEBIAN_FRONTEND" => "noninteractive" })
end
end
diff --git a/spec/unit/provider/package/apt_spec.rb b/spec/unit/provider/package/apt_spec.rb
index b5f0646b79..3fd48e46e8 100644
--- a/spec/unit/provider/package/apt_spec.rb
+++ b/spec/unit/provider/package/apt_spec.rb
@@ -52,6 +52,7 @@ irssi:
it "should create a current resource with the name of the new_resource" do
expect(@provider).to receive(:shell_out!).with(
"apt-cache policy #{@new_resource.package_name}",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(@shell_out)
@provider.load_current_resource
@@ -95,6 +96,7 @@ libmysqlclient15-dev:
virtual_package = double(:stdout => virtual_package_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
"apt-cache policy libmysqlclient15-dev",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(virtual_package)
showpkg_out = <<-SHOWPKG_STDOUT
@@ -118,6 +120,7 @@ libmysqlclient-dev 5.1.41-3ubuntu12
showpkg = double(:stdout => showpkg_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
"apt-cache showpkg libmysqlclient15-dev",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(showpkg)
real_package_out = <<-RPKG_STDOUT
@@ -136,6 +139,7 @@ libmysqlclient-dev:
real_package = double(:stdout => real_package_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
"apt-cache policy libmysqlclient-dev",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(real_package)
@provider.load_current_resource
@@ -152,6 +156,7 @@ mp3-decoder:
virtual_package = double(:stdout => virtual_package_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
"apt-cache policy mp3-decoder",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(virtual_package)
showpkg_out = <<-SHOWPKG_STDOUT
@@ -178,6 +183,7 @@ mpg123 1.12.1-0ubuntu1
showpkg = double(:stdout => showpkg_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
"apt-cache showpkg mp3-decoder",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(showpkg)
expect { @provider.load_current_resource }.to raise_error(Chef::Exceptions::Package)
@@ -191,6 +197,7 @@ mpg123 1.12.1-0ubuntu1
allow(@new_resource).to receive(:provider).and_return(nil)
expect(@provider).to receive(:shell_out!).with(
"apt-cache -o APT::Default-Release=lenny-backports policy irssi",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(@shell_out)
@provider.load_current_resource
@@ -200,11 +207,12 @@ mpg123 1.12.1-0ubuntu1
@new_resource.source "pluto"
expect(@provider).to receive(:shell_out!).with(
"apt-cache policy #{@new_resource.package_name}",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" } ,
:timeout => @timeout
).and_return(@shell_out)
@provider.load_current_resource
@provider.define_resource_requirements
- expect(@provider).to receive(:shell_out!).with("apt-cache policy irssi", { :timeout => 900 }).and_return(@shell_out)
+ expect(@provider).to receive(:shell_out!).with("apt-cache policy irssi", { :env => { "DEBIAN_FRONTEND" => "noninteractive" }, :timeout => 900 }).and_return(@shell_out)
expect { @provider.run_action(:install) }.to raise_error(Chef::Exceptions::Package)
end
end
@@ -219,20 +227,20 @@ mpg123 1.12.1-0ubuntu1
it "should run apt-get install with the package name and version" do
expect(@provider).to receive(:shell_out!). with(
"apt-get -q -y install irssi=0.8.12-7",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
- @provider.install_package("irssi", "0.8.12-7")
+ @provider.install_package(["irssi"], ["0.8.12-7"])
end
it "should run apt-get install with the package name and version and options if specified" do
expect(@provider).to receive(:shell_out!).with(
"apt-get -q -y --force-yes install irssi=0.8.12-7",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@new_resource.options("--force-yes")
- @provider.install_package("irssi", "0.8.12-7")
+ @provider.install_package(["irssi"], ["0.8.12-7"])
end
it "should run apt-get install with the package name and version and default_release if there is one and provider is explicitly defined" do
@@ -244,19 +252,19 @@ mpg123 1.12.1-0ubuntu1
expect(@provider).to receive(:shell_out!).with(
"apt-get -q -y -o APT::Default-Release=lenny-backports install irssi=0.8.12-7",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
- @provider.install_package("irssi", "0.8.12-7")
+ @provider.install_package(["irssi"], ["0.8.12-7"])
end
end
describe resource_klass, "upgrade_package" do
it "should run install_package with the name and version" do
- expect(@provider).to receive(:install_package).with("irssi", "0.8.12-7")
- @provider.upgrade_package("irssi", "0.8.12-7")
+ expect(@provider).to receive(:install_package).with(["irssi"], ["0.8.12-7"])
+ @provider.upgrade_package(["irssi"], ["0.8.12-7"])
end
end
@@ -265,21 +273,21 @@ mpg123 1.12.1-0ubuntu1
it "should run apt-get remove with the package name" do
expect(@provider).to receive(:shell_out!).with(
"apt-get -q -y remove irssi",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
- @provider.remove_package("irssi", "0.8.12-7")
+ @provider.remove_package(["irssi"], ["0.8.12-7"])
end
it "should run apt-get remove with the package name and options if specified" do
expect(@provider).to receive(:shell_out!).with(
"apt-get -q -y --force-yes remove irssi",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@new_resource.options("--force-yes")
- @provider.remove_package("irssi", "0.8.12-7")
+ @provider.remove_package(["irssi"], ["0.8.12-7"])
end
end
@@ -288,21 +296,21 @@ mpg123 1.12.1-0ubuntu1
it "should run apt-get purge with the package name" do
expect(@provider).to receive(:shell_out!).with(
"apt-get -q -y purge irssi",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
- @provider.purge_package("irssi", "0.8.12-7")
+ @provider.purge_package(["irssi"], ["0.8.12-7"])
end
it "should run apt-get purge with the package name and options if specified" do
expect(@provider).to receive(:shell_out!).with(
"apt-get -q -y --force-yes purge irssi",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@new_resource.options("--force-yes")
- @provider.purge_package("irssi", "0.8.12-7")
+ @provider.purge_package(["irssi"], ["0.8.12-7"])
end
end
@@ -316,7 +324,7 @@ mpg123 1.12.1-0ubuntu1
expect(@provider).to receive(:shell_out!).with(
"debconf-set-selections /tmp/irssi-0.8.12-7.seed",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -326,7 +334,7 @@ mpg123 1.12.1-0ubuntu1
it "should run debconf-set-selections on the preseed file if it has changed" do
expect(@provider).to receive(:shell_out!).with(
"debconf-set-selections /tmp/irssi-0.8.12-7.seed",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
file = @provider.get_preseed_file("irssi", "0.8.12-7")
@@ -347,7 +355,7 @@ mpg123 1.12.1-0ubuntu1
it "should run dpkg-reconfigure package" do
expect(@provider).to receive(:shell_out!).with(
"dpkg-reconfigure irssi",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@provider.reconfig_package("irssi", "0.8.12-7")
@@ -359,10 +367,10 @@ mpg123 1.12.1-0ubuntu1
@provider.is_virtual_package["libmysqlclient-dev"] = true
expect(@provider).to receive(:shell_out!).with(
"apt-get -q -y install libmysqlclient-dev",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
- @provider.install_package("libmysqlclient-dev", "not_a_real_version")
+ @provider.install_package(["libmysqlclient-dev"], ["not_a_real_version"])
end
end
@@ -373,7 +381,7 @@ mpg123 1.12.1-0ubuntu1
@provider.is_virtual_package["irssi"] = false
expect(@provider).to receive(:shell_out!).with(
"apt-get -q -y install libmysqlclient-dev irssi=0.8.12-7",
- :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil },
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@provider.install_package(["libmysqlclient-dev", "irssi"], ["not_a_real_version", "0.8.12-7"])
diff --git a/spec/unit/provider/package_spec.rb b/spec/unit/provider/package_spec.rb
index abf0322868..393b5f6853 100644
--- a/spec/unit/provider/package_spec.rb
+++ b/spec/unit/provider/package_spec.rb
@@ -458,8 +458,18 @@ describe "Subclass with use_multipackage_api" do
expect(provider.use_multipackage_api?).to be true
end
- it "offers a_to_s to subclasses to convert an array of strings to a single string" do
- expect(provider.send(:a_to_s, "a", nil, "b", "", "c", " ", "d e", "f-g")).to eq("a b c d e f-g")
+ context "#a_to_s utility for subclasses" do
+ it "converts varargs of strings to a single string" do
+ expect(provider.send(:a_to_s, "a", nil, "b", "", "c", " ", "d e", "f-g")).to eq("a b c d e f-g")
+ end
+
+ it "converts an array of strings to a single string" do
+ expect(provider.send(:a_to_s, ["a", nil, "b", "", "c", " ", "d e", "f-g"])).to eq("a b c d e f-g")
+ end
+
+ it "converts a mishmash of array args to a single string" do
+ expect(provider.send(:a_to_s, "a", [ nil, "b", "", [ "c" ] ], " ", [ "d e", "f-g" ])).to eq("a b c d e f-g")
+ end
end
it "when user passes string to package_name, passes arrays to install_package" do