diff options
-rwxr-xr-x | spec/unit/resource/catalog.rb | 1332 |
1 files changed, 667 insertions, 665 deletions
diff --git a/spec/unit/resource/catalog.rb b/spec/unit/resource/catalog.rb index 27e6296c6..a0b64bc47 100755 --- a/spec/unit/resource/catalog.rb +++ b/spec/unit/resource/catalog.rb @@ -2,631 +2,633 @@ require File.dirname(__FILE__) + '/../../spec_helper' -describe Puppet::Resource::Catalog, " when compiling" do - it "should accept tags" do - config = Puppet::Resource::Catalog.new("mynode") - config.tag("one") - config.tags.should == %w{one} - end - - it "should accept multiple tags at once" do - config = Puppet::Resource::Catalog.new("mynode") - config.tag("one", "two") - config.tags.should == %w{one two} +describe Puppet::Resource::Catalog, "when compiling" do + it "should be an Expirer" do + Puppet::Resource::Catalog.ancestors.should be_include(Puppet::Util::Cacher::Expirer) end - it "should convert all tags to strings" do - config = Puppet::Resource::Catalog.new("mynode") - config.tag("one", :two) - config.tags.should == %w{one two} + it "should always be expired if it's not applying" do + @catalog = Puppet::Resource::Catalog.new("host") + @catalog.expects(:applying?).returns false + @catalog.should be_expired(Time.now) end - it "should tag with both the qualified name and the split name" do - config = Puppet::Resource::Catalog.new("mynode") - config.tag("one::two") - config.tags.include?("one").should be_true - config.tags.include?("one::two").should be_true + it "should not be expired if it's applying and the timestamp is late enough" do + @catalog = Puppet::Resource::Catalog.new("host") + @catalog.expire + @catalog.expects(:applying?).returns true + @catalog.should_not be_expired(Time.now) end - it "should accept classes" do - config = Puppet::Resource::Catalog.new("mynode") - config.add_class("one") - config.classes.should == %w{one} - config.add_class("two", "three") - config.classes.should == %w{one two three} - end + describe "when compiling" do + it "should accept tags" do + config = Puppet::Resource::Catalog.new("mynode") + config.tag("one") + config.tags.should == %w{one} + end - it "should tag itself with passed class names" do - config = Puppet::Resource::Catalog.new("mynode") - config.add_class("one") - config.tags.should == %w{one} - end -end + it "should accept multiple tags at once" do + config = Puppet::Resource::Catalog.new("mynode") + config.tag("one", "two") + config.tags.should == %w{one two} + end -describe Puppet::Resource::Catalog, " when extracting" do - it "should return extraction result as the method result" do - config = Puppet::Resource::Catalog.new("mynode") - config.expects(:extraction_format).returns(:whatever) - config.expects(:extract_to_whatever).returns(:result) - config.extract.should == :result - end -end + it "should convert all tags to strings" do + config = Puppet::Resource::Catalog.new("mynode") + config.tag("one", :two) + config.tags.should == %w{one two} + end -describe Puppet::Resource::Catalog, " when extracting transobjects" do + it "should tag with both the qualified name and the split name" do + config = Puppet::Resource::Catalog.new("mynode") + config.tag("one::two") + config.tags.include?("one").should be_true + config.tags.include?("one::two").should be_true + end - def mkscope - @parser = Puppet::Parser::Parser.new :Code => "" - @node = Puppet::Node.new("mynode") - @compiler = Puppet::Parser::Compiler.new(@node, @parser) + it "should accept classes" do + config = Puppet::Resource::Catalog.new("mynode") + config.add_class("one") + config.classes.should == %w{one} + config.add_class("two", "three") + config.classes.should == %w{one two three} + end - # XXX This is ridiculous. - @compiler.send(:evaluate_main) - @scope = @compiler.topscope + it "should tag itself with passed class names" do + config = Puppet::Resource::Catalog.new("mynode") + config.add_class("one") + config.tags.should == %w{one} + end end - def mkresource(type, name) - Puppet::Parser::Resource.new(:type => type, :title => name, :source => @source, :scope => @scope) + describe "when extracting" do + it "should return extraction result as the method result" do + config = Puppet::Resource::Catalog.new("mynode") + config.expects(:extraction_format).returns(:whatever) + config.expects(:extract_to_whatever).returns(:result) + config.extract.should == :result + end end - it "should always create a TransBucket for the 'main' class" do - config = Puppet::Resource::Catalog.new("mynode") + describe "when extracting transobjects" do - @scope = mkscope - @source = mock 'source' + def mkscope + @parser = Puppet::Parser::Parser.new :Code => "" + @node = Puppet::Node.new("mynode") + @compiler = Puppet::Parser::Compiler.new(@node, @parser) - main = mkresource("class", :main) - config.add_vertex(main) + # XXX This is ridiculous. + @compiler.send(:evaluate_main) + @scope = @compiler.topscope + end - bucket = mock 'bucket' - bucket.expects(:classes=).with(config.classes) - main.stubs(:builtin?).returns(false) - main.expects(:to_transbucket).returns(bucket) + def mkresource(type, name) + Puppet::Parser::Resource.new(:type => type, :title => name, :source => @source, :scope => @scope) + end - config.extract_to_transportable.should equal(bucket) - end + it "should always create a TransBucket for the 'main' class" do + config = Puppet::Resource::Catalog.new("mynode") - # This isn't really a spec-style test, but I don't know how better to do it. - it "should transform the resource graph into a tree of TransBuckets and TransObjects" do - config = Puppet::Resource::Catalog.new("mynode") + @scope = mkscope + @source = mock 'source' - @scope = mkscope - @source = mock 'source' + main = mkresource("class", :main) + config.add_vertex(main) - defined = mkresource("class", :main) - builtin = mkresource("file", "/yay") + bucket = mock 'bucket' + bucket.expects(:classes=).with(config.classes) + main.stubs(:builtin?).returns(false) + main.expects(:to_transbucket).returns(bucket) - config.add_edge(defined, builtin) + config.extract_to_transportable.should equal(bucket) + end - bucket = [] - bucket.expects(:classes=).with(config.classes) - defined.stubs(:builtin?).returns(false) - defined.expects(:to_transbucket).returns(bucket) - builtin.expects(:to_transobject).returns(:builtin) + # This isn't really a spec-style test, but I don't know how better to do it. + it "should transform the resource graph into a tree of TransBuckets and TransObjects" do + config = Puppet::Resource::Catalog.new("mynode") - config.extract_to_transportable.should == [:builtin] - end + @scope = mkscope + @source = mock 'source' - # Now try it with a more complicated graph -- a three tier graph, each tier - it "should transform arbitrarily deep graphs into isomorphic trees" do - config = Puppet::Resource::Catalog.new("mynode") - - @scope = mkscope - @scope.stubs(:tags).returns([]) - @source = mock 'source' - - # Create our scopes. - top = mkresource "class", :main - topbucket = [] - topbucket.expects(:classes=).with([]) - top.expects(:to_trans).returns(topbucket) - topres = mkresource "file", "/top" - topres.expects(:to_trans).returns(:topres) - config.add_edge top, topres - - middle = mkresource "class", "middle" - middle.expects(:to_trans).returns([]) - config.add_edge top, middle - midres = mkresource "file", "/mid" - midres.expects(:to_trans).returns(:midres) - config.add_edge middle, midres - - bottom = mkresource "class", "bottom" - bottom.expects(:to_trans).returns([]) - config.add_edge middle, bottom - botres = mkresource "file", "/bot" - botres.expects(:to_trans).returns(:botres) - config.add_edge bottom, botres - - toparray = config.extract_to_transportable - - # This is annoying; it should look like: - # [[[:botres], :midres], :topres] - # but we can't guarantee sort order. - toparray.include?(:topres).should be_true - - midarray = toparray.find { |t| t.is_a?(Array) } - midarray.include?(:midres).should be_true - botarray = midarray.find { |t| t.is_a?(Array) } - botarray.include?(:botres).should be_true - end -end + defined = mkresource("class", :main) + builtin = mkresource("file", "/yay") -describe Puppet::Resource::Catalog, " when converting to a transobject catalog" do - class CatalogTestResource - attr_accessor :name, :virtual, :builtin - def initialize(name, options = {}) - @name = name - options.each { |p,v| send(p.to_s + "=", v) } - end + config.add_edge(defined, builtin) - def ref - if builtin? - "File[%s]" % name - else - "Class[%s]" % name - end - end + bucket = [] + bucket.expects(:classes=).with(config.classes) + defined.stubs(:builtin?).returns(false) + defined.expects(:to_transbucket).returns(bucket) + builtin.expects(:to_transobject).returns(:builtin) - def virtual? - virtual + config.extract_to_transportable.should == [:builtin] end - def builtin? - builtin - end - - def to_transobject - Puppet::TransObject.new(name, builtin? ? "file" : "class") + # Now try it with a more complicated graph -- a three tier graph, each tier + it "should transform arbitrarily deep graphs into isomorphic trees" do + config = Puppet::Resource::Catalog.new("mynode") + + @scope = mkscope + @scope.stubs(:tags).returns([]) + @source = mock 'source' + + # Create our scopes. + top = mkresource "class", :main + topbucket = [] + topbucket.expects(:classes=).with([]) + top.expects(:to_trans).returns(topbucket) + topres = mkresource "file", "/top" + topres.expects(:to_trans).returns(:topres) + config.add_edge top, topres + + middle = mkresource "class", "middle" + middle.expects(:to_trans).returns([]) + config.add_edge top, middle + midres = mkresource "file", "/mid" + midres.expects(:to_trans).returns(:midres) + config.add_edge middle, midres + + bottom = mkresource "class", "bottom" + bottom.expects(:to_trans).returns([]) + config.add_edge middle, bottom + botres = mkresource "file", "/bot" + botres.expects(:to_trans).returns(:botres) + config.add_edge bottom, botres + + toparray = config.extract_to_transportable + + # This is annoying; it should look like: + # [[[:botres], :midres], :topres] + # but we can't guarantee sort order. + toparray.include?(:topres).should be_true + + midarray = toparray.find { |t| t.is_a?(Array) } + midarray.include?(:midres).should be_true + botarray = midarray.find { |t| t.is_a?(Array) } + botarray.include?(:botres).should be_true end end - before do - @original = Puppet::Resource::Catalog.new("mynode") - @original.tag(*%w{one two three}) - @original.add_class *%w{four five six} - - @top = CatalogTestResource.new 'top' - @topobject = CatalogTestResource.new 'topobject', :builtin => true - @virtual = CatalogTestResource.new 'virtual', :virtual => true - @virtualobject = CatalogTestResource.new 'virtualobject', :builtin => true, :virtual => true - @middle = CatalogTestResource.new 'middle' - @middleobject = CatalogTestResource.new 'middleobject', :builtin => true - @bottom = CatalogTestResource.new 'bottom' - @bottomobject = CatalogTestResource.new 'bottomobject', :builtin => true - - @resources = [@top, @topobject, @middle, @middleobject, @bottom, @bottomobject] - - @original.add_edge(@top, @topobject) - @original.add_edge(@top, @virtual) - @original.add_edge(@virtual, @virtualobject) - @original.add_edge(@top, @middle) - @original.add_edge(@middle, @middleobject) - @original.add_edge(@middle, @bottom) - @original.add_edge(@bottom, @bottomobject) - - @catalog = @original.to_transportable - end - - it "should add all resources as TransObjects" do - @resources.each { |resource| @catalog.resource(resource.ref).should be_instance_of(Puppet::TransObject) } - end + describe "when converting to a transobject catalog" do + class CatalogTestResource + attr_accessor :name, :virtual, :builtin + def initialize(name, options = {}) + @name = name + options.each { |p,v| send(p.to_s + "=", v) } + end - it "should not extract defined virtual resources" do - @catalog.vertices.find { |v| v.name == "virtual" }.should be_nil - end + def ref + if builtin? + "File[%s]" % name + else + "Class[%s]" % name + end + end - it "should not extract builtin virtual resources" do - @catalog.vertices.find { |v| v.name == "virtualobject" }.should be_nil - end + def virtual? + virtual + end - it "should copy the tag list to the new catalog" do - @catalog.tags.sort.should == @original.tags.sort - end + def builtin? + builtin + end - it "should copy the class list to the new catalog" do - @catalog.classes.should == @original.classes - end + def to_transobject + Puppet::TransObject.new(name, builtin? ? "file" : "class") + end + end - it "should duplicate the original edges" do - @original.edges.each do |edge| - next if edge.source.virtual? or edge.target.virtual? - source = @catalog.resource(edge.source.ref) - target = @catalog.resource(edge.target.ref) + before do + @original = Puppet::Resource::Catalog.new("mynode") + @original.tag(*%w{one two three}) + @original.add_class *%w{four five six} + + @top = CatalogTestResource.new 'top' + @topobject = CatalogTestResource.new 'topobject', :builtin => true + @virtual = CatalogTestResource.new 'virtual', :virtual => true + @virtualobject = CatalogTestResource.new 'virtualobject', :builtin => true, :virtual => true + @middle = CatalogTestResource.new 'middle' + @middleobject = CatalogTestResource.new 'middleobject', :builtin => true + @bottom = CatalogTestResource.new 'bottom' + @bottomobject = CatalogTestResource.new 'bottomobject', :builtin => true + + @resources = [@top, @topobject, @middle, @middleobject, @bottom, @bottomobject] + + @original.add_edge(@top, @topobject) + @original.add_edge(@top, @virtual) + @original.add_edge(@virtual, @virtualobject) + @original.add_edge(@top, @middle) + @original.add_edge(@middle, @middleobject) + @original.add_edge(@middle, @bottom) + @original.add_edge(@bottom, @bottomobject) + + @catalog = @original.to_transportable + end - source.should_not be_nil - target.should_not be_nil - @catalog.edge?(source, target).should be_true + it "should add all resources as TransObjects" do + @resources.each { |resource| @catalog.resource(resource.ref).should be_instance_of(Puppet::TransObject) } end - end - it "should set itself as the catalog for each converted resource" do - @catalog.vertices.each { |v| v.catalog.object_id.should equal(@catalog.object_id) } - end -end + it "should not extract defined virtual resources" do + @catalog.vertices.find { |v| v.name == "virtual" }.should be_nil + end -describe Puppet::Resource::Catalog, " when converting to a RAL catalog" do - before do - @original = Puppet::Resource::Catalog.new("mynode") - @original.tag(*%w{one two three}) - @original.add_class *%w{four five six} + it "should not extract builtin virtual resources" do + @catalog.vertices.find { |v| v.name == "virtualobject" }.should be_nil + end - @top = Puppet::TransObject.new 'top', "class" - @topobject = Puppet::TransObject.new '/topobject', "file" - @middle = Puppet::TransObject.new 'middle', "class" - @middleobject = Puppet::TransObject.new '/middleobject', "file" - @bottom = Puppet::TransObject.new 'bottom', "class" - @bottomobject = Puppet::TransObject.new '/bottomobject', "file" + it "should copy the tag list to the new catalog" do + @catalog.tags.sort.should == @original.tags.sort + end - @resources = [@top, @topobject, @middle, @middleobject, @bottom, @bottomobject] + it "should copy the class list to the new catalog" do + @catalog.classes.should == @original.classes + end - @original.add_resource(*@resources) + it "should duplicate the original edges" do + @original.edges.each do |edge| + next if edge.source.virtual? or edge.target.virtual? + source = @catalog.resource(edge.source.ref) + target = @catalog.resource(edge.target.ref) - @original.add_edge(@top, @topobject) - @original.add_edge(@top, @middle) - @original.add_edge(@middle, @middleobject) - @original.add_edge(@middle, @bottom) - @original.add_edge(@bottom, @bottomobject) + source.should_not be_nil + target.should_not be_nil + @catalog.edge?(source, target).should be_true + end + end - @catalog = @original.to_ral + it "should set itself as the catalog for each converted resource" do + @catalog.vertices.each { |v| v.catalog.object_id.should equal(@catalog.object_id) } + end end - it "should add all resources as RAL instances" do - @resources.each { |resource| @catalog.resource(resource.ref).should be_instance_of(Puppet::Type) } - end + describe "when converting to a RAL catalog" do + before do + @original = Puppet::Resource::Catalog.new("mynode") + @original.tag(*%w{one two three}) + @original.add_class *%w{four five six} - it "should copy the tag list to the new catalog" do - @catalog.tags.sort.should == @original.tags.sort - end + @top = Puppet::TransObject.new 'top', "class" + @topobject = Puppet::TransObject.new '/topobject', "file" + @middle = Puppet::TransObject.new 'middle', "class" + @middleobject = Puppet::TransObject.new '/middleobject', "file" + @bottom = Puppet::TransObject.new 'bottom', "class" + @bottomobject = Puppet::TransObject.new '/bottomobject', "file" - it "should copy the class list to the new catalog" do - @catalog.classes.should == @original.classes - end + @resources = [@top, @topobject, @middle, @middleobject, @bottom, @bottomobject] - it "should duplicate the original edges" do - @original.edges.each do |edge| - @catalog.edge?(@catalog.resource(edge.source.ref), @catalog.resource(edge.target.ref)).should be_true - end - end + @original.add_resource(*@resources) - it "should set itself as the catalog for each converted resource" do - @catalog.vertices.each { |v| v.catalog.object_id.should equal(@catalog.object_id) } - end + @original.add_edge(@top, @topobject) + @original.add_edge(@top, @middle) + @original.add_edge(@middle, @middleobject) + @original.add_edge(@middle, @bottom) + @original.add_edge(@bottom, @bottomobject) - it "should convert parser resources to transobjects and set the catalog" do - catalog = Puppet::Resource::Catalog.new("mynode") + @catalog = @original.to_ral + end - result = mock 'catalog' - result.stub_everything + it "should add all resources as RAL instances" do + @resources.each { |resource| @catalog.resource(resource.ref).should be_instance_of(Puppet::Type) } + end - Puppet::Resource::Catalog.expects(:new).returns result + it "should copy the tag list to the new catalog" do + @catalog.tags.sort.should == @original.tags.sort + end - trans = mock 'trans' - resource = Puppet::Parser::Resource.new(:scope => mock("scope"), :source => mock("source"), :type => :file, :title => "/eh") - resource.expects(:to_transobject).returns trans - trans.expects(:catalog=).with result + it "should copy the class list to the new catalog" do + @catalog.classes.should == @original.classes + end - trans.stub_everything + it "should duplicate the original edges" do + @original.edges.each do |edge| + @catalog.edge?(@catalog.resource(edge.source.ref), @catalog.resource(edge.target.ref)).should be_true + end + end - catalog.add_resource(resource) + it "should set itself as the catalog for each converted resource" do + @catalog.vertices.each { |v| v.catalog.object_id.should equal(@catalog.object_id) } + end - catalog.to_ral - end + it "should convert parser resources to transobjects and set the catalog" do + catalog = Puppet::Resource::Catalog.new("mynode") - # This tests #931. - it "should not lose track of resources whose names vary" do - changer = Puppet::TransObject.new 'changer', 'test' + result = mock 'catalog' + result.stub_everything - config = Puppet::Resource::Catalog.new('test') - config.add_resource(changer) - config.add_resource(@top) + Puppet::Resource::Catalog.expects(:new).returns result - config.add_edge(@top, changer) + trans = mock 'trans' + resource = Puppet::Parser::Resource.new(:scope => mock("scope"), :source => mock("source"), :type => :file, :title => "/eh") + resource.expects(:to_transobject).returns trans + trans.expects(:catalog=).with result - resource = stub 'resource', :name => "changer2", :title => "changer2", :ref => "Test[changer2]", :catalog= => nil, :remove => nil + trans.stub_everything - #changer is going to get duplicated as part of a fix for aliases 1094 - changer.expects(:dup).returns(changer) - changer.expects(:to_type).returns(resource) + catalog.add_resource(resource) - newconfig = nil + catalog.to_ral + end - proc { @catalog = config.to_ral }.should_not raise_error - @catalog.resource("Test[changer2]").should equal(resource) - end + # This tests #931. + it "should not lose track of resources whose names vary" do + changer = Puppet::TransObject.new 'changer', 'test' - after do - # Remove all resource instances. - @catalog.clear(true) - end -end + config = Puppet::Resource::Catalog.new('test') + config.add_resource(changer) + config.add_resource(@top) -describe Puppet::Resource::Catalog, " when functioning as a resource container" do - before do - @catalog = Puppet::Resource::Catalog.new("host") - @one = Puppet::Type.type(:notify).create :name => "one" - @two = Puppet::Type.type(:notify).create :name => "two" - @dupe = Puppet::Type.type(:notify).create :name => "one" - end + config.add_edge(@top, changer) - it "should provide a method to add one or more resources" do - @catalog.add_resource @one, @two - @catalog.resource(@one.ref).should equal(@one) - @catalog.resource(@two.ref).should equal(@two) - end + resource = stub 'resource', :name => "changer2", :title => "changer2", :ref => "Test[changer2]", :catalog= => nil, :remove => nil - it "should add resources to the relationship graph if it exists" do - relgraph = @catalog.relationship_graph - @catalog.add_resource @one - relgraph.should be_vertex(@one) - end + #changer is going to get duplicated as part of a fix for aliases 1094 + changer.expects(:dup).returns(changer) + changer.expects(:to_type).returns(resource) - it "should yield added resources if a block is provided" do - yielded = [] - @catalog.add_resource(@one, @two) { |r| yielded << r } - yielded.length.should == 2 - end + newconfig = nil - it "should set itself as the resource's catalog if it is not a relationship graph" do - @one.expects(:catalog=).with(@catalog) - @catalog.add_resource @one - end + proc { @catalog = config.to_ral }.should_not raise_error + @catalog.resource("Test[changer2]").should equal(resource) + end - it "should make all vertices available by resource reference" do - @catalog.add_resource(@one) - @catalog.resource(@one.ref).should equal(@one) - @catalog.vertices.find { |r| r.ref == @one.ref }.should equal(@one) + after do + # Remove all resource instances. + @catalog.clear(true) + end end - it "should canonize how resources are referred to during retrieval when both type and title are provided" do - @catalog.add_resource(@one) + describe "when functioning as a resource container" do + before do + @catalog = Puppet::Resource::Catalog.new("host") + @one = Puppet::Type.type(:notify).create :name => "one" + @two = Puppet::Type.type(:notify).create :name => "two" + @dupe = Puppet::Type.type(:notify).create :name => "one" + end - @catalog.resource("notify", "one").should equal(@one) - end + it "should provide a method to add one or more resources" do + @catalog.add_resource @one, @two + @catalog.resource(@one.ref).should equal(@one) + @catalog.resource(@two.ref).should equal(@two) + end - it "should canonize how resources are referred to during retrieval when just the title is provided" do - @catalog.add_resource(@one) + it "should add resources to the relationship graph if it exists" do + relgraph = @catalog.relationship_graph + @catalog.add_resource @one + relgraph.should be_vertex(@one) + end - @catalog.resource("notify[one]", nil).should equal(@one) - end + it "should yield added resources if a block is provided" do + yielded = [] + @catalog.add_resource(@one, @two) { |r| yielded << r } + yielded.length.should == 2 + end - it "should not allow two resources with the same resource reference" do - @catalog.add_resource(@one) + it "should set itself as the resource's catalog if it is not a relationship graph" do + @one.expects(:catalog=).with(@catalog) + @catalog.add_resource @one + end - proc { @catalog.add_resource(@dupe) }.should raise_error(Puppet::Resource::Catalog::DuplicateResourceError) - end + it "should make all vertices available by resource reference" do + @catalog.add_resource(@one) + @catalog.resource(@one.ref).should equal(@one) + @catalog.vertices.find { |r| r.ref == @one.ref }.should equal(@one) + end - it "should ignore implicit resources that conflict with existing resources" do - @catalog.add_resource(@one) + it "should canonize how resources are referred to during retrieval when both type and title are provided" do + @catalog.add_resource(@one) - @dupe.implicit = true + @catalog.resource("notify", "one").should equal(@one) + end - yielded = [] - @catalog.add_resource(@dupe) { |r| yielded << r } - yielded.should be_empty - end + it "should canonize how resources are referred to during retrieval when just the title is provided" do + @catalog.add_resource(@one) - it "should not set the catalog for ignored implicit resources" do - @catalog.add_resource(@one) + @catalog.resource("notify[one]", nil).should equal(@one) + end - @dupe.implicit = true + it "should not allow two resources with the same resource reference" do + @catalog.add_resource(@one) - @catalog.add_resource(@dupe) - @dupe.catalog.should be_nil - end + proc { @catalog.add_resource(@dupe) }.should raise_error(Puppet::Resource::Catalog::DuplicateResourceError) + end - it "should log when implicit resources are ignored" do - @catalog.add_resource(@one) + it "should ignore implicit resources that conflict with existing resources" do + @catalog.add_resource(@one) - @dupe.implicit = true + @dupe.implicit = true - @dupe.expects(:debug) - @catalog.add_resource(@dupe) - end + yielded = [] + @catalog.add_resource(@dupe) { |r| yielded << r } + yielded.should be_empty + end - it "should replace implicit resources if a conflicting explicit resource is added" do - @catalog.add_resource(@one) - @one.implicit = true + it "should not set the catalog for ignored implicit resources" do + @catalog.add_resource(@one) - proc { @catalog.add_resource(@dupe) }.should_not raise_error - @catalog.resource(:notify, "one").should equal(@dupe) - end + @dupe.implicit = true - it "should log when implicit resources are removed from the catalog" do - @catalog.add_resource(@one) - @one.implicit = true + @catalog.add_resource(@dupe) + @dupe.catalog.should be_nil + end - @one.expects(:debug) - @catalog.add_resource(@dupe) - end + it "should log when implicit resources are ignored" do + @catalog.add_resource(@one) - it "should not store objects that do not respond to :ref" do - proc { @catalog.add_resource("thing") }.should raise_error(ArgumentError) - end + @dupe.implicit = true - it "should remove all resources when asked" do - @catalog.add_resource @one - @catalog.add_resource @two - @one.expects :remove - @two.expects :remove - @catalog.clear(true) - end + @dupe.expects(:debug) + @catalog.add_resource(@dupe) + end - it "should support a mechanism for finishing resources" do - @one.expects :finish - @two.expects :finish - @catalog.add_resource @one - @catalog.add_resource @two + it "should replace implicit resources if a conflicting explicit resource is added" do + @catalog.add_resource(@one) + @one.implicit = true - @catalog.finalize - end + proc { @catalog.add_resource(@dupe) }.should_not raise_error + @catalog.resource(:notify, "one").should equal(@dupe) + end - it "should make default resources when finalizing" do - @catalog.expects(:make_default_resources) - @catalog.finalize - end + it "should log when implicit resources are removed from the catalog" do + @catalog.add_resource(@one) + @one.implicit = true - it "should add default resources to the catalog upon creation" do - @catalog.make_default_resources - @catalog.resource(:schedule, "daily").should_not be_nil - end - - it "should optionally support an initialization block and should finalize after such blocks" do - @one.expects :finish - @two.expects :finish - config = Puppet::Resource::Catalog.new("host") do |conf| - conf.add_resource @one - conf.add_resource @two + @one.expects(:debug) + @catalog.add_resource(@dupe) end - end - it "should inform the resource that it is the resource's catalog" do - @one.expects(:catalog=).with(@catalog) - @catalog.add_resource @one - end + it "should not store objects that do not respond to :ref" do + proc { @catalog.add_resource("thing") }.should raise_error(ArgumentError) + end - it "should be able to find resources by reference" do - @catalog.add_resource @one - @catalog.resource(@one.ref).should equal(@one) - end + it "should remove all resources when asked" do + @catalog.add_resource @one + @catalog.add_resource @two + @one.expects :remove + @two.expects :remove + @catalog.clear(true) + end - it "should be able to find resources by reference or by type/title tuple" do - @catalog.add_resource @one - @catalog.resource("notify", "one").should equal(@one) - end + it "should support a mechanism for finishing resources" do + @one.expects :finish + @two.expects :finish + @catalog.add_resource @one + @catalog.add_resource @two - it "should have a mechanism for removing resources" do - @catalog.add_resource @one - @one.expects :remove - @catalog.remove_resource(@one) - @catalog.resource(@one.ref).should be_nil - @catalog.vertex?(@one).should be_false - end + @catalog.finalize + end - it "should have a method for creating aliases for resources" do - @catalog.add_resource @one - @catalog.alias(@one, "other") - @catalog.resource("notify", "other").should equal(@one) - end + it "should make default resources when finalizing" do + @catalog.expects(:make_default_resources) + @catalog.finalize + end - it "should ignore conflicting aliases that point to the aliased resource" do - @catalog.alias(@one, "other") - lambda { @catalog.alias(@one, "other") }.should_not raise_error - end + it "should add default resources to the catalog upon creation" do + @catalog.make_default_resources + @catalog.resource(:schedule, "daily").should_not be_nil + end + + it "should optionally support an initialization block and should finalize after such blocks" do + @one.expects :finish + @two.expects :finish + config = Puppet::Resource::Catalog.new("host") do |conf| + conf.add_resource @one + conf.add_resource @two + end + end - it "should create aliases for resources isomorphic resources whose names do not match their titles" do - resource = Puppet::Type::File.create(:title => "testing", :path => "/something") + it "should inform the resource that it is the resource's catalog" do + @one.expects(:catalog=).with(@catalog) + @catalog.add_resource @one + end - @catalog.add_resource(resource) + it "should be able to find resources by reference" do + @catalog.add_resource @one + @catalog.resource(@one.ref).should equal(@one) + end - @catalog.resource(:file, "/something").should equal(resource) - end + it "should be able to find resources by reference or by type/title tuple" do + @catalog.add_resource @one + @catalog.resource("notify", "one").should equal(@one) + end - it "should not create aliases for resources non-isomorphic resources whose names do not match their titles" do - resource = Puppet::Type.type(:exec).create(:title => "testing", :command => "echo", :path => %w{/bin /usr/bin /usr/local/bin}) + it "should have a mechanism for removing resources" do + @catalog.add_resource @one + @one.expects :remove + @catalog.remove_resource(@one) + @catalog.resource(@one.ref).should be_nil + @catalog.vertex?(@one).should be_false + end - @catalog.add_resource(resource) + it "should have a method for creating aliases for resources" do + @catalog.add_resource @one + @catalog.alias(@one, "other") + @catalog.resource("notify", "other").should equal(@one) + end - # Yay, I've already got a 'should' method - @catalog.resource(:exec, "echo").object_id.should == nil.object_id - end + it "should ignore conflicting aliases that point to the aliased resource" do + @catalog.alias(@one, "other") + lambda { @catalog.alias(@one, "other") }.should_not raise_error + end - # This test is the same as the previous, but the behaviour should be explicit. - it "should alias using the class name from the resource reference, not the resource class name" do - @catalog.add_resource @one - @catalog.alias(@one, "other") - @catalog.resource("notify", "other").should equal(@one) - end + it "should create aliases for resources isomorphic resources whose names do not match their titles" do + resource = Puppet::Type::File.create(:title => "testing", :path => "/something") - it "should ignore conflicting aliases that point to the aliased resource" do - @catalog.alias(@one, "other") - lambda { @catalog.alias(@one, "other") }.should_not raise_error - end + @catalog.add_resource(resource) - it "should fail to add an alias if the aliased name already exists" do - @catalog.add_resource @one - proc { @catalog.alias @two, "one" }.should raise_error(ArgumentError) - end + @catalog.resource(:file, "/something").should equal(resource) + end - it "should not fail when a resource has duplicate aliases created" do - @catalog.add_resource @one - proc { @catalog.alias @one, "one" }.should_not raise_error - end + it "should not create aliases for resources non-isomorphic resources whose names do not match their titles" do + resource = Puppet::Type.type(:exec).create(:title => "testing", :command => "echo", :path => %w{/bin /usr/bin /usr/local/bin}) - it "should not create aliases that point back to the resource" do - @catalog.alias(@one, "one") - @catalog.resource(:notify, "one").should be_nil - end + @catalog.add_resource(resource) - it "should be able to look resources up by their aliases" do - @catalog.add_resource @one - @catalog.alias @one, "two" - @catalog.resource(:notify, "two").should equal(@one) - end + # Yay, I've already got a 'should' method + @catalog.resource(:exec, "echo").object_id.should == nil.object_id + end - it "should remove resource aliases when the target resource is removed" do - @catalog.add_resource @one - @catalog.alias(@one, "other") - @one.expects :remove - @catalog.remove_resource(@one) - @catalog.resource("notify", "other").should be_nil - end + # This test is the same as the previous, but the behaviour should be explicit. + it "should alias using the class name from the resource reference, not the resource class name" do + @catalog.add_resource @one + @catalog.alias(@one, "other") + @catalog.resource("notify", "other").should equal(@one) + end - it "should add an alias for the namevar when the title and name differ on isomorphic resource types" do - resource = Puppet::Type.type(:file).create :path => "/something", :title => "other", :content => "blah" - resource.expects(:isomorphic?).returns(true) - @catalog.add_resource(resource) - @catalog.resource(:file, "other").should equal(resource) - @catalog.resource(:file, "/something").ref.should == resource.ref - end + it "should ignore conflicting aliases that point to the aliased resource" do + @catalog.alias(@one, "other") + lambda { @catalog.alias(@one, "other") }.should_not raise_error + end - it "should not add an alias for the namevar when the title and name differ on non-isomorphic resource types" do - resource = Puppet::Type.type(:file).create :path => "/something", :title => "other", :content => "blah" - resource.expects(:isomorphic?).returns(false) - @catalog.add_resource(resource) - @catalog.resource(:file, resource.title).should equal(resource) - # We can't use .should here, because the resources respond to that method. - if @catalog.resource(:file, resource.name) - raise "Aliased non-isomorphic resource" + it "should fail to add an alias if the aliased name already exists" do + @catalog.add_resource @one + proc { @catalog.alias @two, "one" }.should raise_error(ArgumentError) end - end - it "should provide a method to create additional resources that also registers the resource" do - args = {:name => "/yay", :ensure => :file} - resource = stub 'file', :ref => "File[/yay]", :catalog= => @catalog, :title => "/yay", :[] => "/yay" - Puppet::Type.type(:file).expects(:create).with(args).returns(resource) - @catalog.create_resource :file, args - @catalog.resource("File[/yay]").should equal(resource) - end -end + it "should not fail when a resource has duplicate aliases created" do + @catalog.add_resource @one + proc { @catalog.alias @one, "one" }.should_not raise_error + end -describe Puppet::Resource::Catalog do - before :each do - @catalog = Puppet::Resource::Catalog.new("host") + it "should not create aliases that point back to the resource" do + @catalog.alias(@one, "one") + @catalog.resource(:notify, "one").should be_nil + end - @catalog.retrieval_duration = Time.now - @transaction = mock 'transaction' - Puppet::Transaction.stubs(:new).returns(@transaction) - @transaction.stubs(:evaluate) - @transaction.stubs(:cleanup) - @transaction.stubs(:addtimes) - end + it "should be able to look resources up by their aliases" do + @catalog.add_resource @one + @catalog.alias @one, "two" + @catalog.resource(:notify, "two").should equal(@one) + end - it "should be an Expirer" do - Puppet::Resource::Catalog.ancestors.should be_include(Puppet::Util::Cacher::Expirer) - end + it "should remove resource aliases when the target resource is removed" do + @catalog.add_resource @one + @catalog.alias(@one, "other") + @one.expects :remove + @catalog.remove_resource(@one) + @catalog.resource("notify", "other").should be_nil + end - it "should always be expired if it's not applying" do - @catalog.expects(:applying?).returns false - @catalog.should be_expired(Time.now) - end + it "should add an alias for the namevar when the title and name differ on isomorphic resource types" do + resource = Puppet::Type.type(:file).create :path => "/something", :title => "other", :content => "blah" + resource.expects(:isomorphic?).returns(true) + @catalog.add_resource(resource) + @catalog.resource(:file, "other").should equal(resource) + @catalog.resource(:file, "/something").ref.should == resource.ref + end - it "should not be expired if it's applying and the timestamp is late enough" do - @catalog.expire - @catalog.expects(:applying?).returns true - @catalog.should_not be_expired(Time.now) + it "should not add an alias for the namevar when the title and name differ on non-isomorphic resource types" do + resource = Puppet::Type.type(:file).create :path => "/something", :title => "other", :content => "blah" + resource.expects(:isomorphic?).returns(false) + @catalog.add_resource(resource) + @catalog.resource(:file, resource.title).should equal(resource) + # We can't use .should here, because the resources respond to that method. + if @catalog.resource(:file, resource.name) + raise "Aliased non-isomorphic resource" + end + end + + it "should provide a method to create additional resources that also registers the resource" do + args = {:name => "/yay", :ensure => :file} + resource = stub 'file', :ref => "File[/yay]", :catalog= => @catalog, :title => "/yay", :[] => "/yay" + Puppet::Type.type(:file).expects(:create).with(args).returns(resource) + @catalog.create_resource :file, args + @catalog.resource("File[/yay]").should equal(resource) + end end describe "when applying" do + before :each do + @catalog = Puppet::Resource::Catalog.new("host") + + @catalog.retrieval_duration = Time.now + @transaction = mock 'transaction' + Puppet::Transaction.stubs(:new).returns(@transaction) + @transaction.stubs(:evaluate) + @transaction.stubs(:cleanup) + @transaction.stubs(:addtimes) + end + it "should create and evaluate a transaction" do @transaction.expects(:evaluate) @catalog.apply @@ -704,229 +706,229 @@ describe Puppet::Resource::Catalog do @catalog.expects(:expire).times(2) @catalog.apply end - end - describe "when applying host catalogs" do + describe "host catalogs" do - # super() doesn't work in the setup method for some reason - before do - @catalog.host_config = true - Puppet::Util::Storage.stubs(:store) - end + # super() doesn't work in the setup method for some reason + before do + @catalog.host_config = true + Puppet::Util::Storage.stubs(:store) + end - it "should send a report if reporting is enabled" do - Puppet[:report] = true - @transaction.expects :send_report - @transaction.stubs :any_failed? => false - @catalog.apply - end + it "should send a report if reporting is enabled" do + Puppet[:report] = true + @transaction.expects :send_report + @transaction.stubs :any_failed? => false + @catalog.apply + end - it "should send a report if report summaries are enabled" do - Puppet[:summarize] = true - @transaction.expects :send_report - @transaction.stubs :any_failed? => false - @catalog.apply - end + it "should send a report if report summaries are enabled" do + Puppet[:summarize] = true + @transaction.expects :send_report + @transaction.stubs :any_failed? => false + @catalog.apply + end - it "should initialize the state database before applying a catalog" do - Puppet::Util::Storage.expects(:load) + it "should initialize the state database before applying a catalog" do + Puppet::Util::Storage.expects(:load) - # Short-circuit the apply, so we know we're loading before the transaction - Puppet::Transaction.expects(:new).raises ArgumentError - proc { @catalog.apply }.should raise_error(ArgumentError) - end + # Short-circuit the apply, so we know we're loading before the transaction + Puppet::Transaction.expects(:new).raises ArgumentError + proc { @catalog.apply }.should raise_error(ArgumentError) + end - it "should sync the state database after applying" do - Puppet::Util::Storage.expects(:store) - @transaction.stubs :any_failed? => false - @catalog.apply + it "should sync the state database after applying" do + Puppet::Util::Storage.expects(:store) + @transaction.stubs :any_failed? => false + @catalog.apply + end + + after { Puppet.settings.clear } end - after { Puppet.settings.clear } - end + describe "non-host catalogs" do - describe Puppet::Resource::Catalog, " when applying non-host catalogs" do + before do + @catalog.host_config = false + end + + it "should never send reports" do + Puppet[:report] = true + Puppet[:summarize] = true + @transaction.expects(:send_report).never + @catalog.apply + end - before do - @catalog.host_config = false - end - - it "should never send reports" do - Puppet[:report] = true - Puppet[:summarize] = true - @transaction.expects(:send_report).never - @catalog.apply - end + it "should never modify the state database" do + Puppet::Util::Storage.expects(:load).never + Puppet::Util::Storage.expects(:store).never + @catalog.apply + end - it "should never modify the state database" do - Puppet::Util::Storage.expects(:load).never - Puppet::Util::Storage.expects(:store).never - @catalog.apply + after { Puppet.settings.clear } end - - after { Puppet.settings.clear } end -end -describe Puppet::Resource::Catalog, " when creating a relationship graph" do - before do - Puppet::Type.type(:component) - @catalog = Puppet::Resource::Catalog.new("host") - @compone = Puppet::Type::Component.create :name => "one" - @comptwo = Puppet::Type::Component.create :name => "two", :require => ["class", "one"] - @file = Puppet::Type.type(:file) - @one = @file.create :path => "/one" - @two = @file.create :path => "/two" - @sub = @file.create :path => "/two/subdir" - @catalog.add_edge @compone, @one - @catalog.add_edge @comptwo, @two - - @three = @file.create :path => "/three" - @four = @file.create :path => "/four", :require => ["file", "/three"] - @five = @file.create :path => "/five" - @catalog.add_resource @compone, @comptwo, @one, @two, @three, @four, @five, @sub - @relationships = @catalog.relationship_graph - end + describe "when creating a relationship graph" do + before do + Puppet::Type.type(:component) + @catalog = Puppet::Resource::Catalog.new("host") + @compone = Puppet::Type::Component.create :name => "one" + @comptwo = Puppet::Type::Component.create :name => "two", :require => ["class", "one"] + @file = Puppet::Type.type(:file) + @one = @file.create :path => "/one" + @two = @file.create :path => "/two" + @sub = @file.create :path => "/two/subdir" + @catalog.add_edge @compone, @one + @catalog.add_edge @comptwo, @two + + @three = @file.create :path => "/three" + @four = @file.create :path => "/four", :require => ["file", "/three"] + @five = @file.create :path => "/five" + @catalog.add_resource @compone, @comptwo, @one, @two, @three, @four, @five, @sub + @relationships = @catalog.relationship_graph + end - it "should be able to create a relationship graph" do - @relationships.should be_instance_of(Puppet::SimpleGraph) - end + it "should be able to create a relationship graph" do + @relationships.should be_instance_of(Puppet::SimpleGraph) + end - it "should not have any components" do - @relationships.vertices.find { |r| r.instance_of?(Puppet::Type::Component) }.should be_nil - end + it "should not have any components" do + @relationships.vertices.find { |r| r.instance_of?(Puppet::Type::Component) }.should be_nil + end - it "should have all non-component resources from the catalog" do - # The failures print out too much info, so i just do a class comparison - @relationships.vertex?(@five).should be_true - end + it "should have all non-component resources from the catalog" do + # The failures print out too much info, so i just do a class comparison + @relationships.vertex?(@five).should be_true + end - it "should have all resource relationships set as edges" do - @relationships.edge?(@three, @four).should be_true - end + it "should have all resource relationships set as edges" do + @relationships.edge?(@three, @four).should be_true + end - it "should copy component relationships to all contained resources" do - @relationships.edge?(@one, @two).should be_true - end + it "should copy component relationships to all contained resources" do + @relationships.edge?(@one, @two).should be_true + end - it "should add automatic relationships to the relationship graph" do - @relationships.edge?(@two, @sub).should be_true - end + it "should add automatic relationships to the relationship graph" do + @relationships.edge?(@two, @sub).should be_true + end - it "should get removed when the catalog is cleaned up" do - @relationships.expects(:clear) - @catalog.clear - @catalog.instance_variable_get("@relationship_graph").should be_nil - end + it "should get removed when the catalog is cleaned up" do + @relationships.expects(:clear) + @catalog.clear + @catalog.instance_variable_get("@relationship_graph").should be_nil + end - it "should write :relationships and :expanded_relationships graph files if the catalog is a host catalog" do - @catalog.clear - graph = Puppet::SimpleGraph.new - Puppet::SimpleGraph.expects(:new).returns graph + it "should write :relationships and :expanded_relationships graph files if the catalog is a host catalog" do + @catalog.clear + graph = Puppet::SimpleGraph.new + Puppet::SimpleGraph.expects(:new).returns graph - graph.expects(:write_graph).with(:relationships) - graph.expects(:write_graph).with(:expanded_relationships) + graph.expects(:write_graph).with(:relationships) + graph.expects(:write_graph).with(:expanded_relationships) - @catalog.host_config = true + @catalog.host_config = true - @catalog.relationship_graph - end + @catalog.relationship_graph + end - it "should not write graph files if the catalog is not a host catalog" do - @catalog.clear - graph = Puppet::SimpleGraph.new - Puppet::SimpleGraph.expects(:new).returns graph + it "should not write graph files if the catalog is not a host catalog" do + @catalog.clear + graph = Puppet::SimpleGraph.new + Puppet::SimpleGraph.expects(:new).returns graph - graph.expects(:write_graph).never + graph.expects(:write_graph).never - @catalog.host_config = false + @catalog.host_config = false - @catalog.relationship_graph - end + @catalog.relationship_graph + end - it "should create a new relationship graph after clearing the old one" do - @relationships.expects(:clear) - @catalog.clear - @catalog.relationship_graph.should be_instance_of(Puppet::SimpleGraph) - end + it "should create a new relationship graph after clearing the old one" do + @relationships.expects(:clear) + @catalog.clear + @catalog.relationship_graph.should be_instance_of(Puppet::SimpleGraph) + end - it "should remove removed resources from the relationship graph if it exists" do - @catalog.remove_resource(@one) - @catalog.relationship_graph.vertex?(@one).should be_false + it "should remove removed resources from the relationship graph if it exists" do + @catalog.remove_resource(@one) + @catalog.relationship_graph.vertex?(@one).should be_false + end end -end -describe Puppet::Resource::Catalog, " when writing dot files" do - before do - @catalog = Puppet::Resource::Catalog.new("host") - @name = :test - @file = File.join(Puppet[:graphdir], @name.to_s + ".dot") - end + describe "when writing dot files" do + before do + @catalog = Puppet::Resource::Catalog.new("host") + @name = :test + @file = File.join(Puppet[:graphdir], @name.to_s + ".dot") + end - it "should only write when it is a host catalog" do - File.expects(:open).with(@file).never - @catalog.host_config = false - Puppet[:graph] = true - @catalog.write_graph(@name) - end + it "should only write when it is a host catalog" do + File.expects(:open).with(@file).never + @catalog.host_config = false + Puppet[:graph] = true + @catalog.write_graph(@name) + end - after do - Puppet.settings.clear + after do + Puppet.settings.clear + end end -end -describe Puppet::Resource::Catalog, " when indirecting" do - before do - @indirection = stub 'indirection', :name => :catalog + describe "when indirecting" do + before do + @indirection = stub 'indirection', :name => :catalog - Puppet::Util::Cacher.expire - end + Puppet::Util::Cacher.expire + end - it "should redirect to the indirection for retrieval" do - Puppet::Resource::Catalog.stubs(:indirection).returns(@indirection) - @indirection.expects(:find) - Puppet::Resource::Catalog.find(:myconfig) - end + it "should redirect to the indirection for retrieval" do + Puppet::Resource::Catalog.stubs(:indirection).returns(@indirection) + @indirection.expects(:find) + Puppet::Resource::Catalog.find(:myconfig) + end - it "should default to the 'compiler' terminus" do - Puppet::Resource::Catalog.indirection.terminus_class.should == :compiler - end + it "should default to the 'compiler' terminus" do + Puppet::Resource::Catalog.indirection.terminus_class.should == :compiler + end - after do - Puppet::Util::Cacher.expire + after do + Puppet::Util::Cacher.expire + end end -end -describe Puppet::Resource::Catalog, " when converting to yaml" do - before do - @catalog = Puppet::Resource::Catalog.new("me") - @catalog.add_edge("one", "two") - end + describe "when converting to yaml" do + before do + @catalog = Puppet::Resource::Catalog.new("me") + @catalog.add_edge("one", "two") + end - it "should be able to be dumped to yaml" do - YAML.dump(@catalog).should be_instance_of(String) + it "should be able to be dumped to yaml" do + YAML.dump(@catalog).should be_instance_of(String) + end end -end -describe Puppet::Resource::Catalog, " when converting from yaml" do - before do - @catalog = Puppet::Resource::Catalog.new("me") - @catalog.add_edge("one", "two") + describe "when converting from yaml" do + before do + @catalog = Puppet::Resource::Catalog.new("me") + @catalog.add_edge("one", "two") - text = YAML.dump(@catalog) - @newcatalog = YAML.load(text) - end + text = YAML.dump(@catalog) + @newcatalog = YAML.load(text) + end - it "should get converted back to a catalog" do - @newcatalog.should be_instance_of(Puppet::Resource::Catalog) - end + it "should get converted back to a catalog" do + @newcatalog.should be_instance_of(Puppet::Resource::Catalog) + end - it "should have all vertices" do - @newcatalog.vertex?("one").should be_true - @newcatalog.vertex?("two").should be_true - end + it "should have all vertices" do + @newcatalog.vertex?("one").should be_true + @newcatalog.vertex?("two").should be_true + end - it "should have all edges" do - @newcatalog.edge?("one", "two").should be_true + it "should have all edges" do + @newcatalog.edge?("one", "two").should be_true + end end end |