class Chef::Provider::Package::Apt

Public Class Methods

new(new_resource, run_context) click to toggle source
Calls superclass method Chef::Provider::Package::new
# File lib/chef/provider/package/apt.rb, line 33
def initialize(new_resource, run_context)
  super
end

Public Instance Methods

candidate_version() click to toggle source
# File lib/chef/provider/package/apt.rb, line 71
def candidate_version
  @candidate_version ||= get_candidate_versions
end
define_resource_requirements() click to toggle source
# File lib/chef/provider/package/apt.rb, line 44
def define_resource_requirements
  super

  requirements.assert(:all_actions) do |a|
    a.assertion { !new_resource.source }
    a.failure_message(Chef::Exceptions::Package, "apt package provider cannot handle source property. Use dpkg provider instead")
  end
end
get_candidate_versions() click to toggle source
# File lib/chef/provider/package/apt.rb, line 65
def get_candidate_versions
  package_name_array.map do |package_name|
    package_data[package_name][:candidate_version]
  end
end
get_current_versions() click to toggle source
# File lib/chef/provider/package/apt.rb, line 59
def get_current_versions
  package_name_array.map do |package_name|
    package_data[package_name][:current_version]
  end
end
install_package(name, version) click to toggle source
# File lib/chef/provider/package/apt.rb, line 91
def install_package(name, version)
  package_name = name.zip(version).map do |n, v|
    package_data[n][:virtual] ? n : "#{n}=#{v}"
  end
  dgrade = "--allow-downgrades" if supports_allow_downgrade? && allow_downgrade
  run_noninteractive("apt-get", "-q", "-y", dgrade, config_file_options, default_release_options, options, "install", package_name)
end
load_current_resource() click to toggle source
# File lib/chef/provider/package/apt.rb, line 37
def load_current_resource
  @current_resource = Chef::Resource::AptPackage.new(new_resource.name)
  current_resource.package_name(new_resource.package_name)
  current_resource.version(get_current_versions)
  current_resource
end
lock_package(name, version) click to toggle source
# File lib/chef/provider/package/apt.rb, line 117
def lock_package(name, version)
  run_noninteractive("apt-mark", options, "hold", name)
end
locked_packages() click to toggle source
# File lib/chef/provider/package/apt.rb, line 83
def locked_packages
  @locked_packages ||=
    begin
      locked = shell_out!("apt-mark", "showhold")
      locked.stdout.each_line.map(&:strip)
    end
end
package_data() click to toggle source
# File lib/chef/provider/package/apt.rb, line 53
def package_data
  @package_data ||= Hash.new do |hash, key|
    hash[key] = package_data_for(key)
  end
end
packages_all_locked?(names, versions) click to toggle source
# File lib/chef/provider/package/apt.rb, line 75
def packages_all_locked?(names, versions)
  names.all? { |n| locked_packages.include? n }
end
packages_all_unlocked?(names, versions) click to toggle source
# File lib/chef/provider/package/apt.rb, line 79
def packages_all_unlocked?(names, versions)
  names.all? { |n| !locked_packages.include? n }
end
purge_package(name, version) click to toggle source
# File lib/chef/provider/package/apt.rb, line 110
def purge_package(name, version)
  package_name = name.map do |n|
    package_data[n][:virtual] ? resolve_virtual_package_name(n) : n
  end
  run_noninteractive("apt-get", "-q", "-y", options, "purge", package_name)
end
remove_package(name, version) click to toggle source
# File lib/chef/provider/package/apt.rb, line 103
def remove_package(name, version)
  package_name = name.map do |n|
    package_data[n][:virtual] ? resolve_virtual_package_name(n) : n
  end
  run_noninteractive("apt-get", "-q", "-y", options, "remove", package_name)
end
unlock_package(name, version) click to toggle source
# File lib/chef/provider/package/apt.rb, line 121
def unlock_package(name, version)
  run_noninteractive("apt-mark", options, "unhold", name)
end
upgrade_package(name, version) click to toggle source
# File lib/chef/provider/package/apt.rb, line 99
def upgrade_package(name, version)
  install_package(name, version)
end

Private Instance Methods

apt_version() click to toggle source

@return [String] version of apt-get which is installed

# File lib/chef/provider/package/apt.rb, line 128
def apt_version
  @apt_version ||= shell_out("apt-get --version").stdout.match(/^apt (\S+)/)[1]
end
config_file_options() click to toggle source
# File lib/chef/provider/package/apt.rb, line 162
def config_file_options
  # If the user has specified config file options previously, respect those.
  return if Array(options).any? { |opt| opt.include?("--force-conf") }

  # It doesn't make sense to install packages in a scenario that can
  # result in a prompt. Have users decide up-front whether they want to
  # forcibly overwrite the config file, otherwise preserve it.
  if new_resource.overwrite_config_files
    [ "-o", "Dpkg::Options::=--force-confnew" ]
  else
    [ "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold" ]
  end
end
default_release_options() click to toggle source
# File lib/chef/provider/package/apt.rb, line 155
def default_release_options
  # Use apt::Default-Release option only if provider supports it
  if new_resource.respond_to?(:default_release) && new_resource.default_release
    [ "-o", "APT::Default-Release=#{new_resource.default_release}" ]
  end
end
package_data_for(pkg) click to toggle source
# File lib/chef/provider/package/apt.rb, line 234
def package_data_for(pkg)
  virtual           = false
  current_version   = nil
  candidate_version = nil

  current_version, candidate_version = resolve_package_versions(pkg)

  if candidate_version.nil?
    newpkg = resolve_virtual_package_name(pkg)

    if newpkg
      virtual = true
      logger.info("#{new_resource} is a virtual package, actually acting on package[#{newpkg}]")
      current_version, candidate_version = resolve_package_versions(newpkg)
    end
  end

  {
    current_version: current_version,
    candidate_version: candidate_version,
    virtual: virtual,
  }
end
resolve_package_versions(pkg) click to toggle source
# File lib/chef/provider/package/apt.rb, line 176
def resolve_package_versions(pkg)
  current_version = nil
  candidate_version = nil
  all_versions = []
  run_noninteractive("apt-cache", default_release_options, "policy", pkg).stdout.each_line do |line|
    case line
    when /^\s{2}Installed: (.+)$/
      current_version = ( $1 != "(none)" ) ? $1 : nil
      logger.trace("#{new_resource} installed version for #{pkg} is #{$1}")
    when /^\s{2}Candidate: (.+)$/
      candidate_version = ( $1 != "(none)" ) ? $1 : nil
      logger.trace("#{new_resource} candidate version for #{pkg} is #{$1}")
    when /\s+(?:\*\*\* )?(\S+) \d+/
      all_versions << $1
    end
  end
  # This is a bit ugly... really this whole provider needs
  # to be rewritten to use target_version_array and friends, but
  # for now this gets us moving
  idx = package_name_array.index(pkg)
  chosen_version =
    if idx
      user_ver = new_version_array[idx]
      if user_ver
        if all_versions.include?(user_ver)
          user_ver
        else
          logger.debug("User specified a version that's not available")
          nil
        end
      else
        # user didn't specify a version, use candidate
        candidate_version
      end
    else
      # this probably means we're redirected from a virtual
      # package, so... just go with candidate version
      candidate_version
    end
  [ current_version, chosen_version ]
end
resolve_virtual_package_name(pkg) click to toggle source
# File lib/chef/provider/package/apt.rb, line 218
def resolve_virtual_package_name(pkg)
  showpkg = run_noninteractive("apt-cache", "showpkg", pkg).stdout
  partitions = showpkg.rpartition(/Reverse Provides: ?#{$/}/)
  return nil if partitions[0] == "" && partitions[1] == "" # not found in output

  set = partitions[2].lines.each_with_object(Set.new) do |line, acc|
    # there may be multiple reverse provides for a single package
    acc.add(line.split[0])
  end
  if set.size > 1
    raise Chef::Exceptions::Package, "#{new_resource.package_name} is a virtual package provided by multiple packages, you must explicitly select one"
  end

  set.to_a.first
end
supports_allow_downgrade?() click to toggle source

@return [Boolean] if apt-get supports –allow-downgrades

# File lib/chef/provider/package/apt.rb, line 133
def supports_allow_downgrade?
  return @supports_allow_downgrade unless @supports_allow_downgrade.nil?

  @supports_allow_downgrade = ( version_compare(apt_version, "1.1.0") >= 0 )
end
version_compare(v1, v2) click to toggle source

compare 2 versions to each other to see which is newer. this differs from the standard package method because we need to be able to parse debian version strings which contain tildes which Gem cannot properly parse

@return [Integer] 1 if v1 > v2. 0 if they're equal. -1 if v1 < v2

# File lib/chef/provider/package/apt.rb, line 145
def version_compare(v1, v2)
  if !shell_out("dpkg", "--compare-versions", v1.to_s, "gt", v2.to_s).error?
    1
  elsif !shell_out("dpkg", "--compare-versions", v1.to_s, "eq", v2.to_s).error?
    0
  else
    -1
  end
end