From 306aa3032a3770c0d668907ae08042be88ec725e Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Fri, 12 Nov 2010 13:39:41 +0100 Subject: Fix #4339 - Save a last run report summary to $statedir/last_run_summary.yaml Once a configuration run is done, puppetd will save on the node a yaml summary report roughly akin to: --- time: notify: 0.001025 last_run: 1289561427 schedule: 0.00071 config_retrieval: 0.039518 filebucket: 0.000126 resources: changed: 1 total: 8 out_of_sync: 1 events: total: 1 success: 1 changes: total: 1 This is almost an hash version of the current --summarize output, with the notable exception that the time section includes the last run unix timestamp. The whole idea is to be able to monitor locally if a puppetd does its job. For instance this could be used in a nagios check or to send an SNMP trap. The last_run information might help detect staleness, and this summary can also be used for performance monitoring (ie time section). The resource section can also show the number of failed resources. Signed-off-by: Brice Figureau --- lib/puppet/util/metric.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib/puppet/util') diff --git a/lib/puppet/util/metric.rb b/lib/puppet/util/metric.rb index 09bbb6137..835e1d610 100644 --- a/lib/puppet/util/metric.rb +++ b/lib/puppet/util/metric.rb @@ -122,7 +122,7 @@ class Puppet::Util::Metric def initialize(name,label = nil) @name = name.to_s - @label = label || labelize(name) + @label = label || self.class.labelize(name) @values = [] end @@ -133,7 +133,7 @@ class Puppet::Util::Metric def newvalue(name,value,label = nil) raise ArgumentError.new("metric name #{name.inspect} is not a string") unless name.is_a? String - label ||= labelize(name) + label ||= self.class.labelize(name) @values.push [name,label,value] end @@ -174,10 +174,8 @@ class Puppet::Util::Metric @values.sort { |a, b| a[1] <=> b[1] } end - private - # Convert a name into a label. - def labelize(name) + def self.labelize(name) name.to_s.capitalize.gsub("_", " ") end end -- cgit From 99d78f2c15b6ccf543466d3fa2cdeda7eb3f9987 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Fri, 25 Mar 2011 12:00:39 -0700 Subject: (#6490) Add plugin initialization callback system to core The recurring pattern "drop-in code needs to have something done at startup" is presently being solved with a variety of ad-hock mechanism. This commit adds a general, extensible, centralized system for adding such hooks and 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. Applications can add more places to look for plugins without risk of adding duplicates or changing the order of ones that have already been found with: Puppet::Plugins.look_in(*paths) 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! Hi everyone!!!" 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. Presently supported hooks: before_application_preinit( :application_object => ... ) after_application_preinit( :application_object => ... ) before_application_parse_options( :application_object => ... ) after_application_parse_options( :application_object => ... ) before_application_setup( :application_object => ... ) after_application_setup( :application_object => ... ) before_application_run_command( :application_object => ... ) after_application_run_command( :application_object => ... ) on_commandline_initialization(:command_line_object => ... ) on_application_initialization(:appliation_object => ... ) Paired-with: Daniel Pitman --- lib/puppet/util/command_line.rb | 7 +++- lib/puppet/util/plugins.rb | 82 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 lib/puppet/util/plugins.rb (limited to 'lib/puppet/util') diff --git a/lib/puppet/util/command_line.rb b/lib/puppet/util/command_line.rb index 7f74d266a..fb56b2898 100644 --- a/lib/puppet/util/command_line.rb +++ b/lib/puppet/util/command_line.rb @@ -1,3 +1,5 @@ +require "puppet/util/plugins" + module Puppet module Util class CommandLine @@ -23,6 +25,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,7 +59,9 @@ 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 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 + -- cgit From 1e4968e82a65b21ad5d075015830ef3f54efee05 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Wed, 6 Apr 2011 20:25:45 -0700 Subject: (maint) Indentation fixes --- lib/puppet/util/command_line.rb | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'lib/puppet/util') diff --git a/lib/puppet/util/command_line.rb b/lib/puppet/util/command_line.rb index fb56b2898..52b5f81ef 100644 --- a/lib/puppet/util/command_line.rb +++ b/lib/puppet/util/command_line.rb @@ -4,8 +4,7 @@ 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', @@ -15,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 @@ -68,14 +66,14 @@ module Puppet 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 -- cgit