Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

CHEF-2483: refactor to act on virtual packages more like apt does

The virtual package blocks now ignore packages that aren't virtual packages
If the virtual package is provided by a single package we install or remove it
If the virtual package is provided by more than one package, we throw an exception
  • Loading branch information...
commit 4c9b9e60c93491f68abe15f49996ab6db4b88b60 1 parent fbbbef7
Bryan McLellan btm authored
28 chef/lib/chef/provider/package/apt.rb
@@ -26,7 +26,7 @@ class Package
26 26 class Apt < Chef::Provider::Package
27 27
28 28 include Chef::Mixin::ShellOut
29   - attr_accessor :virtual
  29 + attr_accessor :is_virtual_package
30 30
31 31 def load_current_resource
32 32 @current_resource = Chef::Resource::Package.new(@new_resource.name)
@@ -36,14 +36,15 @@ def load_current_resource
36 36 end
37 37
38 38 def check_package_state(package)
39   - Chef::Log.debug("Checking package status for #{package}")
  39 + Chef::Log.debug("#{@new_resource} checking package status for #{package}")
40 40 installed = false
41   - depends = false
42 41
43 42 shell_out!("aptitude show #{package}").stdout.each_line do |line|
44 43 case line
45 44 when /^State: installed/
46 45 installed = true
  46 + when /^State: not a real package/
  47 + @is_virtual_package = true
47 48 when /^Version: (.*)/
48 49 @candidate_version = $1
49 50 if installed
@@ -51,18 +52,16 @@ def check_package_state(package)
51 52 else
52 53 @current_resource.version(nil)
53 54 end
54   - # Grab the first package in the dependency list to resolve case where a virtual package is provided by more than one package
55   - when /Depends: ([\w\d\-\.]*)/
56   - depends = $1
57   - # Check to see if this is a virtual package
58   - when /Provided by: ([\w\d\-\.]*)/
59   - next if installed
  55 + # If we are a virtual package with one provider package, install it
  56 + when /^Provided by: ([\w\d\-\.]*)$/
  57 + next unless @is_virtual_package
60 58 virtual_provider = $1
61   - virtual_provider = depends if depends
62   - Chef::Log.debug("Virtual package provided by #{virtual_provider}")
63   - @virtual = true
  59 + Chef::Log.info("#{@new_resource} is a virtual package, actually acting on package[#{virtual_provider}]")
64 60 installed = check_package_state(virtual_provider)
65   - @candidate_version = virtual_provider
  61 + # If there is a comma, it is a list of packages. In this case fail to force the user to choose.
  62 + when /^Provided by: .*,/
  63 + next unless @is_virtual_package
  64 + raise Chef::Exceptions::Package, "#{@new_resource.package_name} is a virtual package provided by multiple packages, you must explicitly select one to install"
66 65 end
67 66 end
68 67
@@ -75,7 +74,7 @@ def check_package_state(package)
75 74
76 75 def install_package(name, version)
77 76 package_name = "#{name}=#{version}"
78   - package_name = "#{name} #{@candidate_version}" if @virtual
  77 + package_name = name if @is_virtual_package
79 78 run_command_with_systems_locale(
80 79 :command => "apt-get -q -y#{expand_options(@new_resource.options)} install #{package_name}",
81 80 :environment => {
@@ -90,7 +89,6 @@ def upgrade_package(name, version)
90 89
91 90 def remove_package(name, version)
92 91 package_name = "#{name}"
93   - package_name = "#{name} #{@candidate_version}" if @virtual
94 92 run_command_with_systems_locale(
95 93 :command => "apt-get -q -y#{expand_options(@new_resource.options)} remove #{package_name}",
96 94 :environment => {
122 chef/spec/unit/provider/package/apt_spec.rb
@@ -103,10 +103,12 @@
103 103 @provider.load_current_resource.should eql(@current_resource)
104 104 end
105 105
106   - it "should set candidate version to new package name if virtual package" do
  106 + # libmysqlclient-dev is a real package in newer versions of debian + ubuntu
  107 + # list of virtual packages: http://www.debian.org/doc/packaging-manuals/virtual-package-names-list.txt
  108 + it "should not install the virtual package there is a single provider package and it is installed" do
107 109 @new_resource.package_name("libmysqlclient-dev")
108 110 virtual_package_out=<<-VPKG_STDOUT
109   -"No current or candidate version found for libmysqlclient-dev").
  111 +No current or candidate version found for libmysqlclient-dev
110 112 Package: libmysqlclient-dev
111 113 State: not a real package
112 114 Provided by: libmysqlclient15-dev
@@ -115,109 +117,30 @@
115 117 @provider.should_receive(:shell_out!).with("aptitude show libmysqlclient-dev").and_return(virtual_package)
116 118 real_package_out =<<-REALPKG_STDOUT
117 119 Package: libmysqlclient15-dev
118   -State: not installed
  120 +State: installed
119 121 Version: 5.0.51a-24+lenny4
120 122 REALPKG_STDOUT
121 123 real_package = mock(:stdout => real_package_out,:exitstatus => 0)
122 124 @provider.should_receive(:shell_out!).with("aptitude show libmysqlclient15-dev").and_return(real_package)
  125 + @provider.should_not_receive(:run_command_with_systems_locale)
123 126 @provider.load_current_resource
124   - @provider.candidate_version.should eql("libmysqlclient15-dev")
125 127 end
126 128
127   - describe "multiple virtual package providers" do
128   - it "should set the candidate version to the first package in the depends when the dependency includes a version" do
129   - @new_resource.package_name("vim")
130   - virtual_package_out=<<-VPKG_STDOUT
131   -Package: vim
132   -State: not installed
133   -Version: 2:7.2.330-1ubuntu3
134   -Priority: optional
135   -Section: editors
136   -Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
137   -Uncompressed Size: 1,946k
138   -Depends: vim-common (= 2:7.2.330-1ubuntu3), vim-runtime (= 2:7.2.330-1ubuntu3), libacl1 (>= 2.2.11-1), libc6 (>= 2.11),
139   - libgpm2 (>= 1.20.4), libncurses5 (>= 5.6+20071006-3), libpython2.6 (>= 2.6), libselinux1 (>= 1.32)
140   -Suggests: ctags, vim-doc, vim-scripts
141   -Conflicts: vim-common (< 1:7.1-175+1)
142   -Replaces: vim-common (< 1:7.1-175+1)
143   -Provides: editor
144   -Provided by: vim-gnome, vim-gtk, vim-nox
145   -Description: Vi IMproved - enhanced vi editor
146   - Vim is an almost compatible version of the UNIX editor Vi.
147   -VPKG_STDOUT
148   - virtual_package = mock(:stdout => virtual_package_out,:exitstatus => 0)
149   - @provider.should_receive(:shell_out!).with("aptitude show vim").and_return(virtual_package)
150   - real_package_out=<<-REALPKG_STDOUT
151   -Package: vim-common
152   -State: not installed
153   -Automatically installed: no
154   -Version: 2:7.2.330-1ubuntu3
155   -Priority: important
156   -Section: editors
157   -Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
158   -Uncompressed Size: 389k
159   -Depends: libc6 (>= 2.4)
160   -Recommends: vim | vim-gnome | vim-gtk | vim-lesstif | vim-nox | vim-tiny
161   -Description: Vi IMproved - Common files
162   - Vim is an almost compatible version of the UNIX editor Vi.
163   -REALPKG_STDOUT
164   - real_package = mock(:stdout => real_package_out,:exitstatus => 0)
165   - @provider.should_receive(:shell_out!).with("aptitude show vim-common").and_return(real_package)
166   - @provider.load_current_resource
167   - @provider.candidate_version.should eql("vim-common")
168   - end
169   - it "should set the candidate version to the first package in the depends when the dependency does not include a version" do
170   - @new_resource.package_name("dhcp-client")
171   - virtual_package_out=<<-VPKG_STDOUT
172   -Package: dhcp-client
173   -State: not installed
174   -Version: 3.1.3-2ubuntu3.2
175   -Priority: extra
176   -Section: universe/net
177   -Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
178   -Uncompressed Size: 57.3k
179   -Depends: dhcp3-client
180   -Conflicts: dhcp-client (< 3.0)
181   -Provided by: dhcpcd, pump, udhcpc
182   -Description: DHCP client transitional package
183   - This is the client from version 3 of the Internet Software Consortium's implementation of DHCP. For more information visit http://www.isc.org.
184   -
185   - This is a dummy package to aid in transitioning from the v2 dhcp-client package to the v3 dhcp3-client package.
186   -
187   - This dummy package may be safely removed after upgrading to lenny
  129 + it "should raise an exception if you specify a virtual package with multiple provider packages" do
  130 + @new_resource.package_name("mp3-decoder")
  131 + virtual_package_out=<<-VPKG_STDOUT
  132 +No current or candidate version found for mp3-decoder
  133 +Package: mp3-decoder
  134 +State: not a real package
  135 +Provided by: mpg123, mpg123-oss-i486, mpg321, opencubicplayer, vlc, vlc-nox
188 136 VPKG_STDOUT
189   - virtual_package = mock(:stdout => virtual_package_out,:exitstatus => 0)
190   - @provider.should_receive(:shell_out!).with("aptitude show dhcp-client").and_return(virtual_package)
191   - real_package_out=<<-REALPKG_STDOUT
192   -Package: dhcp3-client
193   -State: not installed
194   -Automatically installed: no
195   -Version: 3.1.3-2ubuntu3.2
196   -Priority: important
197   -Section: net
198   -Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
199   -Uncompressed Size: 692k
200   -Depends: debianutils (>= 2.8.2), dhcp3-common (= 3.1.3-2ubuntu3.2), libc6 (>= 2.7), debconf (>= 0.5) | debconf-2.0
201   -Suggests: resolvconf, avahi-autoipd, apparmor
202   -Conflicts: dhcp-client (< 3.0), samba-common (< 3.0.0beta1-2)
203   -Description: DHCP client
204   - This is the client from version 3 of the Internet Software Consortium's implementation of DHCP. For more information visit http://www.isc.org.
205   -
206   - Dynamic Host Configuration Protocol (DHCP) is a protocol like BOOTP (actually dhcpd includes much of the functionality of bootpd). It gives client machines "leases" for IP addresses and can automatically set their network configuration. If your machine depends on DHCP (especially likely if it's a workstation on a
207   - large network, or a laptop, or attached to a cable modem), keep this or another DHCP client installed.
208   -
209   - Extra documentation can be found in the package dhcp3-common.
210   -REALPKG_STDOUT
211   - real_package = mock(:stdout => real_package_out,:exitstatus => 0)
212   - @provider.should_receive(:shell_out!).with("aptitude show dhcp3-client").and_return(real_package)
213   - @provider.load_current_resource
214   - @provider.candidate_version.should eql("dhcp3-client")
215   - end
  137 + virtual_package = mock(:stdout => virtual_package_out,:exitstatus => 0)
  138 + @provider.should_receive(:shell_out!).with("aptitude show mp3-decoder").and_return(virtual_package)
  139 + lambda { @provider.load_current_resource }.should raise_error(Chef::Exceptions::Package)
216 140 end
217 141 end
218 142
219 143 describe "install_package" do
220   -
221 144 it "should run apt-get install with the package name and version" do
222 145 @provider.should_receive(:run_command_with_systems_locale).with({
223 146 :command => "apt-get -q -y install irssi=0.8.12-7",
@@ -326,4 +249,17 @@
326 249 @provider.preseed_package("irssi", "0.8.12-7")
327 250 end
328 251 end
  252 +
  253 + describe "when installing a virtual package" do
  254 + it "should install the package without specifying a version" do
  255 + @provider.is_virtual_package = true
  256 + @provider.should_receive(:run_command_with_systems_locale).with({
  257 + :command => "apt-get -q -y install libmysqlclient-dev",
  258 + :environment => {
  259 + "DEBIAN_FRONTEND" => "noninteractive"
  260 + }
  261 + })
  262 + @provider.install_package("libmysqlclient-dev", "not_a_real_version")
  263 + end
  264 + end
329 265 end

0 comments on commit 4c9b9e6

Please sign in to comment.
Something went wrong with that request. Please try again.