diff options
author | Nuo Yan <nuo@opscode.com> | 2011-06-02 17:37:40 -0700 |
---|---|---|
committer | Nuo Yan <nuo@opscode.com> | 2011-06-02 17:37:40 -0700 |
commit | 16dd475cd3470de9f1f3818c22916ba6670b806f (patch) | |
tree | a1332f34aa428f42c6f443a2c3e689f3eb96c2cb | |
parent | 5a4fb459291c7133d81ac731fca3fd45f42a5c07 (diff) | |
parent | 3632f292165152bbd3cca59f52323cd0e3ee9fa1 (diff) | |
download | chef-16dd475cd3470de9f1f3818c22916ba6670b806f.tar.gz |
CHEF-1439: Resolve merge conflict.
-rw-r--r-- | chef/lib/chef/provider/package/apt.rb | 63 | ||||
-rw-r--r-- | chef/spec/unit/provider/package/apt_spec.rb | 197 |
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 |