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 #{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? "`#{value.name}` (also called `#{aliases.join(", ")}`)" else "`#{value.name}`" end end.join(", ") + "." end @doc += " Values can match `" + regexes.join("`, `") + "`." unless regexes.empty? 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: # * :event: The event that should be returned when this value is set. # * :call: 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 value.method ||= "set_#{value.name}" if block_given? and ! value.regex? 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 #{value.inspect}. " str += "Valid values are #{values.join(", ")}. " unless values.empty? str += "Valid values match #{regexes.join(", ")}." unless regexes.empty? 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