Skip to content

Commit

Permalink
Add support for better API debugging; start v1.5.0 development
Browse files Browse the repository at this point in the history
In prepration for #305, this adds a mechanism to inspect all API responses
received by the client. That way if you want to figure out why something isn't
working as expected, or you'd like to make use of an undocumented field, you
have access to the response and can use it.

This also adds a `Do()` method, with the same signature as `*http.Client.Do()`,
that allows consumrs to generate their own request, have the client add
authentication details and other headers, before sending the request to the
PagerDuty API. This allows consumers to further debug and make use of features
not yet supported in the REST client.

Also, updates Version string to v1.5.0 as this is work towards that release.

Lastly, this updates some of the test files to remove some deduplication across
them. These changes were needed due to the new fields added to the struct that
had to be initialized to make HTTP requests.
  • Loading branch information
theckman committed May 29, 2021
1 parent e23b94c commit b0805db
Show file tree
Hide file tree
Showing 26 changed files with 561 additions and 180 deletions.
62 changes: 61 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,22 @@ An example of the `service` sub-command
pd service list
```
### Client Library
#### NOTICE: Breaking API Changes in master branch
As part of the upcoming `v1.5.0` release, we will be fixing features that have
never worked correctly and require a breaking API change to fix. One example is
the issue reported in [\#232](https://github.com/PagerDuty/go-pagerduty/issues/232),
as well as a handful of other examples within the
[v1.5.0 milestone](https://github.com/PagerDuty/go-pagerduty/milestone/2).
As a result, the `master` branch now contains breaking changes since the
`v1.4.0` release. We will clearly highlight the breaking changes in the `v1.5.0`
release notes when it's ready.
#### Example Usage
```go
package main
Expand Down Expand Up @@ -113,6 +126,53 @@ func main() {
}
```

#### Extending and Debugging Client

##### Extending The Client

The `*pagerduty.Client` has a `Do` method which allows consumers to wrap the
client, and make their own requests to the PagerDuty API. The method signature
is similar to that of the `http.Client.Do` method, except it also includes a
`bool` to incidate whether the API endpoint is authenticated (i.e., the REST
API). When the API is authenticated, the client will annotate the request with
the appropriate headers to be authenticated by the API.

If PagerDuty the client doesn't natively expose functionality that you wish to
use, such as undocumented JSON fields, you can use the `Do()` method to issue
your own request that you can parse the response of.

Likewise, you can use it to issue requests to the API for the purposes of
debugging. However, that's not the only mechanism for debugging.

##### Debugging the Client

The `*pagerduty.Client` has a method that allows consumers to enable debug
functionality, including interception of PagerDuty API responses. This is done
by using the `SetDebugFlag()` method using the `pagerduty.DebugFlag` unsigned
integer type. There are also exported constants to help consumers enable
specific debug behaviors.

###### Capturing Last PagerDuty Response

If you're not getting the response you expect from the PagerDuty Go client, you
can enable the `DebugCaptureLastResponse` debug flag to capture the HTTP
responses. You can then use one of the methods to make an API call, and then
inspect the API response received. For example:

```Go
client := pagerduty.NewClient("exmaple")

client.SetDebugFlag(pagerduty.DebugCaptureLastResponse)

oncalls, err := client.ListOnCallsWithContext(ctx, pagerduty.ListOnCallOptions{})

resp, ok := client.LastAPIReponse()
if ok { // resp is an *http.Response we can inspect
body, err := ioutil.ReadAll(resp.Body)
// ...
}
```

## Contributing

1. Fork it ( https://github.com/PagerDuty/go-pagerduty/fork )
Expand Down
8 changes: 4 additions & 4 deletions ability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func TestAbility_ListAbilities(t *testing.T) {
_, _ = w.Write([]byte(`{"abilities": ["sso"]}`))
})

client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")
want := &ListAbilityResponse{Abilities: []string{"sso"}}

res, err := client.ListAbilities()
Expand All @@ -34,7 +34,7 @@ func TestAbility_ListAbilitiesFailure(t *testing.T) {
w.WriteHeader(http.StatusForbidden)
})

client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")

if _, err := client.ListAbilities(); err == nil {
t.Fatal("expected error; got nil")
Expand All @@ -50,7 +50,7 @@ func TestAbility_TestAbility(t *testing.T) {
w.WriteHeader(http.StatusNoContent)
})

client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")

if err := client.TestAbility("sso"); err != nil {
t.Fatal(err)
Expand All @@ -66,7 +66,7 @@ func TestAbility_TestAbilityFailure(t *testing.T) {
w.WriteHeader(http.StatusForbidden)
})

client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")

if err := client.TestAbility("sso"); err == nil {
t.Fatal("expected error; got nil")
Expand Down
10 changes: 5 additions & 5 deletions addon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func TestAddon_List(t *testing.T) {
})
listObj := APIListObject{Limit: 0, Offset: 0, More: false, Total: 0}
var opts ListAddonOptions
client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")

res, err := client.ListAddons(opts)
want := &ListAddonResponse{
Expand Down Expand Up @@ -46,7 +46,7 @@ func TestAddon_Install(t *testing.T) {
_, _ = w.Write([]byte(`{"addon": {"name": "Internal Status Page", "id": "1"}}`))
})

client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")

res, err := client.InstallAddon(input)

Expand All @@ -70,7 +70,7 @@ func TestAddon_Get(t *testing.T) {
testMethod(t, r, "GET")
_, _ = w.Write([]byte(`{"addon": {"id": "1"}}`))
})
client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")

res, err := client.GetAddon("1")

Expand All @@ -93,7 +93,7 @@ func TestAddon_Update(t *testing.T) {
testMethod(t, r, "PUT")
_, _ = w.Write([]byte(`{"addon": {"name": "Internal Status Page", "id": "1"}}`))
})
client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")

input := Addon{
Name: "Internal Status Page",
Expand Down Expand Up @@ -121,7 +121,7 @@ func TestAddon_Delete(t *testing.T) {
testMethod(t, r, "DELETE")
w.WriteHeader(http.StatusNoContent)
})
client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")
err := client.DeleteAddon("1")
if err != nil {
t.Fatal(err)
Expand Down
18 changes: 3 additions & 15 deletions analytics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,7 @@ func TestAnalytics_GetAggregatedIncidentData(t *testing.T) {
_, _ = w.Write(bytesAnalyticsResponse)
})

client := &Client{
apiEndpoint: server.URL,
authToken: "foo",
HTTPClient: defaultHTTPClient,
}
client := defaultTestClient(server.URL, "foo")

res, err := client.GetAggregatedIncidentData(context.Background(), analyticsRequest)
want := AnalyticsResponse{
Expand Down Expand Up @@ -85,11 +81,7 @@ func TestAnalytics_GetAggregatedServiceData(t *testing.T) {
_, _ = w.Write(bytesAnalyticsResponse)
})

client := &Client{
apiEndpoint: server.URL,
authToken: "foo",
HTTPClient: defaultHTTPClient,
}
client := defaultTestClient(server.URL, "foo")

res, err := client.GetAggregatedServiceData(context.Background(), analyticsRequest)
want := AnalyticsResponse{
Expand Down Expand Up @@ -133,11 +125,7 @@ func TestAnalytics_GetAggregatedTeamData(t *testing.T) {
_, _ = w.Write(bytesAnalyticsResponse)
})

client := &Client{
apiEndpoint: server.URL,
authToken: "foo",
HTTPClient: defaultHTTPClient,
}
client := defaultTestClient(server.URL, "foo")

res, err := client.GetAggregatedTeamData(context.Background(), analyticsRequest)
want := AnalyticsResponse{
Expand Down
10 changes: 5 additions & 5 deletions business_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestBusinessService_List(t *testing.T) {
})

listObj := APIListObject{Limit: 0, Offset: 0, More: false, Total: 0}
client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")
opts := ListBusinessServiceOptions{
APIListObject: listObj,
}
Expand Down Expand Up @@ -47,7 +47,7 @@ func TestBusinessService_Create(t *testing.T) {
_, _ = w.Write([]byte(`{"business_service": {"id": "1", "name": "foo"}}`))
})

client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")
input := &BusinessService{
Name: "foo",
}
Expand All @@ -74,7 +74,7 @@ func TestBusinessService_Get(t *testing.T) {
_, _ = w.Write([]byte(`{"business_service": {"id": "1", "name":"foo"}}`))
})

client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")
ruleSetID := "1"

res, _, err := client.GetBusinessService(ruleSetID)
Expand Down Expand Up @@ -112,7 +112,7 @@ func TestBusinessService_Update(t *testing.T) {
_, _ = w.Write([]byte(`{"business_service": {"id": "1", "name":"foo"}}`))
})

client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")
input := &BusinessService{
ID: "1",
Name: "foo",
Expand All @@ -139,7 +139,7 @@ func TestBusinessService_Delete(t *testing.T) {
testMethod(t, r, "DELETE")
})

client := &Client{apiEndpoint: server.URL, authToken: "foo", HTTPClient: defaultHTTPClient}
client := defaultTestClient(server.URL, "foo")
ID := "1"
err := client.DeleteBusinessService(ID)
if err != nil {
Expand Down
14 changes: 2 additions & 12 deletions change_events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,7 @@ func TestChangeEvent_Create(t *testing.T) {
},
)

client := &Client{
v2EventsAPIEndpoint: server.URL,
apiEndpoint: server.URL,
authToken: "foo",
HTTPClient: defaultHTTPClient,
}
client := defaultTestClient(server.URL, "foo")

want := ChangeEventResponse{
Status: "success",
Expand Down Expand Up @@ -81,12 +76,7 @@ func TestChangeEvent_CreateWithPayloadVerification(t *testing.T) {
},
)

client := &Client{
v2EventsAPIEndpoint: server.URL,
apiEndpoint: server.URL,
authToken: "foo",
HTTPClient: defaultHTTPClient,
}
client := defaultTestClient(server.URL, "foo")

eventDetails := map[string]interface{}{"DetailKey1": "DetailValue1", "DetailKey2": "DetailValue2"}
ce := ChangeEvent{
Expand Down
Loading

0 comments on commit b0805db

Please sign in to comment.