2019-12-19 14:24:26 +00:00
|
|
|
package process
|
2019-11-05 23:32:09 +00:00
|
|
|
|
2020-03-27 23:02:36 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"runtime"
|
|
|
|
"strings"
|
|
|
|
"time"
|
2019-11-05 23:32:09 +00:00
|
|
|
|
2020-03-30 23:05:53 +00:00
|
|
|
u "git.eeqj.de/sneak/goutil"
|
|
|
|
"github.com/flosch/pongo2"
|
2020-04-05 01:32:25 +00:00
|
|
|
"github.com/google/uuid"
|
2020-03-30 23:05:53 +00:00
|
|
|
"github.com/labstack/echo"
|
2020-03-27 23:02:36 +00:00
|
|
|
)
|
2019-11-05 23:32:09 +00:00
|
|
|
|
|
|
|
type hash map[string]interface{}
|
|
|
|
|
2019-12-19 14:24:26 +00:00
|
|
|
func (a *Server) instances() []hash {
|
2019-11-05 23:32:09 +00:00
|
|
|
resp := make([]hash, 0)
|
|
|
|
now := time.Now()
|
2019-12-19 14:24:26 +00:00
|
|
|
for _, v := range a.feta.manager.ListInstances() {
|
2019-11-05 23:32:09 +00:00
|
|
|
i := make(hash)
|
2020-04-05 01:16:37 +00:00
|
|
|
// TODO move this locking onto a method on Instance that just
|
|
|
|
// returns a new hash
|
2020-04-09 10:08:31 +00:00
|
|
|
|
|
|
|
//this only locks the FSM, not the whole instance struct
|
|
|
|
i["status"] = v.Status()
|
|
|
|
|
|
|
|
// now do a quick lock of the whole instance just to copy out the
|
|
|
|
// attrs
|
2019-11-05 23:32:09 +00:00
|
|
|
v.Lock()
|
2019-12-19 14:24:26 +00:00
|
|
|
i["hostname"] = v.Hostname
|
2020-04-05 01:16:37 +00:00
|
|
|
i["uuid"] = v.UUID.String()
|
2019-12-19 14:24:26 +00:00
|
|
|
i["nextCheck"] = v.NextFetch.UTC().Format(time.RFC3339)
|
|
|
|
i["nextCheckAfter"] = (-1 * now.Sub(v.NextFetch)).String()
|
|
|
|
i["successCount"] = v.SuccessCount
|
|
|
|
i["errorCount"] = v.ErrorCount
|
2020-04-09 10:08:31 +00:00
|
|
|
i["consecutiveErrorCount"] = v.ConsecutiveErrorCount
|
2019-12-19 14:24:26 +00:00
|
|
|
i["identified"] = v.Identified
|
2019-11-05 23:32:09 +00:00
|
|
|
i["software"] = "unknown"
|
|
|
|
i["version"] = "unknown"
|
2019-12-19 14:24:26 +00:00
|
|
|
if v.Identified {
|
|
|
|
i["software"] = v.ServerImplementationString
|
|
|
|
i["version"] = v.ServerVersionString
|
2019-11-05 23:32:09 +00:00
|
|
|
}
|
|
|
|
v.Unlock()
|
2020-04-09 10:08:31 +00:00
|
|
|
|
2019-11-05 23:32:09 +00:00
|
|
|
resp = append(resp, i)
|
|
|
|
}
|
2020-04-05 01:16:37 +00:00
|
|
|
|
|
|
|
for _, item := range resp {
|
|
|
|
count, err := a.feta.dbm.TootCountForHostname(item["hostname"].(string))
|
|
|
|
item["tootCount"] = 0
|
|
|
|
if err != nil {
|
|
|
|
item["tootCount"] = count
|
|
|
|
}
|
|
|
|
}
|
2019-11-05 23:32:09 +00:00
|
|
|
return resp
|
|
|
|
}
|
|
|
|
|
2020-04-09 10:08:31 +00:00
|
|
|
func (a *Server) instanceStatusSummary() map[string]int {
|
2019-11-06 07:03:42 +00:00
|
|
|
resp := make(map[string]int)
|
2019-12-19 14:24:26 +00:00
|
|
|
for _, v := range a.feta.manager.ListInstances() {
|
2019-11-06 07:03:42 +00:00
|
|
|
v.Lock()
|
|
|
|
resp[fmt.Sprintf("STATUS_%s", v.Status())]++
|
2019-12-19 14:24:26 +00:00
|
|
|
if v.ServerImplementationString != "" {
|
2020-03-30 23:05:53 +00:00
|
|
|
impl := strings.ToUpper(u.FilterToAlnum(v.ServerImplementationString))
|
|
|
|
resp[fmt.Sprintf("SOFTWARE_%s", impl)]++
|
2019-11-06 07:03:42 +00:00
|
|
|
}
|
|
|
|
v.Unlock()
|
|
|
|
}
|
|
|
|
return resp
|
|
|
|
}
|
|
|
|
|
2020-04-05 01:37:30 +00:00
|
|
|
func (a *Server) notFoundHandler(c echo.Context) error {
|
|
|
|
return c.String(http.StatusNotFound, "404 not found")
|
|
|
|
}
|
|
|
|
|
2020-04-05 01:16:37 +00:00
|
|
|
func (a *Server) instanceHandler(c echo.Context) error {
|
|
|
|
tu := c.Param("uuid")
|
|
|
|
u, err := uuid.Parse(tu)
|
|
|
|
if err != nil {
|
2020-04-05 01:40:34 +00:00
|
|
|
return a.notFoundHandler(c)
|
2020-04-05 01:16:37 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 01:32:25 +00:00
|
|
|
tc := pongo2.Context{}
|
|
|
|
instances := a.feta.manager.ListInstances()
|
2020-04-05 01:40:34 +00:00
|
|
|
found := false
|
2020-04-05 01:32:25 +00:00
|
|
|
for _, item := range instances {
|
|
|
|
if item.UUID == u {
|
|
|
|
tc["instance"] = item
|
2020-04-05 01:40:34 +00:00
|
|
|
found = true
|
2020-04-05 01:32:25 +00:00
|
|
|
}
|
2020-04-05 01:16:37 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 01:40:34 +00:00
|
|
|
if !found {
|
2020-04-05 01:37:30 +00:00
|
|
|
return a.notFoundHandler(c)
|
|
|
|
}
|
|
|
|
|
2020-04-05 01:16:37 +00:00
|
|
|
return c.Render(http.StatusOK, "instance.html", tc)
|
|
|
|
}
|
|
|
|
|
2020-03-30 23:05:53 +00:00
|
|
|
func (a *Server) indexHandler(c echo.Context) error {
|
2020-04-09 10:08:31 +00:00
|
|
|
count, err := a.feta.dbm.TotalTootCount()
|
|
|
|
if err != nil {
|
|
|
|
count = 0
|
|
|
|
}
|
|
|
|
tc := pongo2.Context{
|
|
|
|
"time": time.Now().UTC().Format(time.RFC3339Nano),
|
|
|
|
"gitrev": a.feta.version,
|
|
|
|
"tootCount": count,
|
|
|
|
"instances": a.instances(),
|
|
|
|
"instanceStatusSummary": a.instanceStatusSummary(),
|
|
|
|
}
|
|
|
|
return c.Render(http.StatusOK, "index.html", tc)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *Server) instanceListHandler(c echo.Context) error {
|
|
|
|
il := a.instances()
|
2020-03-30 23:05:53 +00:00
|
|
|
tc := pongo2.Context{
|
2020-04-05 01:16:37 +00:00
|
|
|
"time": time.Now().UTC().Format(time.RFC3339Nano),
|
|
|
|
"gitrev": a.feta.version,
|
2020-04-09 10:08:31 +00:00
|
|
|
"instances": il,
|
2019-11-05 23:32:09 +00:00
|
|
|
}
|
2020-04-09 10:08:31 +00:00
|
|
|
return c.Render(http.StatusOK, "instancelist.html", tc)
|
2019-11-05 23:32:09 +00:00
|
|
|
}
|
|
|
|
|
2020-03-30 23:05:53 +00:00
|
|
|
func (a *Server) statsHandler(c echo.Context) error {
|
2020-04-09 10:08:31 +00:00
|
|
|
index := &hash{
|
|
|
|
"server": &hash{
|
2020-03-30 23:05:53 +00:00
|
|
|
"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,
|
|
|
|
},
|
2020-04-09 10:08:31 +00:00
|
|
|
"instanceStatusSummary": a.instanceStatusSummary(),
|
2020-03-30 23:05:53 +00:00
|
|
|
}
|
2019-11-05 23:32:09 +00:00
|
|
|
|
2020-03-30 23:05:53 +00:00
|
|
|
return c.JSONPretty(http.StatusOK, index, " ")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *Server) healthCheckHandler(c echo.Context) error {
|
2020-04-09 10:08:31 +00:00
|
|
|
resp := &hash{
|
2020-03-30 23:05:53 +00:00
|
|
|
"status": "ok",
|
|
|
|
"now": time.Now().UTC().Format(time.RFC3339),
|
|
|
|
"uptime": a.feta.uptime().String(),
|
2019-11-05 23:32:09 +00:00
|
|
|
}
|
2020-03-30 23:05:53 +00:00
|
|
|
return c.JSONPretty(http.StatusOK, resp, " ")
|
|
|
|
|
2019-11-05 23:32:09 +00:00
|
|
|
}
|