Extracted the code from Resource::Type#mk_plain_resource that
evaluates parents, adds the class to the catalog, and tags the
catalog, and moved that into a new method called instantiate_resource.
Instantiate_resource is now also called from
Parser::Ast::Resource#evaluate, so that the notation "class {
classname: }" now executes this code too.

Signed-off-by: Paul Berry <[email protected]>
---
 lib/puppet/parser/ast/resource.rb     |    6 +-
 lib/puppet/parser/compiler.rb         |    4 +-
 lib/puppet/resource/type.rb           |   26 +++--
 spec/unit/parser/ast/resource_spec.rb |  211 +++++++++++++++++++--------------
 spec/unit/parser/compiler_spec.rb     |   16 ++--
 spec/unit/resource/type_spec.rb       |   26 ++--
 6 files changed, 167 insertions(+), 122 deletions(-)

diff --git a/lib/puppet/parser/ast/resource.rb 
b/lib/puppet/parser/ast/resource.rb
index 6909c85..146d9b1 100644
--- a/lib/puppet/parser/ast/resource.rb
+++ b/lib/puppet/parser/ast/resource.rb
@@ -52,7 +52,11 @@ class Resource < AST::ResourceReference
         # And then store the resource in the compiler.
         # At some point, we need to switch all of this to return
         # resources instead of storing them like this.
-        scope.compiler.add_resource(scope, resource)
+        if resource.resource_type.is_a? Puppet::Resource::Type
+          resource.resource_type.instantiate_resource(scope, resource)
+        else
+          scope.compiler.add_resource(scope, resource)
+        end
         resource
       end
     }.reject { |resource| resource.nil? }
diff --git a/lib/puppet/parser/compiler.rb b/lib/puppet/parser/compiler.rb
index e1227e7..00ef000 100644
--- a/lib/puppet/parser/compiler.rb
+++ b/lib/puppet/parser/compiler.rb
@@ -144,7 +144,7 @@ class Puppet::Parser::Compiler
       if klass = scope.find_hostclass(name)
         found << name and next if scope.class_scope(klass)
 
-        resource = klass.mk_plain_resource(scope)
+        resource = klass.mk_singleton_resource(scope)
 
         # If they've disabled lazy evaluation (which the :include function 
does),
         # then evaluate our resource immediately.
@@ -220,7 +220,7 @@ class Puppet::Parser::Compiler
 
     # Create a resource to model this node, and then add it to the list
     # of resources.
-    resource = astnode.mk_plain_resource(topscope)
+    resource = astnode.mk_singleton_resource(topscope)
 
     resource.evaluate
 
diff --git a/lib/puppet/resource/type.rb b/lib/puppet/resource/type.rb
index 7b21e55..e9e6466 100644
--- a/lib/puppet/resource/type.rb
+++ b/lib/puppet/resource/type.rb
@@ -141,18 +141,10 @@ class Puppet::Resource::Type
   # Make an instance of our resource type.  This is only possible
   # for those classes and nodes that don't have any arguments, and is
   # only useful for things like the 'include' function.
-  def mk_plain_resource(scope)
+  def mk_singleton_resource(scope)
     type == :definition and raise ArgumentError, "Cannot create resources for 
defined resource types"
     resource_type = type == :hostclass ? :class : :node
 
-    # Make sure our parent class has been evaluated, if we have one.
-    if parent
-      parent_resource = scope.catalog.resource(resource_type, parent)
-      unless parent_resource
-        parent_type(scope).mk_plain_resource(scope)
-      end
-    end
-
     # Do nothing if the resource already exists; this makes sure we don't
     # get multiple copies of the class resource, which helps provide the
     # singleton nature of classes.
@@ -161,8 +153,22 @@ class Puppet::Resource::Type
     end
 
     resource = Puppet::Parser::Resource.new(resource_type, name, :scope => 
scope, :source => self)
+    instantiate_resource(scope, resource)
+  end
+
+  def instantiate_resource(scope, resource)
+    # Make sure our parent class has been evaluated, if we have one.
+    if parent
+      parent_resource = scope.catalog.resource(resource.type, parent)
+      unless parent_resource
+        parent_type(scope).mk_singleton_resource(scope)
+      end
+    end
+
     scope.compiler.add_resource(scope, resource)
-    scope.catalog.tag(*resource.tags)
+    if ['Class', 'Node'].include? resource.type
+      scope.catalog.tag(*resource.tags)
+    end
     resource
   end
 
diff --git a/spec/unit/parser/ast/resource_spec.rb 
b/spec/unit/parser/ast/resource_spec.rb
index 5c94ac0..5db4526 100755
--- a/spec/unit/parser/ast/resource_spec.rb
+++ b/spec/unit/parser/ast/resource_spec.rb
@@ -5,123 +5,158 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
 describe Puppet::Parser::AST::Resource do
   ast = Puppet::Parser::AST
 
-  before :each do
-    @title = Puppet::Parser::AST::String.new(:value => "mytitle")
-    @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
-    @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
-    @scope.stubs(:resource).returns(stub_everything)
-    @resource = ast::Resource.new(:title => @title, :type => "file", 
:parameters => ast::ASTArray.new(:children => []) )
-    @resource.stubs(:qualified_type).returns("Resource")
-  end
-
-  it "should evaluate all its parameters" do
-    param = stub 'param'
-    param.expects(:safeevaluate).with(@scope).returns 
Puppet::Parser::Resource::Param.new(:name => "myparam", :value => "myvalue", 
:source => stub("source"))
-    @resource.stubs(:parameters).returns [param]
-
-    @resource.evaluate(@scope)
-  end
-
-  it "should evaluate its title" do
-    @resource.evaluate(@scope)[0].title.should == "mytitle"
-  end
-
-  it "should flatten the titles array" do
-    titles = []
-    %w{one two}.each do |title|
-      titles << Puppet::Parser::AST::String.new(:value => title)
+  describe "for builtin types" do
+    before :each do
+      @title = Puppet::Parser::AST::String.new(:value => "mytitle")
+      @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
+      @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
+      @scope.stubs(:resource).returns(stub_everything)
+      @resource = ast::Resource.new(:title => @title, :type => "file", 
:parameters => ast::ASTArray.new(:children => []) )
+      @resource.stubs(:qualified_type).returns("Resource")
     end
 
-    array = Puppet::Parser::AST::ASTArray.new(:children => titles)
+    it "should evaluate all its parameters" do
+      param = stub 'param'
+      param.expects(:safeevaluate).with(@scope).returns 
Puppet::Parser::Resource::Param.new(:name => "myparam", :value => "myvalue", 
:source => stub("source"))
+      @resource.stubs(:parameters).returns [param]
 
-    @resource.title = array
-    result = @resource.evaluate(@scope).collect { |r| r.title }
-    result.should be_include("one")
-    result.should be_include("two")
-  end
+      @resource.evaluate(@scope)
+    end
 
-  it "should create and return one resource objects per title" do
-    titles = []
-    %w{one two}.each do |title|
-      titles << Puppet::Parser::AST::String.new(:value => title)
+    it "should evaluate its title" do
+      @resource.evaluate(@scope)[0].title.should == "mytitle"
     end
 
-    array = Puppet::Parser::AST::ASTArray.new(:children => titles)
+    it "should flatten the titles array" do
+      titles = []
+      %w{one two}.each do |title|
+        titles << Puppet::Parser::AST::String.new(:value => title)
+      end
 
-    @resource.title = array
-    result = @resource.evaluate(@scope).collect { |r| r.title }
-    result.should be_include("one")
-    result.should be_include("two")
-  end
+      array = Puppet::Parser::AST::ASTArray.new(:children => titles)
 
-  it "should handover resources to the compiler" do
-    titles = []
-    %w{one two}.each do |title|
-      titles << Puppet::Parser::AST::String.new(:value => title)
+      @resource.title = array
+      result = @resource.evaluate(@scope).collect { |r| r.title }
+      result.should be_include("one")
+      result.should be_include("two")
     end
 
-    array = Puppet::Parser::AST::ASTArray.new(:children => titles)
+    it "should create and return one resource objects per title" do
+      titles = []
+      %w{one two}.each do |title|
+        titles << Puppet::Parser::AST::String.new(:value => title)
+      end
 
-    @resource.title = array
-    result = @resource.evaluate(@scope)
+      array = Puppet::Parser::AST::ASTArray.new(:children => titles)
 
-    result.each do |res|
-      @compiler.catalog.resource(res.ref).should 
be_instance_of(Puppet::Parser::Resource)
+      @resource.title = array
+      result = @resource.evaluate(@scope).collect { |r| r.title }
+      result.should be_include("one")
+      result.should be_include("two")
     end
-  end
-  it "should generate virtual resources if it is virtual" do
-    @resource.virtual = true
 
-    result = @resource.evaluate(@scope)
-    result[0].should be_virtual
-  end
+    it "should handover resources to the compiler" do
+      titles = []
+      %w{one two}.each do |title|
+        titles << Puppet::Parser::AST::String.new(:value => title)
+      end
 
-  it "should generate virtual and exported resources if it is exported" do
-    @resource.exported = true
+      array = Puppet::Parser::AST::ASTArray.new(:children => titles)
 
-    result = @resource.evaluate(@scope)
-    result[0].should be_virtual
-    result[0].should be_exported
-  end
+      @resource.title = array
+      result = @resource.evaluate(@scope)
 
-  # Related to #806, make sure resources always look up the full path to the 
resource.
-  describe "when generating qualified resources" do
-    before do
-      @scope = Puppet::Parser::Scope.new :compiler => 
Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
-      @parser = Puppet::Parser::Parser.new(Puppet::Node::Environment.new)
-      @parser.newdefine "one"
-      @parser.newdefine "one::two"
-      @parser.newdefine "three"
-      @twoscope = @scope.newscope(:namespace => "one")
-      @twoscope.resource = @scope.resource
+      result.each do |res|
+        @compiler.catalog.resource(res.ref).should 
be_instance_of(Puppet::Parser::Resource)
+      end
     end
 
-    def resource(type, params = nil)
-      params ||= Puppet::Parser::AST::ASTArray.new(:children => [])
-      Puppet::Parser::AST::Resource.new(:type => type, :title => 
Puppet::Parser::AST::String.new(:value => "myresource"), :parameters => params)
+    it "should generate virtual resources if it is virtual" do
+      @resource.virtual = true
+
+      result = @resource.evaluate(@scope)
+      result[0].should be_virtual
     end
 
-    it "should be able to generate resources with fully qualified type 
information" do
-      resource("two").evaluate(@twoscope)[0].type.should == "One::Two"
+    it "should generate virtual and exported resources if it is exported" do
+      @resource.exported = true
+
+      result = @resource.evaluate(@scope)
+      result[0].should be_virtual
+      result[0].should be_exported
     end
 
-    it "should be able to generate resources with unqualified type 
information" do
-      resource("one").evaluate(@twoscope)[0].type.should == "One"
+    # Related to #806, make sure resources always look up the full path to the 
resource.
+    describe "when generating qualified resources" do
+      before do
+        @scope = Puppet::Parser::Scope.new :compiler => 
Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
+        @parser = Puppet::Parser::Parser.new(Puppet::Node::Environment.new)
+        @parser.newdefine "one"
+        @parser.newdefine "one::two"
+        @parser.newdefine "three"
+        @twoscope = @scope.newscope(:namespace => "one")
+        @twoscope.resource = @scope.resource
+      end
+
+      def resource(type, params = nil)
+        params ||= Puppet::Parser::AST::ASTArray.new(:children => [])
+        Puppet::Parser::AST::Resource.new(:type => type, :title => 
Puppet::Parser::AST::String.new(:value => "myresource"), :parameters => params)
+      end
+
+      it "should be able to generate resources with fully qualified type 
information" do
+        resource("two").evaluate(@twoscope)[0].type.should == "One::Two"
+      end
+
+      it "should be able to generate resources with unqualified type 
information" do
+        resource("one").evaluate(@twoscope)[0].type.should == "One"
+      end
+
+      it "should correctly generate resources that can look up builtin types" 
do
+        resource("file").evaluate(@twoscope)[0].type.should == "File"
+      end
+
+      it "should correctly generate resources that can look up defined classes 
by title" do
+        @scope.known_resource_types.add_hostclass 
Puppet::Resource::Type.new(:hostclass, "Myresource", {})
+        res = resource("class").evaluate(@twoscope)[0]
+        res.type.should == "Class"
+        res.title.should == "Myresource"
+      end
+
+      it "should fail for resource types that do not exist" do
+        lambda { resource("nosuchtype").evaluate(@twoscope) }.should 
raise_error(Puppet::ParseError)
+      end
     end
+  end
 
-    it "should correctly generate resources that can look up builtin types" do
-      resource("file").evaluate(@twoscope)[0].type.should == "File"
+  describe "for class resources" do
+    before do
+      @title = Puppet::Parser::AST::String.new(:value => "classname")
+      @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
+      @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
+      @scope.stubs(:resource).returns(stub_everything)
+      @resource = ast::Resource.new(:title => @title, :type => "Class", 
:parameters => ast::ASTArray.new(:children => []) )
+      @resource.stubs(:qualified_type).returns("Resource")
+      @type = Puppet::Resource::Type.new(:hostclass, "classname")
+      @compiler.known_resource_types.add(@type)
     end
 
-    it "should correctly generate resources that can look up defined classes 
by title" do
-      @scope.known_resource_types.add_hostclass 
Puppet::Resource::Type.new(:hostclass, "Myresource", {})
-      res = resource("class").evaluate(@twoscope)[0]
-      res.type.should == "Class"
-      res.title.should == "Myresource"
+    it "should instantiate the class" do
+      result = @resource.evaluate(@scope)
+      result.length.should == 1
+      result.first.ref.should == "Class[Classname]"
+      @compiler.catalog.resource("Class[Classname]").should equal result.first
     end
 
-    it "should fail for resource types that do not exist" do
-      lambda { resource("nosuchtype").evaluate(@twoscope) }.should 
raise_error(Puppet::ParseError)
+    it "should cause its parent to be evaluated" do
+      parent_type = Puppet::Resource::Type.new(:hostclass, "parentname")
+      @compiler.known_resource_types.add(parent_type)
+      @type.parent = "parentname"
+      result = @resource.evaluate(@scope)
+      result.length.should == 1
+      result.first.ref.should == "Class[Classname]"
+      @compiler.catalog.resource("Class[Classname]").should equal result.first
+      @compiler.catalog.resource("Class[Parentname]").should 
be_instance_of(Puppet::Parser::Resource)
     end
   end
+
 end
diff --git a/spec/unit/parser/compiler_spec.rb 
b/spec/unit/parser/compiler_spec.rb
index 22d52f2..53b7085 100755
--- a/spec/unit/parser/compiler_spec.rb
+++ b/spec/unit/parser/compiler_spec.rb
@@ -580,7 +580,7 @@ describe Puppet::Parser::Compiler do
     it "should evaluate each class" do
       @compiler.catalog.stubs(:tag)
 
-      @class.expects(:mk_plain_resource).with(@scope)
+      @class.expects(:mk_singleton_resource).with(@scope)
       @scope.stubs(:class_scope).with(@class)
 
       @compiler.evaluate_classes(%w{myclass}, @scope)
@@ -591,7 +591,7 @@ describe Puppet::Parser::Compiler do
 
       @resource.expects(:evaluate).never
 
-      @class.expects(:mk_plain_resource).returns(@resource)
+      @class.expects(:mk_singleton_resource).returns(@resource)
       @scope.stubs(:class_scope).with(@class)
 
       @compiler.evaluate_classes(%w{myclass}, @scope)
@@ -601,7 +601,7 @@ describe Puppet::Parser::Compiler do
       @compiler.catalog.stubs(:tag)
 
       @resource.expects(:evaluate)
-      @class.expects(:mk_plain_resource).returns(@resource)
+      @class.expects(:mk_singleton_resource).returns(@resource)
       @scope.stubs(:class_scope).with(@class)
 
       @compiler.evaluate_classes(%w{myclass}, @scope, false)
@@ -638,7 +638,7 @@ describe Puppet::Parser::Compiler do
       @scope.stubs(:class_scope).with(@class)
 
       Puppet::Parser::Resource.stubs(:new).returns(@resource)
-      @class.stubs :mk_plain_resource
+      @class.stubs :mk_singleton_resource
       @compiler.evaluate_classes(%w{myclass notfound}, @scope).should == 
%w{myclass}
     end
   end
@@ -678,7 +678,7 @@ describe Puppet::Parser::Compiler do
       @compiler.known_resource_types.stubs(:node).with("c").returns(node_class)
 
       node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => 
nil, :type => "node"
-      node_class.expects(:mk_plain_resource).returns(node_resource)
+      node_class.expects(:mk_singleton_resource).returns(node_resource)
 
       @compiler.compile
     end
@@ -688,7 +688,7 @@ describe Puppet::Parser::Compiler do
       
@compiler.known_resource_types.stubs(:node).with("default").returns(node_class)
 
       node_resource = stub 'node resource', :ref => "Node[default]", :evaluate 
=> nil, :type => "node"
-      node_class.expects(:mk_plain_resource).returns(node_resource)
+      node_class.expects(:mk_singleton_resource).returns(node_resource)
 
       @compiler.compile
     end
@@ -698,7 +698,7 @@ describe Puppet::Parser::Compiler do
       @compiler.known_resource_types.stubs(:node).with("c").returns(node_class)
 
       node_resource = stub 'node resource', :ref => "Node[c]", :type => "node"
-      node_class.expects(:mk_plain_resource).returns(node_resource)
+      node_class.expects(:mk_singleton_resource).returns(node_resource)
 
       node_resource.expects(:evaluate)
 
@@ -707,7 +707,7 @@ describe Puppet::Parser::Compiler do
 
     it "should set the node's scope as the top scope" do
       node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => 
nil, :type => "node"
-      node_class = stub 'node', :name => "c", :mk_plain_resource => 
node_resource
+      node_class = stub 'node', :name => "c", :mk_singleton_resource => 
node_resource
 
       @compiler.known_resource_types.stubs(:node).with("c").returns(node_class)
 
diff --git a/spec/unit/resource/type_spec.rb b/spec/unit/resource/type_spec.rb
index f58092e..e725751 100755
--- a/spec/unit/resource/type_spec.rb
+++ b/spec/unit/resource/type_spec.rb
@@ -580,29 +580,29 @@ describe Puppet::Resource::Type do
     end
 
     it "should create a resource instance" do
-      @top.mk_plain_resource(@scope).should 
be_instance_of(Puppet::Parser::Resource)
+      @top.mk_singleton_resource(@scope).should 
be_instance_of(Puppet::Parser::Resource)
     end
 
     it "should set its resource type to 'class' when it is a hostclass" do
-      Puppet::Resource::Type.new(:hostclass, 
"top").mk_plain_resource(@scope).type.should == "Class"
+      Puppet::Resource::Type.new(:hostclass, 
"top").mk_singleton_resource(@scope).type.should == "Class"
     end
 
     it "should set its resource type to 'node' when it is a node" do
-      Puppet::Resource::Type.new(:node, 
"top").mk_plain_resource(@scope).type.should == "Node"
+      Puppet::Resource::Type.new(:node, 
"top").mk_singleton_resource(@scope).type.should == "Node"
     end
 
     it "should fail when it is a definition" do
-      lambda { Puppet::Resource::Type.new(:definition, 
"top").mk_plain_resource(@scope) }.should raise_error(ArgumentError)
+      lambda { Puppet::Resource::Type.new(:definition, 
"top").mk_singleton_resource(@scope) }.should raise_error(ArgumentError)
     end
 
     it "should add the created resource to the scope's catalog" do
-      @top.mk_plain_resource(@scope)
+      @top.mk_singleton_resource(@scope)
 
       @compiler.catalog.resource(:class, "top").should 
be_instance_of(Puppet::Parser::Resource)
     end
 
     it "should evaluate the parent class if one exists" do
-      @middle.mk_plain_resource(@scope)
+      @middle.mk_singleton_resource(@scope)
 
       @compiler.catalog.resource(:class, "top").should 
be_instance_of(Puppet::Parser::Resource)
     end
@@ -610,40 +610,40 @@ describe Puppet::Resource::Type do
     it "should fail to evaluate if a parent class is defined but cannot be 
found" do
       othertop = Puppet::Resource::Type.new :hostclass, "something", :parent 
=> "yay"
       @code.add othertop
-      lambda { othertop.mk_plain_resource(@scope) }.should 
raise_error(Puppet::ParseError)
+      lambda { othertop.mk_singleton_resource(@scope) }.should 
raise_error(Puppet::ParseError)
     end
 
     it "should not create a new resource if one already exists" do
       @compiler.catalog.expects(:resource).with(:class, 
"top").returns("something")
       @compiler.catalog.expects(:add_resource).never
-      @top.mk_plain_resource(@scope)
+      @top.mk_singleton_resource(@scope)
     end
 
     it "should return the existing resource when not creating a new one" do
       @compiler.catalog.expects(:resource).with(:class, 
"top").returns("something")
       @compiler.catalog.expects(:add_resource).never
-      @top.mk_plain_resource(@scope).should == "something"
+      @top.mk_singleton_resource(@scope).should == "something"
     end
 
     it "should not create a new parent resource if one already exists and it 
has a parent class" do
-      @top.mk_plain_resource(@scope)
+      @top.mk_singleton_resource(@scope)
 
       top_resource = @compiler.catalog.resource(:class, "top")
 
-      @middle.mk_plain_resource(@scope)
+      @middle.mk_singleton_resource(@scope)
 
       @compiler.catalog.resource(:class, "top").should equal(top_resource)
     end
 
     # #795 - tag before evaluation.
     it "should tag the catalog with the resource tags when it is evaluated" do
-      @middle.mk_plain_resource(@scope)
+      @middle.mk_singleton_resource(@scope)
 
       @compiler.catalog.should be_tagged("middle")
     end
 
     it "should tag the catalog with the parent class tags when it is 
evaluated" do
-      @middle.mk_plain_resource(@scope)
+      @middle.mk_singleton_resource(@scope)
 
       @compiler.catalog.should be_tagged("top")
     end
-- 
1.7.2

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to