Puppet Blog

Back to Index

When Puppet Reports, Part II

Posted on
By
James Turnbull
in
Blog, Community, DevOps, How to, Open Source
Responses
5 Comments »

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

Rémi

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

Greg Thompson

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!

James Turnbull

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

Greg Thompson

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

Leave a Response