Commits

Etienne Perot  committed 43130ac

Implement "source" parameter, which allows specifying a puppet://-style URLs to an ini file containing data to merge with the target ini file

  • Participants
  • Parent commits c875af3

Comments (0)

Files changed (4)

File lib/puppet/provider/ini_setting/ruby.rb

 Puppet::Type.type(:ini_setting).provide(:ruby) do
 
   def exists?
+    return true unless resource[:source].empty?
     ini_file.get_value(section, setting)
   end
 
 
   private
   def ini_file
-    @ini_file ||= Puppet::Util::IniFile.new(file_path, separator)
+    @ini_file ||= Puppet::Util::IniFile.new(file_path, separator, true)
   end
 
 end

File lib/puppet/type/ini_setting.rb

+require File.expand_path('../../util/ini_file', __FILE__)
+
 Puppet::Type.newtype(:ini_setting) do
 
   ensurable do
     end
   end
 
+  newparam(:source) do
+    desc 'The ini file to read sections/settings/values from.'
+    defaultto([])
+
+    validate do |sources|
+      sources = [sources] unless sources.is_a?(Array)
+      sources.each do |source|
+        next if Puppet::Util.absolute_path?(source)
+        begin
+          uri = URI.parse(URI.escape(source))
+        rescue => detail
+          self.fail "Could not understand source #{source}: #{detail}"
+        end
+        self.fail "Cannot use relative URLs '#{source}'" unless uri.absolute?
+        self.fail "Cannot use opaque URLs '#{source}'" unless uri.hierarchical?
+        self.fail "Cannot use URLs of type '#{uri.scheme}' for grabbing the source .ini" unless %w{file puppet}.include?(uri.scheme)
+      end
+    end
+
+    SEPARATOR_REGEX = [Regexp.escape(File::SEPARATOR.to_s), Regexp.escape(File::ALT_SEPARATOR.to_s)].join
+    munge do |sources|
+      sources = [sources] unless sources.is_a?(Array)
+      sources.map do |source|
+        source = source.sub(/[#{SEPARATOR_REGEX}]+$/, '')
+        if Puppet::Util.absolute_path?(source)
+          URI.unescape(Puppet::Util.path_to_uri(source).to_s)
+        else
+          source
+        end
+      end
+    end
+  end
+
   newparam(:key_val_separator) do
     desc 'The separator string to use between each setting name and value. ' +
         'Defaults to " = ", but you could use this to override e.g. whether ' +
     desc 'The value of the setting to be defined.'
   end
 
+  def eval_generate
+    return [] if self[:source].empty?
+    content = nil
+    self[:source].each do |source|
+      if tmp = Puppet::FileServing::Content.indirection.find(source, :environment => self.catalog.environment)
+        content = tmp.content
+        break
+      end
+    end
+    fail 'Could not find any valid source URLs' unless content
+    source_ini = Puppet::Util::IniFile.new(content, self[:key_val_separator], false)
+    children = []
+    title = self[:name]
+    source_ini.section_names.each do |section|
+      source_ini.section_settings(section).each do |setting|
+        options = @original_parameters.merge(
+          :source  => [],
+          :section => section,
+          :setting => setting,
+          :value   => source_ini.get_value(section, setting),
+          :name    => title + ' @ [' + section + ']: ' + setting
+        ).reject { |param, value| value.nil? }
+        children << self.class.new(options)
+      end
+    end
+    children
+  end
 
 end

File lib/puppet/util/ini_file.rb

     SETTING_REGEX = /^(\s*)([ \w\d\.,\\\/\-_:;'"!?@#\$%^&*()\|]+?)(\s*=\s*)([\S\s]*?\S|)\s*$/
     COMMENTED_SETTING_REGEX = /^(\s*)[#;]+(\s*)([\w\d\.\\\/\-]+)(\s*=\s*)([\S\s]*\S)\s*$/
 
-    def initialize(path, key_val_separator = ' = ')
-      @path = path
+    def initialize(content, key_val_separator = ' = ', is_path = true)
+      if is_path
+        @path = content
+      else
+        @content = content
+      end
       @key_val_separator = key_val_separator
       @section_names = []
       @sections_hash = {}
-      if File.file?(@path)
+      if not is_path or File.file?(@path)
         parse_file
       end
     end
       @section_names
     end
 
+    def section_settings(section_name)
+      if (@sections_hash.has_key?(section_name))
+        @sections_hash[section_name].settings
+      end
+    end
+
     def get_value(section_name, setting)
       if (@sections_hash.has_key?(section_name))
         @sections_hash[section_name].get_value(setting)
     end
 
     def lines
+        if @content
+          return @content.split(/\r?\n/)
+        end
         @lines ||= IniFile.readlines(@path)
     end
 

File lib/puppet/util/ini_file/section.rb

       @end_line.nil?
     end
 
+    def settings
+      @existing_settings.keys | @additional_settings.keys
+    end
+
     def get_value(setting_name)
       @existing_settings[setting_name] || @additional_settings[setting_name]
     end