dashboard/buildlet: make exec handler return process state in HTTP trailer

Requires Go tip to function, but compiles with old versions of Go, but
without returning the trailer, which we'll be able to detect in the
coordinator to make sure nobody used an old Go to cross-compile a
buildlet.

Change-Id: Ie5f71c0a4477563dea5f1526af10a49aa41536d6
Reviewed-on: https://go-review.googlesource.com/2159
Reviewed-by: Andrew Gerrand <adg@golang.org>
This commit is contained in:
Brad Fitzpatrick 2014-12-29 20:51:32 -08:00
parent 9c946b9540
commit 721bf87b5b
1 changed files with 26 additions and 3 deletions

View File

@ -154,16 +154,32 @@ func untar(r io.Reader, dir string) error {
return nil return nil
} }
// Process-State is an HTTP Trailer set in the /exec handler to "ok"
// on success, or os.ProcessState.String() on failure.
const hdrProcessState = "Process-State"
func handleExec(w http.ResponseWriter, r *http.Request) { func handleExec(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" { if r.Method != "POST" {
http.Error(w, "requires POST method", http.StatusBadRequest) http.Error(w, "requires POST method", http.StatusBadRequest)
return return
} }
if r.ProtoMajor*10+r.ProtoMinor < 11 {
// We need trailers, only available in HTTP/1.1 or HTTP/2.
http.Error(w, "HTTP/1.1 or higher required", http.StatusBadRequest)
return
}
w.Header().Set("Trailer", hdrProcessState) // declare it so we can set it
cmdPath := r.FormValue("cmd") // required cmdPath := r.FormValue("cmd") // required
if !validRelPath(cmdPath) { if !validRelPath(cmdPath) {
http.Error(w, "requires 'cmd' parameter", http.StatusBadRequest) http.Error(w, "requires 'cmd' parameter", http.StatusBadRequest)
return return
} }
if f, ok := w.(http.Flusher); ok {
f.Flush()
}
absCmd := filepath.Join(*scratchDir, filepath.FromSlash(cmdPath)) absCmd := filepath.Join(*scratchDir, filepath.FromSlash(cmdPath))
cmd := exec.Command(absCmd, r.PostForm["cmdArg"]...) cmd := exec.Command(absCmd, r.PostForm["cmdArg"]...)
cmd.Dir = filepath.Dir(absCmd) cmd.Dir = filepath.Dir(absCmd)
@ -171,9 +187,16 @@ func handleExec(w http.ResponseWriter, r *http.Request) {
cmd.Stdout = cmdOutput cmd.Stdout = cmdOutput
cmd.Stderr = cmdOutput cmd.Stderr = cmdOutput
err := cmd.Run() err := cmd.Run()
log.Printf("Run = %v", err) state := "ok"
// TODO: put the exit status in the HTTP trailer, if err != nil {
// once https://golang.org/issue/7759 is fixed. if ps := cmd.ProcessState; ps != nil {
state = ps.String()
} else {
state = err.Error()
}
}
w.Header().Set(hdrProcessState, state)
log.Printf("Run = %s", state)
} }
// flushWriter is an io.Writer wrapper that writes to w and // flushWriter is an io.Writer wrapper that writes to w and