- Lab
- A Cloud Guru
Writing Custom Puppet Facts
There are multiple ways we can provide our own facts to our Puppet infrastructure, including plain-text eternal facts files, executable scripts, and via writing Ruby fact plugins. Custom facts are plugins that leverage Ruby to either provide static fact data or evaluate and command as well as provide the output for the value of the fact. These custom facts can be written so they are as simple as providing us a key-value pair or as complicated as some of the structured data sets we see when we query for our `os`-based facts. In this lab, we'll create a custom aggregate fact that provides us with data about our host's web server (should it exist), learn how to create structured facts, and use various coding techniques to ensure our facts work on all systems.
Path Info
Table of Contents
-
Challenge
Set the Web Server Fact
-
Move into the
nginx
module directory:cd /etc/puppetlabs/code/environments/production/modules/nginx/
-
Create the plugin library location for Facter:
sudo mkdir -p lib/facter
-
Create and open a file called
web.rb
in the plugin location:sudo vim lib/facter/web.rb
-
At its most basic, if we wanted to write a single, non-structured fact that output our web server information, we could write something like:
Facter.add(:web) do setcode do 'Nginx' end end
Notice how this includes the
Facter.add
line to set our fact name, and thesetcode
statement, which provides us our output. Since we just want to supply the textNginx
, that is all we put in our statement block. -
However, since we need this to become a structured, aggregate fact, we're going to refactor this so we can add more facts to our code. Let's first define the overall
web
fact as an aggregate, which means the resolution of ourweb
fact can be read in separate chunks:Facter.add(:web, :type => :aggregate) do
-
Next, we want to replace our
setcode
statement withchunk
, which lets us define the different parts of our structured fact:Facter.add(:web, :type => :aggregate) do chunk(:server) do
-
We now need to update the structure of our output, so it resembles the JSON output we expected when we query for facts. To this, let's create a variable,
web
, then add ourNginx
value as a structured key-value pair:Facter.add(:web, :type => :aggregate) do chunk(:server) do web = {:server => 'Nginx'} web end end
Save and exit.
-
Let's now test our fact:
sudo puppet agent -t sudo facter -p web sudo facter -p web.server
-
-
Challenge
Set the Version Fact
-
Back in the
lib/facter/web.rb
file, create a secondchunk
line, this one calledversion
; include a line at the end calling theweb
variable:chunk(:version) do web end
-
We're going to check our version by using a slightly edited version of the
nginx -v
command — which means we neednginx
for this fact to work. Let's add anif
statement checking fornginx
:chunk(:version) do if Facter::Core::Execution.which('nginx') != nil end web end
-
Finally, we want to execute the appropriate command and have the output sent to a structured line mapped to web. Because our command is on the long side, you may want to create a variable for its output:
chunk(:version) do if Facter::Core::Execution.which('nginx') != nil version = Facter::Core::Execution.execute('nginx -v 2>&1 | grep -Po [0-9]+\.[0-9]+\.[0-9]+') web = {:version => version} end web end
-
If desired, save and test your code thus far.
-
-
Challenge
Set the Fact for the Amount of Running Web Processes
Mimic the same structures as the previous chunks to create the stanza that provides the amount of running processes:
chunk(:processes) do processes = Facter::Core::Execution.execute('pgrep nginx | wc -l') web = {:processes => processes } web end
The full file should look like:
Facter.add(:web, :type => :aggregate) do chunk(:server) do web = {:server => 'Nginx'} web end chunk(:version) do if Facter::Core::Execution.which('nginx') != nil version = Facter::Core::Execution.execute('nginx -v 2>&1 | grep -Po [0-9]+\.[0-9]+\.[0-9]+') web = {:version => version} end web end chunk(:processes) do processes = Facter::Core::Execution.execute('pgrep nginx | wc -l') web = {:processes => processes } web end end
-
Challenge
Test the New Facts
Test that each fact works, as well as the overall
web
fact. Note that the second server is provided so you can test on a node with Nginx, as well as one without it (remember, our Puppet master does not have Nginx installed):sudo puppet agent -t sudo facter -p web sudo facter -p web.server sudo facter -p web.version sudo facter -p web.processes
What's a lab?
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Provided environment for hands-on practice
We will provide the credentials and environment necessary for you to practice right within your browser.
Guided walkthrough
Follow along with the author’s guided walkthrough and build something new in your provided environment!
Did you know?
On average, you retain 75% more of your learning if you get time for practice.