Class: Puppet::Property Abstract

Inherits:
Parameter show all
Defined in:
lib/puppet/property.rb,
lib/puppet/property/list.rb,
lib/puppet/property/keyvalue.rb,
lib/puppet/property/ordered_list.rb

Overview

This class is abstract.
Note:

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.

See Also:

Direct Known Subclasses

Boolean, Ensure, KeyValue, List, SELFileContext

Defined Under Namespace

Classes: Boolean, Ensure, KeyValue, List, OrderedList

Constant Summary

Constants included from Util::Docs

Util::Docs::HEADER_LEVELS

Constants included from Util

Util::AbsolutePathPosix, Util::AbsolutePathWindows, Util::DEFAULT_POSIX_MODE, Util::DEFAULT_WINDOWS_MODE, Util::RFC_3986_URI_REGEX

Constants included from Util::SymbolicFileMode

Util::SymbolicFileMode::SetGIDBit, Util::SymbolicFileMode::SetUIDBit, Util::SymbolicFileMode::StickyBit, Util::SymbolicFileMode::SymbolicMode, Util::SymbolicFileMode::SymbolicSpecialToBit

Constants included from Util::POSIX

Util::POSIX::LOCALE_ENV_VARS, Util::POSIX::USER_ENV_VARS

Class Attribute Summary collapse

Instance Attribute Summary collapse

Attributes inherited from Parameter

#parent, #resource, #sensitive

Attributes included from Util::Docs

#doc, #nodoc

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Parameter

aliasvalue, defaultto, desc, doc, #file, #format, format_value_for_display, #initialize, initvars, isnamevar, isnamevar?, #isnamevar?, isrequired, #line, #metaparam?, munge, #munge, newvalues, nodefault, #path, #pathbuilder, #provider, proxymethods, #remove, required?, #required?, sensitive, #tags, #to_s, #unmunge, unmunge, #unsafe_munge, #validate, validate, #version

Methods included from Util::Docs

#desc, #dochook, #doctable, #markdown_definitionlist, #markdown_header, #nodoc?, #pad, scrub

Methods included from Util

absolute_path?, benchmark, chuser, clear_environment, default_env, deterministic_rand, deterministic_rand_int, exit_on_fail, get_env, get_environment, logmethods, merge_environment, path_to_uri, pretty_backtrace, replace_file, safe_posix_fork, set_env, symbolizehash, thinmark, uri_encode, uri_query_encode, uri_to_path, which, withenv, withumask

Methods included from Util::SymbolicFileMode

#normalize_symbolic_mode, #symbolic_mode_to_int, #valid_symbolic_mode?

Methods included from Util::POSIX

#get_posix_field, #gid, groups_of, #idfield, #methodbyid, #methodbyname, #search_posix_field, #uid

Methods included from Util::Logging

#clear_deprecation_warnings, #debug, #deprecation_warning, #format_exception, #get_deprecation_offender, #log_and_raise, #log_deprecations_to_file, #log_exception, #puppet_deprecation_warning, #send_log, setup_facter_logging!, #warn_once

Methods included from Util::Errors

#adderrorcontext, #devfail, #error_context, error_location, error_location_with_space, error_location_with_unknowns, #exceptwrap, #fail

Constructor Details

This class inherits a constructor from Puppet::Parameter

Class Attribute Details

.array_matchingSymbol

Note:

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 the `is` value matches any of the values in the `should` array. When the `is` value is also an array, the matching is performed against the entire array as the `is` value.

  • `:all` : This is primarily used for multi-valued properties. When matched against an array of

    `should` values, the size of `is` and `should` must be the same, and all values in `is` must match
    a value in `should`.
    

Returns:

  • (Symbol)

    (:first) the mode in which matching is performed

See Also:


90
91
92
# File 'lib/puppet/property.rb', line 90

def array_matching
  @array_matching ||= :first
end

.nameSymbol (readonly)

Returns The name of the property as given when the property was created.

Returns:

  • (Symbol)

    The name of the property as given when the property was created.


66
67
68
# File 'lib/puppet/property.rb', line 66

def name
  @name
end

.unmanagedObject

TODO:

Figure out what this is used for. Can not find any logic in the puppet code base that reads or writes this attribute.

??? Probably Unused


62
63
64
# File 'lib/puppet/property.rb', line 62

def unmanaged
  @unmanaged
end

Instance Attribute Details

#noopBoolean

TODO:

This logic is different than Parameter#noop in that the resource noop mode overrides the property's mode - in parameter it is the other way around. Bug or feature?

Returns whether this property is in noop mode or not; if a difference between the is and should values should be acted on or not. The noop mode is a transitive setting. The mode is checked in this property, then in the _associated resource_ and finally in Puppet.

Returns:

  • (Boolean)

    whether this property is in noop mode or not.


448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/puppet/property.rb', line 448

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

#shouldorigArray<Object>, ... (readonly)

Returns the original wanted value(s) _(should)_ unprocessed by munging/unmunging. The original values are set by #value= or #should=.

Returns:

  • (Array<Object>, Object, nil)

    Array of values if #match_all? else a single value, or nil if there are no wanted values.


48
49
50
# File 'lib/puppet/property.rb', line 48

def shouldorig
  @shouldorig
end

Class Method Details

.idempotentBoolean

Used to mark a type property as having or lacking idempotency (on purpose generally). This is used to avoid marking the property as a corrective_change when there is known idempotency issues with the property rendering a corrective_change flag as useless.

Returns:

  • (Boolean)

    true if the property is marked as idempotent


108
109
110
# File 'lib/puppet/property.rb', line 108

def idempotent
  @idempotent.nil? ? @idempotent = true : @idempotent
end

.idempotent=(value) ⇒ Object

Attribute setter for the idempotent attribute.

Parameters:

  • value (bool)

    boolean indicating if the property is idempotent.

See Also:


115
116
117
# File 'lib/puppet/property.rb', line 115

def idempotent=(value)
  @idempotent = value
end

.method_added(sym) ⇒ Object

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.

Raises:

  • (RuntimeError)

    if the added method is `:safe_insync?`


283
284
285
# File 'lib/puppet/property.rb', line 283

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

TODO:

Option :event original comment says “event should be returned…”, is “returned” the correct word to use?

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.

Parameters:

  • name (Symbol, Regexp)

    a valid literal value, or a regexp that matches a value

  • options (Hash) (defaults to: {})

    a hash with options

Options Hash (options):

  • :event (Symbol)

    The event that should be emitted when this value is set.

  • :invalidate_refreshes (Symbol)

    Indicates a change on this property should invalidate and remove any scheduled refreshes (from notify or subscribe) targeted at the same resource. For example, if a change in this property takes into account any changes that a scheduled refresh would have performed, then the scheduled refresh would be deleted.

  • any (Object)

    Any other option is treated as a call to a setter having the given option name (e.g. `:required_features` calls `required_features=` with the option's value as an argument).


162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/puppet/property.rb', line 162

def self.newvalue(name, options = {}, &block)
  value = value_collection.newvalue(name, options, &block)

  unless value.method.nil?
    method = value.method.to_sym
    if value.block
      if instance_methods(false).include?(method)
        raise ArgumentError, _("Attempt to redefine method %{method} with block") % { method: method }
      end
      define_method(method, &value.block)
    else
      # Let the method be an alias for calling the providers setter unless we already have this method
      alias_method(method, :call_provider) unless method_defined?(method)
    end
  end
  value
end

.value_name(name) ⇒ Symbol, Regexp

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.

Parameters:

  • name (Object)

    the parameter value to match against valid values (names).

Returns:

  • (Symbol, Regexp)

    a value matching predicate


125
126
127
128
# File 'lib/puppet/property.rb', line 125

def self.value_name(name)
  value = value_collection.match?(name)
  value.name if value
end

.value_option(name, option) ⇒ Object

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.

TODO:

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).

Parameters:

  • name (Symbol, Regexp)

    the valid value predicate as returned by value_name

  • option (Symbol)

    the name of the wanted option

Returns:

  • (Object)

    value of the option

Raises:

  • (NoMethodError)

    if the option is not supported


138
139
140
141
# File 'lib/puppet/property.rb', line 138

def self.value_option(name, option)
  value = value_collection.value(name)
  value.send(option) if value
end

Instance Method Details

#call_provider(value) ⇒ Object

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.

Returns:

  • (Object)

    what the provider returns when calling a setter for this property's name

Raises:

  • (Puppet::Error)

    when the provider can not handle this property.

See Also:


186
187
188
189
190
191
192
193
194
# File 'lib/puppet/property.rb', line 186

def call_provider(value)
  # We have no idea how to handle this unless our parent have a provider
  self.fail "#{self.class.name} cannot handle values of type #{value.inspect}" unless @resource.provider
  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

#change_to_s(current_value, newvalue) ⇒ String

Note:

If called with equal values, this is reported as a change.

Formats a message for a property change from the given `current_value` to the given `newvalue`.

Returns:

  • (String)

    a message describing the property change.

Raises:


201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/puppet/property.rb', line 201

def change_to_s(current_value, newvalue)
  begin
    if current_value == :absent
      return "defined '#{name}' as #{should_to_s(newvalue)}"
    elsif newvalue == :absent or newvalue == [:absent]
      return "undefined '#{name}' from #{is_to_s(current_value)}"
    else
      return "#{name} changed #{is_to_s(current_value)} to #{should_to_s(newvalue)}"
    end
  rescue Puppet::Error
    raise
  rescue => detail
    message = _("Could not convert change '%{name}' to string: %{detail}") % { name: name, detail: detail }
    Puppet.log_exception(detail, message)
    raise Puppet::DevError, message, detail.backtrace
  end
end

#event(options = {}) ⇒ Puppet::Transaction::Event

Produces an event describing a change of this property. In addition to the event attributes set by the resource type, this method adds:

  • `:name` - the event_name

  • `:desired_value` - a.k.a should or _wanted value_

  • `:property` - reference to this property

  • `:source_description` - The containment path of this property, indicating what resource this

    property is associated with and in what stage and class that resource
    was declared, e.g. "/Stage[main]/Myclass/File[/tmp/example]/ensure"
    
  • `:invalidate_refreshes` - if scheduled refreshes should be invalidated

  • `:redacted` - if the event will be redacted (due to this property being sensitive)

Returns:

See Also:


254
255
256
257
258
259
260
261
# File 'lib/puppet/property.rb', line 254

def event(options = {})
  attrs = { :name => event_name, :desired_value => should, :property => self, :source_description => path }.merge(options)
  value = self.class.value_collection.match?(should) if should
  
  attrs[:invalidate_refreshes] = true if value && value.invalidate_refreshes 
  attrs[:redacted] = @sensitive
  resource.event attrs
end

#event_nameString

Produces the name of the event to use to describe a change of this property's value. The produced event name is either the event name configured for this property, or a generic event based on the name of the property with suffix `_changed`, or if the property is `:ensure`, the name of the resource type and one of the suffixes `_created`, `_removed`, or `_changed`.

Returns:

  • (String)

    the name of the event that describes the change


225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/puppet/property.rb', line 225

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

#idempotent?Boolean

Returns whether the property is marked as idempotent for the purposes of calculating corrective change.

Returns:

  • (Boolean)

    whether the property is marked as idempotent for the purposes of calculating corrective change.


429
430
431
# File 'lib/puppet/property.rb', line 429

def idempotent?
  self.class.idempotent
end

#insync?(is) ⇒ Boolean

TODO:

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.

Note:

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.

Parameters:

  • is (Object)

    The current _(is)_ value to check if it is in sync with the wanted _(should)_ value(s)

Returns:

  • (Boolean)

    whether the values are in sync or not.

Raises:


307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/puppet/property.rb', line 307

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

#insync_values?(should, is) ⇒ Boolean

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 tests if two values are insync? outside of the properties current should value. This works around the requirement for corrective_change analysis that requires two older values to be compared with the properties potentially custom insync? code.

Parameters:

  • should (Object)

    the value it should be

  • is (Object)

    the value it is

Returns:

  • (Boolean)

    whether or not the values are in sync or not


353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
# File 'lib/puppet/property.rb', line 353

def insync_values?(should, is)
  # Here be dragons. We're setting the should value of a property purely just to
  # call its insync? method, as it lacks a way to pass in a should.
  # Unfortunately there isn't an API compatible way of avoiding this, as both should
  # an insync? behaviours are part of the public API. Future API work should factor
  # this kind of arbitrary comparisons into the API to remove this complexity. -ken

  # Backup old should, set it to the new value, then call insync? on the property.
  old_should = @should

  begin
    @should = should
    insync?(is)
  rescue
    # Certain operations may fail, but we don't want to fail the transaction if we can
    # avoid it
    #TRANSLATORS 'insync_values?' should not be translated
    msg = _("Unknown failure using insync_values? on type: %{type} / property: %{name} to compare values %{should} and %{is}") %
        { type: self.resource.ref, name: self.name, should: should, is: is }
    Puppet.info(msg)

    # Return nil, ie. unknown
    nil
  ensure
    # Always restore old should
    @should = old_should
  end
end

#is_to_s(value) ⇒ String

Produces a pretty printing string for the given value. This default implementation calls #format_value_for_display on the class. A derived implementation may perform property specific pretty printing when the is values are not already in suitable form.

Parameters:

  • value (Object)

    the value to format as a string

Returns:

  • (String)

    a pretty printing string


405
406
407
# File 'lib/puppet/property.rb', line 405

def is_to_s(value)
  self.class.format_value_for_display(value)
end

#log(msg) ⇒ void

This method returns an undefined value.

Emits a log message at the log level specified for the associated resource. The log entry is associated with this property.

Parameters:

  • msg (String)

    the message to log


414
415
416
417
418
419
420
# File 'lib/puppet/property.rb', line 414

def log(msg)
  Puppet::Util::Log.create(
    :level   => resource[:loglevel],
    :message => msg,
    :source  => self
  )
end

#match_all?Boolean

Returns whether the array_matching mode is set to `:all` or not

Returns:


423
424
425
# File 'lib/puppet/property.rb', line 423

def match_all?
  self.class.array_matching == :all
end

#nameSymbol

Note:

A property class (just like a parameter class) describes one specific property and can only be used once within one type's inheritance chain.

Returns the name of the property as stated when the property was created.

Returns:

  • (Symbol)

    the name of the property as stated when the property was created.


436
437
438
# File 'lib/puppet/property.rb', line 436

def name
  self.class.name
end

#property_matches?(current, desired) ⇒ Boolean

Checks if the given current and desired values are equal. This default implementation performs this check in a backwards compatible way where the equality of the two values is checked, and then the equality of current with desired converted to a string.

A derived implementation may override this method to perform a property specific equality check.

The intent of this method is to provide an equality check suitable for checking if the property value is in sync or not. It is typically called from #insync?.

Returns:


392
393
394
395
396
397
# File 'lib/puppet/property.rb', line 392

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

#retrieveObject

Retrieves the current value _(is)_ of this property from the provider. This implementation performs this operation by calling a provider method with the same name as this property (i.e. if the property name is 'gid', a call to the 'provider.gid' is expected to return the current value.

Returns:

  • (Object)

    what the provider returns as the current value of the property


467
468
469
# File 'lib/puppet/property.rb', line 467

def retrieve
  provider.send(self.class.name)
end

#safe_insync?(is) ⇒ Boolean

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.

Note:

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.

Note:

Do not override this method.

Determines whether the property is in-sync or not in a way that is protected against missing value.

Returns:

  • (Boolean)

    the protected result of `true` or the result of calling #insync?.


271
272
273
274
275
276
277
# File 'lib/puppet/property.rb', line 271

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

Sets the current _(is)_ value of this property. The name associated with the value is first obtained by calling value_name. A dynamically created setter method associated with this name is called if it exists, otherwise the value is set using using the provider's setter method for this property by calling (#call_provider).

Parameters:

  • value (Object)

    the value to set

Returns:

Raises:

  • (Puppet::Error)

    if there were problems setting the value using the setter method or when the provider setter should be used but there is no provider in the associated resource_

  • (Puppet::ResourceError)

    if there was a problem setting the value and it was not raised as a Puppet::Error. The original exception is wrapped and logged.


484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
# File 'lib/puppet/property.rb', line 484

def set(value)
  # Set a name for looking up associated options like the event.
  name = self.class.value_name(value)
  method = self.class.value_option(name, :method)
  if method && self.respond_to?(method)
    begin
      self.send(method)
    rescue Puppet::Error
      raise
    rescue => detail
      error = Puppet::ResourceError.new(_("Could not set '%{value}' on %{class_name}: %{detail}") %
                                            { value: value, class_name: self.class.name, detail: detail }, @resource.file, @resource.line, detail)
      error.set_backtrace detail.backtrace
      Puppet.log_exception(detail, error.message)
      raise error
    end
  else
    block = self.class.value_option(name, :block)
    if block
      # FIXME It'd be better here to define a method, so that
      # the blocks could return values.
      self.instance_eval(&block)
    else
      call_provider(value)
    end
  end
end

#shouldArray<Object>, ...

Note:

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.

Returns:

  • (Array<Object>, Object, nil)

    Array of values if #match_all? else a single value, or nil if there are no wanted values.

Raises:

See Also:


525
526
527
528
529
530
531
532
533
534
535
# File 'lib/puppet/property.rb', line 525

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

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.

Parameters:

  • values (Array<Object>, Object)

    the value(s) to set as the wanted value(s)

Raises:


545
546
547
548
549
550
551
552
# File 'lib/puppet/property.rb', line 545

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(value) ⇒ String

Produces a pretty printing string for the given value. This default implementation calls #format_value_for_display on the class. A derived implementation may perform property specific pretty printing when the should values are not already in suitable form.

Parameters:

  • value (Object)

    the value to format as a string

Returns:

  • (String)

    a pretty printing string


560
561
562
# File 'lib/puppet/property.rb', line 560

def should_to_s(value)
  self.class.format_value_for_display(value)
end

#syncObject

TODO:

The implementation of this method is somewhat inefficient as it computes the should array twice.

Synchronizes the current value _(is)_ and the wanted value _(should)_ by calling #set.

Raises:


568
569
570
571
# File 'lib/puppet/property.rb', line 568

def sync
  devfail "Got a nil value for should" unless should
  set(should)
end

#unsafe_validate(value) ⇒ void

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.

Raises:

  • (Exception)

    if the value is invalid, or value can not be handled.


579
580
581
582
# File 'lib/puppet/property.rb', line 579

def unsafe_validate(value)
  super
  validate_features_per_value(value)
end

#validate_features_per_value(value) ⇒ void

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.

Raises:

  • (ArgumentError)

    if a required feature is not present


589
590
591
592
593
594
595
596
597
598
599
600
# File 'lib/puppet/property.rb', line 589

def validate_features_per_value(value)
  features = self.class.value_option(self.class.value_name(value), :required_features)
  if features
    features = Array(features)
    needed_features = features.collect { |f| f.to_s }.join(", ")
    unless provider.satisfies?(features)
      #TRANSLATORS 'Provider' refers to a Puppet provider class
      raise ArgumentError, _("Provider %{provider} must have features '%{needed_features}' to set '%{property}' to '%{value}'") %
          { provider: provider.class.name, needed_features: needed_features, property: self.class.name, value: value }
    end
  end
end

#valueObject?

Returns the wanted _(should)_ value of this property.

Returns:

  • (Object, nil)

    Returns the wanted _(should)_ value of this property.


603
604
605
# File 'lib/puppet/property.rb', line 603

def value
  self.should
end

#value=(values) ⇒ Object

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.

Parameters:

  • values (Array<Object>, Object)

    the value(s) to set as the wanted value(s)

Raises:


608
609
610
# File 'lib/puppet/property.rb', line 608

def value=(values)
  self.should = values
end