diff options
Diffstat (limited to 'sitemodules/profiles/files/puppet_server')
-rwxr-xr-x | sitemodules/profiles/files/puppet_server/git-pull-hook | 94 | ||||
-rw-r--r-- | sitemodules/profiles/files/puppet_server/git-pull-hook.init.sh | 86 |
2 files changed, 180 insertions, 0 deletions
diff --git a/sitemodules/profiles/files/puppet_server/git-pull-hook b/sitemodules/profiles/files/puppet_server/git-pull-hook new file mode 100755 index 0000000..d8761f5 --- /dev/null +++ b/sitemodules/profiles/files/puppet_server/git-pull-hook @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 + +""" +This script takes care of updating the code in a directory by performing +git pull when triggered via an HTTP request to port 8000. + +The script needs the sshpass and git packages installed. + +Configuration is read from /etc/git-pull-hook.ini, ~/.git-pull-hook.ini and +a git-pull-hook.ini in the working directory in that order. +""" + +from configparser import ConfigParser +from http import HTTPStatus +from http.server import HTTPServer, BaseHTTPRequestHandler +import os +from subprocess import Popen, PIPE + +ENV_FOR_GIT = { + 'PATH': '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', +} + +TOKENS = [] +GIT_DIRECTORY = "" + + +def read_ini(): + global ENV_FOR_GIT, TOKENS, GIT_DIRECTORY + config = ConfigParser() + config.read(['/etc/git-pull-hook.ini', + os.path.expanduser('~/.git-pull-hook.ini'), + 'git-pull-hook.ini']) + ENV_FOR_GIT['SSHPASS'] = config['git-pull-hook']['ssh_passphrase'] + TOKENS = [token.strip() for token in + config['git-pull-hook']['tokens'].split(',')] + GIT_DIRECTORY = config['git-pull-hook']['git_directory'] + + +class GitHookRequestHandler(BaseHTTPRequestHandler): + """ + Custom HTTP request handler for updating a git repository when called + with a known authentication token in an "Authentication" HTTP header. + """ + + def _handle_pull(self): + try: + git_proc = Popen( + ['sshpass', '-e', '-P', 'passphrase', 'git', 'pull'], + env=ENV_FOR_GIT, cwd=GIT_DIRECTORY, stdout=PIPE, stderr=PIPE) + stdout, stderr = git_proc.communicate() + for line in stderr.decode('UTF-8').splitlines(): + self.log_error('git: %s', line) + for line in stdout.decode('UTF-8').splitlines(): + self.log_message('git: %s', line) + except Exception as e: + self.log_error("Could not pull changes for %s: %s", + GIT_DIRECTORY, e) + self.send_response(HTTPStatus.OK) + self.send_header('Content-Type', 'text/plain; charset=utf8') + self.flush_headers() + self.wfile.write(("updated %s" % GIT_DIRECTORY).encode('UTF-8')) + + # noinspection PyPep8Naming + def do_GET(self): + """ + Handle GET requests, requests to /health are allowed for every caller, + requests to / need a valid token in the "Authentication" HTTP header + and trigger a git pull in the configured directory. + """ + if self.path == '/': + if self.headers['Authentication'] in [token for token in TOKENS]: + self._handle_pull() + else: + self.send_response(HTTPStatus.UNAUTHORIZED) + self.flush_headers() + elif self.path == '/health': + self.send_response(HTTPStatus.OK) + self.flush_headers() + self.wfile.write(b"I'm healthy!") + else: + self.send_error(HTTPStatus.BAD_REQUEST) + self.flush_headers() + self.wfile.write(b"You requested something I do not understand") + + +def run(server_class=HTTPServer, handler_class=GitHookRequestHandler): + server_address = ('', 8000) + httpd = server_class(server_address, handler_class) + httpd.serve_forever() + + +if __name__ == '__main__': + read_ini() + run() diff --git a/sitemodules/profiles/files/puppet_server/git-pull-hook.init.sh b/sitemodules/profiles/files/puppet_server/git-pull-hook.init.sh new file mode 100644 index 0000000..7974a9f --- /dev/null +++ b/sitemodules/profiles/files/puppet_server/git-pull-hook.init.sh @@ -0,0 +1,86 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: git-pull-hook +# Required-Start: $remote_fs +# Required-Stop: $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: CAcert puppet git pull hook +# Description: CAcert puppet git pull hook +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +BASE=git-pull-hook + +GIT_PULL_HOOK=/usr/local/sbin/git-pull-hook +GIT_PULL_HOOK_PIDFILE=/var/run/$BASE.pid +GIT_PULL_HOOK_LOGFILE=/var/log/$BASE.log +GIT_PULL_HOOK_DESC="Puppet git pull hook" + +# Get lsb functions +. /lib/lsb/init-functions + +# Check git-pull-hook is present +if [ ! -x $GIT_PULL_HOOK ]; then + log_failure_msg "$GIT_PULL_HOOK not present or not executable" + exit 1 +fi + +fail_unless_root() { + if [ "$(id -u)" != '0' ]; then + log_failure_msg "$GIT_PULL_HOOK_DESC must be run as root" + exit 1 + fi +} + +case "$1" in + start) + fail_unless_root + + touch "$GIT_PULL_HOOK_LOGFILE" + chown root:adm "$GIT_PULL_HOOK_LOGFILE" + + log_begin_msg "Starting $GIT_PULL_HOOK_DESC: $GIT_PULL_HOOK" + start-stop-daemon --start --background --no-close \ + --exec "$GIT_PULL_HOOK" \ + --pidfile "$GIT_PULL_HOOK_PIDFILE" \ + --chdir "/" \ + --make-pidfile \ + >> "$GIT_PULL_HOOK_LOGFILE" 2>&1 + log_end_msg $? + ;; + + stop) + fail_unless_root + if [ -f "$GIT_PULL_HOOK_PIDFILE" ]; then + start-stop-daemon --stop --pidfile "$GIT_PULL_HOOK_PIDFILE" --retry 5 + log_end_msg $? + else + log_warning_msg "$GIT_PULL_HOOK_DESC already stopped - file $GIT_PULL_HOOK_PIDFILE not found." + fi + ;; + + restart) + fail_unless_root + git_pull_hook_pid=`cat "$GIT_PULL_HOOK_PIDFILE" 2> /dev/null` + [ -n "$git_pull_hook_pid" ] \ + && ps -p $git_pull_hook_pid > /dev/null 2>&1 \ + && $0 stop + $0 start + ;; + + force-reload) + fail_unless_root + $0 restart + ;; + + status) + status_of_proc -p "$GIT_PULL_HOOK_PIDFILE" "$GIT_PULL_HOOK" "$GIT_PULL_HOOK_DESC" + ;; + + *) + echo "Usage: service git-pull-hook {start|stop|restart|force-reload|status}" + exit 1 + ;; +esac |