lib/puppet/provider/parsedfile.rb in puppet-3.1.1 vs lib/puppet/provider/parsedfile.rb in puppet-3.2.0.rc1

- old
+ new

@@ -101,10 +101,41 @@ %{# HEADER: This file was autogenerated at #{Time.now} # HEADER: by puppet. While it can still be managed manually, it # HEADER: is definitely not recommended.\n} end + # An optional regular expression matched by third party headers. + # + # For example, this can be used to filter the vixie cron headers as + # erronously exported by older cron versions. + # + # @api private + # @abstract Providers based on ParsedFile may implement this to make it + # possible to identify a header maintained by a third party tool. + # The provider can then allow that header to remain near the top of the + # written file, or remove it after composing the file content. + # If implemented, the function must return a Regexp object. + # The expression must be tailored to match exactly one third party header. + # @see drop_native_header + # @note When specifying regular expressions in multiline mode, avoid + # greedy repititions such as '.*' (use .*? instead). Otherwise, the + # provider may drop file content between sparse headers. + def self.native_header_regex + nil + end + + # How to handle third party headers. + # @api private + # @abstract Providers based on ParsedFile that make use of the support for + # third party headers may override this method to return +true+. + # When this is done, headers that are matched by the native_header_regex + # are not written back to disk. + # @see native_header_regex + def self.drop_native_header + false + end + # Add another type var. def self.initvars @records = [] @target_objects = {} @@ -184,41 +215,69 @@ @records = prefetch_all_targets(resources) match_providers_with_resources(resources) end + # Match a list of catalog resources with provider instances + # + # @api private + # + # @param [Array<Puppet::Resource>] resources A list of resources using this class as a provider def self.match_providers_with_resources(resources) return unless resources matchers = resources.dup @records.each do |record| # Skip things like comments and blank lines next if skip_record?(record) - if name = record[:name] and resource = resources[name] + if (resource = resource_for_record(record, resources)) resource.provider = new(record) elsif respond_to?(:match) if resource = match(record, matchers) - # Remove this resource from circulation so we don't unnecessarily try to match matchers.delete(resource.title) record[:name] = resource[:name] resource.provider = new(record) end end end end + # Look up a resource based on a parsed file record + # + # @api private + # + # @param [Hash<Symbol, Object>] record + # @param [Array<Puppet::Resource>] resources + # + # @return [Puppet::Resource, nil] The resource if found, else nil + def self.resource_for_record(record, resources) + name = record[:name] + if name + resources[name] + end + end + def self.prefetch_all_targets(resources) records = [] targets(resources).each do |target| records += prefetch_target(target) end records end # Prefetch an individual target. def self.prefetch_target(target) - target_records = retrieve(target).each do |r| + + begin + target_records = retrieve(target) + rescue Puppet::Util::FileType::FileReadError => detail + puts detail.backtrace if Puppet[:trace] + Puppet.err "Could not prefetch #{self.resource_type.name} provider '#{self.name}' target '#{target}': #{detail}. Treating as empty" + target_records = [] + end + + target_records.each do |r| r[:on_disk] = true r[:target] = target r[:ensure] = :present end @@ -297,11 +356,29 @@ end targets.uniq.compact end + # Compose file contents from the set of records. + # + # If self.native_header_regex is not nil, possible vendor headers are + # identified by matching the return value against the expression. + # If one (or several consecutive) such headers, are found, they are + # either moved in front of the self.header if self.drop_native_header + # is false (this is the default), or removed from the return value otherwise. + # + # @api private def self.to_file(records) text = super + if native_header_regex and (match = text.match(native_header_regex)) + if drop_native_header + # concatenate the text in front of and after the native header + text = match.pre_match + match.post_match + else + native_header = match[0] + return native_header + header + match.pre_match + match.post_match + end + end header + text end def create @resource.class.validproperties.each do |property|