Files
blog/content/posts/2017-04-05-git-post-receive-hook-for-puppet-control-repo-updates.md
T

4.8 KiB
Raw Blame History

title, author, type, date, url, categories
title author type date url categories
Git post-receive hook for Puppet control repo updates james post 2017-04-05T19:24:28+00:00 /2017/04/git-post-receive-hook-for-puppet-control-repo-updates/
Hacks
Tech

I made a fairly simple post-receive hook setup to automatically update my Puppet master when I push changes to my control repo. I keep the repo in gitolite, so I wanted to use a regular git hook rather than web hook magic (or even magicer Puppet Enterprise Code Manager magic).

My control repo itself is based on the puppetlabs control-repo on github. Essentially the idea is that every branch in the repo becomes a Puppet environment on your master, complete with automatically updated modules based on a Puppetfile. The r10k tool takes care of the heavy lifting here, and its documentation explains how it works in some detail.

But we don't have the patience for that! First, install r10k on your Puppet master and configure it to be able to yank your control repo in /etc/puppetlabs/r10k/r10k.yaml, something like this:

{{< highlight yaml >}} :cachedir: '/var/cache/r10k'

:sources: :myrepo: remote: 'gitolite3@git.example.com:puppet' basedir: '/etc/puppetlabs/code/environments' {{< / highlight >}}

Make sure you have SSH keys relationships set up so that you can pull the repo. Running r10k deploy environment --verbose info should let you see whats going on. Once it works, continue on.

Create an SSH key on your git server as the user that runs git. In my case on Debian, that user is gitolite3, but just wherever you have your repo running.

Copy the public key and install it in your puppet masters /root/.ssh/authorized_keys:

{{< highlight sh >}} command="/usr/local/sbin/puppet-update.sh" ssh-ed25519 AAASOMEKEYMATERIAL gitolite3@git.example.com {{< / highlight >}}

What's this puppet-update.sh, I hear you cry? Im glad you asked:

{{< highlight sh >}} #!/bin/bash

/usr/local/bin/r10k deploy environment $SSH_ORIGINAL_COMMAND {{< / highlight >}}

Pretty straightforward. Obviously youll want to point to wherever you have r10k installed, and make sure the script is executable. This setup takes whatever command you try to run over ssh with this key and appends it to /usr/local/bin/r10k deploy environment. The security conscious may want to do some other sanity checks too. I did say it was simple!

The meat of the matter is the post-receive hook itself. This should go on your git server, inside the puppet control repos hooks directory. In my case this is ~gitolite3/repositories/puppet.git/hooks/post-receive. It, too, should be executable.

{{< highlight sh >}} #!/bin/bash

post-receive hook to trigger r10k over ssh on updates to puppet control repo

Set SSHTARGET in ~/.config/puppet-update to eg:

root@puppet.example.com

Caveat: If you push a branch deletion and an updated Puppetfile in the same

push command, the updates to the Puppetfile will not be deployed. You'll have

to run manually or make another change to the Puppetfile.

CONFIGFILE=~/.config/puppet-update

if [ ! -r $CONFIGFILE ]; then echo "$CONFIGFILE doesn't exist, not updating" >&2 exit 1 fi

source $CONFIGFILE

update() { ssh $SSHTARGET -- --verbose info $@ if [ $? -ne 0 ]; then echo "WARNING: Update had errors: puppet may not be completely updated" >&2 exit 1 fi }

while read oldref newref refname do refname=$(basename $refname) updateargs= if echo ${newref} | egrep -vq '[^0]' then echo "Branch $refname is being deleted, updating all to trigger cleanup" update break fi

If this isn't a new branch and the Puppetfile has been changed, add --puppetfile

The new branch check is needed because diff won't work in that case; new

environments get Puppetfile deployed by r10k automatically (could also use ||)

if echo ${oldref} | egrep -q '[^0]' &&
git diff --name-only ${oldref}..${newref} | grep -q Puppetfile then updateargs="--puppetfile" fi update ${refname} ${updateargs} done {{< / highlight >}}

Like the comment says, youll want to make a ~/.config/puppet-update to tell it where your Puppet master lives.

{{< highlight sh >}} SSHTARGET=root@puppet.example.com {{< / highlight >}}

Now, make a commit to one of your branches and push it. You should see r10k working away in the git push output. Yay! Pushing any changes to any branches will update those environments. If you add or delete branches, it will deploy new environments or clean up. In a handy bit of time saving, it will only deploy the modules from the Puppetfile if the Puppetfile has actually been changed.

This works rather nicely for me, but Id be interested to hear how it works for other people, or what changes you made.