Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event v2 client #241

Merged
merged 5 commits into from
Oct 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 34 additions & 17 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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) {
Expand Down Expand Up @@ -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)
Expand Down
23 changes: 20 additions & 3 deletions event_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand All @@ -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"`
Expand All @@ -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"`
Expand Down Expand Up @@ -69,3 +69,20 @@ 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, error) {
headers := make(map[string]string)

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
}
result := &V2EventResponse{}
err = json.NewDecoder(resp.Body).Decode(result)
return result, err
}
30 changes: 30 additions & 0 deletions event_v2_test.go
Original file line number Diff line number Diff line change
@@ -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{v2EventsAPIEndpoint: server.URL, 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)
}