summaryrefslogtreecommitdiff
path: root/sitemodules/profiles/files/puppet_server/git-pull-hook
diff options
context:
space:
mode:
Diffstat (limited to 'sitemodules/profiles/files/puppet_server/git-pull-hook')
-rwxr-xr-xsitemodules/profiles/files/puppet_server/git-pull-hook94
1 files changed, 94 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()