mirror of
https://github.com/IEEE-SB-Passau/pelican-deployment-system.git
synced 2017-09-06 16:35:38 +02:00
nice status page
This commit is contained in:
7
app.py
7
app.py
@@ -7,6 +7,7 @@ from operator import methodcaller
|
||||
from bottle import run, default_app
|
||||
from wsgiref.simple_server import make_server
|
||||
import pelican_deploy.webhookbottle
|
||||
import pelican_deploy.statusbottle
|
||||
import logging
|
||||
import atexit
|
||||
import sys
|
||||
@@ -48,6 +49,12 @@ def init_app(configpath):
|
||||
pelican_deploy.webhookbottle.set_github_secret(config.GITHUB_SECRET)
|
||||
default_app().mount("/hooks/", pelican_deploy.webhookbottle.app)
|
||||
|
||||
pelican_deploy.statusbottle.set_auth_basic_fn(getattr(config,
|
||||
"STATUS_AUTH_BASIC_FN",
|
||||
lambda us, pw: False))
|
||||
pelican_deploy.statusbottle.set_runners(**runners)
|
||||
default_app().mount("/status/", pelican_deploy.statusbottle.app)
|
||||
|
||||
return default_app()
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import logging
|
||||
from apscheduler.triggers.cron import CronTrigger
|
||||
from apscheduler.triggers.date import DateTrigger
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit("Not meant to be run directly!")
|
||||
@@ -59,9 +60,12 @@ RUNNERS = {
|
||||
# define crojobs as sequence of (runner, trigger) pairs, for cron triggers see
|
||||
# http://apscheduler.readthedocs.io/en/latest/modules/triggers/cron.html
|
||||
SCHEDULED_BUILD_JOBS = [
|
||||
("website_master", CronTrigger(minute="*/30"))
|
||||
("website_master", CronTrigger(minute="*/30")),
|
||||
("website_master", DateTrigger()) # once at start
|
||||
|
||||
]
|
||||
|
||||
|
||||
# username, password for /status/... subpages, accepts nothing if not set
|
||||
def STATUS_AUTH_BASIC_FN(user, passw):
|
||||
return user == "powerpoint" and passw == "karaoke"
|
||||
|
||||
|
||||
@@ -169,7 +169,8 @@ class DeploymentRunner:
|
||||
|
||||
def final_install(self):
|
||||
args = shlex.split(self.final_install_command)
|
||||
self.update_status(True, "Starting final_install")
|
||||
self.update_status(True, "Starting final_install",
|
||||
payload={"cmd": args})
|
||||
log.info("%s: Starting final_install `%s`", self.name, args)
|
||||
proc = Popen(args, stdout=PIPE, stderr=PIPE, universal_newlines=True,
|
||||
start_new_session=True)
|
||||
|
||||
97
pelican_deploy/statusbottle.py
Normal file
97
pelican_deploy/statusbottle.py
Normal file
@@ -0,0 +1,97 @@
|
||||
from bottle import route, template, request, post, Bottle, HTTPError,auth_basic
|
||||
from pprint import pformat
|
||||
from itertools import islice
|
||||
import logging
|
||||
import sys
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
app = Bottle()
|
||||
|
||||
|
||||
def _auth_basic_fn(us, pw):
|
||||
return app.config.get("auth_basic_fn", lambda us, pw: False)(us, pw)
|
||||
|
||||
def set_runners(**name_runner_mapping):
|
||||
app.config["deploy.runners"] = name_runner_mapping
|
||||
|
||||
def set_auth_basic_fn(fn):
|
||||
app.config["auth_basic_fn"] = fn
|
||||
|
||||
def _get_runner(name):
|
||||
try:
|
||||
runners = app.config["deploy.runners"]
|
||||
except KeyError as e:
|
||||
sys.exit("you have to call set_runners first")
|
||||
|
||||
return runners[name]
|
||||
|
||||
@app.route('/')
|
||||
def status():
|
||||
tpl = """
|
||||
<html>
|
||||
<h1>Runners</h1>
|
||||
<ul>
|
||||
% for r in runners:
|
||||
<%
|
||||
bs = r.build_status[-1] if r.build_status else None
|
||||
%>
|
||||
<li>
|
||||
% if bs:
|
||||
<%
|
||||
date = bs.date.strftime("%Y-%m-%d %H:%M:%S %Z%z")
|
||||
%>
|
||||
|
||||
<a href="{{r.name}}">{{r.name}}</a>:
|
||||
{{date}} - {{bs.msg}} - running: {{bs.running}} - ok: {{bs.ok}}
|
||||
% else:
|
||||
No job was ever running.
|
||||
% end
|
||||
</li>
|
||||
|
||||
% end
|
||||
</ul>
|
||||
</html>
|
||||
"""
|
||||
return template(tpl, runners=app.config["deploy.runners"].values())
|
||||
|
||||
@app.route('/<name>')
|
||||
@auth_basic(_auth_basic_fn)
|
||||
def runnerstatus(name):
|
||||
runner = _get_runner(name)
|
||||
rerun = "rerun" in request.query
|
||||
start = int(request.query.get("start", 0))
|
||||
end = int(request.query.get("end", 50))
|
||||
start = start if start >= 0 else 0
|
||||
end = end if end >= 0 else 0
|
||||
tpl = """
|
||||
<html>
|
||||
<h1>{{runner.name}} status events ({{start}} - {{end}}) --
|
||||
<a href={{runner.name}}/rerun>(re)start build</a></h1>
|
||||
<ul>
|
||||
% for bs in islice(reversed(bss),start,end):
|
||||
<%
|
||||
date = bs.date.strftime("%Y-%m-%d %H:%M:%S %Z%z")
|
||||
%>
|
||||
<li>{{date}} -- {{bs.msg}}
|
||||
<ul>
|
||||
<li>build still running: {{bs.running}}</li>
|
||||
<li>nothing went wrong: {{bs.ok}}</li>
|
||||
<li>message payload:<br>
|
||||
<pre>{{pformat(bs.payload, width=120)}}</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
% end
|
||||
</ul>
|
||||
</html>
|
||||
"""
|
||||
return template(tpl, runner=runner, bss=runner.build_status, islice=islice,
|
||||
pformat=pformat, start=start, end=end)
|
||||
|
||||
@auth_basic(_auth_basic_fn)
|
||||
@app.route('/<name>/rerun')
|
||||
def rerun(name):
|
||||
runner = _get_runner(name)
|
||||
runner.build(abort_running=True, ignore_pull_error=True)
|
||||
return "Restarted the build"
|
||||
Reference in New Issue
Block a user