From 462f32a81b9a64ac8ee97fbfb4252f4bf35b417b Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Thu, 12 Mar 2015 11:35:11 -0700 Subject: [PATCH] tools/functional-tester: add http status reporter --- tools/functional-tester/etcd-tester/http.go | 19 ++++++++ tools/functional-tester/etcd-tester/main.go | 6 +++ tools/functional-tester/etcd-tester/tester.go | 47 ++++++++++++++++++- 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 tools/functional-tester/etcd-tester/http.go diff --git a/tools/functional-tester/etcd-tester/http.go b/tools/functional-tester/etcd-tester/http.go new file mode 100644 index 000000000..071c4d3b6 --- /dev/null +++ b/tools/functional-tester/etcd-tester/http.go @@ -0,0 +1,19 @@ +package main + +import ( + "encoding/json" + "net/http" +) + +type statusHandler struct { + status *Status +} + +func (sh statusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + en := json.NewEncoder(w) + err := en.Encode(sh.status.get()) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} diff --git a/tools/functional-tester/etcd-tester/main.go b/tools/functional-tester/etcd-tester/main.go index 6c8fe5dac..35856b81f 100644 --- a/tools/functional-tester/etcd-tester/main.go +++ b/tools/functional-tester/etcd-tester/main.go @@ -17,6 +17,7 @@ package main import ( "flag" "log" + "net/http" "strings" ) @@ -43,5 +44,10 @@ func main() { cluster: c, limit: *limit, } + + sh := statusHandler{status: &t.status} + http.Handle("/status", sh) + go func() { log.Fatal(http.ListenAndServe(":9028", nil)) }() + t.runLoop() } diff --git a/tools/functional-tester/etcd-tester/tester.go b/tools/functional-tester/etcd-tester/tester.go index 086fdd92f..03bbdb8cb 100644 --- a/tools/functional-tester/etcd-tester/tester.go +++ b/tools/functional-tester/etcd-tester/tester.go @@ -14,17 +14,32 @@ package main -import "log" +import ( + "log" + "sync" + "time" +) type tester struct { failures []failure cluster *cluster limit int + + status Status } func (tt *tester) runLoop() { + tt.status.Since = time.Now() + tt.status.RoundLimit = tt.limit + for _, f := range tt.failures { + tt.status.Failures = append(tt.status.Failures, f.Desc()) + } for i := 0; i < tt.limit; i++ { + tt.status.setRound(i) + for j, f := range tt.failures { + tt.status.setCase(j) + if err := tt.cluster.WaitHealth(); err != nil { log.Printf("etcd-tester: [round#%d case#%d] wait full health error: %v", i, j, err) if err := tt.cleanup(i, j); err != nil { @@ -64,3 +79,33 @@ func (tt *tester) cleanup(i, j int) error { } return tt.cluster.Bootstrap() } + +type Status struct { + Since time.Time + Failures []string + RoundLimit int + + mu sync.Mutex // guards Round and Case + // TODO: add agent status + Round int + Case int +} + +// get gets a copy of status +func (s *Status) get() Status { + s.mu.Lock() + defer s.mu.Unlock() + return *s +} + +func (s *Status) setRound(r int) { + s.mu.Lock() + defer s.mu.Unlock() + s.Round = r +} + +func (s *Status) setCase(c int) { + s.mu.Lock() + defer s.mu.Unlock() + s.Case = c +}