From 721bf87b5bd65ddc9dd5f8655670a03d75f49a7f Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 29 Dec 2014 20:51:32 -0800 Subject: [PATCH] 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 --- dashboard/buildlet/buildlet.go | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/dashboard/buildlet/buildlet.go b/dashboard/buildlet/buildlet.go index 135e8169..bc356048 100644 --- a/dashboard/buildlet/buildlet.go +++ b/dashboard/buildlet/buildlet.go @@ -154,16 +154,32 @@ func untar(r io.Reader, dir string) error { 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) { if r.Method != "POST" { http.Error(w, "requires POST method", http.StatusBadRequest) 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 if !validRelPath(cmdPath) { http.Error(w, "requires 'cmd' parameter", http.StatusBadRequest) return } + if f, ok := w.(http.Flusher); ok { + f.Flush() + } + absCmd := filepath.Join(*scratchDir, filepath.FromSlash(cmdPath)) cmd := exec.Command(absCmd, r.PostForm["cmdArg"]...) cmd.Dir = filepath.Dir(absCmd) @@ -171,9 +187,16 @@ func handleExec(w http.ResponseWriter, r *http.Request) { cmd.Stdout = cmdOutput cmd.Stderr = cmdOutput err := cmd.Run() - log.Printf("Run = %v", err) - // TODO: put the exit status in the HTTP trailer, - // once https://golang.org/issue/7759 is fixed. + state := "ok" + if err != nil { + 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