diff options
| author | Luke Kanies <luke@madstop.com> | 2005-07-27 00:02:39 +0000 |
|---|---|---|
| committer | Luke Kanies <luke@madstop.com> | 2005-07-27 00:02:39 +0000 |
| commit | 700b9650b8188bc9bf36b66e9ee1f78324fd0c16 (patch) | |
| tree | f422a4ce4916225cb6ed5477a488baa6589280d7 /lib/puppet | |
| parent | e685ddb63aec1c6652e289125178ae43106f4041 (diff) | |
| download | puppet-700b9650b8188bc9bf36b66e9ee1f78324fd0c16.tar.gz puppet-700b9650b8188bc9bf36b66e9ee1f78324fd0c16.tar.xz puppet-700b9650b8188bc9bf36b66e9ee1f78324fd0c16.zip | |
dpkg/apt package installation and removal now works
git-svn-id: https://reductivelabs.com/svn/puppet/library/trunk@465 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib/puppet')
| -rw-r--r-- | lib/puppet/type/package.rb | 289 |
1 files changed, 245 insertions, 44 deletions
diff --git a/lib/puppet/type/package.rb b/lib/puppet/type/package.rb index c4ff4e243..b551ad65f 100644 --- a/lib/puppet/type/package.rb +++ b/lib/puppet/type/package.rb @@ -6,26 +6,55 @@ require 'puppet/type/state' require 'puppet/fact' module Puppet + class PackageError < Puppet::Error; end class State class PackageInstalled < Puppet::State @name = :install def retrieve - #self.is = Puppet::PackageTyping[@object.format][@object.name] - unless @parent.class.listed - @parent.class.getpkglist + unless defined? @is + @parent.retrieve + end + + # if the only requirement is that it's installed, then settle + # for that + if @should == true + if @is + @is = true + end + end + end + + def should=(value) + # possible values are: true, false, and a version number + if value == true or value == false or value =~ /^[0-9]/ + @should = value + else + raise Puppet::Error.new( + "Invalid install value %s" % value + ) end - Puppet.debug "package install state is %s" % self.is end def sync - #begin - raise "cannot sync package states yet" - #rescue - # raise "failed to sync #{@params[:file]}: #{$!}" - #end + type = @parent.pkgtype + begin + if @should == false + type.remove(@parent) + else + type.install(@parent) + end + rescue => detail + raise Puppet::Error.new( + "Could not install package %s: %s" % [@parent.name, detail] + ) + end - #return :package_installed + if @should == false + return :package_removed + else + return :package_installed + end end end end @@ -35,13 +64,15 @@ module Puppet # different commands. We need some way to convert specific packages # into the general package object... class Package < Type - attr_reader :version, :format + attr_reader :version, :pkgtype + @states = [ Puppet::State::PackageInstalled ] @parameters = [ - :format, :name, + :type, + :instance, :status, :version, :category, @@ -58,16 +89,57 @@ module Puppet @allowedmethods = [:types] @@types = nil - def Package.clear + @@default = nil + @@platform = nil + + class << self + attr_reader :listed + end + + def self.clear @listed = false super end - def Package.listed - return @listed + def self.default + if @@default.nil? + self.init + end + + return @@default + end + + def self.defaulttype + return Puppet::PackagingType[self.default] + end + + def self.init + unless @@platform = Facter["operatingsystem"].value.downcase + raise Puppet::DevError( + "Must know platform for package management" + ) + end + case @@platform + when "sunos": @@default = :sunpkg + when "linux": + case Facter["distro"].value.downcase + when "gentoo": raise "No support for gentoo yet" + when "debian": @@default = :apt + when "redhat", "fedora": @@default = :rpm + else + #raise "No default type for " + Puppet::Fact["distro"] + Puppet.warning "Using rpm as default type for %s" % + Facter["distro"].value + @@default = :rpm + end + else + raise Puppet::Error.new( + "No default type for " + Puppet::Fact["operatingsystem"] + ) + end end - def Package.types(array) + def self.types(array) unless array.is_a?(Array) array = [array] end @@ -75,25 +147,12 @@ module Puppet Puppet.debug "Types are %s" % array.join(" ") end - def Package.getpkglist + def self.getpkglist if @@types.nil? - case Puppet::Fact["operatingsystem"] - when "SunOS": @@types = ["sunpkg"] - when "Linux": - case Puppet::Fact["distro"] - when "Gentoo": raise "No support for gentoo yet" - when "Debian": @@types = ["dpkg"] - when "RedHat": @@types = ["rpm"] - when "Fedora": @@types = ["rpm"] - else - #raise "No default type for " + Puppet::Fact["distro"] - Puppet.warning "Using rpm as default type for %s" % - Puppet::Fact["distro"] - @@types = ["rpm"] - end - else - raise "No default type for " + Puppet::Fact["operatingsystem"] + if @@default.nil? + self.init end + @@types = [@@default] end list = @@types.collect { |type| @@ -156,6 +215,14 @@ module Puppet end end + def self.pkgtype(pkgtype) + if @typeary.length != @typehash.length + self.buildpkgtypehash + end + + return @typehash[pkgtype] + end + def addis(state,value) if stateklass = self.class.validstate?(state) @states[state] = stateklass.new(:parent => self) @@ -173,14 +240,88 @@ module Puppet # be set in 'should', or through comparing against the system, in which # case the hash's values should be set in 'is' def initialize(hash) + unless hash.include?(:install) or hash.include?("install") + Puppet.debug "Defaulting to installing a package" + hash[:install] = true + end + super + + unless @parameters.include?(:type) + if @@default.nil? + self.class.init + end + self[:type] = @@default + end end + def retrieve + unless pkgtype = Puppet::PackagingType[@parameters[:type]] + raise Puppet::DevError.new( + "No support for type %s" % @parameters[:type] + ) + end + + begin + hash = pkgtype.query(self) + rescue => error + Puppet.err "Cannot install %s: %s" % + [self.name, error.to_s] + + @states.delete(:install) + end + + if hash.nil? + @states[:install].is = nil + end + + hash.each { |name,value| + if self.class.validstate?(name) + if @states.include?(name) + @states[name].is = value + else + # silently ignore any returned states + # that we're not managing + # this is highly unlikely to happen + Puppet.info "%s missing state %s" % + [self.name, name] + end + elsif self.class.validparameter?(name) + self[name] = value + else + # silently ignore anything that's not a valid state + # or param + end + } + + # now let them all handle things as necessary + @states.each { |name, state| + state.retrieve + } + end + + def paramtype=(typename) + @parameters[:type] = typename + pkgtype = nil + + unless pkgtype = Puppet::PackagingType[typename] + raise Puppet::Error.new( + "Could not find package type %s" % typename + ) + end + + @pkgtype = pkgtype + end end # Puppet::Type::Package end class PackagingType - attr_writer :list, :install, :remove, :check + @params = [:list, :query, :remove, :install] + attr_writer(*@params) + + class << self + attr_reader :params + end @@types = Hash.new(false) @@ -201,12 +342,12 @@ module Puppet return @packages[name] end - [:list, :install, :remove, :check].each { |method| - self.send(:define_method, method) { + @params.each { |method| + self.send(:define_method, method) { |pkg| # retrieve the variable var = eval("@" + method.id2name) if var.is_a?(Proc) - var.call() + var.call(pkg) else raise "only blocks are supported right now" end @@ -229,7 +370,60 @@ module Puppet end end - PackagingType.new("dpkg") { |type| + PackagingType.new(:apt) { |type| + type.query = proc { |pkg| + packages = [] + + # dpkg only prints as many columns as you have available + # which means we don't get all of the info + # stupid stupid + oldcol = ENV["COLUMNS"] + ENV["COLUMNS"] = "500" + fields = [:desired, :status, :error, :name, :version, :description] + + hash = {} + # list out all of the packages + open("| dpkg -l %s 2>/dev/null" % pkg) { |process| + # our regex for matching dpkg output + regex = %r{^(.)(.)(.)\s(\S+)\s+(\S+)\s+(.+)$} + + # we only want the last line + lines = process.readlines + # we've got four header lines, so we should expect all of those + # plus our output + if lines.length < 5 + return nil + end + + line = lines[-1] + + if match = regex.match(line) + fields.zip(match.captures) { |field,value| + hash[field] = value + } + #packages.push Puppet::Type::Package.installedpkg(hash) + else + raise "failed to match dpkg line %s" % line + end + } + ENV["COLUMNS"] = oldcol + + if hash[:error] != " " + raise Puppet::PackageError.new( + "Package %s, version %s is in error state: %s" % + [hash[:name], hash[:install], hash[:error]] + ) + end + + if hash[:status] == "i" + hash[:install] = hash[:version] + else + # this isn't really correct, but we'll settle for it for now + hash[:install] = nil + end + + return hash + } type.list = proc { packages = [] @@ -269,20 +463,27 @@ module Puppet # we need package retrieval mechanisms before we can have package # installation mechanisms... - #type.install = proc { |pkg| - # raise "installation not implemented yet" - #} + type.install = proc { |pkg| + cmd = "apt-get install %s" % pkg + + Puppet.info "Executing %s" % cmd.inspect + output = %x{#{cmd} 2>&1} + + unless $? == 0 + raise Puppet::PackageError.new(output) + end + } type.remove = proc { |pkg| cmd = "dpkg -r %s" % pkg.name output = %x{#{cmd}} if $? != 0 - raise output + raise Puppet::PackageError.new(output) end } } - PackagingType.new("rpm") { |type| + PackagingType.new(:rpm) { |type| type.list = proc { packages = [] @@ -333,7 +534,7 @@ module Puppet } } - PackagingType.new("sunpkg") { |type| + PackagingType.new(:sunpkg) { |type| type.list = proc { packages = [] hash = {} |
