1package pagerduty 2 3import ( 4 "fmt" 5 "net/http" 6 7 "github.com/google/go-querystring/query" 8) 9 10// Integration is an endpoint (like Nagios, email, or an API call) that generates events, which are normalized and de-duplicated by PagerDuty to create incidents. 11type Integration struct { 12 APIObject 13 Name string `json:"name,omitempty"` 14 Service *APIObject `json:"service,omitempty"` 15 CreatedAt string `json:"created_at,omitempty"` 16 Vendor *APIObject `json:"vendor,omitempty"` 17 Type string `json:"type,omitempty"` 18 IntegrationKey string `json:"integration_key,omitempty"` 19 IntegrationEmail string `json:"integration_email,omitempty"` 20} 21 22// InlineModel represents when a scheduled action will occur. 23type InlineModel struct { 24 Type string `json:"type,omitempty"` 25 Name string `json:"name,omitempty"` 26} 27 28// ScheduledAction contains scheduled actions for the service. 29type ScheduledAction struct { 30 Type string `json:"type,omitempty"` 31 At InlineModel `json:"at,omitempty"` 32 ToUrgency string `json:"to_urgency"` 33} 34 35// IncidentUrgencyType are the incidents urgency during or outside support hours. 36type IncidentUrgencyType struct { 37 Type string `json:"type,omitempty"` 38 Urgency string `json:"urgency,omitempty"` 39} 40 41// SupportHours are the support hours for the service. 42type SupportHours struct { 43 Type string `json:"type,omitempty"` 44 Timezone string `json:"time_zone,omitempty"` 45 StartTime string `json:"start_time,omitempty"` 46 EndTime string `json:"end_time,omitempty"` 47 DaysOfWeek []uint `json:"days_of_week,omitempty"` 48} 49 50// IncidentUrgencyRule is the default urgency for new incidents. 51type IncidentUrgencyRule struct { 52 Type string `json:"type,omitempty"` 53 Urgency string `json:"urgency,omitempty"` 54 DuringSupportHours *IncidentUrgencyType `json:"during_support_hours,omitempty"` 55 OutsideSupportHours *IncidentUrgencyType `json:"outside_support_hours,omitempty"` 56} 57 58// Service represents something you monitor (like a web service, email service, or database service). 59type Service struct { 60 APIObject 61 Name string `json:"name,omitempty"` 62 Description string `json:"description,omitempty"` 63 AutoResolveTimeout *uint `json:"auto_resolve_timeout"` 64 AcknowledgementTimeout *uint `json:"acknowledgement_timeout"` 65 CreateAt string `json:"created_at,omitempty"` 66 Status string `json:"status,omitempty"` 67 LastIncidentTimestamp string `json:"last_incident_timestamp,omitempty"` 68 Integrations []Integration `json:"integrations,omitempty"` 69 EscalationPolicy EscalationPolicy `json:"escalation_policy,omitempty"` 70 Teams []Team `json:"teams,omitempty"` 71 IncidentUrgencyRule *IncidentUrgencyRule `json:"incident_urgency_rule,omitempty"` 72 SupportHours *SupportHours `json:"support_hours,omitempty"` 73 ScheduledActions []ScheduledAction `json:"scheduled_actions,omitempty"` 74 AlertCreation string `json:"alert_creation,omitempty"` 75} 76 77// ListServiceOptions is the data structure used when calling the ListServices API endpoint. 78type ListServiceOptions struct { 79 APIListObject 80 TeamIDs []string `url:"team_ids,omitempty,brackets"` 81 TimeZone string `url:"time_zone,omitempty"` 82 SortBy string `url:"sort_by,omitempty"` 83 Query string `url:"query,omitempty"` 84 Includes []string `url:"include,omitempty,brackets"` 85} 86 87// ListServiceResponse is the data structure returned from calling the ListServices API endpoint. 88type ListServiceResponse struct { 89 APIListObject 90 Services []Service 91} 92 93// ListServices lists existing services. 94func (c *Client) ListServices(o ListServiceOptions) (*ListServiceResponse, error) { 95 v, err := query.Values(o) 96 if err != nil { 97 return nil, err 98 } 99 resp, err := c.get("/services?" + v.Encode()) 100 if err != nil { 101 return nil, err 102 } 103 var result ListServiceResponse 104 return &result, c.decodeJSON(resp, &result) 105} 106 107// GetServiceOptions is the data structure used when calling the GetService API endpoint. 108type GetServiceOptions struct { 109 Includes []string `url:"include,brackets,omitempty"` 110} 111 112// GetService gets details about an existing service. 113func (c *Client) GetService(id string, o *GetServiceOptions) (*Service, error) { 114 v, err := query.Values(o) 115 resp, err := c.get("/services/" + id + "?" + v.Encode()) 116 return getServiceFromResponse(c, resp, err) 117} 118 119// CreateService creates a new service. 120func (c *Client) CreateService(s Service) (*Service, error) { 121 data := make(map[string]Service) 122 data["service"] = s 123 resp, err := c.post("/services", data, nil) 124 return getServiceFromResponse(c, resp, err) 125} 126 127// UpdateService updates an existing service. 128func (c *Client) UpdateService(s Service) (*Service, error) { 129 resp, err := c.put("/services/"+s.ID, s, nil) 130 return getServiceFromResponse(c, resp, err) 131} 132 133// DeleteService deletes an existing service. 134func (c *Client) DeleteService(id string) error { 135 _, err := c.delete("/services/" + id) 136 return err 137} 138 139// CreateIntegration creates a new integration belonging to a service. 140func (c *Client) CreateIntegration(id string, i Integration) (*Integration, error) { 141 data := make(map[string]Integration) 142 data["integration"] = i 143 resp, err := c.post("/services/"+id+"/integrations", data, nil) 144 return getIntegrationFromResponse(c, resp, err) 145} 146 147// GetIntegrationOptions is the data structure used when calling the GetIntegration API endpoint. 148type GetIntegrationOptions struct { 149 Includes []string `url:"include,omitempty,brackets"` 150} 151 152// GetIntegration gets details about an integration belonging to a service. 153func (c *Client) GetIntegration(serviceID, integrationID string, o GetIntegrationOptions) (*Integration, error) { 154 v, queryErr := query.Values(o) 155 if queryErr != nil { 156 return nil, queryErr 157 } 158 resp, err := c.get("/services/" + serviceID + "/integrations/" + integrationID + "?" + v.Encode()) 159 return getIntegrationFromResponse(c, resp, err) 160} 161 162// UpdateIntegration updates an integration belonging to a service. 163func (c *Client) UpdateIntegration(serviceID string, i Integration) (*Integration, error) { 164 resp, err := c.put("/services/"+serviceID+"/integrations/"+i.ID, i, nil) 165 return getIntegrationFromResponse(c, resp, err) 166} 167 168// DeleteIntegration deletes an existing integration. 169func (c *Client) DeleteIntegration(serviceID string, integrationID string) error { 170 _, err := c.delete("/services/" + serviceID + "/integrations/" + integrationID) 171 return err 172} 173 174func getServiceFromResponse(c *Client, resp *http.Response, err error) (*Service, error) { 175 if err != nil { 176 return nil, err 177 } 178 var target map[string]Service 179 if dErr := c.decodeJSON(resp, &target); dErr != nil { 180 return nil, fmt.Errorf("Could not decode JSON response: %v", dErr) 181 } 182 rootNode := "service" 183 t, nodeOK := target[rootNode] 184 if !nodeOK { 185 return nil, fmt.Errorf("JSON response does not have %s field", rootNode) 186 } 187 return &t, nil 188} 189 190func getIntegrationFromResponse(c *Client, resp *http.Response, err error) (*Integration, error) { 191 if err != nil { 192 return nil, err 193 } 194 var target map[string]Integration 195 if dErr := c.decodeJSON(resp, &target); dErr != nil { 196 return nil, fmt.Errorf("Could not decode JSON response: %v", err) 197 } 198 rootNode := "integration" 199 t, nodeOK := target[rootNode] 200 if !nodeOK { 201 return nil, fmt.Errorf("JSON response does not have %s field", rootNode) 202 } 203 return &t, nil 204} 205