Skip to content

Commit

Permalink
CHEF-2550: Report source repository when installing.
Browse files Browse the repository at this point in the history
  • Loading branch information
mdkent authored and btm committed Mar 16, 2012
1 parent d8336f6 commit 68498d7
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 47 deletions.
5 changes: 3 additions & 2 deletions chef/lib/chef/provider/package/yum-dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,15 @@ def dump_packages(yb, list, output_provides):
else:
provides = "[]"

print '%s %s %s %s %s %s %s' % (
print '%s %s %s %s %s %s %s %s' % (
pkg.name,
pkg.epoch,
pkg.version,
pkg.release,
pkg.arch,
provides,
pkg.type )
pkg.type,
pkg.repoid )

return 0

Expand Down
53 changes: 45 additions & 8 deletions chef/lib/chef/provider/package/yum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -497,12 +497,13 @@ class RPMRequire < RPMDependency; end
class RPMDbPackage < RPMPackage
# <rpm parts>, installed, available
def initialize(*args)
@repoid = args.pop
# state
@available = args.pop
@installed = args.pop
super(*args)
end
attr_reader :available, :installed
attr_reader :repoid, :available, :installed
end

# Simple storage for RPMPackage objects - keeps them unique and sorted
Expand Down Expand Up @@ -712,14 +713,15 @@ def refresh
next
end

if line =~ %r{^(\S+) ([0-9]+) (\S+) (\S+) (\S+) \[(.*)\] ([i,a,r])$}
if line =~ %r{^(\S+) ([0-9]+) (\S+) (\S+) (\S+) \[(.*)\] ([i,a,r]) (\S+)$}
name = $1
epoch = $2
version = $3
release = $4
arch = $5
provides = parse_provides($6)
type = $7
repoid = $8
else
Chef::Log.warn("Problem parsing line '#{line}' from yum-dump.py! " +
"Please check your yum configuration.")
Expand All @@ -740,7 +742,7 @@ def refresh
installed = true
end

pkg = RPMDbPackage.new(name, epoch, version, release, arch, provides, installed, available)
pkg = RPMDbPackage.new(name, epoch, version, release, arch, provides, installed, available, repoid)
@rpmdb << pkg
end

Expand Down Expand Up @@ -811,23 +813,36 @@ def packages_from_require(rpmdep)
@rpmdb.whatprovides(rpmdep)
end

# Check if a package-version.arch is available to install
def version_available?(package_name, desired_version, arch=nil)
version(package_name, arch, true, false) do |v|
return true if desired_version == v
end
version(package_name, arch, true, false) do |v|
return true if desired_version == v
end

return false
end

# Return the source repository for a package-version.arch
def package_repository(package_name, desired_version, arch=nil)
package(package_name, arch, true, false) do |pkg|
return pkg.repoid if desired_version == pkg.version.to_s
end

return nil
end

# Return the latest available version for a package.arch
def available_version(package_name, arch=nil)
version(package_name, arch, true, false)
end
alias :candidate_version :available_version

# Return the currently installed version for a package.arch
def installed_version(package_name, arch=nil)
version(package_name, arch, false, true)
end

# Return an array of packages allowed to be installed multiple times, such as the kernel
def allow_multi_install
refresh
@allow_multi_install
Expand All @@ -836,6 +851,23 @@ def allow_multi_install
private

def version(package_name, arch=nil, is_available=false, is_installed=false)
package(package_name, arch, is_available, is_installed) do |pkg|
if block_given?
yield pkg.version.to_s
else
# first match is latest version
return pkg.version.to_s
end
end

if block_given?
return self
else
return nil
end
end

def package(package_name, arch=nil, is_available=false, is_installed=false)
refresh
packages = @rpmdb[package_name]
if packages
Expand All @@ -851,10 +883,10 @@ def version(package_name, arch=nil, is_available=false, is_installed=false)
end

if block_given?
yield pkg.version.to_s
yield pkg
else
# first match is latest version
return pkg.version.to_s
return pkg
end
end
end
Expand Down Expand Up @@ -1026,6 +1058,7 @@ def install_package(name, version)
# Work around yum not exiting with an error if a package doesn't exist for CHEF-2062
if @yum.version_available?(name, version, arch)
method = "install"
log_method = "installing"

# More Yum fun:
#
Expand All @@ -1038,6 +1071,7 @@ def install_package(name, version)
# Unless they want this...
if allow_downgrade
method = "downgrade"
log_method = "downgrading"
else
# we bail like yum when the package is older
raise Chef::Exceptions::Package, "Installed package #{name}-#{@current_resource.version} is newer " +
Expand All @@ -1046,6 +1080,9 @@ def install_package(name, version)
end
end

repo = @yum.package_repository(name, version, arch)
Chef::Log.info("#{@new_resource} #{log_method} #{name}-#{version}#{yum_arch} from #{repo} repository")

yum_command("yum -d0 -e0 -y#{expand_options(@new_resource.options)} #{method} #{name}-#{version}#{yum_arch}")
else
raise Chef::Exceptions::Package, "Version #{version} of #{name} not found. Did you specify both version " +
Expand Down
114 changes: 77 additions & 37 deletions chef/spec/unit/provider/package/yum_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
:candidate_version => "1.2.4-11.18.el5_2.3",
:package_available? => true,
:version_available? => true,
:allow_multi_install => [ "kernel" ]
:allow_multi_install => [ "kernel" ],
:package_repository => "base"
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
Expand Down Expand Up @@ -395,7 +396,8 @@
:candidate_version => "1.2.4-11.15.el5",
:package_available? => true,
:version_available? => true,
:allow_multi_install => [ "cups" ]
:allow_multi_install => [ "cups" ],
:package_repository => "base"
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
Expand All @@ -416,7 +418,8 @@
:candidate_version => "1.2.4-11.15.el5",
:package_available? => true,
:version_available? => true,
:allow_multi_install => []
:allow_multi_install => [],
:package_repository => "base"
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
Expand Down Expand Up @@ -1088,10 +1091,10 @@

describe Chef::Provider::Package::Yum::RPMDbPackage do
before(:each) do
# name, version, arch, installed, available
@rpm_x = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "0:1.6.5-9.36.el5", "noarch", [], false, true)
@rpm_y = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "0:1.6.5-9.36.el5", "noarch", [], true, true)
@rpm_z = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "0:1.6.5-9.36.el5", "noarch", [], true, false)
# name, version, arch, installed, available, repoid
@rpm_x = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "0:1.6.5-9.36.el5", "noarch", [], false, true, "base")
@rpm_y = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "0:1.6.5-9.36.el5", "noarch", [], true, true, "extras")
@rpm_z = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "0:1.6.5-9.36.el5", "noarch", [], true, false, "other")
end

describe "initialize" do
Expand All @@ -1116,6 +1119,13 @@
end
end

describe "repoid" do
it "should return the source repository repoid" do
@rpm_x.repoid.should be == "base"
@rpm_y.repoid.should be == "extras"
@rpm_z.repoid.should be == "other"
end
end
end

describe Chef::Provider::Package::Yum::RPMDependency do
Expand Down Expand Up @@ -1305,12 +1315,12 @@
Chef::Provider::Package::Yum::RPMDependency.parse("config(test) = 0:1.6.5-9.36.el5"),
Chef::Provider::Package::Yum::RPMDependency.parse("test-package-c = 0:1.6.5-9.36.el5")
]
@rpm_v = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-a", "0:1.6.5-9.36.el5", "i386", deps_v, true, false)
@rpm_w = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "0:1.6.5-9.36.el5", "i386", [], true, true)
@rpm_x = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "0:1.6.5-9.36.el5", "x86_64", [], false, true)
@rpm_y = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "1:1.6.5-9.36.el5", "x86_64", [], true, true)
@rpm_z = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-c", "0:1.6.5-9.36.el5", "noarch", deps_z, true, true)
@rpm_z_mirror = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-c", "0:1.6.5-9.36.el5", "noarch", deps_z, true, true)
@rpm_v = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-a", "0:1.6.5-9.36.el5", "i386", deps_v, true, false, "base")
@rpm_w = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "0:1.6.5-9.36.el5", "i386", [], true, true, "extras")
@rpm_x = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "0:1.6.5-9.36.el5", "x86_64", [], false, true, "extras")
@rpm_y = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-b", "1:1.6.5-9.36.el5", "x86_64", [], true, true, "extras")
@rpm_z = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-c", "0:1.6.5-9.36.el5", "noarch", deps_z, true, true, "base")
@rpm_z_mirror = Chef::Provider::Package::Yum::RPMDbPackage.new("test-package-c", "0:1.6.5-9.36.el5", "noarch", deps_z, true, true, "base")
end

describe "initialize" do
Expand Down Expand Up @@ -1502,36 +1512,36 @@ def reset_instance
before(:each) do
yum_dump_good_output = <<EOF
[option installonlypkgs] kernel kernel-bigmem kernel-enterprise
erlang-mochiweb 0 1.4.1 5.el5 x86_64 ['erlang-mochiweb = 1.4.1-5.el5', 'mochiweb = 1.4.1-5.el5'] i
zip 0 2.31 2.el5 x86_64 ['zip = 2.31-2.el5'] r
zisofs-tools 0 1.0.6 3.2.2 x86_64 [] a
zlib 0 1.2.3 3 x86_64 ['zlib = 1.2.3-3', 'libz.so.1()(64bit)'] r
zlib 0 1.2.3 3 i386 ['zlib = 1.2.3-3', 'libz.so.1'] r
zlib-devel 0 1.2.3 3 i386 [] a
zlib-devel 0 1.2.3 3 x86_64 ['zlib-devel = 1.2.3-3'] r
znc 0 0.098 1.el5 x86_64 [] a
znc-devel 0 0.098 1.el5 i386 [] a
znc-devel 0 0.098 1.el5 x86_64 [] a
znc-extra 0 0.098 1.el5 x86_64 [] a
znc-modtcl 0 0.098 1.el5 x86_64 [] a
znc-test.beta1 0 0.098 1.el5 x86_64 [] a
znc-test.test.beta1 0 0.098 1.el5 x86_64 [] a
erlang-mochiweb 0 1.4.1 5.el5 x86_64 ['erlang-mochiweb = 1.4.1-5.el5', 'mochiweb = 1.4.1-5.el5'] i installed
zip 0 2.31 2.el5 x86_64 ['zip = 2.31-2.el5'] r base
zisofs-tools 0 1.0.6 3.2.2 x86_64 [] a extras
zlib 0 1.2.3 3 x86_64 ['zlib = 1.2.3-3', 'libz.so.1()(64bit)'] r base
zlib 0 1.2.3 3 i386 ['zlib = 1.2.3-3', 'libz.so.1'] r base
zlib-devel 0 1.2.3 3 i386 [] a extras
zlib-devel 0 1.2.3 3 x86_64 ['zlib-devel = 1.2.3-3'] r base
znc 0 0.098 1.el5 x86_64 [] a base
znc-devel 0 0.098 1.el5 i386 [] a extras
znc-devel 0 0.098 1.el5 x86_64 [] a base
znc-extra 0 0.098 1.el5 x86_64 [] a base
znc-modtcl 0 0.098 1.el5 x86_64 [] a base
znc-test.beta1 0 0.098 1.el5 x86_64 [] a extras
znc-test.test.beta1 0 0.098 1.el5 x86_64 [] a base
EOF

yum_dump_bad_output_separators = <<EOF
zip 0 2.31 2.el5 x86_64 ['zip = 2.31-2.el5'] r
zlib 0 1.2.3 3 x86_64 ['zlib = 1.2.3-3', 'libz.so.1()(64bit)'] i bad
zlib-devel 0 1.2.3 3 i386 [] a
bad zlib-devel 0 1.2.3 3 x86_64 ['zlib-devel = 1.2.3-3'] i
znc-modtcl 0 0.098 1.el5 x86_64 [] a bad
zip 0 2.31 2.el5 x86_64 ['zip = 2.31-2.el5'] r base
zlib 0 1.2.3 3 x86_64 ['zlib = 1.2.3-3', 'libz.so.1()(64bit)'] i base bad
zlib-devel 0 1.2.3 3 i386 [] a extras
bad zlib-devel 0 1.2.3 3 x86_64 ['zlib-devel = 1.2.3-3'] i installed
znc-modtcl 0 0.098 1.el5 x86_64 [] a base bad
EOF

yum_dump_bad_output_type = <<EOF
zip 0 2.31 2.el5 x86_64 ['zip = 2.31-2.el5'] r
zlib 0 1.2.3 3 x86_64 ['zlib = 1.2.3-3', 'libz.so.1()(64bit)'] c
zlib-devel 0 1.2.3 3 i386 [] a
zlib-devel 0 1.2.3 3 x86_64 ['zlib-devel = 1.2.3-3'] bad
znc-modtcl 0 0.098 1.el5 x86_64 [] a
zip 0 2.31 2.el5 x86_64 ['zip = 2.31-2.el5'] r base
zlib 0 1.2.3 3 x86_64 ['zlib = 1.2.3-3', 'libz.so.1()(64bit)'] c base
zlib-devel 0 1.2.3 3 i386 [] a extras
zlib-devel 0 1.2.3 3 x86_64 ['zlib-devel = 1.2.3-3'] bad installed
znc-modtcl 0 0.098 1.el5 x86_64 [] a base
EOF

yum_dump_error = <<EOF
Expand Down Expand Up @@ -1718,6 +1728,36 @@ def reset_instance
end
end

describe "package_repository" do
it "should take two or three arguments" do
lambda { @yc.package_repository("zisofs-tools") }.should raise_error(ArgumentError)
lambda { @yc.package_repository("zisofs-tools", "1.0.6-3.2.2") }.should_not raise_error(ArgumentError)
lambda { @yc.package_repository("zisofs-tools", "1.0.6-3.2.2", "x86_64") }.should_not raise_error(ArgumentError)
end

it "should return repoid for package-version-arch" do
@yc.package_repository("zlib-devel", "1.2.3-3", "i386").should be == "extras"
@yc.package_repository("zlib-devel", "1.2.3-3", "x86_64").should be == "base"
end

it "should return repoid for package-version, no arch" do
@yc.package_repository("zisofs-tools", "1.0.6-3.2.2", nil).should be == "extras"
@yc.package_repository("zisofs-tools", "1.0.6-3.2.2").should be == "extras"
end

it "should return nil when no match for package-version-arch" do
@yc.package_repository("zisofs-tools", "1.0.6-3.2.2", "pretend").should be == nil
@yc.package_repository("zisofs-tools", "pretend", "x86_64").should be == nil
@yc.package_repository("pretend", "1.0.6-3.2.2", "x86_64").should be == nil
end

it "should return nil when no match for package-version, no arch" do
@yc.package_repository("zisofs-tools", "pretend", nil).should be == nil
@yc.package_repository("zisofs-tools", "pretend").should be == nil
@yc.package_repository("pretend", "1.0.6-3.2.2").should be == nil
end
end

describe "reset" do
it "should empty the installed and available packages RPMDb" do
@yc.available_version("zip", "x86_64").should be == "2.31-2.el5"
Expand Down

0 comments on commit 68498d7

Please sign in to comment.