diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/puppet/application.rb | 24 | ||||
-rw-r--r-- | lib/puppet/configurer.rb | 4 | ||||
-rw-r--r-- | lib/puppet/node/environment.rb | 4 | ||||
-rwxr-xr-x | lib/puppet/provider/package/gem.rb | 4 | ||||
-rw-r--r-- | lib/puppet/resource/type_collection.rb | 5 | ||||
-rw-r--r-- | lib/puppet/transaction.rb | 2 | ||||
-rwxr-xr-x | lib/puppet/type/cron.rb | 4 | ||||
-rw-r--r-- | lib/puppet/type/file.rb | 19 | ||||
-rw-r--r-- | lib/puppet/util/command_line.rb | 27 | ||||
-rw-r--r-- | lib/puppet/util/plugins.rb | 82 |
10 files changed, 138 insertions, 37 deletions
diff --git a/lib/puppet/application.rb b/lib/puppet/application.rb index 7ef71bc81..57bd88877 100644 --- a/lib/puppet/application.rb +++ b/lib/puppet/application.rb @@ -1,4 +1,5 @@ require 'optparse' +require 'puppet/util/plugins' # This class handles all the aspects of a Puppet application/executable # * setting up options @@ -298,11 +299,11 @@ class Application # This is the main application entry point def run - exit_on_fail("initialize") { preinit } - exit_on_fail("parse options") { parse_options } + exit_on_fail("initialize") { hook('preinit') { preinit } } + exit_on_fail("parse options") { hook('parse_options') { parse_options } } exit_on_fail("parse configuration file") { Puppet.settings.parse } if should_parse_config? - exit_on_fail("prepare for execution") { setup } - exit_on_fail("run") { run_command } + exit_on_fail("prepare for execution") { hook('setup') { setup } } + exit_on_fail("run") { hook('run_command') { run_command } } end def main @@ -392,11 +393,18 @@ class Application private def exit_on_fail(message, code = 1) - yield + yield rescue RuntimeError, NotImplementedError => detail - puts detail.backtrace if Puppet[:trace] - $stderr.puts "Could not #{message}: #{detail}" - exit(code) + puts detail.backtrace if Puppet[:trace] + $stderr.puts "Could not #{message}: #{detail}" + exit(code) + end + + def hook(step,&block) + Puppet::Plugins.send("before_application_#{step}",:application_object => self) + x = yield + Puppet::Plugins.send("after_application_#{step}",:application_object => self, :return_value => x) + x end end end diff --git a/lib/puppet/configurer.rb b/lib/puppet/configurer.rb index 72e387c64..cfeb73a1f 100644 --- a/lib/puppet/configurer.rb +++ b/lib/puppet/configurer.rb @@ -173,9 +173,7 @@ class Puppet::Configurer report.finalize_report if trans puts report.summary if Puppet[:summarize] save_last_run_summary(report) - if Puppet[:report] - Puppet::Transaction::Report.indirection.save(report) - end + Puppet::Transaction::Report.indirection.save(report) if Puppet[:report] rescue => detail puts detail.backtrace if Puppet[:trace] Puppet.err "Could not send report: #{detail}" diff --git a/lib/puppet/node/environment.rb b/lib/puppet/node/environment.rb index d50530618..dc631979e 100644 --- a/lib/puppet/node/environment.rb +++ b/lib/puppet/node/environment.rb @@ -79,7 +79,7 @@ class Puppet::Node::Environment # environment has changed do we delve deeper. Thread.current[:known_resource_types] = nil if (krt = Thread.current[:known_resource_types]) && krt.environment != self Thread.current[:known_resource_types] ||= synchronize { - if @known_resource_types.nil? or @known_resource_types.stale? + if @known_resource_types.nil? or @known_resource_types.require_reparse? @known_resource_types = Puppet::Resource::TypeCollection.new(self) @known_resource_types.import_ast(perform_initial_import, '') end @@ -160,6 +160,8 @@ class Puppet::Node::Environment end parser.parse rescue => detail + known_resource_types.parse_failed = true + msg = "Could not parse for environment #{self}: #{detail}" error = Puppet::Error.new(msg) error.set_backtrace(detail.backtrace) diff --git a/lib/puppet/provider/package/gem.rb b/lib/puppet/provider/package/gem.rb index 19414cec4..28731c849 100755 --- a/lib/puppet/provider/package/gem.rb +++ b/lib/puppet/provider/package/gem.rb @@ -22,7 +22,7 @@ Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package d end if name = hash[:justme] - command << name + command << name + "$" end begin @@ -94,7 +94,7 @@ Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package d command << "--source" << "#{source}" << resource[:name] end else - command << resource[:name] + command << "--no-rdoc" << "--no-ri" << resource[:name] end output = execute(command) diff --git a/lib/puppet/resource/type_collection.rb b/lib/puppet/resource/type_collection.rb index 6ab978f7c..9fe7cdd06 100644 --- a/lib/puppet/resource/type_collection.rb +++ b/lib/puppet/resource/type_collection.rb @@ -1,5 +1,6 @@ class Puppet::Resource::TypeCollection attr_reader :environment + attr_accessor :parse_failed def clear @hostclasses.clear @@ -120,6 +121,10 @@ class Puppet::Resource::TypeCollection end end + def require_reparse? + @parse_failed || stale? + end + def stale? @watched_files.values.detect { |file| file.changed? } end diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index 8118178c3..0533273d9 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -48,7 +48,7 @@ class Puppet::Transaction def apply(resource, ancestor = nil) status = resource_harness.evaluate(resource) add_resource_status(status) - event_manager.queue_events(ancestor || resource, status.events) + event_manager.queue_events(ancestor || resource, status.events) unless status.failed? rescue => detail resource.err "Could not evaluate: #{detail}" end diff --git a/lib/puppet/type/cron.rb b/lib/puppet/type/cron.rb index 4b18e71f9..4f6ea733c 100755 --- a/lib/puppet/type/cron.rb +++ b/lib/puppet/type/cron.rb @@ -226,7 +226,9 @@ Puppet::Type.newtype(:cron) do end newproperty(:special) do - desc "Special schedules" + desc "A special value such as 'reboot' or 'annually'. + Only available on supported systems such as Vixie Cron. + Overrides more specific time of day/week settings." def specials %w{reboot yearly annually monthly weekly daily midnight hourly} diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb index 5632d41f1..715836b22 100644 --- a/lib/puppet/type/file.rb +++ b/lib/puppet/type/file.rb @@ -123,15 +123,16 @@ Puppet::Type.newtype(:file) do newparam(:recurse) do desc "Whether and how deeply to do recursive management. Options are: - inf,true => Regular style recursion on both remote and local - directory structure. - remote => Descends recursively into the remote directory - but not the local directory. Allows copying of - a few files into a directory containing many - unmanaged files without scanning all the local files. - false => Default of no-recursion. - [0-9]+ => Both, but limit recursion. Warning: this syntax - is deprecated and has moved to recurselimit. + + * `inf,true` --- Regular style recursion on both remote and local + directory structure. + * `remote` --- Descends recursively into the remote directory + but not the local directory. Allows copying of + a few files into a directory containing many + unmanaged files without scanning all the local files. + * `false` --- Default of no recursion. + * `[0-9]+` --- Same as true, but limit recursion. Warning: this syntax + has been deprecated in favor of the `recurselimit` attribute. " newvalues(:true, :false, :inf, :remote, /^[0-9]+$/) diff --git a/lib/puppet/util/command_line.rb b/lib/puppet/util/command_line.rb index 7f74d266a..52b5f81ef 100644 --- a/lib/puppet/util/command_line.rb +++ b/lib/puppet/util/command_line.rb @@ -1,9 +1,10 @@ +require "puppet/util/plugins" + module Puppet module Util class CommandLine - LegacyName = Hash.new{|h,k| k}.update( - { + LegacyName = Hash.new{|h,k| k}.update( 'agent' => 'puppetd', 'cert' => 'puppetca', 'doc' => 'puppetdoc', @@ -13,9 +14,8 @@ module Puppet 'queue' => 'puppetqd', 'resource' => 'ralsh', 'kick' => 'puppetrun', - 'master' => 'puppetmasterd', - - }) + 'master' => 'puppetmasterd' + ) def initialize( zero = $0, argv = ARGV, stdin = STDIN ) @zero = zero @@ -23,6 +23,7 @@ module Puppet @stdin = stdin @subcommand_name, @args = subcommand_and_args( @zero, @argv, @stdin ) + Puppet::Plugins.on_commandline_initialization(:command_line_object => self) end attr :subcommand_name @@ -56,21 +57,23 @@ module Puppet puts usage_message elsif available_subcommands.include?(subcommand_name) #subcommand require_application subcommand_name - Puppet::Application.find(subcommand_name).new(self).run + app = Puppet::Application.find(subcommand_name).new(self) + Puppet::Plugins.on_application_initialization(:appliation_object => self) + app.run else abort "Error: Unknown command #{subcommand_name}.\n#{usage_message}" unless execute_external_subcommand end end def execute_external_subcommand - external_command = "puppet-#{subcommand_name}" + external_command = "puppet-#{subcommand_name}" - require 'puppet/util' - path_to_subcommand = Puppet::Util.which( external_command ) - return false unless path_to_subcommand + require 'puppet/util' + path_to_subcommand = Puppet::Util.which( external_command ) + return false unless path_to_subcommand - system( path_to_subcommand, *args ) - true + system( path_to_subcommand, *args ) + true end def legacy_executable_name diff --git a/lib/puppet/util/plugins.rb b/lib/puppet/util/plugins.rb new file mode 100644 index 000000000..105fdcd75 --- /dev/null +++ b/lib/puppet/util/plugins.rb @@ -0,0 +1,82 @@ +# +# This system manages an extensible set of metadata about plugins which it +# collects by searching for files named "plugin_init.rb" in a series of +# directories. Initially, these are simply the $LOAD_PATH. +# +# The contents of each file found is executed in the context of a Puppet::Plugins +# object (and thus scoped). An example file might contain: +# +# ------------------------------------------------------- +# @name = "Greet the CA" +# +# @description = %q{ +# This plugin causes a friendly greeting to print out on a master +# that is operating as the CA, after it has been set up but before +# it does anything. +# } +# +# def after_application_setup(options) +# if options[:application_object].is_a?(Puppet::Application::Master) && Puppet::SSL::CertificateAuthority.ca? +# puts "Hey, this is the CA!" +# end +# end +# ------------------------------------------------------- +# +# Note that the instance variables are local to this Puppet::Plugin (and so may be used +# for maintaining state, etc.) but the plugin system does not provide any thread safety +# assurances, so they may not be adequate for some complex use cases. +# +# +module Puppet + class Plugins + Paths = [] # Where we might find plugin initialization code + Loaded = [] # Code we have found (one-to-one with paths once searched) + # + # Return all the Puppet::Plugins we know about, searching any new paths + # + def self.known + Paths[Loaded.length...Paths.length].each { |path| + file = File.join(path,'plugin_init.rb') + Loaded << (File.exist?(file) && new(file)) + } + Loaded.compact + end + # + # Add more places to look for plugins without adding duplicates or changing the + # order of ones we've already found. + # + def self.look_in(*paths) + Paths.replace Paths | paths.flatten.collect { |path| File.expand_path(path) } + end + # + # Initially just look in $LOAD_PATH + # + look_in $LOAD_PATH + # + # Calling methods (hooks) on the class calls the method of the same name on + # all plugins that use that hook, passing in the same arguments to each + # and returning an array containing the results returned by each plugin as + # an array of [plugin_name,result] pairs. + # + def self.method_missing(hook,*args,&block) + known. + select { |p| p.respond_to? hook }. + collect { |p| [p.name,p.send(hook,*args,&block)] } + end + # + # + # + attr_reader :path,:name + def initialize(path) + @name = @path = path + class << self + private + def define_hooks + eval File.read(path),nil,path,1 + end + end + define_hooks + end + end +end + |