diff options
| author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-09-05 18:10:57 +0000 |
|---|---|---|
| committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-09-05 18:10:57 +0000 |
| commit | b303e8d3b7c31ebccabb0b3238104f5f019c5b6a (patch) | |
| tree | 149d9eaa498d97456756605711cb62c5e24fec2d | |
| parent | b36df181f4f2064b3dbbce861912262594044b14 (diff) | |
| download | puppet-b303e8d3b7c31ebccabb0b3238104f5f019c5b6a.tar.gz puppet-b303e8d3b7c31ebccabb0b3238104f5f019c5b6a.tar.xz puppet-b303e8d3b7c31ebccabb0b3238104f5f019c5b6a.zip | |
Adding the ability to download facts from the central server. This allows facts to be available before the configuration is compiled.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1561 980ebf18-57e1-0310-9a29-db15c13687c0
| -rw-r--r-- | lib/puppet/client/master.rb | 137 | ||||
| -rw-r--r-- | test/client/master.rb | 82 |
2 files changed, 184 insertions, 35 deletions
diff --git a/lib/puppet/client/master.rb b/lib/puppet/client/master.rb index 906f8be3c..ba6e7ec84 100644 --- a/lib/puppet/client/master.rb +++ b/lib/puppet/client/master.rb @@ -28,6 +28,7 @@ class Puppet::Client::MasterClient < Puppet::Client ] ) + # Plugin information. Puppet.setdefaults("puppet", :pluginpath => ["$vardir/plugins", "Where Puppet should look for plugins. Multiple directories should @@ -42,7 +43,25 @@ class Puppet::Client::MasterClient < Puppet::Client :pluginsync => [false, "Whether plugins should be synced with the central server."], :pluginsignore => [".svn CVS", - "What files to ignore when pulling down plugins.."] + "What files to ignore when pulling down plugins."] + ) + + # Central fact information. + Puppet.setdefaults("puppet", + :factpath => ["$vardir/facts", + "Where Puppet should look for facts. Multiple directories should + be colon-separated, like normal PATH variables."], + :factdest => ["$vardir/facts", + "Where Puppet should store facts that it pulls down from the central + server."], + :factsource => ["puppet://$server/facts", + "From where to retrieve facts. The standard Puppet ``file`` type + is used for retrieval, so anything that is a valid file source can + be used here."], + :factsync => [false, + "Whether facts should be synced with the central server."], + :factsignore => [".svn CVS", + "What files to ignore when pulling down facts."] ) @drivername = :Master @@ -57,6 +76,11 @@ class Puppet::Client::MasterClient < Puppet::Client end def self.facts + # Retrieve the facts from the central server. + if Puppet[:factsync] + self.class.getfacts() + end + facts = {} Facter.each { |name,fact| facts[name] = fact.to_s.downcase @@ -218,6 +242,11 @@ class Puppet::Client::MasterClient < Puppet::Client Puppet.debug("getting config") dostorage() + # Retrieve the plugins. + if Puppet[:pluginsync] + self.class.getplugins() + end + facts = self.class.facts unless facts.length > 0 @@ -226,11 +255,6 @@ class Puppet::Client::MasterClient < Puppet::Client ) end - # Retrieve the plugins. - if Puppet[:pluginsync] - getplugins() - end - objects = nil if @local # If we're local, we don't have to do any of the conversion @@ -471,50 +495,109 @@ class Puppet::Client::MasterClient < Puppet::Client end private - # Retrieve the plugins from the central server. - def getplugins - plugins = Puppet::Type.type(:component).create( - :name => "plugin_collector" + + def self.download(args) + objects = Puppet::Type.type(:component).create( + :name => "#{args[:name]}_collector" ) - plugins.push Puppet::Type.type(:file).create( - :path => Puppet[:plugindest], + hash = { + :path => args[:dest], :recurse => true, - :source => Puppet[:pluginsource], - :ignore => Puppet[:pluginsignore].split(/\s+/), - :tag => "plugins", + :source => args[:source], + :tag => "#{args[:name]}s", :owner => "root" - ) + } - Puppet.info "Retrieving plugins" + if args[:ignore] + hash[:ignore] = args[:ignore].split(/\s+/) + end + objects.push Puppet::Type.type(:file).create(hash) + Puppet.info "Retrieving #{args[:name]}s" begin - trans = plugins.evaluate + trans = objects.evaluate trans.evaluate rescue Puppet::Error => detail if Puppet[:debug] puts detail.backtrace end - Puppet.err "Could not retrieve plugins: %s" % detail + Puppet.err "Could not retrieve #{args[:name]}s: %s" % detail end # Now source all of the changed objects, but only source those # that are top-level. - trans.changed?.find_all { |object| - File.dirname(object[:path]) == Puppet[:pluginpath] - }.each do |object| + trans.changed?.find_all do |object| + yield object + end + + # Now clean up after ourselves + objects.remove + end + + # Retrieve facts from the central server. + def self.getfacts + # First clear all existing definitions. + Facter.clear + + path = Puppet[:factpath].split(":") + download(:dest => Puppet[:factdest], :source => Puppet[:factsource], + :ignore => Puppet[:factsignore], :name => "fact") do |object| + + next unless path.include?(File.dirname(object[:path])) + begin - Puppet.info "Loading plugin %s" % - File.basename(object[:path]).sub(".rb",'') + Puppet.info "Loading fact %s" % + File.basename(File.basename(object[:path])).sub(".rb",'') + load object[:path] + rescue => detail + Puppet.warning "Could not reload fact %s: %s" % + [object[:path], detail] + end + end + ensure + Facter.loadfacts + end + + # Retrieve the plugins from the central server. We only have to load the + # changed plugins, because Puppet::Type loads plugins on demand. + def self.getplugins + path = Puppet[:pluginpath].split(":") + download(:dest => Puppet[:plugindest], :source => Puppet[:pluginsource], + :ignore => Puppet[:pluginsignore], :name => "plugin") do |object| + + next unless path.include?(File.dirname(object[:path])) + + begin + Puppet.info "Reloading plugin %s" % + File.basename(File.basename(object[:path])).sub(".rb",'') load object[:path] rescue => detail Puppet.warning "Could not reload plugin %s: %s" % [object[:path], detail] end end + end - # Now clean up after ourselves - plugins.remove + def self.loaddir(dir, type) + return unless FileTest.directory?(dir) + + Dir.entries(dir).find_all { |e| e =~ /\.rb$/ }.each do |file| + fqfile = File.join(dir, file) + begin + Puppet.info "Loading #{type} %s" % + File.basename(file.sub(".rb",'')) + load fqfile + rescue => detail + Puppet.warning "Could not load #{type} %s: %s" % [fqfile, detail] + end + end + end + + def self.loadfacts + Puppet[:factpath].split(":").each do |dir| + loaddir(dir, "fact") + end end def reportclient @@ -526,6 +609,8 @@ class Puppet::Client::MasterClient < Puppet::Client @reportclient end + + loadfacts() end # $Id$ diff --git a/test/client/master.rb b/test/client/master.rb index 655b3fae6..2f88123b5 100644 --- a/test/client/master.rb +++ b/test/client/master.rb @@ -146,10 +146,8 @@ end } end - client = mkclient() - assert_nothing_raised { - client.send(:getplugins) + Puppet::Client::MasterClient.getplugins } destfile = File.join(Puppet[:plugindest], "myplugin.rb") @@ -177,7 +175,7 @@ end end assert_nothing_raised { - client.send(:getplugins) + Puppet::Client::MasterClient.getplugins } destfile = File.join(Puppet[:pluginpath], "myplugin.rb") @@ -194,13 +192,79 @@ end assert(! obj.validattr?(:argument), "Old namevar is still valid") + end - # Now make sure it works with multiple paths specified. - newdir = tempfile() - Dir.mkdir(newdir) - Puppet[:pluginpath] = [Puppet[:pluginpath], newdir].join(":") + def test_getfacts + Puppet[:factsource] = tempfile() + Dir.mkdir(Puppet[:factsource]) - client.send(:getplugins) + myfact = File.join(Puppet[:factsource], "myfact.rb") + File.open(myfact, "w") do |f| + f.puts %{Facter.add("myfact") do + setcode { "yayness" } +end +} + end + + assert_nothing_raised { + Puppet::Client::MasterClient.getfacts + } + + destfile = File.join(Puppet[:factdest], "myfact.rb") + + assert(File.exists?(destfile), "Did not get fact") + + assert_equal("yayness", Facter["myfact"].value, + "Did not get correct fact value") + + # Now modify the file and make sure the type is replaced + File.open(myfact, "w") do |f| + f.puts %{Facter.add("myfact") do + setcode { "funtest" } +end +} + end + + assert_nothing_raised { + Puppet::Client::MasterClient.getfacts + } + + assert_equal("funtest", Facter["myfact"].value, + "Did not reload fact") + end + + # Make sure we load all facts on startup. + def test_loadfacts + dirs = [tempfile(), tempfile()] + count = 0 + names = [] + dirs.each do |dir| + Dir.mkdir(dir) + name = "fact%s" % count + names << name + file = File.join(dir, "%s.rb" % name) + + # Write out a plugin file + File.open(file, "w") do |f| + f.puts %{Facter.add("#{name}") do setcode { "#{name}" } end } + end + count += 1 + end + + Puppet[:factpath] = dirs.join(":") + + names.each do |name| + assert_nil(Facter.value(name), "Somehow retrieved invalid fact") + end + + assert_nothing_raised { + Puppet::Client::MasterClient.loadfacts + } + + names.each do |name| + assert_equal(name, Facter.value(name), + "Did not retrieve facts") + end end end |
