summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-10-07 20:52:19 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-10-07 20:52:19 +0000
commit34f8337c68ff6f4b8ff57e604bae77529eb0d16e (patch)
treed7188575a0ec20c4082990afbf6b907146da364e /lib/puppet
parent5b6ee8c823a78f26cd1a1ad957da3d234910b9c2 (diff)
downloadpuppet-34f8337c68ff6f4b8ff57e604bae77529eb0d16e.tar.gz
puppet-34f8337c68ff6f4b8ff57e604bae77529eb0d16e.tar.xz
puppet-34f8337c68ff6f4b8ff57e604bae77529eb0d16e.zip
Refactoring reporting. Reports are now modules instead of simple methods.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1746 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/reports/rrdgraph.rb46
-rw-r--r--lib/puppet/reports/store.rb67
-rw-r--r--lib/puppet/reports/tagmail.rb185
-rw-r--r--lib/puppet/server.rb4
-rwxr-xr-xlib/puppet/server/report.rb134
-rw-r--r--lib/puppet/util/classgen.rb9
6 files changed, 248 insertions, 197 deletions
diff --git a/lib/puppet/reports/rrdgraph.rb b/lib/puppet/reports/rrdgraph.rb
index 0fb7e2ea7..2c405c051 100644
--- a/lib/puppet/reports/rrdgraph.rb
+++ b/lib/puppet/reports/rrdgraph.rb
@@ -1,34 +1,38 @@
require 'puppet'
-Puppet::Server::Report.newreport(:rrdgraph) do |report|
- time = Time.now.to_i
+Puppet::Server::Report.newreport(:rrdgraph) do
+ desc "Graph some data about hosts."
- host = report.host
+ def process
+ time = Time.now.to_i
- hostdir = File.join(Puppet[:rrddir], host)
+ host = self.host
- unless File.directory?(hostdir)
- # Some hackishness to create the dir
- config = Puppet::Config.new
- config.setdefaults(:reports, :hostdir => [hostdir, "eh"])
+ hostdir = File.join(Puppet[:rrddir], host)
- # This creates the dir.
- config.use(:reports)
- end
+ unless File.directory?(hostdir)
+ # Some hackishness to create the dir
+ config = Puppet::Config.new
+ config.setdefaults(:reports, :hostdir => [hostdir, "eh"])
- File.open(File.join(hostdir, "index.html"),"w") { |of|
- of.puts "<html><body>"
- report.metrics.each do |name, metric|
- metric.basedir = hostdir
- metric.store(time)
+ # This creates the dir.
+ config.use(:reports)
+ end
- metric.graph
+ File.open(File.join(hostdir, "index.html"),"w") { |of|
+ of.puts "<html><body>"
+ self.metrics.each do |name, metric|
+ metric.basedir = hostdir
+ metric.store(time)
- of.puts "<img src=%s.png><br>" % name
- end
+ metric.graph
- of.puts "</body></html>"
- }
+ of.puts "<img src=%s.png><br>" % name
+ end
+
+ of.puts "</body></html>"
+ }
+ end
end
# $Id$
diff --git a/lib/puppet/reports/store.rb b/lib/puppet/reports/store.rb
new file mode 100644
index 000000000..82eebff39
--- /dev/null
+++ b/lib/puppet/reports/store.rb
@@ -0,0 +1,67 @@
+require 'puppet'
+
+Puppet::Server::Report.newreport(:store, :useyaml => true) do
+ Puppet.setdefaults(:reporting,
+ :reportdir => {:default => "$vardir/reports",
+ :mode => 0750,
+ :owner => "$user",
+ :group => "$group",
+ :desc => "The directory in which to store reports received from the
+ client. Each client gets a separate subdirectory."}
+ )
+
+ Puppet.config.use(:reporting)
+
+ desc "Store the yaml report on disk"
+
+ def mkclientdir(client, dir)
+ config = Puppet::Config.new
+ config.setdefaults("reportclient-#{client}",
+ "clientdir-#{client}" => { :default => dir,
+ :mode => 0750,
+ :owner => "$user",
+ :group => "$group"
+ }
+ )
+
+ config.use("reportclient-#{client}")
+ end
+
+ def process(yaml)
+ # We don't want any tracking back in the fs. Unlikely, but there
+ # you go.
+ client = self.host.gsub("..",".")
+
+ dir = File.join(Puppet[:reportdir], client)
+
+ unless FileTest.exists?(dir)
+ mkclientdir(client, dir)
+ end
+
+ # Now store the report.
+ now = Time.now.gmtime
+ name = %w{year month day hour min}.collect do |method|
+ # Make sure we're at least two digits everywhere
+ "%02d" % now.send(method).to_s
+ end.join("") + ".yaml"
+
+ file = File.join(dir, name)
+
+ begin
+ File.open(file, "w", 0640) do |f|
+ f.puts yaml
+ end
+ rescue => detail
+ if Puppet[:trace]
+ puts detail.backtrace
+ end
+ Puppet.warning "Could not write report for %s at %s: %s" %
+ [client, file, detail]
+ end
+
+ # Only testing cares about the return value
+ return file
+ end
+end
+
+# $Id$
diff --git a/lib/puppet/reports/tagmail.rb b/lib/puppet/reports/tagmail.rb
index b7025802d..e842b17ac 100644
--- a/lib/puppet/reports/tagmail.rb
+++ b/lib/puppet/reports/tagmail.rb
@@ -14,116 +14,119 @@ Puppet.config.setdefaults(:reporting,
require 'net/smtp'
-Puppet::Server::Report.newreport(:tagmail) do |report|
- unless FileTest.exists?(Puppet[:tagmap])
- Puppet.notice "Cannot send tagmail report; no tagmap file %s" %
- Puppet[:tagmap]
- return
- end
-
- # Load the config file
- taglists = {}
- File.readlines(Puppet[:tagmap]).each do |line|
- taglist = emails = nil
- case line.chomp
- when /^\s*#/: next
- when /^\s*$/: next
- when /^\s*(.+)\s*:\s*(.+)\s*$/:
- taglist = $1
- emails = $2
- else
- raise ArgumentError, "Invalid tagmail config file"
+Puppet::Server::Report.newreport(:tagmail) do
+ desc "Send email reports."
+ def process
+ unless FileTest.exists?(Puppet[:tagmap])
+ Puppet.notice "Cannot send tagmail report; no tagmap file %s" %
+ Puppet[:tagmap]
+ return
end
- pos = []
- neg = []
- taglist.split(/\s*,\s*/).each do |tag|
- case tag
- when /^\w+/: pos << tag
- when /^!\w+/: neg << tag.sub("!", '')
+ # Load the config file
+ taglists = {}
+ File.readlines(Puppet[:tagmap]).each do |line|
+ taglist = emails = nil
+ case line.chomp
+ when /^\s*#/: next
+ when /^\s*$/: next
+ when /^\s*(.+)\s*:\s*(.+)\s*$/:
+ taglist = $1
+ emails = $2
else
- raise Puppet::Error, "Invalid tag '%s'" % tag
+ raise ArgumentError, "Invalid tagmail config file"
end
- end
- # Now split the emails
- emails = emails.split(/\s*,\s*/)
- taglists[emails] = [pos, neg]
- end
+ pos = []
+ neg = []
+ taglist.split(/\s*,\s*/).each do |tag|
+ case tag
+ when /^\w+/: pos << tag
+ when /^!\w+/: neg << tag.sub("!", '')
+ else
+ raise Puppet::Error, "Invalid tag '%s'" % tag
+ end
+ end
- # Now find any appropriately tagged messages.
- reports = {}
- taglists.each do |emails, tags|
- pos, neg = tags
+ # Now split the emails
+ emails = emails.split(/\s*,\s*/)
+ taglists[emails] = [pos, neg]
+ end
- # First find all of the messages matched by our positive tags
- messages = nil
- if pos.include?("all")
- messages = report.logs
- else
- # Find all of the messages that are tagged with any of our
- # tags.
- messages = report.logs.find_all do |log|
- pos.detect { |tag| log.tagged?(tag) }
+ # Now find any appropriately tagged messages.
+ reports = {}
+ taglists.each do |emails, tags|
+ pos, neg = tags
+
+ # First find all of the messages matched by our positive tags
+ messages = nil
+ if pos.include?("all")
+ messages = self.logs
+ else
+ # Find all of the messages that are tagged with any of our
+ # tags.
+ messages = self.logs.find_all do |log|
+ pos.detect { |tag| log.tagged?(tag) }
+ end
end
- end
- # Now go through and remove any messages that match our negative tags
- messages.reject! do |log|
- if neg.detect do |tag| log.tagged?(tag) end
- true
+ # Now go through and remove any messages that match our negative tags
+ messages.reject! do |log|
+ if neg.detect do |tag| log.tagged?(tag) end
+ true
+ end
end
- end
- if messages.empty?
- Puppet.info "No messages to report to %s" % emails.join(",")
- next
- else
- reports[emails] = messages.collect { |m| m.to_report }.join("\n")
+ if messages.empty?
+ Puppet.info "No messages to report to %s" % emails.join(",")
+ next
+ else
+ reports[emails] = messages.collect { |m| m.to_report }.join("\n")
+ end
end
- end
- # Let's fork for the sending of the email, since you never know what might
- # happen.
- fork do
- if Puppet[:smtpserver] != "none"
- begin
- Net::SMTP.start(Puppet[:smtpserver]) do |smtp|
- reports.each do |emails, messages|
- Puppet.info "Sending report to %s" % emails.join(", ")
- smtp.send_message(messages, Puppet[:reportfrom], *emails)
+ # Let's fork for the sending of the email, since you never know what might
+ # happen.
+ fork do
+ if Puppet[:smtpserver] != "none"
+ begin
+ Net::SMTP.start(Puppet[:smtpserver]) do |smtp|
+ reports.each do |emails, messages|
+ Puppet.info "Sending report to %s" % emails.join(", ")
+ smtp.send_message(messages, Puppet[:reportfrom], *emails)
+ end
end
+ rescue => detail
+ if Puppet[:debug]
+ puts detail.backtrace
+ end
+ raise Puppet::Error,
+ "Could not send report emails through smtp: %s" % detail
end
- rescue => detail
- if Puppet[:debug]
- puts detail.backtrace
- end
- raise Puppet::Error,
- "Could not send report emails through smtp: %s" % detail
- end
- elsif Puppet[:sendmail] != ""
- begin
- reports.each do |emails, messages|
- Puppet.info "Sending report to %s" % emails.join(", ")
- # We need to open a separate process for every set of email addresses
- IO.popen(Puppet[:sendmail] + " " + emails.join(" "), "w") do |p|
- p.puts "From: #{Puppet[:reportfrom]}"
- p.puts "To: %s" % emails.join(', ')
- p.puts "Subject: Puppet Report for %s" % report.host
- p.puts "To: " + emails.join(", ")
+ elsif Puppet[:sendmail] != ""
+ begin
+ reports.each do |emails, messages|
+ Puppet.info "Sending report to %s" % emails.join(", ")
+ # We need to open a separate process for every set of email addresses
+ IO.popen(Puppet[:sendmail] + " " + emails.join(" "), "w") do |p|
+ p.puts "From: #{Puppet[:reportfrom]}"
+ p.puts "To: %s" % emails.join(', ')
+ p.puts "Subject: Puppet Report for %s" % self.host
+ p.puts "To: " + emails.join(", ")
- p.puts messages
+ p.puts messages
+ end
end
+ rescue => detail
+ if Puppet[:debug]
+ puts detail.backtrace
+ end
+ raise Puppet::Error,
+ "Could not send report emails via sendmail: %s" % detail
end
- rescue => detail
- if Puppet[:debug]
- puts detail.backtrace
- end
- raise Puppet::Error,
- "Could not send report emails via sendmail: %s" % detail
+ else
+ raise Puppet::Error, "SMTP server is unset and could not find sendmail"
end
- else
- raise Puppet::Error, "SMTP server is unset and could not find sendmail"
end
end
end
diff --git a/lib/puppet/server.rb b/lib/puppet/server.rb
index 84d2940c3..6809c7c36 100644
--- a/lib/puppet/server.rb
+++ b/lib/puppet/server.rb
@@ -143,6 +143,10 @@ module Puppet
# the base class for the different handlers
class Handler
attr_accessor :server
+ class << self
+ include Puppet::Util
+ end
+
@subclasses = []
def self.each
diff --git a/lib/puppet/server/report.rb b/lib/puppet/server/report.rb
index 027c78f9d..6253f6a0e 100755
--- a/lib/puppet/server/report.rb
+++ b/lib/puppet/server/report.rb
@@ -2,18 +2,29 @@ module Puppet
class Server
# A simple server for triggering a new run on a Puppet client.
class Report < Handler
+ class << self
+ include Puppet::Util::ClassGen
+ end
+
+ module ReportBase
+ include Puppet::Util::Docs
+ attr_writer :useyaml
+
+ def useyaml?
+ if defined? @useyaml
+ @useyaml
+ else
+ false
+ end
+ end
+ end
+
@interface = XMLRPC::Service::Interface.new("puppetreports") { |iface|
iface.add_method("string report(array)")
}
Puppet.setdefaults(:reporting,
- :reportdirectory => {:default => "$vardir/reports",
- :mode => 0750,
- :owner => "$user",
- :group => "$group",
- :desc => "The directory in which to store reports received from the
- client. Each client gets a separate subdirectory."},
- :reports => ["none",
+ :reports => ["store",
"The list of reports to generate. All reports are looked for
in puppet/reports/<name>.rb, and multiple report names should be
comma-separated (whitespace is okay)."
@@ -27,19 +38,19 @@ class Server
attr_reader :hooks
end
- def self.reportmethod(report)
- "report_" + report.to_s
- end
+ # Add a new report type.
+ def self.newreport(name, options = {}, &block)
+ name = symbolize(name)
- # Add a hook for processing reports.
- def self.newreport(name, &block)
- name = name.intern if name.is_a? String
- method = reportmethod(name)
+ mod = genmodule(name, :extend => ReportBase, :hash => @reports, :block => block)
- # We want to define a method so that reports can use 'return'.
- define_method(method, &block)
+ if options[:useyaml]
+ mod.useyaml = true
+ end
- @reports[name] = method
+ mod.send(:define_method, :report_name) do
+ name
+ end
end
# Load a report.
@@ -58,8 +69,12 @@ class Server
return nil
end
end
+ @reports[symbolize(name)]
+ end
- @reports[name]
+ def self.reports
+ @reportloader.loadall
+ @reports.keys
end
def initialize(*args)
@@ -68,24 +83,8 @@ class Server
Puppet.config.use(:metrics)
end
- # Dynamically create the report methods as necessary.
- def method_missing(name, *args)
- if name.to_s =~ /^report_(.+)$/
- if self.class.report($1)
- send(name, *args)
- else
- super
- end
- else
- super
- end
- end
-
# Accept a report from a client.
def report(report, client = nil, clientip = nil)
- # We need the client name for storing files.
- client ||= Facter["hostname"].value
-
# Unescape the report
unless @local
report = CGI.unescape(report)
@@ -99,74 +98,39 @@ class Server
puts detail.backtrace
end
end
-
- # We don't want any tracking back in the fs. Unlikely, but there
- # you go.
- client.gsub("..",".")
-
- dir = File.join(Puppet[:reportdirectory], client)
-
- unless FileTest.exists?(dir)
- mkclientdir(client, dir)
- end
-
- # Now store the report.
- now = Time.now.gmtime
- name = %w{year month day hour min}.collect do |method|
- # Make sure we're at least two digits everywhere
- "%02d" % now.send(method).to_s
- end.join("") + ".yaml"
-
- file = File.join(dir, name)
-
- begin
- File.open(file, "w", 0640) do |f|
- f.puts report
- end
- rescue => detail
- if Puppet[:trace]
- puts detail.backtrace
- end
- Puppet.warning "Could not write report for %s at %s: %s" %
- [client, file, detail]
- end
-
-
- # Our report is in YAML
- return file
end
private
- def mkclientdir(client, dir)
- Puppet.config.setdefaults("reportclient-#{client}",
- "clientdir-#{client}" => { :default => dir,
- :mode => 0750,
- :owner => "$user",
- :group => "$group"
- }
- )
-
- Puppet.config.use("reportclient-#{client}")
- end
-
# Process the report using all of the existing hooks.
- def process(report)
+ def process(yaml)
return if Puppet[:reports] == "none"
# First convert the report to real objects
begin
- report = YAML.load(report)
+ report = YAML.load(yaml)
rescue => detail
Puppet.warning "Could not load report: %s" % detail
return
end
+ # Used for those reports that accept yaml
+ client = report.host
+
reports().each do |name|
- if method = self.class.report(name) and respond_to? method
+ if mod = self.class.report(name)
Puppet.info "Processing report %s" % name
+
+ # We have to use a dup because we're including a module in the
+ # report.
+ newrep = report.dup
begin
- send(method, report)
+ newrep.extend(mod)
+ if mod.useyaml?
+ newrep.process(yaml)
+ else
+ newrep.process
+ end
rescue => detail
if Puppet[:trace]
puts detail.backtrace
diff --git a/lib/puppet/util/classgen.rb b/lib/puppet/util/classgen.rb
index dabbda3d1..8fa2a34cf 100644
--- a/lib/puppet/util/classgen.rb
+++ b/lib/puppet/util/classgen.rb
@@ -154,6 +154,15 @@ module Puppet::Util::ClassGen
end
end
+ [:include, :extend].each do |method|
+ if set = options[method]
+ set = [set] unless set.is_a?(Array)
+ set.each do |mod|
+ klass.send(method, mod)
+ end
+ end
+ end
+
if klass.respond_to? :preinit
klass.preinit
end