summaryrefslogtreecommitdiff
path: root/lib/chef/provider/package/apt.rb
diff options
context:
space:
mode:
authorPhil Dibowitz <phil@ipom.com>2014-12-19 19:03:44 -0800
committerPhil Dibowitz <phil@ipom.com>2015-02-03 19:32:35 -0800
commit36ce3c58d7deb3467858ff7aefb05c819be9c416 (patch)
tree7832a6cb8c4581cd699fa09487bd75a384e67607 /lib/chef/provider/package/apt.rb
parent23cb1c709d83f1476e6a155a2ec8d0cdde14c0f9 (diff)
downloadchef-36ce3c58d7deb3467858ff7aefb05c819be9c416.tar.gz
Multipackge support
Allow the `package` provider to take an array of packages to handle in one transaction. This solves two large problems: * There are times when you cannot install two packages in sequence, like when a binary is moving between two packages - they *must* be done in the same transaction. * When using Chef to install the vast majority of your base system, it can make imaging take a very, very long time because executing yum or apt once for every single package is painfully slow. This solves both. The scaffolding is all there in the Package HWRP, plus the underlying implementation for both apt and yum, the two I have access to test.
Diffstat (limited to 'lib/chef/provider/package/apt.rb')
-rw-r--r--lib/chef/provider/package/apt.rb137
1 files changed, 93 insertions, 44 deletions
diff --git a/lib/chef/provider/package/apt.rb b/lib/chef/provider/package/apt.rb
index fd132c817c..099a4a9b61 100644
--- a/lib/chef/provider/package/apt.rb
+++ b/lib/chef/provider/package/apt.rb
@@ -51,54 +51,89 @@ class Chef
end
def check_package_state(package)
- Chef::Log.debug("#{@new_resource} checking package status for #{package}")
- installed = false
-
- shell_out!("apt-cache#{expand_options(default_release_options)} policy #{package}", :timeout => @new_resource.timeout).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")
- @current_resource.version(nil)
- else
- Chef::Log.debug("#{@new_resource} current version is #{installed_version}")
- @current_resource.version(installed_version)
- installed = true
- end
- when /^\s{2}Candidate: (.+)$/
- candidate_version = $1
- 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!("apt-cache showpkg #{package}", :timeout => @new_resource.timeout).stdout
- providers = Hash.new
- # Returns all lines after 'Reverse Provides:'
- showpkg.rpartition(/Reverse Provides:\s*#{$/}/)[2].each_line do |line|
- provider, version = line.split
- providers[provider] = version
+ if package.is_a?(Array)
+ final_installed_version = []
+ final_candidate_version = []
+ final_installed = []
+ final_virtual = []
+ end
+ installed = virtual = false
+ installed_version = candidate_version = nil
+
+ [package].flatten.each do |pkg|
+ installed = virtual = false
+ installed_version = candidate_version = nil
+ shell_out!("apt-cache#{expand_options(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")
+ installed_version = nil
+ else
+ Chef::Log.debug("#{@new_resource} current version is #{installed_version}")
+ installed = true
+ end
+ when /^\s{2}Candidate: (.+)$/
+ candidate_version = $1
+ if candidate_version == '(none)'
+ # This may not be an appropriate assumption, but it shouldn't break anything that already worked -- btm
+ virtual = true
+ showpkg = shell_out!("apt-cache showpkg #{package}").stdout
+ providers = Hash.new
+ showpkg.rpartition(/Reverse Provides:? #{$/}/)[2].each_line do |line|
+ provider, version = line.split
+ providers[provider] = version
+ 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
+ # 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
+ # 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}]")
+ installed = check_package_state(providers.keys.first)
+ else
+ Chef::Log.debug("#{@new_resource} candidate version is #{$1}")
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
- # 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
- # 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}]")
- installed = check_package_state(providers.keys.first)
- else
- Chef::Log.debug("#{@new_resource} candidate version is #{$1}")
- @candidate_version = $1
end
end
+ if package.is_a?(Array)
+ final_installed_version << installed_version
+ final_candidate_version << candidate_version
+ final_installed << installed
+ final_virtual << virtual
+ else
+ final_installed_version = installed_version
+ final_candidate_version = candidate_version
+ final_installed = installed
+ final_virtual = virtual
+ end
end
-
- return installed
+ @candidate_version = final_candidate_version
+ @current_resource.version(final_installed_version)
+ @is_virtual_package = final_virtual
+
+ return final_installed.is_a?(Array) ? final_installed.any? : final_installed
end
def install_package(name, version)
- package_name = "#{name}=#{version}"
- package_name = name if @is_virtual_package
+ if name.is_a?(Array)
+ index = 0
+ package_name = name.zip(version).map do |x, y|
+ namestr = nil
+ if @is_virtual_package[index]
+ namestr = x
+ else
+ namestr = "#{x}=#{y}"
+ end
+ index += 1
+ namestr
+ end.join(' ')
+ else
+ package_name = "#{name}=#{version}"
+ package_name = name if @is_virtual_package
+ end
run_noninteractive("apt-get -q -y#{expand_options(default_release_options)}#{expand_options(@new_resource.options)} install #{package_name}")
end
@@ -107,12 +142,21 @@ class Chef
end
def remove_package(name, version)
- package_name = "#{name}"
+ if name.is_a?(Array)
+ package_name = name.join(' ')
+ else
+ package_name = name
+ end
run_noninteractive("apt-get -q -y#{expand_options(@new_resource.options)} remove #{package_name}")
end
def purge_package(name, version)
- run_noninteractive("apt-get -q -y#{expand_options(@new_resource.options)} purge #{@new_resource.package_name}")
+ if name.is_a?(Array)
+ package_name = name.join(' ')
+ else
+ package_name = "#{name}"
+ end
+ run_noninteractive("apt-get -q -y#{expand_options(@new_resource.options)} purge #{package_name}")
end
def preseed_package(preseed_file)
@@ -121,8 +165,13 @@ class Chef
end
def reconfig_package(name, version)
+ if name.is_a?(Array)
+ package_name = name.join(' ')
+ else
+ package_name = "#{name}"
+ end
Chef::Log.info("#{@new_resource} reconfiguring")
- run_noninteractive("dpkg-reconfigure #{name}")
+ run_noninteractive("dpkg-reconfigure #{package_name}")
end
private