summaryrefslogtreecommitdiffstats
path: root/spec/unit/indirector/node/ldap.rb
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-07-01 21:55:53 -0500
committerLuke Kanies <luke@madstop.com>2008-07-01 22:22:07 -0500
commitb47d4e1b3e1224541e555648854baf0503b1612e (patch)
treef6c49b41ce1a5b13fe58e715ca60e4caf15ee0ba /spec/unit/indirector/node/ldap.rb
parenta1d1abdd5a2fc11dceeed63da8c6f48d2fa21cfe (diff)
downloadpuppet-b47d4e1b3e1224541e555648854baf0503b1612e.tar.gz
puppet-b47d4e1b3e1224541e555648854baf0503b1612e.tar.xz
puppet-b47d4e1b3e1224541e555648854baf0503b1612e.zip
Added a 'search' method to the ldap node terminus.
This makes it easy to find multiple nodes in ldap, and was done so it can be used by puppetrun.
Diffstat (limited to 'spec/unit/indirector/node/ldap.rb')
-rwxr-xr-xspec/unit/indirector/node/ldap.rb439
1 files changed, 221 insertions, 218 deletions
diff --git a/spec/unit/indirector/node/ldap.rb b/spec/unit/indirector/node/ldap.rb
index 24b2dd759..03faaa557 100755
--- a/spec/unit/indirector/node/ldap.rb
+++ b/spec/unit/indirector/node/ldap.rb
@@ -5,304 +5,307 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
require 'puppet/indirector/node/ldap'
describe Puppet::Node::Ldap do
- describe "when searching for nodes" do
+ before do
+ Puppet::Node::Facts.stubs(:terminus_class).returns :yaml
+ end
+
+ describe "when searching for a single node" do
before :each do
@searcher = Puppet::Node::Ldap.new
- @entries = {}
- entries = @entries
- @connection = mock 'connection'
- @entry = mock 'entry'
- @connection.stubs(:search).yields(@entry)
- @searcher.stubs(:connection).returns(@connection)
- @searcher.stubs(:class_attributes).returns([])
- @searcher.stubs(:parent_attribute).returns(nil)
- @searcher.stubs(:stacked_attributes).returns([])
- @searcher.stubs(:search_base).returns(:yay)
- @searcher.stubs(:search_filter).returns(:filter)
-
@name = "mynode.domain.com"
- @node = stub 'node', :name => @name
- @node.stubs(:fact_merge)
- Puppet::Node.stubs(:new).with(@name).returns(@node)
+ @node = stub 'node', :name => @name, :name= => nil
+ @node.stub_everything
+
+ Puppet::Node.stubs(:new).returns(@node)
@request = stub 'request', :key => @name
end
- it "should search first for the provided key" do
- @searcher.expects(:entry2hash).with("mynode.domain.com").returns({})
- @searcher.find(@request)
+ it "should convert the hostname into a search filter" do
+ entry = stub 'entry', :dn => 'cn=mynode.domain.com,ou=hosts,dc=madstop,dc=com', :vals => %w{}, :to_hash => {}
+ @searcher.expects(:ldapsearch).with("(&(objectclass=puppetClient)(cn=#{@name}))").yields entry
+ @searcher.name2hash(@name)
end
- it "should search for the short version of the provided key if the key looks like a hostname and no results are found for the key itself" do
- @searcher.expects(:entry2hash).with("mynode.domain.com").returns(nil)
- @searcher.expects(:entry2hash).with("mynode").returns({})
- @searcher.find(@request)
+ it "should convert any found entry into a hash" do
+ entry = stub 'entry', :dn => 'cn=mynode.domain.com,ou=hosts,dc=madstop,dc=com', :vals => %w{}, :to_hash => {}
+ @searcher.expects(:ldapsearch).with("(&(objectclass=puppetClient)(cn=#{@name}))").yields entry
+ @searcher.expects(:entry2hash).with(entry).returns "myhash"
+ @searcher.name2hash(@name).should == "myhash"
end
- it "should search for default information if no information can be found for the key" do
- @searcher.expects(:entry2hash).with("mynode.domain.com").returns(nil)
- @searcher.expects(:entry2hash).with("mynode").returns(nil)
- @searcher.expects(:entry2hash).with("default").returns({})
- @searcher.find(@request)
- end
+ # This heavily tests our entry2hash method, so we don't have to stub out the stupid entry information any more.
+ describe "when an ldap entry is found" do
+ before do
+ @entry = stub 'entry', :dn => 'cn=mynode.domain.com,ou=hosts,dc=madstop,dc=com', :vals => %w{}, :to_hash => {}
+ @searcher.stubs(:ldapsearch).yields @entry
+ end
- it "should return nil if no results are found in ldap" do
- @connection.stubs(:search)
- @searcher.find(@request).should be_nil
- end
+ it "should convert the entry to a hash" do
+ @searcher.entry2hash(@entry).should be_instance_of(Hash)
+ end
- it "should return a node object if results are found in ldap" do
- @entry.stubs(:to_hash).returns({})
- @searcher.find(@request).should equal(@node)
- end
+ it "should add the entry's common name to the hash" do
+ @searcher.entry2hash(@entry)[:name].should == "mynode.domain.com"
+ end
- it "should deduplicate class values" do
- @entry.stubs(:to_hash).returns({})
- @searcher.stubs(:class_attributes).returns(%w{one two})
- @entry.stubs(:vals).with("one").returns(%w{a b})
- @entry.stubs(:vals).with("two").returns(%w{b c})
- @node.expects(:classes=).with(%w{a b c})
- @searcher.find(@request)
- end
+ it "should add all of the entry's classes to the hash" do
+ @entry.stubs(:vals).with("puppetclass").returns %w{one two}
+ @searcher.entry2hash(@entry)[:classes].should == %w{one two}
+ end
- it "should add any values stored in the class_attributes attributes to the node classes" do
- @entry.stubs(:to_hash).returns({})
- @searcher.stubs(:class_attributes).returns(%w{one two})
- @entry.stubs(:vals).with("one").returns(%w{a b})
- @entry.stubs(:vals).with("two").returns(%w{c d})
- @node.expects(:classes=).with(%w{a b c d})
- @searcher.find(@request)
+ it "should deduplicate class values" do
+ @entry.stubs(:to_hash).returns({})
+ @searcher.stubs(:class_attributes).returns(%w{one two})
+ @entry.stubs(:vals).with("one").returns(%w{a b})
+ @entry.stubs(:vals).with("two").returns(%w{b c})
+ @searcher.entry2hash(@entry)[:classes].should == %w{a b c}
+ end
+
+ it "should add the entry's environment to the hash" do
+ @entry.stubs(:to_hash).returns("environment" => %w{production})
+ @searcher.entry2hash(@entry)[:environment].should == "production"
+ end
+
+ it "should add all stacked parameters as parameters in the hash" do
+ @entry.stubs(:vals).with("puppetvar").returns(%w{one=two three=four})
+ result = @searcher.entry2hash(@entry)
+ result[:parameters]["one"].should == "two"
+ result[:parameters]["three"].should == "four"
+ end
+
+ it "should not add the stacked parameter as a normal parameter" do
+ @entry.stubs(:vals).with("puppetvar").returns(%w{one=two three=four})
+ @entry.stubs(:to_hash).returns("puppetvar" => %w{one=two three=four})
+ @searcher.entry2hash(@entry)[:parameters]["puppetvar"].should be_nil
+ end
+
+ it "should add all other attributes as parameters in the hash" do
+ @entry.stubs(:to_hash).returns("foo" => %w{one two})
+ @searcher.entry2hash(@entry)[:parameters]["foo"].should == %w{one two}
+ end
+
+ it "should return single-value parameters as strings, not arrays" do
+ @entry.stubs(:to_hash).returns("foo" => %w{one})
+ @searcher.entry2hash(@entry)[:parameters]["foo"].should == "one"
+ end
+
+ it "should add the parent's name if present" do
+ @entry.stubs(:vals).with("parentnode").returns(%w{foo})
+ @searcher.entry2hash(@entry)[:parent].should == "foo"
+ end
+
+ it "should fail if more than one parent is specified" do
+ @entry.stubs(:vals).with("parentnode").returns(%w{foo})
+ @searcher.entry2hash(@entry)[:parent].should == "foo"
+ end
end
- it "should add all entry attributes as node parameters" do
- @entry.stubs(:to_hash).returns("one" => ["two"], "three" => ["four"])
- @node.expects(:parameters=).with("one" => "two", "three" => "four")
+ it "should search first for the provided key" do
+ @searcher.expects(:name2hash).with("mynode.domain.com").returns({})
@searcher.find(@request)
end
- it "should set the node's environment to the environment of the results" do
- @entry.stubs(:to_hash).returns("environment" => ["test"])
- @node.stubs(:parameters=)
- @node.expects(:environment=).with("test")
+ it "should search for the short version of the provided key if the key looks like a hostname and no results are found for the key itself" do
+ @searcher.expects(:name2hash).with("mynode.domain.com").returns(nil)
+ @searcher.expects(:name2hash).with("mynode").returns({})
@searcher.find(@request)
end
- it "should retain false parameter values" do
- @entry.stubs(:to_hash).returns("one" => [false])
- @node.expects(:parameters=).with("one" => false)
+ it "should search for default information if no information can be found for the key" do
+ @searcher.expects(:name2hash).with("mynode.domain.com").returns(nil)
+ @searcher.expects(:name2hash).with("mynode").returns(nil)
+ @searcher.expects(:name2hash).with("default").returns({})
@searcher.find(@request)
end
- it "should turn single-value parameter value arrays into single non-arrays" do
- @entry.stubs(:to_hash).returns("one" => ["a"])
- @node.expects(:parameters=).with("one" => "a")
- @searcher.find(@request)
+ it "should return nil if no results are found in ldap" do
+ @searcher.stubs(:name2hash).returns nil
+ @searcher.find(@request).should be_nil
end
- it "should keep multi-valued parametes as arrays" do
- @entry.stubs(:to_hash).returns("one" => ["a", "b"])
- @node.expects(:parameters=).with("one" => ["a", "b"])
- @searcher.find(@request)
+ it "should return a node object if results are found in ldap" do
+ @searcher.stubs(:name2hash).returns({})
+ @searcher.find(@request).should equal(@node)
end
- describe "and a parent node is specified" do
+ describe "and node information is found in LDAP" do
before do
- @parent = mock 'parent'
- @parent_parent = mock 'parent_parent'
-
- @searcher.meta_def(:search_filter) do |name|
- return name
- end
- @connection.stubs(:search).with { |*args| args[2] == @name }.yields(@entry)
- @connection.stubs(:search).with { |*args| args[2] == 'parent' }.yields(@parent)
- @connection.stubs(:search).with { |*args| args[2] == 'parent_parent' }.yields(@parent_parent)
-
- @searcher.stubs(:parent_attribute).returns(:parent)
+ @result = {}
+ @searcher.stubs(:name2hash).returns @result
end
- it "should fail if the parent cannot be found" do
- @connection.stubs(:search).with { |*args| args[2] == 'parent' }.returns("whatever")
-
- @entry.stubs(:to_hash).returns({})
- @entry.stubs(:vals).with(:parent).returns(%w{parent})
-
- proc { @searcher.find(@request) }.should raise_error(Puppet::Error)
- end
-
- it "should add any parent classes to the node's classes" do
- @entry.stubs(:to_hash).returns({})
- @entry.stubs(:vals).with(:parent).returns(%w{parent})
- @entry.stubs(:vals).with("classes").returns(%w{a b})
-
- @parent.stubs(:to_hash).returns({})
- @parent.stubs(:vals).with("classes").returns(%w{c d})
- @parent.stubs(:vals).with(:parent).returns(nil)
-
- @searcher.stubs(:class_attributes).returns(%w{classes})
+ it "should add any classes from ldap" do
+ @result[:classes] = %w[a b c d]
@node.expects(:classes=).with(%w{a b c d})
@searcher.find(@request)
end
- it "should add any parent parameters to the node's parameters" do
- @entry.stubs(:to_hash).returns("one" => "two")
- @entry.stubs(:vals).with(:parent).returns(%w{parent})
-
- @parent.stubs(:to_hash).returns("three" => "four")
- @parent.stubs(:vals).with(:parent).returns(nil)
-
+ it "should add all entry attributes as node parameters" do
+ @result[:parameters] = {"one" => "two", "three" => "four"}
@node.expects(:parameters=).with("one" => "two", "three" => "four")
@searcher.find(@request)
end
- it "should prefer node parameters over parent parameters" do
- @entry.stubs(:to_hash).returns("one" => "two")
- @entry.stubs(:vals).with(:parent).returns(%w{parent})
-
- @parent.stubs(:to_hash).returns("one" => "three")
- @parent.stubs(:vals).with(:parent).returns(nil)
+ it "should set the node's environment to the environment of the results" do
+ @result[:environment] = "test"
+ @node.expects(:environment=).with("test")
+ @searcher.find(@request)
+ end
- @node.expects(:parameters=).with("one" => "two")
+ it "should retain false parameter values" do
+ @result[:parameters] = {}
+ @result[:parameters]["one"] = false
+ @node.expects(:parameters=).with("one" => false)
@searcher.find(@request)
end
- it "should use the parent's environment if the node has none" do
- @entry.stubs(:to_hash).returns({})
- @entry.stubs(:vals).with(:parent).returns(%w{parent})
+ describe "and a parent node is specified" do
+ before do
+ @entry = {:classes => [], :parameters => {}}
+ @parent = {:classes => [], :parameters => {}}
+ @parent_parent = {:classes => [], :parameters => {}}
- @parent.stubs(:to_hash).returns("environment" => ["parent"])
- @parent.stubs(:vals).with(:parent).returns(nil)
+ @searcher.stubs(:name2hash).with(@name).returns(@entry)
+ @searcher.stubs(:name2hash).with('parent').returns(@parent)
+ @searcher.stubs(:name2hash).with('parent_parent').returns(@parent_parent)
- @node.stubs(:parameters=)
- @node.expects(:environment=).with("parent")
- @searcher.find(@request)
- end
+ @searcher.stubs(:parent_attribute).returns(:parent)
+ end
- it "should prefer the node's environment to the parent's" do
- @entry.stubs(:to_hash).returns("environment" => %w{child})
- @entry.stubs(:vals).with(:parent).returns(%w{parent})
+ it "should search for the parent node" do
+ @entry[:parent] = "parent"
- @parent.stubs(:to_hash).returns("environment" => ["parent"])
- @parent.stubs(:vals).with(:parent).returns(nil)
+ @searcher.expects(:name2hash).with(@name).returns @entry
+ @searcher.expects(:name2hash).with('parent').returns @parent
- @node.stubs(:parameters=)
- @node.expects(:environment=).with("child")
- @searcher.find(@request)
- end
+ @searcher.find(@request)
+ end
- it "should recursively look up parent information" do
- @entry.stubs(:to_hash).returns("one" => "two")
- @entry.stubs(:vals).with(:parent).returns(%w{parent})
+ it "should fail if the parent cannot be found" do
+ @entry[:parent] = "parent"
- @parent.stubs(:to_hash).returns("three" => "four")
- @parent.stubs(:vals).with(:parent).returns(['parent_parent'])
+ @searcher.expects(:name2hash).with('parent').returns nil
- @parent_parent.stubs(:to_hash).returns("five" => "six")
- @parent_parent.stubs(:vals).with(:parent).returns(nil)
- @parent_parent.stubs(:vals).with(:parent).returns(nil)
+ proc { @searcher.find(@request) }.should raise_error(Puppet::Error)
+ end
- @node.expects(:parameters=).with("one" => "two", "three" => "four", "five" => "six")
- @searcher.find(@request)
- end
+ it "should add any parent classes to the node's classes" do
+ @entry[:parent] = "parent"
+ @entry[:classes] = %w{a b}
- it "should not allow loops in parent declarations" do
- @entry.stubs(:to_hash).returns("one" => "two")
- @entry.stubs(:vals).with(:parent).returns(%w{parent})
+ @parent[:classes] = %w{c d}
- @parent.stubs(:to_hash).returns("three" => "four")
- @parent.stubs(:vals).with(:parent).returns([@name])
- proc { @searcher.find(@request) }.should raise_error(ArgumentError)
- end
- end
+ @node.expects(:classes=).with(%w{a b c d})
+ @searcher.find(@request)
+ end
- describe "and a puppet variable is specified" do
- before do
- @searcher.stubs(:stacked_attributes).returns(['puppetvar'])
- end
+ it "should add any parent parameters to the node's parameters" do
+ @entry[:parent] = "parent"
+ @entry[:parameters]["one"] = "two"
- it "should add the variable to the node parameters" do
- @entry.stubs(:vals).with("puppetvar").returns(%w{one=two})
- @entry.stubs(:to_hash).returns({})
- @node.expects(:parameters=).with("one" => "two")
- @searcher.find(@request)
- end
+ @parent[:parameters]["three"] = "four"
- it "should not overwrite node parameters specified as ldap object attribute" do
- @entry.stubs(:vals).with("puppetvar").returns(%w{one=two})
- @entry.stubs(:to_hash).returns("one" => "three")
- @node.expects(:parameters=).with("one" => "three")
- @searcher.find(@request)
- end
+ @node.expects(:parameters=).with("one" => "two", "three" => "four")
+ @searcher.find(@request)
+ end
- it "should set entries without an equal sign to nil" do
- @entry.stubs(:vals).with("puppetvar").returns(%w{one})
- @entry.stubs(:to_hash).returns({})
- @node.expects(:parameters=).with("one" => nil)
- @searcher.find(@request)
- end
+ it "should prefer node parameters over parent parameters" do
+ @entry[:parent] = "parent"
+ @entry[:parameters]["one"] = "two"
- it "should ignore empty entries" do
- @entry.stubs(:vals).with("puppetvar").returns(%w{})
- @entry.stubs(:to_hash).returns({})
- @searcher.find(@request)
- end
- end
- describe "and a puppet variable as well as a parent node are specified" do
- before do
- @parent = mock 'parent'
+ @parent[:parameters]["one"] = "three"
- @searcher.meta_def(:search_filter) do |name|
- return name
+ @node.expects(:parameters=).with("one" => "two")
+ @searcher.find(@request)
end
- @connection.stubs(:search).with { |*args| args[2] == @name }.yields(@entry)
- @connection.stubs(:search).with { |*args| args[2] == 'parent' }.yields(@parent)
- @searcher.stubs(:stacked_attributes).returns(['puppetvar'])
- @searcher.stubs(:parent_attribute).returns(:parent)
- end
+ it "should use the parent's environment if the node has none" do
+ @entry[:parent] = "parent"
- it "should add parent node variables to the child node parameters" do
- @parent.stubs(:to_hash).returns({})
- @parent.stubs(:vals).with("puppetvar").returns(%w{one=two})
- @parent.stubs(:vals).with(:parent).returns(nil)
+ @parent[:environment] = "parent"
- @entry.stubs(:to_hash).returns({})
- @entry.stubs(:vals).with("puppetvar").returns(%w{})
- @entry.stubs(:vals).with(:parent).returns(%w{parent})
+ @node.stubs(:parameters=)
+ @node.expects(:environment=).with("parent")
+ @searcher.find(@request)
+ end
- @node.expects(:parameters=).with("one" => "two")
+ it "should prefer the node's environment to the parent's" do
+ @entry[:parent] = "parent"
+ @entry[:environment] = "child"
- @searcher.find(@request)
- end
+ @parent[:environment] = "parent"
- it "should overwrite parent node variables with child node parameters" do
- @parent.stubs(:to_hash).returns({})
- @parent.stubs(:vals).with("puppetvar").returns(%w{one=two})
- @parent.stubs(:vals).with(:parent).returns(nil)
+ @node.stubs(:parameters=)
+ @node.expects(:environment=).with("child")
+ @searcher.find(@request)
+ end
- @entry.stubs(:to_hash).returns({})
- @entry.stubs(:vals).with("puppetvar").returns(%w{one=three})
- @entry.stubs(:vals).with(:parent).returns(%w{parent})
+ it "should recursively look up parent information" do
+ @entry[:parent] = "parent"
+ @entry[:parameters]["one"] = "two"
- @node.expects(:parameters=).with("one" => "three")
+ @parent[:parent] = "parent_parent"
+ @parent[:parameters]["three"] = "four"
- @searcher.find(@request)
+ @parent_parent[:parameters]["five"] = "six"
+
+ @node.expects(:parameters=).with("one" => "two", "three" => "four", "five" => "six")
+ @searcher.find(@request)
+ end
+
+ it "should not allow loops in parent declarations" do
+ @entry[:parent] = "parent"
+ @parent[:parent] = @name
+ proc { @searcher.find(@request) }.should raise_error(ArgumentError)
+ end
end
+ end
+ end
- it "should not overwrite parent node parameters specified as ldap object attribute" do
- @parent.stubs(:to_hash).returns("one" => "three")
- @parent.stubs(:vals).with("puppetvar").returns(%w{})
- @parent.stubs(:vals).with(:parent).returns(nil)
+ describe "when searching for multiple nodes" do
+ before :each do
+ @searcher = Puppet::Node::Ldap.new
+ @request = stub 'request', :key => @name
- @entry.stubs(:vals).with("puppetvar").returns(%w{one=two})
- @entry.stubs(:to_hash).returns({})
- @entry.stubs(:vals).with(:parent).returns(%w{parent})
+ Puppet::Node::Facts.stubs(:terminus_class).returns :yaml
+ end
- @node.expects(:parameters=).with("one" => "three")
+ it "should find all nodes if no arguments are provided" do
+ @searcher.expects(:ldapsearch).with("(objectclass=puppetClient)")
+ # LAK:NOTE The search method requires an essentially bogus key. It's
+ # an API problem that I don't really know how to fix.
+ @searcher.search "foo"
+ end
- @searcher.find(@request)
+ describe "and a class is specified" do
+ it "should find all nodes that are members of that class" do
+ @searcher.expects(:ldapsearch).with("(&(objectclass=puppetClient)(puppetclass=one))")
+ @searcher.search "foo", :class => "one"
+ end
+ end
+
+ describe "multiple classes are specified" do
+ it "should find all nodes that are members of all classes" do
+ @searcher.expects(:ldapsearch).with("(&(objectclass=puppetClient)(puppetclass=one)(puppetclass=two))")
+ @searcher.search "foo", :class => ["one", "two"]
end
+ end
+
+ it "should process each found entry" do
+ # .yields can't be used to yield multiple values :/
+ @searcher.expects(:ldapsearch).yields("one")
+ @searcher.expects(:entry2hash).with("one").returns(:name => "foo")
+ @searcher.search "foo"
+ end
+ it "should return a node for each processed entry" do
+ @searcher.expects(:ldapsearch).yields("one")
+ @searcher.expects(:entry2hash).with("one").returns(:name => "foo")
+ result = @searcher.search("foo")
+ result[0].should be_instance_of(Puppet::Node)
+ result[0].name.should == "foo"
end
end
end