| 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 |
| 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] |
Set whether properties should match all values or just the first one.
# 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
# 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
initialize our property
# 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:
# 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
Look up a value‘s name, so we can find options and such.
# 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
Call the provider method.
# 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.
# 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?
# 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.
# 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
# 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.
# 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
# File lib/puppet/property.rb, line 290
290: def is_to_s(currentvalue)
291: currentvalue
292: end
Send a log message.
# 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?
# File lib/puppet/property.rb, line 307
307: def match_all?
308: self.class.array_matching == :all
309: end
for testing whether we should actually do anything
# 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
Set our value, using the provider, an associated block, or both.
# 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
# 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
# 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
# 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.
# 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.
# 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
# File lib/puppet/property.rb, line 440
440: def to_s
441: return "%s(%s)" % [@resource.name,self.name]
442: end