<artwork />   <projects />   <rhetoric />   <snippets />

Puppet 2.6 Workaround for launchctl overrides.plist

We’re stuck with an old version of puppet on our Macs because our puppet server is running RHEL 6 (surprise) which is stuck at 2.6.14. My previous attempts to bridge major version differences have failed miserably. Now I just keep them in sync and sigh at all the awesome features I don’t get to play with just yet.

I don’t know how we didn’t run into this problem in the past (perhaps it was a change on puppet’s part), but during my Lion testing, I noticed that puppet was trying to load launchctl jobs without the -w flag. In particular, Cups and SSH were refusing to load. After some Googling, I discovered that puppet didn’t know that new versions of Mac OS X no longer stored the Disable key inside the launchctl plist file in /System/Library/LaunchDaemons. Instead, Disable keys are stored in /var/db/launchd.db/com.apple.launchd/overrides.plist.

It looks like newer versions of puppet have a fix, but unless that fix gets back ported, I’m stuck finding my own solution. Enter PlistBuddy, a simple (and somewhat stupid) tool for editing plist files. Here’s an example of how to get the Disable key settings for Cups and SSH (I apologize for my web design laziness; if your window isn’t wide enough, the text will run off the screen):

# /usr/libexec/PlistBuddy -c "Print :org.cups.cupsd:Disabled" /var/db/launchd.db/com.apple.launchd/overrides.plist
# /usr/libexec/PlistBuddy -c "Print :com.openssh.sshd:Disabled" /var/db/launchd.db/com.apple.launchd/overrides.plist

Please note the colons (:) in the command we send to PlistBuddy. If you open the /var/db/launchd.db/com.apple.launchd/overrides.plist file, you’ll see that it’s in XML and that it’s a dictionary with many keys. Each key in that dictionary is the name of a launchctl job. At the highest level, you can run something like:

# /usr/libexec/PlistBuddy -c "Print :" /var/db/launchd.db/com.apple.launchd/overrides.plist

This prints the dictionary keys and their values (which, as you might have noticed, are also dictionaries). The following will let you see the value of just one dictionary key, “com.openssh.sshd”:

# /usr/libexec/PlistBuddy -c "Print :com.openssh.sshd" /var/db/launchd.db/com.apple.launchd/overrides.plist

This prints out the dictionary stored inside the com.openssh.sshd key. And lastly, the original command I gave you will give you the value of the key inside that dictionary:

# /usr/libexec/PlistBuddy -c "Print :com.openssh.sshd:Disabled" /var/db/launchd.db/com.apple.launchd/overrides.plist

A value of true means the service will not start, and a value of false means that the service can start. PlistBuddy can also set values. The syntax is the same, but instead of using Print, you pass it the Set command. For something simple, like setting something to true or false, this is very straightforward:

# /usr/libexec/PlistBuddy -c "Set :com.openssh.sshd:Disabled false" /var/db/launchd.db/com.apple.launchd/overrides.plist

OK, now that I’ve walked you through how PlistBuddy works (you can read about other supported commands in man PlistBuddy), I’ll show you how to set the value in puppet, using the exec type. Here’s an example for SSH:

exec {
  "Turn off Disabled key for SSH":
    command => "/usr/libexec/PlistBuddy -c 'Set :com.openssh.sshd:Disabled false' /var/db/launchd.db/com.apple.launchd/overrides.plist",
    onlyif  => "/usr/libexec/PlistBuddy -c 'Print :com.openssh.sshd:Disabled' /var/db/launchd.db/com.apple.launchd/overrides.plist | grep -q true";

Here, the command simply sets the Disabled flag to false, provided that it’s currently set to true. Obviously, this would lend itself very well to scripting. You could replace “:com.openssh.sshd:Disabled” with a puppet variable and call it for each service you wanted to enable. And if you wanted to be sure that the Service resource loaded correctly the first time, you could use a require line to tell puppet to try running the exec first:

Service {
    ensure  => true,
    enable  => true,
    hasstatus => true,
    require => Exec["Turn off Disabled key for SSH"];

I hope this helps someone else. I wasted too much time on this trying to be clever. I’m looking forward to using a version of puppet that has a patch for this built into it.

Leave a Reply

about | blog | email | links | sitemap

Entries (RSS) and Comments (RSS).