Skip to content

Commit

Permalink
(Maint) Pull config file parsing into a class
Browse files Browse the repository at this point in the history
The parser for config files used to be tied up with all of the other
logic for handling configuration settings. This takes the first step in
encapsulating that parsing into a class that is dedicated to just
parsing a configuration file.
  • Loading branch information
zaphod42 committed Oct 1, 2012
1 parent da40d8d commit cfe8bd4
Showing 1 changed file with 77 additions and 68 deletions.
145 changes: 77 additions & 68 deletions lib/puppet/settings.rb
Expand Up @@ -1094,30 +1094,6 @@ def settings_with_hooks
@config.values.find_all { |setting| setting.has_hook? }
end

# Extract extra setting information for files.
def extract_fileinfo(string)
result = {}
value = string.sub(/\{\s*([^}]+)\s*\}/) do
params = $1
params.split(/\s*,\s*/).each do |str|
if str =~ /^\s*(\w+)\s*=\s*([\w\d]+)\s*$/
param, value = $1.intern, $2
result[param] = value
raise ArgumentError, "Invalid file option '#{param}'" unless [:owner, :mode, :group].include?(param)

if param == :mode and value !~ /^\d+$/
raise ArgumentError, "File modes must be numbers"
end
else
raise ArgumentError, "Could not parse '#{string}'"
end
end
''
end
result[:value] = value.sub(/\s*$/, '')
result
end

# Convert arguments into booleans, integers, or whatever.
def munge_value(value)
# Handle different data types correctly
Expand All @@ -1132,60 +1108,93 @@ def munge_value(value)
end
end

# This method just turns a file in to a hash of hashes.
def parse_file(file)
text = read_file(file)
class ConfigParser
def initialize(value_converter)
@value_converter = value_converter
end

result = Hash.new { |names, name|
names[name] = {}
}
def parse_file(file, text)
result = Hash.new { |names, name|
names[name] = {}
}

count = 0

# Default to 'main' for the section.
section = :main
result[section][:_meta] = {}
text.split(/\n/).each do |line|
count += 1
case line
when /^\s*\[(\w+)\]\s*$/
section = $1.intern # Section names
#disallow application_defaults in config file
if section == :application_defaults
raise Puppet::Error, "Illegal section 'application_defaults' in config file #{file} at line #{line}"
end
# Add a meta section
result[section][:_meta] ||= {}
when /^\s*#/; next # Skip comments
when /^\s*$/; next # Skip blanks
when /^\s*(\w+)\s*=\s*(.*?)\s*$/ # settings
var = $1.intern

# We don't want to munge modes, because they're specified in octal, so we'll
# just leave them as a String, since Puppet handles that case correctly.
if var == :mode
value = $2
count = 0

# Default to 'main' for the section.
section = :main
result[section][:_meta] = {}
text.split(/\n/).each do |line|
count += 1
case line
when /^\s*\[(\w+)\]\s*$/
section = $1.intern # Section names
#disallow application_defaults in config file
if section == :application_defaults
raise Puppet::Error, "Illegal section 'application_defaults' in config file #{file} at line #{line}"
end
# Add a meta section
result[section][:_meta] ||= {}
when /^\s*#/; next # Skip comments
when /^\s*$/; next # Skip blanks
when /^\s*(\w+)\s*=\s*(.*?)\s*$/ # settings
var = $1.intern

# We don't want to munge modes, because they're specified in octal, so we'll
# just leave them as a String, since Puppet handles that case correctly.
if var == :mode
value = $2
else
value = @value_converter.call($2)
end

# Check to see if this is a file argument and it has extra options
begin
if value.is_a?(String) and options = extract_fileinfo(value)
value = options[:value]
options.delete(:value)
result[section][:_meta][var] = options
end
result[section][var] = value
rescue Puppet::Error => detail
raise ParseError.new(detail.message, file, line, detail)
end
else
value = munge_value($2)
raise ParseError.new("Could not match line #{line}", file, line)
end
end

result
end

# Check to see if this is a file argument and it has extra options
begin
if value.is_a?(String) and options = extract_fileinfo(value)
value = options[:value]
options.delete(:value)
result[section][:_meta][var] = options
private

def extract_fileinfo(string)
result = {}
value = string.sub(/\{\s*([^}]+)\s*\}/) do
params = $1
params.split(/\s*,\s*/).each do |str|
if str =~ /^\s*(\w+)\s*=\s*([\w\d]+)\s*$/
param, value = $1.intern, $2
result[param] = value
raise ArgumentError, "Invalid file option '#{param}'" unless [:owner, :mode, :group].include?(param)

if param == :mode and value !~ /^\d+$/
raise ArgumentError, "File modes must be numbers"
end
else
raise ArgumentError, "Could not parse '#{string}'"
end
result[section][var] = value
rescue Puppet::Error => detail
raise ParseError.new(detail.message, file, line, detail)
end
else
raise ParseError.new("Could not match line #{line}", file, line)
''
end
result[:value] = value.sub(/\s*$/, '')
result
end
end

result
# This method just turns a file in to a hash of hashes.
def parse_file(file)
Puppet::Settings::ConfigParser.new(method(:munge_value)).parse_file(file, read_file(file))
end

# Read the file in.
Expand Down

0 comments on commit cfe8bd4

Please sign in to comment.