class Chef::Provider::Package::Windows

Public Instance Methods

action_install() click to toggle source
Calls superclass method
# File lib/chef/provider/package/windows.rb, line 123
def action_install
  if uri_scheme?(new_resource.source)
    download_source_file
    load_current_resource
  else
    validate_content!
  end

  super
end
candidate_version() click to toggle source

@return [String] #candidate_version

# File lib/chef/provider/package/windows.rb, line 151
def candidate_version
  @candidate_version ||= (new_resource.version || "latest")
end
current_version_array() click to toggle source

@return [Array] current_version(s) as an array this package provider does not support package arrays However, There may be multiple versions for a single package so the first element may be a nested array

# File lib/chef/provider/package/windows.rb, line 159
def current_version_array
  [ current_resource.version ]
end
define_resource_requirements() click to toggle source
# File lib/chef/provider/package/windows.rb, line 37
def define_resource_requirements
  requirements.assert(:install) do |a|
    a.assertion { new_resource.source || msi? }
    a.failure_message Chef::Exceptions::NoWindowsPackageSource, "Source for package #{new_resource.name} must be specified in the resource's source property for package to be installed because the package_name property is used to test for the package installation state for this package type."
  end
end
have_any_matching_version?() click to toggle source
# File lib/chef/provider/package/windows.rb, line 180
def have_any_matching_version?
  target_version_already_installed?(current_resource.version, new_resource.version)
end
install_package(name, version) click to toggle source

Chef::Provider::Package #action_install + action_remove call #install_package + #remove_package Pass those calls to the correct sub-provider

# File lib/chef/provider/package/windows.rb, line 136
def install_package(name, version)
  package_provider.install_package
end
installer_type() click to toggle source
# File lib/chef/provider/package/windows.rb, line 73
def installer_type
  # Depending on the installer, we may need to examine installer_type or
  # source attributes, or search for text strings in the installer file
  # binary to determine the installer type for the user. Since the file
  # must be on disk to do so, we have to make this choice in the provider.
  @installer_type ||= begin
    return :msi if msi?

    if new_resource.installer_type
      new_resource.installer_type
    elsif source_location.nil?
      inferred_registry_type
    else
      basename = ::File.basename(source_location)
      file_extension = basename.split(".").last.downcase

      # search the binary file for installer type
      ::Kernel.open(::File.expand_path(source_location), "rb") do |io|
        filesize = io.size
        bufsize = 4096 # read 4K buffers
        overlap = 16 # bytes to overlap between buffer reads

        until io.eof
          contents = io.read(bufsize)

          case contents
          when /inno/i # Inno Setup
            return :inno
          when /wise/i # Wise InstallMaster
            return :wise
          when /nullsoft/i # Nullsoft Scriptable Install System
            return :nsis
          end

          if io.tell < filesize
            io.seek(io.tell - overlap)
          end
        end

        # if file is named 'setup.exe' assume installshield
        if basename == "setup.exe"
          :installshield
        else
          raise Chef::Exceptions::CannotDetermineWindowsInstallerType, "Installer type for Windows Package '#{new_resource.name}' not specified and cannot be determined from file extension '#{file_extension}'"
        end
      end
    end
  end
end
load_current_resource() click to toggle source

#load_current_resource is run in Chef::Provider#run_action when not in whyrun_mode?

# File lib/chef/provider/package/windows.rb, line 45
def load_current_resource
  @current_resource = Chef::Resource::WindowsPackage.new(new_resource.name)
  if downloadable_file_missing?
    logger.trace("We do not know the version of #{new_resource.source} because the file is not downloaded")
    current_resource.version(:unknown.to_s)
  else
    current_resource.version(package_provider.installed_version)
    new_resource.version(package_provider.package_version) if package_provider.package_version
  end

  current_resource
end
new_version_array() click to toggle source

@return [Array] new_version(s) as an array

# File lib/chef/provider/package/windows.rb, line 145
def new_version_array
  # Because the one in the parent caches things
  [new_resource.version]
end
package_provider() click to toggle source
# File lib/chef/provider/package/windows.rb, line 58
def package_provider
  @package_provider ||= begin
    case installer_type
    when :msi
      logger.trace("#{new_resource} is MSI")
      require "chef/provider/package/windows/msi"
      Chef::Provider::Package::Windows::MSI.new(resource_for_provider, uninstall_registry_entries)
    else
      logger.trace("#{new_resource} is EXE with type '#{installer_type}'")
      require "chef/provider/package/windows/exe"
      Chef::Provider::Package::Windows::Exe.new(resource_for_provider, installer_type, uninstall_registry_entries)
    end
  end
end
remove_package(name, version) click to toggle source
# File lib/chef/provider/package/windows.rb, line 140
def remove_package(name, version)
  package_provider.remove_package
end
target_version_already_installed?(current_version, new_version) click to toggle source

@param current_version<String> one or more versions currently installed @param new_version<String> version of the new resource

@return [Boolean] true if new_version is equal to or included in current_version

# File lib/chef/provider/package/windows.rb, line 167
def target_version_already_installed?(current_version, new_version)
  version_equals?(current_version, new_version)
end
version_equals?(current_version, new_version) click to toggle source
# File lib/chef/provider/package/windows.rb, line 171
def version_equals?(current_version, new_version)
  logger.trace("Checking if #{new_resource} version '#{new_version}' is already installed. #{current_version} is currently installed")
  if current_version.is_a?(Array)
    current_version.include?(new_version)
  else
    new_version == current_version
  end
end

Private Instance Methods

default_download_cache_path() click to toggle source
# File lib/chef/provider/package/windows.rb, line 247
def default_download_cache_path
  uri = ::URI.parse(new_resource.source)
  filename = ::File.basename(::URI.unescape(uri.path))
  file_cache_dir = Chef::FileCache.create_cache_path("package/")
  Chef::Util::PathHelper.cleanpath("#{file_cache_dir}/#{filename}")
end
download_source_file() click to toggle source
# File lib/chef/provider/package/windows.rb, line 227
def download_source_file
  source_resource.run_action(:create)
  logger.trace("#{new_resource} fetched source file to #{source_resource.path}")
end
downloadable_file_missing?() click to toggle source
# File lib/chef/provider/package/windows.rb, line 212
def downloadable_file_missing?
  !new_resource.source.nil? && uri_scheme?(new_resource.source) && !::File.exist?(source_location)
end
inferred_registry_type() click to toggle source
# File lib/chef/provider/package/windows.rb, line 201
def inferred_registry_type
  @inferred_registry_type ||= begin
    uninstall_registry_entries.each do |entry|
      return :inno if entry.key.end_with?("_is1")
      return :msi if entry.uninstall_string.downcase.start_with?("msiexec.exe ")
      return :nsis if entry.uninstall_string.downcase.end_with?("uninst.exe\"")
    end
    nil
  end
end
msi?() click to toggle source
# File lib/chef/provider/package/windows.rb, line 274
def msi?
  return true if new_resource.installer_type == :msi

  if source_location.nil?
    inferred_registry_type == :msi
  else
    ::File.extname(source_location).casecmp(".msi") == 0
  end
end
resource_for_provider() click to toggle source
# File lib/chef/provider/package/windows.rb, line 216
def resource_for_provider
  @resource_for_provider = Chef::Resource::WindowsPackage.new(new_resource.name).tap do |r|
    r.source(Chef::Util::PathHelper.validate_path(source_location)) unless source_location.nil?
    r.cookbook_name = new_resource.cookbook_name
    r.version(new_resource.version)
    r.timeout(new_resource.timeout)
    r.returns(new_resource.returns)
    r.options(new_resource.options)
  end
end
source_location() click to toggle source
# File lib/chef/provider/package/windows.rb, line 254
def source_location
  if new_resource.source.nil?
    nil
  elsif uri_scheme?(new_resource.source)
    source_resource.path
  else
    new_source = Chef::Util::PathHelper.cleanpath(new_resource.source)
    ::File.exist?(new_source) ? new_source : nil
  end
end
source_resource() click to toggle source
# File lib/chef/provider/package/windows.rb, line 232
def source_resource
  @source_resource ||= Chef::Resource::RemoteFile.new(default_download_cache_path, run_context).tap do |r|
    r.source(new_resource.source)
    r.cookbook_name = new_resource.cookbook_name
    r.checksum(new_resource.checksum)
    r.backup(false)

    if new_resource.remote_file_attributes
      new_resource.remote_file_attributes.each do |(k, v)|
        r.send(k.to_sym, v)
      end
    end
  end
end
uninstall_registry_entries() click to toggle source
# File lib/chef/provider/package/windows.rb, line 197
def uninstall_registry_entries
  @uninstall_registry_entries ||= Chef::Provider::Package::Windows::RegistryUninstallEntry.find_entries(new_resource.package_name)
end
validate_content!() click to toggle source
# File lib/chef/provider/package/windows.rb, line 265
def validate_content!
  if new_resource.checksum
    source_checksum = checksum(source_location)
    if new_resource.checksum.downcase != source_checksum
      raise Chef::Exceptions::ChecksumMismatch.new(short_cksum(new_resource.checksum), short_cksum(source_checksum))
    end
  end
end
version_compare(v1, v2) click to toggle source
# File lib/chef/provider/package/windows.rb, line 186
def version_compare(v1, v2)
  if v1 == "latest" || v2 == "latest"
    return 0
  end

  gem_v1 = Gem::Version.new(v1)
  gem_v2 = Gem::Version.new(v2)

  gem_v1 <=> gem_v2
end