Using Puppet to Fix a File if it Exists

Using Puppet to Fix a File if it Exists

This past week I stumbled on a little bug in Ubuntu Oneiric that would bring a PHP web server to it's knees.

There's a simple temporary fix, that requires editing a single file on an affected server. I decided to deploy the fix with Puppet, then I realized that since the file wasn't directly deployed by puppet that it wasn't as easy to manage that file.

The trouble was that I only wanted to change the file if the distribution is Oneiric and the file exists. The file exists if you install LAMP (Linux, Apache, MySQL, PHP), but there are certain instances where that file may be installed without Puppet being the one to install LAMP, so I didn't want to tie the fix to my LAMP setup script.

Rather than breaking my LAMP install into multiple parts and complicating things more I set out on a quest to find how to replace a file using Puppet, but only if that file exists to begin with on the target system.

The solution I found isn't ideal, as Puppet doesn't have a way to directly test for a file that it's not already managing as part of a recipe. Instead you use an exec command.

To keep the exec command from running every single time Puppet runs, I have it create a file called /root/fixedphpcron that lets the Puppet script know that it's already done this.

Here's the Puppet recipe I came up with:

if $lsbdistcodename == "oneiric" {
     $oneiricfixphp_file = "/etc/cron.d/php5"
     $oneiricfixphp_text = "09,39 * * * * root [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -delete"
     exec { "oneiricfixphp": 
          command => "touch /root/fixedphpcron;/bin/echo '$oneiricfixphp_text' > $oneiricfixphp_file",
          onlyif => "/usr/bin/test -s /etc/cron.d/php5",
          creates => "/root/fixedphpcron",

There may be better ways to do this but the net result is that if the distribution is Oneiric and the /etc/cron.d/php5 file exists, replace it with my new contents. The "onlyif" feature would be awesome if it would work for a "file" object in the recipe, but it only works with the "exec" command.

Posted by Tony on Apr 05, 2012 | Servers, Puppet