icinga

Icinga2 API client in Go
git clone https://git.olowe.co/icinga
Log | Files | Refs | README | LICENSE

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 }