Class: Puppet::Property
- Defined in:
- lib/vendor/puppet/property.rb,
lib/vendor/puppet/type/zpool.rb,
lib/vendor/puppet/property/list.rb,
lib/vendor/puppet/property/keyvalue.rb,
lib/vendor/puppet/property/ordered_list.rb
Direct Known Subclasses
Defined Under Namespace
Classes: Ensure, KeyValue, List, MultiVDev, OrderedList, VDev
Constant Summary
Constants included from Util::Docs
Constants included from Util
Util::AbsolutePathPosix, Util::AbsolutePathWindows
Class Attribute Summary collapse
-
.name ⇒ Object
readonly
Returns the value of attribute name.
-
.unmanaged ⇒ Object
Returns the value of attribute unmanaged.
Instance Attribute Summary collapse
-
#noop ⇒ Object
for testing whether we should actually do anything.
-
#shadow ⇒ Object
readonly
Returns the value of attribute shadow.
-
#shouldorig ⇒ Object
readonly
Because ‘should’ uses an array, we have a special method for handling it.
Attributes inherited from Parameter
Attributes included from Util::Docs
Class Method Summary collapse
-
.array_matching ⇒ Object
Return array matching info, defaulting to just matching the first value.
-
.array_matching=(value) ⇒ Object
Set whether properties should match all values or just the first one.
- .method_added(sym) ⇒ Object
-
.newvalue(name, options = {}, &block) ⇒ Object
Define a new valid value for a property.
-
.value_name(name) ⇒ Object
Look up a value’s name, so we can find options and such.
-
.value_option(name, option) ⇒ Object
Retrieve an option set when a value was defined.
Instance Method Summary collapse
-
#call_provider(value) ⇒ Object
Call the provider method.
-
#call_valuemethod(name, value) ⇒ Object
Call the dynamically-created method associated with our value, if there is one.
-
#change_to_s(current_value, newvalue) ⇒ Object
How should a property change be printed as a string?.
-
#event ⇒ Object
Return a modified form of the resource event.
-
#event_name ⇒ Object
Figure out which event to return.
-
#initialize(hash = {}) ⇒ Property
constructor
initialize our property.
-
#insync?(is) ⇒ Boolean
This method may be overridden by derived classes if necessary to provide extra logic to determine whether the property is in sync.
-
#is_to_s(currentvalue) ⇒ Object
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.
-
#log(msg) ⇒ Object
Send a log message.
-
#match_all? ⇒ Boolean
Should we match all values, or just the first?.
-
#munge(value) ⇒ Object
Execute our shadow’s munge code, too, if we have one.
-
#name ⇒ Object
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.
-
#property_matches?(current, desired) ⇒ Boolean
Compare the current and desired value of a property in a property-specific way.
-
#retrieve ⇒ Object
By default, call the method associated with the property name on our provider.
-
#safe_insync?(is) ⇒ Boolean
Determine whether the property is in-sync or not.
-
#set(value) ⇒ Object
Set our value, using the provider, an associated block, or both.
-
#setup_shadow(klass) ⇒ Object
If there’s a shadowing metaparam, instantiate it now.
-
#should ⇒ Object
Only return the first value.
-
#should=(values) ⇒ Object
Set the should value.
- #should_to_s(newvalue) ⇒ Object
- #sync ⇒ Object
-
#unsafe_validate(value) ⇒ Object
Verify that the passed value is valid.
-
#validate_features_per_value(value) ⇒ Object
Make sure that we’ve got all of the required features for a given value.
-
#value ⇒ Object
Just return any should value we might have.
-
#value=(value) ⇒ Object
Match the Parameter interface, but we really just use ‘should’ internally.
Methods inherited from Parameter
aliasvalue, defaultto, desc, #devfail, doc, #fail, format_value_for_display, initvars, isnamevar, isnamevar?, isrequired, #metaparam?, munge, newvalues, nodefault, #pathbuilder, #provider, proxymethods, #remove, required?, #tags, #to_s, unmunge, #unmunge, #unsafe_munge, #validate, validate
Methods included from Util::Docs
#desc, #dochook, #doctable, #markdown_definitionlist, #markdown_header, #nodoc?, #pad, scrub
Methods included from Util
absolute_path?, activerecord_version, benchmark, binread, chuser, classproxy, #execfail, #execpipe, execute, execute_posix, execute_windows, logmethods, memory, path_to_uri, proxy, replace_file, safe_posix_fork, symbolize, symbolizehash, symbolizehash!, synchronize_on, thinmark, #threadlock, uri_to_path, wait_for_output, which, withumask
Methods included from Util::POSIX
#get_posix_field, #gid, #idfield, #methodbyid, #methodbyname, #search_posix_field, #uid
Methods included from Util::MethodHelper
#requiredopts, #set_options, #symbolize_options
Methods included from Util::Logging
#clear_deprecation_warnings, #deprecation_warning, #send_log
Methods included from Util::LogPaths
Methods included from Util::Errors
#adderrorcontext, #devfail, #error_context, #exceptwrap, #fail
Constructor Details
Class Attribute Details
.name ⇒ Object (readonly)
Returns the value of attribute name.
19 20 21 |
# File 'lib/vendor/puppet/property.rb', line 19 def name @name end |
.unmanaged ⇒ Object
Returns the value of attribute unmanaged.
18 19 20 |
# File 'lib/vendor/puppet/property.rb', line 18 def unmanaged @unmanaged end |
Instance Attribute Details
#noop ⇒ Object
for testing whether we should actually do anything
262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/vendor/puppet/property.rb', line 262 def noop # This is only here to make testing easier. if @resource.respond_to?(:noop?) @resource.noop? else if defined?(@noop) @noop else Puppet[:noop] end end end |
#shadow ⇒ Object (readonly)
Returns the value of attribute shadow.
140 141 142 |
# File 'lib/vendor/puppet/property.rb', line 140 def shadow @shadow end |
#shouldorig ⇒ Object (readonly)
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.
13 14 15 |
# File 'lib/vendor/puppet/property.rb', line 13 def shouldorig @shouldorig end |
Class Method Details
.array_matching ⇒ Object
Return array matching info, defaulting to just matching the first value.
23 24 25 |
# File 'lib/vendor/puppet/property.rb', line 23 def array_matching @array_matching ||= :first end |
.array_matching=(value) ⇒ Object
Set whether properties should match all values or just the first one.
28 29 30 31 32 |
# File 'lib/vendor/puppet/property.rb', line 28 def array_matching=(value) value = value.intern if value.is_a?(String) raise ArgumentError, "Supported values for Property#array_matching are 'first' and 'all'" unless [:first, :all].include?(value) @array_matching = value end |
.method_added(sym) ⇒ Object
167 168 169 |
# File 'lib/vendor/puppet/property.rb', line 167 def self.method_added(sym) raise "Puppet::Property#safe_insync? shouldn't be overridden; please override insync? instead" if sym == :safe_insync? end |
.newvalue(name, options = {}, &block) ⇒ Object
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:
-
:method
: The name of the method to define. Defaults to ‘set_<value>’. -
:required_features
: A list of features this value requires. -
: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).
62 63 64 65 66 67 |
# File 'lib/vendor/puppet/property.rb', line 62 def self.newvalue(name, = {}, &block) value = value_collection.newvalue(name, , &block) define_method(value.method, &value.block) if value.method and value.block value end |
.value_name(name) ⇒ Object
Look up a value’s name, so we can find options and such.
36 37 38 39 40 |
# File 'lib/vendor/puppet/property.rb', line 36 def self.value_name(name) if value = value_collection.match?(name) value.name end end |
.value_option(name, option) ⇒ Object
Retrieve an option set when a value was defined.
43 44 45 46 47 |
# File 'lib/vendor/puppet/property.rb', line 43 def self.value_option(name, option) if value = value_collection.value(name) value.send(option) end end |
Instance Method Details
#call_provider(value) ⇒ Object
Call the provider method.
70 71 72 73 74 75 76 |
# File 'lib/vendor/puppet/property.rb', line 70 def call_provider(value) method = self.class.name.to_s + "=" unless provider.respond_to? method self.fail "The #{provider.class.name} provider can not handle attribute #{self.class.name}" end provider.send(method, value) end |
#call_valuemethod(name, value) ⇒ Object
Call the dynamically-created method associated with our value, if there is one.
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/vendor/puppet/property.rb', line 80 def call_valuemethod(name, value) if method = self.class.value_option(name, :method) and self.respond_to?(method) begin event = self.send(method) rescue Puppet::Error raise rescue => detail puts detail.backtrace if Puppet[:trace] error = Puppet::Error.new("Could not set '#{value} on #{self.class.name}: #{detail}", @resource.line, @resource.file) error.set_backtrace detail.backtrace raise error end elsif block = self.class.value_option(name, :block) # FIXME It'd be better here to define a method, so that # the blocks could return values. self.instance_eval(&block) else devfail "Could not find method for value '#{name}'" end end |
#change_to_s(current_value, newvalue) ⇒ Object
How should a property change be printed as a string?
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/vendor/puppet/property.rb', line 102 def change_to_s(current_value, newvalue) begin if current_value == :absent return "defined '#{name}' as #{self.class.format_value_for_display should_to_s(newvalue)}" elsif newvalue == :absent or newvalue == [:absent] return "undefined '#{name}' from #{self.class.format_value_for_display is_to_s(current_value)}" else return "#{name} changed #{self.class.format_value_for_display is_to_s(current_value)} to #{self.class.format_value_for_display should_to_s(newvalue)}" end rescue Puppet::Error, Puppet::DevError raise rescue => detail puts detail.backtrace if Puppet[:trace] raise Puppet::DevError, "Could not convert change '#{name}' to string: #{detail}" end end |
#event ⇒ Object
Return a modified form of the resource event.
136 137 138 |
# File 'lib/vendor/puppet/property.rb', line 136 def event resource.event :name => event_name, :desired_value => should, :property => self, :source_description => path end |
#event_name ⇒ Object
Figure out which event to return.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/vendor/puppet/property.rb', line 120 def event_name value = self.should event_name = self.class.value_option(value, :event) and return event_name name == :ensure or return (name.to_s + "_changed").to_sym return (resource.type.to_s + case value when :present; "_created" when :absent; "_removed" else "_changed" end).to_sym end |
#insync?(is) ⇒ Boolean
This method may be overridden by derived classes if necessary to provide extra logic to determine whether the property is in sync. In most cases, however, only ‘property_matches?` needs to be overridden to give the correct outcome - without reproducing all the array matching logic, etc, found here.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/vendor/puppet/property.rb', line 176 def insync?(is) self.devfail "#{self.class.name}'s should is not array" unless @should.is_a?(Array) # an empty array is analogous to no should values return true if @should.empty? # Look for a matching value, either for all the @should values, or any of # them, depending on the configuration of this property. if match_all? then # Emulate Array#== using our own comparison function. # A non-array was not equal to an array, which @should always is. return false unless is.is_a? Array # If they were different lengths, they are not equal. return false unless is.length == @should.length # Finally, are all the elements equal? In order to preserve the # behaviour of previous 2.7.x releases, we need to impose some fun rules # on "equality" here. # # Specifically, we need to implement *this* comparison: the two arrays # are identical if the is values are == the should values, or if the is # values are == the should values, stringified. # # This does mean that property equality is not commutative, and will not # work unless the `is` value is carefully arranged to match the should. return (is == @should or is == @should.map(&:to_s)) # When we stop being idiots about this, and actually have meaningful # semantics, this version is the thing we actually want to do. # # return is.zip(@should).all? {|a, b| property_matches?(a, b) } else return @should.any? {|want| property_matches?(is, want) } end end |
#is_to_s(currentvalue) ⇒ Object
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
228 229 230 |
# File 'lib/vendor/puppet/property.rb', line 228 def is_to_s(currentvalue) currentvalue end |
#log(msg) ⇒ Object
Send a log message.
233 234 235 236 237 238 239 |
# File 'lib/vendor/puppet/property.rb', line 233 def log(msg) Puppet::Util::Log.create( :level => resource[:loglevel], :message => msg, :source => self ) end |
#match_all? ⇒ Boolean
Should we match all values, or just the first?
242 243 244 |
# File 'lib/vendor/puppet/property.rb', line 242 def match_all? self.class.array_matching == :all end |
#munge(value) ⇒ Object
Execute our shadow’s munge code, too, if we have one.
247 248 249 250 251 |
# File 'lib/vendor/puppet/property.rb', line 247 def munge(value) self.shadow.munge(value) if self.shadow super end |
#name ⇒ Object
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
257 258 259 |
# File 'lib/vendor/puppet/property.rb', line 257 def name self.class.name end |
#property_matches?(current, desired) ⇒ Boolean
Compare the current and desired value of a property in a property-specific way. Invoked by ‘insync?`; this should be overridden if your property has a different comparison type but does not actually differentiate the overall insync? logic.
217 218 219 220 221 222 |
# File 'lib/vendor/puppet/property.rb', line 217 def property_matches?(current, desired) # This preserves the older Puppet behaviour of doing raw and string # equality comparisons for all equality. I am not clear this is globally # desirable, but at least it is not a breaking change. --daniel 2011-11-11 current == desired or current == desired.to_s end |
#retrieve ⇒ Object
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.
278 279 280 |
# File 'lib/vendor/puppet/property.rb', line 278 def retrieve provider.send(self.class.name) end |
#safe_insync?(is) ⇒ Boolean
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.
Don’t override this method.
159 160 161 162 163 164 165 |
# File 'lib/vendor/puppet/property.rb', line 159 def safe_insync?(is) # If there is no @should value, consider the property to be in sync. return true unless @should # Otherwise delegate to the (possibly derived) insync? method. insync?(is) end |
#set(value) ⇒ Object
Set our value, using the provider, an associated block, or both.
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
# File 'lib/vendor/puppet/property.rb', line 283 def set(value) # Set a name for looking up associated options like the event. name = self.class.value_name(value) call = self.class.value_option(name, :call) || :none if call == :instead call_valuemethod(name, value) elsif call == :none # They haven't provided a block, and our parent does not have # a provider, so we have no idea how to handle this. self.fail "#{self.class.name} cannot handle values of type #{value.inspect}" unless @resource.provider call_provider(value) else # LAK:NOTE 20081031 This is a change in behaviour -- you could # previously specify :call => [;before|:after], which would call # the setter *in addition to* the block. I'm convinced this # was never used, and it makes things unecessarily complicated. # If you want to specify a block and still call the setter, then # do so in the block. devfail "Cannot use obsolete :call value '#{call}' for property '#{self.class.name}'" end end |
#setup_shadow(klass) ⇒ Object
If there’s a shadowing metaparam, instantiate it now. This allows us to create a property or parameter with the same name as a metaparameter, and the metaparam will only be stored as a shadow.
311 312 313 |
# File 'lib/vendor/puppet/property.rb', line 311 def setup_shadow(klass) @shadow = klass.new(:resource => self.resource) end |
#should ⇒ Object
Only return the first value
316 317 318 319 320 321 322 323 324 325 326 |
# File 'lib/vendor/puppet/property.rb', line 316 def should return nil unless defined?(@should) self.devfail "should for #{self.class.name} on #{resource.name} is not an array" unless @should.is_a?(Array) if match_all? return @should.collect { |val| self.unmunge(val) } else return self.unmunge(@should[0]) end end |
#should=(values) ⇒ Object
Set the should value.
329 330 331 332 333 334 335 336 |
# File 'lib/vendor/puppet/property.rb', line 329 def should=(values) values = [values] unless values.is_a?(Array) @shouldorig = values values.each { |val| validate(val) } @should = values.collect { |val| self.munge(val) } end |
#should_to_s(newvalue) ⇒ Object
338 339 340 |
# File 'lib/vendor/puppet/property.rb', line 338 def should_to_s(newvalue) [newvalue].flatten.join(" ") end |
#sync ⇒ Object
342 343 344 345 |
# File 'lib/vendor/puppet/property.rb', line 342 def sync devfail "Got a nil value for should" unless should set(should) end |
#unsafe_validate(value) ⇒ Object
Verify that the passed value is valid. If the developer uses a ‘validate’ hook, this method will get overridden.
349 350 351 352 |
# File 'lib/vendor/puppet/property.rb', line 349 def unsafe_validate(value) super validate_features_per_value(value) end |
#validate_features_per_value(value) ⇒ Object
Make sure that we’ve got all of the required features for a given value.
355 356 357 358 359 360 361 |
# File 'lib/vendor/puppet/property.rb', line 355 def validate_features_per_value(value) if features = self.class.value_option(self.class.value_name(value), :required_features) features = Array(features) needed_features = features.collect { |f| f.to_s }.join(", ") raise ArgumentError, "Provider must have features '#{needed_features}' to set '#{self.class.name}' to '#{value}'" unless provider.satisfies?(features) end end |
#value ⇒ Object
Just return any should value we might have.
364 365 366 |
# File 'lib/vendor/puppet/property.rb', line 364 def value self.should end |
#value=(value) ⇒ Object
Match the Parameter interface, but we really just use ‘should’ internally. Note that the should= method does all of the validation and such.
370 371 372 |
# File 'lib/vendor/puppet/property.rb', line 370 def value=(value) self.should = value end |