Easy per-machine custom facts for Puppet

As this is the first time I am posting about Puppet, maybe a few words about it first.  Puppet is a configuration management system that helps you manage large infrastructures.  There are ofcourse many similar things, cfengine and lcfg to name just two.  I like Puppet as it has a big and active community but it is also a modern approach to the problem being that it has some properties of Object Orientation and so forth.

I've used cfengine - actually chose it over Puppet when it was still young - but that is over a year ago now and I if you have many or even 2 of the same nodes to maintain I urge you to check out Puppet.

So the rest is only really useful if you already know Puppet, sorry if this will bore many people :)

On a site I worked we used to have a file on each machine that defines a few Facter facts, this was very handy and I wanted to do something similar because I define variables like $country="uk" and so forth in my nodes which then helps my manifests builds correct ntp configs for example.  Now doing it with a global variable in the node is ok and all, but not nearly as sexy as letting each node know where they are in via facts.

In the old days hacking in new facts was a right pain and you possibly even needed to maintain your own package of facter, not so anymore, it's in fact really nice now.

Puppet now lets you drop bits of ruby code into a directory and then sends the code off to clients on demand for integration into Facter, I won't go into setting it up the Puppet Wiki goes into it at length.  Instead I'll show a simple bit of code to read in /etc/facts.txt on a node and present the values in it as facts.


var = nil
value = nil
facts = {}

if File.exists?("/etc/facts.txt")
        File.open("/etc/facts.txt").each do |line|
                var = $1 and value = $2 if line =~ /^(.+)=(.+)$/
                if var != nil && value != nil
                        facts[var] = value
                        var = nil
                        value = nil
                end
        end

        facts.each{|var,val|
                Facter.add(var) do
                        setcode do
                                val
                        end
                end
        }
end
This code essentially just reads stuff out of key=val pairs in /etc/facts.txt and adds them to facter.  Drop that into your facts directory on the master in a file ending in .rb and that should be it, with facts files on your nodes the values will now be available for use in your manifests.

Maybe not the best Ruby code as it's my first ever Ruby code and mostly based on a sample I found in the Puppet book, I would have liked to do the Facter.add() call right in the loop that parses the file instead of using a array, but I couldn't get that going.

Anyway, now I just distribute /etc/facts.txt to all my machines, and they know where they are and I have a simple no-hassle method for teaching machines about new things.

Leave a comment

Recent Entries

  • flashpolicyd 2.0

    I wrote a multi threaded server for Adobe Flash Policy requests, some background from Adobe:Since policy files were first introduced, Flash Player has recognized /crossdomain.xml...

  • Adventures with Ruby

    Some more about my continuing experiences with ruby, in my last post I saidthe language does what you'd expect and as you'll see in my...

  • New programming language of choice - Ruby

    I have fallen out of love with Perl some time ago, I cannot point to one specific thing about it that put me off, I...

  • On working from home

    I've not been posting much here, work has been incredibly manic the last while, especially I need to still finish off my SSO posts with...

  • Rework of puppet facts for /etc/facts.txt

    Previously I blogged a custom fact that reads /etc/facts.txt to build up some custom facts for use in Puppet manifests, well I've since learned a...

Close