diff options
| author | Luke Kanies <luke@madstop.com> | 2007-09-25 00:43:15 -0500 |
|---|---|---|
| committer | Luke Kanies <luke@madstop.com> | 2007-09-25 00:43:15 -0500 |
| commit | 4679f4dcc110e3362b0097efe1d5a416c659611b (patch) | |
| tree | d8dd9aa3f220c7a1d8e3cb0d486e1a7bba7276f7 /spec/unit/node | |
| parent | c3c3e519219ad80ac07d21c74849fbc4246c9d7a (diff) | |
| parent | cdc8ea6e81c1b5eba5ea784bb7079c4c1f3965a4 (diff) | |
| download | puppet-4679f4dcc110e3362b0097efe1d5a416c659611b.tar.gz puppet-4679f4dcc110e3362b0097efe1d5a416c659611b.tar.xz puppet-4679f4dcc110e3362b0097efe1d5a416c659611b.zip | |
Merge branch 'indirection' of git://reductivelabs.com/puppet-luke
Diffstat (limited to 'spec/unit/node')
| -rwxr-xr-x | spec/unit/node/configuration.rb | 337 | ||||
| -rwxr-xr-x | spec/unit/node/facts.rb | 39 | ||||
| -rwxr-xr-x | spec/unit/node/node.rb | 135 | ||||
| -rwxr-xr-x | spec/unit/node/searching.rb | 79 |
4 files changed, 590 insertions, 0 deletions
diff --git a/spec/unit/node/configuration.rb b/spec/unit/node/configuration.rb index 4429fe3a3..8ba55f50c 100755 --- a/spec/unit/node/configuration.rb +++ b/spec/unit/node/configuration.rb @@ -133,3 +133,340 @@ describe Puppet::Node::Configuration, " when extracting transobjects" do botarray.include?(:botres).should be_true end end + +describe Puppet::Node::Configuration, " when functioning as a resource container" do + before do + @config = Puppet::Node::Configuration.new("host") + @one = stub 'resource1', :ref => "Me[you]", :configuration= => nil + @two = stub 'resource2', :ref => "Me[him]", :configuration= => nil + @dupe = stub 'resource3', :ref => "Me[you]", :configuration= => nil + end + + it "should provide a method to add one or more resources" do + @config.add_resource @one, @two + @config.resource(@one.ref).should equal(@one) + @config.resource(@two.ref).should equal(@two) + end + + it "should make all vertices available by resource reference" do + @config.add_resource(@one) + @config.resource(@one.ref).should equal(@one) + @config.vertices.find { |r| r.ref == @one.ref }.should equal(@one) + end + + it "should not allow two resources with the same resource reference" do + @config.add_resource(@one) + proc { @config.add_resource(@dupe) }.should raise_error(ArgumentError) + end + + it "should not store objects that do not respond to :ref" do + proc { @config.add_resource("thing") }.should raise_error(ArgumentError) + end + + it "should remove all resources when asked" do + @config.add_resource @one + @config.add_resource @two + @one.expects :remove + @two.expects :remove + @config.clear(true) + end + + it "should support a mechanism for finishing resources" do + @one.expects :finish + @two.expects :finish + @config.add_resource @one + @config.add_resource @two + + @config.finalize + end + + it "should optionally support an initialization block and should finalize after such blocks" do + @one.expects :finish + @two.expects :finish + config = Puppet::Node::Configuration.new("host") do |conf| + conf.add_resource @one + conf.add_resource @two + end + end + + it "should inform the resource that it is the resource's configuration" do + @one.expects(:configuration=).with(@config) + @config.add_resource @one + end + + it "should be able to find resources by reference" do + @config.add_resource @one + @config.resource(@one.ref).should equal(@one) + end + + it "should be able to find resources by reference or by type/title tuple" do + @config.add_resource @one + @config.resource("me", "you").should equal(@one) + end + + it "should have a mechanism for removing resources" do + @config.add_resource @one + @one.expects :remove + @config.remove_resource(@one) + @config.resource(@one.ref).should be_nil + @config.vertex?(@one).should be_false + end +end + +module ApplyingConfigurations + def setup + @config = Puppet::Node::Configuration.new("host") + + @config.retrieval_duration = Time.now + @transaction = mock 'transaction' + Puppet::Transaction.stubs(:new).returns(@transaction) + @transaction.stubs(:evaluate) + @transaction.stubs(:cleanup) + @transaction.stubs(:addtimes) + end +end + +describe Puppet::Node::Configuration, " when applying" do + include ApplyingConfigurations + + it "should create and evaluate a transaction" do + @transaction.expects(:evaluate) + @config.apply + end + + it "should provide the configuration time to the transaction" do + @transaction.expects(:addtimes).with do |arg| + arg[:config_retrieval].should be_instance_of(Time) + true + end + @config.apply + end + + it "should clean up the transaction" do + @transaction.expects :cleanup + @config.apply + end + + it "should return the transaction" do + @config.apply.should equal(@transaction) + end + + it "should yield the transaction if a block is provided" do + @config.apply do |trans| + trans.should equal(@transaction) + end + end + + it "should default to not being a host configuration" do + @config.host_config.should be_nil + end + + it "should pass supplied tags on to the transaction" do + @transaction.expects(:tags=).with(%w{one two}) + @config.apply(:tags => %w{one two}) + end + + it "should set ignoreschedules on the transaction if specified in apply()" do + @transaction.expects(:ignoreschedules=).with(true) + @config.apply(:ignoreschedules => true) + end +end + +describe Puppet::Node::Configuration, " when applying host configurations" do + include ApplyingConfigurations + + # super() doesn't work in the setup method for some reason + before do + @config.host_config = true + end + + it "should send a report if reporting is enabled" do + Puppet[:report] = true + @transaction.expects :send_report + @config.apply + end + + it "should send a report if report summaries are enabled" do + Puppet[:summarize] = true + @transaction.expects :send_report + @config.apply + end + + it "should initialize the state database before applying a configuration" 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 { @config.apply }.should raise_error(ArgumentError) + end + + it "should sync the state database after applying" do + Puppet::Util::Storage.expects(:store) + @config.apply + end + + after { Puppet.settings.clear } +end + +describe Puppet::Node::Configuration, " when applying non-host configurations" do + include ApplyingConfigurations + + before do + @config.host_config = false + end + + it "should never send reports" do + Puppet[:report] = true + Puppet[:summarize] = true + @transaction.expects(:send_report).never + @config.apply + end + + it "should never modify the state database" do + Puppet::Util::Storage.expects(:load).never + Puppet::Util::Storage.expects(:store).never + @config.apply + end + + after { Puppet.settings.clear } +end + +describe Puppet::Node::Configuration, " when creating a relationship graph" do + before do + @config = Puppet::Node::Configuration.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" + @config.add_edge! @compone, @one + @config.add_edge! @comptwo, @two + + @three = @file.create :path => "/three" + @four = @file.create :path => "/four", :require => ["file", "/three"] + @five = @file.create :path => "/five" + @config.add_resource @compone, @comptwo, @one, @two, @three, @four, @five + @relationships = @config.relationship_graph + end + + it "should be able to create a relationship graph" do + @relationships.should be_instance_of(Puppet::Node::Configuration) + end + + it "should copy its host_config setting to the relationship graph" do + config = Puppet::Node::Configuration.new + config.host_config = true + config.relationship_graph.host_config.should be_true + 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 configuration" 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 copy component relationships to all contained resources" do + @relationships.edge?(@one, @two).should be_true + end + + it "should get removed when the configuration is cleaned up" do + @relationships.expects(:clear).with(false) + @config.clear + @config.instance_variable_get("@relationship_graph").should be_nil + end + + it "should create a new relationship graph after clearing the old one" do + @relationships.expects(:clear).with(false) + @config.clear + @config.relationship_graph.should be_instance_of(Puppet::Node::Configuration) + end + + it "should look up resources in the relationship graph if not found in the main configuration" do + five = stub 'five', :ref => "File[five]", :configuration= => nil + @relationships.add_resource five + @config.resource(five.ref).should equal(five) + 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]", :configuration= => @config + Puppet::Type.type(:file).expects(:create).with(args).returns(resource) + @config.create_resource :file, args + @config.resource("File[/yay]").should equal(resource) + end + + it "should provide a mechanism for creating implicit resources" do + args = {:name => "/yay", :ensure => :file} + resource = stub 'file', :ref => "File[/yay]", :configuration= => @config + Puppet::Type.type(:file).expects(:create).with(args).returns(resource) + resource.expects(:implicit=).with(true) + @config.create_implicit_resource :file, args + @config.resource("File[/yay]").should equal(resource) + end + + it "should remove resources created mid-transaction" do + args = {:name => "/yay", :ensure => :file} + resource = stub 'file', :ref => "File[/yay]", :configuration= => @config + @transaction = mock 'transaction' + Puppet::Transaction.stubs(:new).returns(@transaction) + @transaction.stubs(:evaluate) + @transaction.stubs(:cleanup) + @transaction.stubs(:addtimes) + Puppet::Type.type(:file).expects(:create).with(args).returns(resource) + resource.expects :remove + @config.apply do |trans| + @config.create_resource :file, args + @config.resource("File[/yay]").should equal(resource) + end + @config.resource("File[/yay]").should be_nil + end + + it "should remove resources from the relationship graph if it exists" do + @config.remove_resource(@one) + @config.relationship_graph.vertex?(@one).should be_false + end + + after do + Puppet::Type.allclear + end +end + +describe Puppet::Node::Configuration, " when writing dot files" do + before do + @config = Puppet::Node::Configuration.new("host") + @name = :test + @file = File.join(Puppet[:graphdir], @name.to_s + ".dot") + end + it "should only write when it is a host configuration" do + File.expects(:open).with(@file).never + @config.host_config = false + Puppet[:graph] = true + @config.write_graph(@name) + end + + it "should only write when graphing is enabled" do + File.expects(:open).with(@file).never + @config.host_config = true + Puppet[:graph] = false + @config.write_graph(@name) + end + + it "should write a dot file based on the passed name" do + File.expects(:open).with(@file, "w").yields(stub("file", :puts => nil)) + @config.expects(:to_dot).with("name" => @name.to_s.capitalize) + @config.host_config = true + Puppet[:graph] = true + @config.write_graph(@name) + end + + after do + Puppet.settings.clear + end +end diff --git a/spec/unit/node/facts.rb b/spec/unit/node/facts.rb new file mode 100755 index 000000000..61f05a2b2 --- /dev/null +++ b/spec/unit/node/facts.rb @@ -0,0 +1,39 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/node/facts' + +describe Puppet::Node::Facts, " when indirecting" do + before do + @terminus = mock 'terminus' + Puppet::Node::Facts.stubs(:indirection).returns(@terminus) + + # We have to clear the cache so that the facts ask for our terminus stub, + # instead of anything that might be cached. + Puppet::Indirector::Indirection.clear_cache + @facts = Puppet::Node::Facts.new("me", "one" => "two") + end + + it "should redirect to the specified fact store for retrieval" do + @terminus.expects(:find).with(:my_facts) + Puppet::Node::Facts.find(:my_facts) + end + + it "should redirect to the specified fact store for storage" do + @terminus.expects(:save).with(@facts) + @facts.save + end + + after do + mocha_verify + Puppet::Indirector::Indirection.clear_cache + end +end + +describe Puppet::Node::Facts, " when storing and retrieving" do + it "should add metadata to the facts" do + facts = Puppet::Node::Facts.new("me", "one" => "two", "three" => "four") + facts.values[:_timestamp].should be_instance_of(Time) + end +end diff --git a/spec/unit/node/node.rb b/spec/unit/node/node.rb new file mode 100755 index 000000000..fe5d2be8b --- /dev/null +++ b/spec/unit/node/node.rb @@ -0,0 +1,135 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' + +describe Puppet::Node, " when initializing" do + before do + @node = Puppet::Node.new("testnode") + end + + it "should set the node name" do + @node.name.should == "testnode" + end + + it "should not allow nil node names" do + proc { Puppet::Node.new(nil) }.should raise_error(ArgumentError) + end + + it "should default to an empty parameter hash" do + @node.parameters.should == {} + end + + it "should default to an empty class array" do + @node.classes.should == [] + end + + it "should note its creation time" do + @node.time.should be_instance_of(Time) + end + + it "should accept parameters passed in during initialization" do + params = {"a" => "b"} + @node = Puppet::Node.new("testing", :parameters => params) + @node.parameters.should == params + end + + it "should accept classes passed in during initialization" do + classes = %w{one two} + @node = Puppet::Node.new("testing", :classes => classes) + @node.classes.should == classes + end + + it "should always return classes as an array" do + @node = Puppet::Node.new("testing", :classes => "myclass") + @node.classes.should == ["myclass"] + end + + it "should accept the environment during initialization" do + @node = Puppet::Node.new("testing", :environment => "myenv") + @node.environment.should == "myenv" + end + + it "should accept names passed in" do + @node = Puppet::Node.new("testing", :names => ["myenv"]) + @node.names.should == ["myenv"] + end +end + +describe Puppet::Node, " when returning the environment" do + before do + @node = Puppet::Node.new("testnode") + end + + it "should return the 'environment' fact if present and there is no explicit environment" do + @node.parameters = {"environment" => "myenv"} + @node.environment.should == "myenv" + end + + it "should return the central environment if there is no environment fact nor explicit environment" do + Puppet.settings.expects(:[]).with(:environment).returns(:centralenv) + @node.environment.should == :centralenv + end + + it "should not use an explicit environment that is an empty string" do + @node.environment == "" + @node.environment.should be_nil + end + + it "should not use an environment fact that is an empty string" do + @node.parameters = {"environment" => ""} + @node.environment.should be_nil + end + + it "should not use an explicit environment that is an empty string" do + Puppet.settings.expects(:[]).with(:environment).returns(nil) + @node.environment.should be_nil + end +end + +describe Puppet::Node, " when merging facts" do + before do + @node = Puppet::Node.new("testnode") + Puppet::Node::Facts.stubs(:find).with(@node.name).returns(Puppet::Node::Facts.new(@node.name, "one" => "c", "two" => "b")) + end + + it "should prefer parameters already set on the node over facts from the node" do + @node.parameters = {"one" => "a"} + @node.fact_merge + @node.parameters["one"].should == "a" + end + + it "should add passed parameters to the parameter list" do + @node.parameters = {"one" => "a"} + @node.fact_merge + @node.parameters["two"].should == "b" + end + + it "should accept arbitrary parameters to merge into its parameters" do + @node.parameters = {"one" => "a"} + @node.merge "two" => "three" + @node.parameters["two"].should == "three" + end +end + +describe Puppet::Node, " when indirecting" do + before do + @terminus = mock 'terminus' + Puppet::Node.stubs(:indirection).returns(@terminus) + end + + it "should redirect to the specified node source" do + @terminus.expects(:find).with(:my_node.to_s) + Puppet::Node.find(:my_node.to_s) + end + + after do + Puppet::Indirector::Indirection.clear_cache + end +end + +describe Puppet::Node do + # LAK:NOTE This is used to keep track of when a given node has connected, + # so we can report on nodes that do not appear to connecting to the + # central server. + it "should provide a method for noting that the node has connected" +end diff --git a/spec/unit/node/searching.rb b/spec/unit/node/searching.rb new file mode 100755 index 000000000..e747996e4 --- /dev/null +++ b/spec/unit/node/searching.rb @@ -0,0 +1,79 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' +require 'puppet/node/searching' +require 'puppet/node/facts' + +describe Puppet::Node::Searching, " when searching for nodes" do + before do + @searcher = Object.new + @searcher.extend(Puppet::Node::Searching) + @facts = Puppet::Node::Facts.new("foo", "hostname" => "yay", "domain" => "domain.com") + @node = Puppet::Node.new("foo") + Puppet::Node::Facts.stubs(:find).with("foo").returns(@facts) + end + + it "should search for the node by its key first" do + names = [] + @searcher.expects(:find).with do |name| + names << name + names == %w{foo} + end.returns(@node) + @searcher.search("foo").should equal(@node) + end + + it "should return the first node found using the generated list of names" do + names = [] + @searcher.expects(:find).with("foo").returns(nil) + @searcher.expects(:find).with("yay.domain.com").returns(@node) + @searcher.search("foo").should equal(@node) + end + + it "should search for the rest of the names inversely by length" do + names = [] + @facts.values["fqdn"] = "longer.than.the.normal.fqdn.com" + @searcher.stubs(:find).with do |name| + names << name + end + @searcher.search("foo") + # Strip off the key + names.shift + + # And the 'default' + names.pop + + length = 100 + names.each do |name| + (name.length < length).should be_true + length = name.length + end + end + + it "should attempt to find a default node if no names are found" do + names = [] + @searcher.stubs(:find).with do |name| + names << name + end.returns(nil) + @searcher.search("foo") + names[-1].should == "default" + end + + it "should cache the nodes" do + @searcher.expects(:find).with("foo").returns(@node) + @searcher.search("foo").should equal(@node) + @searcher.search("foo").should equal(@node) + end + + it "should flush the node cache using the :filetimeout parameter" do + node2 = Puppet::Node.new("foo2") + Puppet[:filetimeout] = -1 + # I couldn't get this to work with :expects + @searcher.stubs(:find).returns(@node, node2).then.raises(ArgumentError) + @searcher.search("foo").should equal(@node) + @searcher.search("foo").should equal(node2) + end + + after do + Puppet.settings.clear + end +end |
