dashboard/app: add admin page
Add /admin page and move logs, jobs, manager onto it.
The main page is too overloaded and takes too long to load.
We need to start splitting it. This is a first step.
diff --git a/dashboard/app/admin.html b/dashboard/app/admin.html
new file mode 100644
index 0000000..09fd675
--- /dev/null
+++ b/dashboard/app/admin.html
@@ -0,0 +1,80 @@
+{{/*
+Copyright 2019 syzkaller project authors. All rights reserved.
+Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+Main page.
+*/}}
+
+<!doctype html>
+<html>
+<head>
+ {{template "head" .Header}}
+ <title>syzbot</title>
+</head>
+<body>
+ {{template "header" .Header}}
+
+ <a class="plain" href="#log"><div id="log"><b>Error log:</b></div></a>
+ <textarea id="log_textarea" readonly rows="20" wrap=off>{{printf "%s" .Log}}</textarea>
+ <script>
+ var textarea = document.getElementById("log_textarea");
+ textarea.scrollTop = textarea.scrollHeight;
+ </script>
+ <br><br>
+
+ {{template "manager_list" $.Managers}}
+
+ <table class="list_table">
+ <caption id="jobs"><a class="plain" href="#jobs">Recent jobs:</a></caption>
+ <tr>
+ <th>Bug</th>
+ <th>Created</th>
+ <th>Duration</th>
+ <th>User</th>
+ <th>Patch</th>
+ <th>Repo</th>
+ <th>Manager</th>
+ <th>Result</th>
+ </tr>
+ {{range $job := $.Jobs}}
+ <tr>
+ <td class="title"><a href="{{$job.BugLink}}">{{$job.BugTitle}}</a></td>
+ <td class="time">{{link $job.ExternalLink (formatTime $job.Created)}}</td>
+ <td class="time" title="started: {{formatTime $job.Started}}
finished: {{formatTime $job.Finished}}">
+ {{formatDuration $job.Duration}}{{if gt $job.Attempts 1}} ({{$job.Attempts}}){{end}}
+ </td>
+ <td>
+ {{if eq $job.Type 0}}
+ {{$job.User}}
+ {{else if eq $job.Type 1}}
+ bisect
+ {{else if eq $job.Type 2}}
+ bisect fix
+ {{end}}
+ </td>
+ <td>{{optlink $job.PatchLink "patch"}}</td>
+ <td class="kernel" title="{{$job.KernelAlias}}">{{$job.KernelAlias}}</td>
+ <td title="{{$job.Namespace}}/{{$job.Reporting}}">{{$job.Manager}}</td>
+ <td class="result">
+ {{if $job.ErrorLink}}
+ {{link $job.ErrorLink "error"}}
+ {{else if $job.LogLink}}
+ {{link $job.LogLink "log"}}
+ ({{if $job.Commit}}1{{else}}{{len $job.Commits}}{{end}})
+ {{else if $job.CrashTitle}}
+ {{optlink $job.CrashReportLink "report"}}
+ {{optlink $job.CrashLogLink "log"}}
+ {{else if formatTime $job.Finished}}
+ OK
+ {{else if formatTime $job.Started}}
+ running
+ {{else}}
+ pending
+ {{end}}
+ </td>
+ </tr>
+ {{end}}
+ </table>
+ <br><br>
+</body>
+</html>
diff --git a/dashboard/app/app.yaml b/dashboard/app/app.yaml
index e3300bf..7c8d90a 100644
--- a/dashboard/app/app.yaml
+++ b/dashboard/app/app.yaml
@@ -25,7 +25,7 @@
- url: /(api)
script: _go_app
secure: always
-- url: /(email_poll)
+- url: /(admin|email_poll)
script: _go_app
login: admin
secure: always
diff --git a/dashboard/app/handler.go b/dashboard/app/handler.go
index 167ca58..7fc133b 100644
--- a/dashboard/app/handler.go
+++ b/dashboard/app/handler.go
@@ -73,12 +73,14 @@
}
type uiHeader struct {
+ Admin bool
LoginLink string
AnalyticsTrackingID string
}
func commonHeader(c context.Context, r *http.Request) *uiHeader {
h := &uiHeader{
+ Admin: accessLevel(c, r) == AccessAdmin,
AnalyticsTrackingID: config.AnalyticsTrackingID,
}
if user.Current(c) == nil {
diff --git a/dashboard/app/main.go b/dashboard/app/main.go
index 01e2f68..fdf3904 100644
--- a/dashboard/app/main.go
+++ b/dashboard/app/main.go
@@ -27,6 +27,7 @@
http.Handle("/", handlerWrapper(handleMain))
http.Handle("/bug", handlerWrapper(handleBug))
http.Handle("/text", handlerWrapper(handleText))
+ http.Handle("/admin", handlerWrapper(handleAdmin))
http.Handle("/x/.config", handlerWrapper(handleTextX(textKernelConfig)))
http.Handle("/x/log.txt", handlerWrapper(handleTextX(textCrashLog)))
http.Handle("/x/report.txt", handlerWrapper(handleTextX(textCrashReport)))
@@ -40,12 +41,16 @@
type uiMain struct {
Header *uiHeader
Now time.Time
- Log []byte
- Managers []*uiManager
- Jobs []*uiJob
BugNamespaces []*uiBugNamespace
}
+type uiAdminPage struct {
+ Header *uiHeader
+ Log []byte
+ Managers []*uiManager
+ Jobs []*uiJob
+}
+
type uiManager struct {
Now time.Time
Namespace string
@@ -186,27 +191,14 @@
// handleMain serves main page.
func handleMain(c context.Context, w http.ResponseWriter, r *http.Request) error {
- var errorLog []byte
- var managers []*uiManager
- var jobs []*uiJob
accessLevel := accessLevel(c, r)
-
+ var managers []*uiManager
if r.FormValue("fixed") == "" {
var err error
managers, err = loadManagers(c, accessLevel)
if err != nil {
return err
}
- if accessLevel == AccessAdmin {
- errorLog, err = fetchErrorLogs(c)
- if err != nil {
- return err
- }
- jobs, err = loadRecentJobs(c)
- if err != nil {
- return err
- }
- }
}
bugNamespaces, err := fetchBugs(c, r)
if err != nil {
@@ -222,16 +214,37 @@
data := &uiMain{
Header: commonHeader(c, r),
Now: timeNow(c),
- Log: errorLog,
- Jobs: jobs,
BugNamespaces: bugNamespaces,
}
- if accessLevel == AccessAdmin {
- data.Managers = managers
- }
return serveTemplate(w, "main.html", data)
}
+func handleAdmin(c context.Context, w http.ResponseWriter, r *http.Request) error {
+ accessLevel := accessLevel(c, r)
+ if accessLevel != AccessAdmin {
+ return ErrAccess
+ }
+ managers, err := loadManagers(c, accessLevel)
+ if err != nil {
+ return err
+ }
+ errorLog, err := fetchErrorLogs(c)
+ if err != nil {
+ return err
+ }
+ jobs, err := loadRecentJobs(c)
+ if err != nil {
+ return err
+ }
+ data := &uiAdminPage{
+ Header: commonHeader(c, r),
+ Log: errorLog,
+ Managers: managers,
+ Jobs: jobs,
+ }
+ return serveTemplate(w, "admin.html", data)
+}
+
// handleBug serves page about a single bug (which is passed in id argument).
func handleBug(c context.Context, w http.ResponseWriter, r *http.Request) error {
bug := new(Bug)
diff --git a/dashboard/app/main.html b/dashboard/app/main.html
index f0f2db9..e1fc5a5 100644
--- a/dashboard/app/main.html
+++ b/dashboard/app/main.html
@@ -14,73 +14,6 @@
<body>
{{template "header" .Header}}
- {{if .Log}}
- <a class="plain" href="#log"><div id="log"><b>Error log:</b></div></a>
- <textarea id="log_textarea" readonly rows="20" wrap=off>{{printf "%s" .Log}}</textarea>
- <script>
- var textarea = document.getElementById("log_textarea");
- textarea.scrollTop = textarea.scrollHeight;
- </script>
- <br><br>
- {{end}}
-
- {{template "manager_list" $.Managers}}
-
- {{if $.Jobs}}
- <table class="list_table">
- <caption id="jobs"><a class="plain" href="#jobs">Recent jobs:</a></caption>
- <tr>
- <th>Bug</th>
- <th>Created</th>
- <th>Duration</th>
- <th>User</th>
- <th>Patch</th>
- <th>Repo</th>
- <th>Manager</th>
- <th>Result</th>
- </tr>
- {{range $job := $.Jobs}}
- <tr>
- <td class="title"><a href="{{$job.BugLink}}">{{$job.BugTitle}}</a></td>
- <td class="time">{{link $job.ExternalLink (formatTime $job.Created)}}</td>
- <td class="time" title="started: {{formatTime $job.Started}}
finished: {{formatTime $job.Finished}}">
- {{formatDuration $job.Duration}}{{if gt $job.Attempts 1}} ({{$job.Attempts}}){{end}}
- </td>
- <td>
- {{if eq $job.Type 0}}
- {{$job.User}}
- {{else if eq $job.Type 1}}
- bisect
- {{else if eq $job.Type 2}}
- bisect fix
- {{end}}
- </td>
- <td>{{optlink $job.PatchLink "patch"}}</td>
- <td class="kernel" title="{{$job.KernelAlias}}">{{$job.KernelAlias}}</td>
- <td title="{{$job.Namespace}}/{{$job.Reporting}}">{{$job.Manager}}</td>
- <td class="result">
- {{if $job.ErrorLink}}
- {{link $job.ErrorLink "error"}}
- {{else if $job.LogLink}}
- {{link $job.LogLink "log"}}
- ({{if $job.Commit}}1{{else}}{{len $job.Commits}}{{end}})
- {{else if $job.CrashTitle}}
- {{optlink $job.CrashReportLink "report"}}
- {{optlink $job.CrashLogLink "log"}}
- {{else if formatTime $job.Finished}}
- OK
- {{else if formatTime $job.Started}}
- running
- {{else}}
- pending
- {{end}}
- </td>
- </tr>
- {{end}}
- </table>
- <br><br>
- {{end}}
-
{{range $ns := $.BugNamespaces}}
<br>
<a class="plain" href="#{{$ns.Name}}"><h2 id="{{$ns.Name}}">{{$ns.Caption}}</h2></a>
diff --git a/dashboard/app/templates.html b/dashboard/app/templates.html
index 3d7bba4..5747aa7 100644
--- a/dashboard/app/templates.html
+++ b/dashboard/app/templates.html
@@ -27,6 +27,9 @@
<h1><a href="/">syzbot</a></h1>
</td>
<td class="search">
+ {{if .Admin}}
+ <a href="/admin">admin</a> |
+ {{end}}
{{if .LoginLink}}
<a href="{{.LoginLink}}">sign-in</a> |
{{end}}
diff --git a/dashboard/app/util_test.go b/dashboard/app/util_test.go
index a12b9ec..73d1986 100644
--- a/dashboard/app/util_test.go
+++ b/dashboard/app/util_test.go
@@ -140,6 +140,7 @@
if !c.t.Failed() {
// Ensure that we can render main page and all bugs in the final test state.
c.expectOK(c.GET("/"))
+ c.expectOK(c.GET("/admin"))
var bugs []*Bug
keys, err := db.NewQuery("Bug").GetAll(c.ctx, &bugs)
if err != nil {