summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/interpreter.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/parser/interpreter.rb')
-rw-r--r--lib/puppet/parser/interpreter.rb251
1 files changed, 37 insertions, 214 deletions
diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb
index b4936dd23..9da1928b3 100644
--- a/lib/puppet/parser/interpreter.rb
+++ b/lib/puppet/parser/interpreter.rb
@@ -30,6 +30,7 @@ class Puppet::Parser::Interpreter
begin
options[:scope].function_include(classes.find_all { |c| options[:scope].findclass(c) })
rescue => detail
+ puts detail.backtrace
raise Puppet::ParseError, "Could not evaluate classes for %s: %s" % [name, detail]
end
end
@@ -59,6 +60,7 @@ class Puppet::Parser::Interpreter
class << self
attr_writer :ldap
end
+
# just shorten the constant path a bit, using what amounts to an alias
AST = Puppet::Parser::AST
@@ -105,10 +107,6 @@ class Puppet::Parser::Interpreter
end
end
- def clear
- initparsevars
- end
-
# Iteratively evaluate all of the objects. This finds all of the objects
# that represent definitions and evaluates the definitions appropriately.
# It also adds defaults and overrides as appropriate.
@@ -264,48 +262,13 @@ class Puppet::Parser::Interpreter
check_resource_collections(scope)
end
- # Find a class definition, relative to the current namespace.
+ # Create proxy methods, so the scopes can call the interpreter, since
+ # they don't have access to the parser.
def findclass(namespace, name)
- #find_or_load namespace, name, @classtable
- fqfind namespace, name, @classtable
+ @parser.findclass(namespace, name)
end
-
- # Find a component definition, relative to the current namespace.
def finddefine(namespace, name)
- #find_or_load namespace, name, @definetable
- fqfind namespace, name, @definetable
- end
-
- # The recursive method used to actually look these objects up.
- def fqfind(namespace, name, table)
- namespace = namespace.downcase
- name = name.downcase
- if name =~ /^::/ or namespace == ""
- classname = name.sub(/^::/, '')
- unless table[classname]
- self.load(classname)
- end
- return table[classname]
- end
- ary = namespace.split("::")
-
- while ary.length > 0
- newname = (ary + [name]).join("::").sub(/^::/, '')
- if obj = table[newname] or (self.load(newname) and obj = table[newname])
- return obj
- end
-
- # Delete the second to last object, which reduces our namespace by one.
- ary.pop
- end
-
- # If we've gotten to this point without finding it, see if the name
- # exists at the top namespace
- if obj = table[name] or (self.load(name) and obj = table[name])
- return obj
- end
-
- return nil
+ @parser.finddefine(namespace, name)
end
# create our interpreter
@@ -335,8 +298,6 @@ class Puppet::Parser::Interpreter
@setup = false
- initparsevars()
-
# Set it to either the value or nil. This is currently only used
# by the cfengine module.
@classes = hash[:Classes] || []
@@ -361,55 +322,11 @@ class Puppet::Parser::Interpreter
end
@files = []
- @loaded = []
# Create our parser object
parsefiles
end
- # Initialize or reset the variables related to parsing.
- def initparsevars
- @classtable = {}
- @namespace = "main"
-
- @nodetable = {}
-
- @definetable = {}
- end
-
- # Try to load a class, since we could not find it.
- def load(classname)
- return false if classname == ""
- filename = classname.gsub("::", File::SEPARATOR)
-
- loaded = false
- # First try to load the top-level module
- mod = filename.scan(/^[\w-]+/).shift
- unless @loaded.include?(mod)
- @loaded << mod
- begin
- @parser.import(mod)
- Puppet.info "Autoloaded module %s" % mod
- loaded = true
- rescue Puppet::ImportError => detail
- # We couldn't load the module
- end
- end
-
- unless filename == mod and ! @loaded.include?(mod)
- @loaded << mod
- # Then the individual file
- begin
- @parser.import(filename)
- Puppet.info "Autoloaded file %s from module %s" % [filename, mod]
- loaded = true
- rescue Puppet::ImportError => detail
- # We couldn't load the file
- end
- end
- return loaded
- end
-
# Find the ldap node, return the class list and parent node specially,
# and everything else in a parameter hash.
def ldapsearch(node)
@@ -505,115 +422,10 @@ class Puppet::Parser::Interpreter
end
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
-
- # Create a new class, or merge with an existing class.
- def newclass(name, options = {})
- name = name.downcase
- if @definetable.include?(name)
- raise Puppet::ParseError, "Cannot redefine class %s as a definition" %
- name
- end
- code = options[:code]
- parent = options[:parent]
-
- # If the class is already defined, then add code to it.
- if other = @classtable[name]
- # Make sure the parents match
- if parent and other.parentclass and (parent != other.parentclass)
- @parser.error("Class %s is already defined at %s:%s; cannot redefine" % [name, other.file, other.line])
- end
-
- # This might be dangerous...
- if parent and ! other.parentclass
- other.parentclass = parent
- end
-
- # This might just be an empty, stub class.
- if code
- tmp = name
- if tmp == ""
- tmp = "main"
- end
-
- Puppet.debug @parser.addcontext("Adding code to %s" % tmp)
- # Else, add our code to it.
- if other.code and code
- other.code.children += code.children
- else
- other.code ||= code
- end
- end
- else
- # Define it anew.
- # Note we're doing something somewhat weird here -- we're setting
- # the class's namespace to its fully qualified name. This means
- # anything inside that class starts looking in that namespace first.
- args = {:namespace => name, :classname => name, :interp => self}
- args[:code] = code if code
- args[:parentclass] = parent if parent
- @classtable[name] = @parser.ast AST::HostClass, args
- end
-
- return @classtable[name]
- end
-
- # Create a new definition.
- def newdefine(name, options = {})
- name = name.downcase
- if @classtable.include?(name)
- raise Puppet::ParseError, "Cannot redefine class %s as a definition" %
- name
- end
- # Make sure our definition doesn't already exist
- if other = @definetable[name]
- @parser.error("%s is already defined at %s:%s; cannot redefine" % [name, other.file, other.line])
- end
-
- ns, whatever = namesplit(name)
- args = {
- :namespace => ns,
- :arguments => options[:arguments],
- :code => options[:code],
- :classname => name
- }
-
- [:code, :arguments].each do |param|
- args[param] = options[param] if options[param]
- end
-
- @definetable[name] = @parser.ast AST::Component, args
- end
-
- # Create a new node. Nodes are special, because they're stored in a global
- # table, not according to namespaces.
- def newnode(names, options = {})
- names = [names] unless names.instance_of?(Array)
- names.collect do |name|
- name = name.to_s.downcase
- if other = @nodetable[name]
- @parser.error("Node %s is already defined at %s:%s; cannot redefine" % [other.name, other.file, other.line])
- end
- name = name.to_s if name.is_a?(Symbol)
- args = {
- :name => name,
- }
- if options[:code]
- args[:code] = options[:code]
- end
- if options[:parent]
- args[:parentclass] = options[:parent]
- end
- @nodetable[name] = @parser.ast(AST::Node, args)
- @nodetable[name].classname = name
- @nodetable[name].interp = self
- @nodetable[name]
+ # Pass these methods through to the parser.
+ [:newclass, :newdefine, :newnode].each do |name|
+ define_method(name) do |*args|
+ @parser.send(name, *args)
end
end
@@ -662,7 +474,7 @@ class Puppet::Parser::Interpreter
# See if our node was defined in the code.
def nodesearch_code(name)
- @nodetable[name]
+ @parser.nodes[name]
end
# Look for external node definitions.
@@ -815,29 +627,40 @@ class Puppet::Parser::Interpreter
end
end
- # Reset our parse tables.
- clear()
-
- # Create a new parser, just to keep things fresh.
- @parser = Puppet::Parser::Parser.new(self)
+ # Create a new parser, just to keep things fresh. Don't replace our
+ # current parser until we know weverything works.
+ newparser = Puppet::Parser::Parser.new()
if @code
- @parser.string = @code
+ newparser.string = @code
else
- @parser.file = @file
- # Mark when we parsed, so we can check freshness
- @parsedate = File.stat(@file).ctime.to_i
+ newparser.file = @file
end
# Parsing stores all classes and defines and such in their
# various tables, so we don't worry about the return.
- if @local
- @parser.parse
- else
- benchmark(:info, "Parsed manifest") do
- @parser.parse
+ begin
+ if @local
+ newparser.parse
+ else
+ benchmark(:info, "Parsed manifest") do
+ newparser.parse
+ end
+ end
+ # We've gotten this far, so it's ok to swap the parsers.
+ oldparser = @parser
+ @parser = newparser
+ if oldparser
+ oldparser.clear
+ end
+
+ # Mark when we parsed, so we can check freshness
+ @parsedate = Time.now.to_i
+ rescue => detail
+ if Puppet[:trace]
+ puts detail.backtrace
end
+ Puppet.err "Could not parse; using old configuration: %s" % detail
end
- @parsedate = Time.now.to_i
end
# Store the configs into the database.