package feta import "time" import "net/http" import "encoding/json" import "runtime" import "fmt" import "strings" import "github.com/gin-gonic/gin" type hash map[string]interface{} func (a *fetaAPIServer) instances() []hash { resp := make([]hash, 0) now := time.Now() for _, v := range a.feta.manager.listInstances() { i := make(hash) // FIXME figure out why a very short lock here deadlocks v.Lock() i["hostname"] = v.hostname i["nextCheck"] = v.nextFetch.UTC().Format(time.RFC3339) i["nextCheckAfter"] = (-1 * now.Sub(v.nextFetch)).String() i["successCount"] = v.successCount i["errorCount"] = v.errorCount i["identified"] = v.identified i["status"] = v.Status() i["software"] = "unknown" i["version"] = "unknown" if v.identified { i["software"] = v.serverImplementationString i["version"] = v.serverVersionString } v.Unlock() resp = append(resp, i) } return resp } func (a *fetaAPIServer) instanceSummary() map[string]int { resp := make(map[string]int) for _, v := range a.feta.manager.listInstances() { v.Lock() resp[fmt.Sprintf("STATUS_%s", v.Status())]++ if v.serverImplementationString != "" { //FIXME(sneak) sanitize this to a-z0-9, it is server-provided resp[fmt.Sprintf("SOFTWARE_%s", strings.ToUpper(v.serverImplementationString))]++ } v.Unlock() } return resp } func (a *fetaAPIServer) getInstanceListHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { result := &gin.H{ "instances": a.instances(), } json, err := json.Marshal(result) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") w.Write(json) } } func (a *fetaAPIServer) getIndexHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { index := &gin.H{ "server": &gin.H{ "now": time.Now().UTC().Format(time.RFC3339), "uptime": a.feta.uptime().String(), "goroutines": runtime.NumGoroutine(), "goversion": runtime.Version(), "version": a.feta.version, "buildarch": a.feta.buildarch, }, "instanceSummary": a.instanceSummary(), } json, err := json.Marshal(index) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") w.Write(json) } } func (a *fetaAPIServer) getHealthCheckHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { resp := &gin.H{ "status": "ok", "now": time.Now().UTC().Format(time.RFC3339), "uptime": a.feta.uptime().String(), } json, err := json.Marshal(resp) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") w.Write(json) } }