class Node::Ldap

Public Instance Methods

class_attributes() click to toggle source

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
entry2hash(entry, fqdn = false) click to toggle source

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
find(request) click to toggle source

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
name2hash(name) click to toggle source

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
parent_attribute() click to toggle source

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
search_attributes() click to toggle source

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
search_filter(name) click to toggle source

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
stacked_attributes(dummy_argument=:work_arround_for_ruby_GC_bug) click to toggle source

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

Private Instance Methods

add_to_node(node, information) click to toggle source

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(value) click to toggle source

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
convert_parameters(parameters) click to toggle source
# 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_and_merge_parent(parent, information) click to toggle source

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
get_classes_from_entry(entry) click to toggle source
# 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
get_parameters_from_entry(entry) click to toggle source
# 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
get_parent_from_entry(entry) click to toggle source
# 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
get_stacked_values_from_entry(entry) click to toggle source
# 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
info2node(name, info) click to toggle source

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
merge_parent(info) click to toggle source
# 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