aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-06-11 10:02:45 +0200
committerDmitry Vyukov <dvyukov@google.com>2018-06-11 12:12:01 +0300
commitd6ae9b97396cde206f3d294594cd4a8fd55e3c63 (patch)
tree6338574f771e54458ca3aa6b76d802e25d7d64c9
parent866118af36a38963903be2bdee4aff0c36ae365f (diff)
dashboard/app: simplify config deployment
Currently one needs to switch between config_stub.go and prod config back and forth on every deployment. This is very inconvinient. Rework config, so that switching is not necessary.
-rw-r--r--dashboard/app/api.go2
-rw-r--r--dashboard/app/app_test.go10
-rw-r--r--dashboard/app/config.go44
-rw-r--r--dashboard/app/config_stub.go47
-rw-r--r--dashboard/app/main.go2
-rw-r--r--dashboard/app/reporting_email.go2
-rw-r--r--dashboard/app/util_test.go2
7 files changed, 41 insertions, 68 deletions
diff --git a/dashboard/app/api.go b/dashboard/app/api.go
index 1b5f016ca..93ae5a275 100644
--- a/dashboard/app/api.go
+++ b/dashboard/app/api.go
@@ -25,7 +25,7 @@ import (
"google.golang.org/appengine/log"
)
-func init() {
+func initAPIHandlers() {
http.Handle("/api", handleJSON(handleAPI))
}
diff --git a/dashboard/app/app_test.go b/dashboard/app/app_test.go
index 21fdc75b3..f40a648ea 100644
--- a/dashboard/app/app_test.go
+++ b/dashboard/app/app_test.go
@@ -14,8 +14,13 @@ import (
"github.com/google/syzkaller/dashboard/dashapi"
)
+func init() {
+ initMocks()
+ installConfig(testConfig)
+}
+
// Config used in tests.
-var config = GlobalConfig{
+var testConfig = &GlobalConfig{
AccessLevel: AccessPublic,
AuthDomain: "@syzkaller.com",
Clients: map[string]string{
@@ -124,7 +129,8 @@ var config = GlobalConfig{
},
},
"access-public": &Config{
- Key: "publickeypublickeypublickey",
+ AccessLevel: AccessPublic,
+ Key: "publickeypublickeypublickey",
Clients: map[string]string{
clientPublic: keyPublic,
},
diff --git a/dashboard/app/config.go b/dashboard/app/config.go
index cb826a782..c4d702d08 100644
--- a/dashboard/app/config.go
+++ b/dashboard/app/config.go
@@ -126,10 +126,6 @@ const (
FilterHold // Hold off with reporting this bug.
)
-func reportAllFilter(bug *Bug) FilterResult { return FilterReport }
-func reportSkipFilter(bug *Bug) FilterResult { return FilterSkip }
-func reportHoldFilter(bug *Bug) FilterResult { return FilterHold }
-
func (cfg *Config) ReportingByName(name string) *Reporting {
for i := range cfg.Reporting {
reporting := &cfg.Reporting[i]
@@ -140,19 +136,26 @@ func (cfg *Config) ReportingByName(name string) *Reporting {
return nil
}
-func init() {
- // Validate the global config.
- if len(config.Namespaces) == 0 {
+// config is populated by installConfig which should be called either from tests
+// or from a separate file that provides actual production config.
+var config *GlobalConfig
+
+func installConfig(cfg *GlobalConfig) {
+ if config != nil {
+ panic("another config is already installed")
+ }
+ // Validate the global cfg.
+ if len(cfg.Namespaces) == 0 {
panic("no namespaces found")
}
- for i := range config.EmailBlacklist {
- config.EmailBlacklist[i] = email.CanonicalEmail(config.EmailBlacklist[i])
+ for i := range cfg.EmailBlacklist {
+ cfg.EmailBlacklist[i] = email.CanonicalEmail(cfg.EmailBlacklist[i])
}
namespaces := make(map[string]bool)
clientNames := make(map[string]bool)
- checkClients(clientNames, config.Clients)
- checkConfigAccessLevel(&config.AccessLevel, AccessPublic, "global")
- for ns, cfg := range config.Namespaces {
+ checkClients(clientNames, cfg.Clients)
+ checkConfigAccessLevel(&cfg.AccessLevel, AccessPublic, "global")
+ for ns, cfg := range cfg.Namespaces {
if ns == "" {
panic("empty namespace name")
}
@@ -188,7 +191,7 @@ func init() {
if len(cfg.Reporting) == 0 {
panic(fmt.Sprintf("no reporting in namespace %q", ns))
}
- checkConfigAccessLevel(&cfg.AccessLevel, config.AccessLevel, fmt.Sprintf("namespace %q", ns))
+ checkConfigAccessLevel(&cfg.AccessLevel, cfg.AccessLevel, fmt.Sprintf("namespace %q", ns))
parentAccessLevel := cfg.AccessLevel
reportingNames := make(map[string]bool)
// Go backwards because access levels get stricter backwards.
@@ -207,7 +210,7 @@ func init() {
fmt.Sprintf("reporting %q/%q", ns, reporting.Name))
parentAccessLevel = reporting.AccessLevel
if reporting.Filter == nil {
- reporting.Filter = reportAllFilter
+ reporting.Filter = func(bug *Bug) FilterResult { return FilterReport }
}
reportingNames[reporting.Name] = true
if reporting.Config.Type() == "" {
@@ -222,7 +225,7 @@ func init() {
}
}
}
- for repo, info := range config.KernelRepos {
+ for repo, info := range cfg.KernelRepos {
if info.Alias == "" {
panic(fmt.Sprintf("empty kernel repo alias for %q", repo))
}
@@ -230,6 +233,17 @@ func init() {
panic(fmt.Sprintf("bad kernel repo reporting priority %v for %q", prio, repo))
}
}
+ config = cfg
+ initEmailReporting()
+ initHTTPHandlers()
+ initAPIHandlers()
+}
+
+func init() {
+ // Prevents gometalinter from considering everything as dead code.
+ if false {
+ installConfig(nil)
+ }
}
func checkConfigAccessLevel(current *AccessLevel, parent AccessLevel, what string) {
diff --git a/dashboard/app/config_stub.go b/dashboard/app/config_stub.go
deleted file mode 100644
index dc7f3b6c5..000000000
--- a/dashboard/app/config_stub.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2017 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.
-
-// +build !aetest
-
-package dash
-
-import "time"
-
-// Stub config variable that merely makes link success.
-// The app will panic in init with this empty config.
-// When deploying the app one needs to replace this config with a real one.
-// See an example below.
-var config GlobalConfig
-
-// Example config:
-var _ = GlobalConfig{
- Namespaces: map[string]*Config{
- "upstream": &Config{
- Key: "123",
- Clients: map[string]string{
- "foo": "bar",
- },
- MailWithoutReport: false,
- WaitForRepro: 12 * time.Hour,
- Reporting: []Reporting{
- Reporting{
- Name: "upstream",
- DailyLimit: 10,
- Filter: reportAllFilter,
- Config: &EmailConfig{
- Email: "syzkaller@googlegroups.com",
- MailMaintainers: true,
- },
- },
- Reporting{
- Name: "another",
- Filter: reportSkipFilter,
- },
- Reporting{
- Name: "yetanother",
- Filter: reportHoldFilter,
- },
- },
- },
- },
-}
diff --git a/dashboard/app/main.go b/dashboard/app/main.go
index 5e3792a9d..431c490bb 100644
--- a/dashboard/app/main.go
+++ b/dashboard/app/main.go
@@ -21,7 +21,7 @@ import (
// This file contains web UI http handlers.
-func init() {
+func initHTTPHandlers() {
http.Handle("/", handlerWrapper(handleMain))
http.Handle("/bug", handlerWrapper(handleBug))
http.Handle("/text", handlerWrapper(handleText))
diff --git a/dashboard/app/reporting_email.go b/dashboard/app/reporting_email.go
index a7b885001..de5855bc2 100644
--- a/dashboard/app/reporting_email.go
+++ b/dashboard/app/reporting_email.go
@@ -26,7 +26,7 @@ import (
// Email reporting interface.
-func init() {
+func initEmailReporting() {
http.HandleFunc("/email_poll", handleEmailPoll)
http.HandleFunc("/_ah/mail/", handleIncomingMail)
http.HandleFunc("/_ah/bounce", handleEmailBounce)
diff --git a/dashboard/app/util_test.go b/dashboard/app/util_test.go
index 3a005ea5f..2504a52d1 100644
--- a/dashboard/app/util_test.go
+++ b/dashboard/app/util_test.go
@@ -357,7 +357,7 @@ Content-Type: text/plain
c.expectOK(c.POST("/_ah/mail/", email))
}
-func init() {
+func initMocks() {
// Mock time as some functionality relies on real time.
timeNow = func(c context.Context) time.Time {
return getRequestContext(c).mockedTime