Blob


1 package icinga
3 import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "net/http"
8 "strings"
9 )
11 type checker interface {
12 object
13 Check(*Client) error
14 }
16 type checkFilter struct {
17 Type string `json:"type"`
18 Expr string `json:"filter"`
19 }
21 type StateType int
23 const (
24 StateSoft StateType = 0 + iota
25 StateHard
26 )
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 }
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 }
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 }
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 }
54 func splitServiceName(name string) []string {
55 return strings.SplitN(name, "!", 2)
56 }
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 }
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 }
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
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
108 resp, err := c.post("/actions/reschedule-check", buf)
109 if err != nil {
110 return err
112 if resp.StatusCode == http.StatusOK {
113 return nil
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
125 return fmt.Errorf("%s", resp.Status)