Created
June 9, 2011 16:01
-
-
Save rubiojr/1017053 to your computer and use it in GitHub Desktop.
patched chef yum.rb provider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Author:: Adam Jacob (<adam@opscode.com>) | |
# Copyright:: Copyright (c) 2008 Opscode, Inc. | |
# License:: Apache License, Version 2.0 | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
# | |
require 'chef/provider/package' | |
require 'chef/mixin/command' | |
require 'chef/resource/package' | |
require 'singleton' | |
class Chef | |
class Provider | |
class Package | |
class Yum < Chef::Provider::Package | |
class YumCache | |
include Chef::Mixin::Command | |
include Singleton | |
include Chef::Mixin::ShellOut | |
def initialize | |
load_data | |
end | |
def stale? | |
interval = Chef::Config[:interval].to_f | |
# run once mode | |
if interval == 0 | |
return false | |
elsif (Time.now - @updated_at) > interval | |
return true | |
end | |
false | |
end | |
def refresh | |
if @data.empty? | |
reload | |
elsif stale? | |
reload | |
end | |
end | |
def load_data | |
@data = Hash.new | |
error = String.new | |
helper = ::File.join(::File.dirname(__FILE__), 'yum-dump.py') | |
shout = shell_out("/usr/bin/python #{helper}") | |
shout.stdout.each_line do |line| | |
line.chomp! | |
name, type, epoch, version, release, arch = line.split(',') | |
type_sym = type.to_sym | |
if !@data.has_key?(name) | |
@data[name] = Hash.new | |
end | |
if !@data[name].has_key?(type_sym) | |
@data[name][type_sym] = Hash.new | |
end | |
@data[name][type_sym][arch] = { :epoch => epoch, :version => version, | |
:release => release } | |
end | |
unless shout.exitstatus == 0 | |
raise Chef::Exceptions::Package, "yum failed - #{shout.stdout} - returns: #{shout.stderr}" | |
end | |
@updated_at = Time.now | |
end | |
alias :reload :load_data | |
def version(package_name, type, arch) | |
if (x = @data[package_name]) | |
if (y = x[type]) | |
if arch | |
if (z = y[arch]) | |
return "#{z[:version]}-#{z[:release]}" | |
end | |
else | |
# no arch specified - take the first match | |
z = y.to_a[0][1] | |
return "#{z[:version]}-#{z[:release]}" | |
end | |
end | |
end | |
nil | |
end | |
def version_available?(package_name, desired_version, arch) | |
if (package_data = @data[package_name]) | |
if (available_versions = package_data[:available]) | |
if arch | |
# arch gets passed like ".x86_64" | |
matching_versions = [ available_versions[arch.sub(/^./, '')]] | |
else | |
matching_versions = available_versions.values | |
end | |
if matching_versions.nil? | |
if arch.empty? | |
arch_msg = "" | |
else | |
arch_msg = "with arch #{arch.sub(/^./, '')} " | |
end | |
raise ArgumentError, "#{package_name}: Found no available versions #{arch_msg}to match" | |
end | |
# Expect [ { :version => "ver", :release => "rel" }, { :version => "ver", :release => "rel" }, { :version => "ver", :release => "rel" } ] ??? | |
matching_versions.each do |ver| | |
Chef::Log.debug("#{@new_resource} trying to match #{desired_version} to version #{ver[:version]} and release #{ver[:release]}") | |
if (desired_version == "#{ver[:version]}-#{ver[:release]}") | |
return true | |
end | |
end | |
end | |
end | |
nil | |
end | |
def installed_version(package_name, arch) | |
version(package_name, :installed, arch) | |
end | |
def candidate_version(package_name, arch) | |
version(package_name, :available, arch) | |
end | |
def flush | |
@data.clear | |
end | |
end | |
def initialize(new_resource, run_context) | |
super | |
@yum = YumCache.instance | |
end | |
def arch | |
if @new_resource.respond_to?("arch") | |
@new_resource.arch | |
else | |
nil | |
end | |
end | |
def yum_arch | |
arch ? ".#{arch}" : nil | |
end | |
def load_current_resource | |
@current_resource = Chef::Resource::Package.new(@new_resource.name) | |
@current_resource.package_name(@new_resource.package_name) | |
if @new_resource.source | |
unless ::File.exists?(@new_resource.source) | |
raise Chef::Exceptions::Package, "Package #{@new_resource.name} not found: #{@new_resource.source}" | |
end | |
Chef::Log.debug("#{@new_resource} checking rpm status") | |
status = popen4("rpm -qp --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' #{@new_resource.source}") do |pid, stdin, stdout, stderr| | |
stdout.each do |line| | |
case line | |
when /([\w\d_.-]+)\s([\w\d_.-]+)/ | |
@current_resource.package_name($1) | |
@new_resource.version($2) | |
end | |
end | |
end | |
end | |
Chef::Log.debug("#{@new_resource} checking yum info for #{@new_resource.package_name}#{yum_arch}") | |
@yum.refresh | |
installed_version = @yum.installed_version(@new_resource.package_name, arch) | |
@candidate_version = @yum.candidate_version(@new_resource.package_name, arch) | |
@current_resource.version(installed_version) | |
if candidate_version | |
@candidate_version = candidate_version | |
else | |
@candidate_version = installed_version | |
end | |
Chef::Log.debug("#{@new_resource} installed version: #{installed_version} candidate version: #{candidate_version}") | |
@current_resource | |
end | |
def install_package(name, version) | |
if @new_resource.source | |
run_command_with_systems_locale( | |
:command => "yum -d0 -e0 -y #{@new_resource.options} localinstall #{@new_resource.source}" | |
) | |
else | |
# Work around yum not exiting with an error if a package doesn't exist for CHEF-2062 | |
if @yum.version_available?(name, version, yum_arch) | |
run_command_with_systems_locale( | |
:command => "yum -d0 -e0 -y #{@new_resource.options} install #{name}-#{version}#{yum_arch}" | |
) | |
else | |
raise ArgumentError, "#{@new_resource.name}: Version #{version} of #{name} not found. Did you specify both version and release? (version-release, e.g. 1.84-10.fc6)" | |
end | |
end | |
@yum.flush | |
end | |
def upgrade_package(name, version) | |
# If we're not given a version, running update is the correct | |
# option. If we are, then running install_package is right. | |
unless version | |
run_command_with_systems_locale( | |
:command => "yum -d0 -e0 -y #{@new_resource.options} update #{name}#{yum_arch}" | |
) | |
@yum.flush | |
else | |
install_package(name, version) | |
end | |
end | |
def remove_package(name, version) | |
if version | |
run_command_with_systems_locale( | |
:command => "yum -d0 -e0 -y #{@new_resource.options} remove #{name}-#{version}#{yum_arch}" | |
) | |
else | |
run_command_with_systems_locale( | |
:command => "yum -d0 -e0 -y #{@new_resource.options} remove #{name}#{yum_arch}" | |
) | |
end | |
@yum.flush | |
end | |
def purge_package(name, version) | |
remove_package(name, version) | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is there a bug associated with this patch? Apparently there are some people manually applying this file. It would be nice to trace it back into the ticketing system so we can ensure their issues are being resolved.