summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNuo Yan <nuo@opscode.com>2011-06-02 17:37:40 -0700
committerNuo Yan <nuo@opscode.com>2011-06-02 17:37:40 -0700
commit16dd475cd3470de9f1f3818c22916ba6670b806f (patch)
treea1332f34aa428f42c6f443a2c3e689f3eb96c2cb
parent5a4fb459291c7133d81ac731fca3fd45f42a5c07 (diff)
parent3632f292165152bbd3cca59f52323cd0e3ee9fa1 (diff)
downloadchef-16dd475cd3470de9f1f3818c22916ba6670b806f.tar.gz
CHEF-1439: Resolve merge conflict.
-rw-r--r--chef/lib/chef/provider/package/apt.rb63
-rw-r--r--chef/spec/unit/provider/package/apt_spec.rb197
2 files changed, 164 insertions, 96 deletions
diff --git a/chef/lib/chef/provider/package/apt.rb b/chef/lib/chef/provider/package/apt.rb
index 5f7ff0d204..44bb0f158e 100644
--- a/chef/lib/chef/provider/package/apt.rb
+++ b/chef/lib/chef/provider/package/apt.rb
@@ -25,44 +25,57 @@ class Chef
class Package
class Apt < Chef::Provider::Package
+ include Chef::Mixin::ShellOut
+ attr_accessor :virtual
+
def load_current_resource
@current_resource = Chef::Resource::Package.new(@new_resource.name)
@current_resource.package_name(@new_resource.package_name)
+ check_package_state(@new_resource.package_name)
+ @current_resource
+ end
+
+ def check_package_state(package)
+ Chef::Log.debug("Checking package status for #{package}")
+ installed = false
+ depends = false
- Chef::Log.debug("#{@new_resource} checking apt-cache policy")
- status = popen4("apt-cache policy #{@new_resource.package_name}") do |pid, stdin, stdout, stderr|
- stdout.each do |line|
- case line
- when /^\s{2}Installed: (.+)$/
- installed_version = $1
- if installed_version == '(none)'
- Chef::Log.debug("#{@new_resource} current version is nil")
- @current_resource.version(nil)
- else
- Chef::Log.debug("#{@new_resource} current version is #{installed_version}")
- @current_resource.version(installed_version)
- end
- when /^\s{2}Candidate: (.+)$/
- Chef::Log.debug("#{@new_resource} candidate version is #{$1}")
- @candidate_version = $1
+ shell_out!("aptitude show #{package}").stdout.each_line do |line|
+ case line
+ when /^State: installed/
+ installed = true
+ when /^Version: (.*)/
+ @candidate_version = $1
+ if installed
+ @current_resource.version($1)
+ else
+ @current_resource.version(nil)
end
+ when /Depends: ([^\s]*) /
+ depends = $1
+ when /Provided by: ([\w\d\-\.]*)/
+ next if installed
+ virtual_provider = $1
+ virtual_provider = depends if depends
+ Chef::Log.debug("Virtual package provided by #{virtual_provider}")
+ @virtual = true
+ installed = check_package_state(virtual_provider)
+ @candidate_version = virtual_provider
end
end
- unless status.exitstatus == 0
- raise Chef::Exceptions::Package, "apt-cache failed - #{status.inspect}!"
- end
-
- if @candidate_version == "(none)"
+ if @candidate_version.nil?
raise Chef::Exceptions::Package, "apt does not have a version of package #{@new_resource.package_name}"
end
- @current_resource
+ return installed
end
def install_package(name, version)
+ package_name = "#{name}=#{version}"
+ package_name = "#{name} #{@candidate_version}" if @virtual
run_command_with_systems_locale(
- :command => "apt-get -q -y#{expand_options(@new_resource.options)} install #{name}=#{version}",
+ :command => "apt-get -q -y#{expand_options(@new_resource.options)} install #{package_name}",
:environment => {
"DEBIAN_FRONTEND" => "noninteractive"
}
@@ -74,8 +87,10 @@ class Chef
end
def remove_package(name, version)
+ package_name = "#{name}"
+ package_name = "#{name} #{@candidate_version}" if @virtual
run_command_with_systems_locale(
- :command => "apt-get -q -y#{expand_options(@new_resource.options)} remove #{@new_resource.package_name}",
+ :command => "apt-get -q -y#{expand_options(@new_resource.options)} remove #{package_name}",
:environment => {
"DEBIAN_FRONTEND" => "noninteractive"
}
diff --git a/chef/spec/unit/provider/package/apt_spec.rb b/chef/spec/unit/provider/package/apt_spec.rb
index d4298fa374..1eada8fbb3 100644
--- a/chef/spec/unit/provider/package/apt_spec.rb
+++ b/chef/spec/unit/provider/package/apt_spec.rb
@@ -23,94 +23,147 @@ describe Chef::Provider::Package::Apt do
@node = Chef::Node.new
@node.cookbook_collection = {}
@run_context = Chef::RunContext.new(@node, {})
- @new_resource = Chef::Resource::Package.new("emacs", @run_context)
- @current_resource = Chef::Resource::Package.new("emacs", @run_context)
+ @new_resource = Chef::Resource::Package.new("irssi", @run_context)
+ @current_resource = Chef::Resource::Package.new("irssi", @run_context)
@status = mock("Status", :exitstatus => 0)
@provider = Chef::Provider::Package::Apt.new(@new_resource, @run_context)
Chef::Resource::Package.stub!(:new).and_return(@current_resource)
@provider.stub!(:popen4).and_return(@status)
- @stdin = StringIO.new
- @stdout = StringIO.new(<<-SAMPLE_STDOUT)
-emacs:
- Installed: (none)
- Candidate: 0.1.1
- Version Table:
-SAMPLE_STDOUT
- @stderr = StringIO.new
- @pid = mock("PID")
+ @stdin = mock("STDIN", :null_object => true)
+ @stdout =<<-PKG_STATUS
+Package: irssi
+State: not installed
+Version: 0.8.12-7
+PKG_STATUS
+ @stderr = mock("STDERR", :null_object => true)
+ @pid = mock("PID", :null_object => true)
+ @shell_out = OpenStruct.new(:stdout => @stdout,:stdin => @stdin,:stderr => @stderr,:status => @status,:exitstatus => 0)
end
describe "when loading current resource" do
it "should create a current resource with the name of the new_resource" do
+ @provider.should_receive(:shell_out!).and_return(@shell_out)
Chef::Resource::Package.should_receive(:new).and_return(@current_resource)
@provider.load_current_resource
end
it "should set the current resources package name to the new resources package name" do
+ @provider.should_receive(:shell_out!).and_return(@shell_out)
@current_resource.should_receive(:package_name).with(@new_resource.package_name)
@provider.load_current_resource
end
- it "should run apt-cache policy with the package name" do
- @provider.should_receive(:popen4).with("apt-cache policy #{@new_resource.package_name}").and_return(@status)
+ it "should run aptitude show with the package name" do
+ @provider.should_receive(:shell_out!).with("aptitude show #{@new_resource.package_name}").and_return(@shell_out)
@provider.load_current_resource
end
- it "should read stdout on apt-cache policy" do
- @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
- @stdout.should_receive(:each).and_return(true)
- @provider.load_current_resource
- end
-
- it "should set the installed version to nil on the current resource if apt-cache policy installed version is (none)" do
- @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ it "should set the installed version to nil on the current resource if package state is not installed" do
+ @provider.should_receive(:shell_out!).and_return(@shell_out)
@current_resource.should_receive(:version).with(nil).and_return(true)
@provider.load_current_resource
end
- it "should set the installed version if apt-cache policy has one" do
- @stdout.stub!(:each).and_yield("emacs:").
- and_yield(" Installed: 0.1.1").
- and_yield(" Candidate: 0.1.1").
- and_yield(" Version Table:")
- @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
- @current_resource.should_receive(:version).with("0.1.1").and_return(true)
+ it "should set the installed version if package has one" do
+ @stdout.replace(<<-INSTALLED)
+Package: sudo
+State: installed
+Automatically installed: no
+Version: 1.7.2p1-1ubuntu5
+Priority: important
+Section: admin
+Maintainer: Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+Uncompressed Size: 602k
+Depends: libc6 (>= 2.8), libpam0g (>= 0.99.7.1), libpam-modules
+Conflicts: sudo-ldap
+Replaces: sudo-ldap
+Provided by: sudo-ldap
+Description: Provide limited super user privileges to specific users
+Sudo is a program designed to allow a sysadmin to give limited root privileges
+to users and log root activity. The basic philosophy is to give as few
+privileges as possible but still allow people to get their work done.
+INSTALLED
+ @provider.should_receive(:shell_out!).and_return(@shell_out)
@provider.load_current_resource
+ @current_resource.version.should == "1.7.2p1-1ubuntu5"
+ @provider.candidate_version.should eql("1.7.2p1-1ubuntu5")
end
- it "should set the candidate version if apt-cache policy has one" do
- @stdout.stub!(:each).and_yield("emacs:").
- and_yield(" Installed: 0.1.1").
- and_yield(" Candidate: 10").
- and_yield(" Version Table:")
- @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
- @provider.load_current_resource
- @provider.candidate_version.should eql("10")
- end
-
- it "should raise an exception if apt-cache policy fails" do
- @status.should_receive(:exitstatus).and_return(1)
+ it "should raise an exception if aptitude show does not return a candidate version" do
+ @stdout.replace("E: Unable to locate package magic")
+ @provider.should_receive(:shell_out!).and_return(@shell_out)
lambda { @provider.load_current_resource }.should raise_error(Chef::Exceptions::Package)
end
- it "should not raise an exception if apt-cache policy succeeds" do
- @status.should_receive(:exitstatus).and_return(0)
- lambda { @provider.load_current_resource }.should_not raise_error(Chef::Exceptions::Package)
+ it "should return the current resouce" do
+ @provider.should_receive(:shell_out!).and_return(@shell_out)
+ @provider.load_current_resource.should eql(@current_resource)
end
- it "should raise an exception if apt-cache policy does not return a candidate version" do
- @stdout.stub!(:each).and_yield("emacs:").
- and_yield(" Installed: 0.1.1").
- and_yield(" Candidate: (none)").
- and_yield(" Version Table:")
- @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
- lambda { @provider.load_current_resource }.should raise_error(Chef::Exceptions::Package)
+ it "should set candidate version to new package name if virtual package" do
+ @new_resource.package_name("libmysqlclient-dev")
+ virtual_package_out=<<-VPKG_STDOUT
+"No current or candidate version found for libmysqlclient-dev").
+Package: libmysqlclient-dev
+State: not a real package
+Provided by: libmysqlclient15-dev
+VPKG_STDOUT
+ virtual_package = mock(:stdout => virtual_package_out,:exitstatus => 0)
+ @provider.should_receive(:shell_out!).with("aptitude show libmysqlclient-dev").and_return(virtual_package)
+ real_package_out=mock("STDOUT", :null_object => true)
+ real_package_out =<<-REALPKG_STDOUT
+Package: libmysqlclient15-dev
+State: not installed
+Version: 5.0.51a-24+lenny4
+REALPKG_STDOUT
+ real_package = mock(:stdout => real_package_out,:exitstatus => 0)
+ @provider.should_receive(:shell_out!).with("aptitude show libmysqlclient15-dev").and_return(real_package)
+ @provider.load_current_resource
+ @provider.candidate_version.should eql("libmysqlclient15-dev")
end
- it "should return the current resouce" do
- @provider.load_current_resource.should eql(@current_resource)
+ it "should set candidate version to the first depends package name if multiple virtual package providers" do
+ @new_resource.package_name("vim")
+ virtual_package_out=<<-VPKG_STDOUT
+Package: vim
+State: not installed
+Version: 2:7.2.330-1ubuntu3
+Priority: optional
+Section: editors
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+Uncompressed Size: 1,946k
+Depends: vim-common (= 2:7.2.330-1ubuntu3), vim-runtime (= 2:7.2.330-1ubuntu3), libacl1 (>= 2.2.11-1), libc6 (>= 2.11),
+ libgpm2 (>= 1.20.4), libncurses5 (>= 5.6+20071006-3), libpython2.6 (>= 2.6), libselinux1 (>= 1.32)
+Suggests: ctags, vim-doc, vim-scripts
+Conflicts: vim-common (< 1:7.1-175+1)
+Replaces: vim-common (< 1:7.1-175+1)
+Provides: editor
+Provided by: vim-gnome, vim-gtk, vim-nox
+Description: Vi IMproved - enhanced vi editor
+ Vim is an almost compatible version of the UNIX editor Vi.
+VPKG_STDOUT
+ virtual_package = mock(:stdout => virtual_package_out,:exitstatus => 0)
+ @provider.should_receive(:shell_out!).with("aptitude show vim").and_return(virtual_package)
+ real_package_out=<<-REALPKG_STDOUT
+Package: vim-common
+State: not installed
+Automatically installed: no
+Version: 2:7.2.330-1ubuntu3
+Priority: important
+Section: editors
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+Uncompressed Size: 389k
+Depends: libc6 (>= 2.4)
+Recommends: vim | vim-gnome | vim-gtk | vim-lesstif | vim-nox | vim-tiny
+Description: Vi IMproved - Common files
+ Vim is an almost compatible version of the UNIX editor Vi.
+REALPKG_STDOUT
+ real_package = mock(:stdout => real_package_out,:exitstatus => 0)
+ @provider.should_receive(:shell_out!).with("aptitude show vim-common").and_return(real_package)
+ @provider.load_current_resource
+ @provider.candidate_version.should eql("vim-common")
end
end
@@ -119,32 +172,32 @@ SAMPLE_STDOUT
it "should run apt-get install with the package name and version" do
@provider.should_receive(:run_command_with_systems_locale).with({
- :command => "apt-get -q -y install emacs=1.0",
+ :command => "apt-get -q -y install irssi=0.8.12-7",
:environment => {
"DEBIAN_FRONTEND" => "noninteractive"
}
})
- @provider.install_package("emacs", "1.0")
+ @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
@provider.should_receive(:run_command_with_systems_locale).with({
- :command => "apt-get -q -y --force-yes install emacs=1.0",
+ :command => "apt-get -q -y --force-yes install irssi=0.8.12-7",
:environment => {
"DEBIAN_FRONTEND" => "noninteractive"
}
})
@new_resource.stub!(:options).and_return("--force-yes")
- @provider.install_package("emacs", "1.0")
+ @provider.install_package("irssi", "0.8.12-7")
end
end
describe Chef::Provider::Package::Apt, "upgrade_package" do
it "should run install_package with the name and version" do
- @provider.should_receive(:install_package).with("emacs", "1.0")
- @provider.upgrade_package("emacs", "1.0")
+ @provider.should_receive(:install_package).with("irssi", "0.8.12-7")
+ @provider.upgrade_package("irssi", "0.8.12-7")
end
end
@@ -152,24 +205,24 @@ SAMPLE_STDOUT
it "should run apt-get remove with the package name" do
@provider.should_receive(:run_command_with_systems_locale).with({
- :command => "apt-get -q -y remove emacs",
+ :command => "apt-get -q -y remove irssi",
:environment => {
"DEBIAN_FRONTEND" => "noninteractive"
}
})
- @provider.remove_package("emacs", "1.0")
+ @provider.remove_package("irssi", "0.8.12-7")
end
it "should run apt-get remove with the package name and options if specified" do
@provider.should_receive(:run_command_with_systems_locale).with({
- :command => "apt-get -q -y --force-yes remove emacs",
+ :command => "apt-get -q -y --force-yes remove irssi",
:environment => {
"DEBIAN_FRONTEND" => "noninteractive"
}
})
@new_resource.stub!(:options).and_return("--force-yes")
- @provider.remove_package("emacs", "1.0")
+ @provider.remove_package("irssi", "0.8.12-7")
end
end
@@ -177,52 +230,52 @@ SAMPLE_STDOUT
it "should run apt-get purge with the package name" do
@provider.should_receive(:run_command_with_systems_locale).with({
- :command => "apt-get -q -y purge emacs",
+ :command => "apt-get -q -y purge irssi",
:environment => {
"DEBIAN_FRONTEND" => "noninteractive"
}
})
- @provider.purge_package("emacs", "1.0")
+ @provider.purge_package("irssi", "0.8.12-7")
end
it "should run apt-get purge with the package name and options if specified" do
@provider.should_receive(:run_command_with_systems_locale).with({
- :command => "apt-get -q -y --force-yes purge emacs",
+ :command => "apt-get -q -y --force-yes purge irssi",
:environment => {
"DEBIAN_FRONTEND" => "noninteractive"
}
})
@new_resource.stub!(:options).and_return("--force-yes")
- @provider.purge_package("emacs", "1.0")
+ @provider.purge_package("irssi", "0.8.12-7")
end
end
describe "when preseeding a package" do
before(:each) do
- @provider.stub!(:get_preseed_file).and_return("/tmp/emacs-10.seed")
+ @provider.stub!(:get_preseed_file).and_return("/tmp/irssi-0.8.12-7.seed")
@provider.stub!(:run_command_with_systems_locale).and_return(true)
end
it "should get the full path to the preseed response file" do
- @provider.should_receive(:get_preseed_file).with("emacs", "10").and_return("/tmp/emacs-10.seed")
- @provider.preseed_package("emacs", "10")
+ @provider.should_receive(:get_preseed_file).with("irssi", "0.8.12-7").and_return("/tmp/irssi-0.8.12-7.seed")
+ @provider.preseed_package("irssi", "0.8.12-7")
end
it "should run debconf-set-selections on the preseed file if it has changed" do
@provider.should_receive(:run_command_with_systems_locale).with({
- :command => "debconf-set-selections /tmp/emacs-10.seed",
+ :command => "debconf-set-selections /tmp/irssi-0.8.12-7.seed",
:environment => {
"DEBIAN_FRONTEND" => "noninteractive"
}
}).and_return(true)
- @provider.preseed_package("emacs", "10")
+ @provider.preseed_package("irssi", "0.8.12-7")
end
it "should not run debconf-set-selections if the preseed file has not changed" do
@provider.stub!(:get_preseed_file).and_return(false)
@provider.should_not_receive(:run_command_with_systems_locale)
- @provider.preseed_package("emacs", "10")
+ @provider.preseed_package("irssi", "0.8.12-7")
end
end
end