summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRick Bradley <rick@rickbradley.com>2007-10-03 16:42:28 -0500
committerRick Bradley <rick@rickbradley.com>2007-10-03 16:42:28 -0500
commit1334b786ac622a6094ba68b3e66fce3f5841deed (patch)
tree70692f08d0dcbb327bfdd899b019f559780c135a
parent3f90ddbfc7d20b631ca17f72e2d72d5e7ca00629 (diff)
parentb727a95aa4b72ce057653101cf1f50fa49c4b0a8 (diff)
downloadpuppet-1334b786ac622a6094ba68b3e66fce3f5841deed.tar.gz
puppet-1334b786ac622a6094ba68b3e66fce3f5841deed.tar.xz
puppet-1334b786ac622a6094ba68b3e66fce3f5841deed.zip
Merge branch 'master' of git://reductivelabs.com/puppet into routing
-rw-r--r--lib/puppet/module.rb13
-rwxr-xr-xlib/puppet/provider/package/rpm.rb75
-rwxr-xr-xlib/puppet/provider/package/yum.rb58
-rw-r--r--lib/puppet/provider/package/yumhelper.py37
-rwxr-xr-xspec/unit/other/modules.rb51
-rwxr-xr-xtest/ral/types/package.rb3
6 files changed, 165 insertions, 72 deletions
diff --git a/lib/puppet/module.rb b/lib/puppet/module.rb
index dc30d8167..45860c74d 100644
--- a/lib/puppet/module.rb
+++ b/lib/puppet/module.rb
@@ -27,8 +27,8 @@ class Puppet::Module
return nil
end
- modpath = modulepath(environment).collect { |p|
- File::join(p, modname)
+ modpath = modulepath(environment).collect { |path|
+ File::join(path, modname)
}.find { |f| File::directory?(f) }
return nil unless modpath
@@ -72,10 +72,9 @@ class Puppet::Module
# Otherwise, try to find manifests matching +pat+ relative to +cwd+
def self.find_manifests(start, options = {})
cwd = options[:cwd] || Dir.getwd
- path, pat = split_path(start)
- mod = find(path, options[:environment])
- if mod
- return mod.manifests(pat)
+ module_name, pattern = split_path(start)
+ if module_name and mod = find(module_name, options[:environment])
+ return mod.manifests(pattern)
else
abspat = File::expand_path(start, cwd)
files = Dir.glob(abspat).reject { |f| FileTest.directory?(f) }
@@ -87,6 +86,8 @@ class Puppet::Module
end
# Split the path into the module and the rest of the path.
+ # This method can and often does return nil, so anyone calling
+ # it needs to handle that.
def self.split_path(path)
if path =~ %r/^#{File::SEPARATOR}/
return nil
diff --git a/lib/puppet/provider/package/rpm.rb b/lib/puppet/provider/package/rpm.rb
index a31e4edf6..6e0ba5070 100755
--- a/lib/puppet/provider/package/rpm.rb
+++ b/lib/puppet/provider/package/rpm.rb
@@ -5,15 +5,14 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
binary."
# The query format by which we identify installed packages
- NVRFORMAT = "%{NAME}-%{VERSION}-%{RELEASE}"
-
- VERSIONSTRING = "%{VERSION}-%{RELEASE}"
+ NEVRAFORMAT = "%{NAME} %|EPOCH?{%{EPOCH}}:{0}| %{VERSION} %{RELEASE} %{ARCH}"
+ NEVRA_FIELDS = [:name, :epoch, :version, :release, :arch]
commands :rpm => "rpm"
if command('rpm')
confine :true => begin
- rpm('-ql', 'rpm')
+ rpm('--version')
rescue Puppet::ExecutionFailure
false
else
@@ -26,23 +25,11 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
# list out all of the packages
begin
- execpipe("#{command(:rpm)} -qa --nosignature --nodigest --qf '%{NAME} #{VERSIONSTRING}\n'") { |process|
- # our regex for matching dpkg output
- regex = %r{^(\S+)\s+(\S+)}
- fields = [:name, :ensure]
-
+ execpipe("#{command(:rpm)} -qa --nosignature --nodigest --qf '#{NEVRAFORMAT}\n'") { |process|
# now turn each returned line into a package object
process.each { |line|
- if match = regex.match(line)
- hash = {}
- fields.zip(match.captures) { |field,value|
- hash[field] = value
- }
- hash[:provider] = self.name
- packages << new(hash)
- else
- raise "failed to match rpm line %s" % line
- end
+ hash = nevra_to_hash(line)
+ packages << new(hash)
}
}
rescue Puppet::ExecutionFailure
@@ -56,30 +43,21 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
# a hash with entries :instance => fully versioned package name, and
# :ensure => version-release
def query
- cmd = ["-q", @resource[:name], "--nosignature", "--nodigest", "--qf", "#{NVRFORMAT} #{VERSIONSTRING}\n"]
-
- begin
- output = rpm(*cmd)
- rescue Puppet::ExecutionFailure
- return nil
+ unless @property_hash[:epoch]
+ cmd = ["-q", @resource[:name], "--nosignature", "--nodigest", "--qf", "#{NEVRAFORMAT}\n"]
+
+ begin
+ output = rpm(*cmd)
+ rescue Puppet::ExecutionFailure
+ return nil
+ end
+
+ # FIXME: We could actually be getting back multiple packages
+ # for multilib
+ @property_hash.update(self.class.nevra_to_hash(output))
end
- regex = %r{^(\S+)\s+(\S+)}
- fields = [:instance, :ensure]
- attrs = {}
- if match = regex.match(output)
- fields.zip(match.captures) { |field,value|
- attrs[field] = value
- }
- else
- raise Puppet::DevError,
- "Failed to match rpm output '%s'" %
- output
- end
-
- @nvr = attrs[:instance]
-
- return attrs
+ return @property_hash.dup
end
# Here we just retrieve the version from the file specified in the source.
@@ -88,9 +66,9 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
@resource.fail "RPMs must specify a package source"
end
- cmd = [command(:rpm), "-q", "--qf", "#{VERSIONSTRING}", "-p", "#{@resource[:source]}"]
- version = execfail(cmd, Puppet::Error)
- return version
+ cmd = [command(:rpm), "-q", "--qf", "#{NEVRAFORMAT}\n", "-p", "#{@resource[:source]}"]
+ h = nevra_to_hash(execfail(cmd, Puppet::Error))
+ return h[:ensure]
end
def install
@@ -125,6 +103,15 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
query unless @nvr
@nvr
end
+
+ def self.nevra_to_hash(line)
+ line.chomp!
+ hash = {}
+ NEVRA_FIELDS.zip(line.split) { |f, v| hash[f] = v }
+ hash[:provider] = self.name
+ hash[:ensure] = "#{hash[:version]}-#{hash[:release]}"
+ return hash
+ end
end
# $Id$
diff --git a/lib/puppet/provider/package/yum.rb b/lib/puppet/provider/package/yum.rb
index 13863ee55..a9427061c 100755
--- a/lib/puppet/provider/package/yum.rb
+++ b/lib/puppet/provider/package/yum.rb
@@ -3,11 +3,17 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
has_feature :versionable
- commands :yum => "yum", :rpm => "rpm"
+ commands :yum => "yum", :rpm => "rpm", :python => "python"
+
+ YUMHELPER = File::join(File::dirname(__FILE__), "yumhelper.py")
+
+ class << self
+ attr_reader :updates
+ end
if command('rpm')
confine :true => begin
- rpm('-ql', 'rpm')
+ rpm('--version')
rescue Puppet::ExecutionFailure
false
else
@@ -17,8 +23,26 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
defaultfor :operatingsystem => [:fedora, :centos, :redhat]
- def install
+ def self.prefetch(packages)
+ @updates = {}
+ if Process.euid != 0
+ raise Puppet::Error, "The yum provider can only be used as root"
+ end
+ super
+ python(YUMHELPER).each_line do |l|
+ l.chomp!
+ next if l.empty?
+ if l[0,4] == "_pkg"
+ hash = nevra_to_hash(l[5..-1])
+ [hash[:name], "#{hash[:name]}.#{hash[:arch]}"].each do |n|
+ @updates[n] ||= []
+ @updates[n] << hash
+ end
+ end
+ end
+ end
+ def install
should = @resource.should(:ensure)
self.debug "Ensuring => #{should}"
wanted = @resource[:name]
@@ -27,6 +51,7 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
case should
when true, false, Symbol
# pass
+ should = nil
else
# Add the package version
wanted += "-%s" % should
@@ -34,26 +59,33 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
output = yum "-d", "0", "-e", "0", "-y", :install, wanted
- unless self.query
- raise Puppet::Error.new(
- "Could not find package %s" % self.name
- )
+ is = self.query
+ unless is
+ raise Puppet::Error, "Could not find package %s" % self.name
+ end
+
+ # FIXME: Should we raise an exception even if should == :latest
+ # and yum updated us to a version other than @param_hash[:ensure] ?
+ if should && should != is[:ensure]
+ raise Puppet::Error, "Failed to update to version #{should}, got version #{is[:ensure]} instead"
end
end
# What's the latest package version available?
def latest
- output = yum "-d", "0", "-e", "0", :list, :available, @resource[:name]
-
- if output =~ /^#{Regexp.escape(@resource[:name])}\S+\s+(\S+)\s/
- return $1
+ upd = self.class.updates[@resource[:name]]
+ unless upd.nil?
+ # FIXME: there could be more than one update for a package
+ # because of multiarch
+ upd = upd[0]
+ return "#{upd[:version]}-#{upd[:release]}"
else
# Yum didn't find updates, pretend the current
# version is the latest
- unless properties[:ensure] != :absent
+ if properties[:ensure] == :absent
raise Puppet::DevError, "Tried to get latest on a missing package"
end
- return @property_hash[:ensure]
+ return properties[:ensure]
end
end
diff --git a/lib/puppet/provider/package/yumhelper.py b/lib/puppet/provider/package/yumhelper.py
new file mode 100644
index 000000000..1142401b9
--- /dev/null
+++ b/lib/puppet/provider/package/yumhelper.py
@@ -0,0 +1,37 @@
+# Python helper script to query for the packages that have
+# pending updates. Called by the yum package provider
+#
+# (C) 2007 Red Hat Inc.
+# David Lutterkort <dlutter @redhat.com>
+
+import yum
+import sys
+
+OVERRIDE_OPTS = {
+ 'debuglevel': 0,
+ 'errorlevel': 0,
+ 'logfile': '/dev/null'
+}
+
+def pkg_lists():
+ my = yum.YumBase()
+ my.doConfigSetup()
+
+ for k in OVERRIDE_OPTS.keys():
+ if hasattr(my.conf, k):
+ setattr(my.conf, k, OVERRIDE_OPTS[k])
+ else:
+ my.conf.setConfigOption(k, OVERRIDE_OPTS[k])
+
+ my.doTsSetup()
+ my.doRpmDBSetup()
+ return my.doPackageLists('updates')
+
+try:
+ ypl = pkg_lists()
+except IOError, e:
+ print "_err IOError %d %s" % (e.errno, e)
+ sys.exit(1)
+
+for pkg in ypl.updates:
+ print "_pkg %s %s %s %s %s" % (pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch)
diff --git a/spec/unit/other/modules.rb b/spec/unit/other/modules.rb
index f53c43e89..26ca3907d 100755
--- a/spec/unit/other/modules.rb
+++ b/spec/unit/other/modules.rb
@@ -108,22 +108,55 @@ describe Puppet::Module, " when searching for templates" do
after { Puppet.settings.clear }
end
-describe Puppet::Module, " when searching for manifests" do
- it "should return the manifests from the first found module" do
- Puppet[:modulepath] = "/one:/two"
- File.stubs(:directory?).returns(true)
- Dir.expects(:glob).with("/one/mymod/manifests/init.pp").returns(%w{/one/mymod/manifests/init.pp})
- Puppet::Module.find_manifests("mymod/init.pp").should == ["/one/mymod/manifests/init.pp"]
+describe Puppet::Module, " when searching for manifests when no module is found" do
+ before do
+ File.stubs(:find).returns(nil)
end
- it "should search the cwd if no module is found" do
- Puppet[:modulepath] = "/one:/two"
- File.stubs(:find).returns(nil)
+ it "should not look for modules when paths are fully qualified" do
+ Puppet.expects(:value).with(:modulepath).never
+ file = "/fully/qualified/file.pp"
+ Dir.stubs(:glob).with(file).returns([file])
+ Puppet::Module.find_manifests(file)
+ end
+
+ it "should directly return fully qualified files" do
+ file = "/fully/qualified/file.pp"
+ Dir.stubs(:glob).with(file).returns([file])
+ Puppet::Module.find_manifests(file).should == [file]
+ end
+
+ it "should match against provided fully qualified patterns" do
+ pattern = "/fully/qualified/pattern/*"
+ Dir.expects(:glob).with(pattern).returns(%w{my file list})
+ Puppet::Module.find_manifests(pattern).should == %w{my file list}
+ end
+
+ it "should look for files relative to the current directory" do
cwd = Dir.getwd
Dir.expects(:glob).with("#{cwd}/mymod/init.pp").returns(["#{cwd}/mymod/init.pp"])
Puppet::Module.find_manifests("mymod/init.pp").should == ["#{cwd}/mymod/init.pp"]
end
+ it "should only return files, not directories" do
+ pattern = "/fully/qualified/pattern/*"
+ file = "/my/file"
+ dir = "/my/directory"
+ Dir.expects(:glob).with(pattern).returns([file, dir])
+ FileTest.expects(:directory?).with(file).returns(false)
+ FileTest.expects(:directory?).with(dir).returns(true)
+ Puppet::Module.find_manifests(pattern).should == [file]
+ end
+end
+
+describe Puppet::Module, " when searching for manifests in a found module" do
+ it "should return the manifests from the first found module" do
+ Puppet[:modulepath] = "/one:/two"
+ File.stubs(:directory?).returns(true)
+ Dir.expects(:glob).with("/one/mymod/manifests/init.pp").returns(%w{/one/mymod/manifests/init.pp})
+ Puppet::Module.find_manifests("mymod/init.pp").should == ["/one/mymod/manifests/init.pp"]
+ end
+
it "should use the node environment if specified" do
Puppet.settings.expects(:value).with(:modulepath, "myenv").returns("/env/modules")
File.stubs(:directory?).returns(true)
diff --git a/test/ral/types/package.rb b/test/ral/types/package.rb
index 79b769c26..e97c6bd3c 100755
--- a/test/ral/types/package.rb
+++ b/test/ral/types/package.rb
@@ -120,6 +120,9 @@ class TestPackages < Test::Unit::TestCase
# Make sure we can prefetch package information, rather than getting it one package at a time.
def test_prefetch
@type.providers_by_source.each do |provider|
+ # The yum provider can't be used if you're not root
+ next if provider.name == :yum && Process.euid != 0
+
# First get a list of packages
list = provider.instances