~ubuntu-branches/ubuntu/lucid/puppet/lucid-security

« back to all changes in this revision

Viewing changes to lib/puppet/property.rb

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2009-12-23 00:48:10 UTC
  • mfrom: (1.1.10 upstream) (3.1.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091223004810-3i4oryds922g5n59
Tags: 0.25.1-3ubuntu1
* Merge from debian testing.  Remaining changes:
  - debian/rules:
    + Don't start puppet when first installing puppet.
  - debian/puppet.conf, lib/puppet/defaults.rb:
    + Move templates to /etc/puppet
  - lib/puppet/defaults.rb:
    + Fix /var/lib/puppet/state ownership.
  - man/man8/puppet.conf.8: 
    + Fix broken URL in manpage.
  - debian/control:
    + Update maintainer accordint to spec.
    + Puppetmaster Recommends -> Suggests
    + Created puppet-testsuite as a seperate. Allow the users to run puppet's 
      testsuite.
  - tests/Rakefile: Fix rakefile so that the testsuite can acutally be ran.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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.
3
3
 
4
4
require 'puppet'
5
5
require 'puppet/parameter'
6
6
 
7
 
module Puppet
8
 
class Property < Puppet::Parameter
 
7
class Puppet::Property < Puppet::Parameter
9
8
 
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
54
53
    end
55
54
 
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)
59
 
            return name
60
 
        elsif ary = self.match?(value)
61
 
            return ary[0]
62
 
        else
63
 
            return nil
 
56
    def self.value_name(name)
 
57
        if value = value_collection.match?(name)
 
58
            value.name
64
59
        end
65
60
    end
66
61
 
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]
71
 
            hash[option]
72
 
        else
73
 
            nil
 
64
        if value = value_collection.value(name)
 
65
            value.send(option)
74
66
        end
75
67
    end
76
68
 
77
 
    # Create the value management variables.
78
 
    def self.initvars
79
 
        @parametervalues = {}
80
 
        @aliasvalues = {}
81
 
        @parameterregexes = {}
82
 
        @parameteroptions = {}
83
 
    end
84
 
 
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.
87
71
    #
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
98
 
 
99
 
        @parameteroptions[name] = {}
100
 
        paramopts = @parameteroptions[name]
101
 
 
102
 
        # Symbolize everything
103
 
        options.each do |opt, val|
104
 
            paramopts[symbolize(opt)] = symbolize(val)
105
 
        end
106
 
 
107
 
        # By default, call the block instead of the provider.
108
 
        if block_given?
109
 
            paramopts[:call] ||= :instead
110
 
        else
111
 
            paramopts[:call] ||= :none
112
 
        end
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
115
 
        block ||= true
116
 
 
117
 
        case name
118
 
        when Symbol
119
 
            if @parametervalues.include?(name)
120
 
                Puppet.warning "%s reassigning value %s" % [self.name, name]
121
 
            end
122
 
            @parametervalues[name] = block
123
 
 
124
 
            if block_given?
125
 
                method = "set_" + name.to_s
126
 
                settor = paramopts[:settor] || (self.name.to_s + "=")
127
 
                define_method(method, &block)
128
 
                paramopts[:method] = method
129
 
            end
130
 
        when Regexp
131
 
            # The regexes are handled in parameter.rb.  This value is used
132
 
            # for validation.
133
 
            @parameterregexes[name] = block
134
 
 
135
 
            # This is used for looking up the block for execution.
136
 
            if block_given?
137
 
                paramopts[:block] = block
138
 
            end
139
 
        else
140
 
            raise ArgumentError, "Invalid value %s of type %s" %
141
 
                [name, name.class]
142
 
        end
 
83
        value = value_collection.newvalue(name, options, &block)
 
84
 
 
85
        if value.method and value.block
 
86
            define_method(value.method, &value.block)
 
87
        end
 
88
        value
143
89
    end
144
90
 
145
91
    # Call the provider method.
175
121
        elsif block = self.class.value_option(name, :block)
176
122
            # FIXME It'd be better here to define a method, so that
177
123
            # the blocks could return values.
178
 
            # If the regex was defined with no associated block, then just pass
179
 
            # through and the correct event will be passed back.
180
124
            event = self.instance_eval(&block)
 
125
        else
 
126
            devfail "Could not find method for value '%s'" % name
181
127
        end
182
128
        return event, name
183
129
    end
198
144
        rescue Puppet::Error, Puppet::DevError
199
145
            raise
200
146
        rescue => detail
 
147
            puts detail.backtrace if Puppet[:trace]
201
148
            raise Puppet::DevError, "Could not convert change %s to string: %s" %
202
149
                [self.name, detail]
203
150
        end
206
153
    # Figure out which event to return.
207
154
    def event(name, event = nil)
208
155
        if value_event = self.class.value_option(name, :event)
209
 
            return value_event 
 
156
            return value_event
210
157
        end
211
158
 
212
159
        if event and event.is_a?(Symbol)
219
166
 
220
167
        if self.class.name == :ensure
221
168
            event = case self.should
222
 
            when :present: (@resource.class.name.to_s + "_created").intern
223
 
            when :absent: (@resource.class.name.to_s + "_removed").intern
 
169
            when :present; (@resource.class.name.to_s + "_created").intern
 
170
            when :absent; (@resource.class.name.to_s + "_removed").intern
224
171
            else
225
172
                (@resource.class.name.to_s + "_changed").intern
226
173
            end
230
177
 
231
178
        return event
232
179
    end
233
 
    
 
180
 
 
181
    attr_reader :shadow
 
182
 
234
183
    # initialize our property
235
184
    def initialize(hash = {})
236
185
        super
237
 
    end
238
 
 
239
 
    def inspect
240
 
        str = "Property('%s', " % self.name
241
 
 
242
 
        if defined? @should and @should
243
 
            str += "@should = '%s')" % @should.join(", ")
244
 
        else
245
 
            str += "@should = nil)"
 
186
 
 
187
        if ! self.metaparam? and klass = Puppet::Type.metaparamclass(self.class.name)
 
188
            setup_shadow(klass)
246
189
        end
247
190
    end
248
191
 
308
251
        self.class.array_matching == :all
309
252
    end
310
253
 
 
254
    # Execute our shadow's munge code, too, if we have one.
 
255
    def munge(value)
 
256
        self.shadow.munge(value) if self.shadow
 
257
 
 
258
        super
 
259
    end
 
260
 
311
261
    # each property class must define the name() method, and property instances
312
262
    # do not change that name
313
263
    # this implicitly means that a given object can only have one property
342
292
        # Set a name for looking up associated options like the event.
343
293
        name = self.class.value_name(value)
344
294
 
345
 
        call = self.class.value_option(name, :call)
 
295
        call = self.class.value_option(name, :call) || :none
346
296
 
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) 
350
 
        end
351
 
        unless call == :instead
 
297
        if call == :instead
 
298
            event, tmp = call_valuemethod(name, value)
 
299
        elsif call == :none
352
300
            if @resource.provider
353
301
                call_provider(value)
354
302
            else
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]
359
306
            end
360
 
        end
361
 
        if call == :after
362
 
            event, tmp = call_valuemethod(name, value) 
 
307
        else
 
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]
363
315
        end
364
316
 
365
317
        return event(name, event)
366
318
    end
367
319
 
 
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)
 
326
    end
 
327
 
368
328
    # Only return the first value
369
329
    def should
370
330
        if defined? @should
373
333
                    [self.class.name, @resource.name]
374
334
            end
375
335
            if match_all?
376
 
                return @should
 
336
                return @should.collect { |val| self.unmunge(val) }
377
337
            else
378
 
                return @should[0]
 
338
                return self.unmunge(@should[0])
379
339
            end
380
340
        else
381
341
            return nil
390
350
 
391
351
        @shouldorig = values
392
352
 
393
 
        if self.respond_to?(:validate)
394
 
            values.each { |val|
395
 
                validate(val)
396
 
            }
397
 
        end
398
 
        if self.respond_to?(:munge)
399
 
            @should = values.collect { |val|
400
 
                self.munge(val)
401
 
            }
402
 
        else
403
 
            @should = values
404
 
        end
 
353
        values.each { |val| validate(val) }
 
354
        @should = values.collect { |val| self.munge(val) }
405
355
    end
406
356
 
407
357
    def should_to_s(newvalue)
413
363
        end
414
364
    end
415
365
 
416
 
    # The default 'sync' method only selects among a list of registered # values.
417
366
    def sync
418
 
        self.devfail("No values defined for %s" % self.class.name) unless self.class.values
419
 
 
420
367
        if value = self.should
421
368
            set(value)
422
369
        else
424
371
        end
425
372
    end
426
373
 
427
 
    # The properties need to return tags so that logs correctly collect them.
428
 
    def tags
429
 
        unless defined? @tags
430
 
            @tags = []
431
 
            # This might not be true in testing
432
 
            if @resource.respond_to? :tags
433
 
                @tags = @resource.tags
434
 
            end
435
 
            @tags << self.name
436
 
        end
437
 
        @tags
438
 
    end
439
 
 
440
374
    def to_s
441
375
        return "%s(%s)" % [@resource.name,self.name]
442
376
    end
443
377
 
 
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)
 
381
        super
 
382
        validate_features_per_value(value)
 
383
    end
 
384
 
 
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)
 
389
        end
 
390
    end
 
391
 
444
392
    # Just return any should value we might have.
445
393
    def value
446
394
        self.should
545
493
        end
546
494
    end
547
495
end
548
 
end
549