summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-02-07 02:31:00 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-02-07 02:31:00 +0000
commit4ecfa7bf4a0f88334afdec359f317b3bf7b44c21 (patch)
tree02dd9e06b7d7dc4ca29aa4523a3ada56c9f1be6c
parent9114cbe18b11d2a4f3f58c4799f615721f4c2d71 (diff)
downloadpuppet-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.rb209
-rwxr-xr-xtest/other/config.rb98
-rw-r--r--test/puppettest.rb1
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