diff options
| author | Luke Kanies <luke@madstop.com> | 2007-09-03 19:38:15 -0500 |
|---|---|---|
| committer | Luke Kanies <luke@madstop.com> | 2007-09-03 19:38:15 -0500 |
| commit | 0faf76ee187c7fa7c67a7fb7e7c345897006b7d8 (patch) | |
| tree | 21b680c617e869b11579172ab9aac33518db68da | |
| parent | 9d70b9746c09f648efd6a315b3ea088da38ecd1e (diff) | |
| download | puppet-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.rb | 18 | ||||
| -rw-r--r-- | lib/puppet/parser/ast/hostclass.rb | 8 | ||||
| -rw-r--r-- | lib/puppet/parser/ast/node.rb | 10 | ||||
| -rw-r--r-- | lib/puppet/parser/ast/resourceoverride.rb | 2 | ||||
| -rw-r--r-- | lib/puppet/parser/compile.rb | 12 | ||||
| -rw-r--r-- | lib/puppet/parser/scope.rb | 71 | ||||
| -rwxr-xr-x | test/language/ast.rb | 2 | ||||
| -rwxr-xr-x | test/language/ast/definition.rb | 8 | ||||
| -rwxr-xr-x | test/language/ast/hostclass.rb | 14 | ||||
| -rwxr-xr-x | test/language/compile.rb | 4 | ||||
| -rwxr-xr-x | test/language/scope.rb | 47 |
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 |
