class Puppet::Type
The base class for all Puppet
types.
A type describes:
Attributes
@todo Don't know if this is a name, or a reference to a Provider
instance (now marked up as an instance
of Provider.
@return [Puppet::Provider, nil] The default provider for this type, or nil if non is defines
@return [String] the name of the resource type; e.g., “File”
The reference to a parent type for the parameter `:provider` used to get a list of providers for documentation purposes.
@return [Array<Puppet::Property>] The list of declared properties for the resource type. The returned lists contains instances if Puppet::Property
or its subclasses.
The loader of providers to use when loading providers from disk. Although it looks like this attribute provides a way to operate with different loaders of providers that is not the case; the attribute is written when a new type is created, and should not be changed thereafter. @api private
@return [Boolean] true if the type should send itself a refresh event on change.
@todo what does this mean “this resource” (sounds like this if for an instance of the type, not the meta Type
),
but not sure if this is about the catalog where the meta Type is included)
@return [??? TODO] The catalog that this resource is stored in.
@return [Boolean] Flag indicating if this type is exported
@return [String] The file from which this type originates from
@return [Integer] The line in {#file} from which this type originates from
The noop attribute of WHAT ??? does WHAT??? @todo Figure out what this is the noop attribute of (it appears on line 1931 currently). @return [???] the noop WHAT ??? (mode? if so of what, or noop for an instance of the type, or for all
instances of a type, or for what???
@return [Hash] hash of parameters originally defined @api private
The provider that has been selected for the instance of the resource type. @return [Puppet::Provider,nil] the selected provider or nil, if none has been selected
The title attribute of WHAT ??? @todo Figure out what this is the title attribute of (it appears on line 1926 currently). @return [String] the title
@return [Boolean] Flag indicating if the type is virtual (it should not be).
Public Class Methods
Returns all the attribute names of the type in the appropriate order. The {key_attributes} come first, then the {provider}, then the {properties}, and finally the {parameters} and {metaparams}, all in the order they were specified in the respective files. @return [Array<String>] all type attribute names in a defined order.
# File lib/puppet/type.rb 122 def self.allattrs 123 key_attributes | (parameters & [:provider]) | properties.collect { |property| property.name } | parameters | metaparams 124 end
Makes this type apply to `:host` if not already applied to something else. @return [Symbol] a `:device`, `:host`, or `:both` enumeration @api private
# File lib/puppet/type.rb 250 def self.apply_to 251 @apply_to ||= :host 252 end
Makes this type applicable to `:both` (i.e. `:host` and `:device`). @return [Symbol] Returns `:both` @api private
# File lib/puppet/type.rb 243 def self.apply_to_all 244 @apply_to = :both 245 end
@comment These `apply_to` methods are horrible. They should really be implemented
as part of the usual system of constraints that apply to a type and provider pair, but were implemented as a separate shadow system.
@comment We should rip them out in favour of a real constraint pattern around the
target device - whatever that looks like - and not have this additional magic here. --daniel 2012-03-08
Makes this type applicable to `:device`. @return [Symbol] Returns `:device` @api private
# File lib/puppet/type.rb 227 def self.apply_to_device 228 @apply_to = :device 229 end
Makes this type applicable to `:host`. @return [Symbol] Returns `:host` @api private
# File lib/puppet/type.rb 235 def self.apply_to_host 236 @apply_to = :host 237 end
Returns the class associated with the given attribute name. @param name [String] the name of the attribute to obtain the class for @return [Class, nil] the class for the given attribute, or nil if the name does not refer to an existing attribute
# File lib/puppet/type.rb 130 def self.attrclass(name) 131 @attrclasses ||= {} 132 133 # We cache the value, since this method gets called such a huge number 134 # of times (as in, hundreds of thousands in a given run). 135 unless @attrclasses.include?(name) 136 @attrclasses[name] = case self.attrtype(name) 137 when :property; @validproperties[name] 138 when :meta; @@metaparamhash[name] 139 when :param; @paramhash[name] 140 end 141 end 142 @attrclasses[name] 143 end
Returns the attribute type (`:property`, `;param`, `:meta`). @comment What type of parameter are we dealing with? Cache the results, because
this method gets called so many times.
@return [Symbol] a symbol describing the type of attribute (`:property`, `;param`, `:meta`)
# File lib/puppet/type.rb 150 def self.attrtype(attr) 151 @attrtypes ||= {} 152 unless @attrtypes.include?(attr) 153 @attrtypes[attr] = case 154 when @validproperties.include?(attr); :property 155 when @paramhash.include?(attr); :param 156 when @@metaparamhash.include?(attr); :meta 157 end 158 end 159 160 @attrtypes[attr] 161 end
# File lib/puppet/type.rb 2039 def self.autobefore(name, &block) 2040 @autobefores ||= {} 2041 @autobefores[name] = block 2042 end
# File lib/puppet/type.rb 2049 def self.autonotify(name, &block) 2050 @autonotifies ||= {} 2051 @autonotifies[name] = block 2052 end
Adds a block producing a single name (or list of names) of the given resource type name to autorelate.
The four relationship types require, before, notify, and subscribe are all supported.
Be careful with notify and subscribe as they may have unintended consequences.
Resources in the catalog that have the named type and a title that is included in the result will be linked to the calling resource as a requirement.
@example Autorequire the files File['foo', 'bar']
autorequire( 'file', {|| ['foo', 'bar'] })
@example Autobefore the files File['foo', 'bar']
autobefore( 'file', {|| ['foo', 'bar'] })
@example Autosubscribe the files File['foo', 'bar']
autosubscribe( 'file', {|| ['foo', 'bar'] })
@example Autonotify the files File['foo', 'bar']
autonotify( 'file', {|| ['foo', 'bar'] })
@param name [String] the name of a type of which one or several resources should be autorelated e.g. “file” @yield [ ] a block returning list of names of given type to auto require @yieldreturn [String, Array<String>] one or several resource names for the named type @return [void] @dsl type @api public
# File lib/puppet/type.rb 2034 def self.autorequire(name, &block) 2035 @autorequires ||= {} 2036 @autorequires[name] = block 2037 end
# File lib/puppet/type.rb 2044 def self.autosubscribe(name, &block) 2045 @autosubscribes ||= {} 2046 @autosubscribes[name] = block 2047 end
Returns true if this type is applicable to the given target. @param target [Symbol] should be :device, :host or :target, if anything else, :host is enforced @return [Boolean] true @api private
# File lib/puppet/type.rb 259 def self.can_apply_to(target) 260 [ target == :device ? :device : :host, :both ].include?(apply_to) 261 end
The default provider, or the most suitable provider if no default provider was set. @note a warning will be issued if no default provider has been configured and a search for the most
suitable provider returns more than one equally suitable provider.
@return [Puppet::Provider, nil] the default or most suitable provider, or nil if no provider was found
# File lib/puppet/type.rb 1734 def self.defaultprovider 1735 return @defaultprovider if @defaultprovider 1736 1737 suitable = suitableprovider 1738 1739 # Find which providers are a default for this system. 1740 defaults = suitable.find_all { |provider| provider.default? } 1741 1742 # If we don't have any default we use suitable providers 1743 defaults = suitable if defaults.empty? 1744 max = defaults.collect { |provider| provider.specificity }.max 1745 defaults = defaults.find_all { |provider| provider.specificity == max } 1746 1747 if defaults.length > 1 1748 Puppet.warning(_("Found multiple default providers for %{name}: %{provider_list}; using %{selected_provider}") % 1749 { name: self.name, provider_list: defaults.collect { |i| i.name.to_s }.join(", "), selected_provider: defaults[0].name }) 1750 end 1751 1752 @defaultprovider = defaults.shift unless defaults.empty? 1753 end
Provides the ability to add documentation to a provider.
# File lib/puppet/type.rb 1888 def self.doc 1889 # Since we're mixing @doc with text from other sources, we must normalize 1890 # its indentation with scrub. But we don't need to manually scrub the 1891 # provider's doc string, since markdown_definitionlist sanitizes its inputs. 1892 scrub(@doc) + "Available providers are:\n\n" + parenttype.providers.sort_by(&:to_s).collect { |i| 1893 markdown_definitionlist( i, scrub(parenttype().provider(i).doc) ) 1894 }.join 1895 end
Provides iteration over added auto-requirements (see {autobefore}). @yieldparam type [String] the name of the type to autorequire an instance of @yieldparam block [Proc] a block producing one or several dependencies to auto require (see {autobefore}). @yieldreturn [void] @return [void]
# File lib/puppet/type.rb 2071 def self.eachautobefore 2072 @autobefores ||= {} 2073 @autobefores.each { |type,block| 2074 yield(type, block) 2075 } 2076 end
Provides iteration over added auto-requirements (see {autonotify}). @yieldparam type [String] the name of the type to autorequire an instance of @yieldparam block [Proc] a block producing one or several dependencies to auto require (see {autonotify}). @yieldreturn [void] @return [void]
# File lib/puppet/type.rb 2095 def self.eachautonotify 2096 @autonotifies ||= {} 2097 @autonotifies.each { |type,block| 2098 yield(type, block) 2099 } 2100 end
Provides iteration over added auto-requirements (see {autorequire}). @yieldparam type [String] the name of the type to autorequire an instance of @yieldparam block [Proc] a block producing one or several dependencies to auto require (see {autorequire}). @yieldreturn [void] @return [void]
# File lib/puppet/type.rb 2059 def self.eachautorequire 2060 @autorequires ||= {} 2061 @autorequires.each { |type, block| 2062 yield(type, block) 2063 } 2064 end
Provides iteration over added auto-requirements (see {autosubscribe}). @yieldparam type [String] the name of the type to autorequire an instance of @yieldparam block [Proc] a block producing one or several dependencies to auto require (see {autosubscribe}). @yieldreturn [void] @return [void]
# File lib/puppet/type.rb 2083 def self.eachautosubscribe 2084 @autosubscribes ||= {} 2085 @autosubscribes.each { |type,block| 2086 yield(type, block) 2087 } 2088 end
Provides iteration over meta-parameters. @yieldparam p [Puppet::Parameter] each meta parameter @return [void]
# File lib/puppet/type.rb 167 def self.eachmetaparam 168 @@metaparams.each { |p| yield p.name } 169 end
Creates a new `ensure` property with configured default values or with configuration by an optional block. This method is a convenience method for creating a property `ensure` with default accepted values. If no block is specified, the new `ensure` property will accept the default symbolic values `:present`, and `:absent` - see {Puppet::Property::Ensure}. If something else is wanted, pass a block and make calls to {Puppet::Property.newvalue} from this block to define each possible value. If a block is passed, the defaults are not automatically added to the set of valid values.
@note This method will be automatically called without a block if the type implements the methods
specified by {ensurable?}. It is recommended to always call this method and not rely on this automatic specification to clearly state that the type is ensurable.
@overload ensurable() @overload ensurable({|| … }) @yield [ ] A block evaluated in scope of the new Parameter
@yieldreturn [void] @return [void] @dsl type @api public
# File lib/puppet/type.rb 191 def self.ensurable(&block) 192 if block_given? 193 self.newproperty(:ensure, :parent => Puppet::Property::Ensure, &block) 194 else 195 self.newproperty(:ensure, :parent => Puppet::Property::Ensure) do 196 self.defaultvalues 197 end 198 end 199 end
Returns true if the type implements the default behavior expected by being ensurable “by default”. A type is ensurable by default if it responds to `:exists`, `:create`, and `:destroy`. If a type implements these methods and have not already specified that it is ensurable, it will be made so with the defaults specified in {ensurable}. @return [Boolean] whether the type is ensurable or not.
# File lib/puppet/type.rb 207 def self.ensurable? 208 # If the class has all three of these methods defined, then it's 209 # ensurable. 210 [:exists?, :create, :destroy].all? { |method| 211 self.public_method_defined?(method) 212 } 213 end
Processes the options for a named parameter. @param name [String] the name of a parameter @param options [Hash] a hash of options @option options [Boolean] :boolean if option set to true, an access method on the form name? is added for the param @return [void]
# File lib/puppet/type.rb 269 def self.handle_param_options(name, options) 270 # If it's a boolean parameter, create a method to test the value easily 271 if options[:boolean] 272 define_method(name.to_s + "?") do 273 val = self[name] 274 if val == :true or val == true 275 return true 276 end 277 end 278 end 279 end
Converts a simple hash into a Resource
instance. @todo as opposed to a complex hash? Other raised exceptions? @param [Hash{Symbol, String => Object}] hash resource attribute to value map to initialize the created resource from @return [Puppet::Resource] the resource created from the hash @raise [Puppet::Error] if a title is missing in the given hash
# File lib/puppet/type.rb 1226 def self.hash2resource(hash) 1227 hash = hash.inject({}) { |result, ary| result[ary[0].to_sym] = ary[1]; result } 1228 1229 title = hash.delete(:title) 1230 title ||= hash[:name] 1231 title ||= hash[key_attributes.first] if key_attributes.length == 1 1232 1233 raise Puppet::Error, "Title or name must be provided" unless title 1234 1235 # Now create our resource. 1236 resource = Puppet::Resource.new(self, title) 1237 resource.catalog = hash.delete(:catalog) 1238 1239 sensitive = hash.delete(:sensitive_parameters) 1240 if sensitive 1241 resource.sensitive_parameters = sensitive 1242 end 1243 1244 hash.each do |param, value| 1245 resource[param] = value 1246 end 1247 resource 1248 end
Initializes all of the variables that must be initialized for each subclass. @todo Does the explanation make sense? @return [void]
# File lib/puppet/type.rb 2232 def self.initvars 2233 # all of the instances of this class 2234 @objects = Hash.new 2235 @aliases = Hash.new 2236 2237 @defaults = {} 2238 2239 @parameters ||= [] 2240 2241 @validproperties = {} 2242 @properties = [] 2243 @parameters = [] 2244 @paramhash = {} 2245 2246 @paramdoc = Hash.new { |hash,key| 2247 key = key.intern if key.is_a?(String) 2248 if hash.include?(key) 2249 hash[key] 2250 else 2251 "Param Documentation for #{key} not found" 2252 end 2253 } 2254 2255 @doc ||= "" 2256 2257 end
Retrieves all known instances. @todo Retrieves them from where? Known to whom? Either requires providers or must be overridden. @raise [Puppet::DevError] when there are no providers and the implementation has not overridden this method.
# File lib/puppet/type.rb 1179 def self.instances 1180 raise Puppet::DevError, _("%{name} has no providers and has not overridden 'instances'") % { name: self.name } if provider_hash.empty? 1181 1182 # Put the default provider first, then the rest of the suitable providers. 1183 provider_instances = {} 1184 providers_by_source.collect do |provider| 1185 provider.instances.collect do |instance| 1186 # We always want to use the "first" provider instance we find, unless the resource 1187 # is already managed and has a different provider set 1188 title = instance.respond_to?(:title) ? instance.title : instance.name 1189 other = provider_instances[title] 1190 if other 1191 Puppet.debug { 1192 "%s %s found in both %s and %s; skipping the %s version" % [self.name.to_s.capitalize, title, other.class.name, instance.class.name, instance.class.name] 1193 } 1194 next 1195 end 1196 provider_instances[title] = instance 1197 1198 result = new(:name => instance.name, :provider => instance, :title => title) 1199 properties.each { |name| result.newattr(name) } 1200 result 1201 end 1202 end.flatten.compact 1203 end
Returns true if the type's notion of name is the identity of a resource. See the overview of this class for a longer explanation of the concept isomorphism. Defaults to true.
@return [Boolean] true, if this type's name is isomorphic with the object
# File lib/puppet/type.rb 915 def self.isomorphic? 916 if defined?(@isomorphic) 917 return @isomorphic 918 else 919 return true 920 end 921 end
Returns the list of parameters that comprise the composite key / “uniqueness key”. All parameters that return true from isnamevar? or is named `:name` are included in the returned result. @see uniqueness_key
@return [Array<Puppet::Parameter>] WARNING: this return type is uncertain
# File lib/puppet/type.rb 362 def self.key_attribute_parameters 363 @key_attribute_parameters ||= ( 364 @parameters.find_all { |param| 365 param.isnamevar? or param.name == :name 366 } 367 ) 368 end
Returns cached {key_attribute_parameters} names. Key attributes are properties and parameters that comprise a composite key or “uniqueness key”. @return [Array<String>] cached key_attribute names
# File lib/puppet/type.rb 375 def self.key_attributes 376 # This is a cache miss around 0.05 percent of the time. --daniel 2012-07-17 377 @key_attributes_cache ||= key_attribute_parameters.collect { |p| p.name } 378 end
Is the given parameter a meta-parameter? @return [Boolean] true if the given parameter is a meta-parameter.
# File lib/puppet/type.rb 284 def self.metaparam?(param) 285 @@metaparamhash.include?(param.intern) 286 end
Returns the meta-parameter class associated with the given meta-parameter name. Accepts a `nil` name, and return nil. @param name [String, nil] the name of a meta-parameter @return [Class,nil] the class for the given meta-parameter, or `nil` if no such meta-parameter exists, (or if
the given meta-parameter name is `nil`.
# File lib/puppet/type.rb 294 def self.metaparamclass(name) 295 return nil if name.nil? 296 @@metaparamhash[name.intern] 297 end
Returns the documentation for a given meta-parameter of this type. @param metaparam [Puppet::Parameter] the meta-parameter to get documentation for. @return [String] the documentation associated with the given meta-parameter, or nil of no such documentation
exists.
@raise if the given metaparam is not a meta-parameter in this type
# File lib/puppet/type.rb 312 def self.metaparamdoc(metaparam) 313 @@metaparamhash[metaparam].doc 314 end
Returns all meta-parameter names. @return [Array<String>] all meta-parameter names
# File lib/puppet/type.rb 302 def self.metaparams 303 @@metaparams.collect { |param| param.name } 304 end
Says if the ensure property should be retrieved if the resource is ensurable Defaults to true. Some resource type classes can override it
# File lib/puppet/type.rb 1067 def self.needs_ensure_retrieved 1068 true 1069 end
Creates an instance of Type
from a hash or a {Puppet::Resource}. @todo Unclear if this is a new Type
or a new instance of a given type (the initialization ends
with calling validate - which seems like validation of an instance of a given type, not a new meta type.
@todo Explain what the Hash and Resource
are. There seems to be two different types of
resources; one that causes the title to be set to resource.title, and one that causes the title to be resource.ref ("for components") - what is a component?
@overload initialize(hash)
@param [Hash] hash @raise [Puppet::ResourceError] when the type validation raises Puppet::Error or ArgumentError
@overload initialize(resource)
@param resource [Puppet:Resource] @raise [Puppet::ResourceError] when the type validation raises Puppet::Error or ArgumentError
# File lib/puppet/type.rb 2344 def initialize(resource) 2345 resource = self.class.hash2resource(resource) unless resource.is_a?(Puppet::Resource) 2346 2347 # The list of parameter/property instances. 2348 @parameters = {} 2349 2350 # Set the title first, so any failures print correctly. 2351 if resource.type.to_s.downcase.to_sym == self.class.name 2352 self.title = resource.title 2353 else 2354 # This should only ever happen for components 2355 self.title = resource.ref 2356 end 2357 2358 [:file, :line, :catalog, :exported, :virtual].each do |getter| 2359 setter = getter.to_s + "=" 2360 val = resource.send(getter) 2361 self.send(setter, val) if val 2362 end 2363 2364 merge_tags_from(resource) 2365 2366 @original_parameters = resource.to_hash 2367 2368 set_name(@original_parameters) 2369 2370 set_default(:provider) 2371 2372 set_parameters(@original_parameters) 2373 2374 begin 2375 self.validate if self.respond_to?(:validate) 2376 rescue Puppet::Error, ArgumentError => detail 2377 error = Puppet::ResourceError.new("Validation of #{ref} failed: #{detail}") 2378 adderrorcontext(error, detail) 2379 raise error 2380 end 2381 2382 set_sensitive_parameters(resource.sensitive_parameters) 2383 end
Creates a new meta-parameter. This creates a new meta-parameter that is added to this and all inheriting types. @param name [Symbol] the name of the parameter @param options [Hash] a hash with options. @option options [Class<inherits Puppet::Parameter>] :parent (Puppet::Parameter
) the super class of this parameter @option options [Hash{String => Object}] :attributes a hash that is applied to the generated class
by calling setter methods corresponding to this hash's keys/value pairs. This is done before the given block is evaluated.
@option options [Boolean] :boolean (false) specifies if this is a boolean parameter @option options [Boolean] :namevar (false) specifies if this parameter is the namevar @option options [Symbol, Array<Symbol>] :required_features specifies required provider features by name @return [Class<inherits Puppet::Parameter>] the created parameter @yield [ ] a required block that is evaluated in the scope of the new meta-parameter @api public @dsl type @todo Verify that this description is ok
# File lib/puppet/type.rb 333 def self.newmetaparam(name, options = {}, &block) 334 @@metaparams ||= [] 335 @@metaparamhash ||= {} 336 name = name.intern 337 338 param = genclass( 339 name, 340 :parent => options[:parent] || Puppet::Parameter, 341 :prefix => "MetaParam", 342 :hash => @@metaparamhash, 343 :array => @@metaparams, 344 :attributes => options[:attributes], 345 &block 346 ) 347 348 # Grr. 349 param.required_features = options[:required_features] if options[:required_features] 350 351 handle_param_options(name, options) 352 353 param.metaparam = true 354 355 param 356 end
Creates a new parameter. @param name [Symbol] the name of the parameter @param options [Hash] a hash with options. @option options [Class<inherits Puppet::Parameter>] :parent (Puppet::Parameter
) the super class of this parameter @option options [Hash{String => Object}] :attributes a hash that is applied to the generated class
by calling setter methods corresponding to this hash's keys/value pairs. This is done before the given block is evaluated.
@option options [Boolean] :boolean (false) specifies if this is a boolean parameter @option options [Boolean] :namevar (false) specifies if this parameter is the namevar @option options [Symbol, Array<Symbol>] :required_features specifies required provider features by name @return [Class<inherits Puppet::Parameter>] the created parameter @yield [ ] a required block that is evaluated in the scope of the new parameter @api public @dsl type
# File lib/puppet/type.rb 448 def self.newparam(name, options = {}, &block) 449 options[:attributes] ||= {} 450 451 param = genclass( 452 name, 453 :parent => options[:parent] || Puppet::Parameter, 454 :attributes => options[:attributes], 455 :block => block, 456 :prefix => "Parameter", 457 :array => @parameters, 458 :hash => @paramhash 459 ) 460 461 handle_param_options(name, options) 462 463 # Grr. 464 param.required_features = options[:required_features] if options[:required_features] 465 466 param.isnamevar if options[:namevar] 467 468 param 469 end
Creates a new property. @param name [Symbol] the name of the property @param options [Hash] a hash with options. @option options [Symbol] :array_matching (:first) specifies how the current state is matched against
the wanted state. Use `:first` if the property is single valued, and (`:all`) otherwise.
@option options [Class<inherits Puppet::Property>] :parent (Puppet::Property
) the super class of this property @option options [Hash{String => Object}] :attributes a hash that is applied to the generated class
by calling setter methods corresponding to this hash's keys/value pairs. This is done before the given block is evaluated.
@option options [Boolean] :boolean (false) specifies if this is a boolean parameter @option options [Symbol] :retrieve the method to call on the provider (or `parent` if `provider` is not set)
to retrieve the current value of this property.
@option options [Symbol, Array<Symbol>] :required_features specifies required provider features by name @return [Class<inherits Puppet::Property>] the created property @yield [ ] a required block that is evaluated in the scope of the new property @api public @dsl type
# File lib/puppet/type.rb 489 def self.newproperty(name, options = {}, &block) 490 name = name.intern 491 492 # This is here for types that might still have the old method of defining 493 # a parent class. 494 unless options.is_a? Hash 495 raise Puppet::DevError, _("Options must be a hash, not %{type}") % { type: options.inspect } 496 end 497 498 raise Puppet::DevError, _("Class %{class_name} already has a property named %{property}") % { class_name: self.name, property: name } if @validproperties.include?(name) 499 500 parent = options[:parent] 501 if parent 502 options.delete(:parent) 503 else 504 parent = Puppet::Property 505 end 506 507 # We have to create our own, new block here because we want to define 508 # an initial :retrieve method, if told to, and then eval the passed 509 # block if available. 510 prop = genclass(name, :parent => parent, :hash => @validproperties, :attributes => options) do 511 # If they've passed a retrieve method, then override the retrieve 512 # method on the class. 513 if options[:retrieve] 514 define_method(:retrieve) do 515 provider.send(options[:retrieve]) 516 end 517 end 518 519 class_eval(&block) if block 520 end 521 522 # If it's the 'ensure' property, always put it first. 523 if name == :ensure 524 @properties.unshift prop 525 else 526 @properties << prop 527 end 528 529 prop 530 end
@return [Puppet::Parameter] Returns the parameter class associated with the given parameter name.
# File lib/puppet/type.rb 543 def self.paramclass(name) 544 @paramhash[name] 545 end
# File lib/puppet/type.rb 532 def self.paramdoc(param) 533 @paramhash[param].doc 534 end
@return [Array<String>] Returns the parameter names
# File lib/puppet/type.rb 537 def self.parameters 538 return [] unless defined?(@parameters) 539 @parameters.collect { |klass| klass.name } 540 end
Returns any parameters that should be included by default in puppet resource's output @return [Array<Symbol>] the parameters to include
# File lib/puppet/type.rb 382 def self.parameters_to_include 383 [] 384 end
@return [Puppet::Property] Returns the property class ??? associated with the given property name
# File lib/puppet/type.rb 548 def self.propertybyname(name) 549 @validproperties[name] 550 end
Creates a new provider of a type. This method must be called directly on the type that it's implementing. @todo Fix Confusing Explanations!
Is this a new provider of a Type (metatype), or a provider of an instance of Type (a resource), or a Provider (the implementation of a Type's behavior). CONFUSED. It calls magically named methods like "providify" ...
@param name [String, Symbol] the name of the WHAT? provider? type? @param options [Hash{Symbol => Object}] a hash of options, used by this method, and passed on to {#genclass}, (see
it for additional options to pass).
@option options [Puppet::Provider] :parent the parent provider (what is this?) @option options [Puppet::Type] :resource_type the resource type, defaults to this type if unspecified @return [Puppet::Provider] a provider ??? @raise [Puppet::DevError] when the parent provider could not be found.
# File lib/puppet/type.rb 1818 def self.provide(name, options = {}, &block) 1819 name = name.intern 1820 1821 if unprovide(name) 1822 Puppet.debug { "Reloading #{name} #{self.name} provider" } 1823 end 1824 1825 pname = options[:parent] 1826 parent = if pname 1827 options.delete(:parent) 1828 if pname.is_a? Class 1829 pname 1830 else 1831 provider = self.provider(pname) 1832 if provider 1833 provider 1834 else 1835 raise Puppet::DevError, _("Could not find parent provider %{parent} of %{name}") % { parent: pname, name: name } 1836 end 1837 end 1838 else 1839 Puppet::Provider 1840 end 1841 1842 options[:resource_type] ||= self 1843 1844 self.providify 1845 1846 provider = genclass( 1847 name, 1848 :parent => parent, 1849 :hash => provider_hash, 1850 :prefix => "Provider", 1851 :block => block, 1852 :include => feature_module, 1853 :extend => feature_module, 1854 :attributes => options 1855 ) 1856 1857 provider 1858 end
Returns the provider having the given name. This will load a provider if it is not already loaded. The returned provider is the first found provider having the given name, where “first found” semantics is defined by the {providerloader} in use.
@param name [String] the name of the provider to get @return [Puppet::Provider, nil] the found provider, or nil if no provider of the given name was found
# File lib/puppet/type.rb 1775 def self.provider(name) 1776 name = name.intern 1777 1778 # If we don't have it yet, try loading it. 1779 @providerloader.load(name, Puppet.lookup(:current_environment)) unless provider_hash.has_key?(name) 1780 provider_hash[name] 1781 end
@return [Hash{ ??? => Puppet::Provider}] Returns a hash of WHAT EXACTLY for this type. @see provider_hash_by_type
method to get the same for some other type
# File lib/puppet/type.rb 1764 def self.provider_hash 1765 Puppet::Type.provider_hash_by_type(self.name) 1766 end
@return [Hash{??? => Puppet::Provider}] Returns a hash of WHAT EXACTLY for the given type @todo what goes into this hash?
# File lib/puppet/type.rb 1757 def self.provider_hash_by_type(type) 1758 @provider_hashes ||= {} 1759 @provider_hashes[type] ||= {} 1760 end
Returns a list of loaded providers by name. This method will not load/search for available providers. @return [Array<String>] list of loaded provider names
# File lib/puppet/type.rb 1787 def self.providers 1788 provider_hash.keys 1789 end
Returns a list of one suitable provider per source, with the default provider first. @todo Needs better explanation; what does “source” mean in this context? @return [Array<Puppet::Provider>] list of providers
# File lib/puppet/type.rb 1209 def self.providers_by_source 1210 # Put the default provider first (can be nil), then the rest of the suitable providers. 1211 sources = [] 1212 [defaultprovider, suitableprovider].flatten.uniq.collect do |provider| 1213 next if provider.nil? 1214 next if sources.include?(provider.source) 1215 1216 sources << provider.source 1217 provider 1218 end.compact 1219 end
Ensures there is a `:provider` parameter defined. Should only be called if there are providers. @return [void]
# File lib/puppet/type.rb 1863 def self.providify 1864 return if @paramhash.has_key? :provider 1865 1866 param = newparam(:provider) do 1867 # We're using a hacky way to get the name of our type, since there doesn't 1868 # seem to be a correct way to introspect this at the time this code is run. 1869 # We expect that the class in which this code is executed will be something 1870 # like Puppet::Type::Ssh_authorized_key::ParameterProvider. 1871 desc <<-EOT 1872 The specific backend to use for this `#{self.to_s.split('::')[2].downcase}` 1873 resource. You will seldom need to specify this --- Puppet will usually 1874 discover the appropriate provider for your platform. 1875 EOT 1876 1877 # This is so we can refer back to the type to get a list of 1878 # providers for documentation. 1879 class << self 1880 # The reference to a parent type for the parameter `:provider` used to get a list of 1881 # providers for documentation purposes. 1882 # 1883 attr_accessor :parenttype 1884 end 1885 1886 # Provides the ability to add documentation to a provider. 1887 # 1888 def self.doc 1889 # Since we're mixing @doc with text from other sources, we must normalize 1890 # its indentation with scrub. But we don't need to manually scrub the 1891 # provider's doc string, since markdown_definitionlist sanitizes its inputs. 1892 scrub(@doc) + "Available providers are:\n\n" + parenttype.providers.sort_by(&:to_s).collect { |i| 1893 markdown_definitionlist( i, scrub(parenttype().provider(i).doc) ) 1894 }.join 1895 end 1896 1897 # For each resource, the provider param defaults to 1898 # the type's default provider 1899 defaultto { 1900 prov = @resource.class.defaultprovider 1901 prov.name if prov 1902 } 1903 1904 validate do |provider_class| 1905 provider_class = provider_class[0] if provider_class.is_a? Array 1906 provider_class = provider_class.class.name if provider_class.is_a?(Puppet::Provider) 1907 1908 unless @resource.class.provider(provider_class) 1909 raise ArgumentError, _("Invalid %{resource} provider '%{provider_class}'") % { resource: @resource.class.name, provider_class: provider_class} 1910 end 1911 end 1912 1913 munge do |provider| 1914 provider = provider[0] if provider.is_a? Array 1915 provider = provider.intern if provider.is_a? String 1916 @resource.provider = provider 1917 1918 if provider.is_a?(Puppet::Provider) 1919 provider.class.name 1920 else 1921 provider 1922 end 1923 end 1924 end 1925 param.parenttype = self 1926 end
@todo document this, have no clue what this does… it returns “RelationshipMetaparam.subclasses”
# File lib/puppet/type.rb 1598 def self.relationship_params 1599 RelationshipMetaparam.subclasses 1600 end
Returns a list of suitable providers for the given type. A call to this method will load all providers if not already loaded and ask each if it is suitable - those that are are included in the result. @note This method also does some special processing which rejects a provider named `:fake` (for testing purposes). @return [Array<Puppet::Provider>] Returns an array of all suitable providers.
# File lib/puppet/type.rb 1945 def self.suitableprovider 1946 providerloader.loadall(Puppet.lookup(:current_environment)) if provider_hash.empty? 1947 provider_hash.find_all { |name, provider| 1948 provider.suitable? 1949 }.collect { |name, provider| 1950 provider 1951 }.reject { |p| p.name == :fake } # For testing 1952 end
Returns a mapping from the title string to setting of attribute values. This default implementation provides a mapping of title to the one and only namevar present in the type's definition. @note Advanced: some logic requires this mapping to be done differently, using a different
validation/pattern, breaking up the title into several parts assigning each to an individual attribute, or even use a composite identity where all namevars are seen as part of the unique identity (such computation is done by the {#uniqueness} method. These advanced options are rarely used (only one of the built in puppet types use this, and then only a small part of the available functionality), and the support for these advanced mappings is not implemented in a straight forward way. For these reasons, this method has been marked as private).
@raise [Puppet::DevError] if there is no title pattern and there are two or more key attributes @return [Array<Array<Regexp, Array<Array <Symbol, Proc>>>>, nil] a structure with a regexp and the first key_attribute ??? @comment This wonderful piece of logic creates a structure used by Resource.parse_title
which
has the capability to assign parts of the title to one or more attributes; It looks like an implementation of a composite identity key (all parts of the key_attributes array are in the key). This can also be seen in the method uniqueness_key. The implementation in this method simply assigns the title to the one and only namevar (which is name or a variable marked as namevar). If there are multiple namevars (any in addition to :name?) then this method MUST be implemented as it raises an exception if there is more than 1. Note that in puppet, it is only File that uses this to create a different pattern for assigning to the :path attribute This requires further digging. The entire construct is somewhat strange, since resource checks if the method "title_patterns" is implemented (it seems it always is) - why take this more expensive regexp mathching route for all other types?
@api private
# File lib/puppet/type.rb 414 def self.title_patterns 415 case key_attributes.length 416 when 0; [] 417 when 1; 418 [ [ /(.*)/m, [ [key_attributes.first] ] ] ] 419 else 420 raise Puppet::DevError, _("you must specify title patterns when there are two or more key attributes") 421 end 422 end
Returns the name of this type (if specified) or the parent type to_s
. The returned name is on the form “Puppet::Type::<name>”, where the first letter of name is capitalized. @return [String] the fully qualified name Puppet::Type::<name> where the first letter of name is capitalized
Object#to_s
# File lib/puppet/type.rb 2264 def self.to_s 2265 if defined?(@name) 2266 "Puppet::Type::#{@name.to_s.capitalize}" 2267 else 2268 super 2269 end 2270 end
@todo this needs a better explanation Removes the implementation class of a given provider. @return [Object] returns what {Puppet::Util::ClassGen#rmclass} returns
# File lib/puppet/type.rb 1931 def self.unprovide(name) 1932 if @defaultprovider and @defaultprovider.name == name 1933 @defaultprovider = nil 1934 end 1935 1936 rmclass(name, :hash => provider_hash, :prefix => "Provider") 1937 end
(see validattr?) @note see comment in code - how should this be documented? Are some of the other query methods deprecated?
(or should be).
@comment This is a forward-compatibility method - it's the validity interface we'll use in Puppet::Resource
.
# File lib/puppet/type.rb 593 def self.valid_parameter?(name) 594 validattr?(name) 595 end
Creates a `validate` method that is used to validate a resource before it is operated on. The validation should raise exceptions if the validation finds errors. (It is not recommended to issue warnings as this typically just ends up in a logfile - you should fail if a validation fails). The easiest way to raise an appropriate exception is to call the method {Puppet::Util::Errors.fail} with the message as an argument.
@yield [ ] a required block called with self set to the instance of a Type
class representing a resource. @return [void] @dsl type @api public
# File lib/puppet/type.rb 2283 def self.validate(&block) 2284 define_method(:validate, &block) 2285 end
Returns whether or not the given name is the name of a property, parameter or meta-parameter @return [Boolean] true if the given attribute name is the name of an existing property, parameter or meta-parameter
# File lib/puppet/type.rb 555 def self.validattr?(name) 556 name = name.intern 557 return true if name == :name 558 @validattrs ||= {} 559 560 unless @validattrs.include?(name) 561 @validattrs[name] = !!(self.validproperty?(name) or self.validparameter?(name) or self.metaparam?(name)) 562 end 563 564 @validattrs[name] 565 end
@return [Boolean] Returns true if the given name is the name of an existing parameter
# File lib/puppet/type.rb 584 def self.validparameter?(name) 585 raise Puppet::DevError, _("Class %{class_name} has not defined parameters") % { class_name: self } unless defined?(@parameters) 586 !!(@paramhash.include?(name) or @@metaparamhash.include?(name)) 587 end
@return [Array<Symbol>, {}] Returns a list of valid property names, or an empty hash if there are none. @todo An empty hash is returned if there are no defined parameters (not an empty array). This looks like
a bug.
# File lib/puppet/type.rb 577 def self.validproperties 578 return {} unless defined?(@parameters) 579 580 @validproperties.keys 581 end
@return [Boolean] Returns true if the given name is the name of an existing property
# File lib/puppet/type.rb 568 def self.validproperty?(name) 569 name = name.intern 570 @validproperties.include?(name) && @validproperties[name] 571 end
Returns true if the given name is a reference to a provider and if this is a suitable provider for this type. @todo How does the provider know if it is suitable for the type? Is it just suitable for the platform/
environment where this method is executing?
@param name [String] the name of the provider for which validity is checked @return [Boolean] true if the given name references a provider that is suitable
# File lib/puppet/type.rb 1798 def self.validprovider?(name) 1799 name = name.intern 1800 1801 (provider_hash.has_key?(name) && provider_hash[name].suitable?) 1802 end
Public Instance Methods
Compares this type against the given other (type) and returns -1, 0, or +1 depending on the order. @param other [Object] the object to compare against (produces nil, if not kind of Type} @return [-1, 0, +1, nil] produces -1 if this type is before the given other type, 0 if equals, and 1 if after.
Returns nil, if the given _other_ is not a kind of Type.
@see Comparable
# File lib/puppet/type.rb 98 def <=>(other) 99 # Order is only maintained against other types, not arbitrary objects. 100 # The natural order is based on the reference name used when comparing 101 return nil unless other.is_a?(Puppet::CompilableResourceType) || other.class.is_a?(Puppet::CompilableResourceType) 102 # against other type instances. 103 self.ref <=> other.ref 104 end
Gets the 'should' (wanted state) value of a parameter or property by name. To explicitly get the 'is' (current state) value use `o.is(:name)`, and to explicitly get the 'should' value use `o.should(:name)` @param name [String] the name of the attribute to obtain the 'should' value for. @return [Object] 'should'/wanted value of the given attribute
# File lib/puppet/type.rb 630 def [](name) 631 name = name.intern 632 fail("Invalid parameter #{name}(#{name.inspect})") unless self.class.validattr?(name) 633 634 if name == :name 635 nv = name_var 636 name = nv if nv 637 end 638 639 obj = @parameters[name] 640 if obj 641 # Note that if this is a property, then the value is the "should" value, 642 # not the current value. 643 obj.value 644 else 645 return nil 646 end 647 end
Sets the 'should' (wanted state) value of a property, or the value of a parameter. @return @raise [Puppet::Error] if the setting of the value fails, or if the given name is nil. @raise [Puppet::ResourceError] when the parameter validation raises Puppet::Error
or
ArgumentError
# File lib/puppet/type.rb 654 def []=(name,value) 655 name = name.intern 656 657 fail("no parameter named '#{name}'") unless self.class.validattr?(name) 658 659 if name == :name 660 nv = name_var 661 name = nv if nv 662 end 663 raise Puppet::Error.new("Got nil value for #{name}") if value.nil? 664 665 property = self.newattr(name) 666 667 if property 668 begin 669 # make sure the parameter doesn't have any errors 670 property.value = value 671 rescue Puppet::Error, ArgumentError => detail 672 error = Puppet::ResourceError.new(_("Parameter %{name} failed on %{ref}: %{detail}") % 673 { name: name, ref: ref, detail: detail }) 674 adderrorcontext(error, detail) 675 raise error 676 end 677 end 678 679 nil 680 end
Creates a new property value holder for the resource if it is valid and does not already exist @return [Boolean] true if a new parameter was added, false otherwise
# File lib/puppet/type.rb 604 def add_property_parameter(prop_name) 605 if self.class.validproperty?(prop_name) && !@parameters[prop_name] 606 self.newattr(prop_name) 607 return true 608 end 609 false 610 end
# File lib/puppet/type.rb 1355 def all_properties 1356 resource.class.properties.find_all do |property| 1357 resource.provider.nil? or resource.provider.class.supports_parameter?(property) 1358 end.collect do |property| 1359 property.name 1360 end 1361 end
Returns the ancestors - WHAT? This implementation always returns an empty list. @todo WHAT IS THIS ? @return [Array<???>] returns a list of ancestors.
# File lib/puppet/type.rb 994 def ancestors 995 [] 996 end
@return [Boolean] Returns whether the resource is applicable to `:device` Returns true if a resource of this type can be evaluated on a 'network device' kind of hosts. @api private
# File lib/puppet/type.rb 2637 def appliable_to_device? 2638 self.class.can_apply_to(:device) 2639 end
@return [Boolean] Returns whether the resource is applicable to `:host` Returns true if a resource of this type can be evaluated on a regular generalized computer (ie not an appliance like a network device) @api private
# File lib/puppet/type.rb 2644 def appliable_to_host? 2645 self.class.can_apply_to(:host) 2646 end
# File lib/puppet/type.rb 2152 def autobefore(rel_catalog = nil) 2153 autorelation(:before, rel_catalog) 2154 end
# File lib/puppet/type.rb 2160 def autonotify(rel_catalog = nil) 2161 autorelation(:notify, rel_catalog) 2162 end
Adds dependencies to the catalog from added autorelations. See {autorequire} for how to add an auto-requirement. @todo needs details - see the param rel_catalog, and type of this param @param rel_catalog [Puppet::Resource::Catalog, nil] the catalog to
add dependencies to. Defaults to the current catalog (set when the type instance was added to a catalog)
@raise [Puppet::DevError] if there is no catalog
# File lib/puppet/type.rb 2110 def autorelation(rel_type, rel_catalog = nil) 2111 rel_catalog ||= catalog 2112 raise Puppet::DevError, _("You cannot add relationships without a catalog") unless rel_catalog 2113 2114 reqs = [] 2115 2116 auto_rel = "eachauto#{rel_type}".to_sym 2117 2118 self.class.send(auto_rel) { |type, block| 2119 # Ignore any types we can't find, although that would be a bit odd. 2120 next unless Puppet::Type.type(type) 2121 2122 # Retrieve the list of names from the block. 2123 list = self.instance_eval(&block) 2124 next unless list 2125 list = [list] unless list.is_a?(Array) 2126 2127 # Collect the current prereqs 2128 list.each { |dep| 2129 next if dep.nil? 2130 2131 # Support them passing objects directly, to save some effort. 2132 unless dep.is_a?(Puppet::Type) 2133 # Skip autorelation that we aren't managing 2134 dep = rel_catalog.resource(type, dep) 2135 next unless dep 2136 end 2137 2138 if [:require, :subscribe].include?(rel_type) 2139 reqs << Puppet::Relationship.new(dep, self) 2140 else 2141 reqs << Puppet::Relationship.new(self, dep) 2142 end 2143 } 2144 } 2145 reqs 2146 end
# File lib/puppet/type.rb 2148 def autorequire(rel_catalog = nil) 2149 autorelation(:require, rel_catalog) 2150 end
# File lib/puppet/type.rb 2156 def autosubscribe(rel_catalog = nil) 2157 autorelation(:subscribe, rel_catalog) 2158 end
Builds the dependencies associated with this resource.
@return [Array<Puppet::Relationship>] list of relationships to other resources
# File lib/puppet/type.rb 2167 def builddepends 2168 # Handle the requires 2169 self.class.relationship_params.collect do |klass| 2170 param = @parameters[klass.name] 2171 param.to_edges if param 2172 end.flatten.reject { |r| r.nil? } 2173 end
Returns a hash of the current properties and their values. If a resource is absent, its value is the symbol `:absent` @return [Hash{Puppet::Property => Object}] mapping of property instance to its value
# File lib/puppet/type.rb 1135 def currentpropvalues 1136 # It's important to use the 'properties' method here, as it follows the order 1137 # in which they're defined in the class. It also guarantees that 'ensure' 1138 # is the first property, which is important for skipping 'retrieve' on 1139 # all the properties if the resource is absent. 1140 ensure_state = false 1141 return properties.inject({}) do | prophash, property| 1142 if property.name == :ensure 1143 ensure_state = property.retrieve 1144 prophash[property] = ensure_state 1145 else 1146 if ensure_state == :absent 1147 prophash[property] = :absent 1148 else 1149 prophash[property] = property.retrieve 1150 end 1151 end 1152 prophash 1153 end 1154 end
Removes an attribute from the object; useful in testing or in cleanup when an error has been encountered @todo Don't know what the attr is (name or Property/Parameter?). Guessing it is a String name… @todo Is it possible to delete a meta-parameter? @todo What does delete mean? Is it deleted from the type or is its value state 'is'/'should' deleted? @param attr [String] the attribute to delete from this object. WHAT IS THE TYPE? @raise [Puppet::DecError] when an attempt is made to delete an attribute that does not exists.
# File lib/puppet/type.rb 690 def delete(attr) 691 attr = attr.intern 692 if @parameters.has_key?(attr) 693 @parameters.delete(attr) 694 else 695 raise Puppet::DevError.new(_("Undefined attribute '%{attribute}' in %{name}") % { attribute: attr, name: self}) 696 end 697 end
@return [Boolean] Returns true if the wanted state of the resource is that it should be absent (i.e. to be deleted).
# File lib/puppet/type.rb 598 def deleting? 599 obj = @parameters[:ensure] and obj.should == :absent 600 end
Returns true if the search should be done in depth-first order. This implementation always returns false. @todo What is this used for?
@return [Boolean] true if the search should be done in depth first order.
# File lib/puppet/type.rb 963 def depthfirst? 964 false 965 end
Iterates over all parameters with value currently set. @yieldparam parameter [Puppet::Parameter] or a subclass thereof @return [void]
# File lib/puppet/type.rb 719 def eachparameter 720 parameters_with_value.each { |parameter| yield parameter } 721 end
Iterates over the properties that were set on this resource. @yieldparam property [Puppet::Property] each property @return [void]
# File lib/puppet/type.rb 702 def eachproperty 703 # properties is a private method 704 properties.each { |property| 705 yield property 706 } 707 end
Creates a transaction event. Called by Transaction
or by a property. Merges the given options with the options `:resource`, `:file`, `:line`, and `:tags`, initialized from values in this object. For possible options to pass (if any ????) see {Puppet::Transaction::Event}. @todo Needs a better explanation “Why should I care who is calling this method?”, What do I need to know
about events and how they work? Where can I read about them?
@param options [Hash] options merged with a fixed set of options defined by this method, passed on to {Puppet::Transaction::Event}. @return [Puppet::Transaction::Event] the created event
# File lib/puppet/type.rb 731 def event(options = {}) 732 Puppet::Transaction::Event.new(**{:resource => self, :file => file, :line => line, :tags => tags}.merge(options)) 733 end
@return [Boolean] Returns whether the resource is exported or not
# File lib/puppet/type.rb 2631 def exported?; !!@exported; end
Finishes any outstanding processing. This method should be called as a final step in setup, to allow the parameters that have associated auto-require needs to be processed.
@todo what is the expected sequence here - who is responsible for calling this? When?
Is the returned type correct?
@return [Array<Puppet::Parameter>] the validated list/set of attributes
# File lib/puppet/type.rb 2498 def finish 2499 # Call post_compile hook on every parameter that implements it. This includes all subclasses 2500 # of parameter including, but not limited to, regular parameters, metaparameters, relationship 2501 # parameters, and properties. 2502 eachparameter do |parameter| 2503 parameter.post_compile if parameter.respond_to? :post_compile 2504 end 2505 2506 # Make sure all of our relationships are valid. Again, must be done 2507 # when the entire catalog is instantiated. 2508 self.class.relationship_params.collect do |klass| 2509 param = @parameters[klass.name] 2510 param.validate_relationship if param 2511 end.flatten.reject { |r| r.nil? } 2512 end
Flushes the provider if supported by the provider, else no action. This is called by the transaction. @todo What does Flushing the provider mean? Why is it interesting to know that this is
called by the transaction? (It is not explained anywhere what a transaction is).
@return [???, nil] WHAT DOES IT RETURN? GUESS IS VOID
# File lib/puppet/type.rb 1020 def flush 1021 self.provider.flush if self.provider and self.provider.respond_to?(:flush) 1022 end
Returns true if all contained objects are in sync. @todo “contained in what?” in the given “in” parameter?
@todo deal with the comment _“FIXME I don't think this is used on the type instances any more,
it's really only used for testing"_
@return [Boolean] true if in sync, false otherwise.
# File lib/puppet/type.rb 1031 def insync?(is) 1032 insync = true 1033 1034 property = @parameters[:ensure] 1035 if property 1036 unless is.include? property 1037 #TRANSLATORS 'is' is a variable name and should not be translated 1038 raise Puppet::DevError, _("The 'is' value is not in the 'is' array for '%{name}'") % { name: property.name } 1039 end 1040 ensureis = is[property] 1041 if property.safe_insync?(ensureis) and property.should == :absent 1042 return true 1043 end 1044 end 1045 1046 properties.each { |prop| 1047 unless is.include? prop 1048 #TRANSLATORS 'is' is a variable name and should not be translated 1049 raise Puppet::DevError, _("The 'is' value is not in the 'is' array for '%{name}'") % { name: prop.name } 1050 end 1051 1052 propis = is[prop] 1053 unless prop.safe_insync?(propis) 1054 prop.debug("Not in sync: #{propis.inspect} vs #{prop.should.inspect}") 1055 insync = false 1056 #else 1057 # property.debug("In sync") 1058 end 1059 } 1060 1061 #self.debug("#{self} sync status is #{insync}") 1062 insync 1063 end
@todo check that this gets documentation (it is at the class level as well as instance). (see isomorphic?)
# File lib/puppet/type.rb 925 def isomorphic? 926 self.class.isomorphic? 927 end
Creates a log entry with the given message at the log level specified by the parameter `loglevel` @return [void]
# File lib/puppet/type.rb 2307 def log(msg) 2308 2309 Puppet::Util::Log.create( 2310 2311 :level => @parameters[:loglevel].value, 2312 :message => msg, 2313 2314 :source => self 2315 ) 2316 end
Returns true if the instance is a managed instance. A 'yes' here means that the instance was created from the language, vs. being created in order resolve other questions, such as finding a package in a list. @note An object that is managed always stays managed, but an object that is not managed
may become managed later in its lifecycle.
@return [Boolean] true if the object is managed
# File lib/puppet/type.rb 935 def managed? 936 # Once an object is managed, it always stays managed; but an object 937 # that is listed as unmanaged might become managed later in the process, 938 # so we have to check that every time 939 if @managed 940 return @managed 941 else 942 @managed = false 943 properties.each { |property| 944 s = property.should 945 if s and ! property.class.unmanaged 946 @managed = true 947 break 948 end 949 } 950 return @managed 951 end 952 end
@comment For now, leave the 'name' method functioning like it used to. Once 'title'
works everywhere, I'll switch it.
Returns the resource's name @todo There is a comment in source that this is not quite the same as ':title' and that a switch should
be made...
@return [String] the name of a resource
# File lib/puppet/type.rb 2520 def name 2521 self[:name] 2522 end
@return [Symbol, Boolean] Returns the name of the namevar if there is only one or false otherwise. @comment This is really convoluted and part of the support for multiple namevars (?).
If there is only one namevar, the produced value is naturally this namevar, but if there are several? The logic caches the name of the namevar if it is a single name, but otherwise always calls key_attributes, and then caches the first if there was only one, otherwise it returns false and caches this (which is then subsequently returned as a cache hit).
# File lib/puppet/type.rb 619 def name_var 620 return @name_var_cache unless @name_var_cache.nil? 621 key_attributes = self.class.key_attributes 622 @name_var_cache = (key_attributes.length == 1) && key_attributes.first 623 end
Registers an attribute to this resource type instance. Requires either the attribute name or class as its argument. This is a noop if the named property/parameter is not supported by this resource. Otherwise, an attribute instance is created and kept in this resource's parameters hash. @overload newattr(name)
@param name [Symbol] symbolic name of the attribute
@overload newattr(klass)
@param klass [Class] a class supported as an attribute class, i.e. a subclass of Parameter or Property
@return [Object] An instance of the named Parameter
or Property
class associated
to this resource type instance, or nil if the attribute is not supported
# File lib/puppet/type.rb 759 def newattr(name) 760 if name.is_a?(Class) 761 klass = name 762 name = klass.name 763 end 764 765 klass = self.class.attrclass(name) 766 unless klass 767 raise Puppet::Error, "Resource type #{self.class.name} does not support parameter #{name}" 768 end 769 770 if provider and ! provider.class.supports_parameter?(klass) 771 missing = klass.required_features.find_all { |f| ! provider.class.feature?(f) } 772 debug "Provider %s does not support features %s; not managing attribute %s" % [provider.class.name, missing.join(", "), name] 773 return nil 774 end 775 776 return @parameters[name] if @parameters.include?(name) 777 778 @parameters[name] = klass.new(:resource => self) 779 end
(see noop?
)
# File lib/puppet/type.rb 1171 def noop 1172 noop? 1173 end
Returns the `noop` run mode status of this. @return [Boolean] true if running in noop mode.
# File lib/puppet/type.rb 1158 def noop? 1159 # If we're not a host_config, we're almost certainly part of 1160 # Settings, and we want to ignore 'noop' 1161 return false if catalog and ! catalog.host_config? 1162 1163 if defined?(@noop) 1164 @noop 1165 else 1166 Puppet[:noop] 1167 end 1168 end
Returns the value of this object's parameter given by name @param name [String] the name of the parameter @return [Object] the value
# File lib/puppet/type.rb 791 def parameter(name) 792 @parameters[name.to_sym] 793 end
Returns a shallow copy of this object's hash of attributes by name. Note that his not only comprises parameters, but also properties and metaparameters. Changes to the contained parameters will have an effect on the parameters of this type, but changes to the returned hash does not. @return [Hash{String => Object}] a new hash being a shallow copy of the parameters map name to parameter
# File lib/puppet/type.rb 800 def parameters 801 @parameters.dup 802 end
Return the parameters, metaparams, and properties that have a value or were set by a default. Properties are included since they are a subclass of parameter. @return [Array<Puppet::Parameter>] Array of parameter objects ( or subclass thereof )
# File lib/puppet/type.rb 712 def parameters_with_value 713 self.class.allattrs.collect { |attr| parameter(attr) }.compact 714 end
Returns the parent of this in the catalog. In case of an erroneous catalog where multiple parents have been produced, the first found (non deterministic) parent is returned. @return [Puppet::Type, nil] the
containing resource or nil if there is no catalog or no containing resource.
# File lib/puppet/type.rb 2530 def parent 2531 return nil unless catalog 2532 return @parent if @parent 2533 parents = catalog.adjacent(self, :direction => :in) 2534 @parent = if parents 2535 parents.shift 2536 else 2537 nil 2538 end 2539 end
Returns a string representation of the resource's containment path in the catalog. @return [String]
# File lib/puppet/type.rb 784 def path 785 @path ||= '/' + pathbuilder.join('/') 786 end
Returns an array of strings representing the containment hierarchy (types/classes) that make up the path to the resource from the root of the catalog. This is mostly used for logging purposes.
@api private
# File lib/puppet/type.rb 1256 def pathbuilder 1257 p = parent 1258 if p 1259 [p.pathbuilder, self.ref].flatten 1260 else 1261 [self.ref] 1262 end 1263 end
Lifecycle method for a resource. This is called during graph creation. It should perform any consistency checking of the catalog and raise a Puppet::Error
if the transaction should be aborted.
It differs from the validate method, since it is called later during initialization and can rely on self.catalog to have references to all resources that comprise the catalog.
@see Puppet::Transaction#add_vertex @raise [Puppet::Error] If the pre-run check failed. @return [void] @abstract a resource type may implement this method to perform
validation checks that can query the complete catalog
# File lib/puppet/type.rb 1011 def pre_run_check 1012 end
Given the hash of current properties, should this resource be treated as if it currently exists on the system. May need to be overridden by types that offer up more than just :absent and :present.
# File lib/puppet/type.rb 1127 def present?(current_values) 1128 current_values[:ensure] != :absent 1129 end
@return [Array<Puppet::Property>] Returns all of the property objects, in the order specified in the
class.
@todo “what does the 'order specified in the class' mean? The order the properties where added in the
ruby file adding a new type with new properties?
# File lib/puppet/type.rb 906 def properties 907 self.class.properties.collect { |prop| @parameters[prop.name] }.compact 908 end
# File lib/puppet/type.rb 1363 def properties_to_audit(list) 1364 if !list.kind_of?(Array) && list.to_sym == :all 1365 all_properties 1366 else 1367 Array(list).collect { |p| p.to_sym } 1368 end 1369 end
Returns a {Puppet::Property} instance by name. To return the value, use 'resource' @todo LAK:NOTE(20081028) Since the 'parameter' method is now a superset of this method,
this one should probably go away at some point. - Does this mean it should be deprecated ?
@return [Puppet::Property] the property with the given name, or nil if not a property or does not exist.
# File lib/puppet/type.rb 816 def property(name) 817 obj = @parameters[name.intern] 818 if obj && obj.is_a?(Puppet::Property) 819 obj 820 else 821 nil 822 end 823 end
@return [Boolean] Returns whether the attribute given by name has been added
to this resource or not.
# File lib/puppet/type.rb 806 def propertydefined?(name) 807 name = name.intern unless name.is_a? Symbol 808 @parameters.include?(name) 809 end
Sets the provider to the given provider/name. @overload provider=(name)
Sets the provider to the result of resolving the name to an instance of Provider. @param name [String] the name of the provider
@overload provider=(provider)
Sets the provider to the given instances of Provider. @param provider [Puppet::Provider] the provider to set
@return [Puppet::Provider] the provider set @raise [ArgumentError] if the provider could not be found/resolved.
# File lib/puppet/type.rb 1985 def provider=(name) 1986 if name.is_a?(Puppet::Provider) 1987 @provider = name 1988 @provider.resource = self 1989 else 1990 klass = self.class.provider(name) 1991 if klass 1992 @provider = klass.new(self) 1993 else 1994 raise ArgumentError, _("Could not find %{name} provider of %{provider}") % { name: name, provider: self.class.name } 1995 end 1996 end 1997 end
Marks the object as “being purged”. This method is used by transactions to forbid deletion when there are dependencies. @todo what does this mean; “mark that we are purging” (purging what from where). How to use/when?
Is this internal API in transactions?
@see purging?
# File lib/puppet/type.rb 2563 def purging 2564 @purging = true 2565 end
Returns whether this resource is being purged or not. This method is used by transactions to forbid deletion when there are dependencies. @return [Boolean] the current “purging” state
# File lib/puppet/type.rb 2571 def purging? 2572 if defined?(@purging) 2573 @purging 2574 else 2575 false 2576 end 2577 end
Returns a reference to this as a string in “Type” format. @return [String] a reference to this object on the form 'Type'
# File lib/puppet/type.rb 2544 def ref 2545 # memoizing this is worthwhile ~ 3 percent of calls are the "first time 2546 # around" in an average run of Puppet. --daniel 2012-07-17 2547 @ref ||= "#{self.class.name.to_s.capitalize}[#{self.title}]" 2548 end
Removes this object (FROM WHERE?) @todo removes if from where? @return [void]
# File lib/puppet/type.rb 970 def remove() 971 # This is hackish (mmm, cut and paste), but it works for now, and it's 972 # better than warnings. 973 @parameters.each do |name, obj| 974 obj.remove 975 end 976 @parameters.clear 977 978 @parent = nil 979 980 # Remove the reference to the provider. 981 if self.provider 982 @provider.clear 983 @provider = nil 984 end 985 end
Retrieves the current value of all contained properties. Parameters and meta-parameters are not included in the result. @todo As opposed to all non contained properties? How is this different than any of the other
methods that also "gets" properties/parameters/etc. ?
@return [Puppet::Resource] array of all property values (mix of types) @raise [fail???] if there is a provider and it is not suitable for the host this is evaluated for.
# File lib/puppet/type.rb 1077 def retrieve 1078 fail "Provider #{provider.class.name} is not functional on this host" if self.provider.is_a?(Puppet::Provider) and ! provider.class.suitable? 1079 1080 result = Puppet::Resource.new(self.class, title) 1081 1082 # Provide the name, so we know we'll always refer to a real thing 1083 result[:name] = self[:name] unless self[:name] == title 1084 1085 ensure_prop = property(:ensure) 1086 if !ensure_prop && self.class.needs_ensure_retrieved && self.class.validattr?(:ensure) 1087 ensure_prop = newattr(:ensure) 1088 end 1089 1090 if ensure_prop 1091 result[:ensure] = ensure_state = ensure_prop.retrieve 1092 else 1093 ensure_state = nil 1094 end 1095 1096 properties.each do |property| 1097 next if property.name == :ensure 1098 if ensure_state == :absent 1099 result[property] = :absent 1100 else 1101 result[property] = property.retrieve 1102 end 1103 end 1104 1105 result 1106 end
Retrieve the current state of the system as a Puppet::Resource
. For the base Puppet::Type
this does the same thing as retrieve
, but specific types are free to implement retrieve
as returning a hash, and this will call retrieve
and convert the hash to a resource. This is used when determining when syncing a resource.
@return [Puppet::Resource] A resource representing the current state
of the system.
@api private
# File lib/puppet/type.rb 1118 def retrieve_resource 1119 resource = retrieve 1120 resource = Resource.new(self.class, title, :parameters => resource) if resource.is_a? Hash 1121 resource 1122 end
(see self_refresh
) @todo check that meaningful yardoc is produced - this method delegates to “self.class.self_refresh” @return [Boolean] - ??? returns true when … what?
# File lib/puppet/type.rb 2554 def self_refresh? 2555 self.class.self_refresh 2556 end
@todo comment says “For any parameters or properties that have defaults and have not yet been
set, set them now. This method can be handed a list of attributes, and if so it will only set defaults for those attributes."
@todo Needs a better explanation, and investigation about the claim an array can be passed (it is passed
to self.class.attrclass to produce a class on which a check is made if it has a method class :default (does not seem to support an array...
@return [void]
# File lib/puppet/type.rb 833 def set_default(attr) 834 klass = self.class.attrclass(attr) 835 return unless klass 836 # TODO this is not a necessary check, as we define a class level attr_reader 837 return unless klass.method_defined?(:default) 838 return if @parameters.include?(klass.name) 839 840 parameter = newattr(klass.name) 841 return unless parameter 842 843 value = parameter.default 844 if value and ! value.nil? 845 parameter.value = value 846 else 847 @parameters.delete(parameter.name) 848 end 849 end
@return [Object, nil] Returns the 'should' (wanted state) value for a specified property, or nil if the
given attribute name is not a property (i.e. if it is a parameter, meta-parameter, or does not exist).
# File lib/puppet/type.rb 737 def should(name) 738 prop = @parameters[name.intern] 739 if prop && prop.is_a?(Puppet::Property) 740 prop.should 741 else 742 nil 743 end 744 end
@return [Boolean] Returns true if this is something else than a `:provider`, or if it
is a provider and it is suitable, or if there is a default provider. Otherwise, false is returned.
# File lib/puppet/type.rb 1957 def suitable? 1958 # If we don't use providers, then we consider it suitable. 1959 return true unless self.class.paramclass(:provider) 1960 1961 # We have a provider and it is suitable. 1962 return true if provider && provider.class.suitable? 1963 1964 # We're using the default provider and there is one. 1965 if !provider and self.class.defaultprovider 1966 self.provider = self.class.defaultprovider.name 1967 return true 1968 end 1969 1970 # We specified an unsuitable provider, or there isn't any suitable 1971 # provider. 1972 false 1973 end
Returns the title of this object, or its name if title was not explicitly set. If the title is not already set, it will be computed by looking up the {#name_var} and using that value as the title. @todo it is somewhat confusing that if the name_var
is a valid parameter, it is assumed to
be the name_var called :name, but if it is a property, it uses the name_var. It is further confusing as Type in some respects supports multiple namevars.
@return [String] Returns the title of this object, or its name if title was not explicitly set. @raise [??? devfail] if title is not set, and name_var
can not be found.
# File lib/puppet/type.rb 2588 def title 2589 unless @title 2590 if self.class.validparameter?(name_var) 2591 @title = self[:name] 2592 elsif self.class.validproperty?(name_var) 2593 @title = self.should(name_var) 2594 else 2595 self.devfail "Could not find namevar #{name_var} for #{self.class.name}" 2596 end 2597 end 2598 2599 @title 2600 end
@todo the comment says: “Convert our object to a hash. This just includes properties.” @todo this is confused, again it is the @parameters instance variable that is consulted, and
each value is copied - does it contain "properties" and "parameters" or both? Does it contain meta-parameters?
@return [Hash{ ??? => ??? }] a hash of WHAT?. The hash is a shallow copy, any changes to the
objects returned in this hash will be reflected in the original resource having these attributes.
# File lib/puppet/type.rb 859 def to_hash 860 rethash = {} 861 862 @parameters.each do |name, obj| 863 rethash[name] = obj.value 864 end 865 866 rethash 867 end
Convert this resource type instance to a Puppet::Resource
. @return [Puppet::Resource] Returns a serializable representation of this resource
# File lib/puppet/type.rb 2612 def to_resource 2613 resource = self.retrieve_resource 2614 resource.merge_tags_from(self) 2615 2616 @parameters.each do |name, param| 2617 # Avoid adding each instance name twice 2618 next if param.class.isnamevar? and param.value == self.title 2619 2620 # We've already got property values 2621 next if param.is_a?(Puppet::Property) 2622 resource[name] = param.value 2623 end 2624 2625 resource 2626 end
Produces a reference to this in reference format. @see ref
# File lib/puppet/type.rb 2605 def to_s 2606 self.ref 2607 end
@return [String] the name of this object's class @todo Would that be “file” for the “File” resource type? of “File” or something else?
# File lib/puppet/type.rb 872 def type 873 self.class.name 874 end
Produces a resource's uniqueness_key (or composite key). This key is an array of all key attributes' values. Each distinct tuple must be unique for each resource type. @see key_attributes
@return [Object] an object that is a uniqueness_key for this object
# File lib/puppet/type.rb 429 def uniqueness_key 430 self.class.key_attributes.sort_by { |attribute_name| attribute_name.to_s }.map{ |attribute_name| self[attribute_name] } 431 end
@todo Comment says “Return a specific value for an attribute.”, as opposed to what “An unspecific value”??? @todo is this the 'is' or the 'should' value? @todo why is the return restricted to things that respond to :value? (Only non structural basic data types
supported?
@return [Object, nil] the value of the attribute having the given name, or nil if the given name is not
an attribute, or the referenced attribute does not respond to `:value`.
# File lib/puppet/type.rb 883 def value(name) 884 name = name.intern 885 886 obj = @parameters[name] 887 if obj && obj.respond_to?(:value) 888 obj.value 889 else 890 nil 891 end 892 end
@todo What is this used for? Needs a better explanation. @return [???] the version of the catalog or 0 if there is no catalog.
# File lib/puppet/type.rb 896 def version 897 return 0 unless catalog 898 catalog.version 899 end
@return [Boolean] Returns whether the resource is virtual or not
# File lib/puppet/type.rb 2629 def virtual?; !!@virtual; end
Protected Instance Methods
Mark parameters associated with this type as sensitive, based on the associated resource.
Currently, only instances of `Puppet::Property` can be easily marked for sensitive data handling and information redaction is limited to redacting events generated while synchronizing properties. While support for redaction will be broadened in the future we can't automatically deduce how to redact arbitrary parameters, so if a parameter is marked for redaction the best we can do is warn that we can't handle treating that parameter as sensitive and move on.
In some unusual cases a given parameter will be marked as sensitive but that sensitive context needs to be transferred to another parameter. In this case resource types may need to override this method in order to copy the sensitive context from one parameter to another (and in the process force the early generation of a parameter that might otherwise be lazily generated.) See `Puppet::Type.type(:file)set_sensitive_parameters
` for an example of this.
@note This method visibility is protected since it should only be called by initialize, but is
marked as public as subclasses may need to override this method.
@api public
@param sensitive_parameters [Array<Symbol>] A list of parameters to mark as sensitive.
@return [void]
# File lib/puppet/type.rb 2409 def set_sensitive_parameters(sensitive_parameters) 2410 sensitive_parameters.each do |name| 2411 p = parameter(name) 2412 if p.is_a?(Puppet::Property) 2413 p.sensitive = true 2414 elsif p.is_a?(Puppet::Parameter) 2415 warning(_("Unable to mark '%{name}' as sensitive: %{name} is a parameter and not a property, and cannot be automatically redacted.") % 2416 { name: name }) 2417 elsif self.class.attrclass(name) 2418 warning(_("Unable to mark '%{name}' as sensitive: the property itself was not assigned a value.") % { name: name }) 2419 else 2420 err(_("Unable to mark '%{name}' as sensitive: the property itself is not defined on %{type}.") % { name: name, type: type }) 2421 end 2422 end 2423 2424 parameters.each do |name, param| 2425 next if param.sensitive 2426 if param.is_a?(Puppet::Parameter) 2427 param.sensitive = param.is_sensitive if param.respond_to?(:is_sensitive) 2428 end 2429 end 2430 end
Private Instance Methods
Sets the name of the resource from a hash containing a mapping of `name_var` to value. Sets the value of the property/parameter appointed by the `name_var` (if it is defined). The value set is given by the corresponding entry in the given hash - e.g. if name_var
appoints the name `:path` the value of `:path` is set to the value at the key `:path` in the given hash. As a side effect this key/value is then removed from the given hash.
@note This method mutates the given hash by removing the entry with a key equal to the value
returned from name_var!
@param hash [Hash] a hash of what @return [void]
# File lib/puppet/type.rb 2444 def set_name(hash) 2445 self[name_var] = hash.delete(name_var) if name_var 2446 end
Sets parameters from the given hash. Values are set in _attribute order_ i.e. higher priority attributes before others, otherwise in the order they were specified (as opposed to just setting them in the order they happen to appear in when iterating over the given hash).
Attributes that are not included in the given hash are set to their default value.
@todo Is this description accurate? Is “ensure” an example of such a higher priority attribute? @return [void] @raise [Puppet::DevError] when impossible to set the value due to some problem @raise [ArgumentError, TypeError, Puppet::Error] when faulty arguments have been passed
# File lib/puppet/type.rb 2460 def set_parameters(hash) 2461 # Use the order provided by allattrs, but add in any 2462 # extra attributes from the resource so we get failures 2463 # on invalid attributes. 2464 no_values = [] 2465 (self.class.allattrs + hash.keys).uniq.each do |attr| 2466 begin 2467 # Set any defaults immediately. This is mostly done so 2468 # that the default provider is available for any other 2469 # property validation. 2470 if hash.has_key?(attr) 2471 self[attr] = hash[attr] 2472 else 2473 no_values << attr 2474 end 2475 rescue ArgumentError, Puppet::Error, TypeError 2476 raise 2477 rescue => detail 2478 error = Puppet::DevError.new(_("Could not set %{attribute} on %{class_name}: %{detail}") % { attribute: attr, class_name: self.class.name, detail: detail }) 2479 error.set_backtrace(detail.backtrace) 2480 raise error 2481 end 2482 end 2483 no_values.each do |attr| 2484 set_default(attr) 2485 end 2486 end