UPDATED: The code below is a bit crap – first ever ruby code – try this instead
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
endfacts.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.