Puppet Tips

Puppet Tips

I've been using Puppet to configure systems for a few years now; right back to the 0.24 days. Here's some distilled experience:

  1. Forget about subscribe, require and notify. Immediately.

    These are "meta-parameters" you can pass to resources like file and service. There's no reason to even consider them. Use a new version of Puppet and the chaining resources syntax everywhere, all the time. It's more flexible and completely replaces these old parameters.

  2. Don't skimp on ensure => absent

    Every parameterized class should implement this contract (let's call it "ensurable"):

    • The class accepts an argument called $ensure.
    • The argument has a default value of 'present', or any value with similar semantics.
    • The class reacts accordingly if $ensure is set to 'absent'.
    • The class may react to any other value as it sees fit. ('running', 'stopped', etc.)
    • The class passes a sensible $ensure value to all the resources and parameterized classes it declares.

    Because Puppet classes have named parameters, you can add this $ensure parameter after the fact; there's no need to add it when you first define your class. But what I've (too slowly) learned is: you should define it immediately. Don't be lazy. Do it now.

    Why? Well, when you're starting out writing the definitions for your servers, you will make mistakes. You'll define services on boxes that you want to migrate later. You'll reprovision. You'll accidentally copy and paste chunks of your node definitions and set up an extra service. It happens.

    If your class doesn't define $ensure, it's a problem waiting to happen. For example, you could be left with a concat fragment, because you couldn't pass the correct $ensure value into its declaration when you wanted it gone. Simple enough to avoid, but if that happened to you from an exported resource it that could leave a couple of extraneous lines in a config file on another server. This is a pain in the ass to debug. I guarantee it'll take you at least half an hour to trace it back into the fragments directory and to "that mistake I made last week that was only deployed for a minute". Save that debugging time now. Do the right thing, and make all your classes ensurable.

  3. Consider architecture

    If you're configuring 32-bit systems at all, you'll need to deploy packages with different binaries - in APT speak, the packages will have a different arch. When you define your package, the provider will just hand the problem over to the system's packaging, and everything will 'just work': each system will get the correct package for its architecture.

    However, the contents of those packages will often differ in ways you might not expect; it's not just the binaries that might be different. For example, the default PHP extension_dir contains a build identifier, and that can change on different architectures. So, if you're serving php.ini from Puppet, you'll need to check $::architecture and template it accordingly.

  4. Bookmark the documentation

    These two resources provide you the most help:

    • When you come across a new part of the language, or are considering using a feature, have a look at the Language Guide.
    • In your day-to-day module building, you'll want the Type Reference open in a tab permanently. I find it far more useful than any "cheat sheet" I've seen: you need information about what different providers do (and how they do it), and a few sentences of context are invaluable: the exceptions mentioned implicitly define the rule, if you like - they help you get firm mental model of what each resource represents.