From c646179fa9534dd17b4c970c7bf1ba94ef72d839 Mon Sep 17 00:00:00 2001 From: Gibheer Date: Wed, 2 Jan 2019 16:09:04 +0100 Subject: monfront - show groups This is the first step to view the group status. The templates were split into multipe parts, to make reuse easier. --- cmd/monfront/main.go | 202 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 138 insertions(+), 64 deletions(-) diff --git a/cmd/monfront/main.go b/cmd/monfront/main.go index 87ae717..10dd803 100644 --- a/cmd/monfront/main.go +++ b/cmd/monfront/main.go @@ -19,6 +19,7 @@ import ( var ( configPath = flag.String("config", "monfront.conf", "path to the config file") DB *sql.DB + Tmpl *template.Template ) type ( @@ -28,8 +29,10 @@ type ( } Context struct { + Title string Mappings map[int]map[int]MapEntry Checks []check + Groups []group } MapEntry struct { @@ -38,6 +41,7 @@ type ( } check struct { + NodeId int NodeName string CommandName string CheckID int64 @@ -48,6 +52,15 @@ type ( NextTime time.Time Msg string } + + group struct { + GroupId int + Name string + NodeId int + NodeName string + State int + MappingId int + } ) func main() { @@ -68,11 +81,21 @@ func main() { } DB = db + tmpl := template.New("main") + tmpl.Funcs(Funcs) + for k, val := range Templates { + template.Must(tmpl.New(k).Parse(val)) + } + Tmpl = tmpl + http.HandleFunc("/", showChecks) + http.HandleFunc("/checks", showChecks) + http.HandleFunc("/hosts", showHosts) + http.HandleFunc("/groups", showGroups) http.HandleFunc("/action", checkAction) http.HandleFunc("/unhandled/checks", showChecks) - http.HandleFunc("/unhandled/hosts", showUnhandledHosts) - http.HandleFunc("/unhandled/groups", showUnhandledGroups) + http.HandleFunc("/unhandled/hosts", showHosts) + http.HandleFunc("/unhandled/groups", showGroups) http.ListenAndServe(config.Listen, nil) } @@ -161,11 +184,38 @@ func checkAction(w http.ResponseWriter, r *http.Request) { } func showChecks(w http.ResponseWriter, r *http.Request) { - query := SQLShowChecks + query := `select c.id, n.id, n.name, co.name, ac.mapping_id, ac.states[1] as state, + ac.enabled, ac.notice, ac.next_time, ac.msg + from active_checks ac + join checks c on ac.check_id = c.id + join nodes n on c.node_id = n.id + join commands co on c.command_id = co.id` + where := []string{} if strings.HasPrefix(r.URL.Path, "/unhandled") { - query = SQLShowUnhandledChecks + where = append(where, `ac.states[1] > 0`) } - rows, err := DB.Query(query) + idx := 0 + params := []interface{}{} + if id, found := r.URL.Query()["node_id"]; found { + idx += 1 + where = append(where, fmt.Sprintf("n.id = $%d::int", idx)) + params = append(params, id[0]) + } + if id, found := r.URL.Query()["command_id"]; found { + idx += 1 + where = append(where, fmt.Sprintf("co.id = $%d::int", idx)) + params = append(params, id[0]) + } + if id, found := r.URL.Query()["check_id"]; found { + idx += 1 + where = append(where, fmt.Sprintf("c.id = $%d::int", idx)) + params = append(params, id[0]) + } + if len(where) > 0 { + query += " where " + strings.Join(where, " and ") + } + query += ` order by n.name, co.name` + rows, err := DB.Query(query, params...) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("problems with the database")) @@ -176,7 +226,7 @@ func showChecks(w http.ResponseWriter, r *http.Request) { checks := []check{} for rows.Next() { c := check{} - err := rows.Scan(&c.CheckID, &c.NodeName, &c.CommandName, &c.MappingId, &c.State, &c.Enabled, &c.Notice, &c.NextTime, &c.Msg) + err := rows.Scan(&c.CheckID, &c.NodeId, &c.NodeName, &c.CommandName, &c.MappingId, &c.State, &c.Enabled, &c.Notice, &c.NextTime, &c.Msg) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("problems with the database")) @@ -185,15 +235,6 @@ func showChecks(w http.ResponseWriter, r *http.Request) { } checks = append(checks, c) } - tmpl := template.New("checklist") - tmpl.Funcs(Funcs) - tmpl, err = tmpl.Parse(TmplCheckList) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte("problems with a template")) - log.Printf("could not parse template: %s", err) - return - } con := Context{ Checks: checks, } @@ -204,7 +245,7 @@ func showChecks(w http.ResponseWriter, r *http.Request) { return } w.Header()["Content-Type"] = []string{"text/html"} - if err := tmpl.Execute(w, con); err != nil { + if err := Tmpl.ExecuteTemplate(w, "checklist", con); err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("problem with a template")) log.Printf("could not execute template: %s", err) @@ -213,11 +254,26 @@ func showChecks(w http.ResponseWriter, r *http.Request) { return } -func showUnhandledHosts(w http.ResponseWriter, r *http.Request) { +func showHosts(w http.ResponseWriter, r *http.Request) { } -func showUnhandledGroups(w http.ResponseWriter, r *http.Request) { - rows, err := DB.Query(SQLShowUnhandledGroups) +func showGroups(w http.ResponseWriter, r *http.Request) { + query := `select groupid, groupname, nodeid, nodename, mapping_id, state + from ( + select g.id groupid, g.name groupname, n.id nodeid, n.name nodename, ac.mapping_id, + ac.states[1] state, max(ac.states[1]) over (partition by c.node_id) maxstate + from groups g + join nodes_groups ng on g.id = ng.group_id + join nodes n on ng.node_id = n.id + join checks c on n.id = c.node_id + join active_checks ac on c.id = ac.check_id + join mapping_level ml on ac.mapping_id = ml.mapping_id and ac.states[1] = ml.target + ) s + where state = maxstate` + if strings.HasPrefix(r.URL.Path, "/unhandled") { + query += ` and state > 0` + } + rows, err := DB.Query(query) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("problems with the database")) @@ -225,32 +281,29 @@ func showUnhandledGroups(w http.ResponseWriter, r *http.Request) { return } - type check struct { - GroupName string - NodeName string - State int - } - checks := []check{} + groups := []group{} for rows.Next() { - c := check{} - err := rows.Scan(&c.GroupName, &c.NodeName, &c.State) + g := group{} + err := rows.Scan(&g.GroupId, &g.Name, &g.NodeId, &g.NodeName, &g.MappingId, &g.State) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("problems with the database")) log.Printf("could not get check list: %s", err) return } - checks = append(checks, c) + groups = append(groups, g) } - tmpl, err := template.New("checklist").Parse(TmplUnhandledGroups) - if err != nil { + con := Context{ + Groups: groups, + } + if err := loadMappings(&con); err != nil { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte("problems with a template")) - log.Printf("could not parse template: %s", err) + w.Write([]byte("problem with the mappings")) + log.Printf("could not load mappings: %s", err) return } w.Header()["Content-Type"] = []string{"text/html"} - if err := tmpl.Execute(w, checks); err != nil { + if err := Tmpl.ExecuteTemplate(w, "grouplist", con); err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("problem with a template")) log.Printf("could not execute template: %s", err) @@ -292,36 +345,14 @@ func loadMappings(c *Context) error { var ( SQLShowMappings = `select mapping_id, target, title, color from mapping_level` - SQLShowChecks = `select c.id, n.name, co.name, ac.mapping_id, ac.states[1] as state, - ac.enabled, ac.notice, ac.next_time, ac.msg - from active_checks ac - join checks c on ac.check_id = c.id - join nodes n on c.node_id = n.id - join commands co on c.command_id = co.id - order by n.name, co.name;` - SQLShowUnhandledChecks = `select c.id, n.name, co.name, ac.mapping_id, ac.states[1] as state, - ac.enabled, ac.notice, ac.next_time, ac.msg - from active_checks ac - join checks c on ac.check_id = c.id - join nodes n on c.node_id = n.id - join commands co on c.command_id = co.id - where ac.states[1] > 0 - order by n.name, co.name;` - SQLShowUnhandledGroups = `select g.name, n.name, max(ac.state[1]) - from groups g - join nodes_groups ng on g.id = ng.group_id - join nodes n on ng.node_id = n.id - join checks c on n.id = c.node_id - join active_checks ac on c.id = ac.check_id - where ac.states[1] > 0 - group by g.name, n.name;` ) var ( - TmplCheckList = ` + Templates = map[string]string{ + "header": ` - - check list + + {{ .Title }} @@ -357,7 +388,9 @@ var (
  • unhandled hosts
  • unhandled groups
  • - + `, + "footer": ``, + "checklist": `{{ template "header" . }}