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 }