diff --git a/lib/puppet/error.rb b/lib/puppet/error.rb
index d0a0c9cc5..43a8df0f8 100644
--- a/lib/puppet/error.rb
+++ b/lib/puppet/error.rb
@@ -1,43 +1,49 @@
module Puppet # :nodoc:
- # The base class for all Puppet errors. We want to make it easy to add
- # line and file information. This probably isn't necessary for all
- # errors, but...
+ # The base class for all Puppet errors. It can wrap another exception
class Error < RuntimeError
- attr_accessor :line, :file
-
- def backtrace
- if defined?(@backtrace)
- return @backtrace
- else
- return super
- end
+ attr_reader :original
+ def initialize(message, original=nil)
+ super(message)
+ @original = original
end
+ end
- def initialize(message, line = nil, file = nil)
- @message = message
+ module ExternalFileError
+ # This module implements logging with a filename and line number. Use this
+ # for errors that need to report a location in a non-ruby file that we
+ # parse.
+ attr_accessor :line, :file
- @line = line if line
- @file = file if file
+ def initialize(message, file=nil, line=nil, original=nil)
+ super(message, original)
+ @file = file
+ @line = line
end
def to_s
- str = nil
- if self.file and self.line
- str = "#{@message} at #{@file}:#{@line}"
- elsif self.line
- str = "#{@message} at line #{@line}"
- elsif self.file
- str = "#{@message} in #{self.file}"
+ msg = super
+ if @file and @line
+ "#{msg} at #{@file}:#{@line}"
+ elsif @line
+ "#{msg} at line #{@line}"
+ elsif @file
+ "#{msg} in #{@file}"
else
- str = @message.to_s
+ msg
end
-
- str
end
end
+ class ParseError < Puppet::Error
+ include ExternalFileError
+ end
+
+ class ResourceError < Puppet::Error
+ include ExternalFileError
+ end
+
# An error class for when I don't know what happened. Automatically
# prints a stack trace when in debug mode.
class DevError < Puppet::Error
end
end
diff --git a/lib/puppet/network/rights.rb b/lib/puppet/network/rights.rb
index 086ac74ed..dda2c395c 100755
--- a/lib/puppet/network/rights.rb
+++ b/lib/puppet/network/rights.rb
@@ -1,274 +1,273 @@
require 'puppet/network/authstore'
require 'puppet/error'
module Puppet::Network
# this exception is thrown when a request is not authenticated
class AuthorizationError < Puppet::Error; end
# Define a set of rights and who has access to them.
# There are two types of rights:
# * named rights (ie a common string)
# * path based rights (which are matched on a longest prefix basis)
class Rights
# We basically just proxy directly to our rights. Each Right stores
# its own auth abilities.
[:allow, :deny, :restrict_method, :restrict_environment, :restrict_authenticated].each do |method|
define_method(method) do |name, *args|
if obj = self[name]
obj.send(method, *args)
else
raise ArgumentError, "Unknown right '#{name}'"
end
end
end
# Check that name is allowed or not
def allowed?(name, *args)
!is_forbidden_and_why?(name, :node => args[0], :ip => args[1])
end
def is_request_forbidden_and_why?(indirection, method, key, params)
methods_to_check = if method == :head
# :head is ok if either :find or :save is ok.
[:find, :save]
else
[method]
end
authorization_failure_exceptions = methods_to_check.map do |method|
is_forbidden_and_why?("/#{indirection}/#{key}", params.merge({:method => method}))
end
if authorization_failure_exceptions.include? nil
# One of the methods we checked is ok, therefore this request is ok.
nil
else
# Just need to return any of the failure exceptions.
authorization_failure_exceptions.first
end
end
def is_forbidden_and_why?(name, args = {})
res = :nomatch
right = @rights.find do |acl|
found = false
# an acl can return :dunno, which means "I'm not qualified to answer your question,
# please ask someone else". This is used when for instance an acl matches, but not for the
# current rest method, where we might think some other acl might be more specific.
if match = acl.match?(name)
args[:match] = match
if (res = acl.allowed?(args[:node], args[:ip], args)) != :dunno
# return early if we're allowed
return nil if res
# we matched, select this acl
found = true
end
end
found
end
# if we end here, then that means we either didn't match
# or failed, in any case will throw an error to the outside world
if name =~ /^\// or right
# we're a patch ACL, let's fail
msg = "#{(args[:node].nil? ? args[:ip] : "#{args[:node]}(#{args[:ip]})")} access to #{name} [#{args[:method]}]"
msg += " authenticated " if args[:authenticated]
-
- error = AuthorizationError.new("Forbidden request: #{msg}")
if right
- error.file = right.file
- error.line = right.line
+ msg += " at #{right.file}:#{right.line}"
end
+
+ error = AuthorizationError.new("Forbidden request: #{msg}")
else
# there were no rights allowing/denying name
# if name is not a path, let's throw
raise ArgumentError, "Unknown namespace right '#{name}'"
end
error
end
def initialize
@rights = []
end
def [](name)
@rights.find { |acl| acl == name }
end
def include?(name)
@rights.include?(name)
end
def each
@rights.each { |r| yield r.name,r }
end
# Define a new right to which access can be provided.
def newright(name, line=nil, file=nil)
add_right( Right.new(name, line, file) )
end
private
def add_right(right)
if right.acl_type == :name and include?(right.key)
raise ArgumentError, "Right '%s' already exists"
end
@rights << right
sort_rights
right
end
def sort_rights
@rights.sort!
end
# Retrieve a right by name.
def right(name)
self[name]
end
# A right.
class Right < Puppet::Network::AuthStore
include Puppet::FileCollection::Lookup
attr_accessor :name, :key, :acl_type
attr_accessor :methods, :environment, :authentication
ALL = [:save, :destroy, :find, :search]
Puppet::Util.logmethods(self, true)
def initialize(name, line, file)
@methods = []
@environment = []
@authentication = true # defaults to authenticated
@name = name
@line = line || 0
@file = file
case name
when Symbol
@acl_type = :name
@key = name
when /^\[(.+)\]$/
@acl_type = :name
@key = $1.intern if name.is_a?(String)
when /^\//
@acl_type = :regex
@key = Regexp.new("^" + Regexp.escape(name))
@methods = ALL
when /^~/ # this is a regex
@acl_type = :regex
@name = name.gsub(/^~\s+/,'')
@key = Regexp.new(@name)
@methods = ALL
else
raise ArgumentError, "Unknown right type '#{name}'"
end
super()
end
def to_s
"access[#{@name}]"
end
# There's no real check to do at this point
def valid?
true
end
def regex?
acl_type == :regex
end
# does this right is allowed for this triplet?
# if this right is too restrictive (ie we don't match this access method)
# then return :dunno so that upper layers have a chance to try another right
# tailored to the given method
def allowed?(name, ip, args = {})
return :dunno if acl_type == :regex and not @methods.include?(args[:method])
return :dunno if acl_type == :regex and @environment.size > 0 and not @environment.include?(args[:environment])
return :dunno if acl_type == :regex and (@authentication and not args[:authenticated])
begin
# make sure any capture are replaced if needed
interpolate(args[:match]) if acl_type == :regex and args[:match]
res = super(name,ip)
ensure
reset_interpolation if acl_type == :regex
end
res
end
# restrict this right to some method only
def restrict_method(m)
m = m.intern if m.is_a?(String)
raise ArgumentError, "'#{m}' is not an allowed value for method directive" unless ALL.include?(m)
# if we were allowing all methods, then starts from scratch
if @methods === ALL
@methods = []
end
raise ArgumentError, "'#{m}' is already in the '#{name}' ACL" if @methods.include?(m)
@methods << m
end
def restrict_environment(env)
env = Puppet::Node::Environment.new(env)
raise ArgumentError, "'#{env}' is already in the '#{name}' ACL" if @environment.include?(env)
@environment << env
end
def restrict_authenticated(authentication)
case authentication
when "yes", "on", "true", true
authentication = true
when "no", "off", "false", false, "all" ,"any", :all, :any
authentication = false
else
raise ArgumentError, "'#{name}' incorrect authenticated value: #{authentication}"
end
@authentication = authentication
end
def match?(key)
# if we are a namespace compare directly
return self.key == namespace_to_key(key) if acl_type == :name
# otherwise match with the regex
self.key.match(key)
end
def namespace_to_key(key)
key = key.intern if key.is_a?(String)
key
end
# this is where all the magic happens.
# we're sorting the rights array with this scheme:
# * namespace rights are all in front
# * regex path rights are then all queued in file order
def <=>(rhs)
# move namespace rights at front
return self.acl_type == :name ? -1 : 1 if self.acl_type != rhs.acl_type
# sort by creation order (ie first match appearing in the file will win)
# that is don't sort, in which case the sort algorithm will order in the
# natural array order (ie the creation order)
0
end
def ==(name)
return(acl_type == :name ? self.key == namespace_to_key(name) : self.name == name.gsub(/^~\s+/,''))
end
end
end
end
diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb
index 8918d22e9..b24ee41ae 100644
--- a/lib/puppet/parser/ast.rb
+++ b/lib/puppet/parser/ast.rb
@@ -1,142 +1,142 @@
# the parent class for all of our syntactical objects
require 'puppet'
require 'puppet/util/autoload'
require 'puppet/file_collection/lookup'
# The base class for all of the objects that make up the parse trees.
# Handles things like file name, line #, and also does the initialization
# for all of the parameters of all of the child objects.
class Puppet::Parser::AST
# Do this so I don't have to type the full path in all of the subclasses
AST = Puppet::Parser::AST
include Puppet::FileCollection::Lookup
include Puppet::Util::Errors
include Puppet::Util::MethodHelper
include Puppet::Util::Docs
attr_accessor :parent, :scope
def inspect
"( #{self.class} #{self.to_s} #{@children.inspect} )"
end
# don't fetch lexer comment by default
def use_docs
self.class.use_docs
end
# allow our subclass to specify they want documentation
class << self
attr_accessor :use_docs
def associates_doc
self.use_docs = true
end
end
# Does this ast object set something? If so, it gets evaluated first.
def self.settor?
if defined?(@settor)
@settor
else
false
end
end
# Evaluate the current object. Just a stub method, since the subclass
# should override this method.
# of the contained children and evaluates them in turn, returning a
# list of all of the collected values, rejecting nil values
def evaluate(*options)
raise Puppet::DevError, "Did not override #evaluate in #{self.class}"
end
# Throw a parse error.
def parsefail(message)
self.fail(Puppet::ParseError, message)
end
# Wrap a statemp in a reusable way so we always throw a parse error.
def parsewrap
exceptwrap :type => Puppet::ParseError do
yield
end
end
# The version of the evaluate method that should be called, because it
# correctly handles errors. It is critical to use this method because
# it can enable you to catch the error where it happens, rather than
# much higher up the stack.
def safeevaluate(*options)
# We duplicate code here, rather than using exceptwrap, because this
# is called so many times during parsing.
begin
return self.evaluate(*options)
rescue Puppet::Error => detail
raise adderrorcontext(detail)
rescue => detail
- error = Puppet::Error.new(detail.to_s)
+ error = Puppet::ParseError.new(detail.to_s, nil, nil, detail)
# We can't use self.fail here because it always expects strings,
# not exceptions.
raise adderrorcontext(error, detail)
end
end
# Initialize the object. Requires a hash as the argument, and
# takes each of the parameters of the hash and calls the settor
# method for them. This is probably pretty inefficient and should
# likely be changed at some point.
def initialize(args)
set_options(args)
end
# evaluate ourselves, and match
def evaluate_match(value, scope)
obj = self.safeevaluate(scope)
obj = obj.downcase if obj.respond_to?(:downcase)
value = value.downcase if value.respond_to?(:downcase)
obj = Puppet::Parser::Scope.number?(obj) || obj
value = Puppet::Parser::Scope.number?(value) || value
# "" == undef for case/selector/if
obj == value or (obj == "" and value == :undef) or (obj == :undef and value == "")
end
end
# And include all of the AST subclasses.
require 'puppet/parser/ast/arithmetic_operator'
require 'puppet/parser/ast/astarray'
require 'puppet/parser/ast/asthash'
require 'puppet/parser/ast/boolean_operator'
require 'puppet/parser/ast/branch'
require 'puppet/parser/ast/caseopt'
require 'puppet/parser/ast/casestatement'
require 'puppet/parser/ast/collection'
require 'puppet/parser/ast/collexpr'
require 'puppet/parser/ast/comparison_operator'
require 'puppet/parser/ast/definition'
require 'puppet/parser/ast/else'
require 'puppet/parser/ast/function'
require 'puppet/parser/ast/hostclass'
require 'puppet/parser/ast/ifstatement'
require 'puppet/parser/ast/in_operator'
require 'puppet/parser/ast/leaf'
require 'puppet/parser/ast/match_operator'
require 'puppet/parser/ast/minus'
require 'puppet/parser/ast/node'
require 'puppet/parser/ast/nop'
require 'puppet/parser/ast/not'
require 'puppet/parser/ast/relationship'
require 'puppet/parser/ast/resource'
require 'puppet/parser/ast/resource_defaults'
require 'puppet/parser/ast/resource_instance'
require 'puppet/parser/ast/resource_override'
require 'puppet/parser/ast/resource_reference'
require 'puppet/parser/ast/resourceparam'
require 'puppet/parser/ast/selector'
require 'puppet/parser/ast/tag'
require 'puppet/parser/ast/vardef'
diff --git a/lib/puppet/parser/compiler.rb b/lib/puppet/parser/compiler.rb
index 172ffe67a..85687559f 100644
--- a/lib/puppet/parser/compiler.rb
+++ b/lib/puppet/parser/compiler.rb
@@ -1,489 +1,489 @@
require 'puppet/node'
require 'puppet/resource/catalog'
require 'puppet/util/errors'
require 'puppet/resource/type_collection_helper'
# Maintain a graph of scopes, along with a bunch of data
# about the individual catalog we're compiling.
class Puppet::Parser::Compiler
include Puppet::Util
include Puppet::Util::Errors
include Puppet::Resource::TypeCollectionHelper
def self.compile(node)
# We get these from the environment and only cache them in a thread
# variable for the duration of the compilation. If nothing else is using
# the thread, though, we can leave 'em hanging round with no ill effects,
# and this is safer than cleaning them at the end and assuming that will
# stick until the next entry to this function.
Thread.current[:known_resource_types] = nil
Thread.current[:env_module_directories] = nil
# ...and we actually do the compile now we have caching ready.
new(node).compile.to_resource
rescue => detail
message = "#{detail} on node #{node.name}"
Puppet.log_exception(detail, message)
- raise Puppet::Error, message
+ raise Puppet::Error, message, detail.backtrace
end
attr_reader :node, :facts, :collections, :catalog, :resources, :relationships, :topscope
# Add a collection to the global list.
def add_collection(coll)
@collections << coll
end
def add_relationship(dep)
@relationships << dep
end
# Store a resource override.
def add_override(override)
# If possible, merge the override in immediately.
if resource = @catalog.resource(override.ref)
resource.merge(override)
else
# Otherwise, store the override for later; these
# get evaluated in Resource#finish.
@resource_overrides[override.ref] << override
end
end
# Store a resource in our resource table.
def add_resource(scope, resource)
@resources << resource
# Note that this will fail if the resource is not unique.
@catalog.add_resource(resource)
if resource.type.to_s.downcase != "class" && resource[:stage]
raise ArgumentError, "Only classes can set 'stage'; normal resources like #{resource} cannot change run stage"
end
# Stages should not be inside of classes. They are always a
# top-level container, regardless of where they appear in the
# manifest.
return if resource.type.to_s.downcase == "stage"
# This adds a resource to the class it lexically appears in in the
# manifest.
if resource.type.to_s.downcase != "class"
return @catalog.add_edge(scope.resource, resource)
end
end
# Do we use nodes found in the code, vs. the external node sources?
def ast_nodes?
known_resource_types.nodes?
end
# Store the fact that we've evaluated a class
def add_class(name)
@catalog.add_class(name) unless name == ""
end
# Return a list of all of the defined classes.
def classlist
@catalog.classes
end
# Compiler our catalog. This mostly revolves around finding and evaluating classes.
# This is the main entry into our catalog.
def compile
# Set the client's parameters into the top scope.
set_node_parameters
create_settings_scope
evaluate_main
evaluate_ast_node
evaluate_node_classes
evaluate_generators
finish
fail_on_unevaluated
@catalog
end
# LAK:FIXME There are no tests for this.
def delete_collection(coll)
@collections.delete(coll) if @collections.include?(coll)
end
# Return the node's environment.
def environment
unless defined?(@environment)
@environment = (node.environment and node.environment != "") ? node.environment : nil
end
Puppet::Node::Environment.current = @environment
@environment
end
# Evaluate all of the classes specified by the node.
def evaluate_node_classes
evaluate_classes(@node.classes, @node_scope || topscope)
end
# Evaluate each specified class in turn. If there are any classes we can't
# find, raise an error. This method really just creates resource objects
# that point back to the classes, and then the resources are themselves
# evaluated later in the process.
#
# Sometimes we evaluate classes with a fully qualified name already, in which
# case, we tell scope.find_hostclass we've pre-qualified the name so it
# doesn't need to search it's namespaces again. This gets around a weird
# edge case of duplicate class names, one at top scope and one nested in our
# namespace and the wrong one (or both!) getting selected. See ticket #13349
# for more detail. --jeffweiss 26 apr 2012
def evaluate_classes(classes, scope, lazy_evaluate = true, fqname = false)
raise Puppet::DevError, "No source for scope passed to evaluate_classes" unless scope.source
class_parameters = nil
# if we are a param class, save the classes hash
# and transform classes to be the keys
if classes.class == Hash
class_parameters = classes
classes = classes.keys
end
classes.each do |name|
# If we can find the class, then make a resource that will evaluate it.
if klass = scope.find_hostclass(name, :assume_fqname => fqname)
# If parameters are passed, then attempt to create a duplicate resource
# so the appropriate error is thrown.
if class_parameters
resource = klass.ensure_in_catalog(scope, class_parameters[name] || {})
else
next if scope.class_scope(klass)
resource = klass.ensure_in_catalog(scope)
end
# If they've disabled lazy evaluation (which the :include function does),
# then evaluate our resource immediately.
resource.evaluate unless lazy_evaluate
else
raise Puppet::Error, "Could not find class #{name} for #{node.name}"
end
end
end
def evaluate_relationships
@relationships.each { |rel| rel.evaluate(catalog) }
end
# Return a resource by either its ref or its type and title.
def findresource(*args)
@catalog.resource(*args)
end
def initialize(node, options = {})
@node = node
options.each do |param, value|
begin
send(param.to_s + "=", value)
rescue NoMethodError
raise ArgumentError, "Compiler objects do not accept #{param}"
end
end
initvars
end
# Create a new scope, with either a specified parent scope or
# using the top scope.
def newscope(parent, options = {})
parent ||= topscope
options[:compiler] = self
scope = Puppet::Parser::Scope.new(options)
scope.parent = parent
scope
end
# Return any overrides for the given resource.
def resource_overrides(resource)
@resource_overrides[resource.ref]
end
private
# If ast nodes are enabled, then see if we can find and evaluate one.
def evaluate_ast_node
return unless ast_nodes?
# Now see if we can find the node.
astnode = nil
@node.names.each do |name|
break if astnode = known_resource_types.node(name.to_s.downcase)
end
unless (astnode ||= known_resource_types.node("default"))
raise Puppet::ParseError, "Could not find default node or by name with '#{node.names.join(", ")}'"
end
# Create a resource to model this node, and then add it to the list
# of resources.
resource = astnode.ensure_in_catalog(topscope)
resource.evaluate
@node_scope = topscope.class_scope(astnode)
end
# Evaluate our collections and return true if anything returned an object.
# The 'true' is used to continue a loop, so it's important.
def evaluate_collections
return false if @collections.empty?
found_something = false
exceptwrap do
# We have to iterate over a dup of the array because
# collections can delete themselves from the list, which
# changes its length and causes some collections to get missed.
@collections.dup.each do |collection|
found_something = true if collection.evaluate
end
end
found_something
end
# Make sure all of our resources have been evaluated into native resources.
# We return true if any resources have, so that we know to continue the
# evaluate_generators loop.
def evaluate_definitions
exceptwrap do
!unevaluated_resources.each { |resource| resource.evaluate }.empty?
end
end
# Iterate over collections and resources until we're sure that the whole
# compile is evaluated. This is necessary because both collections
# and defined resources can generate new resources, which themselves could
# be defined resources.
def evaluate_generators
count = 0
loop do
done = true
# Call collections first, then definitions.
done = false if evaluate_collections
done = false if evaluate_definitions
break if done
count += 1
if count > 1000
raise Puppet::ParseError, "Somehow looped more than 1000 times while evaluating host catalog"
end
end
end
# Find and evaluate our main object, if possible.
def evaluate_main
@main = known_resource_types.find_hostclass([""], "") || known_resource_types.add(Puppet::Resource::Type.new(:hostclass, ""))
@topscope.source = @main
@main_resource = Puppet::Parser::Resource.new("class", :main, :scope => @topscope, :source => @main)
@topscope.resource = @main_resource
add_resource(@topscope, @main_resource)
@main_resource.evaluate
end
# Make sure the entire catalog is evaluated.
def fail_on_unevaluated
fail_on_unevaluated_overrides
fail_on_unevaluated_resource_collections
end
# If there are any resource overrides remaining, then we could
# not find the resource they were supposed to override, so we
# want to throw an exception.
def fail_on_unevaluated_overrides
remaining = []
@resource_overrides.each do |name, overrides|
remaining.concat overrides
end
unless remaining.empty?
fail Puppet::ParseError,
"Could not find resource(s) %s for overriding" % remaining.collect { |o|
o.ref
}.join(", ")
end
end
# Make sure we don't have any remaining collections that specifically
# look for resources, because we want to consider those to be
# parse errors.
def fail_on_unevaluated_resource_collections
remaining = []
@collections.each do |coll|
# We're only interested in the 'resource' collections,
# which result from direct calls of 'realize'. Anything
# else is allowed not to return resources.
# Collect all of them, so we have a useful error.
if r = coll.resources
if r.is_a?(Array)
remaining += r
else
remaining << r
end
end
end
raise Puppet::ParseError, "Failed to realize virtual resources #{remaining.join(', ')}" unless remaining.empty?
end
# Make sure all of our resources and such have done any last work
# necessary.
def finish
evaluate_relationships
resources.each do |resource|
# Add in any resource overrides.
if overrides = resource_overrides(resource)
overrides.each do |over|
resource.merge(over)
end
# Remove the overrides, so that the configuration knows there
# are none left.
overrides.clear
end
resource.finish if resource.respond_to?(:finish)
end
add_resource_metaparams
end
def add_resource_metaparams
unless main = catalog.resource(:class, :main)
raise "Couldn't find main"
end
names = []
Puppet::Type.eachmetaparam do |name|
next if Puppet::Parser::Resource.relationship_parameter?(name)
names << name
end
data = {}
catalog.walk(main, :out) do |source, target|
if source_data = data[source] || metaparams_as_data(source, names)
# only store anything in the data hash if we've actually got
# data
data[source] ||= source_data
source_data.each do |param, value|
target[param] = value if target[param].nil?
end
data[target] = source_data.merge(metaparams_as_data(target, names))
end
target.tag(*(source.tags))
end
end
def metaparams_as_data(resource, params)
data = nil
params.each do |param|
unless resource[param].nil?
# Because we could be creating a hash for every resource,
# and we actually probably don't often have any data here at all,
# we're optimizing a bit by only creating a hash if there's
# any data to put in it.
data ||= {}
data[param] = resource[param]
end
end
data
end
# Set up all of our internal variables.
def initvars
# The list of objects that will available for export.
@exported_resources = {}
# The list of overrides. This is used to cache overrides on objects
# that don't exist yet. We store an array of each override.
@resource_overrides = Hash.new do |overs, ref|
overs[ref] = []
end
# The list of collections that have been created. This is a global list,
# but they each refer back to the scope that created them.
@collections = []
# The list of relationships to evaluate.
@relationships = []
# For maintaining the relationship between scopes and their resources.
@catalog = Puppet::Resource::Catalog.new(@node.name)
@catalog.version = known_resource_types.version
@catalog.environment = @node.environment.to_s
# Create our initial scope and a resource that will evaluate main.
@topscope = Puppet::Parser::Scope.new(:compiler => self)
@main_stage_resource = Puppet::Parser::Resource.new("stage", :main, :scope => @topscope)
@catalog.add_resource(@main_stage_resource)
# local resource array to maintain resource ordering
@resources = []
# Make sure any external node classes are in our class list
if @node.classes.class == Hash
@catalog.add_class(*@node.classes.keys)
else
@catalog.add_class(*@node.classes)
end
end
# Set the node's parameters into the top-scope as variables.
def set_node_parameters
node.parameters.each do |param, value|
@topscope[param] = value
end
# These might be nil.
catalog.client_version = node.parameters["clientversion"]
catalog.server_version = node.parameters["serverversion"]
end
def create_settings_scope
unless settings_type = environment.known_resource_types.hostclass("settings")
settings_type = Puppet::Resource::Type.new :hostclass, "settings"
environment.known_resource_types.add(settings_type)
end
settings_resource = Puppet::Parser::Resource.new("class", "settings", :scope => @topscope)
@catalog.add_resource(settings_resource)
settings_type.evaluate_code(settings_resource)
scope = @topscope.class_scope(settings_type)
Puppet.settings.each do |name, setting|
next if name.to_s == "name"
scope[name.to_s] = environment[name]
end
end
# Return an array of all of the unevaluated resources. These will be definitions,
# which need to get evaluated into native resources.
def unevaluated_resources
# The order of these is significant for speed due to short-circuting
resources.reject { |resource| resource.evaluated? or resource.virtual? or resource.builtin_type? }
end
end
diff --git a/lib/puppet/parser/parser.rb b/lib/puppet/parser/parser.rb
index 828a9ddf7..b431b4144 100644
--- a/lib/puppet/parser/parser.rb
+++ b/lib/puppet/parser/parser.rb
@@ -1,2553 +1,2552 @@
#
# DO NOT MODIFY!!!!
# This file is automatically generated by Racc 1.4.8
# from Racc grammer file "".
#
require 'racc/parser.rb'
require 'puppet'
require 'puppet/util/loadedfile'
require 'puppet/parser/lexer'
require 'puppet/parser/ast'
module Puppet
- class ParseError < Puppet::Error; end
class ImportError < Racc::ParseError; end
class AlreadyImportedError < ImportError; end
end
module Puppet
module Parser
class Parser < Racc::Parser
module_eval(<<'...end grammar.ra/module_eval...', 'grammar.ra', 806)
# It got too annoying having code in a file that needs to be compiled.
require 'puppet/parser/parser_support'
# Make emacs happy
# Local Variables:
# mode: ruby
# End:
...end grammar.ra/module_eval...
##### State transition tables begin ###
clist = [
'9,13,167,168,103,155,372,103,249,105,173,344,90,250,373,142,146,333',
'275,314,-183,-177,106,154,137,139,143,145,40,94,48,1,315,10,12,174,21',
'29,35,332,44,49,2,9,13,15,102,138,141,34,272,148,149,132,133,135,136',
'331,140,144,33,9,13,306,-184,134,8,98,275,300,99,40,352,48,1,369,10',
'12,368,21,29,35,339,44,49,2,9,13,15,33,297,298,34,399,64,117,297,298',
'29,222,9,13,49,33,9,13,15,161,72,8,34,53,-112,-96,40,54,48,1,345,10',
'12,33,21,29,35,154,44,49,2,9,13,15,275,362,-178,34,330,64,160,94,179',
'29,75,9,13,49,33,294,-179,15,342,178,8,34,53,293,183,40,54,48,1,-129',
'10,12,33,21,29,35,179,44,49,2,9,13,15,336,72,98,34,178,99,160,132,133',
'183,140,144,140,144,33,9,13,134,53,134,8,155,54,-196,33,205,206,208',
'189,191,64,195,197,200,239,243,-177,207,247,154,9,13,15,-176,199,202',
'244,397,64,249,179,337,29,222,250,303,49,33,9,13,15,178,190,194,34,327',
'183,326,40,283,48,1,282,10,12,33,21,29,35,119,44,49,2,9,13,15,179,140',
'144,34,318,64,-123,334,134,29,222,178,94,49,33,53,183,15,340,54,8,34',
'275,300,154,40,15,48,1,310,10,12,33,21,29,35,309,44,49,2,9,13,15,307',
'305,323,34,384,369,86,98,368,-130,99,303,142,146,33,84,85,307,292,356',
'8,137,139,143,145,40,287,48,1,33,10,12,284,21,29,35,359,44,49,2,9,13',
'15,33,138,141,34,349,148,149,132,133,135,136,33,140,144,33,9,13,248',
'365,134,8,-130,-130,-130,-130,40,-122,48,1,232,10,12,366,21,29,35,225',
'44,49,2,9,13,15,188,105,374,34,172,64,132,133,123,29,222,140,144,49',
'33,9,13,15,134,316,8,34,377,275,276,40,378,48,1,117,10,12,33,21,29,35',
'-182,44,49,2,9,13,15,-180,382,-178,34,395,64,53,-181,-179,29,129,301',
'44,49,33,275,300,15,278,385,8,34,275,276,-176,40,-183,48,1,386,10,12',
'33,21,29,35,86,44,49,2,9,13,15,123,296,-229,34,297,298,121,9,13,388',
'119,72,117,78,33,-40,-40,-40,-40,391,8,59,60,61,57,40,-178,48,1,65,10',
'12,393,21,29,35,303,44,49,2,64,-179,15,109,29,75,34,107,49,92,56,400',
'15,68,9,13,34,33,72,83,78,401,,8,9,13,,33,72,,78,,,,9,13,65,,72,,78',
'-38,-38,-38,-38,,65,64,,,,29,75,,,49,65,64,,15,68,29,75,34,,49,83,64',
',15,68,29,75,34,33,49,83,,,15,68,9,13,34,33,72,83,78,,,,9,13,,33,113',
',-196,,,,9,13,65,,72,,78,-44,-44,-44,-44,,112,64,,,,29,75,,,49,65,64',
',15,68,29,75,34,,49,83,64,,15,,29,75,34,33,49,,,,15,68,9,13,34,33,72',
'83,78,,,,9,13,,33,72,,78,,,,9,13,65,,72,,78,59,60,61,57,,65,64,,,,29',
'75,,,49,65,64,,15,68,29,75,34,,49,83,64,,15,68,29,75,34,33,49,83,,,15',
'68,9,13,34,33,72,83,78,,,,9,13,,33,72,,78,,,,9,13,65,,72,,,,148,149',
'132,133,65,64,,140,144,29,75,,,49,134,64,,15,68,29,75,34,,49,83,64,',
'15,68,29,75,34,33,49,83,,,15,,9,13,34,33,72,,78,,,,9,13,,33,72,,78,',
',,9,13,65,,72,,78,,,,,,65,64,,,,29,75,,,49,65,64,,15,68,29,75,34,,49',
'83,64,,15,68,29,75,34,33,49,83,9,13,15,68,72,,34,33,,83,9,13,,,72,152',
'78,33,,,9,13,,,72,,78,,,,9,13,65,64,72,,78,29,222,,,49,65,64,,15,,29',
'75,34,,49,65,64,,15,68,29,75,34,33,49,83,64,,15,68,29,75,34,33,49,83',
',,15,68,9,13,34,33,72,83,78,,,,9,13,,33,72,,78,,,,9,13,65,,72,,78,,',
',,,65,64,,,,29,75,,,49,65,64,,15,68,29,75,34,,49,83,64,,15,68,29,75',
'34,33,49,83,,,15,68,9,13,34,33,72,83,78,,,,9,13,,33,72,,78,,,,9,13,65',
',72,,78,,,,,,65,64,,,,29,75,,,49,65,64,,15,68,29,75,34,,49,83,64,,15',
'68,29,75,34,33,49,83,,,15,68,9,13,34,33,72,83,78,,,,9,13,,33,72,,78',
',,,9,13,65,,72,,78,,,,,,65,64,,,,29,75,,,49,65,64,,15,68,29,75,34,,49',
'83,64,,15,68,29,75,34,33,49,83,,,15,68,9,13,34,33,72,83,78,,,,9,13,',
'33,72,,78,148,149,132,133,,65,,140,144,,,,,,134,65,64,9,13,,29,75,,',
'49,,64,,15,68,29,75,34,,49,83,,,15,68,,,34,33,,83,,,,,64,53,,33,29,129',
',44,49,9,13,,15,72,,78,34,,,9,13,,,72,,78,,33,,,,65,,,,,,,,,,65,64,',
',,29,75,,,49,,64,,15,68,29,75,34,,49,83,285,,15,68,,,34,33,,83,142,146',
',,,,,33,,137,139,143,145,,,,,,9,13,9,13,,,72,371,78,,,,,,138,141,,,148',
'149,132,133,135,136,65,140,144,,,,9,13,134,64,72,64,78,29,222,29,75',
'49,,49,,15,,15,68,34,,34,65,,83,9,13,,,72,33,78,33,64,,,,29,75,,,49',
',,,15,68,65,,34,9,13,83,,72,,78,,64,,33,,29,75,,,49,9,13,,15,68,65,223',
'34,,,83,,,,,,64,,33,,29,75,,,49,,,,15,68,9,13,34,64,72,83,78,29,222',
',,49,,33,,15,,,,34,9,13,65,279,72,,78,,,,33,,,64,,,,29,75,,,49,65,226',
',15,68,,,34,,,83,64,,,,29,75,,33,49,,,,15,68,,,34,9,13,83,,72,152,78',
',,,33,,,,,,,9,13,,,72,65,78,,,,,,,,,,64,,,,29,75,65,,49,,,,15,68,,,34',
'64,,83,,29,75,,,49,,33,,15,68,9,13,34,,72,83,78,,,,9,13,,33,72,,78,',
',,9,13,65,,72,,78,,,,,,65,64,,,,29,75,,,49,65,64,,15,68,29,75,34,,49',
'83,64,,15,68,29,75,34,33,49,83,,,15,68,9,13,34,33,72,83,78,,,,9,13,',
'33,72,,78,,,,,,65,,,,,,,,,,65,64,,,,29,75,,,49,,64,,15,68,29,75,34,',
'49,83,,230,15,68,,,34,33,,83,142,146,,,,,147,33,,137,139,143,145,,,142',
'146,,,,,,,,137,139,143,145,,,,,138,141,,,148,149,132,133,135,136,,140',
'144,,,138,141,,134,148,149,132,133,135,136,229,140,144,,,,,,134,142',
'146,,,,,,,,137,139,143,145,,,142,146,,,,,,,,137,139,143,145,,,,,138',
'141,,,148,149,132,133,135,136,,140,144,,,138,141,,134,148,149,132,133',
'135,136,,140,144,142,146,,,,134,,,,137,139,143,145,,,142,146,,,,,,,',
'137,139,143,145,,,,,138,141,,,148,149,132,133,135,136,,140,144,,,138',
'141,,134,148,149,132,133,135,136,,140,144,142,146,,,,134,,,,137,139',
'143,145,,,142,146,,,,,,,,137,139,143,145,,,,,138,141,,,148,149,132,133',
'135,136,,140,144,,,138,141,,134,148,149,132,133,135,136,,140,144,142',
'146,,,,134,,,,137,139,143,145,,,142,146,,,,,,,,137,139,143,145,,,,,',
'141,,,148,149,132,133,135,136,,140,144,,,,,,134,148,149,132,133,135',
'136,,140,144,142,146,,,,134,,,,137,139,143,145,,,142,146,,,,,,,,137',
'139,143,145,,,,,,,,,148,149,132,133,135,136,,140,144,,,138,141,,134',
'148,149,132,133,135,136,,140,144,142,146,,,,134,,,,137,139,143,145,',
',142,146,,,,,,,,137,139,143,145,,,,,138,141,,,148,149,132,133,135,136',
',140,144,,,138,141,,134,148,149,132,133,135,136,,140,144,142,146,,,',
'134,,,,137,139,143,145,,,142,146,,,,,,,,137,139,143,145,,,,,138,141',
',,148,149,132,133,135,136,,140,144,,,138,141,,134,148,149,132,133,135',
'136,,140,144,142,146,,,,134,,,,137,139,143,145,,,142,146,,,,,,,254,137',
'139,143,145,,,,,,,146,,148,149,132,133,135,136,137,140,144,,,138,141',
'146,134,148,149,132,133,135,136,137,140,144,,,,,,134,,146,,148,149,132',
'133,135,136,137,140,144,,,,,146,134,148,149,132,133,135,136,137,140',
'144,,,,,,134,,,,148,149,132,133,135,136,,140,144,,,,,,134,148,149,132',
'133,135,136,,140,144,205,206,208,189,191,134,195,197,200,201,203,,207',
'209,,,,,,199,202,204,205,206,208,189,191,,195,197,200,201,215,,207,209',
',190,194,,,199,202,204,205,206,208,189,191,,195,197,200,201,215,,207',
'209,,190,194,,,199,202,204,205,206,208,189,191,,195,197,200,201,203',
',207,209,,190,194,,,199,202,204,205,206,208,189,191,,195,197,200,201',
'215,,207,209,,190,194,,,199,202,204,205,206,208,189,191,,195,197,200',
'201,203,,207,209,,190,194,,,199,202,204,148,149,132,133,135,136,,140',
'144,,,,,,134,190,194,148,149,132,133,135,136,,140,144,,,,,,134' ]
racc_action_table = arr = ::Array.new(2463, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
arr[idx] = i.to_i unless i.empty?
idx += 1
end
end
clist = [
'0,0,88,88,71,75,321,23,123,23,95,286,14,123,321,88,88,251,227,227,14',
'71,23,75,88,88,88,88,0,21,0,0,227,0,0,95,0,0,0,250,0,0,0,147,147,0,23',
'88,88,0,147,88,88,88,88,88,88,249,88,88,0,230,230,210,247,88,0,21,280',
'280,21,147,295,147,147,318,147,147,318,147,147,147,280,147,147,147,393',
'393,147,21,210,210,147,393,230,246,295,295,230,230,78,78,230,147,225',
'225,230,78,225,147,230,287,243,244,393,287,393,393,287,393,393,230,393',
'393,393,243,393,393,393,248,248,393,312,312,242,393,248,225,78,174,299',
'225,225,282,282,225,393,177,240,225,282,299,393,225,12,177,299,248,12',
'248,248,239,248,248,225,248,248,248,179,248,248,248,121,121,248,271',
'121,174,248,179,174,282,273,273,179,255,255,273,273,248,372,372,255',
'1,273,248,129,1,129,174,121,121,121,121,121,121,121,121,121,121,121',
'238,121,121,129,391,391,121,237,121,121,121,391,372,334,102,276,372',
'372,334,236,372,121,223,223,372,102,121,121,372,235,102,233,391,156',
'391,391,156,391,391,372,391,391,391,232,391,391,391,229,229,391,106',
'256,256,391,229,223,226,252,256,223,223,106,173,223,391,22,106,223,281',
'22,391,223,281,281,222,229,22,229,229,219,229,229,223,229,229,229,215',
'229,229,229,344,344,229,212,198,231,229,344,366,10,173,366,316,173,193',
'231,231,229,10,10,302,175,304,229,231,231,231,231,344,166,344,344,173',
'344,344,158,344,344,344,308,344,344,344,292,292,344,144,231,231,344',
'292,231,231,231,231,231,231,140,231,231,344,363,363,122,314,231,344',
'316,316,316,316,292,315,292,292,118,292,292,317,292,292,292,110,292',
'292,292,26,26,292,104,100,325,292,92,363,274,274,87,363,363,274,274',
'363,292,58,58,363,274,228,292,363,328,228,228,26,329,26,26,82,26,26',
'363,26,26,26,81,26,26,26,383,383,26,79,335,77,26,383,58,58,74,73,58',
'58,187,58,58,26,187,187,58,153,348,26,58,153,153,69,383,67,383,383,354',
'383,383,58,383,383,383,64,383,383,383,270,270,383,55,184,362,383,184',
'184,50,40,40,364,48,40,45,40,383,4,4,4,4,369,383,5,5,5,5,270,36,270',
'270,40,270,270,373,270,270,270,376,270,270,270,40,30,270,28,40,40,270',
'24,40,20,2,396,40,40,284,284,40,270,284,40,284,398,,270,13,13,,40,13',
',13,,,,145,145,284,,145,,145,47,47,47,47,,13,284,,,,284,284,,,284,145',
'13,,284,284,13,13,284,,13,284,145,,13,13,145,145,13,284,145,13,,,145',
'145,309,309,145,13,309,145,309,,,,35,35,,145,35,,35,,,,44,44,309,,44',
',44,11,11,11,11,,35,309,,,,309,309,,,309,44,35,,309,309,35,35,309,,35',
'309,44,,35,,44,44,35,309,44,,,,44,44,368,368,44,35,368,44,368,,,,143',
'143,,44,143,,143,,,,142,142,368,,142,,142,16,16,16,16,,143,368,,,,368',
'368,,,368,142,143,,368,368,143,143,368,,143,368,142,,143,143,142,142',
'143,368,142,143,,,142,142,65,65,142,143,65,142,65,,,,141,141,,142,141',
',141,,,,310,310,65,,310,,,,259,259,259,259,141,65,,259,259,65,65,,,65',
'259,141,,65,65,141,141,65,,141,65,310,,141,141,310,310,141,65,310,141',
',,310,,68,68,310,141,68,,68,,,,139,139,,310,139,,139,,,,293,293,68,',
'293,,293,,,,,,139,68,,,,68,68,,,68,293,139,,68,68,139,139,68,,139,68',
'293,,139,139,293,293,139,68,293,139,326,326,293,293,326,,293,139,,293',
'72,72,,,72,72,72,293,,,277,277,,,277,,277,,,,138,138,72,326,138,,138',
'326,326,,,326,277,72,,326,,72,72,326,,72,138,277,,72,72,277,277,72,326',
'277,72,138,,277,277,138,138,277,72,138,277,,,138,138,294,294,138,277',
'294,138,294,,,,137,137,,138,137,,137,,,,332,332,294,,332,,332,,,,,,137',
'294,,,,294,294,,,294,332,137,,294,294,137,137,294,,137,294,332,,137',
'137,332,332,137,294,332,137,,,332,332,331,331,332,137,331,332,331,,',
',83,83,,332,83,,83,,,,84,84,331,,84,,84,,,,,,83,331,,,,331,331,,,331',
'84,83,,331,331,83,83,331,,83,331,84,,83,83,84,84,83,331,84,83,,,84,84',
'85,85,84,83,85,84,85,,,,86,86,,84,86,,86,,,,136,136,85,,136,,136,,,',
',,86,85,,,,85,85,,,85,136,86,,85,85,86,86,85,,86,85,136,,86,86,136,136',
'86,85,136,86,,,136,136,8,8,136,86,8,136,8,,,,90,90,,136,90,,90,258,258',
'258,258,,8,,258,258,,,,,,258,90,8,91,91,,8,8,,,8,,90,,8,8,90,90,8,,90',
'8,,,90,90,,,90,8,,90,,,,,91,91,,90,91,91,,91,91,167,167,,91,167,,167',
'91,,,305,305,,,305,,305,,91,,,,167,,,,,,,,,,305,167,,,,167,167,,,167',
',305,,167,167,305,305,167,,305,167,165,,305,305,,,305,167,,305,165,165',
',,,,,305,,165,165,165,165,,,,,,319,319,103,103,,,103,319,103,,,,,,165',
'165,,,165,165,165,165,165,165,103,165,165,,,,135,135,165,319,135,103',
'135,319,319,103,103,319,,103,,319,,103,103,319,,103,135,,103,134,134',
',,134,319,134,103,135,,,,135,135,,,135,,,,135,135,134,,135,155,155,135',
',155,,155,,134,,135,,134,134,,,134,109,109,,134,134,155,109,134,,,134',
',,,,,155,,134,,155,155,,,155,,,,155,155,154,154,155,109,154,155,154',
'109,109,,,109,,155,,109,,,,109,112,112,154,154,112,,112,,,,109,,,154',
',,,154,154,,,154,112,112,,154,154,,,154,,,154,112,,,,112,112,,154,112',
',,,112,112,,,112,113,113,112,,113,113,113,,,,112,,,,,,,133,133,,,133',
'113,133,,,,,,,,,,113,,,,113,113,133,,113,,,,113,113,,,113,133,,113,',
'133,133,,,133,,113,,133,133,132,132,133,,132,133,132,,,,117,117,,133',
'117,,117,,,,148,148,132,,148,,148,,,,,,117,132,,,,132,132,,,132,148',
'117,,132,132,117,117,132,,117,132,148,,117,117,148,148,117,132,148,117',
',,148,148,149,149,148,117,149,148,149,,,,146,146,,148,146,,146,,,,,',
'149,,,,,,,,,,146,149,,,,149,149,,,149,,146,,149,149,146,146,149,,146',
'149,,116,146,146,,,146,149,,146,116,116,,,,,66,146,,116,116,116,116',
',,66,66,,,,,,,,66,66,66,66,,,,,116,116,,,116,116,116,116,116,116,,116',
'116,,,66,66,,116,66,66,66,66,66,66,114,66,66,,,,,,66,114,114,,,,,,,',
'114,114,114,114,,,343,343,,,,,,,,343,343,343,343,,,,,114,114,,,114,114',
'114,114,114,114,,114,114,,,343,343,,114,343,343,343,343,343,343,,343',
'343,163,163,,,,343,,,,163,163,163,163,,,164,164,,,,,,,,164,164,164,164',
',,,,163,163,,,163,163,163,163,163,163,,163,163,,,164,164,,163,164,164',
'164,164,164,164,,164,164,170,170,,,,164,,,,170,170,170,170,,,338,338',
',,,,,,,338,338,338,338,,,,,170,170,,,170,170,170,170,170,170,,170,170',
',,338,338,,170,338,338,338,338,338,338,,338,338,261,261,,,,338,,,,261',
'261,261,261,,,350,350,,,,,,,,350,350,350,350,,,,,,261,,,261,261,261',
'261,261,261,,261,261,,,,,,261,350,350,350,350,350,350,,350,350,351,351',
',,,350,,,,351,351,351,351,,,151,151,,,,,,,,151,151,151,151,,,,,,,,,351',
'351,351,351,351,351,,351,351,,,151,151,,351,151,151,151,151,151,151',
',151,151,357,357,,,,151,,,,357,357,357,357,,,360,360,,,,,,,,360,360',
'360,360,,,,,357,357,,,357,357,357,357,357,357,,357,357,,,360,360,,357',
'360,360,360,360,360,360,,360,360,379,379,,,,360,,,,379,379,379,379,',
',380,380,,,,,,,,380,380,380,380,,,,,379,379,,,379,379,379,379,379,379',
',379,379,,,380,380,,379,380,380,380,380,380,380,,380,380,264,264,,,',
'380,,,,264,264,264,264,,,131,131,,,,,,,131,131,131,131,131,,,,,,,268',
',264,264,264,264,264,264,268,264,264,,,131,131,262,264,131,131,131,131',
'131,131,262,131,131,,,,,,131,,265,,268,268,268,268,268,268,265,268,268',
',,,,266,268,262,262,262,262,262,262,266,262,262,,,,,,262,,,,265,265',
'265,265,265,265,,265,265,,,,,,265,266,266,266,266,266,266,,266,266,327',
'327,327,327,327,266,327,327,327,327,327,,327,327,,,,,,327,327,327,307',
'307,307,307,307,,307,307,307,307,307,,307,307,,327,327,,,307,307,307',
'107,107,107,107,107,,107,107,107,107,107,,107,107,,307,307,,,107,107',
'107,105,105,105,105,105,,105,105,105,105,105,,105,105,,107,107,,,105',
'105,105,188,188,188,188,188,,188,188,188,188,188,,188,188,,105,105,',
',188,188,188,303,303,303,303,303,,303,303,303,303,303,,303,303,,188',
'188,,,303,303,303,260,260,260,260,260,260,,260,260,,,,,,260,303,303',
'269,269,269,269,269,269,,269,269,,,,,,269' ]
racc_action_check = arr = ::Array.new(2463, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
arr[idx] = i.to_i unless i.empty?
idx += 1
end
end
racc_action_pointer = [
-2, 157, 482, nil, 428, 434, nil, nil, 1137, nil,
304, 561, 118, 538, -3, nil, 628, nil, nil, nil,
525, 27, 240, 1, 515, nil, 385, nil, 496, nil,
494, nil, nil, nil, nil, 605, 479, nil, nil, nil,
481, nil, nil, nil, 615, 482, nil, 494, 484, nil,
474, nil, nil, nil, nil, 452, nil, nil, 403, nil,
nil, nil, nil, nil, 463, 729, 1685, 436, 796, 434,
nil, -2, 869, 418, 417, -1, nil, 412, 98, 410,
nil, 403, 413, 1013, 1023, 1070, 1080, 374, -2, nil,
1147, 1171, 394, nil, nil, -2, nil, nil, nil, nil,
383, nil, 201, 1296, 382, 2335, 237, 2313, nil, 1391,
371, nil, 1441, 1491, 1736, nil, 1670, 1565, 364, nil,
nil, 170, 356, -27, nil, nil, nil, nil, nil, 190,
nil, 2171, 1555, 1508, 1349, 1324, 1090, 946, 889, 806,
296, 739, 682, 672, 285, 548, 1632, 41, 1575, 1622,
nil, 1991, nil, 444, 1421, 1374, 235, nil, 325, nil,
nil, nil, nil, 1796, 1811, 1261, 293, 1213, nil, nil,
1856, nil, nil, 271, 137, 314, nil, 129, nil, 144,
nil, nil, nil, nil, 431, nil, nil, 437, 2357, nil,
nil, nil, nil, 303, nil, nil, nil, nil, 294, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
41, nil, 292, nil, nil, 245, nil, nil, nil, 279,
nil, nil, 261, 231, nil, 102, 244, 7, 402, 256,
59, 299, 252, 201, nil, 220, 218, 195, 188, 138,
125, nil, 111, 101, 90, nil, 89, 41, 127, 42,
24, -8, 256, nil, nil, 125, 202, nil, 1103, 706,
2378, 1916, 2204, nil, 2156, 2222, 2237, nil, 2189, 2395,
471, 166, nil, 127, 341, nil, 219, 879, nil, nil,
57, 272, 141, nil, 528, nil, 3, 75, nil, nil,
nil, nil, 342, 816, 936, 47, nil, nil, nil, 116,
nil, nil, 309, 2379, 314, 1223, nil, 2291, 331, 595,
749, nil, 121, nil, 340, 350, 305, 370, 44, 1294,
nil, -6, nil, nil, nil, 383, 859, 2269, 403, 407,
nil, 1003, 956, nil, 189, 409, nil, nil, 1871, nil,
nil, nil, nil, 1751, 299, nil, nil, nil, 443, nil,
1931, 1976, nil, nil, 453, nil, nil, 2036, nil, nil,
2051, nil, 469, 360, 476, nil, 278, nil, 662, 487,
nil, nil, 188, 500, nil, nil, 500, nil, nil, 2096,
2111, nil, nil, 428, nil, nil, nil, nil, nil, nil,
nil, 213, nil, 84, nil, nil, 518, nil, 528, nil,
nil, nil ]
racc_action_default = [
-205, -242, -74, -19, -8, -20, -9, -185, -242, -124,
-222, -10, -197, -242, -240, -98, -242, -11, -176, -12,
-242, -242, -242, -177, -39, -13, -1, -181, -242, -129,
-41, -14, -2, -230, -96, -97, -42, -15, -3, -180,
-242, -43, -16, -182, -242, -45, -17, -6, -242, -184,
-242, -18, -7, -197, -196, -205, -75, -49, -242, -46,
-47, -48, -142, -141, -222, -242, -242, -240, -242, -59,
-66, -60, -242, -63, -61, -97, -64, -58, -242, -67,
-62, -68, -65, -242, -242, -242, -242, -205, -242, -125,
-242, -242, -242, -204, -202, -205, -198, -200, -201, -203,
-242, -73, -205, -242, -77, -109, -205, -119, -4, -242,
-53, -54, -242, -242, -242, -134, -242, -242, -189, -186,
-187, -109, -242, -206, -207, -40, -44, -37, -39, -97,
-38, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-242, -242, -242, -242, -242, -242, -242, -242, -242, -242,
-159, -56, -225, -242, -242, -242, -242, -234, -242, -238,
-237, -233, -152, -106, -108, -242, -205, -242, -127, -126,
-107, -36, 402, -242, -242, -242, -216, -242, -222, -205,
-90, -89, -80, -97, -242, -81, -83, -242, -119, -25,
-29, -27, -113, -228, -35, -23, -110, -31, -242, -33,
-32, -114, -21, -112, -34, -28, -26, -22, -30, -24,
-242, -117, -228, -118, -120, -112, -183, -177, -179, -242,
-178, -170, -97, -242, -171, -242, -52, -242, -242, -242,
-242, -242, -242, -94, -92, -242, -228, -100, -101, -114,
-103, -104, -99, -97, -34, -102, -105, -24, -242, -215,
-213, -242, -228, -210, -162, -149, -148, -143, -150, -151,
-154, -161, -156, -144, -160, -158, -155, -145, -157, -153,
-5, -242, -133, -146, -147, -226, -227, -242, -223, -123,
-242, -242, -242, -231, -242, -239, -242, -242, -218, -128,
-199, -217, -242, -242, -242, -242, -78, -86, -85, -242,
-227, -131, -228, -229, -242, -242, -79, -229, -242, -242,
-242, -173, -228, -55, -227, -50, -223, -242, -137, -242,
-164, -242, -168, -241, -188, -242, -95, -109, -242, -242,
-191, -242, -242, -208, -229, -242, -132, -224, -57, -122,
-130, -235, -232, -236, -242, -221, -220, -219, -242, -195,
-87, -88, -84, -82, -242, -111, -71, -115, -121, -72,
-116, -175, -227, -242, -242, -51, -137, -136, -242, -242,
-165, -163, -242, -242, -69, -93, -228, -70, -190, -214,
-212, -211, -209, -242, -193, -194, -76, -174, -172, -135,
-138, -242, -169, -242, -91, -192, -242, -140, -242, -167,
-139, -166 ]
racc_goto_table = [
23, 55, 26, 27, 111, 108, 115, 253, 157, 219,
271, 120, 87, 89, 193, 234, 39, 224, 32, 93,
241, 211, 100, 96, 184, 304, 23, 320, 210, 27,
236, 101, 367, 212, 104, 153, 58, 125, 319, 127,
358, 353, 39, 221, 308, 43, 126, 91, 169, 122,
312, 325, 118, 233, 286, 95, 175, 363, 23, 291,
251, 27, 24, 252, 110, 347, 187, 130, 328, 45,
125, 43, 171, 124, 39, 227, 228, 156, 20, 126,
389, 166, nil, nil, 335, nil, nil, nil, 24, nil,
nil, 23, 317, nil, 27, 45, nil, nil, nil, nil,
130, 295, 211, 43, nil, 124, nil, 39, nil, 217,
nil, 329, 27, 176, 302, nil, 370, 280, 281, nil,
128, 238, 18, 219, 27, 39, nil, 45, nil, nil,
322, 311, nil, nil, 354, nil, 43, 39, 263, nil,
nil, nil, 267, nil, 364, nil, nil, 23, 18, nil,
27, nil, nil, 128, 43, 348, nil, nil, nil, nil,
45, nil, nil, 39, nil, nil, 43, 289, nil, nil,
nil, 93, 93, nil, nil, 290, 41, nil, nil, nil,
18, 14, nil, nil, 288, nil, nil, nil, nil, nil,
246, nil, 43, nil, 313, 324, nil, nil, nil, nil,
nil, nil, 41, nil, nil, nil, nil, 14, 394, 24,
nil, nil, 341, 18, nil, nil, 45, 355, 381, 322,
375, 211, nil, 217, 180, 241, 27, nil, 180, 23,
217, 18, 27, 27, 41, nil, 376, nil, nil, 39,
nil, nil, nil, 237, nil, 39, 39, nil, 23, 108,
nil, 27, nil, nil, 396, nil, 398, nil, nil, nil,
nil, nil, nil, 219, 39, nil, nil, 41, 43, 18,
23, 387, 392, 27, 43, 43, nil, nil, nil, 361,
nil, nil, nil, nil, nil, nil, 39, 346, nil, nil,
216, 24, 23, 43, nil, 27, nil, 245, 45, nil,
nil, 180, nil, nil, nil, nil, nil, nil, 39, nil,
24, nil, nil, nil, nil, 43, nil, 45, nil, 217,
nil, nil, 27, 41, nil, nil, 238, nil, 14, 27,
nil, nil, 24, nil, 390, 39, nil, 43, nil, 45,
nil, nil, 39, nil, 23, 18, 383, 27, nil, nil,
nil, 18, 18, nil, 24, nil, nil, nil, nil, nil,
39, 45, 108, 217, 43, nil, 27, nil, nil, nil,
18, 43, 217, nil, nil, 27, nil, nil, nil, 39,
nil, nil, nil, 23, nil, nil, 27, nil, 39, 43,
nil, 23, 18, 23, 27, 246, 27, nil, nil, 39,
nil, 30, nil, nil, 216, 41, 24, 39, 43, 39,
14, 216, nil, 45, 18, nil, nil, 43, nil, nil,
nil, 180, nil, nil, 41, nil, nil, 30, 43, 14,
nil, nil, nil, nil, nil, nil, 43, nil, 43, nil,
nil, 18, nil, nil, nil, 24, 41, nil, 237, nil,
nil, 14, 45, 24, nil, 24, 36, nil, nil, 30,
45, nil, 45, nil, nil, nil, 18, nil, 41, nil,
nil, nil, nil, 14, nil, nil, nil, nil, nil, nil,
nil, nil, 36, nil, nil, 18, nil, nil, nil, nil,
nil, nil, 30, nil, 18, nil, nil, nil, nil, nil,
216, nil, 245, 181, nil, 18, nil, 181, nil, nil,
218, nil, nil, 18, 36, 18, nil, nil, nil, nil,
41, nil, 240, nil, nil, 14, nil, nil, nil, nil,
nil, nil, nil, nil, 159, nil, nil, nil, nil, nil,
nil, nil, nil, nil, 216, nil, nil, 36, 30, nil,
nil, nil, nil, 216, nil, nil, nil, nil, nil, 41,
nil, nil, nil, nil, 14, 220, nil, 41, nil, 41,
nil, nil, 14, nil, 14, nil, nil, 242, nil, nil,
181, 66, nil, nil, nil, nil, 88, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, 36, nil, nil, nil, nil, nil, nil,
nil, nil, nil, 114, nil, nil, nil, 116, nil, nil,
nil, nil, nil, nil, 218, nil, nil, nil, nil, nil,
30, 218, nil, nil, nil, nil, nil, nil, 131, nil,
nil, 150, nil, nil, nil, nil, nil, nil, nil, 30,
nil, nil, nil, nil, nil, nil, 162, 163, 164, 165,
nil, nil, nil, 170, nil, nil, nil, nil, nil, nil,
nil, 30, nil, nil, nil, nil, nil, nil, nil, 220,
nil, nil, nil, nil, nil, 36, 220, nil, nil, nil,
231, nil, nil, 30, nil, nil, nil, nil, nil, nil,
181, nil, nil, nil, 36, 255, 256, 257, 258, 259,
260, 261, 262, nil, 264, 265, 266, nil, 268, 269,
218, 273, 274, nil, nil, nil, 36, 240, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, 159, nil,
88, nil, nil, nil, nil, 30, nil, nil, 36, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, 218, nil, nil, nil, nil, nil,
nil, nil, nil, 218, nil, 220, nil, nil, nil, nil,
nil, nil, 242, nil, 30, nil, nil, nil, nil, nil,
nil, nil, 30, nil, 30, nil, nil, nil, nil, nil,
36, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, 220,
nil, nil, nil, nil, nil, nil, nil, nil, 220, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, 36,
nil, nil, nil, nil, nil, nil, nil, 36, nil, 36,
338, nil, nil, nil, nil, nil, nil, 343, nil, nil,
nil, nil, nil, nil, nil, nil, 350, 351, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, 357, nil,
nil, nil, 360, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, 379, 380, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, 114 ]
racc_goto_check = [
35, 40, 2, 36, 31, 4, 62, 83, 86, 69,
5, 73, 40, 60, 43, 53, 38, 71, 3, 65,
37, 56, 35, 79, 48, 44, 35, 67, 48, 36,
43, 6, 63, 45, 47, 29, 23, 8, 66, 22,
59, 49, 38, 70, 44, 39, 10, 23, 61, 75,
72, 42, 74, 41, 76, 77, 78, 33, 35, 80,
81, 36, 24, 82, 30, 84, 29, 6, 44, 28,
8, 39, 22, 3, 38, 29, 29, 85, 1, 10,
63, 75, nil, nil, 44, nil, nil, nil, 24, nil,
nil, 35, 5, nil, 36, 28, nil, nil, nil, nil,
6, 48, 56, 39, nil, 3, nil, 38, nil, 35,
nil, 5, 36, 3, 45, nil, 67, 29, 29, nil,
24, 35, 34, 69, 36, 38, nil, 28, nil, nil,
69, 71, nil, nil, 44, nil, 39, 38, 65, nil,
nil, nil, 65, nil, 44, nil, nil, 35, 34, nil,
36, nil, nil, 24, 39, 5, nil, nil, nil, nil,
28, nil, nil, 38, nil, nil, 39, 60, nil, nil,
nil, 65, 65, nil, nil, 79, 27, nil, nil, nil,
34, 55, nil, nil, 3, nil, nil, nil, nil, nil,
28, nil, 39, nil, 31, 73, nil, nil, nil, nil,
nil, nil, 27, nil, nil, nil, nil, 55, 44, 24,
nil, nil, 86, 34, nil, nil, 28, 56, 83, 69,
53, 56, nil, 35, 34, 37, 36, nil, 34, 35,
35, 34, 36, 36, 27, nil, 43, nil, nil, 38,
nil, nil, nil, 34, nil, 38, 38, nil, 35, 4,
nil, 36, nil, nil, 5, nil, 5, nil, nil, nil,
nil, nil, nil, 69, 38, nil, nil, 27, 39, 34,
35, 71, 69, 36, 39, 39, nil, nil, nil, 31,
nil, nil, nil, nil, nil, nil, 38, 40, nil, nil,
55, 24, 35, 39, nil, 36, nil, 27, 28, nil,
nil, 34, nil, nil, nil, nil, nil, nil, 38, nil,
24, nil, nil, nil, nil, 39, nil, 28, nil, 35,
nil, nil, 36, 27, nil, nil, 35, nil, 55, 36,
nil, nil, 24, nil, 62, 38, nil, 39, nil, 28,
nil, nil, 38, nil, 35, 34, 2, 36, nil, nil,
nil, 34, 34, nil, 24, nil, nil, nil, nil, nil,
38, 28, 4, 35, 39, nil, 36, nil, nil, nil,
34, 39, 35, nil, nil, 36, nil, nil, nil, 38,
nil, nil, nil, 35, nil, nil, 36, nil, 38, 39,
nil, 35, 34, 35, 36, 28, 36, nil, nil, 38,
nil, 25, nil, nil, 55, 27, 24, 38, 39, 38,
55, 55, nil, 28, 34, nil, nil, 39, nil, nil,
nil, 34, nil, nil, 27, nil, nil, 25, 39, 55,
nil, nil, nil, nil, nil, nil, 39, nil, 39, nil,
nil, 34, nil, nil, nil, 24, 27, nil, 34, nil,
nil, 55, 28, 24, nil, 24, 26, nil, nil, 25,
28, nil, 28, nil, nil, nil, 34, nil, 27, nil,
nil, nil, nil, 55, nil, nil, nil, nil, nil, nil,
nil, nil, 26, nil, nil, 34, nil, nil, nil, nil,
nil, nil, 25, nil, 34, nil, nil, nil, nil, nil,
55, nil, 27, 25, nil, 34, nil, 25, nil, nil,
25, nil, nil, 34, 26, 34, nil, nil, nil, nil,
27, nil, 25, nil, nil, 55, nil, nil, nil, nil,
nil, nil, nil, nil, 26, nil, nil, nil, nil, nil,
nil, nil, nil, nil, 55, nil, nil, 26, 25, nil,
nil, nil, nil, 55, nil, nil, nil, nil, nil, 27,
nil, nil, nil, nil, 55, 26, nil, 27, nil, 27,
nil, nil, 55, nil, 55, nil, nil, 26, nil, nil,
25, 32, nil, nil, nil, nil, 32, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, 26, nil, nil, nil, nil, nil, nil,
nil, nil, nil, 32, nil, nil, nil, 32, nil, nil,
nil, nil, nil, nil, 25, nil, nil, nil, nil, nil,
25, 25, nil, nil, nil, nil, nil, nil, 32, nil,
nil, 32, nil, nil, nil, nil, nil, nil, nil, 25,
nil, nil, nil, nil, nil, nil, 32, 32, 32, 32,
nil, nil, nil, 32, nil, nil, nil, nil, nil, nil,
nil, 25, nil, nil, nil, nil, nil, nil, nil, 26,
nil, nil, nil, nil, nil, 26, 26, nil, nil, nil,
32, nil, nil, 25, nil, nil, nil, nil, nil, nil,
25, nil, nil, nil, 26, 32, 32, 32, 32, 32,
32, 32, 32, nil, 32, 32, 32, nil, 32, 32,
25, 32, 32, nil, nil, nil, 26, 25, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, 26, nil,
32, nil, nil, nil, nil, 25, nil, nil, 26, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, 25, nil, nil, nil, nil, nil,
nil, nil, nil, 25, nil, 26, nil, nil, nil, nil,
nil, nil, 26, nil, 25, nil, nil, nil, nil, nil,
nil, nil, 25, nil, 25, nil, nil, nil, nil, nil,
26, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, 26,
nil, nil, nil, nil, nil, nil, nil, nil, 26, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, 26,
nil, nil, nil, nil, nil, nil, nil, 26, nil, 26,
32, nil, nil, nil, nil, nil, nil, 32, nil, nil,
nil, nil, nil, nil, nil, nil, 32, 32, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, 32, nil,
nil, nil, 32, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, 32, 32, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, 32 ]
racc_goto_pointer = [
nil, 78, 2, 18, -21, -137, 9, nil, -21, nil,
-12, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, -19, 31, 62, 401, 456, 176, 69, -37,
29, -31, 573, -255, 122, 0, 3, -101, 16, 45,
0, -68, -182, -91, -168, -74, nil, 11, -78, -258,
nil, nil, nil, -106, nil, 181, -86, nil, nil, -267,
0, -40, -34, -286, nil, -2, -192, -203, nil, -100,
-66, -92, -173, -37, 4, -6, -112, 34, -39, 2,
-115, -63, -60, -116, -222, -1, -70, nil ]
racc_goto_default = [
nil, nil, 270, 182, 38, nil, 47, 52, 4, 6,
11, 17, 19, 25, 31, 37, 42, 46, 51, 3,
5, 192, 16, nil, 70, 73, 77, 80, 82, nil,
nil, 63, 151, 277, 69, 71, 74, 76, 79, 81,
50, nil, nil, nil, nil, nil, 22, nil, nil, 185,
299, 186, 177, nil, 235, 67, 196, 198, 213, 214,
nil, nil, nil, nil, 62, 7, nil, nil, 321, 28,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
97, nil, nil, nil, nil, nil, nil, 158 ]
racc_reduce_table = [
0, 0, :racc_error,
1, 70, :_reduce_none,
1, 70, :_reduce_none,
1, 71, :_reduce_3,
2, 71, :_reduce_4,
1, 74, :_reduce_5,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 73, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
1, 90, :_reduce_none,
3, 89, :_reduce_36,
3, 89, :_reduce_37,
1, 91, :_reduce_none,
1, 91, :_reduce_none,
1, 91, :_reduce_none,
1, 91, :_reduce_none,
1, 91, :_reduce_none,
1, 91, :_reduce_none,
1, 91, :_reduce_none,
1, 91, :_reduce_none,
1, 92, :_reduce_none,
1, 92, :_reduce_none,
1, 92, :_reduce_none,
1, 92, :_reduce_none,
4, 83, :_reduce_50,
5, 83, :_reduce_51,
3, 83, :_reduce_52,
2, 83, :_reduce_53,
1, 99, :_reduce_54,
3, 99, :_reduce_55,
1, 98, :_reduce_56,
3, 98, :_reduce_57,
1, 100, :_reduce_none,
1, 100, :_reduce_none,
1, 100, :_reduce_none,
1, 100, :_reduce_none,
1, 100, :_reduce_none,
1, 100, :_reduce_none,
1, 100, :_reduce_none,
1, 100, :_reduce_none,
1, 100, :_reduce_none,
1, 100, :_reduce_none,
1, 100, :_reduce_none,
5, 75, :_reduce_69,
5, 75, :_reduce_70,
5, 75, :_reduce_71,
5, 87, :_reduce_72,
2, 76, :_reduce_73,
1, 115, :_reduce_74,
2, 115, :_reduce_75,
6, 77, :_reduce_76,
2, 77, :_reduce_77,
3, 116, :_reduce_78,
3, 116, :_reduce_79,
1, 117, :_reduce_none,
1, 117, :_reduce_none,
3, 117, :_reduce_82,
1, 118, :_reduce_none,
3, 118, :_reduce_84,
1, 119, :_reduce_85,
1, 119, :_reduce_86,
3, 120, :_reduce_87,
3, 120, :_reduce_88,
1, 121, :_reduce_none,
1, 121, :_reduce_none,
4, 122, :_reduce_91,
1, 110, :_reduce_92,
3, 110, :_reduce_93,
0, 111, :_reduce_none,
1, 111, :_reduce_none,
1, 108, :_reduce_96,
1, 103, :_reduce_97,
1, 104, :_reduce_98,
1, 123, :_reduce_none,
1, 123, :_reduce_none,
1, 123, :_reduce_none,
1, 123, :_reduce_none,
1, 123, :_reduce_none,
1, 123, :_reduce_none,
1, 123, :_reduce_none,
3, 78, :_reduce_106,
3, 78, :_reduce_107,
3, 88, :_reduce_108,
0, 112, :_reduce_109,
1, 112, :_reduce_110,
3, 112, :_reduce_111,
1, 126, :_reduce_none,
1, 126, :_reduce_none,
1, 126, :_reduce_none,
3, 125, :_reduce_115,
3, 127, :_reduce_116,
1, 128, :_reduce_none,
1, 128, :_reduce_none,
0, 114, :_reduce_119,
1, 114, :_reduce_120,
3, 114, :_reduce_121,
4, 107, :_reduce_122,
3, 107, :_reduce_123,
1, 95, :_reduce_124,
2, 95, :_reduce_125,
2, 129, :_reduce_126,
1, 130, :_reduce_127,
2, 130, :_reduce_128,
1, 105, :_reduce_129,
4, 93, :_reduce_130,
4, 93, :_reduce_131,
5, 81, :_reduce_132,
4, 81, :_reduce_133,
2, 80, :_reduce_134,
5, 131, :_reduce_135,
4, 131, :_reduce_136,
0, 132, :_reduce_none,
2, 132, :_reduce_138,
4, 132, :_reduce_139,
3, 132, :_reduce_140,
1, 101, :_reduce_none,
1, 101, :_reduce_none,
3, 101, :_reduce_143,
3, 101, :_reduce_144,
3, 101, :_reduce_145,
3, 101, :_reduce_146,
3, 101, :_reduce_147,
3, 101, :_reduce_148,
3, 101, :_reduce_149,
3, 101, :_reduce_150,
3, 101, :_reduce_151,
2, 101, :_reduce_152,
3, 101, :_reduce_153,
3, 101, :_reduce_154,
3, 101, :_reduce_155,
3, 101, :_reduce_156,
3, 101, :_reduce_157,
3, 101, :_reduce_158,
2, 101, :_reduce_159,
3, 101, :_reduce_160,
3, 101, :_reduce_161,
3, 101, :_reduce_162,
5, 79, :_reduce_163,
1, 135, :_reduce_164,
2, 135, :_reduce_165,
5, 136, :_reduce_166,
4, 136, :_reduce_167,
1, 137, :_reduce_168,
3, 137, :_reduce_169,
3, 96, :_reduce_170,
1, 139, :_reduce_none,
4, 139, :_reduce_172,
1, 141, :_reduce_none,
3, 141, :_reduce_174,
3, 140, :_reduce_175,
1, 138, :_reduce_none,
1, 138, :_reduce_none,
1, 138, :_reduce_none,
1, 138, :_reduce_none,
1, 138, :_reduce_none,
1, 138, :_reduce_none,
1, 138, :_reduce_none,
1, 138, :_reduce_none,
1, 138, :_reduce_184,
1, 138, :_reduce_none,
1, 142, :_reduce_186,
1, 143, :_reduce_none,
3, 143, :_reduce_188,
2, 82, :_reduce_189,
6, 84, :_reduce_190,
5, 84, :_reduce_191,
7, 85, :_reduce_192,
6, 85, :_reduce_193,
6, 86, :_reduce_194,
5, 86, :_reduce_195,
1, 109, :_reduce_196,
1, 109, :_reduce_197,
1, 146, :_reduce_198,
3, 146, :_reduce_199,
1, 148, :_reduce_200,
1, 149, :_reduce_201,
1, 149, :_reduce_202,
1, 149, :_reduce_203,
1, 149, :_reduce_none,
0, 72, :_reduce_205,
0, 150, :_reduce_206,
1, 144, :_reduce_none,
3, 144, :_reduce_208,
4, 144, :_reduce_209,
1, 151, :_reduce_none,
3, 151, :_reduce_211,
3, 152, :_reduce_212,
1, 152, :_reduce_213,
3, 152, :_reduce_214,
1, 152, :_reduce_215,
1, 147, :_reduce_none,
2, 147, :_reduce_217,
1, 145, :_reduce_none,
2, 145, :_reduce_219,
1, 153, :_reduce_none,
1, 153, :_reduce_none,
1, 94, :_reduce_222,
3, 106, :_reduce_223,
4, 106, :_reduce_224,
2, 106, :_reduce_225,
1, 102, :_reduce_none,
1, 102, :_reduce_none,
0, 113, :_reduce_none,
1, 113, :_reduce_229,
1, 134, :_reduce_230,
3, 133, :_reduce_231,
4, 133, :_reduce_232,
2, 133, :_reduce_233,
1, 154, :_reduce_none,
3, 154, :_reduce_235,
3, 155, :_reduce_236,
1, 156, :_reduce_237,
1, 156, :_reduce_238,
4, 124, :_reduce_239,
1, 97, :_reduce_none,
4, 97, :_reduce_241 ]
racc_reduce_n = 242
racc_shift_n = 402
racc_token_table = {
false => 0,
:error => 1,
:STRING => 2,
:DQPRE => 3,
:DQMID => 4,
:DQPOST => 5,
:LBRACK => 6,
:RBRACK => 7,
:LBRACE => 8,
:RBRACE => 9,
:SYMBOL => 10,
:FARROW => 11,
:COMMA => 12,
:TRUE => 13,
:FALSE => 14,
:EQUALS => 15,
:APPENDS => 16,
:LESSEQUAL => 17,
:NOTEQUAL => 18,
:DOT => 19,
:COLON => 20,
:LLCOLLECT => 21,
:RRCOLLECT => 22,
:QMARK => 23,
:LPAREN => 24,
:RPAREN => 25,
:ISEQUAL => 26,
:GREATEREQUAL => 27,
:GREATERTHAN => 28,
:LESSTHAN => 29,
:IF => 30,
:ELSE => 31,
:IMPORT => 32,
:DEFINE => 33,
:ELSIF => 34,
:VARIABLE => 35,
:CLASS => 36,
:INHERITS => 37,
:NODE => 38,
:BOOLEAN => 39,
:NAME => 40,
:SEMIC => 41,
:CASE => 42,
:DEFAULT => 43,
:AT => 44,
:LCOLLECT => 45,
:RCOLLECT => 46,
:CLASSREF => 47,
:NOT => 48,
:OR => 49,
:AND => 50,
:UNDEF => 51,
:PARROW => 52,
:PLUS => 53,
:MINUS => 54,
:TIMES => 55,
:DIV => 56,
:LSHIFT => 57,
:RSHIFT => 58,
:UMINUS => 59,
:MATCH => 60,
:NOMATCH => 61,
:REGEX => 62,
:IN_EDGE => 63,
:OUT_EDGE => 64,
:IN_EDGE_SUB => 65,
:OUT_EDGE_SUB => 66,
:IN => 67,
:UNLESS => 68 }
racc_nt_base = 69
racc_use_result_var = true
Racc_arg = [
racc_action_table,
racc_action_check,
racc_action_default,
racc_action_pointer,
racc_goto_table,
racc_goto_check,
racc_goto_default,
racc_goto_pointer,
racc_nt_base,
racc_reduce_table,
racc_token_table,
racc_shift_n,
racc_reduce_n,
racc_use_result_var ]
Racc_token_to_s_table = [
"$end",
"error",
"STRING",
"DQPRE",
"DQMID",
"DQPOST",
"LBRACK",
"RBRACK",
"LBRACE",
"RBRACE",
"SYMBOL",
"FARROW",
"COMMA",
"TRUE",
"FALSE",
"EQUALS",
"APPENDS",
"LESSEQUAL",
"NOTEQUAL",
"DOT",
"COLON",
"LLCOLLECT",
"RRCOLLECT",
"QMARK",
"LPAREN",
"RPAREN",
"ISEQUAL",
"GREATEREQUAL",
"GREATERTHAN",
"LESSTHAN",
"IF",
"ELSE",
"IMPORT",
"DEFINE",
"ELSIF",
"VARIABLE",
"CLASS",
"INHERITS",
"NODE",
"BOOLEAN",
"NAME",
"SEMIC",
"CASE",
"DEFAULT",
"AT",
"LCOLLECT",
"RCOLLECT",
"CLASSREF",
"NOT",
"OR",
"AND",
"UNDEF",
"PARROW",
"PLUS",
"MINUS",
"TIMES",
"DIV",
"LSHIFT",
"RSHIFT",
"UMINUS",
"MATCH",
"NOMATCH",
"REGEX",
"IN_EDGE",
"OUT_EDGE",
"IN_EDGE_SUB",
"OUT_EDGE_SUB",
"IN",
"UNLESS",
"$start",
"program",
"statements_and_declarations",
"nil",
"statement_or_declaration",
"statements",
"resource",
"virtualresource",
"collection",
"assignment",
"casestatement",
"ifstatement_begin",
"unlessstatement",
"import",
"fstatement",
"definition",
"hostclass",
"nodedef",
"resourceoverride",
"append",
"relationship",
"keyword",
"relationship_side",
"edge",
"resourceref",
"variable",
"quotedtext",
"selector",
"hasharrayaccesses",
"expressions",
"funcvalues",
"rvalue",
"expression",
"comma",
"name",
"type",
"boolean",
"array",
"funcrvalue",
"undef",
"classname",
"resourceinstances",
"endsemi",
"params",
"endcomma",
"anyparams",
"at",
"collectrhand",
"collstatements",
"collstatement",
"colljoin",
"collexpr",
"colllval",
"resourceinst",
"resourcename",
"hasharrayaccess",
"param",
"param_name",
"addparam",
"anyparam",
"dqrval",
"dqtail",
"ifstatement",
"else",
"hash",
"regex",
"caseopts",
"caseopt",
"casevalues",
"selectlhand",
"svalues",
"selectval",
"sintvalues",
"string",
"strings",
"argumentlist",
"classparent",
"hostnames",
"nodeparent",
"nodename",
"hostname",
"nothing",
"arguments",
"argument",
"classnameordefault",
"hashpairs",
"hashpair",
"key" ]
Racc_debug_parser = false
##### State transition tables end #####
# reduce 0 omitted
# reduce 1 omitted
# reduce 2 omitted
module_eval(<<'.,.,', 'grammar.ra', 34)
def _reduce_3(val, _values, result)
result = ast AST::ASTArray, :children => (val[0] ? [val[0]] : [])
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 37)
def _reduce_4(val, _values, result)
if val[1]
val[0].push(val[1])
end
result = val[0]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 46)
def _reduce_5(val, _values, result)
val[0].each do |stmt|
if stmt.is_a?(AST::TopLevelConstruct)
error "Classes, definitions, and nodes may only appear at toplevel or inside other classes", \
:line => stmt.context[:line], :file => stmt.context[:file]
end
end
result = val[0]
result
end
.,.,
# reduce 6 omitted
# reduce 7 omitted
# reduce 8 omitted
# reduce 9 omitted
# reduce 10 omitted
# reduce 11 omitted
# reduce 12 omitted
# reduce 13 omitted
# reduce 14 omitted
# reduce 15 omitted
# reduce 16 omitted
# reduce 17 omitted
# reduce 18 omitted
# reduce 19 omitted
# reduce 20 omitted
# reduce 21 omitted
# reduce 22 omitted
# reduce 23 omitted
# reduce 24 omitted
# reduce 25 omitted
# reduce 26 omitted
# reduce 27 omitted
# reduce 28 omitted
# reduce 29 omitted
# reduce 30 omitted
# reduce 31 omitted
# reduce 32 omitted
# reduce 33 omitted
# reduce 34 omitted
# reduce 35 omitted
module_eval(<<'.,.,', 'grammar.ra', 89)
def _reduce_36(val, _values, result)
result = AST::Relationship.new(val[0], val[2], val[1][:value], ast_context)
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 92)
def _reduce_37(val, _values, result)
result = AST::Relationship.new(val[0], val[2], val[1][:value], ast_context)
result
end
.,.,
# reduce 38 omitted
# reduce 39 omitted
# reduce 40 omitted
# reduce 41 omitted
# reduce 42 omitted
# reduce 43 omitted
# reduce 44 omitted
# reduce 45 omitted
# reduce 46 omitted
# reduce 47 omitted
# reduce 48 omitted
# reduce 49 omitted
module_eval(<<'.,.,', 'grammar.ra', 107)
def _reduce_50(val, _values, result)
result = ast AST::Function,
:name => val[0][:value],
:line => val[0][:line],
:arguments => val[2],
:ftype => :statement
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 114)
def _reduce_51(val, _values, result)
result = ast AST::Function,
:name => val[0][:value],
:line => val[0][:line],
:arguments => val[2],
:ftype => :statement
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 120)
def _reduce_52(val, _values, result)
result = ast AST::Function,
:name => val[0][:value],
:line => val[0][:line],
:arguments => AST::ASTArray.new({}),
:ftype => :statement
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 127)
def _reduce_53(val, _values, result)
result = ast AST::Function,
:name => val[0][:value],
:line => val[0][:line],
:arguments => val[1],
:ftype => :statement
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 134)
def _reduce_54(val, _values, result)
result = aryfy(val[0])
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 137)
def _reduce_55(val, _values, result)
val[0].push(val[2])
result = val[0]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 141)
def _reduce_56(val, _values, result)
result = aryfy(val[0])
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 142)
def _reduce_57(val, _values, result)
result = val[0].push(val[2])
result
end
.,.,
# reduce 58 omitted
# reduce 59 omitted
# reduce 60 omitted
# reduce 61 omitted
# reduce 62 omitted
# reduce 63 omitted
# reduce 64 omitted
# reduce 65 omitted
# reduce 66 omitted
# reduce 67 omitted
# reduce 68 omitted
module_eval(<<'.,.,', 'grammar.ra', 157)
def _reduce_69(val, _values, result)
@lexer.commentpop
result = ast(AST::Resource, :type => val[0], :instances => val[2])
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 160)
def _reduce_70(val, _values, result)
# This is a deprecated syntax.
error "All resource specifications require names"
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 163)
def _reduce_71(val, _values, result)
# a defaults setting for a type
@lexer.commentpop
result = ast(AST::ResourceDefaults, :type => val[0].value, :parameters => val[2])
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 170)
def _reduce_72(val, _values, result)
@lexer.commentpop
result = ast AST::ResourceOverride, :object => val[0], :parameters => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 177)
def _reduce_73(val, _values, result)
type = val[0]
if (type == :exported and ! Puppet[:storeconfigs])
Puppet.warning addcontext("You cannot collect without storeconfigs being set")
end
error "Defaults are not virtualizable" if val[1].is_a? AST::ResourceDefaults
method = type.to_s + "="
# Just mark our resource as exported and pass it through.
val[1].send(method, true)
result = val[1]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 193)
def _reduce_74(val, _values, result)
result = :virtual
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 194)
def _reduce_75(val, _values, result)
result = :exported
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 199)
def _reduce_76(val, _values, result)
@lexer.commentpop
type = val[0].value.downcase
args = {:type => type}
if val[1].is_a?(AST::CollExpr)
args[:query] = val[1]
args[:query].type = type
args[:form] = args[:query].form
else
args[:form] = val[1]
end
if args[:form] == :exported and ! Puppet[:storeconfigs]
Puppet.warning addcontext("You cannot collect exported resources without storeconfigs being set; the collection will be ignored")
end
args[:override] = val[3]
result = ast AST::Collection, args
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 217)
def _reduce_77(val, _values, result)
type = val[0].value.downcase
args = {:type => type }
if val[1].is_a?(AST::CollExpr)
args[:query] = val[1]
args[:query].type = type
args[:form] = args[:query].form
else
args[:form] = val[1]
end
if args[:form] == :exported and ! Puppet[:storeconfigs]
Puppet.warning addcontext("You cannot collect exported resources without storeconfigs being set; the collection will be ignored")
end
result = ast AST::Collection, args
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 235)
def _reduce_78(val, _values, result)
if val[1]
result = val[1]
result.form = :virtual
else
result = :virtual
end
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 243)
def _reduce_79(val, _values, result)
if val[1]
result = val[1]
result.form = :exported
else
result = :exported
end
result
end
.,.,
# reduce 80 omitted
# reduce 81 omitted
module_eval(<<'.,.,', 'grammar.ra', 256)
def _reduce_82(val, _values, result)
result = ast AST::CollExpr, :test1 => val[0], :oper => val[1], :test2 => val[2]
result
end
.,.,
# reduce 83 omitted
module_eval(<<'.,.,', 'grammar.ra', 261)
def _reduce_84(val, _values, result)
result = val[1]
result.parens = true
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 265)
def _reduce_85(val, _values, result)
result=val[0][:value]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 266)
def _reduce_86(val, _values, result)
result=val[0][:value]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 269)
def _reduce_87(val, _values, result)
result = ast AST::CollExpr, :test1 => val[0], :oper => val[1][:value], :test2 => val[2]
#result = ast AST::CollExpr
#result.push *val
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 274)
def _reduce_88(val, _values, result)
result = ast AST::CollExpr, :test1 => val[0], :oper => val[1][:value], :test2 => val[2]
#result = ast AST::CollExpr
#result.push *val
result
end
.,.,
# reduce 89 omitted
# reduce 90 omitted
module_eval(<<'.,.,', 'grammar.ra', 283)
def _reduce_91(val, _values, result)
result = ast AST::ResourceInstance, :title => val[0], :parameters => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 286)
def _reduce_92(val, _values, result)
result = aryfy(val[0])
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 288)
def _reduce_93(val, _values, result)
val[0].push val[2]
result = val[0]
result
end
.,.,
# reduce 94 omitted
# reduce 95 omitted
module_eval(<<'.,.,', 'grammar.ra', 296)
def _reduce_96(val, _values, result)
result = ast AST::Undef, :value => :undef
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 300)
def _reduce_97(val, _values, result)
result = ast AST::Name, :value => val[0][:value], :line => val[0][:line]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 304)
def _reduce_98(val, _values, result)
result = ast AST::Type, :value => val[0][:value], :line => val[0][:line]
result
end
.,.,
# reduce 99 omitted
# reduce 100 omitted
# reduce 101 omitted
# reduce 102 omitted
# reduce 103 omitted
# reduce 104 omitted
# reduce 105 omitted
module_eval(<<'.,.,', 'grammar.ra', 316)
def _reduce_106(val, _values, result)
raise Puppet::ParseError, "Cannot assign to variables in other namespaces" if val[0][:value] =~ /::/
# this is distinct from referencing a variable
variable = ast AST::Name, :value => val[0][:value], :line => val[0][:line]
result = ast AST::VarDef, :name => variable, :value => val[2], :line => val[0][:line]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 322)
def _reduce_107(val, _values, result)
result = ast AST::VarDef, :name => val[0], :value => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 326)
def _reduce_108(val, _values, result)
variable = ast AST::Name, :value => val[0][:value], :line => val[0][:line]
result = ast AST::VarDef, :name => variable, :value => val[2], :append => true, :line => val[0][:line]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 332)
def _reduce_109(val, _values, result)
result = ast AST::ASTArray
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 334)
def _reduce_110(val, _values, result)
result = aryfy(val[0])
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 336)
def _reduce_111(val, _values, result)
val[0].push(val[2])
result = val[0]
result
end
.,.,
# reduce 112 omitted
# reduce 113 omitted
# reduce 114 omitted
module_eval(<<'.,.,', 'grammar.ra', 345)
def _reduce_115(val, _values, result)
result = ast AST::ResourceParam, :param => val[0][:value], :line => val[0][:line], :value => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 352)
def _reduce_116(val, _values, result)
result = ast AST::ResourceParam, :param => val[0][:value], :line => val[0][:line], :value => val[2],
:add => true
result
end
.,.,
# reduce 117 omitted
# reduce 118 omitted
module_eval(<<'.,.,', 'grammar.ra', 361)
def _reduce_119(val, _values, result)
result = ast AST::ASTArray
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 363)
def _reduce_120(val, _values, result)
result = aryfy(val[0])
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 365)
def _reduce_121(val, _values, result)
val[0].push(val[2])
result = val[0]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 371)
def _reduce_122(val, _values, result)
result = ast AST::Function,
:name => val[0][:value], :line => val[0][:line],
:arguments => val[2],
:ftype => :rvalue
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 376)
def _reduce_123(val, _values, result)
result = ast AST::Function,
:name => val[0][:value], :line => val[0][:line],
:arguments => AST::ASTArray.new({}),
:ftype => :rvalue
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 382)
def _reduce_124(val, _values, result)
result = ast AST::String, :value => val[0][:value], :line => val[0][:line]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 383)
def _reduce_125(val, _values, result)
result = ast AST::Concat, :value => [ast(AST::String,val[0])]+val[1], :line => val[0][:line]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 385)
def _reduce_126(val, _values, result)
result = [val[0]] + val[1]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 387)
def _reduce_127(val, _values, result)
result = [ast(AST::String,val[0])]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 388)
def _reduce_128(val, _values, result)
result = [ast(AST::String,val[0])] + val[1]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 391)
def _reduce_129(val, _values, result)
result = ast AST::Boolean, :value => val[0][:value], :line => val[0][:line]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 395)
def _reduce_130(val, _values, result)
Puppet.warning addcontext("Deprecation notice: Resource references should now be capitalized")
result = ast AST::ResourceReference, :type => val[0][:value], :line => val[0][:line], :title => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 398)
def _reduce_131(val, _values, result)
result = ast AST::ResourceReference, :type => val[0].value, :title => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 402)
def _reduce_132(val, _values, result)
@lexer.commentpop
args = {
:test => ast(AST::Not, :value => val[1]),
:statements => val[3]
}
result = ast AST::IfStatement, args
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 411)
def _reduce_133(val, _values, result)
@lexer.commentpop
args = {
:test => ast(AST::Not, :value => val[1]),
:statements => ast(AST::Nop)
}
result = ast AST::IfStatement, args
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 420)
def _reduce_134(val, _values, result)
result = val[1]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 424)
def _reduce_135(val, _values, result)
@lexer.commentpop
args = {
:test => val[0],
:statements => val[2]
}
args[:else] = val[4] if val[4]
result = ast AST::IfStatement, args
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 435)
def _reduce_136(val, _values, result)
@lexer.commentpop
args = {
:test => val[0],
:statements => ast(AST::Nop)
}
args[:else] = val[3] if val[3]
result = ast AST::IfStatement, args
result
end
.,.,
# reduce 137 omitted
module_eval(<<'.,.,', 'grammar.ra', 448)
def _reduce_138(val, _values, result)
result = ast AST::Else, :statements => val[1]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 451)
def _reduce_139(val, _values, result)
@lexer.commentpop
result = ast AST::Else, :statements => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 455)
def _reduce_140(val, _values, result)
@lexer.commentpop
result = ast AST::Else, :statements => ast(AST::Nop)
result
end
.,.,
# reduce 141 omitted
# reduce 142 omitted
module_eval(<<'.,.,', 'grammar.ra', 474)
def _reduce_143(val, _values, result)
result = ast AST::InOperator, :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 477)
def _reduce_144(val, _values, result)
result = ast AST::MatchOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 480)
def _reduce_145(val, _values, result)
result = ast AST::MatchOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 483)
def _reduce_146(val, _values, result)
result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 486)
def _reduce_147(val, _values, result)
result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 489)
def _reduce_148(val, _values, result)
result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 492)
def _reduce_149(val, _values, result)
result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 495)
def _reduce_150(val, _values, result)
result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 498)
def _reduce_151(val, _values, result)
result = ast AST::ArithmeticOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 501)
def _reduce_152(val, _values, result)
result = ast AST::Minus, :value => val[1]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 504)
def _reduce_153(val, _values, result)
result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 507)
def _reduce_154(val, _values, result)
result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 510)
def _reduce_155(val, _values, result)
result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 513)
def _reduce_156(val, _values, result)
result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 516)
def _reduce_157(val, _values, result)
result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 519)
def _reduce_158(val, _values, result)
result = ast AST::ComparisonOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 522)
def _reduce_159(val, _values, result)
result = ast AST::Not, :value => val[1]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 525)
def _reduce_160(val, _values, result)
result = ast AST::BooleanOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 528)
def _reduce_161(val, _values, result)
result = ast AST::BooleanOperator, :operator => val[1][:value], :lval => val[0], :rval => val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 531)
def _reduce_162(val, _values, result)
result = val[1]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 535)
def _reduce_163(val, _values, result)
@lexer.commentpop
result = ast AST::CaseStatement, :test => val[1], :options => val[3]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 539)
def _reduce_164(val, _values, result)
result = aryfy(val[0])
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 541)
def _reduce_165(val, _values, result)
val[0].push val[1]
result = val[0]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 546)
def _reduce_166(val, _values, result)
@lexer.commentpop
result = ast AST::CaseOpt, :value => val[0], :statements => val[3]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 549)
def _reduce_167(val, _values, result)
@lexer.commentpop
result = ast(
AST::CaseOpt,
:value => val[0],
:statements => ast(AST::ASTArray)
)
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 559)
def _reduce_168(val, _values, result)
result = aryfy(val[0])
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 561)
def _reduce_169(val, _values, result)
val[0].push(val[2])
result = val[0]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 566)
def _reduce_170(val, _values, result)
result = ast AST::Selector, :param => val[0], :values => val[2]
result
end
.,.,
# reduce 171 omitted
module_eval(<<'.,.,', 'grammar.ra', 571)
def _reduce_172(val, _values, result)
@lexer.commentpop
result = val[1]
result
end
.,.,
# reduce 173 omitted
module_eval(<<'.,.,', 'grammar.ra', 577)
def _reduce_174(val, _values, result)
if val[0].instance_of?(AST::ASTArray)
val[0].push(val[2])
result = val[0]
else
result = ast AST::ASTArray, :children => [val[0],val[2]]
end
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 586)
def _reduce_175(val, _values, result)
result = ast AST::ResourceParam, :param => val[0], :value => val[2]
result
end
.,.,
# reduce 176 omitted
# reduce 177 omitted
# reduce 178 omitted
# reduce 179 omitted
# reduce 180 omitted
# reduce 181 omitted
# reduce 182 omitted
# reduce 183 omitted
module_eval(<<'.,.,', 'grammar.ra', 598)
def _reduce_184(val, _values, result)
result = ast AST::Default, :value => val[0][:value], :line => val[0][:line]
result
end
.,.,
# reduce 185 omitted
module_eval(<<'.,.,', 'grammar.ra', 603)
def _reduce_186(val, _values, result)
result = [val[0][:value]]
result
end
.,.,
# reduce 187 omitted
module_eval(<<'.,.,', 'grammar.ra', 605)
def _reduce_188(val, _values, result)
result = val[0] += val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 608)
def _reduce_189(val, _values, result)
val[1].each do |file|
import(file)
end
result = nil
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 618)
def _reduce_190(val, _values, result)
@lexer.commentpop
result = Puppet::Parser::AST::Definition.new(classname(val[1]),
ast_context(true).merge(:arguments => val[2], :code => val[4],
:line => val[0][:line]))
@lexer.indefine = false
#} | DEFINE NAME argumentlist parent LBRACE RBRACE {
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 626)
def _reduce_191(val, _values, result)
@lexer.commentpop
result = Puppet::Parser::AST::Definition.new(classname(val[1]),
ast_context(true).merge(:arguments => val[2], :line => val[0][:line]))
@lexer.indefine = false
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 634)
def _reduce_192(val, _values, result)
@lexer.commentpop
# Our class gets defined in the parent namespace, not our own.
@lexer.namepop
result = Puppet::Parser::AST::Hostclass.new(classname(val[1]),
ast_context(true).merge(:arguments => val[2], :parent => val[3],
:code => val[5], :line => val[0][:line]))
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 641)
def _reduce_193(val, _values, result)
@lexer.commentpop
# Our class gets defined in the parent namespace, not our own.
@lexer.namepop
result = Puppet::Parser::AST::Hostclass.new(classname(val[1]),
ast_context(true).merge(:arguments => val[2], :parent => val[3],
:line => val[0][:line]))
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 650)
def _reduce_194(val, _values, result)
@lexer.commentpop
result = Puppet::Parser::AST::Node.new(val[1],
ast_context(true).merge(:parent => val[2], :code => val[4],
:line => val[0][:line]))
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 655)
def _reduce_195(val, _values, result)
@lexer.commentpop
result = Puppet::Parser::AST::Node.new(val[1], ast_context(true).merge(:parent => val[2], :line => val[0][:line]))
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 659)
def _reduce_196(val, _values, result)
result = val[0][:value]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 660)
def _reduce_197(val, _values, result)
result = "class"
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 665)
def _reduce_198(val, _values, result)
result = [result]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 668)
def _reduce_199(val, _values, result)
result = val[0]
result << val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 673)
def _reduce_200(val, _values, result)
result = ast AST::HostName, :value => val[0]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 676)
def _reduce_201(val, _values, result)
result = val[0][:value]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 677)
def _reduce_202(val, _values, result)
result = val[0][:value]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 678)
def _reduce_203(val, _values, result)
result = val[0][:value]
result
end
.,.,
# reduce 204 omitted
module_eval(<<'.,.,', 'grammar.ra', 682)
def _reduce_205(val, _values, result)
result = nil
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 686)
def _reduce_206(val, _values, result)
result = ast AST::ASTArray, :children => []
result
end
.,.,
# reduce 207 omitted
module_eval(<<'.,.,', 'grammar.ra', 691)
def _reduce_208(val, _values, result)
result = nil
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 694)
def _reduce_209(val, _values, result)
result = val[1]
result = [result] unless result[0].is_a?(Array)
result
end
.,.,
# reduce 210 omitted
module_eval(<<'.,.,', 'grammar.ra', 700)
def _reduce_211(val, _values, result)
result = val[0]
result = [result] unless result[0].is_a?(Array)
result << val[2]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 706)
def _reduce_212(val, _values, result)
Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
result = [val[0][:value], val[2]]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 710)
def _reduce_213(val, _values, result)
Puppet.warning addcontext("Deprecation notice: must now include '$' in prototype")
result = [val[0][:value]]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 713)
def _reduce_214(val, _values, result)
result = [val[0][:value], val[2]]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 715)
def _reduce_215(val, _values, result)
result = [val[0][:value]]
result
end
.,.,
# reduce 216 omitted
module_eval(<<'.,.,', 'grammar.ra', 720)
def _reduce_217(val, _values, result)
result = val[1]
result
end
.,.,
# reduce 218 omitted
module_eval(<<'.,.,', 'grammar.ra', 725)
def _reduce_219(val, _values, result)
result = val[1]
result
end
.,.,
# reduce 220 omitted
# reduce 221 omitted
module_eval(<<'.,.,', 'grammar.ra', 731)
def _reduce_222(val, _values, result)
result = ast AST::Variable, :value => val[0][:value], :line => val[0][:line]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 734)
def _reduce_223(val, _values, result)
result = val[1]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 735)
def _reduce_224(val, _values, result)
result = val[1]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 736)
def _reduce_225(val, _values, result)
result = ast AST::ASTArray
result
end
.,.,
# reduce 226 omitted
# reduce 227 omitted
# reduce 228 omitted
module_eval(<<'.,.,', 'grammar.ra', 742)
def _reduce_229(val, _values, result)
result = nil
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 745)
def _reduce_230(val, _values, result)
result = ast AST::Regex, :value => val[0][:value]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 749)
def _reduce_231(val, _values, result)
if val[1].instance_of?(AST::ASTHash)
result = val[1]
else
result = ast AST::ASTHash, { :value => val[1] }
end
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 756)
def _reduce_232(val, _values, result)
if val[1].instance_of?(AST::ASTHash)
result = val[1]
else
result = ast AST::ASTHash, { :value => val[1] }
end
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 762)
def _reduce_233(val, _values, result)
result = ast AST::ASTHash
result
end
.,.,
# reduce 234 omitted
module_eval(<<'.,.,', 'grammar.ra', 767)
def _reduce_235(val, _values, result)
if val[0].instance_of?(AST::ASTHash)
result = val[0].merge(val[2])
else
result = ast AST::ASTHash, :value => val[0]
result.merge(val[2])
end
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 776)
def _reduce_236(val, _values, result)
result = ast AST::ASTHash, { :value => { val[0] => val[2] } }
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 779)
def _reduce_237(val, _values, result)
result = val[0][:value]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 780)
def _reduce_238(val, _values, result)
result = val[0]
result
end
.,.,
module_eval(<<'.,.,', 'grammar.ra', 783)
def _reduce_239(val, _values, result)
result = ast AST::HashOrArrayAccess, :variable => val[0][:value], :key => val[2]
result
end
.,.,
# reduce 240 omitted
module_eval(<<'.,.,', 'grammar.ra', 788)
def _reduce_241(val, _values, result)
result = ast AST::HashOrArrayAccess, :variable => val[0], :key => val[2]
result
end
.,.,
def _reduce_none(val, _values, result)
val[0]
end
end # class Parser
end # module Parser
end # module Puppet
diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb
index 7888fe1dc..86d70720d 100644
--- a/lib/puppet/parser/parser_support.rb
+++ b/lib/puppet/parser/parser_support.rb
@@ -1,211 +1,192 @@
# I pulled this into a separate file, because I got
# tired of rebuilding the parser.rb file all the time.
class Puppet::Parser::Parser
require 'puppet/parser/functions'
require 'puppet/parser/files'
require 'puppet/resource/type_collection'
require 'puppet/resource/type_collection_helper'
require 'puppet/resource/type'
require 'monitor'
AST = Puppet::Parser::AST
include Puppet::Resource::TypeCollectionHelper
attr_reader :version, :environment
attr_accessor :files
attr_accessor :lexer
# Add context to a message; useful for error messages and such.
def addcontext(message, obj = nil)
obj ||= @lexer
message += " on line #{obj.line}"
if file = obj.file
message += " in file #{file}"
end
message
end
# Create an AST array containing a single element
def aryfy(arg)
ast AST::ASTArray, :children => [arg]
end
# Create an AST object, and automatically add the file and line information if
# available.
def ast(klass, hash = {})
klass.new ast_context(klass.use_docs, hash[:line]).merge(hash)
end
def ast_context(include_docs = false, ast_line = nil)
result = {
:line => ast_line || lexer.line,
:file => lexer.file
}
result[:doc] = lexer.getcomment(result[:line]) if include_docs
result
end
# The fully qualifed name, with the full namespace.
def classname(name)
[@lexer.namespace, name].join("::").sub(/^::/, '')
end
def clear
initvars
end
# Raise a Parse error.
def error(message, options = {})
if brace = @lexer.expected
message += "; expected '%s'"
end
except = Puppet::ParseError.new(message)
except.line = options[:line] || @lexer.line
except.file = options[:file] || @lexer.file
raise except
end
def file
@lexer.file
end
def file=(file)
unless FileTest.exist?(file)
unless file =~ /\.pp$/
file = file + ".pp"
end
end
raise Puppet::AlreadyImportedError, "Import loop detected" if known_resource_types.watching_file?(file)
watch_file(file)
@lexer.file = file
end
[:hostclass, :definition, :node, :nodes?].each do |method|
define_method(method) do |*args|
known_resource_types.send(method, *args)
end
end
def find_hostclass(namespace, name)
known_resource_types.find_hostclass(namespace, name)
end
def find_definition(namespace, name)
known_resource_types.find_definition(namespace, name)
end
def import(file)
known_resource_types.loader.import(file, @lexer.file)
end
def initialize(env)
# The environment is needed to know how to find the resource type collection.
@environment = env.is_a?(String) ? Puppet::Node::Environment.new(env) : env
initvars
end
# Initialize or reset all of our variables.
def initvars
@lexer = Puppet::Parser::Lexer.new
end
# Split an fq name into a namespace and name
def namesplit(fullname)
ary = fullname.split("::")
n = ary.pop || ""
ns = ary.join("::")
return ns, n
end
def on_error(token,value,stack)
if token == 0 # denotes end of file
value = 'end of file'
else
value = "'#{value[:value]}'"
end
error = "Syntax error at #{value}"
if brace = @lexer.expected
error += "; expected '#{brace}'"
end
except = Puppet::ParseError.new(error)
except.line = @lexer.line
except.file = @lexer.file if @lexer.file
raise except
end
# how should I do error handling here?
def parse(string = nil)
if self.file =~ /\.rb$/
main = parse_ruby_file
else
self.string = string if string
begin
@yydebug = false
main = yyparse(@lexer,:scan)
- rescue Racc::ParseError => except
- error = Puppet::ParseError.new(except)
- error.line = @lexer.line
- error.file = @lexer.file
- error.set_backtrace except.backtrace
- raise error
rescue Puppet::ParseError => except
except.line ||= @lexer.line
except.file ||= @lexer.file
raise except
- rescue Puppet::Error => except
- # and this is a framework error
- except.line ||= @lexer.line
- except.file ||= @lexer.file
- raise except
- rescue Puppet::DevError => except
- except.line ||= @lexer.line
- except.file ||= @lexer.file
- raise except
rescue => except
- error = Puppet::DevError.new(except.message)
- error.line = @lexer.line
- error.file = @lexer.file
- error.set_backtrace except.backtrace
- raise error
+ raise Puppet::ParseError.new(except.message, @lexer.file, @lexer.line, except)
end
end
# Store the results as the top-level class.
return Puppet::Parser::AST::Hostclass.new('', :code => main)
ensure
@lexer.clear
end
def parse_ruby_file
# Execute the contents of the file inside its own "main" object so
# that it can call methods in the resource type API.
main_object = Puppet::DSL::ResourceTypeAPI.new
main_object.instance_eval(File.read(self.file))
# Then extract any types that were created.
Puppet::Parser::AST::ASTArray.new :children => main_object.instance_eval { @__created_ast_objects__ }
end
def string=(string)
@lexer.string = string
end
def version
known_resource_types.version
end
# Add a new file to be checked when we're checking to see if we should be
# reparsed. This is basically only used by the TemplateWrapper to let the
# parser know about templates that should be parsed.
def watch_file(filename)
known_resource_types.watch_file(filename)
end
end
diff --git a/lib/puppet/property.rb b/lib/puppet/property.rb
index f0d62f044..af4744428 100644
--- a/lib/puppet/property.rb
+++ b/lib/puppet/property.rb
@@ -1,372 +1,372 @@
# The virtual base class for properties, which are the self-contained building
# blocks for actually doing work on the system.
require 'puppet'
require 'puppet/parameter'
class Puppet::Property < Puppet::Parameter
require 'puppet/property/ensure'
# Because 'should' uses an array, we have a special method for handling
# it. We also want to keep copies of the original values, so that
# they can be retrieved and compared later when merging.
attr_reader :shouldorig
attr_writer :noop
class << self
attr_accessor :unmanaged
attr_reader :name
# Return array matching info, defaulting to just matching
# the first value.
def array_matching
@array_matching ||= :first
end
# Set whether properties should match all values or just the first one.
def array_matching=(value)
value = value.intern if value.is_a?(String)
raise ArgumentError, "Supported values for Property#array_matching are 'first' and 'all'" unless [:first, :all].include?(value)
@array_matching = value
end
end
# Look up a value's name, so we can find options and such.
def self.value_name(name)
if value = value_collection.match?(name)
value.name
end
end
# Retrieve an option set when a value was defined.
def self.value_option(name, option)
if value = value_collection.value(name)
value.send(option)
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:
# * :method: The name of the method to define. Defaults to 'set_'.
# * :required_features: A list of features this value requires.
# * :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 self.newvalue(name, options = {}, &block)
value = value_collection.newvalue(name, options, &block)
define_method(value.method, &value.block) if value.method and value.block
value
end
# Call the provider method.
def call_provider(value)
provider.send(self.class.name.to_s + "=", value)
rescue NoMethodError
self.fail "The #{provider.class.name} provider can not handle attribute #{self.class.name}"
end
# Call the dynamically-created method associated with our value, if
# there is one.
def call_valuemethod(name, value)
if method = self.class.value_option(name, :method) and self.respond_to?(method)
begin
event = self.send(method)
rescue Puppet::Error
raise
rescue => detail
- error = Puppet::Error.new("Could not set '#{value}' on #{self.class.name}: #{detail}", @resource.line, @resource.file)
+ error = Puppet::ResourceError.new("Could not set '#{value}' on #{self.class.name}: #{detail}", @resource.line, @resource.file, detail)
error.set_backtrace detail.backtrace
Puppet.log_exception(detail, error.message)
raise error
end
elsif block = self.class.value_option(name, :block)
# FIXME It'd be better here to define a method, so that
# the blocks could return values.
self.instance_eval(&block)
else
devfail "Could not find method for value '#{name}'"
end
end
# How should a property change be printed as a string?
def change_to_s(current_value, newvalue)
begin
if current_value == :absent
return "defined '#{name}' as #{self.class.format_value_for_display should_to_s(newvalue)}"
elsif newvalue == :absent or newvalue == [:absent]
return "undefined '#{name}' from #{self.class.format_value_for_display is_to_s(current_value)}"
else
return "#{name} changed #{self.class.format_value_for_display is_to_s(current_value)} to #{self.class.format_value_for_display should_to_s(newvalue)}"
end
rescue Puppet::Error, Puppet::DevError
raise
rescue => detail
message = "Could not convert change '#{name}' to string: #{detail}"
Puppet.log_exception(detail, message)
raise Puppet::DevError, message
end
end
# Figure out which event to return.
def event_name
value = self.should
event_name = self.class.value_option(value, :event) and return event_name
name == :ensure or return (name.to_s + "_changed").to_sym
return (resource.type.to_s + case value
when :present; "_created"
when :absent; "_removed"
else
"_changed"
end).to_sym
end
# Return a modified form of the resource event.
def event
resource.event :name => event_name, :desired_value => should, :property => self, :source_description => path
end
attr_reader :shadow
# initialize our property
def initialize(hash = {})
super
if ! self.metaparam? and klass = Puppet::Type.metaparamclass(self.class.name)
setup_shadow(klass)
end
end
# Determine whether the property is in-sync or not. If @should is
# not defined or is set to a non-true value, then we do not have
# a valid value for it and thus consider the property to be in-sync
# since we cannot fix it. Otherwise, we expect our should value
# to be an array, and if @is matches any of those values, then
# we consider it to be in-sync.
#
# Don't override this method.
def safe_insync?(is)
# If there is no @should value, consider the property to be in sync.
return true unless @should
# Otherwise delegate to the (possibly derived) insync? method.
insync?(is)
end
def self.method_added(sym)
raise "Puppet::Property#safe_insync? shouldn't be overridden; please override insync? instead" if sym == :safe_insync?
end
# This method may be overridden by derived classes if necessary
# to provide extra logic to determine whether the property is in
# sync. In most cases, however, only `property_matches?` needs to be
# overridden to give the correct outcome - without reproducing all the array
# matching logic, etc, found here.
def insync?(is)
self.devfail "#{self.class.name}'s should is not array" unless @should.is_a?(Array)
# an empty array is analogous to no should values
return true if @should.empty?
# Look for a matching value, either for all the @should values, or any of
# them, depending on the configuration of this property.
if match_all? then
# Emulate Array#== using our own comparison function.
# A non-array was not equal to an array, which @should always is.
return false unless is.is_a? Array
# If they were different lengths, they are not equal.
return false unless is.length == @should.length
# Finally, are all the elements equal? In order to preserve the
# behaviour of previous 2.7.x releases, we need to impose some fun rules
# on "equality" here.
#
# Specifically, we need to implement *this* comparison: the two arrays
# are identical if the is values are == the should values, or if the is
# values are == the should values, stringified.
#
# This does mean that property equality is not commutative, and will not
# work unless the `is` value is carefully arranged to match the should.
return (is == @should or is == @should.map(&:to_s))
# When we stop being idiots about this, and actually have meaningful
# semantics, this version is the thing we actually want to do.
#
# return is.zip(@should).all? {|a, b| property_matches?(a, b) }
else
return @should.any? {|want| property_matches?(is, want) }
end
end
# Compare the current and desired value of a property in a property-specific
# way. Invoked by `insync?`; this should be overridden if your property
# has a different comparison type but does not actually differentiate the
# overall insync? logic.
def property_matches?(current, desired)
# This preserves the older Puppet behaviour of doing raw and string
# equality comparisons for all equality. I am not clear this is globally
# desirable, but at least it is not a breaking change. --daniel 2011-11-11
current == desired or current == desired.to_s
end
# because the @should and @is vars might be in weird formats,
# we need to set up a mechanism for pretty printing of the values
# default to just the values, but this way individual properties can
# override these methods
def is_to_s(currentvalue)
currentvalue
end
# Send a log message.
def log(msg)
Puppet::Util::Log.create(
:level => resource[:loglevel],
:message => msg,
:source => self
)
end
# Should we match all values, or just the first?
def match_all?
self.class.array_matching == :all
end
# Execute our shadow's munge code, too, if we have one.
def munge(value)
self.shadow.munge(value) if self.shadow
super
end
# each property class must define the name method, and property instances
# do not change that name
# this implicitly means that a given object can only have one property
# instance of a given property class
def name
self.class.name
end
# for testing whether we should actually do anything
def noop
# This is only here to make testing easier.
if @resource.respond_to?(:noop?)
@resource.noop?
else
if defined?(@noop)
@noop
else
Puppet[:noop]
end
end
end
# By default, call the method associated with the property name on our
# provider. In other words, if the property name is 'gid', we'll call
# 'provider.gid' to retrieve the current value.
def retrieve
provider.send(self.class.name)
end
# Set our value, using the provider, an associated block, or both.
def set(value)
# Set a name for looking up associated options like the event.
name = self.class.value_name(value)
call = self.class.value_option(name, :call) || :none
if call == :instead
call_valuemethod(name, value)
elsif call == :none
# They haven't provided a block, and our parent does not have
# a provider, so we have no idea how to handle this.
self.fail "#{self.class.name} cannot handle values of type #{value.inspect}" unless @resource.provider
call_provider(value)
else
# LAK:NOTE 20081031 This is a change in behaviour -- you could
# previously specify :call => [;before|:after], which would call
# the setter *in addition to* the block. I'm convinced this
# was never used, and it makes things unecessarily complicated.
# If you want to specify a block and still call the setter, then
# do so in the block.
devfail "Cannot use obsolete :call value '#{call}' for property '#{self.class.name}'"
end
end
# If there's a shadowing metaparam, instantiate it now.
# This allows us to create a property or parameter with the
# same name as a metaparameter, and the metaparam will only be
# stored as a shadow.
def setup_shadow(klass)
@shadow = klass.new(:resource => self.resource)
end
# Only return the first value
def should
return nil unless defined?(@should)
self.devfail "should for #{self.class.name} on #{resource.name} is not an array" unless @should.is_a?(Array)
if match_all?
return @should.collect { |val| self.unmunge(val) }
else
return self.unmunge(@should[0])
end
end
# Set the should value.
def should=(values)
values = [values] unless values.is_a?(Array)
@shouldorig = values
values.each { |val| validate(val) }
@should = values.collect { |val| self.munge(val) }
end
def should_to_s(newvalue)
[newvalue].flatten.join(" ")
end
def sync
devfail "Got a nil value for should" unless should
set(should)
end
# Verify that the passed value is valid.
# If the developer uses a 'validate' hook, this method will get overridden.
def unsafe_validate(value)
super
validate_features_per_value(value)
end
# Make sure that we've got all of the required features for a given value.
def validate_features_per_value(value)
if features = self.class.value_option(self.class.value_name(value), :required_features)
features = Array(features)
needed_features = features.collect { |f| f.to_s }.join(", ")
raise ArgumentError, "Provider must have features '#{needed_features}' to set '#{self.class.name}' to '#{value}'" unless provider.satisfies?(features)
end
end
# Just return any should value we might have.
def value
self.should
end
# Match the Parameter interface, but we really just use 'should' internally.
# Note that the should= method does all of the validation and such.
def value=(value)
self.should = value
end
end
diff --git a/lib/puppet/util/errors.rb b/lib/puppet/util/errors.rb
index 5a7a7630b..fd9b98864 100644
--- a/lib/puppet/util/errors.rb
+++ b/lib/puppet/util/errors.rb
@@ -1,63 +1,62 @@
# Some helper methods for throwing errors.
module Puppet::Util::Errors
# Throw a dev error.
def devfail(msg)
self.fail(Puppet::DevError, msg)
end
# Add line and file info if available and appropriate.
def adderrorcontext(error, other = nil)
- error.line ||= self.line if self.respond_to?(:line) and self.line
- error.file ||= self.file if self.respond_to?(:file) and self.file
+ error.line ||= self.line if error.respond_to?(:line=) and self.respond_to?(:line) and self.line
+ error.file ||= self.file if error.respond_to?(:file=) and self.respond_to?(:file) and self.file
- error.set_backtrace other.backtrace if other and other.respond_to?(:backtrace)
+ error.set_backtrace(other.backtrace) if other and other.respond_to?(:backtrace)
error
end
def error_context
if file and line
" at #{file}:#{line}"
elsif line
" at line #{line}"
elsif file
" in #{file}"
else
""
end
end
# Wrap a call in such a way that we always throw the right exception and keep
# as much context as possible.
def exceptwrap(options = {})
options[:type] ||= Puppet::DevError
begin
return yield
rescue Puppet::Error => detail
raise adderrorcontext(detail)
rescue => detail
message = options[:message] || "#{self.class} failed with error #{detail.class}: #{detail}"
error = options[:type].new(message)
# We can't use self.fail here because it always expects strings,
# not exceptions.
raise adderrorcontext(error, detail)
end
retval
end
# Throw an error, defaulting to a Puppet::Error.
def fail(*args)
if args[0].is_a?(Class)
type = args.shift
else
type = Puppet::Error
end
error = adderrorcontext(type.new(args.join(" ")))
raise error
end
end
-
diff --git a/lib/puppet/util/settings.rb b/lib/puppet/util/settings.rb
index 6deab0c2a..fc558f73f 100644
--- a/lib/puppet/util/settings.rb
+++ b/lib/puppet/util/settings.rb
@@ -1,1283 +1,1283 @@
require 'puppet'
require 'sync'
require 'getoptlong'
require 'puppet/util/loadedfile'
require 'puppet/util/command_line/puppet_option_parser'
class Puppet::SettingsError < Puppet::Error
end
# The class for handling configuration files.
class Puppet::Util::Settings
include Enumerable
require 'puppet/util/settings/string_setting'
require 'puppet/util/settings/file_setting'
require 'puppet/util/settings/directory_setting'
require 'puppet/util/settings/path_setting'
require 'puppet/util/settings/boolean_setting'
# local reference for convenience
PuppetOptionParser = Puppet::Util::CommandLine::PuppetOptionParser
attr_accessor :files
attr_reader :timer
READ_ONLY_SETTINGS = [:run_mode]
# These are the settings that every app is required to specify; there are reasonable defaults defined in application.rb.
REQUIRED_APP_SETTINGS = [:run_mode, :logdir, :confdir, :vardir]
# This method is intended for puppet internal use only; it is a convenience method that
# returns reasonable application default settings values for a given run_mode.
def self.app_defaults_for_run_mode(run_mode)
{
:name => run_mode.to_s,
:run_mode => run_mode.name,
:confdir => run_mode.conf_dir,
:vardir => run_mode.var_dir,
:rundir => run_mode.run_dir,
:logdir => run_mode.log_dir,
}
end
def self.default_global_config_dir()
Puppet.features.microsoft_windows? ? File.join(Dir::COMMON_APPDATA, "PuppetLabs", "puppet", "etc") : "/etc/puppet"
end
def self.default_user_config_dir()
"~/.puppet"
end
def self.default_global_var_dir()
Puppet.features.microsoft_windows? ? File.join(Dir::COMMON_APPDATA, "PuppetLabs", "puppet", "var") : "/var/lib/puppet"
end
def self.default_user_var_dir()
"~/.puppet/var"
end
def self.default_config_file_name()
"puppet.conf"
end
# Retrieve a config value
def [](param)
value(param)
end
# Set a config value. This doesn't set the defaults, it sets the value itself.
def []=(param, value)
set_value(param, value, :memory)
end
# Generate the list of valid arguments, in a format that GetoptLong can
# understand, and add them to the passed option list.
def addargs(options)
# Add all of the config parameters as valid options.
self.each { |name, setting|
setting.getopt_args.each { |args| options << args }
}
options
end
# Generate the list of valid arguments, in a format that OptionParser can
# understand, and add them to the passed option list.
def optparse_addargs(options)
# Add all of the config parameters as valid options.
self.each { |name, setting|
options << setting.optparse_args
}
options
end
# Is our parameter a boolean parameter?
def boolean?(param)
param = param.to_sym
!!(@config.include?(param) and @config[param].kind_of? BooleanSetting)
end
# Remove all set values, potentially skipping cli values.
def clear
@sync.synchronize do
unsafe_clear
end
end
# Remove all set values, potentially skipping cli values.
def unsafe_clear(clear_cli = true, clear_application_defaults = false)
@values.each do |name, values|
next if ((name == :application_defaults) and !clear_application_defaults)
next if ((name == :cli) and !clear_cli)
@values.delete(name)
end
# Only clear the 'used' values if we were explicitly asked to clear out
# :cli values; otherwise, it may be just a config file reparse,
# and we want to retain this cli values.
@used = [] if clear_cli
@app_defaults_initialized = false if clear_application_defaults
@cache.clear
end
private :unsafe_clear
# This is mostly just used for testing.
def clearused
@cache.clear
@used = []
end
def global_defaults_initialized?()
@global_defaults_initialized
end
def initialize_global_settings(args = [])
raise Puppet::DevError, "Attempting to initialize global default settings more than once!" if global_defaults_initialized?
# The first two phases of the lifecycle of a puppet application are:
# 1) To parse the command line options and handle any of them that are registered, defined "global" puppet
# settings (mostly from defaults.rb).)
# 2) To parse the puppet config file(s).
#
# These 2 steps are being handled explicitly here. If there ever arises a situation where they need to be
# triggered from outside of this class, without triggering the rest of the lifecycle--we might want to move them
# out into a separate method that we call from here. However, this seems to be sufficient for now.
# --cprice 2012-03-16
# Here's step 1.
parse_global_options(args)
# Here's step 2. NOTE: this is a change in behavior where we are now parsing the config file on every run;
# before, there were several apps that specifically registered themselves as not requiring anything from
# the config file. The fact that we're always parsing it now might be a small performance hit, but it was
# necessary in order to make sure that we can resolve the libdir before we look for the available applications.
parse_config_files
@global_defaults_initialized = true
end
# This method is called during application bootstrapping. It is responsible for parsing all of the
# command line options and initializing the settings accordingly.
#
# It will ignore options that are not defined in the global puppet settings list, because they may
# be valid options for the specific application that we are about to launch... however, at this point
# in the bootstrapping lifecycle, we don't yet know what that application is.
def parse_global_options(args)
# Create an option parser
option_parser = PuppetOptionParser.new
option_parser.ignore_invalid_options = true
# Add all global options to it.
self.optparse_addargs([]).each do |option|
option_parser.on(*option) do |arg|
opt, val = Puppet::Util::Settings.clean_opt(option[0], arg)
handlearg(opt, val)
end
end
option_parser.parse(args)
end
private :parse_global_options
## Private utility method; this is the callback that the OptionParser will use when it finds
## an option that was defined in Puppet.settings. All that this method does is a little bit
## of clanup to get the option into the exact format that Puppet.settings expects it to be in,
## and then passes it along to Puppet.settings.
##
## @param [String] opt the command-line option that was matched
## @param [String, TrueClass, FalseClass] the value for the setting (as determined by the OptionParser)
#def handlearg(opt, val)
# opt, val = self.class.clean_opt(opt, val)
# Puppet.settings.handlearg(opt, val)
#end
#private :handlearg
# A utility method (public, is used by application.rb and perhaps elsewhere) that munges a command-line
# option string into the format that Puppet.settings expects. (This mostly has to deal with handling the
# "no-" prefix on flag/boolean options).
#
# @param [String] opt the command line option that we are munging
# @param [String, TrueClass, FalseClass] the value for the setting (as determined by the OptionParser)
def self.clean_opt(opt, val)
# rewrite --[no-]option to --no-option if that's what was given
if opt =~ /\[no-\]/ and !val
opt = opt.gsub(/\[no-\]/,'no-')
end
# otherwise remove the [no-] prefix to not confuse everybody
opt = opt.gsub(/\[no-\]/, '')
[opt, val]
end
def app_defaults_initialized?()
@app_defaults_initialized
end
def initialize_app_defaults(app_defaults)
raise Puppet::DevError, "Attempting to initialize application default settings more than once!" if app_defaults_initialized?
REQUIRED_APP_SETTINGS.each do |key|
raise Puppet::SettingsError, "missing required app default setting '#{key}'" unless app_defaults.has_key?(key)
end
app_defaults.each do |key, value|
set_value(key, value, :application_defaults)
end
call_hooks_deferred_to_application_initialization
@app_defaults_initialized = true
end
def call_hooks_deferred_to_application_initialization(options = {})
@hooks_to_call_on_application_initialization.each do |setting|
begin
setting.handle(self.value(setting.name))
rescue Puppet::SettingsError => err
raise err unless options[:ignore_interpolation_dependency_errors]
#swallow. We're not concerned if we can't call hooks because dependencies don't exist yet
#we'll get another chance after application defaults are initialized
end
end
end
private :call_hooks_deferred_to_application_initialization
# Do variable interpolation on the value.
def convert(value, environment = nil)
return nil if value.nil?
return value unless value.is_a? String
newval = value.gsub(/\$(\w+)|\$\{(\w+)\}/) do |value|
varname = $2 || $1
if varname == "environment" and environment
environment
elsif pval = self.value(varname, environment)
pval
else
raise Puppet::SettingsError, "Could not find value for #{value}"
end
end
newval
end
# Return a value's description.
def description(name)
if obj = @config[name.to_sym]
obj.desc
else
nil
end
end
def each
@config.each { |name, object|
yield name, object
}
end
# Iterate over each section name.
def eachsection
yielded = []
@config.each do |name, object|
section = object.section
unless yielded.include? section
yield section
yielded << section
end
end
end
# Return an object by name.
def setting(param)
param = param.to_sym
@config[param]
end
# Handle a command-line argument.
def handlearg(opt, value = nil)
@cache.clear
if value.is_a?(FalseClass)
value = "false"
elsif value.is_a?(TrueClass)
value = "true"
end
value &&= munge_value(value)
str = opt.sub(/^--/,'')
bool = true
newstr = str.sub(/^no-/, '')
if newstr != str
str = newstr
bool = false
end
str = str.intern
if @config[str].is_a?(Puppet::Util::Settings::BooleanSetting)
if value == "" or value.nil?
value = bool
end
end
set_value(str, value, :cli)
end
def include?(name)
name = name.intern if name.is_a? String
@config.include?(name)
end
# check to see if a short name is already defined
def shortinclude?(short)
short = short.intern if name.is_a? String
@shortnames.include?(short)
end
# Create a new collection of config settings.
def initialize
@config = {}
@shortnames = {}
@created = []
@searchpath = nil
# Mutex-like thing to protect @values
@sync = Sync.new
# Keep track of set values.
@values = Hash.new { |hash, key| hash[key] = {} }
# And keep a per-environment cache
@cache = Hash.new { |hash, key| hash[key] = {} }
# The list of sections we've used.
@used = []
@hooks_to_call_on_application_initialization = []
end
# NOTE: ACS ahh the util classes. . .sigh
# as part of a fix for 1183, I pulled the logic for the following 5 methods out of the executables and puppet.rb
# They probably deserve their own class, but I don't want to do that until I can refactor environments
# its a little better than where they were
# Prints the contents of a config file with the available config settings, or it
# prints a single value of a config setting.
def print_config_options
env = value(:environment)
val = value(:configprint)
if val == "all"
hash = {}
each do |name, obj|
val = value(name,env)
val = val.inspect if val == ""
hash[name] = val
end
hash.sort { |a,b| a[0].to_s <=> b[0].to_s }.each do |name, val|
puts "#{name} = #{val}"
end
else
val.split(/\s*,\s*/).sort.each do |v|
if include?(v)
#if there is only one value, just print it for back compatibility
if v == val
puts value(val,env)
break
end
puts "#{v} = #{value(v,env)}"
else
puts "invalid parameter: #{v}"
return false
end
end
end
true
end
def generate_config
puts to_config
true
end
def generate_manifest
puts to_manifest
true
end
def print_configs
return print_config_options if value(:configprint) != ""
return generate_config if value(:genconfig)
generate_manifest if value(:genmanifest)
end
def print_configs?
(value(:configprint) != "" || value(:genconfig) || value(:genmanifest)) && true
end
# Return a given object's file metadata.
def metadata(param)
if obj = @config[param.to_sym] and obj.is_a?(FileSetting)
return [:owner, :group, :mode].inject({}) do |meta, p|
if v = obj.send(p)
meta[p] = v
end
meta
end
else
nil
end
end
# Make a directory with the appropriate user, group, and mode
def mkdir(default)
obj = get_config_file_default(default)
Puppet::Util::SUIDManager.asuser(obj.owner, obj.group) do
mode = obj.mode || 0750
Dir.mkdir(obj.value, mode)
end
end
# Figure out the section name for the run_mode.
def run_mode
@run_mode || :user
end
# PRIVATE! This only exists because we need a hook to validate the run mode when it's being set, and
# it should never, ever, ever, ever be called from outside of this file.
def run_mode=(mode)
raise Puppet::DevError, "Invalid run mode '#{mode}'" unless [:master, :agent, :user].include?(mode)
@run_mode = mode
end
private :run_mode=
# Return all of the parameters associated with a given section.
def params(section = nil)
if section
section = section.intern if section.is_a? String
@config.find_all { |name, obj|
obj.section == section
}.collect { |name, obj|
name
}
else
@config.keys
end
end
# Parse the configuration file. Just provides
# thread safety.
def parse_config_files
# we are now supporting multiple config files; the "main" config file will be the one located in
# /etc/puppet (or overridden $confdir)... but we will also look for a config file in the user's home
# directory. This was introduced in an effort to provide maximum backwards compatibility while
# de-coupling the process of locating the config file from the "run mode" of the application.
files = [main_config_file]
files << user_config_file unless Puppet.features.root?
@sync.synchronize do
unsafe_parse(files)
end
# talking with cprice, Settings.parse will not be the final location for this. He's working on ticket
# that, as a side effect, will create a more appropriate place for this. At that time, this will be
# moved to the new location. --jeffweiss 24 apr 2012
call_hooks_deferred_to_application_initialization :ignore_interpolation_dependency_errors => true
end
private :parse_config_files
def main_config_file
# the algorithm here is basically this:
# * use the explicit config file location if one has been specified; this can be affected by modifications
# to either the "confdir" or "config" settings (most likely via CLI arguments).
# * if no explicit config location has been specified, we fall back to the default.
#
# The easiest way to determine whether an explicit one has been specified is to simply attempt to evaluate
# the value of ":config". This will obviously be successful if they've passed an explicit value for :config,
# but it will also result in successful interpolation if they've only passed an explicit value for :confdir.
#
# If they've specified neither, then the interpolation will fail and we'll get an exception.
#
begin
return self[:config] if self[:config]
rescue Puppet::SettingsError => err
# This means we failed to interpolate, which means that they didn't explicitly specify either :config or
# :confdir... so we'll fall out to the default value.
end
# return the default value.
return File.join(self.class.default_global_config_dir, config_file_name)
end
private :main_config_file
def user_config_file
return File.join(self.class.default_user_config_dir, config_file_name)
end
private :user_config_file
# This method is here to get around some life-cycle issues. We need to be able to determine the config file name
# before the settings / defaults are fully loaded. However, we also need to respect any overrides of this value
# that the user may have specified on the command line.
#
# The easiest way to do this is to attempt to read the setting, and if we catch an error (meaning that it hasn't been
# set yet), we'll fall back to the default value.
def config_file_name
begin
return self[:config_file_name] if self[:config_file_name]
rescue Puppet::SettingsError => err
# This just means that the setting wasn't explicitly set on the command line, so we will ignore it and
# fall through to the default name.
end
return self.class.default_config_file_name
end
private :config_file_name
# Unsafely parse the file -- this isn't thread-safe and causes plenty of problems if used directly.
def unsafe_parse(files)
raise Puppet::DevError unless files.length > 0
# build up a single data structure that contains the values from all of the parsed files.
data = {}
files.each do |file|
next unless FileTest.exist?(file)
begin
file_data = parse_file(file)
# This is a little kludgy; basically we are merging a hash of hashes. We can't use "merge" at the
# outermost level or we risking losing data from the hash we're merging into.
file_data.keys.each do |key|
if data.has_key?(key)
data[key].merge!(file_data[key])
else
data[key] = file_data[key]
end
end
rescue => detail
Puppet.log_exception(detail, "Could not parse #{file}: #{detail}")
return
end
end
# If we get here and don't have any data, we just return and don't muck with the current state of the world.
return if data.empty?
# If we get here then we have some data, so we need to clear out any previous settings that may have come from
# config files.
unsafe_clear(false, false)
# And now we can repopulate with the values from our last parsing of the config files.
metas = {}
data.each do |area, values|
metas[area] = values.delete(:_meta)
values.each do |key,value|
set_value(key, value, area, :dont_trigger_handles => true, :ignore_bad_settings => true )
end
end
# Determine our environment, if we have one.
if @config[:environment]
env = self.value(:environment).to_sym
else
env = "none"
end
# Call any hooks we should be calling.
settings_with_hooks.each do |setting|
each_source(env) do |source|
if value = @values[source][setting.name]
# We still have to use value to retrieve the value, since
# we want the fully interpolated value, not $vardir/lib or whatever.
# This results in extra work, but so few of the settings
# will have associated hooks that it ends up being less work this
# way overall.
setting.handle(self.value(setting.name, env))
break
end
end
end
# We have to do it in the reverse of the search path,
# because multiple sections could set the same value
# and I'm too lazy to only set the metadata once.
searchpath.reverse.each do |source|
source = run_mode if source == :run_mode
source = @name if (@name && source == :name)
if meta = metas[source]
set_metadata(meta)
end
end
end
private :unsafe_parse
# Create a new setting. The value is passed in because it's used to determine
# what kind of setting we're creating, but the value itself might be either
# a default or a value, so we can't actually assign it.
#
# See #define_settings for documentation on the legal values for the ":type" option.
def newsetting(hash)
klass = nil
hash[:section] = hash[:section].to_sym if hash[:section]
if type = hash[:type]
unless klass = {
:string => StringSetting,
:file => FileSetting,
:directory => DirectorySetting,
:path => PathSetting,
:boolean => BooleanSetting,
} [type]
raise ArgumentError, "Invalid setting type '#{type}'"
end
hash.delete(:type)
else
# The only implicit typing we still do for settings is to fall back to "String" type if they didn't explicitly
# specify a type. Personally I'd like to get rid of this too, and make the "type" option mandatory... but
# there was a little resistance to taking things quite that far for now. --cprice 2012-03-19
klass = StringSetting
end
hash[:settings] = self
setting = klass.new(hash)
setting
end
# This has to be private, because it doesn't add the settings to @config
private :newsetting
# Iterate across all of the objects in a given section.
def persection(section)
section = section.to_sym
self.each { |name, obj|
if obj.section == section
yield obj
end
}
end
# Reparse our config file, if necessary.
def reparse_config_files
if files
if filename = any_files_changed?
Puppet.notice "Config file #{filename} changed; triggering re-parse of all config files."
parse_config_files
reuse
end
end
end
def files
return @files if @files
@files = []
[main_config_file, user_config_file].each do |path|
if FileTest.exist?(path)
@files << Puppet::Util::LoadedFile.new(path)
end
end
@files
end
private :files
# Checks to see if any of the config files have been modified
# @return the filename of the first file that is found to have changed, or nil if no files have changed
def any_files_changed?
files.each do |file|
return file.file if file.changed?
end
nil
end
private :any_files_changed?
def reuse
return unless defined?(@used)
@sync.synchronize do # yay, thread-safe
new = @used
@used = []
self.use(*new)
end
end
# The order in which to search for values.
def searchpath(environment = nil)
if environment
[:cli, :memory, environment, :run_mode, :main, :application_defaults]
else
[:cli, :memory, :run_mode, :main, :application_defaults]
end
end
# Get a list of objects per section
def sectionlist
sectionlist = []
self.each { |name, obj|
section = obj.section || "puppet"
sections[section] ||= []
sectionlist << section unless sectionlist.include?(section)
sections[section] << obj
}
return sectionlist, sections
end
def service_user_available?
return @service_user_available if defined?(@service_user_available)
return @service_user_available = false unless user_name = self[:user]
user = Puppet::Type.type(:user).new :name => self[:user], :audit => :ensure
@service_user_available = user.exists?
end
def legacy_to_mode(type, param)
require 'puppet/util/command_line/legacy_command_line'
if Puppet::Util::CommandLine::LegacyCommandLine::LEGACY_APPS.has_key?(type)
new_type = Puppet::Util::CommandLine::LegacyCommandLine::LEGACY_APPS[type].run_mode
Puppet.deprecation_warning "You have configuration parameter $#{param} specified in [#{type}], which is a deprecated section. I'm assuming you meant [#{new_type}]"
return new_type
end
type
end
# Allow later inspection to determine if the setting was set on the
# command line, or through some other code path. Used for the
# `dns_alt_names` option during cert generate. --daniel 2011-10-18
def set_by_cli?(param)
param = param.to_sym
!@values[:cli][param].nil?
end
def set_value(param, value, type, options = {})
param = param.to_sym
unless setting = @config[param]
if options[:ignore_bad_settings]
return
else
raise ArgumentError,
"Attempt to assign a value to unknown configuration parameter #{param.inspect}"
end
end
setting.handle(value) if setting.has_hook? and not options[:dont_trigger_handles]
if read_only_settings.include? param and type != :application_defaults
raise ArgumentError,
"You're attempting to set configuration parameter $#{param}, which is read-only."
end
type = legacy_to_mode(type, param)
@sync.synchronize do # yay, thread-safe
@values[type][param] = value
@cache.clear
clearused
# Clear the list of environments, because they cache, at least, the module path.
# We *could* preferentially just clear them if the modulepath is changed,
# but we don't really know if, say, the vardir is changed and the modulepath
# is defined relative to it. We need the defined?(stuff) because of loading
# order issues.
Puppet::Node::Environment.clear if defined?(Puppet::Node) and defined?(Puppet::Node::Environment)
end
# This is a hack. The run_mode should probably not be a "normal" setting, because the places
# it is used tend to create lifecycle issues and cause other weird problems. In some places
# we need for it to have a default value, in other places it may be preferable to be able to
# determine that it has not yet been set. There used to be a global variable that some
# code paths would access; as a first step towards cleaning it up, I've gotten rid of the global
# variable and am instead using an instance variable in this class, but that means that if
# someone modifies the value of the setting at a later point during execution, then the
# instance variable needs to be updated as well... so that's what we're doing here.
#
# This code should be removed if we get a chance to remove run_mode from the defined settings.
# --cprice 2012-03-19
self.run_mode = value if param == :run_mode
value
end
# Deprecated; use #define_settings instead
def setdefaults(section, defs)
Puppet.deprecation_warning("'setdefaults' is deprecated and will be removed; please call 'define_settings' instead")
define_settings(section, defs)
end
# Define a group of settings.
#
# @param [Symbol] section a symbol to use for grouping multiple settings together into a conceptual unit. This value
# (and the conceptual separation) is not used very often; the main place where it will have a potential impact
# is when code calls Settings#use method. See docs on that method for further details, but basically that method
# just attempts to do any preparation that may be necessary before code attempts to leverage the value of a particular
# setting. This has the most impact for file/directory settings, where #use will attempt to "ensure" those
# files / directories.
# @param [Hash[Hash]] defs the settings to be defined. This argument is a hash of hashes; each key should be a symbol,
# which is basically the name of the setting that you are defining. The value should be another hash that specifies
# the parameters for the particular setting. Legal values include:
# [:default] => required; this is a string value that will be used as a default value for a setting if no other
# value is specified (via cli, config file, etc.) This string may include "variables", demarcated with $ or ${},
# which will be interpolated with values of other settings.
# [:desc] => required; a description of the setting, used in documentation / help generation
# [:type] => not required, but highly encouraged! This specifies the data type that the setting represents. If
# you do not specify it, it will default to "string". Legal values include:
# :string - A generic string setting
# :boolean - A boolean setting; values are expected to be "true" or "false"
# :file - A (single) file path; puppet may attempt to create this file depending on how the settings are used. This type
# also supports additional options such as "mode", "owner", "group"
# :directory - A (single) directory path; puppet may attempt to create this file depending on how the settings are used. This type
# also supports additional options such as "mode", "owner", "group"
# :path - This is intended to be used for settings whose value can contain multiple directory paths, respresented
# as strings separated by the system path separator (e.g. system path, module path, etc.).
# [:mode] => an (optional) octal value to be used as the permissions/mode for :file and :directory settings
# [:owner] => optional owner username/uid for :file and :directory settings
# [:group] => optional group name/gid for :file and :directory settings
#
def define_settings(section, defs)
section = section.to_sym
call = []
defs.each { |name, hash|
raise ArgumentError, "setting definition for '#{name}' is not a hash!" unless hash.is_a? Hash
name = name.to_sym
hash[:name] = name
hash[:section] = section
raise ArgumentError, "Parameter #{name} is already defined" if @config.include?(name)
tryconfig = newsetting(hash)
if short = tryconfig.short
if other = @shortnames[short]
raise ArgumentError, "Parameter #{other.name} is already using short name '#{short}'"
end
@shortnames[short] = tryconfig
end
@config[name] = tryconfig
# Collect the settings that need to have their hooks called immediately.
# We have to collect them so that we can be sure we're fully initialized before
# the hook is called.
call << tryconfig if tryconfig.call_hook_on_define?
@hooks_to_call_on_application_initialization << tryconfig if tryconfig.call_hook_on_initialize?
}
call.each { |setting| setting.handle(self.value(setting.name)) }
end
# Convert the settings we manage into a catalog full of resources that model those settings.
def to_catalog(*sections)
sections = nil if sections.empty?
catalog = Puppet::Resource::Catalog.new("Settings")
@config.keys.find_all { |key| @config[key].is_a?(FileSetting) }.each do |key|
file = @config[key]
next unless (sections.nil? or sections.include?(file.section))
next unless resource = file.to_resource
next if catalog.resource(resource.ref)
Puppet.debug("Using settings: adding file resource '#{key}': '#{resource.inspect}'")
catalog.add_resource(resource)
end
add_user_resources(catalog, sections)
catalog
end
# Convert our list of config settings into a configuration file.
def to_config
str = %{The configuration file for #{Puppet.run_mode.name}. Note that this file
is likely to have unused configuration parameters in it; any parameter that's
valid anywhere in Puppet can be in any config file, even if it's not used.
Every section can specify three special parameters: owner, group, and mode.
These parameters affect the required permissions of any files specified after
their specification. Puppet will sometimes use these parameters to check its
own configured state, so they can be used to make Puppet a bit more self-managing.
Generated on #{Time.now}.
}.gsub(/^/, "# ")
# Add a section heading that matches our name.
if @config.include?(:run_mode)
str += "[#{self[:run_mode]}]\n"
end
eachsection do |section|
persection(section) do |obj|
str += obj.to_config + "\n" unless read_only_settings.include? obj.name or obj.name == :genconfig
end
end
return str
end
# Convert to a parseable manifest
def to_manifest
catalog = to_catalog
catalog.resource_refs.collect do |ref|
catalog.resource(ref).to_manifest
end.join("\n\n")
end
# Create the necessary objects to use a section. This is idempotent;
# you can 'use' a section as many times as you want.
def use(*sections)
sections = sections.collect { |s| s.to_sym }
@sync.synchronize do # yay, thread-safe
sections = sections.reject { |s| @used.include?(s) }
return if sections.empty?
begin
catalog = to_catalog(*sections).to_ral
rescue => detail
Puppet.log_and_raise(detail, "Could not create resources for managing Puppet's files and directories in sections #{sections.inspect}: #{detail}")
end
catalog.host_config = false
catalog.apply do |transaction|
if transaction.any_failed?
report = transaction.report
failures = report.logs.find_all { |log| log.level == :err }
raise "Got #{failures.length} failure(s) while initializing: #{failures.collect { |l| l.to_s }.join("; ")}"
end
end
sections.each { |s| @used << s }
@used.uniq!
end
end
def valid?(param)
param = param.to_sym
@config.has_key?(param)
end
def uninterpolated_value(param, environment = nil)
param = param.to_sym
environment &&= environment.to_sym
# See if we can find it within our searchable list of values
val = find_value(environment, param)
# If we didn't get a value, use the default
val = @config[param].default if val.nil?
val
end
def find_value(environment, param)
each_source(environment) do |source|
# Look for the value. We have to test the hash for whether
# it exists, because the value might be false.
@sync.synchronize do
return @values[source][param] if @values[source].include?(param)
end
end
return nil
end
private :find_value
# Find the correct value using our search path. Optionally accept an environment
# in which to search before the other configuration sections.
def value(param, environment = nil, bypass_interpolation = false)
param = param.to_sym
environment &&= environment.to_sym
setting = @config[param]
# Short circuit to nil for undefined parameters.
return nil unless @config.include?(param)
# Yay, recursion.
#self.reparse unless [:config, :filetimeout].include?(param)
# Check the cache first. It needs to be a per-environment
# cache so that we don't spread values from one env
# to another.
if cached = @cache[environment||"none"][param]
return cached
end
val = uninterpolated_value(param, environment)
return val if bypass_interpolation
if param == :code
# if we interpolate code, all hell breaks loose.
return val
end
# Convert it if necessary
begin
val = convert(val, environment)
rescue Puppet::SettingsError => err
raise Puppet::SettingsError.new("Error converting value for param '#{param}': #{err}")
end
val = setting.munge(val) if setting.respond_to?(:munge)
# And cache it
@cache[environment||"none"][param] = val
val
end
# Open a file with the appropriate user, group, and mode
def write(default, *args, &bloc)
obj = get_config_file_default(default)
writesub(default, value(obj.name), *args, &bloc)
end
# Open a non-default file under a default dir with the appropriate user,
# group, and mode
def writesub(default, file, *args, &bloc)
obj = get_config_file_default(default)
chown = nil
if Puppet.features.root?
chown = [obj.owner, obj.group]
else
chown = [nil, nil]
end
Puppet::Util::SUIDManager.asuser(*chown) do
mode = obj.mode ? obj.mode.to_i : 0640
args << "w" if args.empty?
args << mode
# Update the umask to make non-executable files
Puppet::Util.withumask(File.umask ^ 0111) do
File.open(file, *args) do |file|
yield file
end
end
end
end
def readwritelock(default, *args, &bloc)
file = value(get_config_file_default(default).name)
tmpfile = file + ".tmp"
sync = Sync.new
raise Puppet::DevError, "Cannot create #{file}; directory #{File.dirname(file)} does not exist" unless FileTest.directory?(File.dirname(tmpfile))
sync.synchronize(Sync::EX) do
File.open(file, ::File::CREAT|::File::RDWR, 0600) do |rf|
rf.lock_exclusive do
if File.exist?(tmpfile)
raise Puppet::Error, ".tmp file already exists for #{file}; Aborting locked write. Check the .tmp file and delete if appropriate"
end
# If there's a failure, remove our tmpfile
begin
writesub(default, tmpfile, *args, &bloc)
rescue
File.unlink(tmpfile) if FileTest.exist?(tmpfile)
raise
end
begin
File.rename(tmpfile, file)
rescue => detail
Puppet.err "Could not rename #{file} to #{tmpfile}: #{detail}"
File.unlink(tmpfile) if FileTest.exist?(tmpfile)
end
end
end
end
end
private
# This is just here to simplify testing. This method can be stubbed easily. Constants can't.
def read_only_settings()
READ_ONLY_SETTINGS
end
def get_config_file_default(default)
obj = nil
unless obj = @config[default]
raise ArgumentError, "Unknown default #{default}"
end
raise ArgumentError, "Default #{default} is not a file" unless obj.is_a? FileSetting
obj
end
def add_user_resources(catalog, sections)
return unless Puppet.features.root?
return if Puppet.features.microsoft_windows?
return unless self[:mkusers]
@config.each do |name, setting|
next unless setting.respond_to?(:owner)
next unless sections.nil? or sections.include?(setting.section)
if user = setting.owner and user != "root" and catalog.resource(:user, user).nil?
resource = Puppet::Resource.new(:user, user, :parameters => {:ensure => :present})
resource[:gid] = self[:group] if self[:group]
catalog.add_resource resource
end
if group = setting.group and ! %w{root wheel}.include?(group) and catalog.resource(:group, group).nil?
catalog.add_resource Puppet::Resource.new(:group, group, :parameters => {:ensure => :present})
end
end
end
# Yield each search source in turn.
def each_source(environment)
searchpath(environment).each do |source|
# Modify the source as necessary.
source = self.run_mode if source == :run_mode
yield source
end
end
# Return all settings that have associated hooks; this is so
# we can call them after parsing the configuration file.
def settings_with_hooks
@config.values.find_all { |setting| setting.has_hook? }
end
# Extract extra setting information for files.
def extract_fileinfo(string)
result = {}
value = string.sub(/\{\s*([^}]+)\s*\}/) do
params = $1
params.split(/\s*,\s*/).each do |str|
if str =~ /^\s*(\w+)\s*=\s*([\w\d]+)\s*$/
param, value = $1.intern, $2
result[param] = value
raise ArgumentError, "Invalid file option '#{param}'" unless [:owner, :mode, :group].include?(param)
if param == :mode and value !~ /^\d+$/
raise ArgumentError, "File modes must be numbers"
end
else
raise ArgumentError, "Could not parse '#{string}'"
end
end
''
end
result[:value] = value.sub(/\s*$/, '')
result
end
# Convert arguments into booleans, integers, or whatever.
def munge_value(value)
# Handle different data types correctly
return case value
when /^false$/i; false
when /^true$/i; true
when /^\d+$/i; Integer(value)
when true; true
when false; false
else
value.gsub(/^["']|["']$/,'').sub(/\s+$/, '')
end
end
# This method just turns a file in to a hash of hashes.
def parse_file(file)
text = read_file(file)
result = Hash.new { |names, name|
names[name] = {}
}
count = 0
# Default to 'main' for the section.
section = :main
result[section][:_meta] = {}
text.split(/\n/).each do |line|
count += 1
case line
when /^\s*\[(\w+)\]\s*$/
section = $1.intern # Section names
#disallow application_defaults in config file
if section == :application_defaults
- raise Puppet::Error.new("Illegal section 'application_defaults' in config file", file, line)
+ raise Puppet::Error, "Illegal section 'application_defaults' in config file #{file} at line #{line}"
end
# Add a meta section
result[section][:_meta] ||= {}
when /^\s*#/; next # Skip comments
when /^\s*$/; next # Skip blanks
when /^\s*(\w+)\s*=\s*(.*?)\s*$/ # settings
var = $1.intern
# We don't want to munge modes, because they're specified in octal, so we'll
# just leave them as a String, since Puppet handles that case correctly.
if var == :mode
value = $2
else
value = munge_value($2)
end
# Check to see if this is a file argument and it has extra options
begin
if value.is_a?(String) and options = extract_fileinfo(value)
value = options[:value]
options.delete(:value)
result[section][:_meta][var] = options
end
result[section][var] = value
rescue Puppet::Error => detail
detail.file = file
detail.line = line
raise
end
else
error = Puppet::Error.new("Could not match line #{line}")
error.file = file
error.line = line
raise error
end
end
result
end
# Read the file in.
def read_file(file)
begin
return File.read(file)
rescue Errno::ENOENT
raise ArgumentError, "No such file #{file}"
rescue Errno::EACCES
raise ArgumentError, "Permission denied to file #{file}"
end
end
# Set file metadata.
def set_metadata(meta)
meta.each do |var, values|
values.each do |param, value|
@config[var].send(param.to_s + "=", value)
end
end
end
# Private method for internal test use only; allows to do a comprehensive clear of all settings between tests.
#
# @return nil
def clear_everything_for_tests()
@sync.synchronize do
unsafe_clear(true, true)
@global_defaults_initialized = false
@app_defaults_initialized = false
end
end
private :clear_everything_for_tests
end