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 |
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