Blob


1 package icinga
3 import (
4 "encoding/json"
5 "errors"
6 "fmt"
7 "io"
8 "strings"
9 )
11 type apiResponse struct {
12 Results []struct {
13 Name string
14 Type string
15 Errors []string
16 Permissions []string
17 Attrs json.RawMessage
18 }
19 Status string
20 }
22 type response struct {
23 Results []object
24 Error error
25 }
27 func parseAPIResponse(r io.Reader) (apiResponse, error) {
28 var apiresp apiResponse
29 if err := json.NewDecoder(r).Decode(&apiresp); err != nil {
30 return apiResponse{}, err
31 }
32 return apiresp, nil
33 }
35 func parseResponse(r io.Reader) (*response, error) {
36 apiresp, err := parseAPIResponse(r)
37 if err != nil {
38 return nil, err
39 }
40 // Confusingly the top-level status field in an API response contains
41 // an error message. Successful statuses are actually held in the
42 // status field in Results!
43 if apiresp.Status != "" {
44 return &response{Error: errors.New(apiresp.Status)}, nil
45 }
46 resp := &response{}
47 for _, r := range apiresp.Results {
48 if len(r.Errors) > 0 {
49 resp.Error = errors.New(strings.Join(r.Errors, ", "))
50 // got an error so nothing left in the API response
51 break
52 }
53 if r.Type == "" {
54 continue //
55 }
56 switch r.Type {
57 case "Host":
58 var h Host
59 h.Name = r.Name
60 if err := json.Unmarshal(r.Attrs, &h); err != nil {
61 return nil, err
62 }
63 resp.Results = append(resp.Results, h)
64 case "Service":
65 var s Service
66 s.Name = r.Name
67 if err := json.Unmarshal(r.Attrs, &s); err != nil {
68 return nil, err
69 }
70 resp.Results = append(resp.Results, s)
71 case "User":
72 var u User
73 u.Name = r.Name
74 if err := json.Unmarshal(r.Attrs, &u); err != nil {
75 return nil, err
76 }
77 resp.Results = append(resp.Results, u)
78 case "HostGroup":
79 var h HostGroup
80 h.Name = r.Name
81 if err := json.Unmarshal(r.Attrs, &h); err != nil {
82 return nil, err
83 }
84 resp.Results = append(resp.Results, h)
85 default:
86 return nil, fmt.Errorf("unsupported unmarshal of type %s", r.Type)
87 }
88 }
89 return resp, nil
90 }
92 func objectFromLookup(resp *response) (object, error) {
93 if len(resp.Results) == 0 {
94 return nil, errors.New("empty results")
95 } else if len(resp.Results) > 1 {
96 return nil, errors.New("too many results")
97 }
98 return resp.Results[0], nil
99 }