Apply puppet automatically

Posted 03.01.2013

I recently started using github web interface as editor for my puppet configuration. I wanted to be able to push a new configuration without doing it manually, as I do not have a puppet master I wanted to try using Github hooks as in the Github lamp code. I have the puppet-repo cloned to /puppet/ and the main manifest is in /puppet/manifests/site.pp. The code below is the script. It checks the payload from Github and will only apply the configuration if changes are pushed to the master branch. A GET request would simply get a 404.

from fabric.api import local, lcd
import web, json

urls = (
    '/', 'GithubHook',

render = web.template.render('.')

class GithubHook:
    def POST(self):
        data = json.loads(web.input().payload)
        if 'ref' in data:
            if data['ref'] == 'refs/heads/master':
              with lcd('/puppet/'):
                    local('git pull origin master')
                    local('puppet apply /puppet/manifests/site.pp')
                    print "applied puppet"
            print "ref: %s" % data['ref']
            print "no ref"
        return ""

    def GET(self):
        raise web.notfound()

if __name__ == "__main__":
    app = web.application(urls, globals())

application = web.application(urls, globals(), True).wsgifunc()

I running this with uWSGI and Nginx in front. To make the setup a little more secure I added deny all and allow to Github's IP-addresses.

server {
    listen 80;

    access_log /var/log/nginx/puppet_apply.access.log;
    error_log /var/log/nginx/puppet_apply.error.log;

    location / {
        deny all;

        proxy_redirect     off;

        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

    location = /favicon.ico {
        access_log off;
        log_not_found off;
        return 204;

The script is in /home/web/puppet_apply/ The ini-file used by uWSGI is below.

chdir = /home/web/puppet_apply
virtualenv = /home/web/puppet_apply/venv
pythonpath = /home/web/puppet_apply
procname-prefix = puppet_apply
wsgi-file = /home/web/puppet_apply/
http-socket =
master = True
processes = 1