Class Puppet::Property
In: lib/puppet/property/keyvalue.rb
lib/puppet/property/ordered_list.rb
lib/puppet/property/list.rb
lib/puppet/type/zpool.rb
lib/puppet/property.rb
Parent: Object

Methods

Classes and Modules

Class Puppet::Property::Ensure
Class Puppet::Property::KeyValue
Class Puppet::Property::List
Class Puppet::Property::MultiVDev
Class Puppet::Property::OrderedList
Class Puppet::Property::VDev

Attributes

name  [R] 
noop  [W] 
shouldorig  [R]  Because ‘should’ uses an array, we have a special method for handling it. We also want to keep copies of the original values, so that they can be retrieved and compared later when merging.
unmanaged  [RW] 

Public Class methods

Return array matching info, defaulting to just matching the first value.

[Source]

    # File lib/puppet/property.rb, line 23
23:         def array_matching
24:             unless defined?(@array_matching)
25:                 @array_matching = :first
26:             end
27:             @array_matching
28:         end

Set whether properties should match all values or just the first one.

[Source]

    # File lib/puppet/property.rb, line 31
31:         def array_matching=(value)
32:             value = value.intern if value.is_a?(String)
33:             unless [:first, :all].include?(value)
34:                 raise ArgumentError, "Supported values for Property#array_matching are 'first' and 'all'"
35:             end
36:             @array_matching = value
37:         end

[Source]

    # File lib/puppet/property.rb, line 39
39:         def checkable
40:             @checkable = true
41:         end

[Source]

    # File lib/puppet/property.rb, line 47
47:         def checkable?
48:             if defined? @checkable
49:                 return @checkable
50:             else
51:                 return true
52:             end
53:         end

Create the value management variables.

[Source]

    # File lib/puppet/property.rb, line 78
78:     def self.initvars
79:         @parametervalues = {}
80:         @aliasvalues = {}
81:         @parameterregexes = {}
82:         @parameteroptions = {}
83:     end

initialize our property

[Source]

     # File lib/puppet/property.rb, line 235
235:     def initialize(hash = {})
236:         super
237:     end

Define a new valid value for a property. You must provide the value itself, usually as a symbol, or a regex to match the value.

The first argument to the method is either the value itself or a regex. The second argument is an option hash; valid options are:

  • :event: The event that should be returned when this value is set.
  • :call: When to call any associated block. The default value is ``instead``, which means to call the value instead of calling the provider. You can also specify ``before`` or ``after``, which will call both the block and the provider, according to the order you specify (the ``first`` refers to when the block is called, not the provider).

[Source]

     # File lib/puppet/property.rb, line 96
 96:     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
143:     end

[Source]

    # File lib/puppet/property.rb, line 43
43:         def uncheckable
44:             @checkable = false
45:         end

Look up a value‘s name, so we can find options and such.

[Source]

    # File lib/puppet/property.rb, line 57
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
64:         end
65:     end

Retrieve an option set when a value was defined.

[Source]

    # File lib/puppet/property.rb, line 68
68:     def self.value_option(name, option)
69:         option = option.to_sym
70:         if hash = @parameteroptions[name]
71:             hash[option]
72:         else
73:             nil
74:         end
75:     end

Public Instance methods

Call the provider method.

[Source]

     # File lib/puppet/property.rb, line 146
146:     def call_provider(value)
147:         begin
148:             provider.send(self.class.name.to_s + "=", value)
149:         rescue NoMethodError
150:             self.fail "The %s provider can not handle attribute %s" %
151:                 [provider.class.name, self.class.name]
152:         end
153:     end

Call the dynamically-created method associated with our value, if there is one.

[Source]

     # File lib/puppet/property.rb, line 157
157:     def call_valuemethod(name, value)
158:         event = nil
159:         if method = self.class.value_option(name, :method) and self.respond_to?(method)
160:             #self.debug "setting %s (currently %s)" % [value, self.retrieve]
161: 
162:             begin
163:                 event = self.send(method)
164:             rescue Puppet::Error
165:                 raise
166:             rescue => detail
167:                 if Puppet[:trace]
168:                     puts detail.backtrace
169:                 end
170:                 error = Puppet::Error.new("Could not set %s on %s: %s" %
171:                     [value, self.class.name, detail], @resource.line, @resource.file)
172:                 error.set_backtrace detail.backtrace
173:                 raise error
174:             end
175:         elsif block = self.class.value_option(name, :block)
176:             # FIXME It'd be better here to define a method, so that
177:             # 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:             event = self.instance_eval(&block)
181:         end
182:         return event, name
183:     end

How should a property change be printed as a string?

[Source]

     # File lib/puppet/property.rb, line 186
186:     def change_to_s(currentvalue, newvalue)
187:         begin
188:             if currentvalue == :absent
189:                 return "defined '%s' as '%s'" %
190:                     [self.name, self.should_to_s(newvalue)]
191:             elsif newvalue == :absent or newvalue == [:absent]
192:                 return "undefined %s from '%s'" %
193:                     [self.name, self.is_to_s(currentvalue)]
194:             else
195:                 return "%s changed '%s' to '%s'" %
196:                     [self.name, self.is_to_s(currentvalue), self.should_to_s(newvalue)]
197:             end
198:         rescue Puppet::Error, Puppet::DevError
199:             raise
200:         rescue => detail
201:             raise Puppet::DevError, "Could not convert change %s to string: %s" %
202:                 [self.name, detail]
203:         end
204:     end

Figure out which event to return.

[Source]

     # File lib/puppet/property.rb, line 207
207:     def event(name, event = nil)
208:         if value_event = self.class.value_option(name, :event)
209:             return value_event 
210:         end
211: 
212:         if event and event.is_a?(Symbol)
213:             if event == :nochange
214:                 return nil
215:             else
216:                 return event
217:             end
218:         end
219: 
220:         if self.class.name == :ensure
221:             event = case self.should
222:             when :present: (@resource.class.name.to_s + "_created").intern
223:             when :absent: (@resource.class.name.to_s + "_removed").intern
224:             else
225:                 (@resource.class.name.to_s + "_changed").intern
226:             end
227:         else
228:             event = (@resource.class.name.to_s + "_changed").intern
229:         end
230: 
231:         return event
232:     end

[Source]

     # File lib/puppet/property.rb, line 239
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)"
246:         end
247:     end

Determine whether the property is in-sync or not. If @should is not defined or is set to a non-true value, then we do not have a valid value for it and thus consider the property to be in-sync since we cannot fix it. Otherwise, we expect our should value to be an array, and if @is matches any of those values, then we consider it to be in-sync.

[Source]

     # File lib/puppet/property.rb, line 255
255:     def insync?(is)
256:         #debug "%s value is '%s', should be '%s'" %
257:         #    [self,self.is.inspect,self.should.inspect]
258:         unless defined? @should and @should
259:             return true
260:         end
261: 
262:         unless @should.is_a?(Array)
263:             self.devfail "%s's should is not array" % self.class.name
264:         end
265: 
266:         # an empty array is analogous to no should values
267:         if @should.empty?
268:             return true
269:         end
270: 
271:         # Look for a matching value
272:         if match_all?
273:             return (is == @should or is == @should.collect { |v| v.to_s })
274:         else
275:             @should.each { |val|
276:                 if is == val or is == val.to_s
277:                     return true
278:                 end
279:             }
280:         end
281: 
282:         # otherwise, return false
283:         return false
284:     end

because the @should and @is vars might be in weird formats, we need to set up a mechanism for pretty printing of the values default to just the values, but this way individual properties can override these methods

[Source]

     # File lib/puppet/property.rb, line 290
290:     def is_to_s(currentvalue)
291:         currentvalue
292:     end

Send a log message.

[Source]

     # File lib/puppet/property.rb, line 295
295:     def log(msg)
296:         unless @resource[:loglevel]
297:             self.devfail "Parent %s has no loglevel" % @resource.name
298:         end
299:         Puppet::Util::Log.create(
300:             :level => @resource[:loglevel],
301:             :message => msg,
302:             :source => self
303:         )
304:     end

Should we match all values, or just the first?

[Source]

     # File lib/puppet/property.rb, line 307
307:     def match_all?
308:         self.class.array_matching == :all
309:     end

each property class must define the name() method, and property instances do not change that name this implicitly means that a given object can only have one property instance of a given property class

[Source]

     # File lib/puppet/property.rb, line 315
315:     def name
316:         return self.class.name
317:     end

for testing whether we should actually do anything

[Source]

     # File lib/puppet/property.rb, line 320
320:     def noop
321:         # This is only here to make testing easier.
322:         if @resource.respond_to?(:noop?)
323:             @resource.noop?
324:         else
325:             if defined?(@noop)
326:                 @noop
327:             else
328:                 Puppet[:noop]
329:             end
330:         end
331:     end

By default, call the method associated with the property name on our provider. In other words, if the property name is ‘gid’, we‘ll call ‘provider.gid’ to retrieve the current value.

[Source]

     # File lib/puppet/property.rb, line 336
336:     def retrieve
337:         provider.send(self.class.name)
338:     end

Set our value, using the provider, an associated block, or both.

[Source]

     # File lib/puppet/property.rb, line 341
341:     def set(value)
342:         # Set a name for looking up associated options like the event.
343:         name = self.class.value_name(value)
344: 
345:         call = self.class.value_option(name, :call)
346: 
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
352:             if @resource.provider
353:                 call_provider(value)
354:             else
355:                 # They haven't provided a block, and our parent does not have
356:                 # 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]
359:             end
360:         end
361:         if call == :after
362:             event, tmp = call_valuemethod(name, value) 
363:         end
364: 
365:         return event(name, event)
366:     end

Only return the first value

[Source]

     # File lib/puppet/property.rb, line 369
369:     def should
370:         if defined? @should
371:             unless @should.is_a?(Array)
372:                 self.devfail "should for %s on %s is not an array" %
373:                     [self.class.name, @resource.name]
374:             end
375:             if match_all?
376:                 return @should
377:             else
378:                 return @should[0]
379:             end
380:         else
381:             return nil
382:         end
383:     end

Set the should value.

[Source]

     # File lib/puppet/property.rb, line 386
386:     def should=(values)
387:         unless values.is_a?(Array)
388:             values = [values]
389:         end
390: 
391:         @shouldorig = values
392: 
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
405:     end

[Source]

     # File lib/puppet/property.rb, line 407
407:     def should_to_s(newvalue)
408:         newvalue = [newvalue] unless newvalue.is_a? Array
409:         if defined? newvalue
410:             newvalue.join(" ")
411:         else
412:             return nil
413:         end
414:     end

The default ‘sync’ method only selects among a list of registered # values.

[Source]

     # File lib/puppet/property.rb, line 417
417:     def sync
418:         self.devfail("No values defined for %s" % self.class.name) unless self.class.values
419: 
420:         if value = self.should
421:             set(value)
422:         else
423:             self.devfail "Got a nil value for should"
424:         end
425:     end

The properties need to return tags so that logs correctly collect them.

[Source]

     # File lib/puppet/property.rb, line 428
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

[Source]

     # File lib/puppet/property.rb, line 440
440:     def to_s
441:         return "%s(%s)" % [@resource.name,self.name]
442:     end

Just return any should value we might have.

[Source]

     # File lib/puppet/property.rb, line 445
445:     def value
446:         self.should
447:     end

Match the Parameter interface, but we really just use ‘should’ internally. Note that the should= method does all of the validation and such.

[Source]

     # File lib/puppet/property.rb, line 451
451:     def value=(value)
452:         self.should = value
453:     end

[Validate]