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