diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2007-03-19 08:15:36 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2007-03-19 08:15:36 +0000 |
commit | 5b2ffbcb5d2e4113efec9c8ba882c5506d53c242 (patch) | |
tree | b4127af05cf5682f38fbca928c9fb53e0b42f52b /lib | |
parent | 80dac92b3a5ebd2cb8904505845d63759b5cebb3 (diff) | |
download | puppet-5b2ffbcb5d2e4113efec9c8ba882c5506d53c242.tar.gz puppet-5b2ffbcb5d2e4113efec9c8ba882c5506d53c242.tar.xz puppet-5b2ffbcb5d2e4113efec9c8ba882c5506d53c242.zip |
Adding provider features. Woot!
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@2313 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib')
-rw-r--r-- | lib/puppet/metatype/providers.rb | 76 | ||||
-rw-r--r-- | lib/puppet/provider.rb | 8 | ||||
-rw-r--r-- | lib/puppet/type/package.rb | 27 | ||||
-rw-r--r-- | lib/puppet/util/provider_features.rb | 108 |
4 files changed, 216 insertions, 3 deletions
diff --git a/lib/puppet/metatype/providers.rb b/lib/puppet/metatype/providers.rb index ef7f73c6c..c078ced24 100644 --- a/lib/puppet/metatype/providers.rb +++ b/lib/puppet/metatype/providers.rb @@ -1,4 +1,8 @@ +require 'puppet/util/provider_features' class Puppet::Type + # Add the feature handling module. + extend Puppet::Util::ProviderFeatures + attr_reader :provider # the Type class attribute accessors @@ -41,6 +45,74 @@ class Puppet::Type return @defaultprovider end + # Define one or more features. Currently, features are just a list of + # methods; if all methods are defined as instance methods on the provider, + # then the provider has that feature, otherwise it does not. + def self.dis_features(hash) + @features ||= {} + hash.each do |name, methods| + name = symbolize(name) + methods = methods.collect { |m| symbolize(m) } + if @features.include?(name) + raise Puppet::DevError, "Feature %s is already defined" % name + end + @features[name] = methods + end + end + + # Generate a module that sets up the boolean methods to test for given + # features. + def self.dis_feature_module + unless defined? @feature_module + @features ||= {} + @feature_module = ::Module.new + const_set("FeatureModule", @feature_module) + features = @features + @feature_module.send(:define_method, :feature?) do |name| + method = name.to_s + "?" + if respond_to?(method) and send(method) + return true + else + return false + end + end + @feature_module.send(:define_method, :features) do + return false unless defined?(features) + features.keys.find_all { |n| feature?(n) }.sort { |a,b| + a.to_s <=> b.to_s + } + end + #if defined?(@features) + @features.each do |name, methods| + method = name.to_s + "?" + @feature_module.send(:define_method, method) do + set = nil + methods.each do |m| + if is_a?(Class) + unless public_method_defined?(m) + set = false + break + end + else + unless respond_to?(m) + set = false + break + end + end + end + + if set.nil? + true + else + false + end + end + end + #end + end + @feature_module + end + # Convert a hash, as provided by, um, a provider, into an instance of self. def self.hash2obj(hash) obj = nil @@ -161,6 +233,10 @@ class Puppet::Type :attributes => options ) + # Add the feature module to both the instances and classes. + provider.send(:include, feature_module) + provider.send(:extend, feature_module) + return provider end diff --git a/lib/puppet/provider.rb b/lib/puppet/provider.rb index 23c921ac0..f5e45ba6d 100644 --- a/lib/puppet/provider.rb +++ b/lib/puppet/provider.rb @@ -212,6 +212,14 @@ class Puppet::Provider end end + dochook(:features) do + if features().length > 0 + return " Supported features: " + features().collect do |f| + "``#{f}``" + end.join(", ") + "." + end + end + # Remove the reference to the model, so GC can clean up. def clear @model = nil diff --git a/lib/puppet/type/package.rb b/lib/puppet/type/package.rb index 107acc20d..14ce4a941 100644 --- a/lib/puppet/type/package.rb +++ b/lib/puppet/type/package.rb @@ -17,8 +17,23 @@ module Puppet Puppet will automatically guess the packaging format that you are using based on the platform you are on, but you can override it - using the ``type`` parameter; obviously, if you specify that you - want to use ``rpm`` then the ``rpm`` tools must be available." + using the ``provider`` parameter; each provider defines what it + requires in order to function, and you must meet those requirements + to use a given provider." + + feature :installable, "The provider can install packages.", + :methods => [:install] + feature :uninstallable, "The provider can uninstall packages.", + :methods => [:uninstall] + feature :upgradeable, "The provider can upgrade to the latest version of a + package. This feature is used by specifying ``latest`` as the + desired value for the package.", + :methods => [:update, :latest] + feature :purgeable, "The provider can purge packages. This generally means + that all traces of the package are removed, including + existing configuration files. This feature is thus destructive + and should be used with the utmost care.", + :methods => [:purge] ensurable do desc "What state the package should be in. @@ -42,6 +57,12 @@ module Puppet end newvalue(:purged, :event => :package_purged) do + unless provider.purgeable? + self.fail( + "Package provider %s does not purging" % + @parent[:provider] + ) + end provider.purge end @@ -49,7 +70,7 @@ module Puppet aliasvalue(:installed, :present) newvalue(:latest) do - unless provider.respond_to?(:latest) + unless provider.upgradeable? self.fail( "Package provider %s does not support specifying 'latest'" % @parent[:provider] diff --git a/lib/puppet/util/provider_features.rb b/lib/puppet/util/provider_features.rb new file mode 100644 index 000000000..c378ff805 --- /dev/null +++ b/lib/puppet/util/provider_features.rb @@ -0,0 +1,108 @@ +# Provides feature definitions. +module Puppet::Util::ProviderFeatures + class ProviderFeature + require 'puppet/util/methodhelper' + require 'puppet/util' + include Puppet::Util + include Puppet::Util::MethodHelper + attr_accessor :name, :docs, :methods + def initialize(name, docs, hash) + self.name = symbolize(name) + self.docs = docs + hash = symbolize_options(hash) + set_options(hash) + end + end + + # Define one or more features. At a minimum, features require a name + # and docs, and at this point they should also specify a list of methods + # required to determine if the feature is present. + def feature(name, docs, hash) + @features ||= {} + if @features.include?(name) + raise Puppet::DevError, "Feature %s is already defined" % name + end + begin + obj = ProviderFeature.new(name, docs, hash) + @features[obj.name] = obj + rescue ArgumentError => detail + error = ArgumentError.new( + "Could not create feature %s: %s" % [name, detail] + ) + error.set_backtrace(detail.backtrace) + raise error + end + end + + # Return a hash of all feature documentation. + def featuredocs + str = "" + @features ||= {} + return nil if @features.empty? + @features.each do |name, feature| + doc = feature.docs.gsub(/\n\s+/, " ") + str += " - **%s**: %s\n" % [name, doc] + end + str + end + + # Generate a module that sets up the boolean methods to test for given + # features. + def feature_module + unless defined? @feature_module + @features ||= {} + @feature_module = ::Module.new + const_set("FeatureModule", @feature_module) + features = @features + # Create a feature? method that can be passed a feature name and + # determine if the feature is present. + @feature_module.send(:define_method, :feature?) do |name| + method = name.to_s + "?" + if respond_to?(method) and send(method) + return true + else + return false + end + end + + # Create a method that will list all functional features. + @feature_module.send(:define_method, :features) do + return false unless defined?(features) + features.keys.find_all { |n| feature?(n) }.sort { |a,b| + a.to_s <=> b.to_s + } + end + + # Create a boolean method for each feature so you can test them + # individually as you might need. + @features.each do |name, feature| + method = name.to_s + "?" + @feature_module.send(:define_method, method) do + set = nil + feature.methods.each do |m| + if is_a?(Class) + unless public_method_defined?(m) + set = false + break + end + else + unless respond_to?(m) + set = false + break + end + end + end + + if set.nil? + true + else + false + end + end + end + end + @feature_module + end +end + +# $Id$ |