summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ickweb/app.py120
-rw-r--r--views/builds.tpl19
-rw-r--r--views/index.tpl10
-rw-r--r--views/log.tpl13
-rw-r--r--views/login.tpl6
-rw-r--r--views/project.tpl13
-rw-r--r--views/projects.tpl19
7 files changed, 192 insertions, 8 deletions
diff --git a/ickweb/app.py b/ickweb/app.py
index f420098..42504e3 100644
--- a/ickweb/app.py
+++ b/ickweb/app.py
@@ -1,22 +1,140 @@
+import json
+
import bottle
+import requests
+import yaml
+
+API_URL = 'https://ci-prod-controller.vm.liw.fi'
COOKIE = 'ickweb1'
+TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJpc3MiOiJodHRwczovL2NpLXByb2QtY29udHJvbGxlci52bS5saXcuZmkiLCJhdWQiOiJhZG1pbiIsInN1YiI6IiIsInNjb3BlIjoidWFwaV92ZXJzaW9uX2dldCB1YXBpX3N0YXR1c19nZXQgdWFwaV9wcm9qZWN0c19pZF9zdGF0dXNfZ2V0IHVhcGlfcHJvamVjdHNfaWRfc3RhdHVzX3B1dCB1YXBpX2Jsb2JzX2lkX2dldCB1YXBpX25vdGlmeV9wb3N0IHVhcGlfcHJvamVjdHNfZ2V0IHVhcGlfcHJvamVjdHNfcG9zdCB1YXBpX3Byb2plY3RzX2lkX2dldCB1YXBpX3Byb2plY3RzX2lkX3B1dCB1YXBpX3Byb2plY3RzX2lkX2RlbGV0ZSB1YXBpX3BpcGVsaW5lc19nZXQgdWFwaV9waXBlbGluZXNfcG9zdCB1YXBpX3BpcGVsaW5lc19pZF9nZXQgdWFwaV9waXBlbGluZXNfaWRfcHV0IHVhcGlfcGlwZWxpbmVzX2lkX2RlbGV0ZSB1YXBpX3dvcmtlcnNfZ2V0IHVhcGlfd29ya2Vyc19pZF9nZXQgdWFwaV9idWlsZHNfZ2V0IHVhcGlfYnVpbGRzX2lkX2dldCB1YXBpX2xvZ3NfZ2V0IHVhcGlfbG9nc19pZF9nZXQiLCJleHAiOjE1MzMyOTkzMTIuNTgxNDMxfQ.MNd3eP6zmet7vLLGE_XXnfDZ1_flRb7qRw87qdKtZdx496NK3j-Aco0DuA5lKAeSFcK1yx01pnIH9maUO1uU5CTkOaVk2jlq1rr9LyRBaqyF1VI1qrTiWQ5QfLLCUXsH4zl4PC2g33BhcgLY74ua22P7QA3Rwnkp1xLP32VA6zN_Y4nrJDJhTFpRJXQk1Lo59hyOeiXnc2s26wXDASWMmqqNFJHf9i6uTvJQDrxjhiLjI7w3s_DxtBINJ6eWaZqbVvkYvQYVGBjqbDd3N1VOg4thoi_XXsF12Jrwo9LORT8pNygxlR40Lb-n5gDN9olTj0fVWZ9UMP-G1DQVrxZPf3rlMhRiPSmEvfLJJn7IF9fqwSnsseZYwvzjh6DafdFctuL9cNrCQt_UrlH7l0KPHC65GR1P4ejCVM5E5FC0Lx3KWhh6eagcnd47LNtQCxCMvl5Ffig58VBlRer4J3vTtpECkEryIC6rVurwUETlOGqai1LTJO_KOM3h9eP_RbAy0fogj8sE_UjIiEbp9IuodEaRwp3hGlX_qBkLZwKDMMhlhtZGX3dOyb4CiEoDxKnYQm7sE3Hu0KAE88QrpS8Lwt36q1SeD9srI5yfo31YXW__vBQ2AYlXF9efSpm0XuYIWHEaGX-7DF1ANAV0vMmyDxYsf32K4MQUEsF5nQ_fvao'
+
def create_app():
app = bottle.Bottle()
+ api = API(API_URL)
+ api.set_token(TOKEN)
+
+ @app.route('/favicon.ico')
+ def favicon():
+ raise bottle.HTTPError(status=404)
@app.route('/')
def root():
- if bottle.request.get_cookie(COOKIE) == 'yes':
+ if is_logged_in():
return bottle.template('index')
else:
return bottle.template('login')
+ def is_logged_in():
+ return True # FIXME
+
+ @app.route('/projects')
+ def projects():
+ projects = api.get_projects()
+ return bottle.template('projects', projects=projects)
+
+ @app.route('/projects/<name>')
+ def show_project(name):
+ project = api.get_project(name)
+ params = {
+ 'project': project,
+ 'as_yaml': as_yaml(project),
+ }
+ return bottle.template('project', **params)
+
+ @app.route('/builds')
+ def builds():
+ builds = api.get_builds()
+ return bottle.template('builds', builds=builds)
+
+ @app.route('/logs/<buildid:path>')
+ def show_log(buildid):
+ log = api.get_log(buildid)
+ return bottle.template('log', buildid=buildid, log=log)
+
@app.route('/callback')
def callback():
+ assert 0
+ print('/callback called')
+ print('URL args:', dict(bottle.request.query))
+
bottle.response.set_cookie(ICKWEB, 'yes')
bottle.redirect('/')
return app
+
+
+def as_yaml(obj):
+ return yaml.safe_dump(obj, indent=4, default_flow_style=False)
+
+
+def string_representer(dumper, data):
+ style = None
+ if '\n' in data:
+ style = '|'
+ return dumper.represent_scalar('tag:yaml.org,2002:str', data, style=style)
+
+
+yaml.add_representer(str, string_representer, Dumper=yaml.SafeDumper)
+
+
+class API:
+
+ def __init__(self, api_url):
+ self._url = api_url
+ self.set_token(None)
+
+ def set_token(self, token):
+ self._token = token
+
+ def get_token(self):
+ return self._token
+
+ def get_projects(self):
+ url = self.url('/projects')
+ headers = {
+ 'Authorization': 'Bearer {}'.format(self.get_token())
+ }
+ r = requests.get(url, headers=headers)
+ if not r.ok:
+ raise bottle.HTTPError(status=r.status_code)
+ obj = r.json()
+ return list(sorted(obj['projects'], key=lambda p: p['project']))
+
+ def get_project(self, name):
+ url = self.url('/projects', name)
+ print('get_project: url:', url)
+ headers = {
+ 'Authorization': 'Bearer {}'.format(self.get_token())
+ }
+ r = requests.get(url, headers=headers)
+ if not r.ok:
+ raise bottle.HTTPError(status=r.status_code)
+ return r.json()
+
+ def get_builds(self):
+ url = self.url('/builds')
+ headers = {
+ 'Authorization': 'Bearer {}'.format(self.get_token())
+ }
+ r = requests.get(url, headers=headers)
+ if not r.ok:
+ raise bottle.HTTPError(status=r.status_code)
+ obj = r.json()
+ return list(sorted(obj['builds'], key=lambda p: p['build_id']))
+
+ def get_log(self, buildid):
+ url = self.url('/logs', buildid)
+ headers = {
+ 'Authorization': 'Bearer {}'.format(self.get_token())
+ }
+ r = requests.get(url, headers=headers)
+ if not r.ok:
+ raise bottle.HTTPError(status=r.status_code)
+ return r.text
+
+ def url(self, *parts):
+ return '{}{}'.format(self._url, '/'.join(parts))
diff --git a/views/builds.tpl b/views/builds.tpl
new file mode 100644
index 0000000..2fd2d71
--- /dev/null
+++ b/views/builds.tpl
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="description" content="ickweb">
+ <meta name="author" content="The ick project">
+ <title>Ick builds</title>
+ </head>
+ <body>
+ <p>Builds:</p>
+ <ol>
+ % for build in builds:
+ <li>
+ <a href="{{build['log']}}">{{ build['log'] }}</a>
+ </li>
+ % end
+ </ol>
+ </body>
+</html>
diff --git a/views/index.tpl b/views/index.tpl
index 20ba140..01868ec 100644
--- a/views/index.tpl
+++ b/views/index.tpl
@@ -2,11 +2,13 @@
<html>
<head>
<meta charset="utf-8">
- <meta name="description" content="Facade content">
- <meta name="author" content="Qvarnlabs Ltd">
- <title>Facade content</title>
+ <meta name="description" content="ickweb">
+ <meta name="author" content="The ick project">
+ <title>Ick</title>
</head>
<body>
- <p>You ARE logged in. Well done!</p>
+ <p>You ARE logged in. Well done!</p>
+ <p><a href="/projects">Projects</p>
+ <p><a href="/builds">Builds</p>
</body>
</html>
diff --git a/views/log.tpl b/views/log.tpl
new file mode 100644
index 0000000..14c5235
--- /dev/null
+++ b/views/log.tpl
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="description" content="ickweb">
+ <meta name="author" content="The ick project">
+ <title>Ick build log {{ buildid }}</title>
+ </head>
+ <body>
+ <p>Build log {{buildid }}:</p>
+ <p><blockquote><pre>{{ log }}</pre></blockquote></p>
+ </body>
+</html>
diff --git a/views/login.tpl b/views/login.tpl
index f983ac0..66cc02e 100644
--- a/views/login.tpl
+++ b/views/login.tpl
@@ -2,12 +2,12 @@
<html>
<head>
<meta charset="utf-8">
- <meta name="description" content="Facade login">
- <meta name="author" content="Qvarnlabs Ltd">
+ <meta name="description" content="Ickweb login">
+ <meta name="author" content="Lars Wirzenius">
<title>Facade login</title>
</head>
<body>
<p>You are NOT logged in.</p>
- <p><a href="https://qvisqve-demo.h.qvarnlabs.eu/login">Login</a></p>
+ <p><a href="https://ci-prod-controller.vm.liw.fi/login">Login</a></p>
</body>
</html>
diff --git a/views/project.tpl b/views/project.tpl
new file mode 100644
index 0000000..a4428aa
--- /dev/null
+++ b/views/project.tpl
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="description" content="ickweb">
+ <meta name="author" content="The ick project">
+ <title>Ick project: {{ project['project'] }}</title>
+ </head>
+ <body>
+ <p>Project: {{ project['project'] }}</p>
+ <p><blockquote><pre>{{ as_yaml }}</pre></blockquote></p>
+ </body>
+</html>
diff --git a/views/projects.tpl b/views/projects.tpl
new file mode 100644
index 0000000..66feecf
--- /dev/null
+++ b/views/projects.tpl
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="description" content="ickweb">
+ <meta name="author" content="The ick project">
+ <title>Ick projects</title>
+ </head>
+ <body>
+ <p>Projects:</p>
+ <ol>
+ % for p in projects:
+ <li>
+ <a href="/projects/{{p['project']}}">{{ p['project'] }}</a>
+ </li>
+ % end
+ </ol>
+ </body>
+</html>