summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/parameter.rb92
-rw-r--r--lib/puppet/type.rb9
-rw-r--r--lib/puppet/type/state.rb74
-rwxr-xr-xlib/puppet/type/symlink.rb16
-rw-r--r--test/types/parameter.rb107
-rw-r--r--test/types/state.rb92
-rwxr-xr-xtest/types/symlink.rb26
7 files changed, 360 insertions, 56 deletions
diff --git a/lib/puppet/parameter.rb b/lib/puppet/parameter.rb
index cee53afbf..81b5cb68c 100644
--- a/lib/puppet/parameter.rb
+++ b/lib/puppet/parameter.rb
@@ -30,6 +30,12 @@ module Puppet
@doc = str
end
+ def initvars
+ @parametervalues = []
+ @aliasvalues = {}
+ @parameterregexes = []
+ end
+
# This is how we munge the value. Basically, this is our
# opportunity to convert the value from one form into another.
def munge(&block)
@@ -56,10 +62,6 @@ module Puppet
#@munger = block
end
- #def inspect
- # "Parameter(#{self.name})"
- #end
-
# Mark whether we're the namevar.
def isnamevar
@isnamevar = true
@@ -118,27 +120,46 @@ module Puppet
end
end
+ # Does the value match any of our regexes?
+ def match?(value)
+ value = value.to_s unless value.is_a? String
+ @parameterregexes.find { |r|
+ r = r[0] if r.is_a? Array # States use a hash here
+ r =~ value
+ }
+ end
+
# Define a new value for our parameter.
def newvalues(*names)
- @parametervalues ||= []
-
names.each { |name|
- if @parametervalues.include?(name)
- Puppet.warning "%s already has a value for %s" %
- [name, name]
+ name = name.intern if name.is_a? String
+
+ case name
+ when Symbol
+ if @parametervalues.include?(name)
+ Puppet.warning "%s already has a value for %s" %
+ [name, name]
+ end
+ @parametervalues << name
+ when Regexp
+ if @parameterregexes.include?(name)
+ Puppet.warning "%s already has a value for %s" %
+ [name, name]
+ end
+ @parameterregexes << name
+ else
+ raise ArgumentError, "Invalid value %s of type %s" %
+ [name, name.class]
end
- @parametervalues << name
}
end
def aliasvalue(name, other)
- @parametervalues ||= []
unless @parametervalues.include?(other)
raise Puppet::DevError,
"Cannot alias nonexistent value %s" % other
end
- @aliasvalues ||= {}
@aliasvalues[name] = other
end
@@ -146,11 +167,12 @@ module Puppet
@aliasvalues[name]
end
+ def regexes
+ return @parameterregexes.dup
+ end
+
# Return the list of valid values.
def values
- @parametervalues ||= []
- @aliasvalues ||= {}
-
#[@aliasvalues.keys, @parametervalues.keys].flatten
if @parametervalues.is_a? Array
return @parametervalues.dup
@@ -240,7 +262,7 @@ module Puppet
# If the specified value is allowed, then munge appropriately.
munge do |value|
- if self.class.values.empty?
+ if self.class.values.empty? and self.class.regexes.empty?
# This parameter isn't using defined values to do its work.
return value
end
@@ -254,25 +276,51 @@ module Puppet
retval = intern
elsif other = self.class.alias(intern)
retval = other
+ elsif ary = self.class.match?(value)
+ retval = value
else
+ # If it passed the validation but is not a registered value,
+ # we just return it as is.
retval = value
end
+
retval
end
# Verify that the passed value is valid.
validate do |value|
- values = self.class.values
- if values.empty?
+ vals = self.class.values
+ regs = self.class.regexes
+
+ if regs.is_a? Hash # this is true on states
+ regs = regs.keys
+ end
+ if vals.empty? and regs.empty?
# This parameter isn't using defined values to do its work.
return
end
+ newval = value
unless value.is_a?(Symbol)
- value = value.to_s.intern
+ newval = value.to_s.intern
end
- unless values.include?(value) or self.class.alias(value)
- self.fail "Invalid '%s' value '%s'. Valid values are '%s'" %
- [self.class.name, value, values.join(", ")]
+
+ unless vals.include?(newval) or
+ self.class.alias(newval) or
+ self.class.match?(value) # We match the string, not the symbol
+ str = "Invalid '%s' value %s. " %
+ [self.class.name, value.inspect]
+
+ unless vals.empty?
+ str += "Valid values are %s. " % vals.join(", ")
+ end
+
+ unless regs.empty?
+ str += "Valid values match %s." % regs.collect { |r|
+ r.to_s
+ }.join(", ")
+ end
+
+ raise ArgumentError, str
end
end
diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb
index 9adcf54b4..a50f24f75 100644
--- a/lib/puppet/type.rb
+++ b/lib/puppet/type.rb
@@ -417,6 +417,9 @@ class Type < Puppet::Element
param = Class.new(Puppet::Parameter) do
@name = name
end
+
+ param.initvars
+
param.ismetaparameter
param.class_eval(&block)
const_set("MetaParam" + name.to_s.capitalize,param)
@@ -440,6 +443,9 @@ class Type < Puppet::Element
param = Class.new(Puppet::Parameter) do
@name = name
end
+
+ param.initvars
+
param.element = self
param.class_eval(&block)
const_set("Parameter" + name.to_s.capitalize,param)
@@ -475,6 +481,9 @@ class Type < Puppet::Element
s = Class.new(parent) do
@name = name
end
+
+ s.initvars
+
const_set("State" + name.to_s.capitalize,s)
s.class_eval(&block)
@states ||= []
diff --git a/lib/puppet/type/state.rb b/lib/puppet/type/state.rb
index 38cf7fc9e..17a004056 100644
--- a/lib/puppet/type/state.rb
+++ b/lib/puppet/type/state.rb
@@ -18,26 +18,34 @@ class State < Puppet::Parameter
class << self
attr_accessor :unmanaged
attr_reader :name
+ end
- #def inspect
- # "State(%s)" % self.name
- #end
-
- #def to_s
- # self.inspect
- #end
+ # Create the value management variables.
+ def self.initvars
+ @parametervalues = {}
+ @aliasvalues = {}
+ @parameterregexes = {}
end
- # Parameters just use 'newvalues', since there's no work associated with them.
+ # Parameters just use 'newvalues', since there's no work associated with them,
+ # but states have blocks associated with their allowed values.
def self.newvalue(name, &block)
- @parametervalues ||= {}
+ name = name.intern if name.is_a? String
- if @parametervalues.include?(name)
- Puppet.warning "%s already has a value for %s" % [name, name]
- end
- @parametervalues[name] = block
+ case name
+ when Symbol
+ if @parametervalues.include?(name)
+ Puppet.warning "%s reassigning value %s" % [self.name, name]
+ end
+ @parametervalues[name] = block
- define_method("set_" + name.to_s, &block)
+ define_method("set_" + name.to_s, &block)
+ when Regexp
+ @parameterregexes[name] = block
+ else
+ raise ArgumentError, "Invalid value %s of type %s" %
+ [name, name.class]
+ end
end
# Call the method associated with a given value.
@@ -49,22 +57,26 @@ class State < Puppet::Parameter
value = self.should
method = "set_" + value.to_s
- unless self.respond_to?(method)
- self.fail "%s is not a valid value for %s" %
- [value, self.class.name]
- end
- self.debug "setting %s (currently %s)" % [value, self.is]
+ event = nil
+ if self.respond_to?(method)
+ self.debug "setting %s (currently %s)" % [value, self.is]
- begin
- event = self.send(method)
- rescue Puppet::Error
- raise
- rescue => detail
- if Puppet[:debug]
- puts detail.backtrace
+ begin
+ event = self.send(method)
+ rescue Puppet::Error
+ raise
+ rescue => detail
+ if Puppet[:debug]
+ puts detail.backtrace
+ end
+ self.fail "Could not set %s on %s: %s" %
+ [value, self.class.name, detail]
end
- self.fail "Could not set %s on %s: %s" %
- [value, self.class.name, detail]
+ elsif ary = self.class.match?(value)
+ event = ary[1].call(value)
+ else
+ self.fail "%s is not a valid value for %s" %
+ [value, self.class.name]
end
if event and event.is_a?(Symbol)
@@ -186,7 +198,11 @@ class State < Puppet::Parameter
# return the full path to us, for logging and rollback; not currently
# used
def path
- return [@parent.path, self.name].join("/")
+ if defined? @parent and @parent
+ return [@parent.path, self.name].join("/")
+ else
+ return self.name
+ end
end
# Only return the first value
diff --git a/lib/puppet/type/symlink.rb b/lib/puppet/type/symlink.rb
index a0b36f0cf..cb05c3a88 100755
--- a/lib/puppet/type/symlink.rb
+++ b/lib/puppet/type/symlink.rb
@@ -65,7 +65,7 @@ module Puppet
end
# this is somewhat complicated, because it could exist and be
- # a file
+ # a link
def sync
case self.should
when :absent
@@ -101,6 +101,8 @@ module Puppet
copyparam(Puppet.type(:file), :path)
newparam(:recurse) do
+ attr_reader :setparent
+
desc "If target is a directory, recursively create
directories (using `file`'s `source` parameter) and link all
contained files. For instance::
@@ -109,7 +111,7 @@ module Puppet
# in /opt/csw; link it into /usr/local
symlink { \"/usr/local\":
ensure => \"/opt/csw\",
- recurse => 1
+ recurse => true
}
@@ -120,13 +122,16 @@ module Puppet
@stat = nil
@target = @parent.state(:ensure).should
+ self.setparent()
+ end
+
+ def setparent
# we want to remove our state, because we're creating children
# to do the links
if FileTest.exist?(@target)
- @stat = File.stat(@target)
+ @stat = File.lstat(@target)
else
- @parent.info "Target %s must exist for recursive links" %
- @target
+ @setparent = false
return
end
@@ -168,6 +173,7 @@ module Puppet
dir = Puppet.type(:file).implicitcreate(args)
dir.parent = @parent
@parent.push dir
+ @setparent = true
end
end
diff --git a/test/types/parameter.rb b/test/types/parameter.rb
new file mode 100644
index 000000000..d95ef461d
--- /dev/null
+++ b/test/types/parameter.rb
@@ -0,0 +1,107 @@
+if __FILE__ == $0
+ $:.unshift '..'
+ $:.unshift '../../lib'
+ $puppetbase = "../.."
+end
+
+require 'puppet/type'
+require 'puppettest'
+require 'test/unit'
+
+class TestState < Test::Unit::TestCase
+ include TestPuppet
+
+ def newparam(name = :fakeparam)
+ assert_nothing_raised {
+ param = Class.new(Puppet::Parameter) do
+ @name = :fakeparam
+ end
+ param.initvars
+
+ return param
+ }
+ end
+
+ def newinst(param)
+ assert_nothing_raised {
+ return param.new
+ }
+ end
+
+ # Test the basic newvalue stuff.
+ def test_newvalue
+ param = newparam()
+
+ # Try it with both symbols and strings.
+ assert_nothing_raised {
+ param.newvalues(:one, "two")
+ }
+
+ inst = newinst(param)
+
+ assert_nothing_raised {
+ inst.value = "one"
+ }
+
+ assert_equal(:one, inst.value)
+
+ assert_nothing_raised {
+ inst.value = :two
+ }
+ assert_equal(:two, inst.value)
+
+ assert_raise(ArgumentError) {
+ inst.value = :three
+ }
+ assert_equal(:two, inst.value)
+ end
+
+ # Test using regexes.
+ def test_regexvalues
+ param = newparam
+
+ assert_nothing_raised {
+ param.newvalues(/^\d+$/)
+ }
+ assert(param.match?("14"))
+ assert(param.match?(14))
+
+ inst = newinst(param)
+
+ assert_nothing_raised {
+ inst.value = 14
+ }
+
+ assert_nothing_raised {
+ inst.value = "14"
+ }
+
+ assert_raise(ArgumentError) {
+ inst.value = "a14"
+ }
+ end
+
+ # Test using both. Equality should beat matching.
+ def test_regexesandnormals
+ param = newparam
+
+ assert_nothing_raised {
+ param.newvalues(:one, /^\w+$/)
+ }
+
+ inst = newinst(param)
+
+ assert_nothing_raised {
+ inst.value = "one"
+ }
+
+ assert_equal(:one, inst.value, "Value used regex instead of equality")
+
+ assert_nothing_raised {
+ inst.value = "two"
+ }
+ assert_equal("two", inst.value, "Matched value didn't take")
+ end
+end
+
+# $Id$
diff --git a/test/types/state.rb b/test/types/state.rb
new file mode 100644
index 000000000..88df6575d
--- /dev/null
+++ b/test/types/state.rb
@@ -0,0 +1,92 @@
+if __FILE__ == $0
+ $:.unshift '..'
+ $:.unshift '../../lib'
+ $puppetbase = "../.."
+end
+
+require 'puppet/type'
+require 'puppettest'
+require 'test/unit'
+
+class TestState < Test::Unit::TestCase
+ include TestPuppet
+
+ def newinst(state)
+ inst = nil
+ assert_nothing_raised {
+ return state.new(:parent => nil)
+ }
+ end
+
+ def newstate(name = :fakestate)
+ assert_nothing_raised {
+ state = Class.new(Puppet::State) do
+ @name = :fakeparam
+ end
+ state.initvars
+
+ return state
+ }
+ end
+
+ def test_newvalue
+ state = newstate()
+
+ assert_nothing_raised {
+ state.newvalue(:one) do
+ @is = 1
+ end
+ }
+
+ assert_nothing_raised {
+ state.newvalue("two") do
+ @is = 2
+ end
+ }
+
+ inst = newinst(state)
+
+ assert_nothing_raised {
+ inst.should = "one"
+ }
+
+ assert_equal(:one, inst.should)
+ assert_nothing_raised { inst.set_one }
+ assert_equal(1, inst.is)
+
+ assert_nothing_raised {
+ inst.should = :two
+ }
+
+ assert_equal(:two, inst.should)
+ assert_nothing_raised { inst.set_two }
+ assert_equal(2, inst.is)
+ end
+
+ def test_newvaluewithregexes
+ state = newstate()
+
+ assert_nothing_raised {
+ state.newvalue(/^\w+$/) do |value|
+ @is = value.upcase
+ return :regex_matched
+ end
+ }
+
+ inst = newinst(state)
+
+ assert_nothing_raised {
+ inst.should = "yayness"
+ }
+
+ assert_equal("yayness", inst.should)
+
+ assert_nothing_raised {
+ inst.sync
+ }
+
+ assert_equal("yayness".upcase, inst.is)
+ end
+end
+
+# $Id$
diff --git a/test/types/symlink.rb b/test/types/symlink.rb
index a07a2fbb6..21b1e865b 100755
--- a/test/types/symlink.rb
+++ b/test/types/symlink.rb
@@ -88,4 +88,30 @@ class TestSymlink < Test::Unit::TestCase
}
}
end
+
+ def test_createdrecursion
+ source = tempfile()
+ file = File.join(source, "file")
+ dest = tempfile()
+ link = File.join(dest, "file")
+
+ objects = []
+ objects << Puppet.type(:file).create(
+ :path => source,
+ :ensure => "directory"
+ )
+ objects << Puppet.type(:file).create(
+ :path => file,
+ :ensure => "file"
+ )
+ objects << Puppet.type(:symlink).create(
+ :path => dest,
+ :ensure => source,
+ :recurse => true
+ )
+
+ assert_apply(*objects)
+
+ assert(FileTest.symlink?(link), "Link was not created")
+ end
end