Insert Wit Here

Posts Tagged ‘hacks

A simple IP Address reflector

Or, Why the hell do I have to build every tool myself. I find it incredible that no one else has wanted this before.

In the course of another side project I needed to determine a nodes externally visible IP Address and FQDN. After a while I eventually found this forum post. And their “bot” url does work, though it’s a bit limited. So I hacked up some simple PHP to do it in a flavor that I like.

donavanm$  curl

Will also accept source and (reasonable) timeout parameters. A simple TCP connection is attempted back to your IP and specified port. Handy to see if NAT/iptables/etc is functioning.

donavanm$  curl

Get the source or try it yourself.

Written by donavan

2011/02/10 at 19:16

Posted in Software

Tagged with

Array of Hashes in Puppet DSL

A while back I was writing some custom server side functions to interrogate an inventory system for live information about other nodes. The returned data can be used to dynamically configure all sorts of settings that rely on other nodes: DNS resolvers, LDAP servers, Ganglia forwarders, etc.

Returning an array of nodes I could iterate a Define multiple times to create a set of resources. Here’s an example creating a set of Host resources for all of my DNS resolvers:

$mynameservers = find_nearest_nodes("puppetclass == dns::resolver")
# => ['ns1.domain.tld','ns2.domain.tld']
define hostentry() {
    $entry_ip = find_node_fact($name, "ipaddress")
    $entry_hostname = find_node_fact($name, "hostname")
    host{ $name: ip => $entry_ip, host_aliases => $entry_hostname }
hostentry { $mynameservers }

The two lookups in the define bothered me a bit. Assuming each lookup had some overhead latency that could add up. Why not simply return a hash with all the information i needed?

$myhashes = find_nearest_nodes("puppetclass == dns::resolver", ['ipaddress', 'hostname'])
# => [ {"ns2.domain.tld"=>{"ipaddress"=>"", "hostname"=>"ns2"}}, {"ns1.domain.tld"=>{"ipaddress"=>"", "hostname"=>"ns1"}} ]

But this array of hashes isn’t very useful. Each array entry is passed as $name to the target resource. Native resource types like File or Host will expect a string as the $name. Passing them the hash object won’t do what you want, I’m guessing it’d be collapsed in to a string with #to_s.

We can solve that though by wrapping the native type with a defined type . Inside the define you’ll be able to access the subkeys of $name like a normal hash. This allows you to pass your hash values as parameters to the actual resource:

$myhashes = find_nearest_nodes("puppetclass == dns::resolver", ['ipaddress', 'hostname'])
# =>  [ {"ns2.domain.tld"=>{"ipaddress"=>"", "hostname"=>"ns2"}}, {"ns1.domain.tld"=>{"ipaddress"=>"", "hostname"=>"ns1"}} ]
define hostentry() {
    # $name looks like {"ns2.domain.tld"=>{"ipaddress"=>"", "hostname"=>"ns2"}}
    host{ $name: ip => $name[ipaddress], host_aliases => $name[hostname] }
hostentry{ $myhashes: }

EDIT: 4/7/11
Sorry #puppet, I’ve updated that last example. I’d written this post from memory and obviously didnt try the examples. $myhashes is an Array of Hashes, not HoH, and I missed the : when calling the hostentry define.
And if you think you want to do this, don’t. Drop in to a template or Ruby DSL. Usage is non obvious and relies on undefined behavior with namevar. I wouldn’t be surprised if it breaks horribly in a point release (though it works in 2.6.7).

Written by donavan

2011/01/19 at 17:36

Posted in Software

Tagged with ,