Commit 2c007221 authored by Andrew Gerrand's avatar Andrew Gerrand

misc/dashboard: init handler for bootstrapping

misc/dashboard: support unauthenticated GETs
misc/dashboard: add ?nukeonly=1 option to /buildtest

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/5450091
parent b9bd0c75
...@@ -6,8 +6,8 @@ api_version: 3 ...@@ -6,8 +6,8 @@ api_version: 3
handlers: handlers:
- url: /log/.+ - url: /log/.+
script: _go_app script: _go_app
- url: /(commit|package|result|tag|todo) - url: /(commit|packages|result|tag|todo)
script: _go_app script: _go_app
- url: /buildtest - url: /(init|buildtest)
script: _go_app script: _go_app
login: admin login: admin
...@@ -79,7 +79,7 @@ func (c *Commit) Valid() os.Error { ...@@ -79,7 +79,7 @@ func (c *Commit) Valid() os.Error {
if !validHash(c.Hash) { if !validHash(c.Hash) {
return os.NewError("invalid Hash") return os.NewError("invalid Hash")
} }
if !validHash(c.ParentHash) { if c.ParentHash != "" && !validHash(c.ParentHash) { // empty is OK
return os.NewError("invalid ParentHash") return os.NewError("invalid ParentHash")
} }
return nil return nil
...@@ -207,7 +207,6 @@ func commitHandler(r *http.Request) (interface{}, os.Error) { ...@@ -207,7 +207,6 @@ func commitHandler(r *http.Request) (interface{}, os.Error) {
c := appengine.NewContext(r) c := appengine.NewContext(r)
com := new(Commit) com := new(Commit)
// TODO(adg): support unauthenticated GET requests to this handler
if r.Method == "GET" { if r.Method == "GET" {
com.PackagePath = r.FormValue("packagePath") com.PackagePath = r.FormValue("packagePath")
com.Hash = r.FormValue("hash") com.Hash = r.FormValue("hash")
...@@ -216,6 +215,9 @@ func commitHandler(r *http.Request) (interface{}, os.Error) { ...@@ -216,6 +215,9 @@ func commitHandler(r *http.Request) (interface{}, os.Error) {
} }
return com, nil return com, nil
} }
if r.Method != "POST" {
return nil, errBadMethod(r.Method)
}
// POST request // POST request
defer r.Body.Close() defer r.Body.Close()
...@@ -280,6 +282,10 @@ func addCommit(c appengine.Context, com *Commit) os.Error { ...@@ -280,6 +282,10 @@ func addCommit(c appengine.Context, com *Commit) os.Error {
// //
// This handler is used by a gobuilder process in -commit mode. // This handler is used by a gobuilder process in -commit mode.
func tagHandler(r *http.Request) (interface{}, os.Error) { func tagHandler(r *http.Request) (interface{}, os.Error) {
if r.Method != "POST" {
return nil, errBadMethod(r.Method)
}
t := new(Tag) t := new(Tag)
defer r.Body.Close() defer r.Body.Close()
if err := json.NewDecoder(r.Body).Decode(t); err != nil { if err := json.NewDecoder(r.Body).Decode(t); err != nil {
...@@ -364,6 +370,10 @@ func packagesHandler(r *http.Request) (interface{}, os.Error) { ...@@ -364,6 +370,10 @@ func packagesHandler(r *http.Request) (interface{}, os.Error) {
// If the Log field is not empty, resultHandler creates a new Log entity // If the Log field is not empty, resultHandler creates a new Log entity
// and updates the LogHash field before putting the Commit entity. // and updates the LogHash field before putting the Commit entity.
func resultHandler(r *http.Request) (interface{}, os.Error) { func resultHandler(r *http.Request) (interface{}, os.Error) {
if r.Method != "POST" {
return nil, errBadMethod(r.Method)
}
c := appengine.NewContext(r) c := appengine.NewContext(r)
res := new(Result) res := new(Result)
defer r.Body.Close() defer r.Body.Close()
...@@ -416,11 +426,17 @@ func logHandler(w http.ResponseWriter, r *http.Request) { ...@@ -416,11 +426,17 @@ func logHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
type errBadMethod string
func (e errBadMethod) String() string {
return "bad method: " + string(e)
}
type dashHandler func(*http.Request) (interface{}, os.Error) type dashHandler func(*http.Request) (interface{}, os.Error)
type dashResponse struct { type dashResponse struct {
Response interface{} Response interface{}
Error os.Error Error string
} }
// AuthHandler wraps a http.HandlerFunc with a handler that validates the // AuthHandler wraps a http.HandlerFunc with a handler that validates the
...@@ -431,9 +447,9 @@ func AuthHandler(h dashHandler) http.HandlerFunc { ...@@ -431,9 +447,9 @@ func AuthHandler(h dashHandler) http.HandlerFunc {
// request body when calling r.FormValue. // request body when calling r.FormValue.
r.Form = r.URL.Query() r.Form = r.URL.Query()
// Validate key query parameter. // Validate key query parameter for POST requests only.
key := r.FormValue("key") key := r.FormValue("key")
if key != secretKey { if r.Method == "POST" && key != secretKey {
h := sha1.New() h := sha1.New()
h.Write([]byte(r.FormValue("builder") + secretKey)) h.Write([]byte(r.FormValue("builder") + secretKey))
if key != fmt.Sprintf("%x", h.Sum()) { if key != fmt.Sprintf("%x", h.Sum()) {
...@@ -445,18 +461,39 @@ func AuthHandler(h dashHandler) http.HandlerFunc { ...@@ -445,18 +461,39 @@ func AuthHandler(h dashHandler) http.HandlerFunc {
// Call the original HandlerFunc and return the response. // Call the original HandlerFunc and return the response.
c := appengine.NewContext(r) c := appengine.NewContext(r)
resp, err := h(r) resp, err := h(r)
dashResp := dashResponse{Response: resp}
if err != nil { if err != nil {
c.Errorf("%v", err) c.Errorf("%v", err)
dashResp.Error = err.String()
} }
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(dashResponse{resp, err}) if err = json.NewEncoder(w).Encode(dashResp); err != nil {
if err != nil {
c.Criticalf("%v", err) c.Criticalf("%v", err)
} }
} }
} }
func initHandler(w http.ResponseWriter, r *http.Request) {
// TODO(adg): devise a better way of bootstrapping new packages
var pkgs = []*Package{
&Package{Name: "Go", Path: ""},
&Package{Name: "Test", Path: "code.google.com/p/go.test"},
}
c := appengine.NewContext(r)
for _, p := range pkgs {
_, err := datastore.Put(c, p.Key(c), p)
if err != nil {
logErr(w, r, err)
return
}
}
fmt.Fprint(w, "OK")
}
func init() { func init() {
// admin handlers
http.HandleFunc("/init", initHandler)
// authenticated handlers // authenticated handlers
http.HandleFunc("/commit", AuthHandler(commitHandler)) http.HandleFunc("/commit", AuthHandler(commitHandler))
http.HandleFunc("/packages", AuthHandler(packagesHandler)) http.HandleFunc("/packages", AuthHandler(packagesHandler))
......
...@@ -31,7 +31,7 @@ var testEntityKinds = []string{ ...@@ -31,7 +31,7 @@ var testEntityKinds = []string{
"Log", "Log",
} }
const testPkg = "code.google.com/p/go.more" const testPkg = "code.google.com/p/go.test"
var testPackage = &Package{Name: "Test", Path: testPkg} var testPackage = &Package{Name: "Test", Path: testPkg}
...@@ -104,6 +104,10 @@ func testHandler(w http.ResponseWriter, r *http.Request) { ...@@ -104,6 +104,10 @@ func testHandler(w http.ResponseWriter, r *http.Request) {
logErr(w, r, err) logErr(w, r, err)
return return
} }
if r.FormValue("nukeonly") != "" {
fmt.Fprint(w, "OK")
return
}
for _, p := range testPackages { for _, p := range testPackages {
if _, err := datastore.Put(c, p.Key(c), p); err != nil { if _, err := datastore.Put(c, p.Key(c), p); err != nil {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment