When Puppet Reports, Part II
Puppet provides a lot of very useful data about itself and your infrastructure, collected in the Puppet Data Library. Every Puppet run on a client creates a report including every action taken during the run, log output, and metrics on the performance of the run. As we discovered in Part I, there are a broad selection of report processors available for Puppet. But you are not limited to these report processors. Puppet also allows you to create your own. A new report processor is a very simple Ruby plug-in; most processors are less than 50 lines of code. The large collection of existing report processors also makes it easy to adapt a processor to suit your needs.
Much like custom facts, report processors can be stored in modules and distributed using pluginsync. Let’s start by creating a new module to hold our new report processor.
$ mkdir -p newreport/manifests $ mkdir -p newreport/lib/puppet/reports $ touch newreport/manifests/init.pp |
We put our new report processor in the newreport/lib/puppet/reports directory.
Now let’s create our report processor itself. Each report processor is very simple:
require 'puppet' Puppet::Reports.register_report(:newreport) do end |
We start with requiring Puppet itself, require ‘puppet’. We then register our new report in a register_report block, we’ve named ours newreport.
Next we’re going to add some documentation to explain what our report processor does:
require 'puppet' Puppet::Reports.register_report(:newreport) do desc <<-DESC A new report processor. DESC end |
Next we need to create the core logic of our report processor. This needs to be contained in a method called process.
require 'puppet' Puppet::Reports.register_report(:newreport) do desc <<-DESC A new report processor. DESC def process end end |
A variety of data from the client report is available to the process method. The report itself is passed to the method and referenced as the self object. You can refer to each component of the report by prefixing it with self., for example self.host will contain the node name of the client. The table below is a list of the majority of the data available in the report. You can see some more details here.
| self.host | The node name of the client |
| self.status | The status of the run: failed, unchanged, etc |
| self.configuration_version | The configuration version of the run |
| self.kind | The type of run: apply, inspect, etc |
| self.environment | The environment of the client |
| self.metrics | The metrics from the run |
| self.logs | The log output from the run |
Let’s take all of this and look at a simple example of a custom report processor.
require 'puppet' Puppet::Reports.register_report(:newreport) do desc <<-DESC A new report processor. DESC def process Puppet.debug “Puppet #{self.kind} run on #{self.host} ended with status #{self.status}” end end |
Here we’re sending a Puppet debug message indicating the status and some details of the Puppet run. We could instead send the same message as an instant message or to IRC as we saw in two of the report processors we looked at in Part I.
Let’s see another, more sophisticated, example of a report processor:
require 'puppet' Puppet::Reports.register_report(:newreport) do desc <<-DESC A new report processor. DESC def process client = self.host logs = self.logs config_version = self.configuration_version dir = File.join(Puppet[:reportdir], client) Dir.mkdir(dir) unless File.exists?(dir) file = config_version + ".logs" destination = File.join(dir, file) File.open(destination,"w") do |f| f.write(logs) end end end |
In our new processor we are taking the log output from a Puppet run and writing it to a file.
Lastly, we create a Modulefile for our new report.
name 'puppet-newreport' version '0.0.1' license 'Apache 2.0' summary 'A new Puppet report processor’ project_page 'https://github.com/puppetlabs/puppet-newreport' |
We would then add our report name to Puppet in the puppet.conf configuration file and enable pluginsync.
report=true pluginsync=true reports=store,log,newreport |
Next time Puppet runs our report processor will be enabled and our custom report generated.
Learn More
5 Comments
Thanks for these articles about reporting… I’ve just starting to write a xymon report processor ;-) There is a typo in the table : self.logs not self.log
Thanks again,
Regards
Thanks! Fixed.
I found this blog post to be a little confusing. In this post you state that reports are shipped via plugin sync, which is used for shipping things that run on the agent but reports run on the server. In the Pro Puppet book you state that custom reports require installation into the reports dir inside the ../ruby/1.8/puppet/reports directory on the puppet master. Of these approaches I found the one from the book worked. Could you please clarify what the difference is? Is it now possible to use plugin sync for reports and if so could you provide a little bit more information on how to configure it? Many thanks and keep up the good work!
Greg
The pluginsync assumes you’re plugin syncing the report processor to the master, i.e. you’re loading the module on the master and running the Puppet agent locally on the master to populate it. That saves you having to copy the processor around.
Hope that helps!
James
Thanks James.
I had initially used a file resource, processed by the masters agent, to put the report in place. After reading you advice I went back to plugin sync and now have it working properly.
Thanks again,
Greg