diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2005-10-20 20:52:56 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2005-10-20 20:52:56 +0000 |
commit | 3cd8ee9186ee0f0cc2127e5598aeebde41e70e5d (patch) | |
tree | 1d3f39e213ab443eca8d7631007697c9055c9731 | |
parent | 66db3d89153bea5ba35ce421416773d7585ae88e (diff) | |
download | puppet-3cd8ee9186ee0f0cc2127e5598aeebde41e70e5d.tar.gz puppet-3cd8ee9186ee0f0cc2127e5598aeebde41e70e5d.tar.xz puppet-3cd8ee9186ee0f0cc2127e5598aeebde41e70e5d.zip |
"latest" is now a valid value for packages, and yum support is also included
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@718 980ebf18-57e1-0310-9a29-db15c13687c0
-rw-r--r-- | lib/puppet/transaction.rb | 6 | ||||
-rw-r--r-- | lib/puppet/type.rb | 6 | ||||
-rw-r--r-- | lib/puppet/type/package.rb | 86 | ||||
-rwxr-xr-x | lib/puppet/type/package/apt.rb | 40 | ||||
-rwxr-xr-x | lib/puppet/type/package/rpm.rb | 17 | ||||
-rwxr-xr-x | lib/puppet/type/package/yum.rb | 58 | ||||
-rw-r--r-- | test/types/tc_package.rb | 79 |
7 files changed, 245 insertions, 47 deletions
diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index a39ec55d1..57f43b17a 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -1,7 +1,3 @@ -#!/usr/local/bin/ruby -w - -# $Id$ - # the class that actually walks our object/state tree, collects the changes, # and performs them @@ -182,3 +178,5 @@ class Transaction end end #--------------------------------------------------------------- + +# $Id$ diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index a460e6024..f0ad6f0e7 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -1026,13 +1026,15 @@ class Type < Puppet::Element end # if all contained objects are in sync, then we're in sync - # FIXME I don't think this is used on the type instances any more + # FIXME I don't think this is used on the type instances any more, + # it's really only used for testing def insync? insync = true states.each { |state| unless state.insync? - Puppet.debug("%s is not in sync" % state) + Puppet.debug("%s is not in sync: %s vs %s" % + [state, state.is, state.should]) insync = false end } diff --git a/lib/puppet/type/package.rb b/lib/puppet/type/package.rb index 6c8057576..098fff48e 100644 --- a/lib/puppet/type/package.rb +++ b/lib/puppet/type/package.rb @@ -7,6 +7,7 @@ require 'puppet/type/state' require 'puppet/type/package/dpkg.rb' require 'puppet/type/package/apt.rb' require 'puppet/type/package/rpm.rb' +require 'puppet/type/package/yum.rb' require 'puppet/type/package/sun.rb' module Puppet @@ -15,9 +16,40 @@ module Puppet class PackageInstalled < Puppet::State @name = :install - @doc = "What state the package should be in. - *true*/*false*/``version``" + @doc = "What state the package should be in. *true*/*false*/*latest*" + + # Override the parent method, because we've got all kinds of + # funky definitions of 'in sync'. + def insync? + Puppet.debug "is: %s" % @is + # Iterate across all of the should values, and see how they turn out. + @should.each { |should| + Puppet.debug "should: %s" % should + case should + when :installed + unless @is == :notinstalled + return true + end + when :latest + latest = @parent.latest + if @is == latest + return true + else + Puppet.warning "latest is %s" % latest + end + when :notinstalled + if @is == :notinstalled + return true + end + when @is + return true + end + } + + return false + end + # This retrieves the current state def retrieve unless defined? @is @parent.retrieve @@ -27,15 +59,22 @@ module Puppet def shouldprocess(value) # possible values are: true, false, and a version number case value - #when true, /^[0-9]/: - when true: - return value - when false: + when "latest": + unless @parent.respond_to?(:latest) + raise Puppet::Error, + "Package type %s does not support querying versions" % + @parent[:type] + end + return :latest + when true, :installed: + return :installed + when false, :notinstalled: return :notinstalled else - raise Puppet::Error.new( - "Invalid install value %s" % value - ) + # We allow them to set a should value however they want, + # but only specific package types will be able to use this + # value + return value end end @@ -43,18 +82,39 @@ module Puppet method = nil event = nil case @should[0] - when true: + when :installed: method = :install event = :package_installed when :notinstalled: method = :remove event = :package_removed + when :latest + if @is == :notinstalled + method = :install + event = :package_installed + else + method = :update + event = :package_updated + end else - raise Puppet::Error, "Invalid should value %s" % @should[0] + unless ! @parent.respond_to?(:versionable?) or @parent.versionable? + Puppet.warning value + raise Puppet::Error, + "Package type %s does not support specifying versions" % + @parent[:type] + else + method = :install + event = :package_installed + end end if @parent.respond_to?(method) + begin @parent.send(method) + rescue => detail + Puppet.err "Could not run %s: %s" % [method, detail.to_s] + raise + end else raise Puppet::Error, "Packages of type %s do not support %s" % [@parent[:type], method] @@ -76,6 +136,7 @@ module Puppet Puppet::PackagingType::APT, Puppet::PackagingType::DPKG, Puppet::PackagingType::RPM, + Puppet::PackagingType::Yum, Puppet::PackagingType::Sun ] @@ -168,7 +229,8 @@ module Puppet Puppet.notice "No support for gentoo yet" @default = nil when "debian": @default = :apt - when "redhat", "fedora": @default = :rpm + when "fedora": @default = :yum + when "redhat": @default = :rpm else Puppet.warning "Using rpm as default type for %s" % Facter["distro"].value diff --git a/lib/puppet/type/package/apt.rb b/lib/puppet/type/package/apt.rb index dd4e69d50..47887ec8a 100755 --- a/lib/puppet/type/package/apt.rb +++ b/lib/puppet/type/package/apt.rb @@ -6,9 +6,20 @@ module Puppet module APT include DPKG - # Install a package using 'apt-get'. + # Install a package using 'apt-get'. This function needs to support + # installing a specific version. def install - cmd = "apt-get install %s" % self.name + should = self.should(:install) + + str = self.name + case should + when true, false, Symbol + # pass + else + # Add the package version + str += "=%s" % should + end + cmd = "apt-get install %s" % str Puppet.info "Executing %s" % cmd.inspect output = %x{#{cmd} 2>&1} @@ -17,6 +28,31 @@ module Puppet raise Puppet::PackageError.new(output) end end + + # What's the latest package version available? + def latest + cmd = "apt-cache show %s" % self.name + output = %x{#{cmd} 2>&1} + + unless $? == 0 + raise Puppet::PackageError.new(output) + end + + if output =~ /Version: (.+)\n/ + return $1 + else + Puppet.debug "No version" + if Puppet[:debug] + print output + end + + return nil + end + end + + def update + self.install + end end end end diff --git a/lib/puppet/type/package/rpm.rb b/lib/puppet/type/package/rpm.rb index 3b195dcbc..ed88af507 100755 --- a/lib/puppet/type/package/rpm.rb +++ b/lib/puppet/type/package/rpm.rb @@ -8,29 +8,28 @@ module Puppet :description => "DESCRIPTION" } - cmd = "rpm -q --qf '%s\n'" % - %w{NAME VERSION DESCRIPTION}.collect { |str| - "%{#{str}}" - }.join(" ") + cmd = "rpm -q #{self.name} --qf '%s\n'" % + "%{NAME} %{VERSION}-%{RELEASE}" # list out all of the packages - str = %x{#{cmd} 2>/dev/null}.chomp + output = %x{#{cmd} 2>/dev/null}.chomp if $? != 0 return nil end - regex = %r{^(\S+)\s+(\S+)\s+(.+)} - fields = [:name, :install, :description] + regex = %r{^(\S+)\s+(\S+)} + #fields = [:name, :install, :description] + fields = [:name, :install] hash = {} - if match = regex.match(str) + if match = regex.match(output) fields.zip(match.captures) { |field,value| hash[field] = value } else raise Puppet::DevError, "Failed to match rpm output '%s'" % - str + output end return hash diff --git a/lib/puppet/type/package/yum.rb b/lib/puppet/type/package/yum.rb new file mode 100755 index 000000000..581f3f326 --- /dev/null +++ b/lib/puppet/type/package/yum.rb @@ -0,0 +1,58 @@ +module Puppet + module PackagingType + # A derivative of DPKG; this is how most people actually manage + # Debian boxes, and the only thing that differs is that it can + # install packages from remote sites. + module Yum + include RPM + + # Install a package using 'apt-get'. + def install + cmd = "yum -y install %s" % self.name + + Puppet.info "Executing %s" % cmd.inspect + output = %x{#{cmd} 2>&1} + + unless $? == 0 + raise Puppet::PackageError.new(output) + end + end + + # What's the latest package version available? + def latest + cmd = "yum list %s" % self.name + output = %x{#{cmd} 2>&1} + + unless $? == 0 + raise Puppet::PackageError.new(output) + end + + if output =~ /#{self.name}\S+\s+(\S+)\s/ + return $1 + else + Puppet.debug "No version" + if Puppet[:debug] + print output + end + + return nil + end + end + + def update + cmd = "yum -y update %s" % self.name + + Puppet.info "Executing %s" % cmd.inspect + output = %x{#{cmd} 2>&1} + + unless $? == 0 + raise Puppet::PackageError.new(output) + end + end + + def versionable? + false + end + end + end +end diff --git a/test/types/tc_package.rb b/test/types/tc_package.rb index 55ef21914..a1eaefa52 100644 --- a/test/types/tc_package.rb +++ b/test/types/tc_package.rb @@ -35,6 +35,27 @@ class TestPackages < Test::Unit::TestCase super end + def tstpkg + case $platform + #when "SunOS" + # type = "sunpkg" + when "Linux" + case Facter["distro"].value + when "Debian": + return %w{zec} + #when "RedHat": type = :rpm + when "Fedora": + return %w{wv} + else + Puppet.notice "No test packags for %s" % $platform + return nil + end + else + Puppet.notice "No test packags for %s" % $platform + return nil + end + end + def mkpkgcomp(pkg) assert_nothing_raised { pkg = Puppet::Type::Package.create(:name => pkg, :install => true) @@ -57,6 +78,7 @@ class TestPackages < Test::Unit::TestCase when "Linux" case Facter["distro"].value when "Debian": pkg = "ssh" + when "Fedora": pkg = "openssh" #when "RedHat": type = :rpm else Puppet.notice "No test package for %s" % $platform @@ -99,29 +121,25 @@ class TestPackages < Test::Unit::TestCase "Somehow retrieved unknown pkg's version") end + def test_latestpkg + pkgs = tstpkg || return + + pkgs.each { |name| + pkg = Puppet::Type::Package.create(:name => name) + assert_nothing_raised { + assert(pkg.latest, "Package did not return value for 'latest'") + } + } + end + unless Process.uid == 0 $stderr.puts "Run as root to perform package installation tests" else def test_installpkg - pkgs = nil - case $platform - #when "SunOS" - # type = "sunpkg" - when "Linux" - case Facter["distro"].value - when "Debian": - pkgs = %w{zec} - #when "RedHat": type = :rpm - else - Puppet.notice "No test packags for %s" % $platform - return - end - else - Puppet.notice "No test packags for %s" % $platform - return - end - + pkgs = tstpkg || return pkgs.each { |pkg| + # we first set install to 'true', and make sure something gets + # installed assert_nothing_raised { pkg = Puppet::Type::Package.create(:name => pkg, :install => true) } @@ -138,10 +156,35 @@ class TestPackages < Test::Unit::TestCase assert_events(comp, [:package_installed], "package") + # then uninstall it + assert_nothing_raised { + pkg[:install] = false + } + + + pkg.retrieve + + assert(! pkg.insync?, "Package is insync") + + assert_events(comp, [:package_removed], "package") + + # and now set install to 'latest' and verify it installs + # FIXME this isn't really a very good test -- we should install + # a low version, and then upgrade using this. But, eh. + assert_nothing_raised { + pkg[:install] = "latest" + } + + assert_events(comp, [:package_installed], "package") + + pkg.retrieve + assert(pkg.insync?, "After install, package is not insync") + assert_nothing_raised { pkg[:install] = false } + pkg.retrieve assert(! pkg.insync?, "Package is insync") |