diff options
author | Luke Kanies <luke@madstop.com> | 2007-09-22 00:16:39 -0500 |
---|---|---|
committer | Luke Kanies <luke@madstop.com> | 2007-09-22 00:16:39 -0500 |
commit | ebe7290bf0c9119e268c9037c33da515e527aa5b (patch) | |
tree | 3f59b5b3fc46c35f5ef18e0a1110381c94187692 /spec/unit | |
parent | b9dc6cb22f087f419b328cafa945c9604043b22f (diff) | |
download | puppet-ebe7290bf0c9119e268c9037c33da515e527aa5b.tar.gz puppet-ebe7290bf0c9119e268c9037c33da515e527aa5b.tar.xz puppet-ebe7290bf0c9119e268c9037c33da515e527aa5b.zip |
All indirections are working, and they have all
been migrated over to the new organization. Where we
would have previously had an 'ldap' node terminus at
puppet/indirector/node/ldap.rb, we would not have it at
puppet/indirector/ldap/node.rb, and it would be a subclass
of puppet/indirector/ldap.rb.
These are called terminus classes, and there are now three
categories of them: The base class itself, abstract classes
that provide most of the functionality (e.g., the ldap and
yaml classes), and the classes themselves that implement
the functionality for a given model like Node or Facts.
The base terminus class handles auto-loading any of these
classes from disk.
Diffstat (limited to 'spec/unit')
-rwxr-xr-x | spec/unit/indirector/exec.rb | 49 | ||||
-rwxr-xr-x | spec/unit/indirector/exec/node.rb | 62 | ||||
-rwxr-xr-x | spec/unit/indirector/indirection.rb | 20 | ||||
-rwxr-xr-x | spec/unit/indirector/ldap.rb | 147 | ||||
-rwxr-xr-x | spec/unit/indirector/ldap/node.rb | 84 | ||||
-rwxr-xr-x | spec/unit/indirector/node/external.rb | 119 | ||||
-rwxr-xr-x | spec/unit/indirector/node/ldap.rb | 243 | ||||
-rwxr-xr-x | spec/unit/indirector/node/none.rb | 32 | ||||
-rwxr-xr-x | spec/unit/indirector/null.rb | 27 | ||||
-rwxr-xr-x | spec/unit/indirector/null/node.rb | 18 | ||||
-rwxr-xr-x | spec/unit/indirector/terminus.rb | 14 |
11 files changed, 414 insertions, 401 deletions
diff --git a/spec/unit/indirector/exec.rb b/spec/unit/indirector/exec.rb new file mode 100755 index 000000000..42fbe0955 --- /dev/null +++ b/spec/unit/indirector/exec.rb @@ -0,0 +1,49 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/indirector/exec' + +describe Puppet::Indirector::Exec do + before do + @indirection = mock 'indirection' + Puppet::Indirector::Indirection.expects(:instance).with(:testing).returns(@indirection) + @exec_class = Class.new(Puppet::Indirector::Exec) do + def self.to_s + "Testing" + end + + attr_accessor :command + end + + @searcher = @exec_class.new + @searcher.command = ["/echo"] + end + + it "should throw an exception if the command is not an array" do + @searcher.command = "/usr/bin/echo" + proc { @searcher.find("foo") }.should raise_error(Puppet::DevError) + end + + it "should throw an exception if the command is not fully qualified" do + @searcher.command = ["mycommand"] + proc { @searcher.find("foo") }.should raise_error(ArgumentError) + end + + it "should execute the command with the object name as the only argument" do + @searcher.expects(:execute).with(%w{/echo yay}) + @searcher.find("yay") + end + + it "should return the output of the script" do + @searcher.expects(:execute).with(%w{/echo yay}).returns("whatever") + @searcher.find("yay").should == "whatever" + end + + it "should return nil when the command produces no output" do + @searcher.expects(:execute).with(%w{/echo yay}).returns(nil) + @searcher.find("yay").should be_nil + end + + it "should be able to execute commands with multiple arguments" +end diff --git a/spec/unit/indirector/exec/node.rb b/spec/unit/indirector/exec/node.rb new file mode 100755 index 000000000..2eaf3c12e --- /dev/null +++ b/spec/unit/indirector/exec/node.rb @@ -0,0 +1,62 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/indirector/exec/node' + +describe Puppet::Indirector::Exec::Node, " when constructing the command to run" do + before do + @indirection = mock 'indirection' + Puppet.config.stubs(:value).with(:external_nodes).returns("/echo") + @searcher = Puppet::Indirector::Exec::Node.new + end + + it "should use the external_node script as the command" do + Puppet.expects(:[]).with(:external_nodes).returns("/bin/echo") + @searcher.command.should == %w{/bin/echo} + end + + it "should throw an exception if no external node command is set" do + Puppet.expects(:[]).with(:external_nodes).returns("none") + proc { @searcher.find("foo") }.should raise_error(ArgumentError) + end +end + +describe Puppet::Indirector::Exec::Node, " when handling the results of the command" do + before do + @indirection = mock 'indirection' + Puppet.config.stubs(:value).with(:external_nodes).returns("/echo") + @searcher = Puppet::Indirector::Exec::Node.new + @node = stub 'node', :fact_merge => nil + @name = "yay" + Puppet::Node.expects(:new).with(@name).returns(@node) + @result = {} + # Use a local variable so the reference is usable in the execute() definition. + result = @result + @searcher.meta_def(:execute) do |command| + return YAML.dump(result) + end + end + + it "should translate the YAML into a Node instance" do + # Use an empty hash + @searcher.find(@name).should equal(@node) + end + + it "should set the resulting parameters as the node parameters" do + @result[:parameters] = {"a" => "b", "c" => "d"} + @node.expects(:parameters=).with "a" => "b", "c" => "d" + @searcher.find(@name) + end + + it "should set the resulting classes as the node classes" do + @result[:classes] = %w{one two} + @node.expects(:classes=).with %w{one two} + @searcher.find(@name) + end + + it "should merge the node's facts with its parameters" do + @node.expects(:fact_merge) + @searcher.find(@name) + end +end diff --git a/spec/unit/indirector/indirection.rb b/spec/unit/indirector/indirection.rb index 5866f2d5f..e57f12072 100755 --- a/spec/unit/indirector/indirection.rb +++ b/spec/unit/indirector/indirection.rb @@ -5,13 +5,19 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/indirector' describe Puppet::Indirector::Indirection, " when initializing" do + it "should keep a reference to the indirecting model" do + model = mock 'model' + @indirection = Puppet::Indirector::Indirection.new(model, :myind) + @indirection.model.should equal(model) + end + it "should set the name" do - @indirection = Puppet::Indirector::Indirection.new(:myind) + @indirection = Puppet::Indirector::Indirection.new(mock('model'), :myind) @indirection.name.should == :myind end it "should require indirections to have unique names" do - @indirection = Puppet::Indirector::Indirection.new(:test) + @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) proc { Puppet::Indirector::Indirection.new(:test) }.should raise_error(ArgumentError) end @@ -22,7 +28,7 @@ end describe Puppet::Indirector::Indirection, " when managing indirection instances" do it "should allow an indirection to be retrieved by name" do - @indirection = Puppet::Indirector::Indirection.new(:test) + @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) Puppet::Indirector::Indirection.instance(:test).should equal(@indirection) end @@ -37,7 +43,7 @@ end describe Puppet::Indirector::Indirection, " when choosing terminus types" do before do - @indirection = Puppet::Indirector::Indirection.new(:test) + @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) @terminus = mock 'terminus' @terminus_class = stub 'terminus class', :new => @terminus end @@ -82,7 +88,7 @@ end describe Puppet::Indirector::Indirection, " when managing terminus instances" do before do - @indirection = Puppet::Indirector::Indirection.new(:test) + @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) @terminus = mock 'terminus' @terminus_class = mock 'terminus class' Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class) @@ -111,7 +117,7 @@ describe Puppet::Indirector::Indirection, " when managing terminus instances" do it "should not create a terminus instance until one is actually needed" do Puppet::Indirector.expects(:terminus).never - indirection = Puppet::Indirector::Indirection.new(:lazytest) + indirection = Puppet::Indirector::Indirection.new(mock('model'), :lazytest) end after do @@ -122,7 +128,7 @@ end describe Puppet::Indirector::Indirection do before do - @indirection = Puppet::Indirector::Indirection.new(:test) + @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) @terminus = mock 'terminus' @indirection.stubs(:terminus).returns(@terminus) end diff --git a/spec/unit/indirector/ldap.rb b/spec/unit/indirector/ldap.rb new file mode 100755 index 000000000..a936936bc --- /dev/null +++ b/spec/unit/indirector/ldap.rb @@ -0,0 +1,147 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/indirector/ldap' + +describe Puppet::Indirector::Ldap, " when searching ldap" do + before do + @indirection = mock 'indirection' + Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection) + @ldap_class = Class.new(Puppet::Indirector::Ldap) do + def self.to_s + "Testing" + end + end + + @connection = mock 'ldap' + + @searcher = @ldap_class.new + + # Stub everything, and we can selectively replace with an expect as + # we need to for testing. + @searcher.stubs(:connection).returns(@connection) + @searcher.stubs(:search_filter).returns(:filter) + @searcher.stubs(:search_base).returns(:base) + @searcher.stubs(:process) + end + + it "should call the ldapsearch method with the name being searched for" do + @searcher.expects(:ldapsearch).with("yay") + @searcher.find "yay" + end + + it "should fail if no block is passed to the ldapsearch method" do + proc { @searcher.ldapsearch("blah") }.should raise_error(ArgumentError) + end + + it "should use the results of the ldapbase method as the ldap search base" do + @searcher.stubs(:search_base).returns("mybase") + @connection.expects(:search).with do |*args| + args[0].should == "mybase" + true + end + @searcher.find "yay" + end + + it "should default to the value of the :search_base setting as the result of the ldapbase method" do + Puppet.expects(:[]).with(:ldapbase).returns("myldapbase") + searcher = @ldap_class.new + searcher.search_base.should == "myldapbase" + end + + it "should use the results of the :search_attributes method as the list of attributes to return" do + @searcher.stubs(:search_attributes).returns(:myattrs) + @connection.expects(:search).with do |*args| + args[3].should == :myattrs + true + end + @searcher.find "yay" + end + + it "should use the results of the :search_filter method as the search filter" do + @searcher.stubs(:search_filter).with("yay").returns("yay's filter") + @connection.expects(:search).with do |*args| + args[2].should == "yay's filter" + true + end + @searcher.find "yay" + end + + it "should use depth 2 when searching" do + @connection.expects(:search).with do |*args| + args[1].should == 2 + true + end + @searcher.find "yay" + end + + it "should call process() on the first found entry" do + @connection.expects(:search).yields("myresult") + @searcher.expects(:process).with("myresult") + @searcher.find "yay" + end + + it "should reconnect and retry the search if there is a failure" do + run = false + @connection.stubs(:search).with do |*args| + if run + true + else + run = true + raise "failed" + end + end.yields("myresult") + @searcher.expects(:process).with("myresult") + + @searcher.find "yay" + end + + it "should not reconnect on failure more than once" do + count = 0 + @connection.stubs(:search).with do |*args| + count += 1 + raise ArgumentError, "yay" + end + proc { @searcher.find("whatever") }.should raise_error(Puppet::Error) + count.should == 2 + end + + it "should return true if an entry is found" do + @connection.expects(:search).yields("result") + @searcher.ldapsearch("whatever") { |r| }.should be_true + end +end + +describe Puppet::Indirector::Ldap, " when connecting to ldap" do + confine "LDAP is not available" => Puppet.features.ldap? + confine "No LDAP test data for networks other than Luke's" => Facter.value(:domain) == "madstop.com" + + it "should only create the ldap connection when asked for it the first time" + + it "should throw an exception if it cannot connect to LDAP" + + it "should use SSL when the :ldapssl setting is true" + + it "should connect to the server specified in the :ldapserver setting" + + it "should use the port specified in the :ldapport setting" + + it "should use protocol version 3" + + it "should follow referrals" + + it "should use the user specified in the :ldapuser setting" + + it "should use the password specified in the :ldappassord setting" + + it "should have an ldap method that returns an LDAP connection object" + + it "should fail when LDAP support is missing" +end + +describe Puppet::Indirector::Ldap, " when reconnecting to ldap" do + confine "Not running on culain as root" => (Puppet::Util::SUIDManager.uid == 0 and Facter.value("hostname") == "culain") + + it "should reconnect to ldap when connections are lost" +end diff --git a/spec/unit/indirector/ldap/node.rb b/spec/unit/indirector/ldap/node.rb new file mode 100755 index 000000000..edaf77e92 --- /dev/null +++ b/spec/unit/indirector/ldap/node.rb @@ -0,0 +1,84 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/indirector/ldap/node' + +describe Puppet::Indirector::Ldap::Node, " when searching for nodes" do + before do + @searcher = Puppet::Indirector::Ldap::Node.new + end + + it "should return the value of the :ldapclassattrs split on commas as the class attributes" do + Puppet.stubs(:[]).with(:ldapclassattrs).returns("one,two") + @searcher.class_attributes.should == %w{one two} + end + + it "should return nil as the parent attribute if the :ldapparentattr is set to an empty string" do + Puppet.stubs(:[]).with(:ldapparentattr).returns("") + @searcher.parent_attribute.should be_nil + end + + it "should return the value of the :ldapparentattr as the parent attribute" do + Puppet.stubs(:[]).with(:ldapparentattr).returns("pere") + @searcher.parent_attribute.should == "pere" + end + + it "should use the value of the :ldapstring as the search filter" do + Puppet.stubs(:[]).with(:ldapstring).returns("mystring") + @searcher.search_filter("testing").should == "mystring" + end + + it "should replace '%s' with the node name in the search filter if it is present" do + Puppet.stubs(:[]).with(:ldapstring).returns("my%sstring") + @searcher.search_filter("testing").should == "mytestingstring" + end + + it "should not modify the global :ldapstring when replacing '%s' in the search filter" do + filter = mock 'filter' + filter.expects(:include?).with("%s").returns(true) + filter.expects(:gsub).with("%s", "testing").returns("mynewstring") + Puppet.stubs(:[]).with(:ldapstring).returns(filter) + @searcher.search_filter("testing").should == "mynewstring" + end +end + +describe Puppet::Indirector::Ldap::Node, " when deciding attributes to search for" do + before do + @searcher = Puppet::Indirector::Ldap::Node.new + end + + it "should use 'nil' if the :ldapattrs setting is 'all'" do + Puppet.stubs(:[]).with(:ldapattrs).returns("all") + @searcher.search_attributes.should be_nil + end + + it "should split the value of :ldapattrs on commas and use the result as the attribute list" do + Puppet.stubs(:[]).with(:ldapattrs).returns("one,two") + @searcher.stubs(:class_attributes).returns([]) + @searcher.stubs(:parent_attribute).returns(nil) + @searcher.search_attributes.should == %w{one two} + end + + it "should add the class attributes to the search attributes if not returning all attributes" do + Puppet.stubs(:[]).with(:ldapattrs).returns("one,two") + @searcher.stubs(:class_attributes).returns(%w{three four}) + @searcher.stubs(:parent_attribute).returns(nil) + # Sort them so i don't have to care about return order + @searcher.search_attributes.sort.should == %w{one two three four}.sort + end + + it "should add the parent attribute to the search attributes if not returning all attributes" do + Puppet.stubs(:[]).with(:ldapattrs).returns("one,two") + @searcher.stubs(:class_attributes).returns([]) + @searcher.stubs(:parent_attribute).returns("parent") + @searcher.search_attributes.sort.should == %w{one two parent}.sort + end + + it "should not add nil parent attributes to the search attributes" do + Puppet.stubs(:[]).with(:ldapattrs).returns("one,two") + @searcher.stubs(:class_attributes).returns([]) + @searcher.stubs(:parent_attribute).returns(nil) + @searcher.search_attributes.should == %w{one two} + end +end diff --git a/spec/unit/indirector/node/external.rb b/spec/unit/indirector/node/external.rb deleted file mode 100755 index c64a6f6e2..000000000 --- a/spec/unit/indirector/node/external.rb +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -require 'yaml' -require 'puppet/indirector' - -describe Puppet::Indirector.terminus(:node, :external), " when searching for nodes" do - require 'puppet/node' - - before do - Puppet.config[:external_nodes] = "/yay/ness" - @searcher = Puppet::Indirector.terminus(:node, :external).new - - # Set the searcher up so that we do not need to actually call the - # external script. - @searcher.meta_def(:execute) do |command| - name = command.last.chomp - result = {} - - if name =~ /a/ - result[:parameters] = {'one' => command.last + '1', 'two' => command.last + '2'} - end - - if name =~ /p/ - result['classes'] = [1,2,3].collect { |n| command.last + n.to_s } - end - - return YAML.dump(result) - end - end - - it "should throw an exception if the node_source is external but no external node command is set" do - Puppet[:external_nodes] = "none" - proc { @searcher.find("foo") }.should raise_error(ArgumentError) - end - - it "should throw an exception if the external node source is not fully qualified" do - Puppet[:external_nodes] = "mycommand" - proc { @searcher.find("foo") }.should raise_error(ArgumentError) - end - - it "should execute the command with the node name as the only argument" do - command = [Puppet[:external_nodes], "yay"] - @searcher.expects(:execute).with(command).returns("") - @searcher.find("yay") - end - - it "should return a node object" do - @searcher.find("apple").should be_instance_of(Puppet::Node) - end - - it "should set the node's name" do - @searcher.find("apple").name.should == "apple" - end - - # If we use a name that has a 'p' but no 'a', then our test generator - # will return classes but no parameters. - it "should be able to configure a node's classes" do - node = @searcher.find("plum") - node.classes.should == %w{plum1 plum2 plum3} - node.parameters.should == {} - end - - # If we use a name that has an 'a' but no 'p', then our test generator - # will return parameters but no classes. - it "should be able to configure a node's parameters" do - node = @searcher.find("guava") - node.classes.should == [] - node.parameters.should == {"one" => "guava1", "two" => "guava2"} - end - - it "should be able to configure a node's classes and parameters" do - node = @searcher.find("apple") - node.classes.should == %w{apple1 apple2 apple3} - node.parameters.should == {"one" => "apple1", "two" => "apple2"} - end - - it "should merge node facts with returned parameters" do - facts = Puppet::Node::Facts.new("apple", "three" => "four") - Puppet::Node::Facts.expects(:find).with("apple").returns(facts) - node = @searcher.find("apple") - node.parameters["three"].should == "four" - end - - it "should return nil when it cannot find the node" do - @searcher.find("honeydew").should be_nil - end - - # Make sure a nodesearch with arguments works - def test_nodesearch_external_arguments - mapper = mk_node_mapper - Puppet[:external_nodes] = "#{mapper} -s something -p somethingelse" - searcher = mk_searcher(:external) - node = nil - assert_nothing_raised do - node = searcher.nodesearch("apple") - end - assert_instance_of(SimpleNode, node, "did not create node") - end - - # A wrapper test, to make sure we're correctly calling the external search method. - def test_nodesearch_external_functional - mapper = mk_node_mapper - searcher = mk_searcher(:external) - - Puppet[:external_nodes] = mapper - - node = nil - assert_nothing_raised do - node = searcher.nodesearch("apple") - end - assert_instance_of(SimpleNode, node, "did not create node") - end - - after do - Puppet.config.clear - end -end diff --git a/spec/unit/indirector/node/ldap.rb b/spec/unit/indirector/node/ldap.rb deleted file mode 100755 index e4b0cd7d4..000000000 --- a/spec/unit/indirector/node/ldap.rb +++ /dev/null @@ -1,243 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' - -require 'yaml' -require 'puppet/indirector' - -describe Puppet::Indirector.terminus(:node, :ldap), " when searching for nodes" do - require 'puppet/node' - - def setup - Puppet.config[:external_nodes] = "/yay/ness" - @searcher = Puppet::Indirector.terminus(:node, :ldap).new - nodetable = {} - @nodetable = nodetable - # Override the ldapsearch definition, so we don't have to actually set it up. - @searcher.meta_def(:ldapsearch) do |name| - nodetable[name] - end - end - - it "should return nil for hosts that cannot be found" do - @searcher.find("foo").should be_nil - end - - it "should return Puppet::Node instances" do - @nodetable["foo"] = [nil, %w{}, {}] - @searcher.find("foo").should be_instance_of(Puppet::Node) - end - - it "should set the node name" do - @nodetable["foo"] = [nil, %w{}, {}] - @searcher.find("foo").name.should == "foo" - end - - it "should set the classes" do - @nodetable["foo"] = [nil, %w{one two}, {}] - @searcher.find("foo").classes.should == %w{one two} - end - - it "should set the parameters" do - @nodetable["foo"] = [nil, %w{}, {"one" => "two"}] - @searcher.find("foo").parameters.should == {"one" => "two"} - end - - it "should set classes and parameters from the parent node" do - @nodetable["foo"] = ["middle", %w{one two}, {"one" => "two"}] - @nodetable["middle"] = [nil, %w{three four}, {"three" => "four"}] - node = @searcher.find("foo") - node.classes.sort.should == %w{one two three four}.sort - node.parameters.should == {"one" => "two", "three" => "four"} - end - - it "should prefer child parameters to parent parameters" do - @nodetable["foo"] = ["middle", %w{}, {"one" => "two"}] - @nodetable["middle"] = [nil, %w{}, {"one" => "four"}] - @searcher.find("foo").parameters["one"].should == "two" - end - - it "should recurse indefinitely through parent relationships" do - @nodetable["foo"] = ["middle", %w{one two}, {"one" => "two"}] - @nodetable["middle"] = ["top", %w{three four}, {"three" => "four"}] - @nodetable["top"] = [nil, %w{five six}, {"five" => "six"}] - node = @searcher.find("foo") - node.parameters.should == {"one" => "two", "three" => "four", "five" => "six"} - node.classes.sort.should == %w{one two three four five six}.sort - end - - # This can stay in the main test suite because it doesn't actually use ldapsearch, - # it just overrides the method so it behaves as though it were hitting ldap. - def test_ldap_nodesearch - - # Make sure we get nothing for nonexistent hosts - node = nil - assert_nothing_raised do - node = searcher.nodesearch("nosuchhost") - end - - assert_nil(node, "Got a node for a non-existent host") - - # Now add a base node with some classes and parameters - nodetable["base"] = [nil, %w{one two}, {"base" => "true"}] - - assert_nothing_raised do - node = searcher.nodesearch("base") - end - - assert_instance_of(SimpleNode, node, "Did not get node from ldap nodesearch") - assert_equal("base", node.name, "node name was not set") - - assert_equal(%w{one two}, node.classes, "node classes were not set") - assert_equal({"base" => "true"}, node.parameters, "node parameters were not set") - - # Now use a different with this as the base - nodetable["middle"] = ["base", %w{three}, {"center" => "boo"}] - assert_nothing_raised do - node = searcher.nodesearch("middle") - end - - assert_instance_of(SimpleNode, node, "Did not get node from ldap nodesearch") - assert_equal("middle", node.name, "node name was not set") - - assert_equal(%w{one two three}.sort, node.classes.sort, "node classes were not set correctly with a parent node") - assert_equal({"base" => "true", "center" => "boo"}, node.parameters, "node parameters were not set correctly with a parent node") - - # And one further, to make sure we fully recurse - nodetable["top"] = ["middle", %w{four five}, {"master" => "far"}] - assert_nothing_raised do - node = searcher.nodesearch("top") - end - - assert_instance_of(SimpleNode, node, "Did not get node from ldap nodesearch") - assert_equal("top", node.name, "node name was not set") - - assert_equal(%w{one two three four five}.sort, node.classes.sort, "node classes were not set correctly with the top node") - assert_equal({"base" => "true", "center" => "boo", "master" => "far"}, node.parameters, "node parameters were not set correctly with the top node") - end -end - -describe Puppet::Indirector.terminus(:node, :ldap), " when interacting with ldap" do - confine "LDAP is not available" => Puppet.features.ldap? - confine "No LDAP test data for networks other than Luke's" => Facter.value(:domain) == "madstop.com" - - def ldapconnect - - @ldap = LDAP::Conn.new("ldap", 389) - @ldap.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 ) - @ldap.simple_bind("", "") - - return @ldap - end - - def ldaphost(name) - node = Puppet::Node.new(name) - parent = nil - found = false - @ldap.search( "ou=hosts, dc=madstop, dc=com", 2, - "(&(objectclass=puppetclient)(cn=%s))" % name - ) do |entry| - node.classes = entry.vals("puppetclass") || [] - node.parameters = entry.to_hash.inject({}) do |hash, ary| - if ary[1].length == 1 - hash[ary[0]] = ary[1].shift - else - hash[ary[0]] = ary[1] - end - hash - end - parent = node.parameters["parentnode"] - found = true - end - raise "Could not find node %s" % name unless found - - return node, parent - end - - it "should have tests" do - raise ArgumentError - end - - def test_ldapsearch - Puppet[:ldapbase] = "ou=hosts, dc=madstop, dc=com" - Puppet[:ldapnodes] = true - - searcher = Object.new - searcher.extend(Node.node_source(:ldap)) - - ldapconnect() - - # Make sure we get nil and nil back when we search for something missing - parent, classes, parameters = nil - assert_nothing_raised do - parent, classes, parameters = searcher.ldapsearch("nosuchhost") - end - - assert_nil(parent, "Got a parent for a non-existent host") - assert_nil(classes, "Got classes for a non-existent host") - - # Make sure we can find 'culain' in ldap - assert_nothing_raised do - parent, classes, parameters = searcher.ldapsearch("culain") - end - - node, realparent = ldaphost("culain") - assert_equal(realparent, parent, "did not get correct parent node from ldap") - assert_equal(node.classes, classes, "did not get correct ldap classes from ldap") - assert_equal(node.parameters, parameters, "did not get correct ldap parameters from ldap") - - # Now compare when we specify the attributes to get. - Puppet[:ldapattrs] = "cn" - assert_nothing_raised do - parent, classes, parameters = searcher.ldapsearch("culain") - end - assert_equal(realparent, parent, "did not get correct parent node from ldap") - assert_equal(node.classes, classes, "did not get correct ldap classes from ldap") - - list = %w{cn puppetclass parentnode dn} - should = node.parameters.inject({}) { |h, a| h[a[0]] = a[1] if list.include?(a[0]); h } - assert_equal(should, parameters, "did not get correct ldap parameters from ldap") - end -end - -describe Puppet::Indirector.terminus(:node, :ldap), " when connecting to ldap" do - confine "Not running on culain as root" => (Puppet::Util::SUIDManager.uid == 0 and Facter.value("hostname") == "culain") - - it "should have tests" do - raise ArgumentError - end - - def test_ldapreconnect - Puppet[:ldapbase] = "ou=hosts, dc=madstop, dc=com" - Puppet[:ldapnodes] = true - - searcher = Object.new - searcher.extend(Node.node_source(:ldap)) - hostname = "culain.madstop.com" - - # look for our host - assert_nothing_raised { - parent, classes = searcher.nodesearch(hostname) - } - - # Now restart ldap - system("/etc/init.d/slapd restart 2>/dev/null >/dev/null") - sleep(1) - - # and look again - assert_nothing_raised { - parent, classes = searcher.nodesearch(hostname) - } - - # Now stop ldap - system("/etc/init.d/slapd stop 2>/dev/null >/dev/null") - cleanup do - system("/etc/init.d/slapd start 2>/dev/null >/dev/null") - end - - # And make sure we actually fail here - assert_raise(Puppet::Error) { - parent, classes = searcher.nodesearch(hostname) - } - end -end diff --git a/spec/unit/indirector/node/none.rb b/spec/unit/indirector/node/none.rb deleted file mode 100755 index 2329cdfbb..000000000 --- a/spec/unit/indirector/node/none.rb +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../../spec_helper' -require 'puppet/indirector' -require 'puppet/node/facts' - -describe Puppet::Indirector.terminus(:node, :none), " when searching for nodes" do - before do - Puppet.config[:node_source] = "none" - @searcher = Puppet::Indirector.terminus(:node, :none).new - end - - it "should create a node instance" do - @searcher.find("yay").should be_instance_of(Puppet::Node) - end - - it "should create a new node with the correct name" do - @searcher.find("yay").name.should == "yay" - end - - it "should merge the node's facts" do - facts = Puppet::Node::Facts.new("yay", "one" => "two", "three" => "four") - Puppet::Node::Facts.expects(:find).with("yay").returns(facts) - node = @searcher.find("yay") - node.parameters["one"].should == "two" - node.parameters["three"].should == "four" - end - - after do - Puppet.config.clear - end -end diff --git a/spec/unit/indirector/null.rb b/spec/unit/indirector/null.rb new file mode 100755 index 000000000..9e1dcb07c --- /dev/null +++ b/spec/unit/indirector/null.rb @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' +require 'puppet/indirector/null' + +describe Puppet::Indirector::Null do + before do + Puppet::Indirector::Terminus.stubs(:register_terminus_class) + @model = mock 'model' + @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model + Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection) + + @null_class = Class.new(Puppet::Indirector::Null) do + def self.to_s + "Testing" + end + end + + @searcher = @null_class.new + end + + it "should return return an instance of the indirected model" do + object = mock 'object' + @model.expects(:new).with("yay").returns object + @searcher.find("yay").should equal(object) + end +end diff --git a/spec/unit/indirector/null/node.rb b/spec/unit/indirector/null/node.rb new file mode 100755 index 000000000..c589e5820 --- /dev/null +++ b/spec/unit/indirector/null/node.rb @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/indirector/null/node' + +describe Puppet::Indirector::Null::Node do + before do + @searcher = Puppet::Indirector::Null::Node.new + end + + it "should call node_merge() on the returned node" do + node = mock 'node' + Puppet::Node.expects(:new).with("mynode").returns(node) + node.expects(:fact_merge) + @searcher.find("mynode") + end +end diff --git a/spec/unit/indirector/terminus.rb b/spec/unit/indirector/terminus.rb index 08e7e6ccb..dc86cf315 100755 --- a/spec/unit/indirector/terminus.rb +++ b/spec/unit/indirector/terminus.rb @@ -36,6 +36,10 @@ describe Puppet::Indirector::Terminus do @terminus.should respond_to(:terminus_type) end + it "should support a class-level model attribute" do + @terminus.should respond_to(:model) + end + it "should accept indirection instances as its indirection" do indirection = stub 'indirection', :is_a? => true, :register_terminus_type => nil proc { @terminus.indirection = indirection }.should_not raise_error @@ -177,6 +181,11 @@ describe Puppet::Indirector::Terminus, " when creating terminus classes" do it "should set the subclass's name to the indirection name" do @terminus.name.should == :myindirection end + + it "should set the subclass's model to the indirection model" do + @indirection.expects(:model).returns :yay + @terminus.model.should == :yay + end end describe Puppet::Indirector::Terminus, " when a terminus instance" do @@ -209,4 +218,9 @@ describe Puppet::Indirector::Terminus, " when a terminus instance" do it "should set the instances's type to the abstract terminus type's name" do @terminus.terminus_type.should == :abstract end + + it "should set the instances's model to the indirection's model" do + @indirection.expects(:model).returns :yay + @terminus.model.should == :yay + end end |