summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parameter
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/parameter')
-rw-r--r--lib/puppet/parameter/value.rb64
-rw-r--r--lib/puppet/parameter/value_collection.rb151
2 files changed, 215 insertions, 0 deletions
diff --git a/lib/puppet/parameter/value.rb b/lib/puppet/parameter/value.rb
new file mode 100644
index 000000000..5171f2580
--- /dev/null
+++ b/lib/puppet/parameter/value.rb
@@ -0,0 +1,64 @@
+require 'puppet/parameter/value_collection'
+
+# An individual Value class.
+class Puppet::Parameter::Value
+ attr_reader :name, :options, :event
+ attr_accessor :block, :call, :method, :required_features
+
+ # Add an alias for this value.
+ def alias(name)
+ @aliases << convert(name)
+ end
+
+ # Return all aliases.
+ def aliases
+ @aliases.dup
+ end
+
+ # Store the event that our value generates, if it does so.
+ def event=(value)
+ @event = convert(value)
+ end
+
+ def initialize(name)
+ if name.is_a?(Regexp)
+ @name = name
+ else
+ # Convert to a string and then a symbol, so things like true/false
+ # still show up as symbols.
+ @name = convert(name)
+ end
+
+ @aliases = []
+
+ @call = :instead
+ end
+
+ # Does a provided value match our value?
+ def match?(value)
+ if regex?
+ return true if name =~ value.to_s
+ else
+ return true if name == convert(value)
+ return @aliases.include?(convert(value))
+ end
+ end
+
+ # Is our value a regex?
+ def regex?
+ @name.is_a?(Regexp)
+ end
+
+ private
+
+ # A standard way of converting all of our values, so we're always
+ # comparing apples to apples.
+ def convert(value)
+ if value == ''
+ # We can't intern an empty string, yay.
+ value
+ else
+ value.to_s.to_sym
+ end
+ end
+end
diff --git a/lib/puppet/parameter/value_collection.rb b/lib/puppet/parameter/value_collection.rb
new file mode 100644
index 000000000..436226ebe
--- /dev/null
+++ b/lib/puppet/parameter/value_collection.rb
@@ -0,0 +1,151 @@
+require 'puppet/parameter/value'
+
+# A collection of values and regexes, used for specifying
+# what values are allowed in a given parameter.
+class Puppet::Parameter::ValueCollection
+
+ def aliasvalue(name, other)
+ other = other.to_sym
+ unless value = match?(other)
+ raise Puppet::DevError, "Cannot alias nonexistent value %s" % other
+ end
+
+ value.alias(name)
+ end
+
+ # Return a doc string for all of the values in this parameter/property.
+ def doc
+ unless defined?(@doc)
+ @doc = ""
+ unless values.empty?
+ @doc += " Valid values are "
+ @doc += @strings.collect do |value|
+ if aliases = value.aliases and ! aliases.empty?
+ "``%s`` (also called ``%s``)" % [value.name, aliases.join(", ")]
+ else
+ "``%s``" % value.name
+ end
+ end.join(", ") + "."
+ end
+
+ unless regexes.empty?
+ @doc += " Values can match ``" + regexes.join("``, ``") + "``."
+ end
+ end
+
+ @doc
+ end
+
+ # Does this collection contain any value definitions?
+ def empty?
+ @values.empty?
+ end
+
+ def initialize
+ # We often look values up by name, so a hash makes more sense.
+ @values = {}
+
+ # However, we want to retain the ability to match values in order,
+ # but we always prefer directly equality (i.e., strings) over regex matches.
+ @regexes = []
+ @strings = []
+ end
+
+ # Can we match a given value?
+ def match?(test_value)
+ # First look for normal values
+ if value = @strings.find { |v| v.match?(test_value) }
+ return value
+ end
+
+ # Then look for a regex match
+ @regexes.find { |v| v.match?(test_value) }
+ end
+
+ # If the specified value is allowed, then munge appropriately.
+ def munge(value)
+ return value if empty?
+
+ if instance = match?(value)
+ if instance.regex?
+ return value
+ else
+ return instance.name
+ end
+ else
+ return value
+ end
+ end
+
+ # Define a new valid value for a property. You must provide the value itself,
+ # usually as a symbol, or a regex to match the value.
+ #
+ # The first argument to the method is either the value itself or a regex.
+ # The second argument is an option hash; valid options are:
+ # * <tt>:event</tt>: The event that should be returned when this value is set.
+ # * <tt>:call</tt>: When to call any associated block. The default value
+ # is ``instead``, which means to call the value instead of calling the
+ # provider. You can also specify ``before`` or ``after``, which will
+ # call both the block and the provider, according to the order you specify
+ # (the ``first`` refers to when the block is called, not the provider).
+ def newvalue(name, options = {}, &block)
+ value = Puppet::Parameter::Value.new(name)
+ @values[value.name] = value
+ if value.regex?
+ @regexes << value
+ else
+ @strings << value
+ end
+
+ options.each { |opt, arg| value.send(opt.to_s + "=", arg) }
+ if block_given?
+ value.block = block
+ else
+ value.call = options[:call] || :none
+ end
+
+ if block_given? and ! value.regex?
+ value.method ||= "set_" + value.name.to_s
+ end
+
+ value
+ end
+
+ # Define one or more new values for our parameter.
+ def newvalues(*names)
+ names.each { |name| newvalue(name) }
+ end
+
+ def regexes
+ @regexes.collect { |r| r.name.inspect }
+ end
+
+ # Verify that the passed value is valid.
+ def validate(value)
+ return if empty?
+
+ unless @values.detect { |name, v| v.match?(value) }
+ str = "Invalid value %s. " % [value.inspect]
+
+ unless values.empty?
+ str += "Valid values are %s. " % values.join(", ")
+ end
+
+ unless regexes.empty?
+ str += "Valid values match %s." % regexes.join(", ")
+ end
+
+ raise ArgumentError, str
+ end
+ end
+
+ # Return a single value instance.
+ def value(name)
+ @values[name]
+ end
+
+ # Return the list of valid values.
+ def values
+ @strings.collect { |s| s.name }
+ end
+end