1
# The virtual base class for properties, which are the self-contained building
1
# The virtual base class for properties, which are the self-contained building
2
2
# blocks for actually doing work on the system.
5
5
require 'puppet/parameter'
8
class Property < Puppet::Parameter
7
class Puppet::Property < Puppet::Parameter
10
9
# Because 'should' uses an array, we have a special method for handling
11
10
# it. We also want to keep copies of the original values, so that
56
55
# Look up a value's name, so we can find options and such.
57
def self.value_name(value)
58
if value != '' and name = symbolize(value) and @parametervalues.include?(name)
60
elsif ary = self.match?(value)
56
def self.value_name(name)
57
if value = value_collection.match?(name)
67
62
# Retrieve an option set when a value was defined.
68
63
def self.value_option(name, option)
69
option = option.to_sym
70
if hash = @parameteroptions[name]
64
if value = value_collection.value(name)
77
# Create the value management variables.
81
@parameterregexes = {}
82
@parameteroptions = {}
85
69
# Define a new valid value for a property. You must provide the value itself,
86
70
# usually as a symbol, or a regex to match the value.
88
72
# The first argument to the method is either the value itself or a regex.
89
73
# The second argument is an option hash; valid options are:
74
# * <tt>:method</tt>: The name of the method to define. Defaults to 'set_<value>'.
75
# * <tt>:required_features</tt>: A list of features this value requires.
90
76
# * <tt>:event</tt>: The event that should be returned when this value is set.
91
77
# * <tt>:call</tt>: When to call any associated block. The default value
92
78
# is ``instead``, which means to call the value instead of calling the
93
# provider. You can also specify ``before`` or ``after``, which will
79
# provider. You can also specify ``before`` or ``after``, which will
94
80
# call both the block and the provider, according to the order you specify
95
81
# (the ``first`` refers to when the block is called, not the provider).
96
82
def self.newvalue(name, options = {}, &block)
97
name = name.intern if name.is_a? String
99
@parameteroptions[name] = {}
100
paramopts = @parameteroptions[name]
102
# Symbolize everything
103
options.each do |opt, val|
104
paramopts[symbolize(opt)] = symbolize(val)
107
# By default, call the block instead of the provider.
109
paramopts[:call] ||= :instead
111
paramopts[:call] ||= :none
113
# If there was no block given, we still want to store the information
114
# for validation, but we won't be defining a method
119
if @parametervalues.include?(name)
120
Puppet.warning "%s reassigning value %s" % [self.name, name]
122
@parametervalues[name] = block
125
method = "set_" + name.to_s
126
settor = paramopts[:settor] || (self.name.to_s + "=")
127
define_method(method, &block)
128
paramopts[:method] = method
131
# The regexes are handled in parameter.rb. This value is used
133
@parameterregexes[name] = block
135
# This is used for looking up the block for execution.
137
paramopts[:block] = block
140
raise ArgumentError, "Invalid value %s of type %s" %
83
value = value_collection.newvalue(name, options, &block)
85
if value.method and value.block
86
define_method(value.method, &value.block)
145
91
# Call the provider method.
342
292
# Set a name for looking up associated options like the event.
343
293
name = self.class.value_name(value)
345
call = self.class.value_option(name, :call)
295
call = self.class.value_option(name, :call) || :none
347
# If we're supposed to call the block first or instead, call it now
348
if call == :before or call == :instead
349
event, tmp = call_valuemethod(name, value)
351
unless call == :instead
298
event, tmp = call_valuemethod(name, value)
352
300
if @resource.provider
353
301
call_provider(value)
355
303
# They haven't provided a block, and our parent does not have
356
304
# a provider, so we have no idea how to handle this.
357
self.fail "%s cannot handle values of type %s" %
358
[self.class.name, value.inspect]
305
self.fail "%s cannot handle values of type %s" % [self.class.name, value.inspect]
362
event, tmp = call_valuemethod(name, value)
308
# LAK:NOTE 20081031 This is a change in behaviour -- you could
309
# previously specify :call => [;before|:after], which would call
310
# the setter *in addition to* the block. I'm convinced this
311
# was never used, and it makes things unecessarily complicated.
312
# If you want to specify a block and still call the setter, then
313
# do so in the block.
314
devfail "Cannot use obsolete :call value '%s' for property '%s'" % [call, self.class.name]
365
317
return event(name, event)
320
# If there's a shadowing metaparam, instantiate it now.
321
# This allows us to create a property or parameter with the
322
# same name as a metaparameter, and the metaparam will only be
323
# stored as a shadow.
324
def setup_shadow(klass)
325
@shadow = klass.new(:resource => self.resource)
368
328
# Only return the first value
370
330
if defined? @should
427
# The properties need to return tags so that logs correctly collect them.
429
unless defined? @tags
431
# This might not be true in testing
432
if @resource.respond_to? :tags
433
@tags = @resource.tags
441
375
return "%s(%s)" % [@resource.name,self.name]
378
# Verify that the passed value is valid.
379
# If the developer uses a 'validate' hook, this method will get overridden.
380
def unsafe_validate(value)
382
validate_features_per_value(value)
385
# Make sure that we've got all of the required features for a given value.
386
def validate_features_per_value(value)
387
if features = self.class.value_option(self.class.value_name(value), :required_features)
388
raise ArgumentError, "Provider must have features '%s' to set '%s' to '%s'" % [[features].flatten.join(", "), self.class.name, value] unless provider.satisfies?(features)
444
392
# Just return any should value we might have.