Using a Pre-Commit Hook to Check Puppet Syntax


The whole idea of Puppet is to put your machine configuration scripts in a versioned repository. This is good because I've found that a syntax error on a manifest not even used by the current machine will stop the puppet updates from running. One error anywhere kills the whole thing everywhere. So, being able to back out of a change is good.

We can go one better however and keep people from checking in files that aren't syntactically correct using the pre-commit hook in SVN. If you don't use SVN, your repository probably has something similar.

I followed these instructions for the hook and these instructions for installing it.

I ran into a problem however. The pre-commit script wasn't reporting an error condition correctly. I'm not sure what was wrong. Running the puppet command on the command line and then checking $? gave a "1", but inside the script it wasn't working that way. So, I punted and wrote the error output to a file and checked whether or not the file existed and then just cat'd that out to standard err. Messy, but it worked and I need to go home. Here's the file as modified by me:

#!/bin/bash
# SVN pre-commit hook to check Puppet syntax for .pp files
PATH="/usr/bin:/bin"
REPOS="$1"
TXN="$2"
tmpfile=`mktemp`
errfile=`mktemp`
export HOME=/
SVNLOOK=/usr/bin/svnlook
$SVNLOOK changed -t "$TXN" "$REPOS" | awk '{print $2}' \\
   | grep '\\.pp$' | while read line
do
  $SVNLOOK cat -t "$TXN" "$REPOS" "$line" > $tmpfile
  if [ $? -ne 0 ]
  then
    echo "Warning: Failed to checkout $line" >&2
  fi
  /usr/bin/puppet --color=false --confdir=/tmp \\
     --vardir=/tmp --parseonly --ignoreimport $tmpfile \\
     >$errfile 2>/dev/null
  if [  -s $errfile ]
  then
    echo "Puppet syntax error in $line." >&2
    cat $errfile >&2
    exit 2
  fi
done
res=$?
rm -f $tmpfile
rm -f $errfile
if [ $res -ne 0 ]
then
  exit $res
fi

Note: you may need to combine lines separated by "\\\\" into a single line.

This works great. Syntax errors are caught before they make it into the repository. I'm still looking for a good way to thoroughly test puppet scripts before they get into the production servers. If you have any best practices in that area, I'd love to hear about them.


Please leave comments using the Hypothes.is sidebar.