summaryrefslogtreecommitdiffstats
path: root/lib/puppet/node_source
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2007-08-14 00:09:49 -0500
committerLuke Kanies <luke@madstop.com>2007-08-14 00:09:49 -0500
commitaab419b8c1ad84e51c6f58839290bbe5d1e7b28b (patch)
tree2447b704e0b601ffe10562d9eb83e6c9280366ba /lib/puppet/node_source
parentab42534ae243c24c8c702e38195a954ab52eaed9 (diff)
downloadpuppet-aab419b8c1ad84e51c6f58839290bbe5d1e7b28b.tar.gz
puppet-aab419b8c1ad84e51c6f58839290bbe5d1e7b28b.tar.xz
puppet-aab419b8c1ad84e51c6f58839290bbe5d1e7b28b.zip
An intermediate commit in the work towards adding multi-environment support.
This has required splitting the interpreter up considerably, which is much cleaner but is a large project. There is now a 'nodes' handler, but it is currently non-functional, although all the support structure is there. It just needs to have the individual methods fleshed out, and it needs to be connected to the 'facts' handler.
Diffstat (limited to 'lib/puppet/node_source')
-rw-r--r--lib/puppet/node_source/external.rb51
-rw-r--r--lib/puppet/node_source/ldap.rb118
2 files changed, 169 insertions, 0 deletions
diff --git a/lib/puppet/node_source/external.rb b/lib/puppet/node_source/external.rb
new file mode 100644
index 000000000..4af68d8ae
--- /dev/null
+++ b/lib/puppet/node_source/external.rb
@@ -0,0 +1,51 @@
+Puppet::Network::Handler::Node.newnode_source(:external) do
+ desc "Call an external program to get node information."
+
+ include Puppet::Util
+ # Look for external node definitions.
+ def nodesearch(name)
+ return nil unless Puppet[:external_nodes] != "none"
+
+ # This is a very cheap way to do this, since it will break on
+ # commands that have spaces in the arguments. But it's good
+ # enough for most cases.
+ external_node_command = Puppet[:external_nodes].split
+ external_node_command << name
+ begin
+ output = Puppet::Util.execute(external_node_command)
+ rescue Puppet::ExecutionFailure => detail
+ if $?.exitstatus == 1
+ return nil
+ else
+ Puppet.err "Could not retrieve external node information for %s: %s" % [name, detail]
+ end
+ return nil
+ end
+
+ if output =~ /\A\s*\Z/ # all whitespace
+ Puppet.debug "Empty response for %s from external node source" % name
+ return nil
+ end
+
+ begin
+ result = YAML.load(output).inject({}) { |hash, data| hash[symbolize(data[0])] = data[1]; hash }
+ rescue => detail
+ raise Puppet::Error, "Could not load external node results for %s: %s" % [name, detail]
+ end
+
+ node = Puppet::Network::Handler::Node::SimpleNode.new(:name => name)
+ set = false
+ [:parameters, :classes].each do |param|
+ if value = result[param]
+ node.send(param.to_s + "=", value)
+ set = true
+ end
+ end
+
+ if set
+ return node
+ else
+ return nil
+ end
+ end
+end
diff --git a/lib/puppet/node_source/ldap.rb b/lib/puppet/node_source/ldap.rb
new file mode 100644
index 000000000..6825f2b68
--- /dev/null
+++ b/lib/puppet/node_source/ldap.rb
@@ -0,0 +1,118 @@
+Puppet::Network::Handler::Node.newnode_source(:ldap) do
+ desc "Search in LDAP for node configuration information."
+
+ # Find the ldap node, return the class list and parent node specially,
+ # and everything else in a parameter hash.
+ def ldapsearch(node)
+ unless defined? @ldap and @ldap
+ setup_ldap()
+ unless @ldap
+ Puppet.info "Skipping ldap source; no ldap connection"
+ return nil
+ end
+ end
+
+ filter = Puppet[:ldapstring]
+ classattrs = Puppet[:ldapclassattrs].split("\s*,\s*")
+ if Puppet[:ldapattrs] == "all"
+ # A nil value here causes all attributes to be returned.
+ search_attrs = nil
+ else
+ search_attrs = classattrs + Puppet[:ldapattrs].split("\s*,\s*")
+ end
+ pattr = nil
+ if pattr = Puppet[:ldapparentattr]
+ if pattr == ""
+ pattr = nil
+ else
+ search_attrs << pattr unless search_attrs.nil?
+ end
+ end
+
+ if filter =~ /%s/
+ filter = filter.gsub(/%s/, node)
+ end
+
+ parent = nil
+ classes = []
+ parameters = nil
+
+ found = false
+ count = 0
+
+ begin
+ # We're always doing a sub here; oh well.
+ @ldap.search(Puppet[:ldapbase], 2, filter, search_attrs) do |entry|
+ found = true
+ if pattr
+ if values = entry.vals(pattr)
+ if values.length > 1
+ raise Puppet::Error,
+ "Node %s has more than one parent: %s" %
+ [node, values.inspect]
+ end
+ unless values.empty?
+ parent = values.shift
+ end
+ end
+ end
+
+ classattrs.each { |attr|
+ if values = entry.vals(attr)
+ values.each do |v| classes << v end
+ end
+ }
+
+ 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
+ end
+ rescue => detail
+ if count == 0
+ # Try reconnecting to ldap
+ @ldap = nil
+ setup_ldap()
+ retry
+ else
+ raise Puppet::Error, "LDAP Search failed: %s" % detail
+ end
+ end
+
+ classes.flatten!
+
+ if classes.empty?
+ classes = nil
+ end
+
+ if parent or classes or parameters
+ return parent, classes, parameters
+ else
+ return nil
+ end
+ end
+
+ # Look for our node in ldap.
+ def nodesearch(node)
+ unless ary = ldapsearch(node)
+ return nil
+ end
+ parent, classes, parameters = ary
+
+ while parent
+ parent, tmpclasses, tmpparams = ldapsearch(parent)
+ classes += tmpclasses if tmpclasses
+ tmpparams.each do |param, value|
+ # Specifically test for whether it's set, so false values are handled
+ # correctly.
+ parameters[param] = value unless parameters.include?(param)
+ end
+ end
+
+ return Puppet::Network::Handler::Node::SimpleNode.new(:name => node, :classes => classes, :source => "ldap", :parameters => parameters)
+ end
+end