From 01da4ee7d2151a2549f2cba1811e133043e6562f Mon Sep 17 00:00:00 2001 From: Ryan King Date: Fri, 11 Sep 2020 20:39:31 +0800 Subject: [PATCH 1/5] add client based ManageEvent --- event_v2.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/event_v2.go b/event_v2.go index 4e5bc4a8..fb99980a 100644 --- a/event_v2.go +++ b/event_v2.go @@ -8,7 +8,7 @@ import ( "net/http" ) -// Event includes the incident/alert details +// V2Event includes the incident/alert details type V2Event struct { RoutingKey string `json:"routing_key"` Action string `json:"event_action"` @@ -20,7 +20,7 @@ type V2Event struct { Payload *V2Payload `json:"payload,omitempty"` } -// Payload represents the individual event details for an event +// V2Payload represents the individual event details for an event type V2Payload struct { Summary string `json:"summary"` Source string `json:"source"` @@ -32,7 +32,7 @@ type V2Payload struct { Details interface{} `json:"custom_details,omitempty"` } -// Response is the json response body for an event +// V2EventResponse is the json response body for an event type V2EventResponse struct { Status string `json:"status,omitempty"` DedupKey string `json:"dedup_key,omitempty"` @@ -69,3 +69,15 @@ func ManageEvent(e V2Event) (*V2EventResponse, error) { } return &eventResponse, nil } + +// ManageEvent handles the trigger, acknowledge, and resolve methods for an event +func (c *Client) ManageEvent(e *V2Event) (*V2EventResponse, *http.Response, error) { + headers := make(map[string]string) + resp, err := c.put("/v2/enqueue", e, &headers) + if err != nil { + return nil, nil, err + } + result := &V2EventResponse{} + err = json.NewDecoder(resp.Body).Decode(result) + return result, resp, err +} From 3f5043ad83a62fc10862fb574a526fc7f9b9f2ea Mon Sep 17 00:00:00 2001 From: Ryan King Date: Fri, 11 Sep 2020 21:34:51 +0800 Subject: [PATCH 2/5] fixup --- event_v2.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/event_v2.go b/event_v2.go index fb99980a..8c08033d 100644 --- a/event_v2.go +++ b/event_v2.go @@ -71,13 +71,13 @@ func ManageEvent(e V2Event) (*V2EventResponse, error) { } // ManageEvent handles the trigger, acknowledge, and resolve methods for an event -func (c *Client) ManageEvent(e *V2Event) (*V2EventResponse, *http.Response, error) { +func (c *Client) ManageEvent(e *V2Event) (*V2EventResponse, error) { headers := make(map[string]string) - resp, err := c.put("/v2/enqueue", e, &headers) + resp, err := c.post("/v2/enqueue", e, &headers) if err != nil { - return nil, nil, err + return nil, err } result := &V2EventResponse{} err = json.NewDecoder(resp.Body).Decode(result) - return result, resp, err + return result, err } From 26930511d4626776d5cffb70d216a8549ea76bb3 Mon Sep 17 00:00:00 2001 From: Ryan King Date: Fri, 11 Sep 2020 21:35:04 +0800 Subject: [PATCH 3/5] add test for event_v2 --- event_v2_test.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 event_v2_test.go diff --git a/event_v2_test.go b/event_v2_test.go new file mode 100644 index 00000000..f969f243 --- /dev/null +++ b/event_v2_test.go @@ -0,0 +1,30 @@ +package pagerduty + +import ( + "net/http" + "testing" +) + +func TestEventV2_ManageEvent(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/enqueue", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + w.Write([]byte(`{"status": "ok", "dedup_key": "yes", "message": "ok"}`)) + }) + var client = &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient} + evt := &V2Event{ + RoutingKey: "abc123", + } + res, err := client.ManageEvent(evt) + if err != nil { + t.Fatal(err) + } + want := &V2EventResponse{ + Status: "ok", + DedupKey: "yes", + Message: "ok", + } + testEqual(t, want, res) +} From 151eee6db272c7c8013ad98fd76849e2a97393d7 Mon Sep 17 00:00:00 2001 From: Ryan King Date: Mon, 14 Sep 2020 16:47:12 +0800 Subject: [PATCH 4/5] add abillity to use different api endpoints - eg: for v2 events, the host is different --- client.go | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/client.go b/client.go index 9e418f9a..68fe571c 100644 --- a/client.go +++ b/client.go @@ -12,7 +12,8 @@ import ( ) const ( - apiEndpoint = "https://api.pagerduty.com" + apiEndpoint = "https://api.pagerduty.com" + v2EventsAPIEndpoint = "https://events.pagerduty.com" ) // The type of authentication to use with the API client @@ -96,8 +97,9 @@ var defaultHTTPClient HTTPClient = newDefaultHTTPClient() // Client wraps http client type Client struct { - authToken string - apiEndpoint string + authToken string + apiEndpoint string + v2EventsAPIEndpoint string // Authentication type to use for API authType authType @@ -111,10 +113,11 @@ type Client struct { // NewClient creates an API client using an account/user API token func NewClient(authToken string, options ...ClientOptions) *Client { client := Client{ - authToken: authToken, - apiEndpoint: apiEndpoint, - authType: apiToken, - HTTPClient: defaultHTTPClient, + authToken: authToken, + apiEndpoint: apiEndpoint, + v2EventsAPIEndpoint: v2EventsAPIEndpoint, + authType: apiToken, + HTTPClient: defaultHTTPClient, } for _, opt := range options { @@ -139,6 +142,13 @@ func WithAPIEndpoint(endpoint string) ClientOptions { } } +// WithV2EventsAPIEndpoint allows for a custom V2 Events API endpoint to be passed into the client +func WithV2EventsAPIEndpoint(endpoint string) ClientOptions { + return func(c *Client) { + c.v2EventsAPIEndpoint = endpoint + } +} + // WithOAuth allows for an OAuth token to be passed into the the client func WithOAuth() ClientOptions { return func(c *Client) { @@ -174,29 +184,36 @@ func (c *Client) get(path string) (*http.Response, error) { return c.do("GET", path, nil, nil) } -func (c *Client) do(method, path string, body io.Reader, headers *map[string]string) (*http.Response, error) { - endpoint := c.apiEndpoint + path - req, _ := http.NewRequest(method, endpoint, body) +// needed where pagerduty use a different endpoint for certain actions (eg: v2 events) +func (c *Client) doWithEndpoint(endpoint, method, path string, authRequired bool, body io.Reader, headers *map[string]string) (*http.Response, error) { + req, _ := http.NewRequest(method, endpoint+path, body) req.Header.Set("Accept", "application/vnd.pagerduty+json;version=2") if headers != nil { for k, v := range *headers { req.Header.Set(k, v) } } - req.Header.Set("User-Agent", "go-pagerduty/"+Version) - req.Header.Set("Content-Type", "application/json") - switch c.authType { - case oauthToken: - req.Header.Set("Authorization", "Bearer "+c.authToken) - default: - req.Header.Set("Authorization", "Token token="+c.authToken) + if authRequired { + switch c.authType { + case oauthToken: + req.Header.Set("Authorization", "Bearer "+c.authToken) + default: + req.Header.Set("Authorization", "Token token="+c.authToken) + } } + req.Header.Set("User-Agent", "go-pagerduty/"+Version) + req.Header.Set("Content-Type", "application/json") + resp, err := c.HTTPClient.Do(req) return c.checkResponse(resp, err) } +func (c *Client) do(method, path string, body io.Reader, headers *map[string]string) (*http.Response, error) { + return c.doWithEndpoint(c.apiEndpoint, method, path, true, body, headers) +} + func (c *Client) decodeJSON(resp *http.Response, payload interface{}) error { defer resp.Body.Close() decoder := json.NewDecoder(resp.Body) From e053a10de4ca07b0e42ddf2c0967d3469a1fd53b Mon Sep 17 00:00:00 2001 From: Ryan King Date: Mon, 14 Sep 2020 16:47:55 +0800 Subject: [PATCH 5/5] use different endpoint for v2 events --- event_v2.go | 7 ++++++- event_v2_test.go | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/event_v2.go b/event_v2.go index 8c08033d..852e24e6 100644 --- a/event_v2.go +++ b/event_v2.go @@ -73,7 +73,12 @@ func ManageEvent(e V2Event) (*V2EventResponse, error) { // ManageEvent handles the trigger, acknowledge, and resolve methods for an event func (c *Client) ManageEvent(e *V2Event) (*V2EventResponse, error) { headers := make(map[string]string) - resp, err := c.post("/v2/enqueue", e, &headers) + + data, err := json.Marshal(e) + if err != nil { + return nil, err + } + resp, err := c.doWithEndpoint(c.v2EventsAPIEndpoint, "POST", "/v2/enqueue", false, bytes.NewBuffer(data), &headers) if err != nil { return nil, err } diff --git a/event_v2_test.go b/event_v2_test.go index f969f243..d9ff4c45 100644 --- a/event_v2_test.go +++ b/event_v2_test.go @@ -13,7 +13,7 @@ func TestEventV2_ManageEvent(t *testing.T) { testMethod(t, r, "POST") w.Write([]byte(`{"status": "ok", "dedup_key": "yes", "message": "ok"}`)) }) - var client = &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient} + var client = &Client{v2EventsAPIEndpoint: server.URL, apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient} evt := &V2Event{ RoutingKey: "abc123", }