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 123 def self.allattrs 124 key_attributes | (parameters & [:provider]) | properties.collect { |property| property.name } | parameters | metaparams 125 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 251 def self.apply_to 252 @apply_to ||= :host 253 end
Makes this type applicable to `:both` (i.e. `:host` and `:device`). @return [Symbol] Returns `:both` @api private
# File lib/puppet/type.rb 244 def self.apply_to_all 245 @apply_to = :both 246 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 228 def self.apply_to_device 229 @apply_to = :device 230 end
Makes this type applicable to `:host`. @return [Symbol] Returns `:host` @api private
# File lib/puppet/type.rb 236 def self.apply_to_host 237 @apply_to = :host 238 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 131 def self.attrclass(name) 132 @attrclasses ||= {} 133 134 # We cache the value, since this method gets called such a huge number 135 # of times (as in, hundreds of thousands in a given run). 136 unless @attrclasses.include?(name) 137 @attrclasses[name] = case self.attrtype(name) 138 when :property; @validproperties[name] 139 when :meta; @@metaparamhash[name] 140 when :param; @paramhash[name] 141 end 142 end 143 @attrclasses[name] 144 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 151 def self.attrtype(attr) 152 @attrtypes ||= {} 153 unless @attrtypes.include?(attr) 154 @attrtypes[attr] = case 155 when @validproperties.include?(attr); :property 156 when @paramhash.include?(attr); :param 157 when @@metaparamhash.include?(attr); :meta 158 end 159 end 160 161 @attrtypes[attr] 162 end
# File lib/puppet/type.rb 2009 def self.autobefore(name, &block) 2010 @autobefores ||= {} 2011 @autobefores[name] = block 2012 end
# File lib/puppet/type.rb 2019 def self.autonotify(name, &block) 2020 @autonotifies ||= {} 2021 @autonotifies[name] = block 2022 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 2004 def self.autorequire(name, &block) 2005 @autorequires ||= {} 2006 @autorequires[name] = block 2007 end
# File lib/puppet/type.rb 2014 def self.autosubscribe(name, &block) 2015 @autosubscribes ||= {} 2016 @autosubscribes[name] = block 2017 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 260 def self.can_apply_to(target) 261 [ target == :device ? :device : :host, :both ].include?(apply_to) 262 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 1704 def self.defaultprovider 1705 return @defaultprovider if @defaultprovider 1706 1707 suitable = suitableprovider 1708 1709 # Find which providers are a default for this system. 1710 defaults = suitable.find_all { |provider| provider.default? } 1711 1712 # If we don't have any default we use suitable providers 1713 defaults = suitable if defaults.empty? 1714 max = defaults.collect { |provider| provider.specificity }.max 1715 defaults = defaults.find_all { |provider| provider.specificity == max } 1716 1717 if defaults.length > 1 1718 Puppet.warning(_("Found multiple default providers for %{name}: %{provider_list}; using %{selected_provider}") % 1719 { name: self.name, provider_list: defaults.collect { |i| i.name.to_s }.join(", "), selected_provider: defaults[0].name }) 1720 end 1721 1722 @defaultprovider = defaults.shift unless defaults.empty? 1723 end
Provides the ability to add documentation to a provider.
# File lib/puppet/type.rb 1858 def self.doc 1859 # Since we're mixing @doc with text from other sources, we must normalize 1860 # its indentation with scrub. But we don't need to manually scrub the 1861 # provider's doc string, since markdown_definitionlist sanitizes its inputs. 1862 scrub(@doc) + "Available providers are:\n\n" + parenttype.providers.sort_by(&:to_s).collect { |i| 1863 markdown_definitionlist( i, scrub(parenttype().provider(i).doc) ) 1864 }.join 1865 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 2041 def self.eachautobefore 2042 @autobefores ||= {} 2043 @autobefores.each { |type,block| 2044 yield(type, block) 2045 } 2046 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 2065 def self.eachautonotify 2066 @autonotifies ||= {} 2067 @autonotifies.each { |type,block| 2068 yield(type, block) 2069 } 2070 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 2029 def self.eachautorequire 2030 @autorequires ||= {} 2031 @autorequires.each { |type, block| 2032 yield(type, block) 2033 } 2034 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 2053 def self.eachautosubscribe 2054 @autosubscribes ||= {} 2055 @autosubscribes.each { |type,block| 2056 yield(type, block) 2057 } 2058 end
Provides iteration over meta-parameters. @yieldparam p [Puppet::Parameter] each meta parameter @return [void]
# File lib/puppet/type.rb 168 def self.eachmetaparam 169 @@metaparams.each { |p| yield p.name } 170 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 192 def self.ensurable(&block) 193 if block_given? 194 self.newproperty(:ensure, :parent => Puppet::Property::Ensure, &block) 195 else 196 self.newproperty(:ensure, :parent => Puppet::Property::Ensure) do 197 self.defaultvalues 198 end 199 end 200 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 208 def self.ensurable? 209 # If the class has all three of these methods defined, then it's 210 # ensurable. 211 [:exists?, :create, :destroy].all? { |method| 212 self.public_method_defined?(method) 213 } 214 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 270 def self.handle_param_options(name, options) 271 # If it's a boolean parameter, create a method to test the value easily 272 if options[:boolean] 273 define_method(name.to_s + "?") do 274 val = self[name] 275 if val == :true or val == true 276 return true 277 end 278 end 279 end 280 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 1196 def self.hash2resource(hash) 1197 hash = hash.inject({}) { |result, ary| result[ary[0].to_sym] = ary[1]; result } 1198 1199 title = hash.delete(:title) 1200 title ||= hash[:name] 1201 title ||= hash[key_attributes.first] if key_attributes.length == 1 1202 1203 raise Puppet::Error, "Title or name must be provided" unless title 1204 1205 # Now create our resource. 1206 resource = Puppet::Resource.new(self, title) 1207 resource.catalog = hash.delete(:catalog) 1208 1209 sensitive = hash.delete(:sensitive_parameters) 1210 if sensitive 1211 resource.sensitive_parameters = sensitive 1212 end 1213 1214 hash.each do |param, value| 1215 resource[param] = value 1216 end 1217 resource 1218 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 2202 def self.initvars 2203 # all of the instances of this class 2204 @objects = Hash.new 2205 @aliases = Hash.new 2206 2207 @defaults = {} 2208 2209 @parameters ||= [] 2210 2211 @validproperties = {} 2212 @properties = [] 2213 @parameters = [] 2214 @paramhash = {} 2215 2216 @paramdoc = Hash.new { |hash,key| 2217 key = key.intern if key.is_a?(String) 2218 if hash.include?(key) 2219 hash[key] 2220 else 2221 "Param Documentation for #{key} not found" 2222 end 2223 } 2224 2225 @doc ||= "" 2226 2227 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 1149 def self.instances 1150 raise Puppet::DevError, _("%{name} has no providers and has not overridden 'instances'") % { name: self.name } if provider_hash.empty? 1151 1152 # Put the default provider first, then the rest of the suitable providers. 1153 provider_instances = {} 1154 providers_by_source.collect do |provider| 1155 provider.instances.collect do |instance| 1156 # We always want to use the "first" provider instance we find, unless the resource 1157 # is already managed and has a different provider set 1158 title = instance.respond_to?(:title) ? instance.title : instance.name 1159 other = provider_instances[title] 1160 if other 1161 Puppet.debug { 1162 "%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] 1163 } 1164 next 1165 end 1166 provider_instances[title] = instance 1167 1168 result = new(:name => instance.name, :provider => instance, :title => title) 1169 properties.each { |name| result.newattr(name) } 1170 result 1171 end 1172 end.flatten.compact 1173 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 926 def self.isomorphic? 927 if defined?(@isomorphic) 928 return @isomorphic 929 else 930 return true 931 end 932 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 373 def self.key_attribute_parameters 374 @key_attribute_parameters ||= ( 375 @parameters.find_all { |param| 376 param.isnamevar? or param.name == :name 377 } 378 ) 379 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 386 def self.key_attributes 387 # This is a cache miss around 0.05 percent of the time. --daniel 2012-07-17 388 @key_attributes_cache ||= key_attribute_parameters.collect { |p| p.name } 389 end
Is the given parameter a meta-parameter? @return [Boolean] true if the given parameter is a meta-parameter.
# File lib/puppet/type.rb 285 def self.metaparam?(param) 286 @@metaparamhash.include?(param.intern) 287 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 295 def self.metaparamclass(name) 296 return nil if name.nil? 297 @@metaparamhash[name.intern] 298 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 313 def self.metaparamdoc(metaparam) 314 @@metaparamhash[metaparam].doc 315 end
Returns all meta-parameter names. @return [Array<String>] all meta-parameter names
# File lib/puppet/type.rb 303 def self.metaparams 304 @@metaparams.collect { |param| param.name } 305 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 1037 def self.needs_ensure_retrieved 1038 true 1039 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 2320 def initialize(resource) 2321 resource = self.class.hash2resource(resource) unless resource.is_a?(Puppet::Resource) 2322 2323 # The list of parameter/property instances. 2324 @parameters = {} 2325 2326 # Set the title first, so any failures print correctly. 2327 if resource.type.to_s.downcase.to_sym == self.class.name 2328 self.title = resource.title 2329 else 2330 # This should only ever happen for components 2331 self.title = resource.ref 2332 end 2333 2334 [:file, :line, :catalog, :exported, :virtual].each do |getter| 2335 setter = getter.to_s + "=" 2336 val = resource.send(getter) 2337 self.send(setter, val) if val 2338 end 2339 2340 merge_tags_from(resource) 2341 2342 @original_parameters = resource.to_hash 2343 2344 set_name(@original_parameters) 2345 2346 set_default(:provider) 2347 2348 set_parameters(@original_parameters) 2349 2350 validate_resource 2351 2352 set_sensitive_parameters(resource.sensitive_parameters) 2353 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 334 def self.newmetaparam(name, options = {}, &block) 335 @@metaparams ||= [] 336 @@metaparamhash ||= {} 337 name = name.intern 338 339 param = genclass( 340 name, 341 :parent => options[:parent] || Puppet::Parameter, 342 :prefix => "MetaParam", 343 :hash => @@metaparamhash, 344 :array => @@metaparams, 345 :attributes => options[:attributes], 346 &block 347 ) 348 349 # Grr. 350 param.required_features = options[:required_features] if options[:required_features] 351 352 handle_param_options(name, options) 353 354 param.metaparam = true 355 356 param 357 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 459 def self.newparam(name, options = {}, &block) 460 options[:attributes] ||= {} 461 462 param = genclass( 463 name, 464 :parent => options[:parent] || Puppet::Parameter, 465 :attributes => options[:attributes], 466 :block => block, 467 :prefix => "Parameter", 468 :array => @parameters, 469 :hash => @paramhash 470 ) 471 472 handle_param_options(name, options) 473 474 # Grr. 475 param.required_features = options[:required_features] if options[:required_features] 476 477 param.isnamevar if options[:namevar] 478 479 param 480 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 500 def self.newproperty(name, options = {}, &block) 501 name = name.intern 502 503 # This is here for types that might still have the old method of defining 504 # a parent class. 505 unless options.is_a? Hash 506 raise Puppet::DevError, _("Options must be a hash, not %{type}") % { type: options.inspect } 507 end 508 509 raise Puppet::DevError, _("Class %{class_name} already has a property named %{property}") % { class_name: self.name, property: name } if @validproperties.include?(name) 510 511 parent = options[:parent] 512 if parent 513 options.delete(:parent) 514 else 515 parent = Puppet::Property 516 end 517 518 # We have to create our own, new block here because we want to define 519 # an initial :retrieve method, if told to, and then eval the passed 520 # block if available. 521 prop = genclass(name, :parent => parent, :hash => @validproperties, :attributes => options) do 522 # If they've passed a retrieve method, then override the retrieve 523 # method on the class. 524 if options[:retrieve] 525 define_method(:retrieve) do 526 provider.send(options[:retrieve]) 527 end 528 end 529 530 class_eval(&block) if block 531 end 532 533 # If it's the 'ensure' property, always put it first. 534 if name == :ensure 535 @properties.unshift prop 536 else 537 @properties << prop 538 end 539 540 prop 541 end
@return [Puppet::Parameter] Returns the parameter class associated with the given parameter name.
# File lib/puppet/type.rb 554 def self.paramclass(name) 555 @paramhash[name] 556 end
# File lib/puppet/type.rb 543 def self.paramdoc(param) 544 @paramhash[param].doc 545 end
@return [Array<String>] Returns the parameter names
# File lib/puppet/type.rb 548 def self.parameters 549 return [] unless defined?(@parameters) 550 @parameters.collect { |klass| klass.name } 551 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 393 def self.parameters_to_include 394 [] 395 end
@return [Puppet::Property] Returns the property class ??? associated with the given property name
# File lib/puppet/type.rb 559 def self.propertybyname(name) 560 @validproperties[name] 561 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 1788 def self.provide(name, options = {}, &block) 1789 name = name.intern 1790 1791 if unprovide(name) 1792 Puppet.debug { "Reloading #{name} #{self.name} provider" } 1793 end 1794 1795 pname = options[:parent] 1796 parent = if pname 1797 options.delete(:parent) 1798 if pname.is_a? Class 1799 pname 1800 else 1801 provider = self.provider(pname) 1802 if provider 1803 provider 1804 else 1805 raise Puppet::DevError, _("Could not find parent provider %{parent} of %{name}") % { parent: pname, name: name } 1806 end 1807 end 1808 else 1809 Puppet::Provider 1810 end 1811 1812 options[:resource_type] ||= self 1813 1814 self.providify 1815 1816 provider = genclass( 1817 name, 1818 :parent => parent, 1819 :hash => provider_hash, 1820 :prefix => "Provider", 1821 :block => block, 1822 :include => feature_module, 1823 :extend => feature_module, 1824 :attributes => options 1825 ) 1826 1827 provider 1828 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 1745 def self.provider(name) 1746 name = name.intern 1747 1748 # If we don't have it yet, try loading it. 1749 @providerloader.load(name, Puppet.lookup(:current_environment)) unless provider_hash.has_key?(name) 1750 provider_hash[name] 1751 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 1734 def self.provider_hash 1735 Puppet::Type.provider_hash_by_type(self.name) 1736 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 1727 def self.provider_hash_by_type(type) 1728 @provider_hashes ||= {} 1729 @provider_hashes[type] ||= {} 1730 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 1757 def self.providers 1758 provider_hash.keys 1759 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 1179 def self.providers_by_source 1180 # Put the default provider first (can be nil), then the rest of the suitable providers. 1181 sources = [] 1182 [defaultprovider, suitableprovider].flatten.uniq.collect do |provider| 1183 next if provider.nil? 1184 next if sources.include?(provider.source) 1185 1186 sources << provider.source 1187 provider 1188 end.compact 1189 end
Ensures there is a `:provider` parameter defined. Should only be called if there are providers. @return [void]
# File lib/puppet/type.rb 1833 def self.providify 1834 return if @paramhash.has_key? :provider 1835 1836 param = newparam(:provider) do 1837 # We're using a hacky way to get the name of our type, since there doesn't 1838 # seem to be a correct way to introspect this at the time this code is run. 1839 # We expect that the class in which this code is executed will be something 1840 # like Puppet::Type::Ssh_authorized_key::ParameterProvider. 1841 desc <<-EOT 1842 The specific backend to use for this `#{self.to_s.split('::')[2].downcase}` 1843 resource. You will seldom need to specify this --- Puppet will usually 1844 discover the appropriate provider for your platform. 1845 EOT 1846 1847 # This is so we can refer back to the type to get a list of 1848 # providers for documentation. 1849 class << self 1850 # The reference to a parent type for the parameter `:provider` used to get a list of 1851 # providers for documentation purposes. 1852 # 1853 attr_accessor :parenttype 1854 end 1855 1856 # Provides the ability to add documentation to a provider. 1857 # 1858 def self.doc 1859 # Since we're mixing @doc with text from other sources, we must normalize 1860 # its indentation with scrub. But we don't need to manually scrub the 1861 # provider's doc string, since markdown_definitionlist sanitizes its inputs. 1862 scrub(@doc) + "Available providers are:\n\n" + parenttype.providers.sort_by(&:to_s).collect { |i| 1863 markdown_definitionlist( i, scrub(parenttype().provider(i).doc) ) 1864 }.join 1865 end 1866 1867 # For each resource, the provider param defaults to 1868 # the type's default provider 1869 defaultto { 1870 prov = @resource.class.defaultprovider 1871 prov.name if prov 1872 } 1873 1874 validate do |provider_class| 1875 provider_class = provider_class[0] if provider_class.is_a? Array 1876 provider_class = provider_class.class.name if provider_class.is_a?(Puppet::Provider) 1877 1878 unless @resource.class.provider(provider_class) 1879 raise ArgumentError, _("Invalid %{resource} provider '%{provider_class}'") % { resource: @resource.class.name, provider_class: provider_class} 1880 end 1881 end 1882 1883 munge do |provider| 1884 provider = provider[0] if provider.is_a? Array 1885 provider = provider.intern if provider.is_a? String 1886 @resource.provider = provider 1887 1888 if provider.is_a?(Puppet::Provider) 1889 provider.class.name 1890 else 1891 provider 1892 end 1893 end 1894 end 1895 param.parenttype = self 1896 end
@todo document this, have no clue what this does… it returns “RelationshipMetaparam.subclasses”
# File lib/puppet/type.rb 1568 def self.relationship_params 1569 RelationshipMetaparam.subclasses 1570 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 1915 def self.suitableprovider 1916 providerloader.loadall(Puppet.lookup(:current_environment)) if provider_hash.empty? 1917 provider_hash.find_all { |name, provider| 1918 provider.suitable? 1919 }.collect { |name, provider| 1920 provider 1921 }.reject { |p| p.name == :fake } # For testing 1922 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 425 def self.title_patterns 426 case key_attributes.length 427 when 0; [] 428 when 1; 429 [ [ /(.*)/m, [ [key_attributes.first] ] ] ] 430 else 431 raise Puppet::DevError, _("you must specify title patterns when there are two or more key attributes") 432 end 433 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 2234 def self.to_s 2235 if defined?(@name) 2236 "Puppet::Type::#{@name.to_s.capitalize}" 2237 else 2238 super 2239 end 2240 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 1901 def self.unprovide(name) 1902 if @defaultprovider and @defaultprovider.name == name 1903 @defaultprovider = nil 1904 end 1905 1906 rmclass(name, :hash => provider_hash, :prefix => "Provider") 1907 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 604 def self.valid_parameter?(name) 605 validattr?(name) 606 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 2253 def self.validate(&block) 2254 define_method(:unsafe_validate, &block) 2255 2256 define_method(:validate) do 2257 return if enum_for(:eachparameter).any? { |p| p.value.instance_of?(Puppet::Pops::Evaluator::DeferredValue) } 2258 2259 unsafe_validate 2260 end 2261 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 566 def self.validattr?(name) 567 name = name.intern 568 return true if name == :name 569 @validattrs ||= {} 570 571 unless @validattrs.include?(name) 572 @validattrs[name] = !!(self.validproperty?(name) or self.validparameter?(name) or self.metaparam?(name)) 573 end 574 575 @validattrs[name] 576 end
@return [Boolean] Returns true if the given name is the name of an existing parameter
# File lib/puppet/type.rb 595 def self.validparameter?(name) 596 raise Puppet::DevError, _("Class %{class_name} has not defined parameters") % { class_name: self } unless defined?(@parameters) 597 !!(@paramhash.include?(name) or @@metaparamhash.include?(name)) 598 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 588 def self.validproperties 589 return {} unless defined?(@parameters) 590 591 @validproperties.keys 592 end
@return [Boolean] Returns true if the given name is the name of an existing property
# File lib/puppet/type.rb 579 def self.validproperty?(name) 580 name = name.intern 581 @validproperties.include?(name) && @validproperties[name] 582 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 1768 def self.validprovider?(name) 1769 name = name.intern 1770 1771 (provider_hash.has_key?(name) && provider_hash[name].suitable?) 1772 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 99 def <=>(other) 100 # Order is only maintained against other types, not arbitrary objects. 101 # The natural order is based on the reference name used when comparing 102 return nil unless other.is_a?(Puppet::CompilableResourceType) || other.class.is_a?(Puppet::CompilableResourceType) 103 # against other type instances. 104 self.ref <=> other.ref 105 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 641 def [](name) 642 name = name.intern 643 fail("Invalid parameter #{name}(#{name.inspect})") unless self.class.validattr?(name) 644 645 if name == :name 646 nv = name_var 647 name = nv if nv 648 end 649 650 obj = @parameters[name] 651 if obj 652 # Note that if this is a property, then the value is the "should" value, 653 # not the current value. 654 obj.value 655 else 656 return nil 657 end 658 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 665 def []=(name,value) 666 name = name.intern 667 668 fail("no parameter named '#{name}'") unless self.class.validattr?(name) 669 670 if name == :name 671 nv = name_var 672 name = nv if nv 673 end 674 raise Puppet::Error.new("Got nil value for #{name}") if value.nil? 675 676 property = self.newattr(name) 677 678 if property 679 begin 680 # make sure the parameter doesn't have any errors 681 property.value = value 682 rescue Puppet::Error, ArgumentError => detail 683 error = Puppet::ResourceError.new(_("Parameter %{name} failed on %{ref}: %{detail}") % 684 { name: name, ref: ref, detail: detail }) 685 adderrorcontext(error, detail) 686 raise error 687 end 688 end 689 690 nil 691 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 615 def add_property_parameter(prop_name) 616 if self.class.validproperty?(prop_name) && !@parameters[prop_name] 617 self.newattr(prop_name) 618 return true 619 end 620 false 621 end
# File lib/puppet/type.rb 1325 def all_properties 1326 resource.class.properties.find_all do |property| 1327 resource.provider.nil? or resource.provider.class.supports_parameter?(property) 1328 end.collect do |property| 1329 property.name 1330 end 1331 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 1005 def ancestors 1006 [] 1007 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 2624 def appliable_to_device? 2625 self.class.can_apply_to(:device) 2626 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 2631 def appliable_to_host? 2632 self.class.can_apply_to(:host) 2633 end
# File lib/puppet/type.rb 2122 def autobefore(rel_catalog = nil) 2123 autorelation(:before, rel_catalog) 2124 end
# File lib/puppet/type.rb 2130 def autonotify(rel_catalog = nil) 2131 autorelation(:notify, rel_catalog) 2132 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 2080 def autorelation(rel_type, rel_catalog = nil) 2081 rel_catalog ||= catalog 2082 raise Puppet::DevError, _("You cannot add relationships without a catalog") unless rel_catalog 2083 2084 reqs = [] 2085 2086 auto_rel = "eachauto#{rel_type}".to_sym 2087 2088 self.class.send(auto_rel) { |type, block| 2089 # Ignore any types we can't find, although that would be a bit odd. 2090 next unless Puppet::Type.type(type) 2091 2092 # Retrieve the list of names from the block. 2093 list = self.instance_eval(&block) 2094 next unless list 2095 list = [list] unless list.is_a?(Array) 2096 2097 # Collect the current prereqs 2098 list.each { |dep| 2099 next if dep.nil? 2100 2101 # Support them passing objects directly, to save some effort. 2102 unless dep.is_a?(Puppet::Type) 2103 # Skip autorelation that we aren't managing 2104 dep = rel_catalog.resource(type, dep) 2105 next unless dep 2106 end 2107 2108 if [:require, :subscribe].include?(rel_type) 2109 reqs << Puppet::Relationship.new(dep, self) 2110 else 2111 reqs << Puppet::Relationship.new(self, dep) 2112 end 2113 } 2114 } 2115 reqs 2116 end
# File lib/puppet/type.rb 2118 def autorequire(rel_catalog = nil) 2119 autorelation(:require, rel_catalog) 2120 end
# File lib/puppet/type.rb 2126 def autosubscribe(rel_catalog = nil) 2127 autorelation(:subscribe, rel_catalog) 2128 end
Builds the dependencies associated with this resource.
@return [Array<Puppet::Relationship>] list of relationships to other resources
# File lib/puppet/type.rb 2137 def builddepends 2138 # Handle the requires 2139 self.class.relationship_params.collect do |klass| 2140 param = @parameters[klass.name] 2141 param.to_edges if param 2142 end.flatten.reject { |r| r.nil? } 2143 end
Copies all of a resource's metaparameters (except `alias`) to a generated child resource @param parameters [Hash] of a resource's parameters @return [Void]
# File lib/puppet/type.rb 362 def copy_metaparams(parameters) 363 parameters.each do |name, param| 364 self[name] = param.value if param.metaparam? && name != :alias 365 end 366 nil 367 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 1105 def currentpropvalues 1106 # It's important to use the 'properties' method here, as it follows the order 1107 # in which they're defined in the class. It also guarantees that 'ensure' 1108 # is the first property, which is important for skipping 'retrieve' on 1109 # all the properties if the resource is absent. 1110 ensure_state = false 1111 return properties.inject({}) do | prophash, property| 1112 if property.name == :ensure 1113 ensure_state = property.retrieve 1114 prophash[property] = ensure_state 1115 else 1116 if ensure_state == :absent 1117 prophash[property] = :absent 1118 else 1119 prophash[property] = property.retrieve 1120 end 1121 end 1122 prophash 1123 end 1124 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 701 def delete(attr) 702 attr = attr.intern 703 if @parameters.has_key?(attr) 704 @parameters.delete(attr) 705 else 706 raise Puppet::DevError.new(_("Undefined attribute '%{attribute}' in %{name}") % { attribute: attr, name: self}) 707 end 708 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 609 def deleting? 610 obj = @parameters[:ensure] and obj.should == :absent 611 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 974 def depthfirst? 975 false 976 end
Iterates over all parameters with value currently set. @yieldparam parameter [Puppet::Parameter] or a subclass thereof @return [void]
# File lib/puppet/type.rb 730 def eachparameter 731 parameters_with_value.each { |parameter| yield parameter } 732 end
Iterates over the properties that were set on this resource. @yieldparam property [Puppet::Property] each property @return [void]
# File lib/puppet/type.rb 713 def eachproperty 714 # properties is a private method 715 properties.each { |property| 716 yield property 717 } 718 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 742 def event(options = {}) 743 Puppet::Transaction::Event.new(**{:resource => self, :file => file, :line => line, :tags => tags}.merge(options)) 744 end
@return [Boolean] Returns whether the resource is exported or not
# File lib/puppet/type.rb 2618 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 2485 def finish 2486 # Call post_compile hook on every parameter that implements it. This includes all subclasses 2487 # of parameter including, but not limited to, regular parameters, metaparameters, relationship 2488 # parameters, and properties. 2489 eachparameter do |parameter| 2490 parameter.post_compile if parameter.respond_to? :post_compile 2491 end 2492 2493 # Make sure all of our relationships are valid. Again, must be done 2494 # when the entire catalog is instantiated. 2495 self.class.relationship_params.collect do |klass| 2496 param = @parameters[klass.name] 2497 param.validate_relationship if param 2498 end.flatten.reject { |r| r.nil? } 2499 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 1031 def flush 1032 self.provider.flush if self.provider and self.provider.respond_to?(:flush) 1033 end
@todo check that this gets documentation (it is at the class level as well as instance). (see isomorphic?)
# File lib/puppet/type.rb 936 def isomorphic? 937 self.class.isomorphic? 938 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 2283 def log(msg) 2284 2285 Puppet::Util::Log.create( 2286 2287 :level => @parameters[:loglevel].value, 2288 :message => msg, 2289 2290 :source => self 2291 ) 2292 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 946 def managed? 947 # Once an object is managed, it always stays managed; but an object 948 # that is listed as unmanaged might become managed later in the process, 949 # so we have to check that every time 950 if @managed 951 return @managed 952 else 953 @managed = false 954 properties.each { |property| 955 s = property.should 956 if s and ! property.class.unmanaged 957 @managed = true 958 break 959 end 960 } 961 return @managed 962 end 963 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 2507 def name 2508 self[:name] 2509 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 630 def name_var 631 return @name_var_cache unless @name_var_cache.nil? 632 key_attributes = self.class.key_attributes 633 @name_var_cache = (key_attributes.length == 1) && key_attributes.first 634 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 770 def newattr(name) 771 if name.is_a?(Class) 772 klass = name 773 name = klass.name 774 end 775 776 klass = self.class.attrclass(name) 777 unless klass 778 raise Puppet::Error, "Resource type #{self.class.name} does not support parameter #{name}" 779 end 780 781 if provider and ! provider.class.supports_parameter?(klass) 782 missing = klass.required_features.find_all { |f| ! provider.class.feature?(f) } 783 debug "Provider %s does not support features %s; not managing attribute %s" % [provider.class.name, missing.join(", "), name] 784 return nil 785 end 786 787 return @parameters[name] if @parameters.include?(name) 788 789 @parameters[name] = klass.new(:resource => self) 790 end
(see noop?)
# File lib/puppet/type.rb 1141 def noop 1142 noop? 1143 end
Returns the `noop` run mode status of this. @return [Boolean] true if running in noop mode.
# File lib/puppet/type.rb 1128 def noop? 1129 # If we're not a host_config, we're almost certainly part of 1130 # Settings, and we want to ignore 'noop' 1131 return false if catalog and ! catalog.host_config? 1132 1133 if defined?(@noop) 1134 @noop 1135 else 1136 Puppet[:noop] 1137 end 1138 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 802 def parameter(name) 803 @parameters[name.to_sym] 804 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 811 def parameters 812 @parameters.dup 813 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 723 def parameters_with_value 724 self.class.allattrs.collect { |attr| parameter(attr) }.compact 725 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 2517 def parent 2518 return nil unless catalog 2519 return @parent if @parent 2520 parents = catalog.adjacent(self, :direction => :in) 2521 @parent = if parents 2522 parents.shift 2523 else 2524 nil 2525 end 2526 end
Returns a string representation of the resource's containment path in the catalog. @return [String]
# File lib/puppet/type.rb 795 def path 796 @path ||= '/' + pathbuilder.join('/') 797 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 1226 def pathbuilder 1227 p = parent 1228 if p 1229 [p.pathbuilder, self.ref].flatten 1230 else 1231 [self.ref] 1232 end 1233 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 1022 def pre_run_check 1023 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 1097 def present?(current_values) 1098 current_values[:ensure] != :absent 1099 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 917 def properties 918 self.class.properties.collect { |prop| @parameters[prop.name] }.compact 919 end
# File lib/puppet/type.rb 1333 def properties_to_audit(list) 1334 if !list.kind_of?(Array) && list.to_sym == :all 1335 all_properties 1336 else 1337 Array(list).collect { |p| p.to_sym } 1338 end 1339 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 827 def property(name) 828 obj = @parameters[name.intern] 829 if obj && obj.is_a?(Puppet::Property) 830 obj 831 else 832 nil 833 end 834 end
@return [Boolean] Returns whether the attribute given by name has been added
to this resource or not.
# File lib/puppet/type.rb 817 def propertydefined?(name) 818 name = name.intern unless name.is_a? Symbol 819 @parameters.include?(name) 820 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 1955 def provider=(name) 1956 if name.is_a?(Puppet::Provider) 1957 @provider = name 1958 @provider.resource = self 1959 else 1960 klass = self.class.provider(name) 1961 if klass 1962 @provider = klass.new(self) 1963 else 1964 raise ArgumentError, _("Could not find %{name} provider of %{provider}") % { name: name, provider: self.class.name } 1965 end 1966 end 1967 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 2550 def purging 2551 @purging = true 2552 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 2558 def purging? 2559 if defined?(@purging) 2560 @purging 2561 else 2562 false 2563 end 2564 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 2531 def ref 2532 # memoizing this is worthwhile ~ 3 percent of calls are the "first time 2533 # around" in an average run of Puppet. --daniel 2012-07-17 2534 @ref ||= "#{self.class.name.to_s.capitalize}[#{self.title}]" 2535 end
Removes this object (FROM WHERE?) @todo removes if from where? @return [void]
# File lib/puppet/type.rb 981 def remove() 982 # This is hackish (mmm, cut and paste), but it works for now, and it's 983 # better than warnings. 984 @parameters.each do |name, obj| 985 obj.remove 986 end 987 @parameters.clear 988 989 @parent = nil 990 991 # Remove the reference to the provider. 992 if self.provider 993 @provider.clear 994 @provider = nil 995 end 996 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 1047 def retrieve 1048 fail "Provider #{provider.class.name} is not functional on this host" if self.provider.is_a?(Puppet::Provider) and ! provider.class.suitable? 1049 1050 result = Puppet::Resource.new(self.class, title) 1051 1052 # Provide the name, so we know we'll always refer to a real thing 1053 result[:name] = self[:name] unless self[:name] == title 1054 1055 ensure_prop = property(:ensure) 1056 if !ensure_prop && self.class.needs_ensure_retrieved && self.class.validattr?(:ensure) 1057 ensure_prop = newattr(:ensure) 1058 end 1059 1060 if ensure_prop 1061 result[:ensure] = ensure_state = ensure_prop.retrieve 1062 else 1063 ensure_state = nil 1064 end 1065 1066 properties.each do |property| 1067 next if property.name == :ensure 1068 if ensure_state == :absent 1069 result[property] = :absent 1070 else 1071 result[property] = property.retrieve 1072 end 1073 end 1074 1075 result 1076 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 1088 def retrieve_resource 1089 resource = retrieve 1090 resource = Resource.new(self.class, title, :parameters => resource) if resource.is_a? Hash 1091 resource 1092 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 2541 def self_refresh? 2542 self.class.self_refresh 2543 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 844 def set_default(attr) 845 klass = self.class.attrclass(attr) 846 return unless klass 847 # TODO this is not a necessary check, as we define a class level attr_reader 848 return unless klass.method_defined?(:default) 849 return if @parameters.include?(klass.name) 850 851 parameter = newattr(klass.name) 852 return unless parameter 853 854 value = parameter.default 855 if value and ! value.nil? 856 parameter.value = value 857 else 858 @parameters.delete(parameter.name) 859 end 860 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 748 def should(name) 749 prop = @parameters[name.intern] 750 if prop && prop.is_a?(Puppet::Property) 751 prop.should 752 else 753 nil 754 end 755 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 1927 def suitable? 1928 # If we don't use providers, then we consider it suitable. 1929 return true unless self.class.paramclass(:provider) 1930 1931 # We have a provider and it is suitable. 1932 return true if provider && provider.class.suitable? 1933 1934 # We're using the default provider and there is one. 1935 if !provider and self.class.defaultprovider 1936 self.provider = self.class.defaultprovider.name 1937 return true 1938 end 1939 1940 # We specified an unsuitable provider, or there isn't any suitable 1941 # provider. 1942 false 1943 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 2575 def title 2576 unless @title 2577 if self.class.validparameter?(name_var) 2578 @title = self[:name] 2579 elsif self.class.validproperty?(name_var) 2580 @title = self.should(name_var) 2581 else 2582 self.devfail "Could not find namevar #{name_var} for #{self.class.name}" 2583 end 2584 end 2585 2586 @title 2587 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 870 def to_hash 871 rethash = {} 872 873 @parameters.each do |name, obj| 874 rethash[name] = obj.value 875 end 876 877 rethash 878 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 2599 def to_resource 2600 resource = self.retrieve_resource 2601 resource.merge_tags_from(self) 2602 2603 @parameters.each do |name, param| 2604 # Avoid adding each instance name twice 2605 next if param.class.isnamevar? and param.value == self.title 2606 2607 # We've already got property values 2608 next if param.is_a?(Puppet::Property) 2609 resource[name] = param.value 2610 end 2611 2612 resource 2613 end
Produces a reference to this in reference format. @see ref
# File lib/puppet/type.rb 2592 def to_s 2593 self.ref 2594 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 883 def type 884 self.class.name 885 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 440 def uniqueness_key 441 self.class.key_attributes.sort_by { |attribute_name| attribute_name.to_s }.map{ |attribute_name| self[attribute_name] } 442 end
Optionally validate the resource. This method is a noop if the type has not defined a `validate` method using the puppet DSL. If validation fails, then an exception will be raised with this resources as the context.
@api public
@return [void]
# File lib/puppet/type.rb 2362 def validate_resource 2363 begin 2364 self.validate if self.respond_to?(:validate) 2365 rescue Puppet::Error, ArgumentError => detail 2366 error = Puppet::ResourceError.new("Validation of #{ref} failed: #{detail}") 2367 adderrorcontext(error, detail) 2368 raise error 2369 end 2370 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 894 def value(name) 895 name = name.intern 896 897 obj = @parameters[name] 898 if obj && obj.respond_to?(:value) 899 obj.value 900 else 901 nil 902 end 903 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 907 def version 908 return 0 unless catalog 909 catalog.version 910 end
@return [Boolean] Returns whether the resource is virtual or not
# File lib/puppet/type.rb 2616 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 2396 def set_sensitive_parameters(sensitive_parameters) 2397 sensitive_parameters.each do |name| 2398 p = parameter(name) 2399 if p.is_a?(Puppet::Property) 2400 p.sensitive = true 2401 elsif p.is_a?(Puppet::Parameter) 2402 warning(_("Unable to mark '%{name}' as sensitive: %{name} is a parameter and not a property, and cannot be automatically redacted.") % 2403 { name: name }) 2404 elsif self.class.attrclass(name) 2405 warning(_("Unable to mark '%{name}' as sensitive: the property itself was not assigned a value.") % { name: name }) 2406 else 2407 err(_("Unable to mark '%{name}' as sensitive: the property itself is not defined on %{type}.") % { name: name, type: type }) 2408 end 2409 end 2410 2411 parameters.each do |name, param| 2412 next if param.sensitive 2413 if param.is_a?(Puppet::Parameter) 2414 param.sensitive = param.is_sensitive if param.respond_to?(:is_sensitive) 2415 end 2416 end 2417 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 2431 def set_name(hash) 2432 self[name_var] = hash.delete(name_var) if name_var 2433 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 2447 def set_parameters(hash) 2448 # Use the order provided by allattrs, but add in any 2449 # extra attributes from the resource so we get failures 2450 # on invalid attributes. 2451 no_values = [] 2452 (self.class.allattrs + hash.keys).uniq.each do |attr| 2453 begin 2454 # Set any defaults immediately. This is mostly done so 2455 # that the default provider is available for any other 2456 # property validation. 2457 if hash.has_key?(attr) 2458 self[attr] = hash[attr] 2459 else 2460 no_values << attr 2461 end 2462 rescue ArgumentError, Puppet::Error, TypeError 2463 raise 2464 rescue => detail 2465 error = Puppet::DevError.new(_("Could not set %{attribute} on %{class_name}: %{detail}") % { attribute: attr, class_name: self.class.name, detail: detail }) 2466 error.set_backtrace(detail.backtrace) 2467 raise error 2468 end 2469 end 2470 no_values.each do |attr| 2471 set_default(attr) 2472 end 2473 end