Puppet stages and APT

gonz -- for no reason except he's the MAN!

At work, our old code deployment strategy was basically a wrapper script doing an svn checkout and some symlinking. With our move to Puppet for config management, we also moved to using Apt packaging for our code deployment, tying them together with a line similar to :

class foo-export {
package { 'foo-export': ensure => latest }

So that whenever we deploy a new version of a package to our apt-repo, it can then be installed with a:

puppet agent --test
(and with an initial dry-run using --noop)

( I should mention I manage our Puppet runs via our own distributed scripts, rather than having the nodes set up to check in every 30mins - when I'm doing so much work on our Puppet setup and config, I'd rather not having machines check in automatically in case the config is in a broken state )

Inevitably I would run the above Puppet command and it would not find any new packages, because ‘d'uh!', of course I still need to run an apt-get update.

I've been using Puppet stages for a while now, in order to group package installations in a broader sense rather than manually spelling out every dependency with a require => stanza, so it was a simple addition to add in a pre stage, and have the nodes run apt-get update before any runs.

In order to use stages, you need to first define them in your site.pp. By default every defined class runs under Stage[main], so you just need to add the new stages and define the running order. (full Puppet stage documentation is here)

At the top of my site.pp file, I added a pre and post stage, then define the execution order via:

stage { [pre, post]: }
Stage[pre] -> Stage[main] -> Stage[post]

Then I created a class called apt-hupdate (sorry, i use stupid naming conventions!) in

which contained:
class apt-hupdate {

exec { "aptHupdate":
command => "/usr/bin/apt-get update",

And finally, include that in your site.pp with:

class { apt-hupdate: stage => pre }

Now every time you do a Puppet run, apt-get update will be the first task run.

puppet mastering

At my work, we're now really digging into using Puppet - no longer just as a TechOps tools, but for our whole development cycle.

The hardest thing I've come across so far is in deploying Perl CPAN packages, although i have been using manifest/recipe i found here -

It had been working quite well, but now as we've been adding more and more to Puppet, I started seeing an error message:

root@machine:~ $ puppet agent -test
err: Could not retrieve catalog from remote server: Could not intern from pson: expected value in object at ‘”i'!
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run

- the error was intermittent and always slightly differently, making it quite hard to track down. I found a number of people running into similar problems on forums and mailing lists, but no satisfactory answers.

Aiiight, so the problem is due to the default HTTP server within Puppet, which is called WEBrick - I didn't dig into why, but after having re-double-triple-checked my manifest syntax and having tried a million other solutions, i thought to switch out the webserver component to see what would happen (I wasn't being completely original here - any article which talks about scaling Puppet says that you have to move to using a different server).

Instructions for switching to Apache2/Passenger (mod_rails) are here - they're quite simple and it's easy to setup.