checkweb.go (4384B)
1 // Command checkweb is a web application for... 2 package main 3 4 import ( 5 "crypto/tls" 6 "errors" 7 "fmt" 8 "html/template" 9 "log" 10 "net/http" 11 "net/url" 12 "path" 13 14 "olowe.co/icinga" 15 ) 16 17 type server struct { 18 tmpl struct { 19 services *template.Template 20 service *template.Template 21 hosts *template.Template 22 host *template.Template 23 root *template.Template 24 } 25 client *icinga.Client 26 } 27 28 func (srv *server) servicesHandler(w http.ResponseWriter, req *http.Request) { 29 filter := req.URL.Query().Get("filter") 30 services, err := srv.client.Services(filter) 31 if err != nil { 32 http.Error(w, err.Error(), http.StatusInternalServerError) 33 log.Print(err) 34 return 35 } 36 if err := srv.tmpl.services.Execute(w, services); err != nil { 37 log.Println("render services:", err) 38 } 39 } 40 41 func (srv *server) hostsHandler(w http.ResponseWriter, req *http.Request) { 42 filter := req.URL.Query().Get("filter") 43 hosts, err := srv.client.Hosts(filter) 44 if err != nil { 45 http.Error(w, err.Error(), http.StatusInternalServerError) 46 log.Print(err) 47 return 48 } 49 if err := srv.tmpl.hosts.Execute(w, hosts); err != nil { 50 log.Println("render hosts:", err) 51 } 52 } 53 54 func (srv *server) hostHandler(w http.ResponseWriter, req *http.Request) { 55 base := path.Base(req.URL.Path) 56 name, err := url.PathUnescape(base) 57 if err != nil { 58 msg := fmt.Sprintf("escape object name: %v", err) 59 log.Println(err) 60 http.Error(w, msg, http.StatusBadRequest) 61 return 62 } 63 host, err := srv.client.LookupHost(name) 64 if err != nil { 65 msg := fmt.Sprintf("lookup %s: %v", name, err) 66 code := http.StatusInternalServerError 67 if errors.Is(err, icinga.ErrNotExist) { 68 code = http.StatusNotFound 69 } 70 http.Error(w, msg, code) 71 return 72 } 73 74 if err := srv.tmpl.host.Execute(w, host); err != nil { 75 log.Println("render hosts:", err) 76 } 77 } 78 79 func (srv *server) serviceHandler(w http.ResponseWriter, req *http.Request) { 80 p := req.URL.Path 81 if req.URL.RawPath != "" { 82 p = req.URL.RawPath 83 } 84 base := path.Base(p) 85 name, err := url.PathUnescape(base) 86 if err != nil { 87 msg := fmt.Sprintf("escape object name: %v", err) 88 log.Println(err) 89 http.Error(w, msg, http.StatusBadRequest) 90 return 91 } 92 fmt.Println("looking up", name) 93 service, err := srv.client.LookupService(name) 94 if err != nil { 95 msg := fmt.Sprintf("lookup %s: %v", name, err) 96 code := http.StatusInternalServerError 97 if errors.Is(err, icinga.ErrNotExist) { 98 code = http.StatusNotFound 99 } 100 http.Error(w, msg, code) 101 return 102 } 103 104 if err := srv.tmpl.service.Execute(w, service); err != nil { 105 log.Println("render service:", err) 106 } 107 } 108 109 func (srv *server) searchHandler(w http.ResponseWriter, req *http.Request) { 110 var u url.URL 111 typ := req.URL.Query().Get("type") 112 switch typ { 113 case "host": 114 u.Path = "/objects/hosts" 115 case "service": 116 u.Path = "/objects/services" 117 } 118 v := url.Values{} 119 v.Set("filter", req.URL.Query().Get("filter")) 120 u.RawQuery = v.Encode() 121 http.Redirect(w, req, u.String(), http.StatusFound) 122 } 123 124 func (srv *server) rootHandler(w http.ResponseWriter, req *http.Request) { 125 if err := srv.tmpl.root.Execute(w, nil); err != nil { 126 log.Println(err) 127 } 128 } 129 130 var tFuncMap = template.FuncMap{ 131 "pathescape": url.PathEscape, 132 } 133 134 func newTemplate(root *template.Template, files ...string) (*template.Template, error) { 135 t, err := root.Clone() 136 if err != nil { 137 return nil, err 138 } 139 return t.ParseFiles(files...) 140 } 141 142 func main() { 143 t := http.DefaultTransport.(*http.Transport) 144 t.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} 145 c := http.DefaultClient 146 c.Transport = t 147 client, err := icinga.Dial("127.0.0.1:5665", "", "", c) 148 if err != nil { 149 log.Fatal(err) 150 } 151 srv := &server{ 152 client: client, 153 } 154 155 srv.tmpl.root = template.Must(template.ParseFiles("base.tmpl")).Funcs(tFuncMap) 156 srv.tmpl.services = template.Must(newTemplate(srv.tmpl.root, "services.tmpl")) 157 srv.tmpl.service = template.Must(newTemplate(srv.tmpl.root, "service.tmpl")) 158 srv.tmpl.hosts = template.Must(newTemplate(srv.tmpl.root, "hosts.tmpl")) 159 srv.tmpl.host = template.Must(newTemplate(srv.tmpl.root, "host.tmpl")) 160 161 http.HandleFunc("/objects/services", srv.servicesHandler) 162 http.HandleFunc("/objects/services/", srv.serviceHandler) 163 http.HandleFunc("/objects/hosts", srv.hostsHandler) 164 http.HandleFunc("/objects/hosts/", srv.hostHandler) 165 http.HandleFunc("/search", srv.searchHandler) 166 http.HandleFunc("/", srv.rootHandler) 167 log.Fatal(http.ListenAndServe(":6969", nil)) 168 }