diff options
| author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-02-07 02:31:00 +0000 |
|---|---|---|
| committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-02-07 02:31:00 +0000 |
| commit | 4ecfa7bf4a0f88334afdec359f317b3bf7b44c21 (patch) | |
| tree | 02dd9e06b7d7dc4ca29aa4523a3ada56c9f1be6c | |
| parent | 9114cbe18b11d2a4f3f58c4799f615721f4c2d71 (diff) | |
| download | puppet-4ecfa7bf4a0f88334afdec359f317b3bf7b44c21.tar.gz puppet-4ecfa7bf4a0f88334afdec359f317b3bf7b44c21.tar.xz puppet-4ecfa7bf4a0f88334afdec359f317b3bf7b44c21.zip | |
Config files now seem to work, so I am ready to start incorporating them.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@868 980ebf18-57e1-0310-9a29-db15c13687c0
| -rw-r--r-- | lib/puppet/config.rb | 209 | ||||
| -rwxr-xr-x | test/other/config.rb | 98 | ||||
| -rw-r--r-- | test/puppettest.rb | 1 |
3 files changed, 260 insertions, 48 deletions
diff --git a/lib/puppet/config.rb b/lib/puppet/config.rb index 833a2c6e3..3f9f65c47 100644 --- a/lib/puppet/config.rb +++ b/lib/puppet/config.rb @@ -1,16 +1,42 @@ module Puppet # The class for handling configuration files. class Config - # Slight override, since we can't seem to have a subclass where all instances - # have the same default block. - def [](section) - unless self.has_key?(section) - self[section] = {} + # Retrieve a config value + def [](param) + param = param.intern unless param.is_a? Symbol + if @config.include?(param) + if @config[param] + val = @config[param].value + return val + end + else + nil + end + end + + # Set a config value. This doesn't set the defaults, it sets the value itself. + def []=(param, value) + param = param.intern unless param.is_a? Symbol + unless @config.include?(param) + @config[param] = newelement(param, value) end - super + @config[param].value = value + end + + # Remove all set values. + def clear + @config.each { |name, obj| + obj.clear + } end - def initialize(file) + # Create a new config object + def initialize + @config = {} + end + + # Parse a configuration file. + def parse(file) text = nil begin @@ -34,64 +60,157 @@ class Config when /^\[(\w+)\]$/: section = $1 # Section names when /^\s*#/: next # Skip comments when /^\s*$/: next # Skip blanks - when /^\s*(\w+)\s+(.+)$/: # settings - var = $1 + when /^\s*(\w+)\s*=\s*(.+)$/: # settings + var = $1.intern value = $2 - self[section][var] = value + Puppet.info "%s: Setting %s to '%s'" % [section, var, value] + + self[var] = value + @config[var].section = section else raise Puppet::Error, "Could not match line %s" % line end } end - def setdefaults(hash) + # Create a new element. The value is passed in because it's used to determine + # what kind of element we're creating, but the value itself might be either + # a default or a value, so we can't actually assign it. + def newelement(param, value) + mod = nil + case value + when true, false, "true", "false": + mod = CBoolean + when /^\$/, /^\//: + mod = CFile + when String: # nothing + else + raise Puppet::Error, "Invalid value '%s'" % value + end + element = CElement.new(param) + element.parent = self + if mod + element.extend(mod) + end + + return element + end + + # Set a bunch of defaults in a given section. The sections are actually pretty + # pointless, but they help break things up a bit, anyway. + def setdefaults(section, hash) + section = section.intern unless section.is_a? Symbol hash.each { |param, value| - if @defaults.include?(param) + if @config.include?(param) and @config[param].default raise Puppet::Error, "Default %s is already defined" % param end + unless @config.include?(param) + @config[param] = newelement(param, value) + end + @config[param].default = value + @config[param].section = section + } + end - case value - when true, false: - @defaults[param] = Boolean.new(param, value) - when String: - @defaults[param] = Element.new(param, value) - when Hash: - type = nil - unless value.include?(:type) - raise Puppet::Error, "You must include the object type" - end - unless type = Puppet.type(value[:type]) - raise Puppet::Error, "Invalid type %s" % value[:type] - end + # The base element type. + class CElement + attr_accessor :name, :section, :default, :parent - value.delete(:type) + # Unset any set value. + def clear + @value = nil + end - # FIXME this won't work, because we don't want to interpolate the - # file name until they actually ask for it - begin - @defaults[param] = type.create(value) - rescue => detail - raise Puppet::Error, "Could not create default %s: %s" % - [param, detail] - end + # Create the new element. Pretty much just sets the name. + def initialize(name, value = nil) + @name = name + if value + @value = value end - } - end + end - class Element - attr_accessor :name, :value - end + # Retrieves the value, or if it's not set, retrieves the default. + def value + retval = nil + if defined? @value and ! @value.nil? + retval = @value + elsif defined? @default + retval = @default + else + return nil + end - class File < Element - end + if respond_to?(:convert) + return convert(retval) + else + return retval + end + end - class Boolean < Element + # Set the value. def value=(value) - unless value == true or value == false - raise Puppet::DevError, "Invalid value %s for %s" % [value, @name] + if respond_to?(:validate) + validate(value) + end + if respond_to?(:munge) + @value = munge(value) + else + @value = value end + end + end - @value = value + # A file. + module CFile + attr_accessor :user, :group, :mode, :type + + def convert(value) + unless value + return nil + end + if value =~ /\$(\w+)/ + parent = $1 + if pval = @parent[parent] + newval = value.sub(/\$#{parent}/, pval) + return File.join(newval.split("/")) + else + raise Puppet::DevError, "Could not find value for %s" % parent + end + else + return value + end + end + + # Set the type appropriately. Yep, a hack. + def munge(value) + if @name.to_s =~ /dir/ + @type = :directory + else + @type = :file + end + return value + end + + # Make sure any provided variables look up to something. + def validate(value) + value.scan(/\$(\w+)/) { |name| + name = name[0] + unless @parent[name] + raise Puppet::Error, "'%s' is unset" % name + end + } + end + end + + # A simple boolean. + module CBoolean + def munge(value) + case value + when true, "true": return true + when false, "false": return false + else + raise Puppet::Error, "Invalid value %s for %s" % [value, @name] + end end end end diff --git a/test/other/config.rb b/test/other/config.rb index ae3392edd..639fb38f7 100755 --- a/test/other/config.rb +++ b/test/other/config.rb @@ -24,7 +24,14 @@ class TestConfig < Test::Unit::TestCase c = mkconfig assert_nothing_raised { - c.setdefaults(:booltest => true) + c.setdefaults(:testing, :booltest => true) + } + + assert(c[:booltest]) + c = mkconfig + + assert_nothing_raised { + c.setdefaults(:testing, :booltest => "true") } assert(c[:booltest]) @@ -33,11 +40,98 @@ class TestConfig < Test::Unit::TestCase c[:booltest] = false } - assert(! c[:booltest]) + assert(! c[:booltest], "Booltest is not false") + + assert_nothing_raised { + c[:booltest] = "false" + } + + assert(! c[:booltest], "Booltest is not false") assert_raise(Puppet::Error) { c[:booltest] = "yayness" } + + assert_raise(Puppet::Error) { + c[:booltest] = "/some/file" + } + end + + def test_strings + c = mkconfig + val = "this is a string" + assert_nothing_raised { + c.setdefaults(:testing, :strtest => val) + } + + assert_equal(val, c[:strtest]) + end + + def test_files + c = mkconfig + + parent = "/puppet" + assert_nothing_raised { + c.setdefaults(:testing, :parentdir => parent) + } + + assert_nothing_raised { + c.setdefaults(:testing, :child => "$parent/child") + } + + assert_equal(parent, c[:parentdir]) + assert_equal("/puppet/child", File.join(c[:parentdir], "child")) + end + + def test_getset + c = mkconfig + initial = "an initial value" + assert_nothing_raised { + c[:yayness] = initial + } + assert_equal(initial, c[:yayness]) + + default = "this is a default" + assert_nothing_raised { + c.setdefaults(:testing, :yayness => default) + } + + assert_equal(initial, c[:yayness]) + + assert_nothing_raised { + c.clear + } + + assert_equal(default, c[:yayness]) + + assert_nothing_raised { + c[:yayness] = "not default" + } + assert_equal("not default", c[:yayness]) + end + + def test_parse + text = %{one = this is a test + two = another test + +[section1] + attr = value + attr2 = /some/dir + attr3 = $attr2/other + } + + file = tempfile() + File.open(file, "w") { |f| f.puts text } + + c = mkconfig + + assert_nothing_raised { + c.parse(file) + } + + assert_equal("value", c[:attr]) + assert_equal("/some/dir", c[:attr2]) + assert_equal("/some/dir/other", c[:attr3]) end end diff --git a/test/puppettest.rb b/test/puppettest.rb index ec7b1b104..439e5b085 100644 --- a/test/puppettest.rb +++ b/test/puppettest.rb @@ -80,7 +80,6 @@ module TestPuppet # stop any services that might be hanging around def stopservices - Puppet.info "Clearing services" if stype = Puppet::Type.type(:service) stype.each { |service| service[:running] = false |
