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.rb126
1 files changed, 101 insertions, 25 deletions
diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index 3d1d690f5..b1b2b6b81 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -6,11 +6,13 @@ require 'puppet/transportable'
module Puppet
module Parser
class Scope
+ Puppet::Util.logmethods(self)
+
include Enumerable
attr_accessor :parent, :level, :interp
attr_accessor :name, :type, :topscope, :base, :keyword, :autoname
- attr_accessor :top
+ attr_accessor :top, :context
# This is probably not all that good of an idea, but...
# This way a parent can share its tables with all of its children.
@@ -40,7 +42,7 @@ module Puppet
obj.tags.each { |tag|
unless list.include?(tag)
if tag.nil? or tag == ""
- Puppet.warning "Got tag %s from %s(%s)" %
+ Puppet.debug "Got tag %s from %s(%s)" %
[tag.inspect, obj.type, obj.name]
else
list << tag
@@ -49,6 +51,14 @@ module Puppet
}
end
+ def declarative=(val)
+ self.class.declarative = val
+ end
+
+ def declarative
+ self.class.declarative
+ end
+
# Log the existing tags. At some point this should be in a better
# place, but eh.
def logtags
@@ -169,7 +179,12 @@ module Puppet
# 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, classes = nil, parent = nil)
+ #def evalnode(names, facts, classes = nil, parent = nil)
+ def evalnode(hash)
+ names = hash[:name]
+ facts = hash[:facts]
+ classes = hash[:classes]
+ parent = hash[:parent]
# First make sure there aren't any other node scopes lying around
self.nodeclean
@@ -203,7 +218,7 @@ module Puppet
# Note that we evaluate the node code with its containing
# scope, not with the top scope. We also retrieve the created
# nodescope so that we can get any classes set within it
- nodescope = code.safeevaluate(scope, facts)
+ nodescope = code.safeevaluate(:scope => scope, :facts => facts)
# We don't need to worry about removing the Node code because
# it will be removed during translation.
@@ -246,12 +261,17 @@ module Puppet
# Now evaluate it, which evaluates the parent but doesn't really
# do anything else but does return the nodescope
- scope = node.safeevaluate(self)
+ scope = node.safeevaluate(:scope => self)
# And now evaluate each set klass within the nodescope.
classes.each { |klass|
if code = scope.lookuptype(klass)
- code.safeevaluate(scope, {}, klass, klass)
+ #code.safeevaluate(scope, {}, klass, klass)
+ code.safeevaluate(
+ :scope => scope,
+ :facts => {},
+ :type => klass
+ )
end
}
@@ -288,18 +308,26 @@ module Puppet
# silly method, in that it just calls evaluate on the passed-in
# objects, and then calls to_trans on itself. It just conceals
# a paltry amount of info from whomever's using the scope object.
- def evaluate(objects, facts = {}, classes = [])
+ #def evaluate(objects, facts = {}, classes = [])
+ def evaluate(hash)
+ objects = hash[:ast]
+ facts = hash[:facts] || {}
+ classes = hash[:classes] || []
facts.each { |var, value|
self.setvar(var, value)
}
- objects.safeevaluate(self)
+ objects.safeevaluate(:scope => self)
# These classes would be passed in manually, via something like
# a cfengine module
classes.each { |klass|
if code = self.lookuptype(klass)
- code.safeevaluate(self, {}, klass, klass)
+ code.safeevaluate(
+ :scope => self,
+ :facts => {},
+ :type => klass
+ )
end
}
@@ -316,8 +344,20 @@ module Puppet
# Initialize our new scope. Defaults to having no parent and to
# being declarative.
- def initialize(parent = nil, declarative = true)
- @parent = parent
+ #def initialize(parent = nil, declarative = true)
+ def initialize(hash = {})
+ @parent = nil
+ @type = nil
+ @name = nil
+ hash.each { |name, val|
+ method = name.to_s + "="
+ if self.respond_to? method
+ self.send(method, val)
+ else
+ raise Puppet::DevError, "Invalid scope argument %s" % name
+ end
+ }
+ #@parent = hash[:parent]
@nodescope = false
@tags = []
@@ -326,12 +366,14 @@ module Puppet
# the level is mostly used for debugging
@level = 1
- @@declarative = declarative
-
# The table for storing class singletons. This will only actually
# be used by top scopes and node scopes.
@classtable = Hash.new(nil)
+ unless hash.include? :declarative
+ self.class.declarative = true
+ end
+
# The table for all defined objects. This will only be
# used in the top scope if we don't have any nodescopes.
@definedtable = Hash.new { |types, type|
@@ -356,11 +398,14 @@ module Puppet
names[name] = []
}
}
+
+ @context = nil
else
@parent.child = self
@level = @parent.level + 1
@interp = @parent.interp
@topscope = @parent.topscope
+ @context = @parent.context
end
# Our child scopes
@@ -408,7 +453,7 @@ module Puppet
# This method abstracts recursive searching. It accepts the type
# of search being done and then either a literal key to search for or
# a Proc instance to do the searching.
- def lookup(type,sub)
+ def lookup(type,sub, usecontext = false)
table = @map[type]
if table.nil?
error = Puppet::ParseError.new(
@@ -423,7 +468,13 @@ module Puppet
elsif table.include?(sub)
return table[sub]
elsif ! @parent.nil?
- return @parent.lookup(type,sub)
+ #self.notice "Context is %s, parent %s is %s" %
+ # [self.context, @parent.type, @parent.context]
+ if usecontext and self.context != @parent.context
+ return :undefined
+ else
+ return @parent.lookup(type,sub, usecontext)
+ end
else
return :undefined
end
@@ -488,7 +539,8 @@ module Puppet
end
end
- # Look up an object by name and type.
+ # Look up an object by name and type. This should only look up objects
+ # within a class structure, not within the entire scope structure.
def lookupobject(name,type)
#Puppet.debug "Looking up object %s of type %s in level %s" %
# [name, type, @level]
@@ -501,7 +553,7 @@ module Puppet
nil
end
}
- value = self.lookup("object",sub)
+ value = self.lookup("object",sub, true)
if value == :undefined
return nil
else
@@ -525,9 +577,10 @@ module Puppet
end
# Create a new scope.
- def newscope
+ def newscope(hash = {})
+ hash[:parent] = self
#Puppet.debug "Creating new scope, level %s" % [self.level + 1]
- return Puppet::Parser::Scope.new(self)
+ return Puppet::Parser::Scope.new(hash)
end
# Store the fact that we've evaluated a given class. We use a hash
@@ -601,13 +654,21 @@ module Puppet
# This method will fail if the named object is already defined anywhere
# in the scope tree, which is what provides some minimal closure-like
# behaviour.
- def setobject(type, name, params, file, line)
+ #def setobject(type, name, params, file, line)
+ def setobject(hash)
# FIXME This objectlookup stuff should be looking up using both
# the name and the namevar.
# First see if we can look the object up using normal scope
# rules, i.e., one of our parent classes has defined the
# object or something
+
+ name = hash[:name]
+ type = hash[:type]
+ params = hash[:arguments]
+ file = hash[:file]
+ line = hash[:line]
+
obj = self.lookupobject(name,type)
# If we can't find it...
@@ -632,6 +693,7 @@ module Puppet
end
# And if it's not, then create it anew
+ #self.info "Adding %s[%s] to table" % [type, name]
obj = @objectable[type][name]
# only set these if we've created the object, which is the
@@ -674,7 +736,8 @@ module Puppet
def tag(*ary)
ary.each { |tag|
if tag.nil? or tag == ""
- Puppet.warning "got told to tag with %s" % tag.inspect
+ Puppet.debug "got told to tag with %s" % tag.inspect
+ next
end
unless @tags.include?(tag)
#Puppet.info "Tagging scope %s with %s" % [self.object_id, tag]
@@ -693,7 +756,8 @@ module Puppet
if @parent
@parent.tags.each { |tag|
if tag.nil? or tag == ""
- Puppet.warning "parent returned tag %s" % tag.inspect
+ Puppet.debug "parent returned tag %s" % tag.inspect
+ next
end
unless tmp.include?(tag)
tmp << tag
@@ -703,6 +767,15 @@ module Puppet
return tmp
end
+ # Used mainly for logging
+ def to_s
+ if @name
+ return "%s[%s]" % [@type, @name]
+ else
+ return @type.to_s
+ end
+ end
+
# Convert our scope to a list of Transportable objects.
def to_trans
#Puppet.debug "Translating scope %s at level %s" %
@@ -765,10 +838,13 @@ module Puppet
# If we have a name and type, then make a TransBucket, which
# becomes a component.
# Else, just stack all of the objects into the current bucket.
- if defined? @name
+ if @type
bucket = TransBucket.new
- bucket.name = @name
- bucket.autoname = self.autoname
+
+ if defined? @name and @name
+ bucket.name = @name
+ bucket.autoname = self.autoname
+ end
# it'd be nice not to have to do this...
results.each { |result|