diff options
| author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2007-04-25 20:04:59 +0000 |
|---|---|---|
| committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2007-04-25 20:04:59 +0000 |
| commit | 7fbd3ffe886e821a4e85e2fe9a27529133f1b84b (patch) | |
| tree | 0799d97dd7de4b55d99a1db1c7537d66948605cc | |
| parent | 4aaae628342debf5f964f4913a3392b641a49f20 (diff) | |
Adding the ability for parameters to declare that they require a given feature, and resources will not instantiate that parameter if required features are missing. This is mostly useful for properties.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@2413 980ebf18-57e1-0310-9a29-db15c13687c0
| -rw-r--r-- | CHANGELOG | 5 | ||||
| -rw-r--r-- | lib/puppet/metatype/attributes.rb | 23 | ||||
| -rw-r--r-- | lib/puppet/parameter.rb | 6 | ||||
| -rw-r--r-- | lib/puppet/util/provider_features.rb | 12 | ||||
| -rwxr-xr-x | test/ral/manager/attributes.rb | 45 | ||||
| -rwxr-xr-x | test/ral/manager/provider.rb | 4 | ||||
| -rwxr-xr-x | test/ral/types/parameter.rb | 12 |
7 files changed, 106 insertions, 1 deletions
@@ -1,3 +1,8 @@ + Parameters can now declare a dependency on specific + features, and parameters that require missing features + will not be instantiated. This is most useful for + properties. + FileParsing classes can now use instance_eval to add many methods at once to a record type. diff --git a/lib/puppet/metatype/attributes.rb b/lib/puppet/metatype/attributes.rb index b4cc5f687..88cff22f5 100644 --- a/lib/puppet/metatype/attributes.rb +++ b/lib/puppet/metatype/attributes.rb @@ -201,6 +201,11 @@ class Puppet::Type :attributes => options[:attributes], &block ) + + # Grr. + if options[:required_features] + s.required_features = options[:required_features] + end handle_param_options(name, options) @@ -243,6 +248,11 @@ class Puppet::Type handle_param_options(name, options) + # Grr. + if options[:required_features] + s.required_features = options[:required_features] + end + # These might be enabled later. # define_method(name) do # @parameters[name].value @@ -319,6 +329,11 @@ class Puppet::Type s.event = options[:event] end + # Grr. + if options[:required_features] + s.required_features = options[:required_features] + end + # define_method(name) do # @parameters[name].should # end @@ -577,6 +592,14 @@ class Puppet::Type [name, self.ref] end + if provider and features = klass.required_features + unless provider.class.satisfies?(features) + missing = features.find_all { |f| ! provider.class.feature?(f) } + info "Provider %s does not support features %s; not managing attribute %s" % [provider.class.name, missing.join(", "), name] + return nil + end + end + # Add parent information at creation time, so it's available # during validation. options[:parent] = self diff --git a/lib/puppet/parameter.rb b/lib/puppet/parameter.rb index 91949e5e3..7c622dbc2 100644 --- a/lib/puppet/parameter.rb +++ b/lib/puppet/parameter.rb @@ -3,7 +3,7 @@ require 'puppet/util/methodhelper' class Puppet::Parameter < Puppet::Element include Puppet::Util::MethodHelper class << self - attr_reader :validater, :munger, :name, :default + attr_reader :validater, :munger, :name, :default, :required_features attr_accessor :metaparam, :element # Define the default value for a given parameter or parameter. This @@ -206,6 +206,10 @@ class Puppet::Parameter < Puppet::Element return @parameterregexes.dup end + def required_features=(*args) + @required_features = args.flatten.collect { |a| a.to_s.downcase.intern } + end + # Return the list of valid values. def values #[@aliasvalues.keys, @parametervalues.keys].flatten diff --git a/lib/puppet/util/provider_features.rb b/lib/puppet/util/provider_features.rb index 3aeb627a3..060026bb9 100644 --- a/lib/puppet/util/provider_features.rb +++ b/lib/puppet/util/provider_features.rb @@ -127,6 +127,18 @@ module Puppet::Util::ProviderFeatures } end + # Create a method that will list all functional features. + @feature_module.send(:define_method, :satisfies?) do |*needed| + ret = true + needed.flatten.each do |feature| + unless feature?(feature) + ret = false + break + end + end + ret + end + # Create a boolean method for each feature so you can test them # individually as you might need. @features.each do |name, feature| diff --git a/test/ral/manager/attributes.rb b/test/ral/manager/attributes.rb index 43d64f367..a23a5e9ce 100755 --- a/test/ral/manager/attributes.rb +++ b/test/ral/manager/attributes.rb @@ -244,6 +244,51 @@ class TestTypeAttributes < Test::Unit::TestCase end assert(should.empty?, "Did not get all of the parameters.") end + + # Make sure newattr handles required features correctly. + def test_newattr_and_required_features + # Make a type with some features + type = mktype + type.feature :fone, "Something" + type.feature :ftwo, "Something else" + type.newparam(:name) {} + + # Make three properties: one with no requirements, one with one, and one with two + none = type.newproperty(:none) {} + one = type.newproperty(:one, :required_features => :fone) {} + two = type.newproperty(:two, :required_features => [:fone, :ftwo]) {} + + # Now make similar providers + nope = type.provide(:nope) {} + maybe = type.provide(:maybe) { has_features :fone} + yep = type.provide(:yep) { has_features :fone, :ftwo} + + attrs = [:none, :one, :two] + + # Now make sure that we get warnings and no properties in those cases where our providers do not support the features requested + [nope, maybe, yep].each_with_index do |prov, i| + resource = type.create(:provider => prov.name, :name => "test%s" % i, :none => "a", :one => "b", :two => "c") + + case prov.name + when :nope: + yes = [:none] + no = [:one, :two] + when :maybe: + yes = [:none, :one] + no = [:two] + when :yep: + yes = [:none, :one, :two] + no = [] + end + yes.each { |a| assert(resource.should(a), "Did not get value for %s in %s" % [a, prov.name]) } + no.each do |a| + assert_nil(resource.should(a), "Got value for unsupported %s in %s" % [a, prov.name]) + assert(@logs.find { |l| l.message =~ /not managing attribute #{a}/ and l.level == :info }, "No warning about failed %s" % a) + end + + @logs.clear + end + end end # $Id$ diff --git a/test/ral/manager/provider.rb b/test/ral/manager/provider.rb index 3b727a4c5..84bb0b40c 100755 --- a/test/ral/manager/provider.rb +++ b/test/ral/manager/provider.rb @@ -115,6 +115,8 @@ class TestProviderFeatures < Test::Unit::TestCase "class missing feature %s" % feature) assert(inst.send(method), "instance missing feature %s" % feature) + assert(inst.satisfies?(feature), + "instance.satisfy %s returned false" % feature) else assert(! provider.feature?(feature), "class has feature? %s" % feature) @@ -124,6 +126,8 @@ class TestProviderFeatures < Test::Unit::TestCase "class has feature %s" % feature) assert(! inst.send(method), "instance has feature %s" % feature) + assert(! inst.satisfies?(feature), + "instance.satisfy %s returned true" % feature) end end diff --git a/test/ral/types/parameter.rb b/test/ral/types/parameter.rb index 784378f9f..b34548546 100755 --- a/test/ral/types/parameter.rb +++ b/test/ral/types/parameter.rb @@ -155,6 +155,18 @@ class TestParameter < Test::Unit::TestCase assert(obj.is_a?(Puppet::Type::Property), "alias instance is now not a property") end + + # Make sure properties can correctly require features and behave appropriately when + # those features are missing. + def test_requires_features + param = newparam(:feature_tests) + + assert_nothing_raised("could not add feature requirements to property") do + param.required_features = "testing" + end + + assert_equal([:testing], param.required_features, "required features value was not arrayfied and interned") + end end # $Id$ |
