six demon bag

Wind, fire, all that kind of thing!

2022-05-21

A Convenience Wrapper for the Puppet Agent

At work we're doing config management with Puppet, and although using the Puppet agent is mostly fine, I have some workflows where it becomes rather unwieldy. For example, when debugging something or developing a new role I usually want to keep the agent disabled, but still do manual (dry-)runs every now and then to check what Puppet would change in the config or apply changes selectively. Which tends to look somewhat like this:


puppet agent --enable; puppet agent --test --noop; puppet agent --disable 'my reason'

or this:

puppet agent --enable; puppet agent --test --tags ssh,rsyslog; puppet agent --disable 'my reason'

As you can see, these are not the most convenient commandlines ever, even if I used short options instead of the long ones. Even more so if I want to keep the disable reason the same that it was before.

Checking if the agent is disabled or not is another thing that's more tedious than it needs to be. Sure, I could run puppet agent -t -n, which would show me a message with the reason if the agent had actually been disabled. But if it hadn't I'd be stuck with an unnecessary dry-run that could take a while. Or I could check the lock file in which the reason is stored, but then I'd have to memorize the path to that file (which, of course, is not in /var/lock, because that would obviously be way too obvious, right?). Hence a quick way of getting basic information about the agent status was also on my wishlist.

And since we usually add a user name or shorthand as well as the current date to the disable reason (so that we can see not only why Puppet was disabled, but also by whom and when), wouldn't it be nice if those bits were added automatically?

So I cobbled together a little script that provides an (IMO) far more convenient interface to the abovementioned operations. Usage is like this:

pat

The above simply invokes puppet agent --test or displays a warning if the agent had been disabled. Adding -v (verbose) enables debug output (puppet agent --test --debug). If you're wondering why -v doesn't translate to --verbose in the agent command: --test already implies --verbose, so it has to be --debug for more verbosity.

You can also run the agent just for particular tags (puppet agent --test --tags logrotate,ssh) by adding them as whitespace-separated arguments:

pat logrotate ssh

To disable the agent just run something like the following:

pat -d -u john "troubleshooting issue XYZ"

Add the option -f (force) if you want to replace an existing reason.

The username option -u can be omitted if a variable $ADMIN_NAME has been defined, e.g. by setting ADMIN_NAME="$USER" on your workstation and adding the variable to AcceptEnv in the sshd_config on the remote host where you invoke this script. Also, note that adding a username to the reason is merely for communicating to other team members who disabled the agent. It's not intended (nor is it suitable) for auditing purposes.

For a dry-run (puppet agent --test --noop) invoke the command with the option -n:

pat -n
pat -n logrotate ssh

The command detects if the agent has been disabled, temporarily re-enables it for the dry-run and disables it again afterwards with the same reason as before.

Alternatively you can force a single live run while the agent is disabled by putting -f instead of -n.

Re-enable the agent by running

pat -e

You may also add the option -r when enabling the agent to immediately trigger a subsequent agent run.

To check the agent status run

pat -s

Currently this shows the puppetmaster and whether or not the agent is disabled.

One last note: We're using cron for scheduled Puppet runs, so my script disables this cron job (/etc/cron.d/puppet) when disabling the agent, and restores it when re-enabling the agent. If you don't do scheduled Puppet runs you can use the script as-is (a missing cron job will simply be ignored). But if you use a different cron job or an entirely different method for scheduling Puppet runs you'll have to modify the function scheduled_runs() accordingly.

Hope you'll find this useful. Have fun.

Download

Github

Posted 12:09 [permalink]