summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/scope.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/parser/scope.rb')
-rw-r--r--lib/puppet/parser/scope.rb144
1 files changed, 121 insertions, 23 deletions
diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index 37e5c39b7..56bf620dd 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -38,6 +38,30 @@ module Puppet
@@declarative
end
+ # Remove a specific child.
+ def delete(child)
+ @children.delete(child)
+ end
+
+ # Verify that no nodescopes are hanging around.
+ def nodeclean
+ @children.find_all { |child|
+ if child.is_a?(Scope)
+ child.nodescope?
+ else
+ false
+ end
+ }.each { |child|
+ @children.delete(child)
+ }
+
+ @children.each { |child|
+ if child.is_a?(Scope)
+ child.nodeclean
+ end
+ }
+ end
+
# Is this scope associated with being a node? The answer determines
# whether we store class instances here
def nodescope?
@@ -60,6 +84,65 @@ module Puppet
}
end
+ # Evaluate a specific node's code. This method will normally be called
+ # on the top-level scope, but it actually evaluates the node at the
+ # appropriate scope.
+ def evalnode(names, facts)
+ scope = code = nil
+ names.each { |node|
+ scope, code = self.findnode(node)
+ if scope and code
+ break
+ end
+ }
+
+ unless scope and code
+ raise Puppet::Error, "Could not find configuration for %s" %
+ names.join(" or ")
+ end
+
+ # First make sure there aren't any other node scopes lying around
+ self.nodeclean
+
+ # We need to do a little skullduggery here. We want a
+ # temporary scope, because we don't want this scope to
+ # show up permanently in the scope tree -- otherwise we could
+ # not evaluate the node multiple times. We could conceivably
+ # cache the results, but it's not worth it at this stage.
+
+ # Note that we evaluate the node code with its containing
+ # scope, not with the top scope.
+ code.safeevaluate(scope, facts)
+
+ # We don't need to worry about removing the Node code because
+ # it will be removed during translation.
+
+ # And now return the whole thing
+ return self.to_trans
+ end
+
+ # Find a given node's definition; searches downward recursively.
+ def findnode(node)
+ if @nodetable.include?(node)
+ return [self, @nodetable[node]]
+ else
+ self.find { |child|
+ child.findnode(node)
+ }
+ end
+ end
+
+ # Evaluate normally, with no node definitions
+ def evaluate(objects, facts = {})
+ facts.each { |var, value|
+ self.setvar(var, value)
+ }
+
+ objects.safeevaluate(self)
+
+ return self.to_trans
+ end
+
# Initialize our new scope. Defaults to having no parent and to
# being declarative.
def initialize(parent = nil, declarative = true)
@@ -88,6 +171,9 @@ module Puppet
# be used by top scopes and node scopes.
@classtable = Hash.new(nil)
+ # A table for storing nodes.
+ @nodetable = Hash.new(nil)
+
# All of the defaults set for types. It's a hash of hashes,
# with the first key being the type, then the second key being
# the parameter.
@@ -115,6 +201,7 @@ module Puppet
@map = {
"variable" => @symtable,
"type" => @typetable,
+ "node" => @nodetable,
"object" => @objectable,
"defaults" => @defaultstable
}
@@ -193,6 +280,18 @@ module Puppet
return values
end
+ # Look up a node by name
+ def lookupnode(name)
+ Puppet.debug "Looking up type %s" % name
+ value = self.lookup("type",name)
+ if value == :undefined
+ return nil
+ else
+ Puppet.debug "Found type %s" % name
+ return value
+ end
+ end
+
# Look up a defined type.
def lookuptype(name)
Puppet.debug "Looking up type %s" % name
@@ -209,18 +308,16 @@ module Puppet
def lookupobject(name,type)
Puppet.debug "Looking up object %s of type %s in level %s" %
[name, type, @level]
- unless defined? @@objectsearch
- @@objectsearch = proc { |table|
- if table.include?(type)
- if table[type].include?(name)
- table[type][name]
- end
- else
- nil
+ sub = proc { |table|
+ if table.include?(type)
+ if table[type].include?(name)
+ table[type][name]
end
- }
- end
- value = self.lookup("object",@@objectsearch)
+ else
+ nil
+ end
+ }
+ value = self.lookup("object",sub)
if value == :undefined
return nil
else
@@ -294,20 +391,14 @@ module Puppet
end
# Store a host in the global table.
- def sethost(name,host)
- if @@hosttable.include?(name)
- str = "Host %s is already defined" % name
- if @@hosttable[name].file
- str += " in file %s" % @@hosttable[name].file
- end
- if @@hosttable[name].line
- str += " on line %s" % @@hosttable[name].line
- end
- raise Puppet::ParseError,
- "Host %s is already defined" % name
+ def setnode(name,code)
+ if @nodetable.include?(name)
+ raise Puppet::Error, "Host %s is already defined" % name
else
- @@hosttable[name] = host
+ @nodetable[name] = code
end
+
+ #self.nodescope = true
end
# Define our type.
@@ -406,6 +497,13 @@ module Puppet
# Otherwise, just add it to our list of results.
results.push(cresult)
end
+
+ # Nodescopes are one-time; once they've been evaluated
+ # I need to destroy them. Nodeclean makes sure this is
+ # done correctly, but this should catch most of them.
+ if child.nodescope?
+ @children.delete(child)
+ end
elsif child.is_a?(TransObject)
results.push(child)
else