From 838dbdad78c4ba7a6ed7d56987cf31a209981321 Mon Sep 17 00:00:00 2001 From: Louis Delossantos Date: Wed, 6 Jun 2018 11:10:25 -0400 Subject: [PATCH 01/10] add create structs, client support, headers in POST --- client.go | 9 +++++++-- incident.go | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/client.go b/client.go index ad61eee9..51aea355 100644 --- a/client.go +++ b/client.go @@ -39,6 +39,11 @@ type APIReference struct { Type string `json:"type,omitempty"` } +type APIDetails struct { + Type string `json:"type,omitempty"` + Details string `json:"details,omitempty"` +} + type errorObject struct { Code int `json:"code,omitempty"` Message string `json:"message,omitempty"` @@ -112,12 +117,12 @@ func (c *Client) put(path string, payload interface{}, headers *map[string]strin return c.do("PUT", path, nil, headers) } -func (c *Client) post(path string, payload interface{}) (*http.Response, error) { +func (c *Client) post(path string, payload interface{}, headers *map[string]string) (*http.Response, error) { data, err := json.Marshal(payload) if err != nil { return nil, err } - return c.do("POST", path, bytes.NewBuffer(data), nil) + return c.do("POST", path, bytes.NewBuffer(data), headers) } func (c *Client) get(path string) (*http.Response, error) { diff --git a/incident.go b/incident.go index 3c7a4330..5f8b9892 100644 --- a/incident.go +++ b/incident.go @@ -1,6 +1,7 @@ package pagerduty import ( + "encoding/json" "fmt" "github.com/google/go-querystring/query" @@ -80,13 +81,50 @@ func (c *Client) ListIncidents(o ListIncidentsOptions) (*ListIncidentsResponse, return &result, c.decodeJSON(resp, &result) } +// CreateIncidentOptions is the structure used when passing paremters to the CreateIncident API endpoint. +type CreateIncidentOptions struct { + // From is a valid email address appended to a From header when POSTing to the CreateIncident API endpoint. + From string +} + +// CreateIncident is the structure used when POSTing to the CreateIncident API endpoint. +type CreateIncident struct { + Incident struct { + Type string `json:"type"` + Title string `json:"title"` + Service APIReference `json:"service"` + Priority APIReference `json:"priority"` + IncidentKey string `json:"incident_key"` + Body APIDetails `json:"details"` + EscalationPolicy APIReference `json:"escalation_policy"` + } `json:"incident"` +} + +// CreateIncident creates an incident synchronously without a corresponding event from a monitoring service. +func (c *Client) CreateIncidents(o CreateIncidentOptions, i CreateIncident) (Incident, error) { + headers := make(map[string]string) + headers["From"] = o.From + resp, e := c.post("/incidents", i, &headers) + if e != nil { + return nil, e + } + + var ii Incident + e = json.NewDecoder(resp.Body).Decode(ii) + if e != nil { + return nil, e + } + + return ii, nil +} + // ManageIncidents acknowledges, resolves, escalates, or reassigns one or more incidents. func (c *Client) ManageIncidents(from string, incidents []Incident) error { r := make(map[string][]Incident) headers := make(map[string]string) headers["From"] = from r["incidents"] = incidents - _, e := c.put("/incidents", r, &headers) + resp, e := c.put("/incidents", r, &headers) return e } From fc0fa9c629b313fbd8fa546eac44b14e2e8108b7 Mon Sep 17 00:00:00 2001 From: Louis Delossantos Date: Wed, 6 Jun 2018 11:15:49 -0400 Subject: [PATCH 02/10] add nil to all post methods, remove wrongly placed resp var --- addon.go | 5 +++-- escalation_policy.go | 4 ++-- incident.go | 10 +++++----- maintenance_window.go | 5 +++-- schedule.go | 6 +++--- service.go | 4 ++-- team.go | 5 +++-- user.go | 5 +++-- 8 files changed, 24 insertions(+), 20 deletions(-) diff --git a/addon.go b/addon.go index ae9d4e57..d5490f3b 100644 --- a/addon.go +++ b/addon.go @@ -2,8 +2,9 @@ package pagerduty import ( "fmt" - "github.com/google/go-querystring/query" "net/http" + + "github.com/google/go-querystring/query" ) // Addon is a third-party add-on to PagerDuty's UI. @@ -46,7 +47,7 @@ func (c *Client) ListAddons(o ListAddonOptions) (*ListAddonResponse, error) { func (c *Client) InstallAddon(a Addon) (*Addon, error) { data := make(map[string]Addon) data["addon"] = a - resp, err := c.post("/addons", data) + resp, err := c.post("/addons", data, nil) defer resp.Body.Close() if err != nil { return nil, err diff --git a/escalation_policy.go b/escalation_policy.go index a8663df2..c8b50fe0 100644 --- a/escalation_policy.go +++ b/escalation_policy.go @@ -74,7 +74,7 @@ func (c *Client) ListEscalationPolicies(o ListEscalationPoliciesOptions) (*ListE func (c *Client) CreateEscalationPolicy(e EscalationPolicy) (*EscalationPolicy, error) { data := make(map[string]EscalationPolicy) data["escalation_policy"] = e - resp, err := c.post(escPath, data) + resp, err := c.post(escPath, data, nil) return getEscalationPolicyFromResponse(c, resp, err) } @@ -112,7 +112,7 @@ func (c *Client) UpdateEscalationPolicy(id string, e *EscalationPolicy) (*Escala func (c *Client) CreateEscalationRule(escID string, e EscalationRule) (*EscalationRule, error) { data := make(map[string]EscalationRule) data["escalation_rule"] = e - resp, err := c.post(escPath+"/"+escID+"/escalation_rules", data) + resp, err := c.post(escPath+"/"+escID+"/escalation_rules", data, nil) return getEscalationRuleFromResponse(c, resp, err) } diff --git a/incident.go b/incident.go index 5f8b9892..03571b23 100644 --- a/incident.go +++ b/incident.go @@ -101,7 +101,7 @@ type CreateIncident struct { } // CreateIncident creates an incident synchronously without a corresponding event from a monitoring service. -func (c *Client) CreateIncidents(o CreateIncidentOptions, i CreateIncident) (Incident, error) { +func (c *Client) CreateIncidents(o CreateIncidentOptions, i *CreateIncident) (*Incident, error) { headers := make(map[string]string) headers["From"] = o.From resp, e := c.post("/incidents", i, &headers) @@ -115,7 +115,7 @@ func (c *Client) CreateIncidents(o CreateIncidentOptions, i CreateIncident) (Inc return nil, e } - return ii, nil + return &ii, nil } // ManageIncidents acknowledges, resolves, escalates, or reassigns one or more incidents. @@ -124,7 +124,7 @@ func (c *Client) ManageIncidents(from string, incidents []Incident) error { headers := make(map[string]string) headers["From"] = from r["incidents"] = incidents - resp, e := c.put("/incidents", r, &headers) + _, e := c.put("/incidents", r, &headers) return e } @@ -174,7 +174,7 @@ func (c *Client) ListIncidentNotes(id string) ([]IncidentNote, error) { func (c *Client) CreateIncidentNote(id string, note IncidentNote) error { data := make(map[string]IncidentNote) data["note"] = note - _, err := c.post("/incidents/"+id+"/notes", data) + _, err := c.post("/incidents/"+id+"/notes", data, nil) return err } @@ -182,7 +182,7 @@ func (c *Client) CreateIncidentNote(id string, note IncidentNote) error { func (c *Client) SnoozeIncident(id string, duration uint) error { data := make(map[string]uint) data["duration"] = duration - _, err := c.post("/incidents/"+id+"/snooze", data) + _, err := c.post("/incidents/"+id+"/snooze", data, nil) return err } diff --git a/maintenance_window.go b/maintenance_window.go index 3b7e610d..2316f0fd 100644 --- a/maintenance_window.go +++ b/maintenance_window.go @@ -2,8 +2,9 @@ package pagerduty import ( "fmt" - "github.com/google/go-querystring/query" "net/http" + + "github.com/google/go-querystring/query" ) // MaintenanceWindow is used to temporarily disable one or more services for a set period of time. @@ -52,7 +53,7 @@ func (c *Client) ListMaintenanceWindows(o ListMaintenanceWindowsOptions) (*ListM func (c *Client) CreateMaintenanceWindows(m MaintenanceWindow) (*MaintenanceWindow, error) { data := make(map[string]MaintenanceWindow) data["maintenance_window"] = m - resp, err := c.post("/maintenance_windows", data) + resp, err := c.post("/maintenance_windows", data, nil) return getMaintenanceWindowFromResponse(c, resp, err) } diff --git a/schedule.go b/schedule.go index d6f76d06..40e0acde 100644 --- a/schedule.go +++ b/schedule.go @@ -84,7 +84,7 @@ func (c *Client) ListSchedules(o ListSchedulesOptions) (*ListSchedulesResponse, func (c *Client) CreateSchedule(s Schedule) (*Schedule, error) { data := make(map[string]Schedule) data["schedule"] = s - resp, err := c.post("/schedules", data) + resp, err := c.post("/schedules", data, nil) if err != nil { return nil, err } @@ -107,7 +107,7 @@ func (c *Client) PreviewSchedule(s Schedule, o PreviewScheduleOptions) error { } var data map[string]Schedule data["schedule"] = s - _, e := c.post("/schedules/preview?"+v.Encode(), data) + _, e := c.post("/schedules/preview?"+v.Encode(), data, nil) return e } @@ -196,7 +196,7 @@ func (c *Client) ListOverrides(id string, o ListOverridesOptions) ([]Override, e func (c *Client) CreateOverride(id string, o Override) (*Override, error) { data := make(map[string]Override) data["override"] = o - resp, err := c.post("/schedules/"+id+"/overrides", data) + resp, err := c.post("/schedules/"+id+"/overrides", data, nil) if err != nil { return nil, err } diff --git a/service.go b/service.go index 704762df..c30994e7 100644 --- a/service.go +++ b/service.go @@ -120,7 +120,7 @@ func (c *Client) GetService(id string, o *GetServiceOptions) (*Service, error) { func (c *Client) CreateService(s Service) (*Service, error) { data := make(map[string]Service) data["service"] = s - resp, err := c.post("/services", data) + resp, err := c.post("/services", data, nil) return getServiceFromResponse(c, resp, err) } @@ -140,7 +140,7 @@ func (c *Client) DeleteService(id string) error { func (c *Client) CreateIntegration(id string, i Integration) (*Integration, error) { data := make(map[string]Integration) data["integration"] = i - resp, err := c.post("/services/"+id+"/integrations", data) + resp, err := c.post("/services/"+id+"/integrations", data, nil) return getIntegrationFromResponse(c, resp, err) } diff --git a/team.go b/team.go index 096d4e8b..75ba20e7 100644 --- a/team.go +++ b/team.go @@ -2,8 +2,9 @@ package pagerduty import ( "fmt" - "github.com/google/go-querystring/query" "net/http" + + "github.com/google/go-querystring/query" ) // Team is a collection of users and escalation policies that represent a group of people within an organization. @@ -42,7 +43,7 @@ func (c *Client) ListTeams(o ListTeamOptions) (*ListTeamResponse, error) { // CreateTeam creates a new team. func (c *Client) CreateTeam(t *Team) (*Team, error) { - resp, err := c.post("/teams", t) + resp, err := c.post("/teams", t, nil) return getTeamFromResponse(c, resp, err) } diff --git a/user.go b/user.go index 2f7bad4c..92b170ed 100644 --- a/user.go +++ b/user.go @@ -2,8 +2,9 @@ package pagerduty import ( "fmt" - "github.com/google/go-querystring/query" "net/http" + + "github.com/google/go-querystring/query" ) // ContactMethod is a way of contacting the user. @@ -79,7 +80,7 @@ func (c *Client) ListUsers(o ListUsersOptions) (*ListUsersResponse, error) { func (c *Client) CreateUser(u User) (*User, error) { data := make(map[string]User) data["user"] = u - resp, err := c.post("/users", data) + resp, err := c.post("/users", data, nil) return getUserFromResponse(c, resp, err) } From 1c5869eb67ea426f8fdb2a13dae716dbae933cf7 Mon Sep 17 00:00:00 2001 From: Louis Delossantos Date: Wed, 6 Jun 2018 16:43:26 -0400 Subject: [PATCH 03/10] Include support for priorities endpoint --- priorites.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 priorites.go diff --git a/priorites.go b/priorites.go new file mode 100644 index 00000000..e0cb4bc2 --- /dev/null +++ b/priorites.go @@ -0,0 +1,33 @@ +package pagerduty + +import ( + "encoding/json" +) + +// PriorityProperty is a single priorty object returned from the Priorities endpoint +type PriorityProperty struct { + APIObject + Name string `json:"name"` + Description string `json:"description"` +} + +type Priorities struct { + APIListObject + Priorities []PriorityProperty `json:"priorities"` +} + +// ListPriorities lists existing priorities +func (c *Client) ListPriorities() (*Priorities, error) { + resp, e := c.get("/priorites") + if e != nil { + return nil, e + } + + var p Priorities + e = json.NewDecoder(resp.Body).Decode(&p) + if e != nil { + return nil, e + } + + return &p, nil +} From b631b8226fadfcbd585908cbb82a283762839816 Mon Sep 17 00:00:00 2001 From: Louis Delossantos Date: Wed, 6 Jun 2018 16:48:03 -0400 Subject: [PATCH 04/10] cleanup CreateIncident, use pointer in Decode method --- incident.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/incident.go b/incident.go index 03571b23..a4c48f12 100644 --- a/incident.go +++ b/incident.go @@ -81,12 +81,6 @@ func (c *Client) ListIncidents(o ListIncidentsOptions) (*ListIncidentsResponse, return &result, c.decodeJSON(resp, &result) } -// CreateIncidentOptions is the structure used when passing paremters to the CreateIncident API endpoint. -type CreateIncidentOptions struct { - // From is a valid email address appended to a From header when POSTing to the CreateIncident API endpoint. - From string -} - // CreateIncident is the structure used when POSTing to the CreateIncident API endpoint. type CreateIncident struct { Incident struct { @@ -101,16 +95,16 @@ type CreateIncident struct { } // CreateIncident creates an incident synchronously without a corresponding event from a monitoring service. -func (c *Client) CreateIncidents(o CreateIncidentOptions, i *CreateIncident) (*Incident, error) { +func (c *Client) CreateIncidents(from string, i *CreateIncident) (*Incident, error) { headers := make(map[string]string) - headers["From"] = o.From + headers["From"] = from resp, e := c.post("/incidents", i, &headers) if e != nil { return nil, e } var ii Incident - e = json.NewDecoder(resp.Body).Decode(ii) + e = json.NewDecoder(resp.Body).Decode(&ii) if e != nil { return nil, e } From 044ea577c12086ff93222e2c1bf57eef8ad435b1 Mon Sep 17 00:00:00 2001 From: Louis Delossantos Date: Wed, 6 Jun 2018 18:11:18 -0400 Subject: [PATCH 05/10] Un-nest create incident struct for cleaner API usage --- incident.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/incident.go b/incident.go index a4c48f12..d5d753b1 100644 --- a/incident.go +++ b/incident.go @@ -81,17 +81,20 @@ func (c *Client) ListIncidents(o ListIncidentsOptions) (*ListIncidentsResponse, return &result, c.decodeJSON(resp, &result) } -// CreateIncident is the structure used when POSTing to the CreateIncident API endpoint. +// type CreateIncident struct { - Incident struct { - Type string `json:"type"` - Title string `json:"title"` - Service APIReference `json:"service"` - Priority APIReference `json:"priority"` - IncidentKey string `json:"incident_key"` - Body APIDetails `json:"details"` - EscalationPolicy APIReference `json:"escalation_policy"` - } `json:"incident"` + Incident CreateIncidentValue `json:"incident"` +} + +// CreateIncidentValue is the structure used when POSTing to the CreateIncident API endpoint. +type CreateIncidentValue struct { + Type string `json:"type"` + Title string `json:"title"` + Service APIReference `json:"service"` + Priority APIReference `json:"priority"` + IncidentKey string `json:"incident_key"` + Body APIDetails `json:"details"` + EscalationPolicy APIReference `json:"escalation_policy"` } // CreateIncident creates an incident synchronously without a corresponding event from a monitoring service. From 96edd9c74280aa0578fbad130944f12c0163c0cb Mon Sep 17 00:00:00 2001 From: Louis Delossantos Date: Wed, 6 Jun 2018 18:13:11 -0400 Subject: [PATCH 06/10] fix typo in priorities endpoint --- priorites.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/priorites.go b/priorites.go index e0cb4bc2..69a33a2b 100644 --- a/priorites.go +++ b/priorites.go @@ -18,7 +18,7 @@ type Priorities struct { // ListPriorities lists existing priorities func (c *Client) ListPriorities() (*Priorities, error) { - resp, e := c.get("/priorites") + resp, e := c.get("/priorities") if e != nil { return nil, e } From 51d766368574de0019593ba351c0fd6f04aa5e86 Mon Sep 17 00:00:00 2001 From: Louis Delossantos Date: Wed, 6 Jun 2018 18:40:36 -0400 Subject: [PATCH 07/10] Wrap necessary incident structures --- incident.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/incident.go b/incident.go index d5d753b1..5a5528d2 100644 --- a/incident.go +++ b/incident.go @@ -81,11 +81,16 @@ func (c *Client) ListIncidents(o ListIncidentsOptions) (*ListIncidentsResponse, return &result, c.decodeJSON(resp, &result) } -// +// CreateIncident is the structure POST'd to the incidents endpoint. It wraps a CreateIncidentValue type CreateIncident struct { Incident CreateIncidentValue `json:"incident"` } +// CreatedIncidentResponse is returned from the API when creating a response. +type CreatedIncidentResponse struct { + Incident Incident `json:incident` +} + // CreateIncidentValue is the structure used when POSTing to the CreateIncident API endpoint. type CreateIncidentValue struct { Type string `json:"type"` @@ -106,13 +111,13 @@ func (c *Client) CreateIncidents(from string, i *CreateIncident) (*Incident, err return nil, e } - var ii Incident + var ii CreatedIncidentResponse e = json.NewDecoder(resp.Body).Decode(&ii) if e != nil { return nil, e } - return &ii, nil + return &ii.Incident, nil } // ManageIncidents acknowledges, resolves, escalates, or reassigns one or more incidents. From 1782ae90a2047c7338723fb07422d261b192f550 Mon Sep 17 00:00:00 2001 From: Louis Delossantos Date: Thu, 7 Jun 2018 11:32:33 -0400 Subject: [PATCH 08/10] Fix incorrect body json tag --- incident.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/incident.go b/incident.go index 5a5528d2..fcee23f0 100644 --- a/incident.go +++ b/incident.go @@ -86,8 +86,8 @@ type CreateIncident struct { Incident CreateIncidentValue `json:"incident"` } -// CreatedIncidentResponse is returned from the API when creating a response. -type CreatedIncidentResponse struct { +// CreateIncidentResponse is returned from the API when creating a response. +type CreateIncidentResponse struct { Incident Incident `json:incident` } @@ -98,7 +98,7 @@ type CreateIncidentValue struct { Service APIReference `json:"service"` Priority APIReference `json:"priority"` IncidentKey string `json:"incident_key"` - Body APIDetails `json:"details"` + Body APIDetails `json:"body"` EscalationPolicy APIReference `json:"escalation_policy"` } @@ -111,7 +111,7 @@ func (c *Client) CreateIncidents(from string, i *CreateIncident) (*Incident, err return nil, e } - var ii CreatedIncidentResponse + var ii CreateIncidentResponse e = json.NewDecoder(resp.Body).Decode(&ii) if e != nil { return nil, e From db3ac3d2a57c84102f97b0c024f9e92eea5f0f90 Mon Sep 17 00:00:00 2001 From: Louis Delossantos Date: Tue, 19 Jun 2018 13:17:33 -0400 Subject: [PATCH 09/10] remove plural, make private --- incident.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/incident.go b/incident.go index fcee23f0..dff90a5e 100644 --- a/incident.go +++ b/incident.go @@ -86,8 +86,8 @@ type CreateIncident struct { Incident CreateIncidentValue `json:"incident"` } -// CreateIncidentResponse is returned from the API when creating a response. -type CreateIncidentResponse struct { +// createIncidentResponse is returned from the API when creating a response. +type createIncidentResponse struct { Incident Incident `json:incident` } @@ -103,7 +103,7 @@ type CreateIncidentValue struct { } // CreateIncident creates an incident synchronously without a corresponding event from a monitoring service. -func (c *Client) CreateIncidents(from string, i *CreateIncident) (*Incident, error) { +func (c *Client) CreateIncident(from string, i *CreateIncident) (*Incident, error) { headers := make(map[string]string) headers["From"] = from resp, e := c.post("/incidents", i, &headers) @@ -111,7 +111,7 @@ func (c *Client) CreateIncidents(from string, i *CreateIncident) (*Incident, err return nil, e } - var ii CreateIncidentResponse + var ii createIncidentResponse e = json.NewDecoder(resp.Body).Decode(&ii) if e != nil { return nil, e From db719369961bbe84884014dc2ce62cffcd3b7080 Mon Sep 17 00:00:00 2001 From: Louis Delossantos Date: Thu, 21 Jun 2018 11:58:44 -0400 Subject: [PATCH 10/10] rename CreateIncidentValue to CreateIncidentOptions --- incident.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/incident.go b/incident.go index dff90a5e..3ec96dea 100644 --- a/incident.go +++ b/incident.go @@ -83,7 +83,7 @@ func (c *Client) ListIncidents(o ListIncidentsOptions) (*ListIncidentsResponse, // CreateIncident is the structure POST'd to the incidents endpoint. It wraps a CreateIncidentValue type CreateIncident struct { - Incident CreateIncidentValue `json:"incident"` + Incident CreateIncidentOptions `json:"incident"` } // createIncidentResponse is returned from the API when creating a response. @@ -91,8 +91,8 @@ type createIncidentResponse struct { Incident Incident `json:incident` } -// CreateIncidentValue is the structure used when POSTing to the CreateIncident API endpoint. -type CreateIncidentValue struct { +// CreateIncidentOptions is the structure used when POSTing to the CreateIncident API endpoint. +type CreateIncidentOptions struct { Type string `json:"type"` Title string `json:"title"` Service APIReference `json:"service"`