summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG6
-rw-r--r--lib/puppet/indirector/catalog/compiler.rb2
-rw-r--r--lib/puppet/indirector/ldap.rb12
-rw-r--r--lib/puppet/indirector/node/ldap.rb122
-rw-r--r--lib/puppet/node.rb118
-rwxr-xr-xspec/unit/indirector/catalog/compiler.rb22
-rwxr-xr-xspec/unit/indirector/node/ldap.rb22
-rwxr-xr-xspec/unit/node.rb76
8 files changed, 164 insertions, 216 deletions
diff --git a/CHANGELOG b/CHANGELOG
index d51e3f0b6..66c1e996b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+ Removed support for the 'node_name' setting in LDAP and external node lookups.
+ Also removed support for 'default' nodes in external nodes.
+ LDAP nodes now use the certificate name, the short name, and 'default',
+ but external nodes just use the certificate name and any custom terminus
+ types will use just the certificate name.
+
Adding a ResourceTemplate class for using templates directly
within resources (i.e., client-side templates). This would really
only be used for composite resources that pass the results of the
diff --git a/lib/puppet/indirector/catalog/compiler.rb b/lib/puppet/indirector/catalog/compiler.rb
index 2b5e8d912..455a92cc7 100644
--- a/lib/puppet/indirector/catalog/compiler.rb
+++ b/lib/puppet/indirector/catalog/compiler.rb
@@ -89,7 +89,7 @@ class Puppet::Node::Catalog::Compiler < Puppet::Indirector::Code
# key = client
#end
- return nil unless node = Puppet::Node.find_by_any_name(key)
+ return nil unless node = Puppet::Node.find(key)
# Add any external data to the node.
add_node_data(node)
diff --git a/lib/puppet/indirector/ldap.rb b/lib/puppet/indirector/ldap.rb
index 07ad38933..695d38a95 100644
--- a/lib/puppet/indirector/ldap.rb
+++ b/lib/puppet/indirector/ldap.rb
@@ -1,14 +1,16 @@
require 'puppet/indirector/terminus'
class Puppet::Indirector::Ldap < Puppet::Indirector::Terminus
- # Perform our ldap search and process the result.
- def find(request)
+ # We split this apart so it's easy to call multiple times with different names.
+ def entry2hash(name)
# We have to use 'yield' here because the LDAP::Entry objects
# get destroyed outside the scope of the search, strangely.
- ldapsearch(request.key) { |entry| return process(request.key, entry) }
+ ldapsearch(name) { |entry| return process(name, entry) }
+ end
- # Return nil if we haven't found something.
- return nil
+ # Perform our ldap search and process the result.
+ def find(request)
+ return entry2hash(request.key) || nil
end
# Process the found entry. We assume that we don't just want the
diff --git a/lib/puppet/indirector/node/ldap.rb b/lib/puppet/indirector/node/ldap.rb
index bc58908fd..4ed053eff 100644
--- a/lib/puppet/indirector/node/ldap.rb
+++ b/lib/puppet/indirector/node/ldap.rb
@@ -3,7 +3,9 @@ require 'puppet/indirector/ldap'
class Puppet::Node::Ldap < Puppet::Indirector::Ldap
desc "Search in LDAP for node configuration information. See
- the `LdapNodes`:trac: page for more information."
+ the `LdapNodes`:trac: page for more information. This will first
+ search for whatever the certificate name is, then (if that name
+ contains a '.') for the short name, then 'default'."
# The attributes that Puppet class information is stored in.
def class_attributes
@@ -13,57 +15,23 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap
# Look for our node in ldap.
def find(request)
- return nil unless information = super
-
- name = request.key
-
- node = Puppet::Node.new(name)
-
- information[:stacked_parameters] = {}
-
- parent_info = nil
- parent = information[:parent]
- parents = [name]
- while parent
- if parents.include?(parent)
- raise ArgumentError, "Found loop in LDAP node parents; %s appears twice" % parent
- end
- parents << parent
-
- ldapsearch(parent) { |entry| parent_info = process(parent, entry) }
-
- unless parent_info
- raise Puppet::Error.new("Could not find parent node '%s'" % parent)
- end
- information[:classes] += parent_info[:classes]
- parent_info[:stacked].each do |value|
- param = value.split('=', 2)
- information[:stacked_parameters][param[0]] = param[1]
- end
- parent_info[:parameters].each do |param, value|
- # Specifically test for whether it's set, so false values are handled
- # correctly.
- information[:parameters][param] = value unless information[:parameters].include?(param)
- end
-
- information[:environment] ||= parent_info[:environment]
-
- parent = parent_info[:parent]
+ names = [request.key]
+ if request.key.include?(".") # we assume it's an fqdn
+ names << request.key.sub(/\..+/, '')
end
+ names << "default"
- information[:stacked].each do |value|
- param = value.split('=', 2)
- information[:stacked_parameters][param[0]] = param[1]
+ information = nil
+ names.each do |name|
+ break if information = entry2hash(name)
end
+ return nil unless information
- information[:stacked_parameters].each do |param, value|
- information[:parameters][param] = value unless information[:parameters].include?(param)
- end
+ name = request.key
- node.classes = information[:classes].uniq unless information[:classes].empty?
- node.parameters = information[:parameters] unless information[:parameters].empty?
- node.environment = information[:environment] if information[:environment]
- node.fact_merge
+ node = Puppet::Node.new(name)
+
+ add_to_node(node, information)
return node
end
@@ -155,4 +123,64 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap
end
filter
end
+
+ private
+
+ # Add our hash of ldap information to the node instance.
+ def add_to_node(node, information)
+ information[:stacked_parameters] = {}
+
+ parent_info = nil
+ parent = information[:parent]
+ parents = [node.name]
+ while parent
+ if parents.include?(parent)
+ raise ArgumentError, "Found loop in LDAP node parents; %s appears twice" % parent
+ end
+ parents << parent
+ parent = find_and_merge_parent(parent, information)
+ end
+
+ if information[:stacked]
+ information[:stacked].each do |value|
+ param = value.split('=', 2)
+ information[:stacked_parameters][param[0]] = param[1]
+ end
+ end
+
+ if information[:stacked_parameters]
+ information[:stacked_parameters].each do |param, value|
+ information[:parameters][param] = value unless information[:parameters].include?(param)
+ end
+ end
+
+ node.classes = information[:classes].uniq unless information[:classes].nil? or information[:classes].empty?
+ node.parameters = information[:parameters] unless information[:parameters].nil? or information[:parameters].empty?
+ node.environment = information[:environment] if information[:environment]
+ node.fact_merge
+ end
+
+ # Find information for our parent and merge it into the current info.
+ def find_and_merge_parent(parent, information)
+ parent_info = nil
+ ldapsearch(parent) { |entry| parent_info = process(parent, entry) }
+
+ unless parent_info
+ raise Puppet::Error.new("Could not find parent node '%s'" % parent)
+ end
+ information[:classes] += parent_info[:classes]
+ parent_info[:stacked].each do |value|
+ param = value.split('=', 2)
+ information[:stacked_parameters][param[0]] = param[1]
+ end
+ parent_info[:parameters].each do |param, value|
+ # Specifically test for whether it's set, so false values are handled
+ # correctly.
+ information[:parameters][param] = value unless information[:parameters].include?(param)
+ end
+
+ information[:environment] ||= parent_info[:environment]
+
+ parent_info[:parent]
+ end
end
diff --git a/lib/puppet/node.rb b/lib/puppet/node.rb
index 576e2265d..14d0f6ac7 100644
--- a/lib/puppet/node.rb
+++ b/lib/puppet/node.rb
@@ -13,88 +13,7 @@ class Puppet::Node
indirects :node, :terminus_setting => :node_terminus, :doc => "Where to find node information.
A node is composed of its name, its facts, and its environment."
- # Retrieve a node from the node source, with some additional munging
- # thrown in for kicks.
- def self.find_by_any_name(key)
- return nil unless key
-
- node = nil
- names = node_names(key)
- names.each do |name|
- name = name.to_s if name.is_a?(Symbol)
- break if node = find(name)
- end
-
- # If they made it this far, we haven't found anything, so look for a
- # default node.
- unless node or names.include?("default")
- if node = find("default")
- Puppet.notice "Using default node for %s" % key
- end
- end
-
- return nil unless node
-
- node.names = names
-
- # This is critical, because it forces our node's name to always
- # be the key, which is nearly always the node's certificate.
- # This is how the node instance is linked to the Facts instance,
- # so it quite matters.
- node.name = key
- return node
- end
-
- private
-
- # Look up the node facts so we can generate the node names to use.
- def self.node_facts(key)
- if facts = Puppet::Node::Facts.find(key)
- facts.values
- else
- {}
- end
- end
-
- # Calculate the list of node names we should use for looking
- # up our node.
- def self.node_names(key, facts = nil)
- facts ||= node_facts(key)
- names = []
-
- # First, get the fqdn
- unless fqdn = facts["fqdn"]
- if domain = facts["domain"]
- fqdn = facts["hostname"] + "." + facts["domain"]
- end
- end
-
- # Now that we (might) have the fqdn, add each piece to the name
- # list to search, in order of longest to shortest.
- if fqdn
- list = fqdn.split(".")
- tmp = []
- list.each_with_index do |short, i|
- tmp << list[0..i].join(".")
- end
- names += tmp.reverse
- end
-
- # And make sure the key is first, since that's the most
- # likely usage.
- # The key is usually the Certificate CN, but it can be
- # set to the 'facter' hostname instead.
- if Puppet[:node_name] == 'cert'
- names.unshift key
- else
- names.unshift facts["hostname"]
- end
- names.uniq
- end
-
- public
-
- attr_accessor :name, :classes, :parameters, :source, :ipaddress, :names
+ attr_accessor :name, :classes, :parameters, :source, :ipaddress
attr_reader :time
# Set the environment, making sure that it's valid.
@@ -165,4 +84,39 @@ class Puppet::Node
@parameters[name] = value unless @parameters.include?(name)
end
end
+
+ # Calculate the list of names we might use for looking
+ # up our node. This is only used for AST nodes.
+ def names
+ names = []
+
+ # First, get the fqdn
+ unless fqdn = parameters["fqdn"]
+ if domain = parameters["domain"]
+ fqdn = parameters["hostname"] + "." + parameters["domain"]
+ end
+ end
+
+ # Now that we (might) have the fqdn, add each piece to the name
+ # list to search, in order of longest to shortest.
+ if fqdn
+ list = fqdn.split(".")
+ tmp = []
+ list.each_with_index do |short, i|
+ tmp << list[0..i].join(".")
+ end
+ names += tmp.reverse
+ end
+
+ # And make sure the node name is first, since that's the most
+ # likely usage.
+ # The name is usually the Certificate CN, but it can be
+ # set to the 'facter' hostname instead.
+ if Puppet[:node_name] == 'cert'
+ names.unshift name
+ else
+ names.unshift parameters["hostname"]
+ end
+ names.uniq
+ end
end
diff --git a/spec/unit/indirector/catalog/compiler.rb b/spec/unit/indirector/catalog/compiler.rb
index 083a9ced5..cf7186a5a 100755
--- a/spec/unit/indirector/catalog/compiler.rb
+++ b/spec/unit/indirector/catalog/compiler.rb
@@ -23,8 +23,8 @@ describe Puppet::Node::Catalog::Compiler do
node1 = stub 'node1', :merge => nil
node2 = stub 'node2', :merge => nil
compiler.stubs(:compile)
- Puppet::Node.stubs(:find_by_any_name).with('node1').returns(node1)
- Puppet::Node.stubs(:find_by_any_name).with('node2').returns(node2)
+ Puppet::Node.stubs(:find).with('node1').returns(node1)
+ Puppet::Node.stubs(:find).with('node2').returns(node2)
compiler.find(stub('request', :key => 'node1', :options => {}))
compiler.find(stub('node2request', :key => 'node2', :options => {}))
@@ -69,7 +69,7 @@ describe Puppet::Node::Catalog::Compiler, " when finding nodes" do
it "should look node information up via the Node class with the provided key" do
@node.stubs :merge
- Puppet::Node.expects(:find_by_any_name).with(@name).returns(@node)
+ Puppet::Node.expects(:find).with(@name).returns(@node)
@compiler.find(@request)
end
end
@@ -77,7 +77,6 @@ end
describe Puppet::Node::Catalog::Compiler, " after finding nodes" do
before do
Puppet.expects(:version).returns(1)
- Puppet.settings.stubs(:value).with(:node_name).returns("cert")
Facter.expects(:value).with('fqdn').returns("my.server.com")
Facter.expects(:value).with('ipaddress').returns("my.ip.address")
@compiler = Puppet::Node::Catalog::Compiler.new
@@ -85,7 +84,7 @@ describe Puppet::Node::Catalog::Compiler, " after finding nodes" do
@node = mock 'node'
@request = stub 'request', :key => @name, :options => {}
@compiler.stubs(:compile)
- Puppet::Node.stubs(:find_by_any_name).with(@name).returns(@node)
+ Puppet::Node.stubs(:find).with(@name).returns(@node)
end
it "should add the server's Puppet version to the node's parameters as 'serverversion'" do
@@ -102,13 +101,6 @@ describe Puppet::Node::Catalog::Compiler, " after finding nodes" do
@node.expects(:merge).with { |args| args["serverip"] == "my.ip.address" }
@compiler.find(@request)
end
-
- # LAK:TODO This is going to be difficult, because this whole process is so
- # far removed from the actual connection that the certificate information
- # will be quite hard to come by, dum by, gum by.
- it "should search for the name using the client certificate's DN if the :node_name setting is set to 'cert'" do
- pending "Probably will end up in the REST work"
- end
end
describe Puppet::Node::Catalog::Compiler, " when creating catalogs" do
@@ -122,18 +114,18 @@ describe Puppet::Node::Catalog::Compiler, " when creating catalogs" do
@node = Puppet::Node.new @name
@node.stubs(:merge)
@request = stub 'request', :key => @name, :options => {}
- Puppet::Node.stubs(:find_by_any_name).with(@name).returns(@node)
+ Puppet::Node.stubs(:find).with(@name).returns(@node)
end
it "should directly use provided nodes" do
- Puppet::Node.expects(:find_by_any_name).never
+ Puppet::Node.expects(:find).never
@compiler.interpreter.expects(:compile).with(@node)
@request.stubs(:options).returns(:node => @node)
@compiler.find(@request)
end
it "should fail if no node is passed and none can be found" do
- Puppet::Node.stubs(:find_by_any_name).with(@name).returns(nil)
+ Puppet::Node.stubs(:find).with(@name).returns(nil)
proc { @compiler.find(@request) }.should raise_error(ArgumentError)
end
diff --git a/spec/unit/indirector/node/ldap.rb b/spec/unit/indirector/node/ldap.rb
index 878039c7c..24b2dd759 100755
--- a/spec/unit/indirector/node/ldap.rb
+++ b/spec/unit/indirector/node/ldap.rb
@@ -21,14 +21,32 @@ describe Puppet::Node::Ldap do
@searcher.stubs(:search_base).returns(:yay)
@searcher.stubs(:search_filter).returns(:filter)
- @node = mock 'node'
+ @name = "mynode.domain.com"
+ @node = stub 'node', :name => @name
@node.stubs(:fact_merge)
- @name = "mynode"
Puppet::Node.stubs(:new).with(@name).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)
+ 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)
+ 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
+
it "should return nil if no results are found in ldap" do
@connection.stubs(:search)
@searcher.find(@request).should be_nil
diff --git a/spec/unit/node.rb b/spec/unit/node.rb
index 6603f6b58..c6d2e61bf 100755
--- a/spec/unit/node.rb
+++ b/spec/unit/node.rb
@@ -54,11 +54,6 @@ describe Puppet::Node, "when initializing" do
Puppet.settings.stubs(:value).with(:environments).returns("myenv")
proc { Puppet::Node.new("testing", :environment => "other") }.should raise_error(ArgumentError)
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
@@ -136,42 +131,33 @@ describe Puppet::Node, "when indirecting" do
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
-
describe Puppet::Node, "when generating the list of names to search through" do
before do
- @facts = Puppet::Node::Facts.new("foo", "hostname" => "yay", "domain" => "domain.com")
- @node = Puppet::Node.new("foo")
-
- Puppet::Node.stubs(:node_facts).returns @facts.values
+ @node = Puppet::Node.new("foo.domain.com")
+ @node.parameters = {"hostname" => "yay", "domain" => "domain.com"}
end
it "should return an array of names" do
- Puppet::Node.node_names("foo").should be_instance_of(Array)
+ @node.names.should be_instance_of(Array)
end
it "should have the node's fqdn as the second name" do
- Puppet::Node.node_names("foo.domain.com")[1].should == "yay.domain.com"
+ @node.names[1].should == "yay.domain.com"
end
it "should set the fqdn to the node's 'fqdn' fact if it is available" do
- @facts.values["fqdn"] = "boo.domain.com"
- Puppet::Node.node_names("foo")[1].should == "boo.domain.com"
+ @node.parameters["fqdn"] = "boo.domain.com"
+ @node.names[1].should == "boo.domain.com"
end
it "should set the fqdn to the node's hostname and domain if no fqdn is available" do
- Puppet::Node.node_names("foo")[1].should == "yay.domain.com"
+ @node.names[1].should == "yay.domain.com"
end
it "should contain an entry for each name available by stripping a segment of the fqdn" do
- @facts.values["fqdn"] = "foo.deep.sub.domain.com"
- Puppet::Node.node_names("foo")[2].should == "foo.deep.sub.domain"
- Puppet::Node.node_names("foo")[3].should == "foo.deep.sub"
+ @node.parameters["fqdn"] = "foo.deep.sub.domain.com"
+ @node.names[2].should == "foo.deep.sub.domain"
+ @node.names[3].should == "foo.deep.sub"
end
describe "and :node_name is set to 'cert'" do
@@ -180,7 +166,7 @@ describe Puppet::Node, "when generating the list of names to search through" do
end
it "should use the passed-in key as the first value" do
- Puppet::Node.node_names("foo")[0].should == "foo"
+ @node.names[0].should == "foo.domain.com"
end
end
@@ -190,45 +176,7 @@ describe Puppet::Node, "when generating the list of names to search through" do
end
it "should use the node's 'hostname' fact as the first value" do
- Puppet::Node.node_names("foo")[0].should == "yay"
+ @node.names[0].should == "yay"
end
end
end
-
-describe Puppet::Node, "when searching for nodes" do
- before do
- @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 use the 'node_names' method to get its list of names to search" do
- Puppet::Node.expects(:node_names).with{ |*args| args[0] == "foo" }.returns %w{a b}
- Puppet::Node.stubs(:find)
- Puppet::Node.find_by_any_name("foo")
- end
-
- it "should return the first node found using the generated list of names" do
- Puppet::Node.expects(:node_names).returns %w{a b}
- Puppet::Node.expects(:find).with("a").returns(nil)
- Puppet::Node.expects(:find).with("b").returns(@node)
- Puppet::Node.find_by_any_name("foo").should equal(@node)
- end
-
- it "should attempt to find a default node if no names are found" do
- names = []
- Puppet::Node.stubs(:find).with do |name|
- names << name
- end.returns(nil)
- Puppet::Node.find_by_any_name("foo")
- names[-1].should == "default"
- end
-
- it "should set the node name to the provided key" do
- Puppet::Node.stubs(:node_names).returns %w{a b}
- Puppet::Node.stubs(:find).returns @node
-
- @node.expects(:name=).with("foo")
- Puppet::Node.find_by_any_name("foo")
- end
-end