The attributes that Puppet class information is stored in.
# File lib/puppet/indirector/node/ldap.rb, line 11 def class_attributes # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] x = Puppet[:ldapclassattrs].split(/\s*,\s*/) end
Convert the found entry into a simple hash.
# File lib/puppet/indirector/node/ldap.rb, line 84 def entry2hash(entry, fqdn = false) result = {} cn = entry.dn[ /cn\s*=\s*([^,\s]+)/,1] dcs = entry.dn.scan(/dc\s*=\s*([^,\s]+)/) result[:name] = fqdn ? ([cn]+dcs).join('.') : cn result[:parent] = get_parent_from_entry(entry) if parent_attribute result[:classes] = get_classes_from_entry(entry) result[:stacked] = get_stacked_values_from_entry(entry) result[:parameters] = get_parameters_from_entry(entry) result[:environment] = result[:parameters]["environment"] if result[:parameters]["environment"] result[:stacked_parameters] = {} if result[:stacked] result[:stacked].each do |value| param = value.split('=', 2) result[:stacked_parameters][param[0]] = param[1] end end if result[:stacked_parameters] result[:stacked_parameters].each do |param, value| result[:parameters][param] = value unless result[:parameters].include?(param) end end result[:parameters] = convert_parameters(result[:parameters]) result end
Look for our node in ldap.
# File lib/puppet/indirector/node/ldap.rb, line 29 def find(request) names = [request.key] names << request.key.sub(/\..+/, '') if request.key.include?(".") # we assume it's an fqdn names << "default" node = nil names.each do |name| next unless info = name2hash(name) merge_parent(info) if info[:parent] info[:environment] ||= request.environment.to_s node = info2node(request.key, info) break end node end
Separate this out so it’s relatively atomic. It’s tempting to call process instead of name2hash() here, but it ends up being difficult to test because all exceptions get caught by ldapsearch. LAK:NOTE Unfortunately, the ldap support is too stupid to throw anything but LDAP::ResultError, even on bad connections, so we are rough handed with our error handling.
# File lib/puppet/indirector/node/ldap.rb, line 22 def name2hash(name) info = nil ldapsearch(search_filter(name)) { |entry| info = entry2hash(entry) } info end
The parent attribute, if we have one.
# File lib/puppet/indirector/node/ldap.rb, line 69 def parent_attribute if pattr = Puppet[:ldapparentattr] and ! pattr.empty? pattr else nil end end
Find more than one node. LAK:NOTE This is a bit of a clumsy API, because the ‘search’ method currently requires a key. It seems appropriate in some cases but not others, and I don’t really know how to get rid of it as a requirement but allow it when desired.
# File lib/puppet/indirector/node/ldap.rb, line 50 def search(request) if classes = request.options[:class] classes = [classes] unless classes.is_a?(Array) filter = "(&(objectclass=puppetClient)(puppetclass=" + classes.join(")(puppetclass=") + "))" else filter = "(objectclass=puppetClient)" end infos = [] ldapsearch(filter) { |entry| infos << entry2hash(entry, request.options[:fqdn]) } return infos.collect do |info| merge_parent(info) if info[:parent] info[:environment] ||= request.environment.to_s info2node(info[:name], info) end end
Default to all attributes.
# File lib/puppet/indirector/node/ldap.rb, line 118 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.
# File lib/puppet/indirector/node/ldap.rb, line 134 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
The attributes that Puppet will stack as array over the full hierarchy.
# File lib/puppet/indirector/node/ldap.rb, line 79 def stacked_attributes(dummy_argument=:work_arround_for_ruby_GC_bug) Puppet[:ldapstackedattrs].split(/\s*,\s*/) end
Add our hash of ldap information to the node instance.
# File lib/puppet/indirector/node/ldap.rb, line 148 def add_to_node(node, information) 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] end
Convert any values if necessary.
# File lib/puppet/indirector/node/ldap.rb, line 167 def convert(value) case value when Integer, Fixnum, Bignum; value when "true"; true when "false"; false else value end end
# File lib/puppet/indirector/node/ldap.rb, line 154 def convert_parameters(parameters) result = {} parameters.each do |param, value| if value.is_a?(Array) result[param] = value.collect { |v| convert(v) } else result[param] = convert(value) end end result end
Find information for our parent and merge it into the current info.
# File lib/puppet/indirector/node/ldap.rb, line 178 def find_and_merge_parent(parent, information) parent_info = name2hash(parent) || raise(Puppet::Error.new("Could not find parent node '#{parent}'")) 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 information[:environment] ||= parent_info[:environment] parent_info[:parent] end
# File lib/puppet/indirector/node/ldap.rb, line 215 def get_classes_from_entry(entry) result = class_attributes.inject([]) do |array, attr| if values = entry.vals(attr) values.each do |v| array << v end end array end result.uniq end
# File lib/puppet/indirector/node/ldap.rb, line 225 def get_parameters_from_entry(entry) stacked_params = stacked_attributes entry.to_hash.inject({}) do |hash, ary| unless stacked_params.include?(ary[0]) # don't add our stacked parameters to the main param list if ary[1].length == 1 hash[ary[0]] = ary[1].shift else hash[ary[0]] = ary[1] end end hash end end
# File lib/puppet/indirector/node/ldap.rb, line 239 def get_parent_from_entry(entry) pattr = parent_attribute return nil unless values = entry.vals(pattr) if values.length > 1 raise Puppet::Error, "Node entry #{entry.dn} specifies more than one parent: #{values.inspect}" end return(values.empty? ? nil : values.shift) end
# File lib/puppet/indirector/node/ldap.rb, line 251 def get_stacked_values_from_entry(entry) stacked_attributes.inject([]) do |result, attr| if values = entry.vals(attr) result += values end result end end
Take a name and a hash, and return a node instance.
# File lib/puppet/indirector/node/ldap.rb, line 190 def info2node(name, info) node = Puppet::Node.new(name) add_to_node(node, info) node.fact_merge node end
# File lib/puppet/indirector/node/ldap.rb, line 200 def merge_parent(info) parent_info = nil parent = info[:parent] # Preload the parent array with the node name. parents = [info[:name]] while parent raise ArgumentError, "Found loop in LDAP node parents; #{parent} appears twice" if parents.include?(parent) parents << parent parent = find_and_merge_parent(parent, info) end info end