diff --git a/lib/puppet/network/handler/master.rb b/lib/puppet/network/handler/master.rb index 3e004046e..dabfaca50 100644 --- a/lib/puppet/network/handler/master.rb +++ b/lib/puppet/network/handler/master.rb @@ -1,133 +1,133 @@ require 'openssl' require 'puppet' require 'puppet/parser/interpreter' require 'puppet/sslcertificates' require 'xmlrpc/server' require 'yaml' class Puppet::Network::Handler class MasterError < Puppet::Error; end class Master < Handler desc "Puppet's configuration interface. Used for all interactions related to generating client configurations." include Puppet::Util attr_accessor :ast attr_reader :ca @interface = XMLRPC::Service::Interface.new("puppetmaster") { |iface| iface.add_method("string getconfig(string)") iface.add_method("int freshness()") } # Tell a client whether there's a fresh config for it def freshness(client = nil, clientip = nil) client ||= Facter.value("hostname") config_handler.version(client, clientip) end def initialize(hash = {}) args = {} if hash[:Local] @local = hash[:Local] else @local = false end args[:Local] = true if hash.include?(:CA) and hash[:CA] @ca = Puppet::SSLCertificates::CA.new() else @ca = nil end Puppet.debug("Creating interpreter") # This is only used by the cfengine module, or if --loadclasses was # specified in +puppet+. if hash.include?(:Classes) args[:Classes] = hash[:Classes] end @config_handler = Puppet::Network::Handler.handler(:configuration).new(args) end # Call our various handlers; this handler is getting deprecated. def getconfig(facts, format = "marshal", client = nil, clientip = nil) facts = decode_facts(facts) client, clientip = clientname(client, clientip, facts) # Pass the facts to the fact handler Puppet::Node::Facts.new(client, facts).save unless local? # And get the configuration from the config handler config = nil benchmark(:notice, "Compiled configuration for %s" % client) do config = config_handler.configuration(client) end return translate(config.extract) end private # Manipulate the client name as appropriate. def clientname(name, ip, facts) # Always use the hostname from Facter. client = facts["hostname"] clientip = facts["ipaddress"] if Puppet[:node_name] == 'cert' if name + client = name facts["fqdn"] = client facts["hostname"], facts["domain"] = client.split('.', 2) - client = name end if ip clientip = ip end end return client, clientip end def config_handler unless defined? @config_handler @config_handler = Puppet::Network::Handler.handler(:config).new :local => local? end @config_handler end # def decode_facts(facts) if @local # we don't need to do anything, since we should already # have raw objects Puppet.debug "Our client is local" else Puppet.debug "Our client is remote" begin facts = YAML.load(CGI.unescape(facts)) rescue => detail raise XMLRPC::FaultException.new( 1, "Could not rebuild facts" ) end end return facts end # Translate our configuration appropriately for sending back to a client. def translate(config) if local? config else CGI.escape(config.to_yaml(:UseBlock => true)) end end end end diff --git a/test/network/handler/master.rb b/test/network/handler/master.rb index 88bfe6b7e..55522237b 100755 --- a/test/network/handler/master.rb +++ b/test/network/handler/master.rb @@ -1,107 +1,111 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../lib/puppettest' require 'puppettest' require 'puppet/network/handler/master' class TestMaster < Test::Unit::TestCase include PuppetTest::ServerTest def teardown super Puppet::Indirector::Indirection.clear_cache end # Make sure that files are reread when they change. def test_filereread # Start with a normal setting Puppet[:filetimeout] = 15 manifest = mktestmanifest() facts = Puppet::Network::Client.master.facts # Store them, so we don't determine frshness based on facts. Puppet::Util::Storage.cache(:configuration)[:facts] = facts file2 = @createdfile + "2" @@tmpfiles << file2 client = master = nil Puppet[:manifest] = manifest assert_nothing_raised() { # this is the default server setup master = Puppet::Network::Handler.master.new( :Local => true ) } config = master.getconfig({"hostname" => "blah"}) # Cache this value for later parse1 = master.freshness("mynode") sleep 1.5 # Create a new manifest File.open(manifest, "w") { |f| f.puts "file { \"%s\": ensure => file }\n" % file2 } # Verify that the master doesn't immediately reparse the file; we # want to wait through the timeout assert_equal(parse1, master.freshness("mynode"), "Master did not wait through timeout") # Then eliminate it Puppet[:filetimeout] = 0 # Now make sure the master does reparse #Puppet.notice "%s vs %s" % [parse1, master.freshness] assert(parse1 != master.freshness("mynode"), "Master did not reparse file") assert(master.getconfig({"hostname" => "blah"}) != config, "Did not use reloaded config") end # Make sure we're correctly doing clientname manipulations. # Testing to make sure we always get a hostname and IP address. def test_clientname # create our master master = Puppet::Network::Handler.master.new( :Manifest => tempfile, :UseNodes => true, :Local => true ) # First check that 'cert' works Puppet[:node_name] = "cert" # Make sure we get the fact data back when nothing is set facts = { "hostname" => "fact_hostname", "domain" => "fact_domain", "fqdn" => "fact_hostname.fact_domain", "ipaddress" => "fact_ip" } certhostname = "cert_hostname" certdomain = "cert_domain" certname = certhostname + "." + certdomain certip = "cert_ip" resname, resip = master.send(:clientname, nil, nil, facts) assert_equal(facts["hostname"], resname, "Did not use fact hostname when no certname was present") assert_equal(facts["ipaddress"], resip, "Did not use fact ip when no certname was present") + assert_equal(facts["domain"], "fact_domain", "Did not use fact domain when no certname was present") + assert_equal(facts["fqdn"], "fact_hostname.fact_domain", "Did not use fact fqdn when no certname was present") # Now try it with the cert stuff present resname, resip = master.send(:clientname, certname, certip, facts) assert_equal(certname, resname, "Did not use cert hostname when certname was present") assert_equal(certip, resip, "Did not use cert ip when certname was present") + assert_equal(facts["domain"], certdomain, "Did not use cert domain when certname was present") + assert_equal(facts["fqdn"], certname, "Did not use cert fqdn when certname was present") # And reset the node_name stuff and make sure we use it. Puppet[:node_name] = :facter resname, resip = master.send(:clientname, certname, certip, facts) assert_equal(facts["hostname"], resname, "Did not use fact hostname when nodename was set to facter") assert_equal(facts["ipaddress"], resip, "Did not use fact ip when nodename was set to facter") end end