This repository has been archived by the owner on Nov 12, 2017. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hooks.py
173 lines (140 loc) · 4.66 KB
/
hooks.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
from flask import Flask, request
import os
import subprocess as sp
import xmlrpc.client
import requests
import json
app = Flask(__name__)
services = [
"cesi",
"codegolf",
]
with open("template.html") as f:
template = f.read()
__all__ = [
"main",
]
def slack_msg(message, channel="#projects", icon=":fc:", username="hookbot"):
requests.post(os.environ.get("SLACK_HOOK_URL"), json.dumps({
"username": username,
"icon_emoji": icon,
"text": message,
"channel": channel,
}))
def gitmsg_format(git_result):
if git_result[1] == 0:
gitmsg = "Git pull successful"
if "Already up-to-date" in git_result[0]:
gitmsg += ". No new commits"
elif len(git_result) == 3:
gitmsg += ". Last commit: " + git_result[2]
else:
gitmsg = "Git pull had non-zero exit status"
return gitmsg
def supervisormsg_format(sup_result):
if len(sup_result) == 3:
supmsg = "Service status: " + sup_result[-1]["statename"]
elif len(sup_result) == 2:
supmsg = "Error starting process"
else:
supmsg = "Error stopping process"
return supmsg
def slack_post(service, git_pull_result, supervisor_result):
gitmsg = gitmsg_format(git_pull_result)
supmsg = supervisormsg_format(supervisor_result)
slack_msg(
"Hook for {} triggered. {}. {}.".format(service, gitmsg, supmsg),
channel="#codegolf" if service == "codegolf" else "#projects",
)
def supervisor_restart(service):
server = xmlrpc.client.ServerProxy(
'http://{username}:{password}@localhost:9001/RPC2'.format(
username=os.environ.get("SUPERVISOR_USER", "user"),
password=os.environ.get("SUPERVISOR_PASS", "123"),
)
)
# if error in stop, doesn't try and start - short circuited booleans
res = server.supervisor.stopProcess(service),
if res[-1]:
res += server.supervisor.startProcess(service),
if res[-1]:
res += server.supervisor.getProcessInfo(service),
return res
def git_pull_in_dir(service):
"""
A service name should match with both its name in supervisor and its /srv/*
path.
"""
previous_cwd = os.getcwd()
os.chdir("/srv/" + service)
try:
out = sp.check_output(["git", "pull"], timeout=120).decode('utf-8')
code = 0
except sp.CalledProcessError as e:
out = e.output.decode('utf-8')
out += "\nErrored out with code " + str(e.returncode) + "."
code = e.returncode
out += "\n"
logmsg = "Error checking logs"
if code == 0:
try:
logmsg = sp.check_output(["git", "log", "-n1", "--oneline"]).decode('utf-8').strip()
except sp.CalledProcessError as e:
logmsg = "Error checking logs"
os.chdir(previous_cwd)
return out, code, logmsg
def wrap(service, queue):
def worker_fn():
git = git_pull_in_dir(service)
sup = supervisor_restart(service)
msg = template.format(
git[0],
sup[-1],
)
slack_post(service, git, sup)
return msg
worker_fn.__name__ = service + "_worker"
def resp():
queue.put(worker_fn)
return "Hook started"
resp.__name__ = service + "_update"
return resp
def add_hookbot(app, queue):
def worker_fn():
git = git_pull_in_dir("hooks")
msg = "Someone triggered my reset switch! "
msg += "There was a git pull with status code {}.".format(git[1])
msg += " Can someone please restart me now? http://cesi.uqcs.org.au."
msg += " (<@U0D0J0HM0>)" # (@trm)
slack_hooks = os.environ.get("SLACK_HOOK_URL")
if slack_hooks:
requests.post(slack_hooks, json.dumps({
"username": "hookbot",
"icon_emoji": ":fc:",
"text": msg,
"channel": "#projects",
}))
supervisor_restart("hooks")
worker_fn.__name__ = "hooks_worker"
@app.route("/hooks", methods=["GET", "POST"])
def hooks_update():
queue.put(worker_fn)
return "Hook started"
def task_queue(queue):
print("Starting task queue")
for item in iter(queue.get, None):
print(item.__name__)
item()
print("Task queue finished")
import threading
from queue import Queue
queue = Queue()
queuthread = threading.Thread(target=task_queue, args=(queue,))
for service in services:
app.route('/'+service, methods=["GET", "POST"])(wrap(service, queue))
add_hookbot(app, queue)
def main(port, host):
queuthread.start()
app.run(port=port, host=host)
queue.put(None)
queuthread.join()