summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2007-09-03 19:38:15 -0500
committerLuke Kanies <luke@madstop.com>2007-09-03 19:38:15 -0500
commit0faf76ee187c7fa7c67a7fb7e7c345897006b7d8 (patch)
tree21b680c617e869b11579172ab9aac33518db68da
parent9d70b9746c09f648efd6a315b3ea088da38ecd1e (diff)
downloadpuppet-0faf76ee187c7fa7c67a7fb7e7c345897006b7d8.tar.gz
puppet-0faf76ee187c7fa7c67a7fb7e7c345897006b7d8.tar.xz
puppet-0faf76ee187c7fa7c67a7fb7e7c345897006b7d8.zip
More refactoring. I have removed a few more extraneous methods from Scope, mostly just pointing directly to the compile, and I have begun (but commented out) the move to having resources to model each of the classes and nodes, in addition to the definitions. This will, again, enable a real Configuration object, and it will enable class versioning and similar features.
-rw-r--r--lib/puppet/parser/ast/definition.rb18
-rw-r--r--lib/puppet/parser/ast/hostclass.rb8
-rw-r--r--lib/puppet/parser/ast/node.rb10
-rw-r--r--lib/puppet/parser/ast/resourceoverride.rb2
-rw-r--r--lib/puppet/parser/compile.rb12
-rw-r--r--lib/puppet/parser/scope.rb71
-rwxr-xr-xtest/language/ast.rb2
-rwxr-xr-xtest/language/ast/definition.rb8
-rwxr-xr-xtest/language/ast/hostclass.rb14
-rwxr-xr-xtest/language/compile.rb4
-rwxr-xr-xtest/language/scope.rb47
11 files changed, 70 insertions, 126 deletions
diff --git a/lib/puppet/parser/ast/definition.rb b/lib/puppet/parser/ast/definition.rb
index cd59da8af..c350c2cdb 100644
--- a/lib/puppet/parser/ast/definition.rb
+++ b/lib/puppet/parser/ast/definition.rb
@@ -32,7 +32,7 @@ class Puppet::Parser::AST
resource = options[:resource]
# Create a new scope.
- scope = subscope(origscope, resource.title)
+ scope = subscope(origscope, resource)
scope.virtual = true if resource.virtual or origscope.virtual?
scope.exported = true if resource.exported or origscope.exported?
@@ -125,14 +125,22 @@ class Puppet::Parser::AST
end
# Create a new subscope in which to evaluate our code.
- def subscope(scope, name = nil)
+ def subscope(scope, resource = nil)
+ if resource
+ type = resource.type
+ else
+ type = self.classname
+ end
args = {
- :type => self.classname,
+ :resource => resource,
+ :type => type,
:keyword => self.keyword,
- :namespace => self.namespace
+ :namespace => self.namespace,
+ :source => self
}
- args[:name] = name if name
+ args[:name] = resource.title if resource
+
oldscope = scope
scope = scope.newscope(args)
scope.source = self
diff --git a/lib/puppet/parser/ast/hostclass.rb b/lib/puppet/parser/ast/hostclass.rb
index 8959dc900..41ca34432 100644
--- a/lib/puppet/parser/ast/hostclass.rb
+++ b/lib/puppet/parser/ast/hostclass.rb
@@ -24,7 +24,7 @@ class Puppet::Parser::AST
scope = options[:scope]
# Verify that we haven't already been evaluated. This is
# what provides the singleton aspect.
- if existing_scope = scope.class_scope(self)
+ if existing_scope = scope.compile.class_scope(self)
Puppet.debug "%s class already evaluated" % @type
return nil
end
@@ -38,7 +38,7 @@ class Puppet::Parser::AST
end
unless options[:nosubscope]
- scope = subscope(scope)
+ scope = subscope(scope, options[:resource])
end
if pnames
@@ -49,7 +49,7 @@ class Puppet::Parser::AST
# Set the class before we do anything else, so that it's set
# during the evaluation and can be inspected.
- scope.setclass(self)
+ scope.compile.class_set(self.classname, scope)
# Now evaluate our code, yo.
if self.code
@@ -65,7 +65,7 @@ class Puppet::Parser::AST
end
def parent_scope(scope, klass)
- if s = scope.class_scope(klass)
+ if s = scope.compile.class_scope(klass)
return s
else
raise Puppet::DevError, "Could not find scope for %s" % klass.fqname
diff --git a/lib/puppet/parser/ast/node.rb b/lib/puppet/parser/ast/node.rb
index 695c15f42..d46df3cff 100644
--- a/lib/puppet/parser/ast/node.rb
+++ b/lib/puppet/parser/ast/node.rb
@@ -33,7 +33,7 @@ class Puppet::Parser::AST
# Mark our node name as a class, too, but strip it of the domain
# name. Make the mark before we evaluate the code, so that it is
# marked within the code itself.
- scope.setclass(self)
+ scope.compile.class_set(self.classname, scope)
# And then evaluate our code if we have any
if self.code
@@ -53,6 +53,12 @@ class Puppet::Parser::AST
end
end
+ # Make sure node scopes are marked as such.
+ def subscope(*args)
+ scope = super
+ scope.nodescope = true
+ end
+
private
# Search for the object matching our parent class.
def find_parentclass
@@ -60,5 +66,3 @@ class Puppet::Parser::AST
end
end
end
-
-# $Id$
diff --git a/lib/puppet/parser/ast/resourceoverride.rb b/lib/puppet/parser/ast/resourceoverride.rb
index 26d69ae97..418c9c8e4 100644
--- a/lib/puppet/parser/ast/resourceoverride.rb
+++ b/lib/puppet/parser/ast/resourceoverride.rb
@@ -44,7 +44,7 @@ class Puppet::Parser::AST
# Now we tell the scope that it's an override, and it behaves as
# necessary.
- scope.setoverride(obj)
+ scope.compile.store_override(obj)
obj
end
diff --git a/lib/puppet/parser/compile.rb b/lib/puppet/parser/compile.rb
index 7159947bf..0ae712e57 100644
--- a/lib/puppet/parser/compile.rb
+++ b/lib/puppet/parser/compile.rb
@@ -111,20 +111,21 @@ class Puppet::Parser::Compile
# Evaluate all of the classes specified by the node.
def evaluate_node_classes
- evaluate_classes(@node.classes, @parser.findclass("", ""))
+ evaluate_classes(@node.classes, @topscope)
end
# Evaluate each specified class in turn. If there are any classes we can't
# find, just tag the configuration and move on. This method really just
# creates resource objects that point back to the classes, and then the
# resources are themselves evaluated later in the process.
- def evaluate_classes(classes, source)
+ def evaluate_classes(classes, scope)
found = []
classes.each do |name|
+ # If we can find the class, then make a resource that will evaluate it.
if klass = @parser.findclass("", name)
# This will result in class_set getting called, which
# will in turn result in tags. Yay.
- klass.safeevaluate(:scope => topscope)
+ klass.safeevaluate(:scope => scope)
found << name
else
Puppet.info "Could not find class %s for %s" % [name, node.name]
@@ -151,7 +152,7 @@ class Puppet::Parser::Compile
@resource_table[string]
end
- # Set up our configuration. We require a parser
+ # Set up our compile. We require a parser
# and a node object; the parser is so we can look up classes
# and AST nodes, and the node has all of the client's info,
# like facts and environment.
@@ -457,6 +458,9 @@ class Puppet::Parser::Compile
# Create our initial scope, our scope graph, and add the initial scope to the graph.
@topscope = Puppet::Parser::Scope.new(:compile => self, :type => "main", :name => "top", :parser => self.parser)
+ #@main = @parser.findclass("", "")
+ #@main_resource = Puppet::Parser::Resource.new(:type => "class", :title => :main, :scope => @topscope, :source => @main)
+ #@topscope.resource = @main_resource
# For maintaining scope relationships.
@scope_graph = GRATR::Digraph.new
diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index 635a471df..5f6f15ba6 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -15,14 +15,29 @@ class Puppet::Parser::Scope
include Enumerable
include Puppet::Util::Errors
- attr_accessor :parent, :level, :parser, :source
- attr_accessor :name, :type, :base, :keyword
- attr_accessor :top, :translated, :exported, :virtual, :compile
+ attr_accessor :parent, :level, :parser, :source, :resource
+ attr_accessor :base, :keyword, :nodescope
+ attr_accessor :top, :translated, :compile
+
+ # Temporary accessors.
+ attr_accessor :name, :type, :title, :exported, :virtual
+ def exported?
+ exported
+ end
+ def virtual?
+ virtual
+ end
+ #[:name, :type, :title, :exported?, :virtual].each do |method|
+ # define_method(method) do
+ # @resource.send(method)
+ # end
+ #end
# Proxy accessors
def host
@compile.node.name
end
+
def interpreter
@compile.interpreter
end
@@ -56,20 +71,11 @@ class Puppet::Parser::Scope
end
end
- # Retrieve a given class scope from the compile.
- def class_scope(klass)
- compile.class_scope(klass)
- end
-
# Are we the top scope?
def topscope?
@level == 1
end
- def exported?
- self.exported
- end
-
def findclass(name)
@namespaces.each do |namespace|
if r = parser.findclass(namespace, name)
@@ -164,7 +170,7 @@ class Puppet::Parser::Scope
unless klass
raise Puppet::ParseError, "Could not find class %s" % klassname
end
- unless kscope = class_scope(klass)
+ unless kscope = compile.class_scope(klass)
raise Puppet::ParseError, "Class %s has not been evaluated so its variables cannot be referenced" % klass.classname
end
return kscope.lookupvar(shortname, usestring)
@@ -209,7 +215,7 @@ class Puppet::Parser::Scope
# is required because of how often the names are used throughout
# the system, including on the client.
def nodescope?
- defined?(@nodescope) and @nodescope
+ self.nodescope
end
# We probably shouldn't cache this value... But it's a lot faster
@@ -231,37 +237,6 @@ class Puppet::Parser::Scope
end
end
- def resources
- @definedtable.values
- end
-
- # Store the fact that we've evaluated a given class. We use a hash
- # that gets inherited from the top scope down, rather than a global
- # hash. We store the object ID, not class name, so that we
- # can support multiple unrelated classes with the same name.
- def setclass(klass)
- if klass.is_a?(AST::HostClass)
- unless name = klass.classname
- raise Puppet::DevError, "Got a %s with no fully qualified name" %
- klass.class
- end
- @compile.class_set(name, self)
- else
- raise Puppet::DevError, "Invalid class %s" % klass.inspect
- end
- if klass.is_a?(AST::Node)
- @nodescope = true
- end
- nil
- end
-
- # Override a parameter in an existing object. If the object does not yet
- # exist, then cache the override in a global table, so it can be flushed
- # at the end.
- def setoverride(resource)
- @compile.store_override(resource)
- end
-
# Set defaults for a type. The typename should already be downcased,
# so that the syntax is isolated. We don't do any kind of type-checking
# here; instead we let the resource do it when the defaults are used.
@@ -433,10 +408,4 @@ class Puppet::Parser::Scope
@symtable.delete(var)
end
end
-
- def virtual?
- self.virtual || self.exported?
- end
end
-
-# $Id$
diff --git a/test/language/ast.rb b/test/language/ast.rb
index 847d24660..000a56a89 100755
--- a/test/language/ast.rb
+++ b/test/language/ast.rb
@@ -57,7 +57,7 @@ class TestAST < Test::Unit::TestCase
end
Puppet::Parser::Resource.expects(:new).with { |o| o.is_a?(Hash) }.returns(:override)
- scope.expects(:setoverride).with(:override)
+ scope.compile.expects(:store_override).with(:override)
ret = nil
assert_nothing_raised do
ret = ref.evaluate :scope => scope
diff --git a/test/language/ast/definition.rb b/test/language/ast/definition.rb
index 5a2e6ffea..51948b01f 100755
--- a/test/language/ast/definition.rb
+++ b/test/language/ast/definition.rb
@@ -110,10 +110,6 @@ class TestASTDefinition < Test::Unit::TestCase
# inside the loop so the subscope expectations work.
klass = parser.newdefine "yayness%s" % i
- subscope = klass.subscope(scope, "yayness%s" % i)
-
- klass.expects(:subscope).returns(subscope)
-
resource = stub 'resource',
:title => hash[:title],
:name => hash[:name] || hash[:title],
@@ -122,6 +118,10 @@ class TestASTDefinition < Test::Unit::TestCase
:exported => false,
:virtual => false
+ subscope = klass.subscope(scope, resource)
+
+ klass.expects(:subscope).returns(subscope)
+
if hash[:name]
resource.stubs(:to_hash).returns({:name => hash[:name]})
end
diff --git a/test/language/ast/hostclass.rb b/test/language/ast/hostclass.rb
index 62483730b..c88152913 100755
--- a/test/language/ast/hostclass.rb
+++ b/test/language/ast/hostclass.rb
@@ -36,7 +36,7 @@ class TestASTHostClass < Test::Unit::TestCase
klass.evaluate(:scope => scope)
end
- assert(scope.class_scope(klass), "Class was not considered evaluated")
+ assert(scope.compile.class_scope(klass), "Class was not considered evaluated")
tmp = scope.findresource("File[/tmp]")
assert(tmp, "Could not find file /tmp")
@@ -76,8 +76,8 @@ class TestASTHostClass < Test::Unit::TestCase
moresub.evaluate(:scope => scope)
end
- assert(scope.class_scope(newbase), "Did not eval newbase")
- assert(scope.class_scope(newsub), "Did not eval newsub")
+ assert(scope.compile.class_scope(newbase), "Did not eval newbase")
+ assert(scope.compile.class_scope(newsub), "Did not eval newsub")
yay = scope.findresource("File[/tmp/yay]")
assert(yay, "Did not find file /tmp/yay")
@@ -141,14 +141,14 @@ class TestASTHostClass < Test::Unit::TestCase
ret = nil
assert_nothing_raised do
- ret = scope.compile.evaluate_classes(["sub"], source)
+ ret = scope.compile.evaluate_classes(["sub"], scope)
end
- subscope = scope.class_scope(scope.findclass("sub"))
+ subscope = scope.compile.class_scope(scope.findclass("sub"))
assert(subscope, "could not find sub scope")
- mscope = scope.class_scope(scope.findclass("middle"))
+ mscope = scope.compile.class_scope(scope.findclass("middle"))
assert(mscope, "could not find middle scope")
- pscope = scope.class_scope(scope.findclass("base"))
+ pscope = scope.compile.class_scope(scope.findclass("base"))
assert(pscope, "could not find parent scope")
assert(pscope == mscope.parent, "parent scope of middle was not set correctly")
diff --git a/test/language/compile.rb b/test/language/compile.rb
index 5fde2500e..3128b8e64 100755
--- a/test/language/compile.rb
+++ b/test/language/compile.rb
@@ -270,10 +270,8 @@ class TestCompile < Test::Unit::TestCase
def test_evaluate_node_classes
config = mkconfig
- main = mock 'main'
- config.parser.expects(:findclass).with("", "").returns(main)
@node.classes = %w{one two three four}
- config.expects(:evaluate_classes).with(%w{one two three four}, main)
+ config.expects(:evaluate_classes).with(%w{one two three four}, config.topscope)
assert_nothing_raised("could not call evaluate_node_classes") do
config.send(:evaluate_node_classes)
end
diff --git a/test/language/scope.rb b/test/language/scope.rb
index fc5e085d4..43cbfd47c 100755
--- a/test/language/scope.rb
+++ b/test/language/scope.rb
@@ -94,7 +94,7 @@ class TestScope < Test::Unit::TestCase
classes = ["", "one", "one::two", "one::two::three"].each do |name|
klass = parser.newclass(name)
klass.evaluate(:scope => scope)
- scopes[name] = scope.class_scope(klass)
+ scopes[name] = scope.compile.class_scope(klass)
end
classes.each do |name|
@@ -188,13 +188,6 @@ class TestScope < Test::Unit::TestCase
assert_equal(top, sub.parent, "Did not find parent scope correctly")
assert_equal(top, sub.parent, "Did not find parent scope on second call")
end
-
- def test_class_scope
- config = mkconfig
- scope = config.topscope
- config.expects(:class_scope).with(:testing).returns(:myscope)
- assert_equal(:myscope, scope.class_scope(:testing), "Did not pass back the results of config.class_scope")
- end
def test_strinterp
# Make and evaluate our classes so the qualified lookups work
@@ -210,7 +203,7 @@ class TestScope < Test::Unit::TestCase
klass.evaluate(:scope => scope)
- scope = scope.class_scope("")
+ scope = scope.compile.class_scope("")
assert_nothing_raised {
scope.setvar("test","value")
}
@@ -220,7 +213,7 @@ class TestScope < Test::Unit::TestCase
%w{one one::two one::two::three}.each do |name|
klass = parser.newclass(name)
klass.evaluate(:scope => scope)
- scopes[name] = scope.class_scope(klass)
+ scopes[name] = scope.compile.class_scope(klass)
scopes[name].setvar("test", "value-%s" % name.sub(/.+::/,''))
end
@@ -274,38 +267,6 @@ class TestScope < Test::Unit::TestCase
end
end
- def test_setclass
- # Run through it when we're a normal class
- config = mkconfig
- scope = config.topscope
- klass = mock("class")
- klass.expects(:classname).returns(:myclass)
- klass.expects(:is_a?).with(AST::HostClass).returns(true)
- klass.expects(:is_a?).with(AST::Node).returns(false)
- config.expects(:class_set).with(:myclass, scope)
- scope.setclass(klass)
-
- # And when we're a node
- config = mkconfig
- scope = config.topscope
- klass = mock("class2")
- klass.expects(:classname).returns(:myclass)
- klass.expects(:is_a?).with(AST::HostClass).returns(true)
- klass.expects(:is_a?).with(AST::Node).returns(true)
- config.expects(:class_set).with(:myclass, scope)
- scope.setclass(klass)
- assert(scope.nodescope?, "Did not set the scope as a node scope when evaluating a node")
-
- # And when we're invalid
- config = mkconfig
- scope = config.topscope
- klass = mock("class3")
- klass.expects(:is_a?).with(AST::HostClass).returns(false)
- assert_raise(Puppet::DevError, "Did not fail when scope got passed a non-component") do
- scope.setclass(klass)
- end
- end
-
def test_validtags
scope = mkscope()
@@ -363,7 +324,7 @@ class TestScope < Test::Unit::TestCase
end
[myclass, otherclass].each do |klass|
- assert(scope.class_scope(klass),
+ assert(scope.compile.class_scope(klass),
"%s was not set" % klass.classname)
end
end