github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/misc/dashboard/builder/http.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "bytes" 9 "encoding/json" 10 "errors" 11 "fmt" 12 "io" 13 "log" 14 "net/http" 15 "net/url" 16 "time" 17 ) 18 19 type obj map[string]interface{} 20 21 // dash runs the given method and command on the dashboard. 22 // If args is non-nil it is encoded as the URL query string. 23 // If req is non-nil it is JSON-encoded and passed as the body of the HTTP POST. 24 // If resp is non-nil the server's response is decoded into the value pointed 25 // to by resp (resp must be a pointer). 26 func dash(meth, cmd string, args url.Values, req, resp interface{}) error { 27 var r *http.Response 28 var err error 29 if *verbose { 30 log.Println("dash", meth, cmd, args, req) 31 } 32 cmd = "http://" + *dashboard + "/" + cmd 33 if len(args) > 0 { 34 cmd += "?" + args.Encode() 35 } 36 switch meth { 37 case "GET": 38 if req != nil { 39 log.Panicf("%s to %s with req", meth, cmd) 40 } 41 r, err = http.Get(cmd) 42 case "POST": 43 var body io.Reader 44 if req != nil { 45 b, err := json.Marshal(req) 46 if err != nil { 47 return err 48 } 49 body = bytes.NewBuffer(b) 50 } 51 r, err = http.Post(cmd, "text/json", body) 52 default: 53 log.Panicf("%s: invalid method %q", cmd, meth) 54 panic("invalid method: " + meth) 55 } 56 if err != nil { 57 return err 58 } 59 defer r.Body.Close() 60 if r.StatusCode != http.StatusOK { 61 return fmt.Errorf("bad http response: %v", r.Status) 62 } 63 body := new(bytes.Buffer) 64 if _, err := body.ReadFrom(r.Body); err != nil { 65 return err 66 } 67 68 // Read JSON-encoded Response into provided resp 69 // and return an error if present. 70 var result = struct { 71 Response interface{} 72 Error string 73 }{ 74 // Put the provided resp in here as it can be a pointer to 75 // some value we should unmarshal into. 76 Response: resp, 77 } 78 if err = json.Unmarshal(body.Bytes(), &result); err != nil { 79 log.Printf("json unmarshal %#q: %s\n", body.Bytes(), err) 80 return err 81 } 82 if result.Error != "" { 83 return errors.New(result.Error) 84 } 85 86 return nil 87 } 88 89 // todo returns the next hash to build. 90 func (b *Builder) todo(kind, pkg, goHash string) (rev string, err error) { 91 args := url.Values{ 92 "kind": {kind}, 93 "builder": {b.name}, 94 "packagePath": {pkg}, 95 "goHash": {goHash}, 96 } 97 var resp *struct { 98 Kind string 99 Data struct { 100 Hash string 101 } 102 } 103 if err = dash("GET", "todo", args, nil, &resp); err != nil { 104 return "", err 105 } 106 if resp == nil { 107 return "", nil 108 } 109 if kind != resp.Kind { 110 return "", fmt.Errorf("expecting Kind %q, got %q", kind, resp.Kind) 111 } 112 return resp.Data.Hash, nil 113 } 114 115 // recordResult sends build results to the dashboard 116 func (b *Builder) recordResult(ok bool, pkg, hash, goHash, buildLog string, runTime time.Duration) error { 117 req := obj{ 118 "Builder": b.name, 119 "PackagePath": pkg, 120 "Hash": hash, 121 "GoHash": goHash, 122 "OK": ok, 123 "Log": buildLog, 124 "RunTime": runTime, 125 } 126 args := url.Values{"key": {b.key}, "builder": {b.name}} 127 return dash("POST", "result", args, req, nil) 128 } 129 130 func postCommit(key, pkg string, l *HgLog) error { 131 t, err := time.Parse(time.RFC3339, l.Date) 132 if err != nil { 133 return fmt.Errorf("parsing %q: %v", l.Date, t) 134 } 135 return dash("POST", "commit", url.Values{"key": {key}}, obj{ 136 "PackagePath": pkg, 137 "Hash": l.Hash, 138 "ParentHash": l.Parent, 139 "Time": t.Format(time.RFC3339), 140 "User": l.Author, 141 "Desc": l.Desc, 142 }, nil) 143 } 144 145 func dashboardCommit(pkg, hash string) bool { 146 err := dash("GET", "commit", url.Values{ 147 "packagePath": {pkg}, 148 "hash": {hash}, 149 }, nil, nil) 150 return err == nil 151 } 152 153 func dashboardPackages(kind string) []string { 154 args := url.Values{"kind": []string{kind}} 155 var resp []struct { 156 Path string 157 } 158 if err := dash("GET", "packages", args, nil, &resp); err != nil { 159 log.Println("dashboardPackages:", err) 160 return nil 161 } 162 var pkgs []string 163 for _, r := range resp { 164 pkgs = append(pkgs, r.Path) 165 } 166 return pkgs 167 }