A collection of task oriented solutions in Puppet

 

What are External Facts?

Challenge

You want to learn about external facts.

Solution

Read on brave reader, read on!

Explanation

In order for puppet to learn all the useful facts about your system that allow it to correctly manage resources, such as the operating system, active IP addresses or the versions of ruby available there needs to be a way to query all of those things. In the case of Puppet that way is a library, and command line tool, named facter.

The facts distributed with core facter, and the ones written in ruby and deployed via puppet modules, are considered to be 'internal facts'. In contrast to these are external facts, either static files of information, or scripts that return certain data structures when called, that add extra functionality. These can be written in any programming language and are called using a simple, and predictable, protocol that doesn't require them to support anything ruby specific. In this recipe we'll focus on external facts.

There are two main types of external facts. The first allows you to surface your own facts from a static file, either plain text key value pairs or a specific YAML / JSON format. These static files should be placed under /etc/facter/facts.d.

$ sudo mkdir -p /etc/facter/facts.d

# note - the .txt file extension
$ echo 'external_fact=yes' | sudo tee /etc/facter/facts.d/external_test.txt
external_fact=worked

$ facter external_fact
worked

At its simplest this is a way to surface basic, static, details from system provisioning and other similar large events but it’s also an easy way to include details from other daemons and cronjobs. One of my first use cases for external facts was to create last_backup_time and last_backup_status facts that are written at the conclusion of my backup cronjob. Having values inserted from out of band is a nicer prospect than writing a custom fact that parses cron logs.

If that's a little too static for you then the second usage might be what you're looking for. Any executable scripts dropped in the same directory, that produce the same output formats as allowed above, will be executed by facter when it's invoked.

# scripts must be executable!
$ sudo chmod a+rx /etc/facter/facts.d/process_count

$ cat /etc/facter/facts.d/process_count
#!/bin/bash

count=$(ps -efwww | wc -l | tr -s ' ')
echo "process_count=$count"

$ facter process_count
209

The ability to run scripts that provide facts and values makes customisation easier in situations where ruby isn't the best language for the job. It's also a nice way to reuse existing tools or for including information from further afield - such as the current binary log in use by MySQL or PostgreSQL or the hosts current state in the load balancer.

See also