/dev/oops

fiddyspence's blog

You Are Feeling Very Sleepy...


I recently wrote a Puppet report processor (mconotify) that processes Puppet reports and sends mcollective messages to trigger Puppet runs.  It was an attempt to build infrastructure where one part of an infrastructure can securely touch another part of the same infrastructure.

I’ve also been thinking about how to make catalog application also take into account parts of an infrastructure when applying state to a node.  Being able to test another configuration at apply time in a way that pauses a Puppet run while you wait for something else to happen sounded like a good idea to me.

One solution I came up with was to use the Puppet resource abstraction layer to do a sleep for an arbitrary length of time - if you have to wait 5 minutes, then

  sleep { 300: }

A more sophisticated approach would be to sleep for 5 minutes, but stop sleeping if your condition is satisfied:

  sleep { ‘until i need to wake up’:
    bedtime       => 300,
    wakeupfor     => ‘nc thedatabaseserver 3306 -w 1’,
    dozetime      => 10,
    failontimeout => true,
  }

In this example, we’ll sleep for a maximum of 5 minutes, but wake up every 10 seconds to netcat to the mysql port on a database server and if that exits successfully exit the sleep and carry on.  If the command doesn’t return 0 by the end of 5 minutes, we fail the resource (and anything in my catalog dependent on it will therefore not apply).  If you wanted to continue anyway, set failontimeout to false, and the thing won’t fail.  Simples.

You could use exec resource types, but it starts to look complicated in terms of the commands you have to run - wrapping it up in a type felt like the right solution here.

I think this is pretty neat.

The code is available on the Puppet Forge, as usual: http://forge.puppetlabs.com/fiddyspence/sleep