icinga

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

checker.go (2833B)


      1 package icinga
      2 
      3 import (
      4 	"bytes"
      5 	"encoding/json"
      6 	"fmt"
      7 	"net/http"
      8 	"strings"
      9 )
     10 
     11 type checker interface {
     12 	object
     13 	Check(*Client) error
     14 }
     15 
     16 type checkFilter struct {
     17 	Type string `json:"type"`
     18 	Expr string `json:"filter"`
     19 }
     20 
     21 type StateType int
     22 
     23 const (
     24 	StateSoft StateType = 0 + iota
     25 	StateHard
     26 )
     27 
     28 func (st StateType) String() string {
     29 	switch st {
     30 	case StateSoft:
     31 		return "StateSoft"
     32 	case StateHard:
     33 		return "StateHard"
     34 	}
     35 	return "unsupported state type"
     36 }
     37 
     38 // Check reschedules the check for s via the provided Client.
     39 func (s Service) Check(c *Client) error {
     40 	return c.check(s)
     41 }
     42 
     43 // Check reschedules the check for h via the provided Client.
     44 func (h Host) Check(c *Client) error {
     45 	return c.check(h)
     46 }
     47 
     48 // Check reschedules the checks for all hosts in the HostGroup hg via the
     49 // provided Client.
     50 func (hg HostGroup) Check(c *Client) error {
     51 	return c.check(hg)
     52 }
     53 
     54 func splitServiceName(name string) []string {
     55 	return strings.SplitN(name, "!", 2)
     56 }
     57 
     58 func (c *Client) check(ch checker) error {
     59 	switch v := ch.(type) {
     60 	case Host:
     61 		return c.CheckHosts(fmt.Sprintf("host.name == %q", v.Name))
     62 	case Service:
     63 		a := splitServiceName(v.Name)
     64 		if len(a) != 2 {
     65 			return fmt.Errorf("check %s: invalid service name", v.Name)
     66 		}
     67 		host := a[0]
     68 		service := a[1]
     69 		return c.CheckServices(fmt.Sprintf("host.name == %q && service.name == %q", host, service))
     70 	case HostGroup:
     71 		return c.CheckHosts(fmt.Sprintf("%q in host.groups", v.Name))
     72 	default:
     73 		return fmt.Errorf("cannot check %T", v)
     74 	}
     75 }
     76 
     77 // CheckHosts schedules checks for all services matching the filter expression
     78 // filter. If no services match the filter, error wraps ErrNoMatch.
     79 func (c *Client) CheckServices(filter string) error {
     80 	f := checkFilter{
     81 		Type: "Service",
     82 		Expr: filter,
     83 	}
     84 	if err := scheduleCheck(c, f); err != nil {
     85 		return fmt.Errorf("check services %s: %w", filter, err)
     86 	}
     87 	return nil
     88 }
     89 
     90 // CheckHosts schedules checks for all hosts matching the filter expression
     91 // filter. If no hosts match the filter, error wraps ErrNoMatch.
     92 func (c *Client) CheckHosts(filter string) error {
     93 	f := checkFilter{
     94 		Type: "Host",
     95 		Expr: filter,
     96 	}
     97 	if err := scheduleCheck(c, f); err != nil {
     98 		return fmt.Errorf("check hosts %s: %w", filter, err)
     99 	}
    100 	return nil
    101 }
    102 
    103 func scheduleCheck(c *Client, filter checkFilter) error {
    104 	buf := &bytes.Buffer{}
    105 	if err := json.NewEncoder(buf).Encode(filter); err != nil {
    106 		return err
    107 	}
    108 	resp, err := c.post("/actions/reschedule-check", buf)
    109 	if err != nil {
    110 		return err
    111 	}
    112 	if resp.StatusCode == http.StatusOK {
    113 		return nil
    114 	}
    115 
    116 	defer resp.Body.Close()
    117 	iresp, err := parseResponse(resp.Body)
    118 	if err != nil {
    119 		return fmt.Errorf("parse response: %v", err)
    120 	} else if iresp.Error != nil {
    121 		return iresp.Error
    122 	} else if len(iresp.Results) == 0 {
    123 		return ErrNoMatch
    124 	}
    125 	return fmt.Errorf("%s", resp.Status)
    126 }