1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
require 'puppet/node'
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 attributes that Puppet class information is stored in.
def class_attributes
Puppet[:ldapclassattrs].split(/\s*,\s*/)
end
# Look for our node in ldap.
def find(name)
return nil unless information = super
node = Puppet::Node.new(name)
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[: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
parent = parent_info[:parent]
end
node.classes = information[:classes].uniq unless information[:classes].empty?
node.parameters = information[:parameters] unless information[:parameters].empty?
node.fact_merge
return node
end
# The parent attribute, if we have one.
def parent_attribute
if pattr = Puppet[:ldapparentattr] and ! pattr.empty?
pattr
else
nil
end
end
# Process the found entry. We assume that we don't just want the
# ldap object.
def process(name, entry)
result = {}
if pattr = parent_attribute
if values = entry.vals(pattr)
if values.length > 1
raise Puppet::Error,
"Node %s has more than one parent: %s" % [name, values.inspect]
end
unless values.empty?
result[:parent] = values.shift
end
end
end
result[:classes] = []
class_attributes.each { |attr|
if values = entry.vals(attr)
values.each do |v| result[:classes] << v end
end
}
result[: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
return result
end
# Default to all attributes.
def search_attributes
ldapattrs = Puppet[:ldapattrs]
# results in everything getting returned
return nil if ldapattrs == "all"
search_attrs = class_attributes + ldapattrs.split(/\s*,\s*/)
if pattr = parent_attribute
search_attrs << pattr
end
search_attrs
end
# The ldap search filter to use.
def search_filter(name)
filter = Puppet[:ldapstring]
if filter.include? "%s"
# Don't replace the string in-line, since that would hard-code our node
# info.
filter = filter.gsub('%s', name)
end
filter
end
end
|