Blame


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