Class: Puppet::Property Abstract
- Inherits:
-
Parameter
- Object
- Parameter
- Puppet::Property
- Defined in:
- lib/puppet/property.rb,
lib/puppet/type/zpool.rb,
lib/puppet/property/list.rb,
lib/puppet/property/keyvalue.rb,
lib/puppet/property/ordered_list.rb
Overview
Describe meta-parameter shadowing. This concept can not be understood by just looking at the descriptions of the methods involved.
Properties of Types are expressed using subclasses of this class. Such a class describes one named property of a particular Type (as opposed to describing a type of property in general). This limits the use of one (concrete) property class instance to occur only once for a given type’s inheritance chain. An instance of a Property class is the value holder of one instance of the resource type (e.g. the mode of a file resource instance). A Property class may server as the superclass (parent) of another; e.g. a Size property that describes handling of measurements such as kb, mb, gb. If a type requires two different size measurements it requires one concrete class per such measure; e.g. MinSize (:parent => Size), and MaxSize (:parent => Size).
The Property class is the implementation of a resource’s attributes of property kind. A Property is a specialized Resource Type Parameter that has both an ‘is’ (current) state, and a ‘should’ (wanted state). However, even if this is conceptually true, the current is value is obtained by asking the associated provider for the value, and hence it is not actually part of a property’s state, and only available when a provider has been selected and can obtain the value (i.e. when running on an agent).
A Property (also in contrast to a parameter) is intended to describe a managed attribute of some system entity, such as the name or mode of a file.
The current value (is) is read and written with the methods #retrieve and #set, and the wanted value (should) is read and written with the methods #value and #value= which delegate to #should and #should=, i.e. when a property is used like any other parameter, it is the should value that is operated on.
All resource type properties in the puppet system are derived from this class.
The intention is that new parameters are created by using the DSL method Type.newproperty.
Direct Known Subclasses
Defined Under Namespace
Classes: Ensure
Constant Summary
Class Attribute Summary (collapse)
-
+ (Symbol) array_matching
DSL
readonly
The
is
vs.should
array matching mode;:first
, or:all
.
Attributes inherited from Parameter
Class Method Summary (collapse)
-
+ (Object) method_added(sym)
private
Protects against override of the #safe_insync? method.
-
+ (Object) newvalue(name, options = {}, &block)
DSL
Defines a new valid value for this property.
-
+ (Symbol, Regexp) value_name(name)
private
Looks up a value’s name among valid values, to enable option lookup with result as a key.
-
+ (Object) value_option(name, option)
private
Returns the value of the given option (set when a valid value with the given “name” was defined).
Instance Method Summary (collapse)
-
- (Object) call_provider(value)
private
Calls the provider setter method for this property with the given value as argument.
-
- (Object) call_valuemethod(name, value)
private
Sets the value of this property to the given value by calling the dynamically created setter method associated with the “valid value” referenced by the given name.
-
- (Property) initialize(hash = {})
constructor
private
Initializes a Property the same way as a Parameter and handles the special case when a property is shadowing a meta-parameter.
-
- (Boolean) insync?(is)
Checks if the current (is) value is in sync with the wanted (should) value.
-
- (Boolean) safe_insync?(is)
private
Determines whether the property is in-sync or not in a way that is protected against missing value.
-
- (Object) set(value)
Sets the current (is) value of this property.
-
- (Array<Object>, ...) should
Returns the wanted (should) value of this property.
-
- (Object) should=(values)
Sets the wanted (should) value of this property.
-
- unsafe_validate(value)
private
Asserts that the given value is valid.
-
- validate_features_per_value(value)
private
Asserts that all required provider features are present for the given property value.
Methods inherited from Parameter
aliasvalue, defaultto, desc, doc, initvars, isnamevar, isnamevar?, isrequired, munge, newvalues, nodefault, #pathbuilder, proxymethods, required?, unmunge, #unsafe_munge, validate, #validate
Methods included from Util
exit_on_fail, #exit_on_fail, which, #which
Constructor Details
- (Property) initialize(hash = {}) private
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
There is some special initialization when a property is not a metaparameter but Puppet::Type.metaparamclass(for this class’s name) is not nil - if that is the case a setup_shadow is performed for that class.
New properties of a type should be created via the DSL method Type.newproperty.
Initializes a Property the same way as a Parameter and handles the special case when a property is shadowing a meta-parameter.
284 285 286 287 288 289 290 |
# File 'lib/puppet/property.rb', line 284 def initialize(hash = {}) super if ! self. and klass = Puppet::Type.(self.class.name) setup_shadow(klass) end end |
Class Attribute Details
+ (Symbol) array_matching DSL
The semantics of these modes are implemented by the method #insync?. That method is the default implementation and it has a backwards compatible behavior that imposes additional constraints on what constitutes a positive match. A derived property may override that method.
The is
vs. should
array matching mode; :first
, or :all
.
:first
This is primarily used for single value properties. When matched against an array of values a match is true if theis
value matches any of the values in theshould
array. When theis
value is also an array, the matching is performed against the entire array as theis
value.-
:all
- This is primarily used for multi-valued properties. When matched against an array of
should
values, the size ofis
andshould
must be the same, and all values inis
must match a value inshould
.
93 94 95 |
# File 'lib/puppet/property.rb', line 93 def array_matching @array_matching ||= :first end |
Class Method Details
+ (Object) method_added(sym) private
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Protects against override of the #safe_insync? method.
312 313 314 |
# File 'lib/puppet/property.rb', line 312 def self.method_added(sym) raise "Puppet::Property#safe_insync? shouldn't be overridden; please override insync? instead" if sym == :safe_insync? end |
+ (Object) newvalue(name, options = {}, &block) DSL
Option :event original comment says “event should be returned…”, is “returned” the correct word to use?
The original documentation states that the option :method
will set the name of the generated
setter method, but this is not implemented. Is the documentatin or the implementation in error?
(The implementation is in Puppet::Parameter::ValueCollection#new_value).
verify that the use of :before and :after have been deprecated (or rather - never worked, and was never in use. (This means, that the option :call could be removed since calls are always :instead).
Defines a new valid value for this property. A valid value is specified as a literal (typically a Symbol), but can also be specified with a Regexp.
156 157 158 159 160 161 |
# File 'lib/puppet/property.rb', line 156 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 |
+ (Symbol, Regexp) value_name(name) private
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Looks up a value’s name among valid values, to enable option lookup with result as a key.
111 112 113 114 115 |
# File 'lib/puppet/property.rb', line 111 def self.value_name(name) if value = value_collection.match?(name) value.name end end |
+ (Object) value_option(name, option) private
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Guessing on result of passing a non supported option (it performs send(option)).
Returns the value of the given option (set when a valid value with the given “name” was defined).
125 126 127 128 129 |
# File 'lib/puppet/property.rb', line 125 def self.value_option(name, option) if value = value_collection.value(name) value.send(option) end end |
Instance Method Details
- (Object) call_provider(value) private
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Calls the provider setter method for this property with the given value as argument.
169 170 171 172 173 174 175 |
# File 'lib/puppet/property.rb', line 169 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 |
- (Object) call_valuemethod(name, value) private
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The check for a valid value option called :method
does not seem to be fully supported
as it seems that this option is never consulted when the method is dynamically created. Needs to
be investigated. (Bug, or documentation needs to be changed).
Sets the value of this property to the given value by calling the dynamically created setter method associated with the “valid value” referenced by the given name.
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/puppet/property.rb', line 190 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 error = Puppet::ResourceError.new("Could not set '#{value}' on #{self.class.name}: #{detail}", @resource.line, @resource.file, detail) error.set_backtrace detail.backtrace Puppet.log_exception(detail, error.) 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 |
- (Boolean) insync?(is)
The implementation should really do return is.zip(@should).all? {|a, b| property_matches?(a, b) } instead of using equality check and then check against an array with converted strings.
The array matching logic in this method contains backwards compatible logic that performs the
comparison in :all
mode by checking equality and equality of is against should converted to array of String,
and that the lengths are equal, and in :first
mode by checking if one of the should values
is included in the is values. This means that the is value needs to be carefully arranged to
match the should.
Checks if the current (is) value is in sync with the wanted (should) value.
The check if the two values are in sync is controlled by the result of #match_all? which
specifies a match of :first
or :all
). The matching of the is value against the entire should value
or each of the should values (as controlled by #match_all? is performed by #property_matches?.
A derived property typically only needs to override the #property_matches? method, but may also override this method if there is a need to have more control over the array matching logic.
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
# File 'lib/puppet/property.rb', line 336 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 |
- (Boolean) safe_insync?(is) private
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
If the wanted value (should) is not defined or is set to a non-true value then this is a state that can not be fixed and the property is reported to be in sync.
Do not override this method.
Determines whether the property is in-sync or not in a way that is protected against missing value.
300 301 302 303 304 305 306 |
# File 'lib/puppet/property.rb', line 300 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 |
- (Object) set(value)
In older versions (before 20081031) it was possible to specify the call types :before
and :after
which had the effect that both the provider method and the valid value block were called.
This is no longer supported.
Sets the current (is) value of this property.
The value is set using the provider’s setter method for this property (#call_provider) if nothing
else has been specified. If the valid value for the given value defines a :call
option with the
value :instead
, the
value is set with #call_valuemethod which invokes a block specified for the valid value.
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 |
# File 'lib/puppet/property.rb', line 482 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 |
- (Array<Object>, ...) should
This method will potentially return different values than the original values as they are converted via munging/unmunging. If the original values are wanted, call #shouldorig.
Returns the wanted (should) value of this property. If the array matching mode #match_all? is true, an array of the wanted values in unmunged format is returned, else the first value in the array of wanted values in unmunged format is returned.
529 530 531 532 533 534 535 536 537 538 539 |
# File 'lib/puppet/property.rb', line 529 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 |
- (Object) should=(values)
Sets the wanted (should) value of this property. If the given value is not already an Array, it will be wrapped in one before being set. This method also sets the cached original should values returned by #shouldorig.
549 550 551 552 553 554 555 556 |
# File 'lib/puppet/property.rb', line 549 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 |
- unsafe_validate(value) private
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Asserts that the given value is valid. If the developer uses a ‘validate’ hook, this method will get overridden.
581 582 583 584 |
# File 'lib/puppet/property.rb', line 581 def unsafe_validate(value) super validate_features_per_value(value) end |
- validate_features_per_value(value) private
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Asserts that all required provider features are present for the given property value.
591 592 593 594 595 596 597 |
# File 'lib/puppet/property.rb', line 591 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 |