{"id":427,"date":"2008-04-17T11:36:06","date_gmt":"2008-04-17T10:36:06","guid":{"rendered":"http:\/\/wp.devco.net\/?p=427"},"modified":"2009-10-09T14:01:07","modified_gmt":"2009-10-09T13:01:07","slug":"easy_per-machine_custom_facts_for_puppet","status":"publish","type":"post","link":"https:\/\/www.devco.net\/archives\/2008\/04\/17\/easy_per-machine_custom_facts_for_puppet.php","title":{"rendered":"Easy per-machine custom facts for Puppet"},"content":{"rendered":"

UPDATED<\/b>: The code below is a bit crap – first ever ruby code – try this instead<\/a><\/p>\n

As this is the first time I am posting about Puppet<\/a>, 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<\/a> and lcfg<\/a> 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.<\/p>\n

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.<\/p>\n

So the rest is only really useful if you already know Puppet, sorry if this will bore many people \ud83d\ude42<\/p>\n

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”<\/i> 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.<\/p>\n

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.<\/p>\n

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.<\/a>  Instead I’ll show a simple bit of code to read in \/etc\/facts.txt<\/i> on a node and present the values in it as facts.<\/p>\n

<\/p>\n

var = nil
value = nil
facts = {}<\/p>\n

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<\/p>\n

        facts.each{|var,val|
                Facter.add(var) do
                        setcode do
                                val
                        end
                end
        }
end<\/p><\/blockquote>\n

This code essentially just reads stuff out of key=val<\/i> pairs in \/etc\/facts.txt<\/i> 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.<\/p>\n

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.<\/p>\n

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.<\/p>\n","protected":false},"excerpt":{"rendered":"

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 […]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","footnotes":""},"categories":[7],"tags":[121,13],"_links":{"self":[{"href":"https:\/\/www.devco.net\/wp-json\/wp\/v2\/posts\/427"}],"collection":[{"href":"https:\/\/www.devco.net\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devco.net\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devco.net\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devco.net\/wp-json\/wp\/v2\/comments?post=427"}],"version-history":[{"count":1,"href":"https:\/\/www.devco.net\/wp-json\/wp\/v2\/posts\/427\/revisions"}],"predecessor-version":[{"id":526,"href":"https:\/\/www.devco.net\/wp-json\/wp\/v2\/posts\/427\/revisions\/526"}],"wp:attachment":[{"href":"https:\/\/www.devco.net\/wp-json\/wp\/v2\/media?parent=427"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devco.net\/wp-json\/wp\/v2\/categories?post=427"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devco.net\/wp-json\/wp\/v2\/tags?post=427"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}