Merge ~hyask/autopkgtest-cloud:skia/improve_browsing into autopkgtest-cloud:master

Proposed by Skia
Status: Merged
Merged at revision: df949e5544820f195b5094b402dd6d0f97a2ef8a
Proposed branch: ~hyask/autopkgtest-cloud:skia/improve_browsing
Merge into: autopkgtest-cloud:master
Diff against target: 372 lines (+90/-88)
10 files modified
charms/focal/autopkgtest-web/charmcraft.yaml (+1/-0)
charms/focal/autopkgtest-web/reactive/autopkgtest_web.py (+0/-14)
charms/focal/autopkgtest-web/webcontrol/browse.cgi (+25/-23)
charms/focal/autopkgtest-web/webcontrol/helpers/utils.py (+18/-2)
charms/focal/autopkgtest-web/webcontrol/static/bootstrap (+1/-0)
charms/focal/autopkgtest-web/webcontrol/templates/browse-admin.html (+4/-19)
charms/focal/autopkgtest-web/webcontrol/templates/browse-layout.html (+5/-5)
charms/focal/autopkgtest-web/webcontrol/templates/browse-package.html (+6/-0)
charms/focal/autopkgtest-web/webcontrol/templates/browse-running.html (+4/-25)
charms/focal/autopkgtest-web/webcontrol/templates/macros.html (+26/-0)
Reviewer Review Type Date Requested Status
Tim Andersson Approve
Review via email: mp+461022@code.launchpad.net

Description of the change

A bit of refactor to bring the feature of displaying currently running jobs on each package's page.

To post a comment you must log in.
Revision history for this message
Tim Andersson (andersson123) wrote :

Looks like I accidentally merged this :)

Revision history for this message
Tim Andersson (andersson123) wrote :

still going to review though

Revision history for this message
Tim Andersson (andersson123) wrote :

lbjsbootstrap changes to be tested in staging before deployment

Revision history for this message
Tim Andersson (andersson123) wrote :

Skia to implement new Exceptions in helpers/exceptions.py for the new get_running_jobs function.

Also implement all exception handler in browse.cgi for extendability.

Revision history for this message
Tim Andersson (andersson123) wrote :

LGTM ig

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/charms/focal/autopkgtest-web/charmcraft.yaml b/charms/focal/autopkgtest-web/charmcraft.yaml
index 93c0816..546437f 100644
--- a/charms/focal/autopkgtest-web/charmcraft.yaml
+++ b/charms/focal/autopkgtest-web/charmcraft.yaml
@@ -6,6 +6,7 @@ parts:
6 build-snaps: [charm]6 build-snaps: [charm]
7 build-packages:7 build-packages:
8 - libjs-jquery8 - libjs-jquery
9 - libjs-bootstrap
9 - python3-dev10 - python3-dev
10bases:11bases:
11 - build-on:12 - build-on:
diff --git a/charms/focal/autopkgtest-web/reactive/autopkgtest_web.py b/charms/focal/autopkgtest-web/reactive/autopkgtest_web.py
index e1be1a2..6920fc1 100644
--- a/charms/focal/autopkgtest-web/reactive/autopkgtest_web.py
+++ b/charms/focal/autopkgtest-web/reactive/autopkgtest_web.py
@@ -338,20 +338,6 @@ def clear_github_status_credentials():
338 pass338 pass
339339
340340
341@when_not("autopkgtest-web.bootstrap-symlinked")
342def symlink_bootstrap():
343 try:
344 os.symlink(
345 os.path.join(
346 os.path.sep, "usr", "share", "javascript", "bootstrap"
347 ),
348 os.path.join(charm_dir(), "webcontrol", "static", "bootstrap"),
349 )
350 set_flag("autopkgtest-web.bootstrap-symlinked")
351 except FileExistsError:
352 pass
353
354
355@when_not("autopkgtest-web.runtime-dir-created")341@when_not("autopkgtest-web.runtime-dir-created")
356def make_runtime_tmpfiles():342def make_runtime_tmpfiles():
357 with open("/etc/tmpfiles.d/autopkgtest-web-runtime.conf", "w") as r:343 with open("/etc/tmpfiles.d/autopkgtest-web-runtime.conf", "w") as r:
diff --git a/charms/focal/autopkgtest-web/webcontrol/browse.cgi b/charms/focal/autopkgtest-web/webcontrol/browse.cgi
index f39b30f..f6be794 100755
--- a/charms/focal/autopkgtest-web/webcontrol/browse.cgi
+++ b/charms/focal/autopkgtest-web/webcontrol/browse.cgi
@@ -10,9 +10,9 @@ import sqlite3
10from collections import OrderedDict10from collections import OrderedDict
11from wsgiref.handlers import CGIHandler11from wsgiref.handlers import CGIHandler
1212
13import distro_info
14import flask13import flask
15from helpers.admin import select_abnormally_long_jobs14from helpers.admin import select_abnormally_long_jobs
15from helpers.utils import get_all_releases, get_supported_releases
16from werkzeug.middleware.proxy_fix import ProxyFix16from werkzeug.middleware.proxy_fix import ProxyFix
1717
18app = flask.Flask("browse")18app = flask.Flask("browse")
@@ -20,13 +20,11 @@ app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1)
20db_con = None20db_con = None
21swift_container_url = None21swift_container_url = None
2222
23UDI = distro_info.UbuntuDistroInfo()23ALL_UBUNTU_RELEASES = get_all_releases()
24ALL_UBUNTU_RELEASES = UDI.all24SUPPORTED_UBUNTU_RELEASES = get_supported_releases()
25SUPPORTED_UBUNTU_RELEASES = sorted(
26 set(UDI.supported() + UDI.supported_esm()), key=ALL_UBUNTU_RELEASES.index
27)
28
29INDEXED_PACKAGES_FP = ""25INDEXED_PACKAGES_FP = ""
26AMQP_QUEUE_CACHE = "/var/lib/cache-amqp/queued.json"
27RUNNING_CACHE = "/run/amqp-status-collector/running.json"
3028
3129
32def init_config():30def init_config():
@@ -60,6 +58,16 @@ def get_test_id(release, arch, src):
60 return None58 return None
6159
6260
61def get_running_jobs():
62 try:
63 with open(RUNNING_CACHE) as f:
64 # package -> runhash -> release -> arch -> (params, duration, logtail)
65 running_info = json.load(f)
66 except FileNotFoundError:
67 running_info = {}
68 return running_info
69
70
63def render(template, code=200, **kwargs):71def render(template, code=200, **kwargs):
64 # sort the values passed in, so that releases are in the right order72 # sort the values passed in, so that releases are in the right order
65 try:73 try:
@@ -81,7 +89,7 @@ def render(template, code=200, **kwargs):
81 flask.render_template(89 flask.render_template(
82 template,90 template,
83 base_url=flask.url_for("index_root"),91 base_url=flask.url_for("index_root"),
84 static_url=flask.url_for("static", filename="/"),92 static_url=flask.url_for("static", filename=""),
85 **kwargs93 **kwargs
86 ),94 ),
87 code,95 code,
@@ -147,7 +155,7 @@ def get_queue_info():
147 Return (releases, arches, context -> release -> arch -> (queue_size, [requests])).155 Return (releases, arches, context -> release -> arch -> (queue_size, [requests])).
148 """156 """
149157
150 with open("/var/lib/cache-amqp/queued.json", "r") as json_file:158 with open(AMQP_QUEUE_CACHE, "r") as json_file:
151 queue_info_j = json.load(json_file)159 queue_info_j = json.load(json_file)
152160
153 arches = queue_info_j["arches"]161 arches = queue_info_j["arches"]
@@ -268,6 +276,10 @@ def package_overview(package, _=None):
268 arches.add(row[3])276 arches.add(row[3])
269 results.setdefault(row[2], {})[row[3]] = human_exitcode(row[1])277 results.setdefault(row[2], {})[row[3]] = human_exitcode(row[1])
270278
279 running_info = dict(
280 (k, v) for (k, v) in get_running_jobs().items() if k == package
281 )
282
271 return render(283 return render(
272 "browse-package.html",284 "browse-package.html",
273 package=package,285 package=package,
@@ -280,6 +292,7 @@ def package_overview(package, _=None):
280 arches=sorted(arches),292 arches=sorted(arches),
281 results=results,293 results=results,
282 title_suffix="- %s" % package,294 title_suffix="- %s" % package,
295 running=running_info,
283 )296 )
284297
285298
@@ -371,12 +384,7 @@ def running():
371 a384 a
372 ] = queue_length385 ] = queue_length
373386
374 try:387 running_info = get_running_jobs()
375 with open("/run/amqp-status-collector/running.json") as f:
376 # package -> runhash -> release -> arch -> (params, duration, logtail)
377 running_info = json.load(f)
378 except FileNotFoundError:
379 running_info = {}
380388
381 return render(389 return render(
382 "browse-running.html",390 "browse-running.html",
@@ -391,13 +399,7 @@ def running():
391399
392@app.route("/admin")400@app.route("/admin")
393def admin():401def admin():
394 try:402 running_info = get_running_jobs()
395 with open("/run/amqp-status-collector/running.json") as f:
396 # package -> runhash -> release -> arch -> (params, duration, logtail)
397 running_info = json.load(f)
398 except FileNotFoundError as exc:
399 running_info = {}
400 raise FileNotFoundError("running.json doesn't exist!") from exc
401 pruned_running_info = select_abnormally_long_jobs(403 pruned_running_info = select_abnormally_long_jobs(
402 running_info, get_test_id=get_test_id, db_con=db_con404 running_info, get_test_id=get_test_id, db_con=db_con
403 )405 )
@@ -439,7 +441,7 @@ def queues_json():
439441
440@app.route("/queued.json")442@app.route("/queued.json")
441def return_queued_exactly():443def return_queued_exactly():
442 with open("/var/lib/cache-amqp/queued.json") as json_file:444 with open(AMQP_QUEUE_CACHE) as json_file:
443 queue_info = json.load(json_file)445 queue_info = json.load(json_file)
444 return queue_info446 return queue_info
445447
diff --git a/charms/focal/autopkgtest-web/webcontrol/helpers/utils.py b/charms/focal/autopkgtest-web/webcontrol/helpers/utils.py
index 58a9514..12d93b5 100644
--- a/charms/focal/autopkgtest-web/webcontrol/helpers/utils.py
+++ b/charms/focal/autopkgtest-web/webcontrol/helpers/utils.py
@@ -8,6 +8,22 @@ import random
8import sqlite38import sqlite3
9import time9import time
1010
11import distro_info
12
13
14def get_all_releases():
15 udi = distro_info.UbuntuDistroInfo()
16 return udi.all
17
18
19def get_supported_releases():
20 udi = distro_info.UbuntuDistroInfo()
21 all_ubuntu_releases = get_all_releases()
22 return sorted(
23 set(udi.supported() + udi.supported_esm()),
24 key=all_ubuntu_releases.index,
25 )
26
1127
12def setup_key(app, path):28def setup_key(app, path):
13 """Create or load app.secret_key for cookie encryption."""29 """Create or load app.secret_key for cookie encryption."""
@@ -22,10 +38,10 @@ def setup_key(app, path):
22 app.secret_key = key38 app.secret_key = key
2339
2440
25def init_db(path):41def init_db(path, **kwargs):
26 """Create DB if it does not exist, and connect to it"""42 """Create DB if it does not exist, and connect to it"""
2743
28 db = sqlite3.connect(path)44 db = sqlite3.connect(path, **kwargs)
29 c = db.cursor()45 c = db.cursor()
30 try:46 try:
31 c.execute("PRAGMA journal_mode = WAL")47 c.execute("PRAGMA journal_mode = WAL")
diff --git a/charms/focal/autopkgtest-web/webcontrol/static/bootstrap b/charms/focal/autopkgtest-web/webcontrol/static/bootstrap
32new file mode 12000048new file mode 120000
index 0000000..fe0f86b
--- /dev/null
+++ b/charms/focal/autopkgtest-web/webcontrol/static/bootstrap
@@ -0,0 +1 @@
1/usr/share/javascript/bootstrap
0\ No newline at end of file2\ No newline at end of file
diff --git a/charms/focal/autopkgtest-web/webcontrol/templates/browse-admin.html b/charms/focal/autopkgtest-web/webcontrol/templates/browse-admin.html
index 5bc2459..266f584 100644
--- a/charms/focal/autopkgtest-web/webcontrol/templates/browse-admin.html
+++ b/charms/focal/autopkgtest-web/webcontrol/templates/browse-admin.html
@@ -1,29 +1,14 @@
1{% extends "browse-layout.html" %}1{% extends "browse-layout.html" %}
2{% import "macros.html" as macros %}
3
2{% block content %}4{% block content %}
3 <h1 class="page-header">Admin</h1>5 <h1 class="page-header">Admin</h1>
4 <p>Click on the package name to jump to the tests of the package for all arches/releases.</p>6 <p>Click on the package name to jump to the tests of the package for all arches/releases.</p>
5 <p>This page is simply a bunch of heuristics filtering all running jobs to try to get the problematic ones. Feel free to come help improve the heuristics <a href="https://code.launchpad.net/~ubuntu-release/autopkgtest-cloud/+git/autopkgtest-cloud/+ref/master">here.</a></p>7 <p>This page is simply a bunch of heuristics filtering all running jobs to try to get the problematic ones. Feel free to come help improve the heuristics <a href="https://code.launchpad.net/~ubuntu-release/autopkgtest-cloud/+git/autopkgtest-cloud/+ref/master">here.</a></p>
68
7 <!-- Running tests -->9 <!-- Running tests -->
8 {% for p in running|sort %}10 {% for p, info in running.items()|sort %}
9 <h2 id="pkg-{{p}}"><a href="/packages/{{p}}">{{p}}</a></h2>11 {{ macros.display_running_job(p, info) }}
10 {% for runhash, relinfo in running[p].items() %}
11 {% for release, archinfo in relinfo.items() %}
12 {% for arch, (params, duration, logtail) in archinfo.items() %}
13 <table class="table-condensed">
14 <tr><th>Release:</th><td>{{release}}</td></tr>
15 <tr><th>Architecture:</th><td>{{arch}}</td></tr>
16 {% for param, v in params.items() %}
17 <tr><th>{{param|capitalize}}:</th><td>{{v}}</td></tr>
18 {% endfor %}
19 <tr><th>Running for:</th><td>{{duration//3600 }}h {{duration % 3600//60}}m {{duration % 60}}s</td></tr>
20 </table>
21 <pre>
22{{logtail}}
23 </pre>
24 {% endfor %}
25 {% endfor %}
26 {% endfor %}
27 {% endfor %}12 {% endfor %}
2813
29{% endblock %}14{% endblock %}
diff --git a/charms/focal/autopkgtest-web/webcontrol/templates/browse-layout.html b/charms/focal/autopkgtest-web/webcontrol/templates/browse-layout.html
index 0f90de3..c91457d 100644
--- a/charms/focal/autopkgtest-web/webcontrol/templates/browse-layout.html
+++ b/charms/focal/autopkgtest-web/webcontrol/templates/browse-layout.html
@@ -6,9 +6,9 @@
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <title>Ubuntu Autopkgtest Results {{title_suffix}}</title>7 <title>Ubuntu Autopkgtest Results {{title_suffix}}</title>
8 <!-- <link rel="icon" type="image/png" href="/debian.png"/> -->8 <!-- <link rel="icon" type="image/png" href="/debian.png"/> -->
9 <link rel="stylesheet" type="text/css" href="{{static_url}}/bootstrap/css/bootstrap.css"/>9 <link rel="stylesheet" type="text/css" href="{{static_url}}bootstrap/css/bootstrap.css"/>
10 <link rel="stylesheet" type="text/css" href="{{static_url}}/bootstrap/css/bootstrap-theme.css"/>10 <link rel="stylesheet" type="text/css" href="{{static_url}}bootstrap/css/bootstrap-theme.css"/>
11 <link rel="stylesheet" type="text/css" href="{{static_url}}/style.css"/>11 <link rel="stylesheet" type="text/css" href="{{static_url}}style.css"/>
12 </head>12 </head>
13 <body>13 <body>
14 <div id='wrap'>14 <div id='wrap'>
@@ -44,7 +44,7 @@
44{% block content %}{% endblock %}44{% block content %}{% endblock %}
45</div>45</div>
4646
47 <script type="text/javascript" src="{{static_url}}/jquery/jquery.min.js"></script>47 <script type="text/javascript" src="{{static_url}}jquery/jquery.min.js"></script>
48 <script type="text/javascript" src="{{static_url}}/bootstrap/js/bootstrap.min.js"></script>48 <script type="text/javascript" src="{{static_url}}bootstrap/js/bootstrap.min.js"></script>
49 </body>49 </body>
50</html>50</html>
diff --git a/charms/focal/autopkgtest-web/webcontrol/templates/browse-package.html b/charms/focal/autopkgtest-web/webcontrol/templates/browse-package.html
index 3ac81c3..fb12afa 100644
--- a/charms/focal/autopkgtest-web/webcontrol/templates/browse-package.html
+++ b/charms/focal/autopkgtest-web/webcontrol/templates/browse-package.html
@@ -1,4 +1,6 @@
1{% extends "browse-layout.html" %}1{% extends "browse-layout.html" %}
2{% import "macros.html" as macros %}
3
2{% block content %}4{% block content %}
3 <h2>{{package}}</h2>5 <h2>{{package}}</h2>
46
@@ -17,4 +19,8 @@
17 </tr>19 </tr>
18 {% endfor %}20 {% endfor %}
19 </table>21 </table>
22
23 {% for p, info in running.items()|sort %}
24 {{ macros.display_running_job(p, info) }}
25 {% endfor %}
20{% endblock %}26{% endblock %}
diff --git a/charms/focal/autopkgtest-web/webcontrol/templates/browse-running.html b/charms/focal/autopkgtest-web/webcontrol/templates/browse-running.html
index 3711b97..53ae2f9 100644
--- a/charms/focal/autopkgtest-web/webcontrol/templates/browse-running.html
+++ b/charms/focal/autopkgtest-web/webcontrol/templates/browse-running.html
@@ -1,4 +1,6 @@
1{% extends "browse-layout.html" %}1{% extends "browse-layout.html" %}
2{% import "macros.html" as macros %}
3
2{% block content %}4{% block content %}
3 <h1 class="page-header">Currently running tests</h1>5 <h1 class="page-header">Currently running tests</h1>
4 <p>Click on the package name to jump to the currently running tests of that package.</p>6 <p>Click on the package name to jump to the currently running tests of that package.</p>
@@ -36,31 +38,8 @@
36 {% endfor %}38 {% endfor %}
3739
38 <!-- Running tests -->40 <!-- Running tests -->
39 {% for p in running|sort %}41 {% for p, info in running.items()|sort %}
40 <h2 id="pkg-{{p}}"><a href="/packages/{{p}}">{{p}}</a></h2>42 {{ macros.display_running_job(p, info) }}
41 {% for runhash, relinfo in running[p].items() %}
42 {% for release, archinfo in relinfo.items() %}
43 {% for arch, (params, duration, logtail) in archinfo.items() %}
44 <table class="table-condensed">
45 <tr><th>Release:</th><td>{{release}}</td></tr>
46 <tr><th>Architecture:</th><td>{{arch}}</td></tr>
47 {% for param, v in params.items() %}
48 {% if param == "requester" %}
49 <tr><th>{{param|capitalize}}:</th><td><a href="https://launchpad.net/~{{v}}">{{v}}</a></td></tr>
50 {% elif param == "uuid" %}
51 <tr><th>{{param|capitalize}}:</th><td>{{v}}</td></tr>
52 {% else %}
53 <tr><th>{{param|capitalize}}:</th><td>{{v}}</td></tr>
54 {% endif %}
55 {% endfor %}
56 <tr><th>Running for:</th><td>{{duration//3600 }}h {{duration % 3600//60}}m {{duration % 60}}s</td></tr>
57 </table>
58 <pre>
59{{logtail}}
60 </pre>
61 {% endfor %}
62 {% endfor %}
63 {% endfor %}
64 {% endfor %}43 {% endfor %}
6544
66 <!-- queue contents -->45 <!-- queue contents -->
diff --git a/charms/focal/autopkgtest-web/webcontrol/templates/macros.html b/charms/focal/autopkgtest-web/webcontrol/templates/macros.html
67new file mode 10064446new file mode 100644
index 0000000..7d43d20
--- /dev/null
+++ b/charms/focal/autopkgtest-web/webcontrol/templates/macros.html
@@ -0,0 +1,26 @@
1{% macro display_running_job(package, info) -%}
2<h2 id="pkg-{{ package }}"><a href="/packages/{{ package }}">{{ package }}</a></h2>
3 {% for runhash, relinfo in info.items() %}
4 {% for release, archinfo in relinfo.items() %}
5 {% for arch, (params, duration, logtail) in archinfo.items() %}
6 <table class="table-condensed">
7 <tr><th>Release:</th><td>{{ release }}</td></tr>
8 <tr><th>Architecture:</th><td>{{ arch }}</td></tr>
9 {% for param, v in params.items() %}
10 {% if param == "requester" %}
11 <tr><th>{{ param|capitalize }}:</th><td><a href="https://launchpad.net/~{{ v }}">{{ v }}</a></td></tr>
12 {% elif param == "uuid" %}
13 <tr><th>{{ param|upper }}:</th><td>{{ v }}</td></tr>
14 {% else %}
15 <tr><th>{{ param|capitalize }}:</th><td>{{ v }}</td></tr>
16 {% endif %}
17 {% endfor %}
18 <tr><th>Running for:</th><td>{{ duration//3600 }}h {{ duration % 3600//60 }}m {{ duration % 60 }}s ({{ duration }}s)</td></tr>
19 </table>
20 <pre>
21{{ logtail }}
22 </pre>
23 {% endfor %}
24 {% endfor %}
25 {% endfor %}
26{%- endmacro %}

Subscribers

People subscribed via source and target branches