diff options
-rw-r--r-- | ext/ldap/puppet.schema | 7 | ||||
-rw-r--r-- | lib/puppet/defaults.rb | 4 | ||||
-rw-r--r-- | lib/puppet/indirector/node/ldap.rb | 29 | ||||
-rwxr-xr-x | spec/unit/indirector/node/ldap.rb | 91 |
4 files changed, 130 insertions, 1 deletions
diff --git a/ext/ldap/puppet.schema b/ext/ldap/puppet.schema index d8dc4260d..a7a5f46ff 100644 --- a/ext/ldap/puppet.schema +++ b/ext/ldap/puppet.schema @@ -17,6 +17,11 @@ attributetype ( 1.1.3.11 NAME 'environment' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributetype ( 1.1.3.12 NAME 'puppetvar' + DESC 'A variable setting for puppet' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + objectclass ( 1.1.1.2 NAME 'puppetClient' SUP top AUXILIARY DESC 'Puppet Client objectclass' - MAY ( puppetclass $ parentnode $ environment )) + MAY ( puppetclass $ parentnode $ environment $ puppetvar )) diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index eed1a00f3..df2fb9425 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -622,6 +622,10 @@ module Puppet :ldapclassattrs => ["puppetclass", "The LDAP attributes to use to define Puppet classes. Values should be comma-separated."], + :ldapstackedattrs => ["puppetvar", + "The LDAP attributes that should be stacked to arrays by adding + the values in all hierarchy elements of the tree. Values + should be comma-separated."], :ldapattrs => ["all", "The LDAP attributes to include when querying LDAP for nodes. All returned attributes are set as variables in the top-level scope. diff --git a/lib/puppet/indirector/node/ldap.rb b/lib/puppet/indirector/node/ldap.rb index 6c41c18d4..bc58908fd 100644 --- a/lib/puppet/indirector/node/ldap.rb +++ b/lib/puppet/indirector/node/ldap.rb @@ -19,6 +19,8 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap node = Puppet::Node.new(name) + information[:stacked_parameters] = {} + parent_info = nil parent = information[:parent] parents = [name] @@ -34,6 +36,10 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap 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. @@ -45,6 +51,15 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap parent = parent_info[:parent] end + information[:stacked].each do |value| + param = value.split('=', 2) + information[:stacked_parameters][param[0]] = param[1] + end + + information[:stacked_parameters].each do |param, value| + information[:parameters][param] = value unless information[:parameters].include?(param) + end + node.classes = information[:classes].uniq unless information[:classes].empty? node.parameters = information[:parameters] unless information[:parameters].empty? node.environment = information[:environment] if information[:environment] @@ -62,6 +77,12 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap end end + # The attributes that Puppet will stack as array over the full + # hierarchy. + def stacked_attributes + Puppet[:ldapstackedattrs].split(/\s*,\s*/) + end + # Process the found entry. We assume that we don't just want the # ldap object. def process(name, entry) @@ -85,6 +106,14 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap end } + result[:stacked] = [] + stacked_attributes.each { |attr| + if values = entry.vals(attr) + result[:stacked] = result[:stacked] + values + end + } + + result[:parameters] = entry.to_hash.inject({}) do |hash, ary| if ary[1].length == 1 hash[ary[0]] = ary[1].shift diff --git a/spec/unit/indirector/node/ldap.rb b/spec/unit/indirector/node/ldap.rb index a40698662..878039c7c 100755 --- a/spec/unit/indirector/node/ldap.rb +++ b/spec/unit/indirector/node/ldap.rb @@ -17,6 +17,7 @@ describe Puppet::Node::Ldap do @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) @@ -195,6 +196,96 @@ describe Puppet::Node::Ldap do proc { @searcher.find(@request) }.should raise_error(ArgumentError) end end + + describe "and a puppet variable is specified" do + before do + @searcher.stubs(:stacked_attributes).returns(['puppetvar']) + end + + 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 + + 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 + + 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 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' + + @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) + + @searcher.stubs(:stacked_attributes).returns(['puppetvar']) + @searcher.stubs(:parent_attribute).returns(:parent) + end + + 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) + + @entry.stubs(:to_hash).returns({}) + @entry.stubs(:vals).with("puppetvar").returns(%w{}) + @entry.stubs(:vals).with(:parent).returns(%w{parent}) + + @node.expects(:parameters=).with("one" => "two") + + @searcher.find(@request) + end + + 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) + + @entry.stubs(:to_hash).returns({}) + @entry.stubs(:vals).with("puppetvar").returns(%w{one=three}) + @entry.stubs(:vals).with(:parent).returns(%w{parent}) + + @node.expects(:parameters=).with("one" => "three") + + @searcher.find(@request) + 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) + + @entry.stubs(:vals).with("puppetvar").returns(%w{one=two}) + @entry.stubs(:to_hash).returns({}) + @entry.stubs(:vals).with(:parent).returns(%w{parent}) + + @node.expects(:parameters=).with("one" => "three") + + @searcher.find(@request) + end + + end end end |