1
+ #! /usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """Automatic Docker Deployment via Webhooks"""
5
+
6
+ import json
7
+ import os
8
+ from subprocess import Popen
9
+ from argparse import ArgumentParser , ArgumentDefaultsHelpFormatter
10
+ try :
11
+ # For Python 3.0 and later
12
+ from http .server import HTTPServer
13
+ from http .server import BaseHTTPRequestHandler
14
+ except ImportError :
15
+ # Fall back to Python 2
16
+ from BaseHTTPServer import BaseHTTPRequestHandler
17
+ from BaseHTTPServer import HTTPServer as HTTPServer
18
+ import sys
19
+ import logging
20
+ import requests
21
+
22
+ logging .basicConfig (format = '%(asctime)s %(levelname)s %(message)s' ,
23
+ level = logging .DEBUG ,
24
+ stream = sys .stdout )
25
+
26
+
27
+ class RequestHandler (BaseHTTPRequestHandler ):
28
+ """A POST request handler which expects a token in its path."""
29
+ def do_POST (self ):
30
+ logging .info ("Path: %s" , self .path )
31
+ header_length = int (self .headers .getheader ('content-length' , "0" ))
32
+ json_payload = self .rfile .read (header_length )
33
+ env = dict (os .environ )
34
+ json_params = {}
35
+ if len (json_payload ) > 0 :
36
+ json_params = json .loads (json_payload )
37
+ env .update (('REPOSITORY_' + var .upper (), str (val ))
38
+ for var , val in json_params ['repository' ].items ())
39
+
40
+ # Check if the secret URL was called
41
+ if args .token in self .path :
42
+ logging .info ("Start executing '%s'" % args .cmd )
43
+ try :
44
+ Popen (args .cmd , env = env ).wait ()
45
+ self .send_response (200 , "OK" )
46
+ if 'callback_url' in json_params :
47
+ # Make a callback to Docker Hub
48
+ data = {'state' : 'success' }
49
+ headers = {'Content-type' : 'application/json' ,
50
+ 'Accept' : 'text/plain' }
51
+ requests .post (json_params ['callback_url' ],
52
+ data = json .dumps (data ),
53
+ headers = headers )
54
+ except OSError as err :
55
+ self .send_response (500 , "OSError" )
56
+ logging .error ("You probably didn't use 'sh ./script.sh'." )
57
+ logging .error (err )
58
+ if 'callback_url' in json_params :
59
+ # Make a callback to Docker Hub
60
+ data = {'state' : 'failure' ,
61
+ 'description' : str (err )}
62
+ headers = {'Content-type' : 'application/json' ,
63
+ 'Accept' : 'text/plain' }
64
+ requests .post (json_params ['callback_url' ],
65
+ data = json .dumps (data ),
66
+ headers = headers )
67
+ else :
68
+ self .send_response (401 , "Not authorized" )
69
+ self .end_headers ()
70
+
71
+
72
+ def get_parser ():
73
+ """Get a command line parser for docker-hook."""
74
+ parser = ArgumentParser (description = __doc__ ,
75
+ formatter_class = ArgumentDefaultsHelpFormatter )
76
+
77
+ parser .add_argument ("-t" , "--token" ,
78
+ dest = "token" ,
79
+ required = True ,
80
+ help = ("Secure auth token (can be choosen "
81
+ "arbitrarily)" ))
82
+ parser .add_argument ("-c" , "--cmd" ,
83
+ dest = "cmd" ,
84
+ required = True ,
85
+ nargs = "*" ,
86
+ help = "Command to execute when triggered" )
87
+ parser .add_argument ("--addr" ,
88
+ dest = "addr" ,
89
+ default = "0.0.0.0" ,
90
+ help = "address where it listens" )
91
+ parser .add_argument ("--port" ,
92
+ dest = "port" ,
93
+ type = int ,
94
+ default = 8555 ,
95
+ metavar = "PORT" ,
96
+ help = "port where it listens" )
97
+ return parser
98
+
99
+
100
+ def main (addr , port ):
101
+ """Start a HTTPServer which waits for requests."""
102
+ httpd = HTTPServer ((addr , port ), RequestHandler )
103
+ httpd .serve_forever ()
104
+
105
+ if __name__ == '__main__' :
106
+ parser = get_parser ()
107
+ if len (sys .argv ) == 1 :
108
+ parser .print_help ()
109
+ sys .exit (1 )
110
+ args = parser .parse_args ()
111
+ main (args .addr , args .port )
0 commit comments