From 1b58bfcf609f22b55618e121872d6f42cecdbcfc Mon Sep 17 00:00:00 2001 From: Sean Marciniak <30928402+MovieStoreGuy@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:01:02 +1030 Subject: [PATCH] Feature: Adding standardize response error (#225) * Adding standardize request error To help simplify and address how errors from request are handled, this returns an error type that allows for deeper introspection from external packages. * Correcting AsResponseError method * Adding slices contains --- alertmuting.go | 45 ++++------ aws_cloudwatch_integration.go | 37 +++----- azure_integration.go | 38 +++----- chart.go | 46 ++++------ dashboard.go | 46 ++++------ dashboardgroup.go | 46 ++++------ datalink.go | 48 ++++------ detector.go | 91 +++++++------------ errors.go | 80 +++++++++++++++++ errors_test.go | 163 ++++++++++++++++++++++++++++++++++ gcp_integration.go | 37 +++----- incident.go | 24 ++--- integration.go | 6 +- jira_integration.go | 37 +++----- metric_ruleset.go | 44 +++------ metrics_metadata.go | 109 ++++++++--------------- opsgenie_integration.go | 38 +++----- organization.go | 64 +++++-------- orgtoken.go | 46 ++++------ pagerduty_integration.go | 46 ++++------ sessiontoken.go | 19 ++-- slack_integration.go | 37 +++----- slo.go | 14 ++- team.go | 84 ++++++------------ victor_ops_integration.go | 37 +++----- webhook_integration.go | 37 +++----- 26 files changed, 600 insertions(+), 719 deletions(-) create mode 100644 errors.go create mode 100644 errors_test.go diff --git a/alertmuting.go b/alertmuting.go index 13b5ce5..d3bd24a 100644 --- a/alertmuting.go +++ b/alertmuting.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -25,16 +24,13 @@ func (c *Client) CreateAlertMutingRule(ctx context.Context, muteRequest *alertmu } resp, err := c.doRequest(ctx, "POST", AlertMutingRuleAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusCreated { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusCreated); err != nil { + return nil, err } finalRule := &alertmuting.AlertMutingRule{} @@ -48,16 +44,13 @@ func (c *Client) CreateAlertMutingRule(ctx context.Context, muteRequest *alertmu // DeleteAlertMutingRule deletes an alert muting rule. func (c *Client) DeleteAlertMutingRule(ctx context.Context, name string) error { resp, err := c.doRequest(ctx, "DELETE", AlertMutingRuleAPIURL+"/"+name, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) @@ -67,16 +60,13 @@ func (c *Client) DeleteAlertMutingRule(ctx context.Context, name string) error { // GetAlertMutingRule gets an alert muting rule. func (c *Client) GetAlertMutingRule(ctx context.Context, id string) (*alertmuting.AlertMutingRule, error) { resp, err := c.doRequest(ctx, "GET", AlertMutingRuleAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalRule := &alertmuting.AlertMutingRule{} @@ -95,16 +85,13 @@ func (c *Client) UpdateAlertMutingRule(ctx context.Context, id string, muteReque } resp, err := c.doRequest(ctx, "PUT", AlertMutingRuleAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalRule := &alertmuting.AlertMutingRule{} @@ -124,12 +111,14 @@ func (c *Client) SearchAlertMutingRules(ctx context.Context, include string, lim params.Add("offset", strconv.Itoa(offset)) resp, err := c.doRequest(ctx, "GET", AlertMutingRuleAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() + + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err + } finalRules := &alertmuting.SearchResult{} diff --git a/aws_cloudwatch_integration.go b/aws_cloudwatch_integration.go index 9981324..460369c 100644 --- a/aws_cloudwatch_integration.go +++ b/aws_cloudwatch_integration.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -20,16 +19,13 @@ func (c *Client) CreateAWSCloudWatchIntegration(ctx context.Context, acwi *integ } resp, err := c.doRequest(ctx, "POST", IntegrationAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.AwsCloudWatchIntegration{} @@ -43,16 +39,13 @@ func (c *Client) CreateAWSCloudWatchIntegration(ctx context.Context, acwi *integ // GetAWSCloudWatchIntegration retrieves an AWS CloudWatch integration. func (c *Client) GetAWSCloudWatchIntegration(ctx context.Context, id string) (*integration.AwsCloudWatchIntegration, error) { resp, err := c.doRequest(ctx, "GET", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.AwsCloudWatchIntegration{} @@ -71,16 +64,13 @@ func (c *Client) UpdateAWSCloudWatchIntegration(ctx context.Context, id string, } resp, err := c.doRequest(ctx, "PUT", IntegrationAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.AwsCloudWatchIntegration{} @@ -94,16 +84,13 @@ func (c *Client) UpdateAWSCloudWatchIntegration(ctx context.Context, id string, // DeleteAWSCloudWatchIntegration deletes an AWS CloudWatch integration. func (c *Client) DeleteAWSCloudWatchIntegration(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) diff --git a/azure_integration.go b/azure_integration.go index 8800103..6ddf932 100644 --- a/azure_integration.go +++ b/azure_integration.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -20,16 +19,13 @@ func (c *Client) CreateAzureIntegration(ctx context.Context, acwi *integration.A } resp, err := c.doRequest(ctx, "POST", IntegrationAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.AzureIntegration{} @@ -43,16 +39,13 @@ func (c *Client) CreateAzureIntegration(ctx context.Context, acwi *integration.A // GetAzureIntegration retrieves an Azure integration. func (c *Client) GetAzureIntegration(ctx context.Context, id string) (*integration.AzureIntegration, error) { resp, err := c.doRequest(ctx, "GET", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.AzureIntegration{} @@ -71,16 +64,14 @@ func (c *Client) UpdateAzureIntegration(ctx context.Context, id string, acwi *in } resp, err := c.doRequest(ctx, "PUT", IntegrationAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } + if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.AzureIntegration{} @@ -94,16 +85,13 @@ func (c *Client) UpdateAzureIntegration(ctx context.Context, id string, acwi *in // DeleteAzureIntegration deletes an Azure integration. func (c *Client) DeleteAzureIntegration(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) diff --git a/chart.go b/chart.go index 54bdfd3..10af821 100644 --- a/chart.go +++ b/chart.go @@ -4,8 +4,6 @@ import ( "bytes" "context" "encoding/json" - "errors" - "fmt" "io" "io/ioutil" "net/http" @@ -26,16 +24,13 @@ func (c *Client) CreateChart(ctx context.Context, chartRequest *chart.CreateUpda } resp, err := c.doRequest(ctx, "POST", ChartAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalChart := &chart.Chart{} @@ -49,15 +44,13 @@ func (c *Client) CreateChart(ctx context.Context, chartRequest *chart.CreateUpda // DeleteChart deletes a chart. func (c *Client) DeleteChart(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", ChartAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return errors.New("Unexpected status code: " + resp.Status) + if err = newResponseError(resp, http.StatusOK); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) @@ -67,16 +60,13 @@ func (c *Client) DeleteChart(ctx context.Context, id string) error { // GetChart gets a chart. func (c *Client) GetChart(ctx context.Context, id string) (*chart.Chart, error) { resp, err := c.doRequest(ctx, "GET", ChartAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalChart := &chart.Chart{} @@ -95,16 +85,13 @@ func (c *Client) UpdateChart(ctx context.Context, id string, chartRequest *chart } resp, err := c.doRequest(ctx, "PUT", ChartAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalChart := &chart.Chart{} @@ -128,16 +115,13 @@ func (c *Client) SearchCharts(ctx context.Context, limit int, name string, offse } resp, err := c.doRequest(ctx, "GET", ChartAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalCharts := &chart.SearchResult{} diff --git a/dashboard.go b/dashboard.go index 9598fd0..0845e8b 100644 --- a/dashboard.go +++ b/dashboard.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -27,16 +26,13 @@ func (c *Client) CreateDashboard(ctx context.Context, dashboardRequest *dashboar } resp, err := c.doRequest(ctx, "POST", DashboardAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDashboard := &dashboard.Dashboard{} @@ -50,16 +46,13 @@ func (c *Client) CreateDashboard(ctx context.Context, dashboardRequest *dashboar // DeleteDashboard deletes a dashboard. func (c *Client) DeleteDashboard(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", DashboardAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) @@ -69,16 +62,13 @@ func (c *Client) DeleteDashboard(ctx context.Context, id string) error { // GetDashboard gets a dashboard. func (c *Client) GetDashboard(ctx context.Context, id string) (*dashboard.Dashboard, error) { resp, err := c.doRequest(ctx, "GET", DashboardAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDashboard := &dashboard.Dashboard{} @@ -97,16 +87,13 @@ func (c *Client) UpdateDashboard(ctx context.Context, id string, dashboardReques } resp, err := c.doRequest(ctx, "PUT", DashboardAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDashboard := &dashboard.Dashboard{} @@ -126,16 +113,13 @@ func (c *Client) SearchDashboard(ctx context.Context, limit int, name string, of params.Add("tags", tags) resp, err := c.doRequest(ctx, "GET", DashboardAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDashboards := &dashboard.SearchResult{} diff --git a/dashboardgroup.go b/dashboardgroup.go index e400f35..1415d84 100644 --- a/dashboardgroup.go +++ b/dashboardgroup.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -32,16 +31,13 @@ func (c *Client) CreateDashboardGroup(ctx context.Context, dashboardGroupRequest } resp, err := c.doRequest(ctx, "POST", DashboardGroupAPIURL, params, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDashboardGroup := &dashboard_group.DashboardGroup{} @@ -55,16 +51,13 @@ func (c *Client) CreateDashboardGroup(ctx context.Context, dashboardGroupRequest // DeleteDashboardGroup deletes a dashboard. func (c *Client) DeleteDashboardGroup(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", DashboardGroupAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) @@ -74,16 +67,13 @@ func (c *Client) DeleteDashboardGroup(ctx context.Context, id string) error { // GetDashboardGroup gets a dashboard group. func (c *Client) GetDashboardGroup(ctx context.Context, id string) (*dashboard_group.DashboardGroup, error) { resp, err := c.doRequest(ctx, "GET", DashboardGroupAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDashboardGroup := &dashboard_group.DashboardGroup{} @@ -102,16 +92,13 @@ func (c *Client) UpdateDashboardGroup(ctx context.Context, id string, dashboardG } resp, err := c.doRequest(ctx, "PUT", DashboardGroupAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDashboardGroup := &dashboard_group.DashboardGroup{} @@ -130,16 +117,13 @@ func (c *Client) SearchDashboardGroups(ctx context.Context, limit int, name stri params.Add("offset", strconv.Itoa(offset)) resp, err := c.doRequest(ctx, "GET", DashboardGroupAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDashboardGroups := &dashboard_group.SearchResult{} diff --git a/datalink.go b/datalink.go index 8c123d8..15144ea 100644 --- a/datalink.go +++ b/datalink.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -25,16 +24,13 @@ func (c *Client) CreateDataLink(ctx context.Context, dataLinkRequest *datalink.C } resp, err := c.doRequest(ctx, "POST", DataLinkAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDataLink := &datalink.DataLink{} @@ -48,19 +44,17 @@ func (c *Client) CreateDataLink(ctx context.Context, dataLinkRequest *datalink.C // DeleteDataLink deletes a data link. func (c *Client) DeleteDataLink(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", DataLinkAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() // The API returns a 200 here, which I think is a mistake so covering for // future changes. - if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent, http.StatusOK); err != nil { + return err } + _, _ = io.Copy(ioutil.Discard, resp.Body) return nil @@ -69,16 +63,13 @@ func (c *Client) DeleteDataLink(ctx context.Context, id string) error { // GetDataLink gets a data link. func (c *Client) GetDataLink(ctx context.Context, id string) (*datalink.DataLink, error) { resp, err := c.doRequest(ctx, "GET", DataLinkAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDataLink := &datalink.DataLink{} @@ -98,16 +89,14 @@ func (c *Client) UpdateDataLink(ctx context.Context, id string, dataLinkRequest encodedName := url.PathEscape(id) resp, err := c.doRequest(ctx, "PUT", DataLinkAPIURL+"/"+encodedName, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } + if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDataLink := &datalink.DataLink{} @@ -126,16 +115,13 @@ func (c *Client) SearchDataLinks(ctx context.Context, limit int, context string, params.Add("offset", strconv.Itoa(offset)) resp, err := c.doRequest(ctx, "GET", DataLinkAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDataLinks := &datalink.SearchResults{} diff --git a/detector.go b/detector.go index 8303783..c5a0f52 100644 --- a/detector.go +++ b/detector.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -25,16 +24,13 @@ func (c *Client) CreateDetector(ctx context.Context, detectorRequest *detector.C } resp, err := c.doRequest(ctx, "POST", DetectorAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDetector := &detector.Detector{} @@ -48,16 +44,13 @@ func (c *Client) CreateDetector(ctx context.Context, detectorRequest *detector.C // DeleteDetector deletes a detector. func (c *Client) DeleteDetector(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", DetectorAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) @@ -72,16 +65,13 @@ func (c *Client) DisableDetector(ctx context.Context, id string, labels []string } resp, err := c.doRequest(ctx, "PUT", DetectorAPIURL+"/"+id+"/disable", nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) @@ -96,16 +86,13 @@ func (c *Client) EnableDetector(ctx context.Context, id string, labels []string) } resp, err := c.doRequest(ctx, "PUT", DetectorAPIURL+"/"+id+"/enable", nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) @@ -115,16 +102,13 @@ func (c *Client) EnableDetector(ctx context.Context, id string, labels []string) // GetDetector gets a detector. func (c *Client) GetDetector(ctx context.Context, id string) (*detector.Detector, error) { resp, err := c.doRequest(ctx, "GET", DetectorAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDetector := &detector.Detector{} @@ -143,16 +127,13 @@ func (c *Client) UpdateDetector(ctx context.Context, id string, detectorRequest } resp, err := c.doRequest(ctx, "PUT", DetectorAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDetector := &detector.Detector{} @@ -174,16 +155,13 @@ func (c *Client) SearchDetectors(ctx context.Context, limit int, name string, of } resp, err := c.doRequest(ctx, "GET", DetectorAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDetectors := &detector.SearchResults{} @@ -202,16 +180,13 @@ func (c *Client) GetDetectorEvents(ctx context.Context, id string, from int, to params.Add("offset", strconv.Itoa(offset)) params.Add("limit", strconv.Itoa(limit)) resp, err := c.doRequest(ctx, "GET", DetectorAPIURL+"/"+id+"/events", params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } var events []*detector.Event @@ -228,16 +203,13 @@ func (c *Client) GetDetectorIncidents(ctx context.Context, id string, offset int params.Add("offset", strconv.Itoa(offset)) params.Add("limit", strconv.Itoa(limit)) resp, err := c.doRequest(ctx, "GET", DetectorAPIURL+"/"+id+"/incidents", params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } var incidents []*detector.Incident @@ -256,16 +228,13 @@ func (c *Client) ValidateDetector(ctx context.Context, detectorRequest *detector } resp, err := c.doRequest(ctx, "POST", DetectorAPIURL+"/validate", nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..eacb176 --- /dev/null +++ b/errors.go @@ -0,0 +1,80 @@ +package signalfx + +import ( + "errors" + "fmt" + "io" + "net/http" + "slices" +) + +// ResponseError captures the error details +// and allows for it to be inspected by external libraries. +type ResponseError struct { + code int + route string + details string +} + +var _ error = (*ResponseError)(nil) + +func newResponseError(resp *http.Response, target int, targets ...int) error { + if resp == nil { + return nil + } + + if slices.Contains(append([]int{target}, targets...), resp.StatusCode) { + return nil + } + + details, _ := io.ReadAll(resp.Body) + + return &ResponseError{ + code: resp.StatusCode, + route: resp.Request.URL.Path, + details: string(details), + } +} + +// AsResponseError is a convenience function to check the error +// to see if it contains an `ResponseError` and returns the value with true. +// If the error was initially joined using [errors.Join], it will check each error +// within the list and return the first matching error. +func AsResponseError(err error) (*ResponseError, bool) { + // When `errors.Join` is called, it returns an error that + // matches the provided interface. + if joined, ok := err.(interface{ Unwrap() []error }); ok { + for _, err := range joined.Unwrap() { + if re, ok := AsResponseError(err); ok { + return re, ok + } + } + return nil, false + } + + for err != nil { + if re, ok := err.(*ResponseError); ok { + return re, true + } + // In case the error is wrapped using `fmt.Errorf` + // this will also account for that. + err = errors.Unwrap(err) + } + return nil, false +} + +func (re *ResponseError) Error() string { + return fmt.Sprintf("route %q had issues with status code %d", re.route, re.code) +} + +func (re *ResponseError) Code() int { + return re.code +} + +func (re *ResponseError) Route() string { + return re.route +} + +func (re *ResponseError) Details() string { + return re.details +} diff --git a/errors_test.go b/errors_test.go new file mode 100644 index 0000000..0ed14de --- /dev/null +++ b/errors_test.go @@ -0,0 +1,163 @@ +package signalfx + +import ( + "errors" + "fmt" + "io" + "net/http" + "net/url" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRequestError(t *testing.T) { + t.Parallel() + + for _, tc := range []struct { + name string + re *ResponseError + err string + }{ + { + name: "simple request error", + re: &ResponseError{ + code: 404, + route: "/internal/heathz", + details: "failed due to overworked", + }, + err: "route \"/internal/heathz\" had issues with status code 404", + }, + { + name: "missed details", + re: &ResponseError{ + code: 404, + route: "/internal/heathz", + }, + err: "route \"/internal/heathz\" had issues with status code 404", + }, + { + name: "missed code", + re: &ResponseError{ + route: "/internal/heathz", + }, + err: "route \"/internal/heathz\" had issues with status code 0", + }, + { + name: "missed all info", + re: &ResponseError{}, + err: "route \"\" had issues with status code 0", + }, + } { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + assert.EqualError(t, tc.re, tc.err, "Must match the expected error string") + }) + } +} + +func TestNewRequestError(t *testing.T) { + t.Parallel() + + for _, tc := range []struct { + name string + resp *http.Response + expect error + }{ + { + name: "no response", + resp: nil, + expect: nil, + }, + { + name: "successful response", + resp: &http.Response{ + StatusCode: http.StatusOK, + Request: &http.Request{ + URL: &url.URL{Host: "localhost", Path: "/internal/heathz"}, + }, + Body: io.NopCloser(strings.NewReader("successs")), + }, + expect: nil, + }, + { + name: "failed response", + resp: &http.Response{ + StatusCode: http.StatusInternalServerError, + Request: &http.Request{ + URL: &url.URL{Host: "localhost", Path: "/internal/heathz"}, + }, + Body: io.NopCloser(strings.NewReader("issue trying to connect")), + }, + expect: &ResponseError{ + code: http.StatusInternalServerError, + route: "/internal/heathz", + details: "issue trying to connect", + }, + }, + } { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + assert.Equal(t, tc.expect, newResponseError(tc.resp, http.StatusOK), "Must match the exected value") + }) + } +} + +func TestIsRequestError(t *testing.T) { + t.Parallel() + + for _, tc := range []struct { + name string + err error + expected bool + }{ + { + name: "no error provided", + err: nil, + expected: false, + }, + { + name: "not a request error", + err: errors.New("failed"), + expected: false, + }, + { + name: "is a request error", + err: &ResponseError{}, + expected: true, + }, + { + name: "joined errors", + err: errors.Join(errors.New("boom"), &ResponseError{}), + expected: true, + }, + { + name: "fmt error", + err: fmt.Errorf("check permissions: %w", &ResponseError{}), + expected: true, + }, + } { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + _, ok := AsResponseError(tc.err) + assert.Equal(t, tc.expected, ok, "Must match the expected value") + }) + } +} + +func TestRequestErrorMethods(t *testing.T) { + t.Parallel() + + re := &ResponseError{code: http.StatusOK, route: "/heathz", details: "service alive"} + + assert.Equal(t, 200, re.Code(), "Must match the expected code") + assert.Equal(t, "/heathz", re.Route(), "Must match the expected route") + assert.Equal(t, "service alive", re.Details(), "Must match the expected details") +} diff --git a/gcp_integration.go b/gcp_integration.go index 47d6d3c..2aa8faa 100644 --- a/gcp_integration.go +++ b/gcp_integration.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -20,16 +19,13 @@ func (c *Client) CreateGCPIntegration(ctx context.Context, gcpi *integration.GCP } resp, err := c.doRequest(ctx, "POST", IntegrationAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.GCPIntegration{} @@ -43,16 +39,13 @@ func (c *Client) CreateGCPIntegration(ctx context.Context, gcpi *integration.GCP // GetGCPIntegration retrieves a GCP integration. func (c *Client) GetGCPIntegration(ctx context.Context, id string) (*integration.GCPIntegration, error) { resp, err := c.doRequest(ctx, "GET", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.GCPIntegration{} @@ -71,16 +64,13 @@ func (c *Client) UpdateGCPIntegration(ctx context.Context, id string, gcpi *inte } resp, err := c.doRequest(ctx, "PUT", IntegrationAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.GCPIntegration{} @@ -94,16 +84,13 @@ func (c *Client) UpdateGCPIntegration(ctx context.Context, id string, gcpi *inte // DeleteGCPIntegration deletes a GCP integration. func (c *Client) DeleteGCPIntegration(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) diff --git a/incident.go b/incident.go index 57a6d86..50e8b05 100644 --- a/incident.go +++ b/incident.go @@ -3,7 +3,6 @@ package signalfx import ( "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -19,16 +18,13 @@ const IncidentAPIURL = "/v2/incident" // Get incident with the given id func (c *Client) GetIncident(ctx context.Context, id string) (*detector.Incident, error) { resp, err := c.doRequest(ctx, "GET", IncidentAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIncident := &detector.Incident{} @@ -47,20 +43,14 @@ func (c *Client) GetIncidents(ctx context.Context, includeResolved bool, limit i params.Add("query", query) params.Add("offset", strconv.Itoa(offset)) resp, err := c.doRequest(ctx, "GET", IncidentAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } - if resp.StatusCode != http.StatusOK { - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - return nil, fmt.Errorf(string(body)) - } if err != nil { return nil, err } + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err + } + var incidents []*detector.Incident err = json.NewDecoder(resp.Body).Decode(&incidents) _, _ = io.Copy(ioutil.Discard, resp.Body) diff --git a/integration.go b/integration.go index b96dcb3..a4b7bfa 100644 --- a/integration.go +++ b/integration.go @@ -10,7 +10,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -69,9 +68,8 @@ func (c *Client) doIntegrationRequest(ctx context.Context, url string, method st return err } - if resp.StatusCode != status { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, status); err != nil { + return err } if out != nil { diff --git a/jira_integration.go b/jira_integration.go index 8e6a5f2..545ea0e 100644 --- a/jira_integration.go +++ b/jira_integration.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -20,16 +19,13 @@ func (c *Client) CreateJiraIntegration(ctx context.Context, ji *integration.Jira } resp, err := c.doRequest(ctx, "POST", IntegrationAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.JiraIntegration{} @@ -43,16 +39,13 @@ func (c *Client) CreateJiraIntegration(ctx context.Context, ji *integration.Jira // GetJiraIntegration retrieves an Jira integration. func (c *Client) GetJiraIntegration(ctx context.Context, id string) (*integration.JiraIntegration, error) { resp, err := c.doRequest(ctx, "GET", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.JiraIntegration{} @@ -71,16 +64,13 @@ func (c *Client) UpdateJiraIntegration(ctx context.Context, id string, ji *integ } resp, err := c.doRequest(ctx, "PUT", IntegrationAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.JiraIntegration{} @@ -94,16 +84,13 @@ func (c *Client) UpdateJiraIntegration(ctx context.Context, id string, ji *integ // DeleteJiraIntegration deletes an Jira integration. func (c *Client) DeleteJiraIntegration(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) diff --git a/metric_ruleset.go b/metric_ruleset.go index fe7f140..91d531d 100644 --- a/metric_ruleset.go +++ b/metric_ruleset.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -18,16 +17,13 @@ const MetricRulesetApiURL = "/v2/metricruleset" // GetMetricRuleset gets a metric ruleset. func (c *Client) GetMetricRuleset(ctx context.Context, id string) (*metric_ruleset.GetMetricRulesetResponse, error) { resp, err := c.doRequest(ctx, http.MethodGet, MetricRulesetApiURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } metricRuleset := &metric_ruleset.GetMetricRulesetResponse{} @@ -53,9 +49,8 @@ func (c *Client) CreateMetricRuleset(ctx context.Context, metricRuleset *metric_ return nil, err } - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } createdMetricRuleset := &metric_ruleset.CreateMetricRulesetResponse{} @@ -73,17 +68,13 @@ func (c *Client) UpdateMetricRuleset(ctx context.Context, id string, metricRules } resp, err := c.doRequest(ctx, http.MethodPut, MetricRulesetApiURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } - if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } updatedMetricRuleset := &metric_ruleset.UpdateMetricRulesetResponse{} @@ -96,17 +87,13 @@ func (c *Client) UpdateMetricRuleset(ctx context.Context, id string, metricRules // DeleteMetricRuleset deletes a metric ruleset. func (c *Client) DeleteMetricRuleset(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, http.MethodDelete, MetricRulesetApiURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } - if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } io.Copy(ioutil.Discard, resp.Body) @@ -121,16 +108,13 @@ func (c *Client) GenerateAggregationMetricName(ctx context.Context, generateAggr } resp, err := c.doRequest(ctx, http.MethodPost, MetricRulesetApiURL+"/generateAggregationMetricName", nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return "", err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return "", fmt.Errorf("bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return "", err } respBody, err := ioutil.ReadAll(resp.Body) diff --git a/metrics_metadata.go b/metrics_metadata.go index 341c555..4721b7b 100644 --- a/metrics_metadata.go +++ b/metrics_metadata.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -29,16 +28,13 @@ const TagAPIURL = "/v2/tag" // GetDimension gets a dimension. func (c *Client) GetDimension(ctx context.Context, key string, value string) (*metrics_metadata.Dimension, error) { resp, err := c.doRequest(ctx, "GET", DimensionAPIURL+"/"+key+"/"+value, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDimension := &metrics_metadata.Dimension{} @@ -56,16 +52,13 @@ func (c *Client) UpdateDimension(ctx context.Context, key string, value string, } resp, err := c.doRequest(ctx, "PUT", DimensionAPIURL+"/"+key+"/"+value, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDimension := &metrics_metadata.Dimension{} @@ -87,16 +80,13 @@ func (c *Client) SearchDimension(ctx context.Context, query string, orderBy stri params.Add("offset", strconv.Itoa(offset)) resp, err := c.doRequest(ctx, "GET", DimensionAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalDimensions := &metrics_metadata.DimensionQueryResponseModel{} @@ -118,16 +108,13 @@ func (c *Client) SearchMetric(ctx context.Context, query string, orderBy string, params.Add("offset", strconv.Itoa(offset)) resp, err := c.doRequest(ctx, "GET", MetricAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalMetrics := &metrics_metadata.RetrieveMetricMetadataResponseModel{} @@ -141,16 +128,13 @@ func (c *Client) SearchMetric(ctx context.Context, query string, orderBy string, // GetMetric retrieves a single metric by name. func (c *Client) GetMetric(ctx context.Context, name string) (*metrics_metadata.Metric, error) { resp, err := c.doRequest(ctx, "GET", MetricAPIURL+"/"+name, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalMetric := &metrics_metadata.Metric{} @@ -169,16 +153,13 @@ func (c *Client) CreateUpdateMetric(ctx context.Context, name string, cumr *metr } resp, err := c.doRequest(ctx, "PUT", MetricAPIURL+"/"+name, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalMetric := &metrics_metadata.Metric{} @@ -192,16 +173,13 @@ func (c *Client) CreateUpdateMetric(ctx context.Context, name string, cumr *metr // GetMetricTimeSeries retrieves a metric time series by id. func (c *Client) GetMetricTimeSeries(ctx context.Context, id string) (*metrics_metadata.MetricTimeSeries, error) { resp, err := c.doRequest(ctx, "GET", MetricTimeSeriesAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalMetricTimeSeries := &metrics_metadata.MetricTimeSeries{} @@ -223,16 +201,13 @@ func (c *Client) SearchMetricTimeSeries(ctx context.Context, query string, order params.Add("offset", strconv.Itoa(offset)) resp, err := c.doRequest(ctx, "GET", MetricTimeSeriesAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalMTS := &metrics_metadata.MetricTimeSeriesRetrieveResponseModel{} @@ -254,16 +229,13 @@ func (c *Client) SearchTag(ctx context.Context, query string, orderBy string, li params.Add("offset", strconv.Itoa(offset)) resp, err := c.doRequest(ctx, "GET", TagAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalTags := &metrics_metadata.TagRetrieveResponseModel{} @@ -277,16 +249,13 @@ func (c *Client) SearchTag(ctx context.Context, query string, orderBy string, li // GetTag gets a tag by name func (c *Client) GetTag(ctx context.Context, name string) (*metrics_metadata.Tag, error) { resp, err := c.doRequest(ctx, "GET", TagAPIURL+"/"+name, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalTag := &metrics_metadata.Tag{} @@ -300,16 +269,13 @@ func (c *Client) GetTag(ctx context.Context, name string) (*metrics_metadata.Tag // DeleteTag deletes a tag. func (c *Client) DeleteTag(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", TagAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) @@ -324,16 +290,13 @@ func (c *Client) CreateUpdateTag(ctx context.Context, name string, cutr *metrics } resp, err := c.doRequest(ctx, "PUT", TagAPIURL+"/"+name, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalTag := &metrics_metadata.Tag{} diff --git a/opsgenie_integration.go b/opsgenie_integration.go index b1f8279..579acc7 100644 --- a/opsgenie_integration.go +++ b/opsgenie_integration.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -20,16 +19,13 @@ func (c *Client) CreateOpsgenieIntegration(ctx context.Context, oi *integration. } resp, err := c.doRequest(ctx, "POST", IntegrationAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.OpsgenieIntegration{} @@ -43,16 +39,13 @@ func (c *Client) CreateOpsgenieIntegration(ctx context.Context, oi *integration. // GetOpsgenieIntegration retrieves an Opsgenie integration. func (c *Client) GetOpsgenieIntegration(ctx context.Context, id string) (*integration.OpsgenieIntegration, error) { resp, err := c.doRequest(ctx, "GET", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.OpsgenieIntegration{} @@ -71,16 +64,13 @@ func (c *Client) UpdateOpsgenieIntegration(ctx context.Context, id string, oi *i } resp, err := c.doRequest(ctx, "PUT", IntegrationAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.OpsgenieIntegration{} @@ -94,17 +84,15 @@ func (c *Client) UpdateOpsgenieIntegration(ctx context.Context, id string, oi *i // DeleteOpsgenieIntegration deletes an Opsgenie integration. func (c *Client) DeleteOpsgenieIntegration(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } + _, _ = io.Copy(ioutil.Discard, resp.Body) return err diff --git a/organization.go b/organization.go index 0ef475c..e6945cf 100644 --- a/organization.go +++ b/organization.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -22,16 +21,13 @@ const OrganizationMembersAPIURL = "/v2/organization/members" // GetOrganization gets an organization. func (c *Client) GetOrganization(ctx context.Context, id string) (*organization.Organization, error) { resp, err := c.doRequest(ctx, "GET", OrganizationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalOrganization := &organization.Organization{} @@ -45,16 +41,13 @@ func (c *Client) GetOrganization(ctx context.Context, id string) (*organization. // GetMember gets a member. func (c *Client) GetMember(ctx context.Context, id string) (*organization.Member, error) { resp, err := c.doRequest(ctx, "GET", OrganizationMemberAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalMember := &organization.Member{} @@ -68,16 +61,13 @@ func (c *Client) GetMember(ctx context.Context, id string) (*organization.Member // DeleteMember deletes a detector. func (c *Client) DeleteMember(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", OrganizationMemberAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) @@ -92,16 +82,13 @@ func (c *Client) InviteMember(ctx context.Context, inviteRequest *organization.C } resp, err := c.doRequest(ctx, "POST", OrganizationMemberAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalMember := &organization.Member{} @@ -120,16 +107,13 @@ func (c *Client) UpdateMember(ctx context.Context, id string, updateRequest *org } resp, err := c.doRequest(ctx, "PUT", OrganizationMemberAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalMember := &organization.Member{} @@ -148,16 +132,13 @@ func (c *Client) InviteMembers(ctx context.Context, inviteRequest *organization. } resp, err := c.doRequest(ctx, "POST", OrganizationMembersAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalMembers := &organization.InviteMembersRequest{} @@ -177,16 +158,13 @@ func (c *Client) GetOrganizationMembers(ctx context.Context, limit int, query st params.Add("orderBy", orderBy) resp, err := c.doRequest(ctx, "GET", OrganizationMemberAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalMembers := &organization.MemberSearchResults{} diff --git a/orgtoken.go b/orgtoken.go index 0af0c83..4377047 100644 --- a/orgtoken.go +++ b/orgtoken.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -25,16 +24,13 @@ func (c *Client) CreateOrgToken(ctx context.Context, tokenRequest *orgtoken.Crea } resp, err := c.doRequest(ctx, "POST", TokenAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalToken := &orgtoken.Token{} @@ -49,16 +45,13 @@ func (c *Client) CreateOrgToken(ctx context.Context, tokenRequest *orgtoken.Crea func (c *Client) DeleteOrgToken(ctx context.Context, name string) error { encodedName := url.PathEscape(name) resp, err := c.doRequest(ctx, "DELETE", TokenAPIURL+"/"+encodedName, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) @@ -69,16 +62,13 @@ func (c *Client) DeleteOrgToken(ctx context.Context, name string) error { func (c *Client) GetOrgToken(ctx context.Context, id string) (*orgtoken.Token, error) { encodedName := url.PathEscape(id) resp, err := c.doRequest(ctx, "GET", TokenAPIURL+"/"+encodedName, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalToken := &orgtoken.Token{} @@ -98,16 +88,13 @@ func (c *Client) UpdateOrgToken(ctx context.Context, id string, tokenRequest *or encodedName := url.PathEscape(id) resp, err := c.doRequest(ctx, "PUT", TokenAPIURL+"/"+encodedName, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalToken := &orgtoken.Token{} @@ -126,16 +113,13 @@ func (c *Client) SearchOrgTokens(ctx context.Context, limit int, name string, of params.Add("offset", strconv.Itoa(offset)) resp, err := c.doRequest(ctx, "GET", TokenAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalTokens := &orgtoken.SearchResults{} diff --git a/pagerduty_integration.go b/pagerduty_integration.go index 8616d64..7f9b139 100644 --- a/pagerduty_integration.go +++ b/pagerduty_integration.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -21,16 +20,13 @@ func (c *Client) CreatePagerDutyIntegration(ctx context.Context, pdi *integratio } resp, err := c.doRequest(ctx, "POST", IntegrationAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.PagerDutyIntegration{} @@ -44,16 +40,13 @@ func (c *Client) CreatePagerDutyIntegration(ctx context.Context, pdi *integratio // GetPagerDutyIntegration retrieves a PagerDuty integration. func (c *Client) GetPagerDutyIntegration(ctx context.Context, id string) (*integration.PagerDutyIntegration, error) { resp, err := c.doRequest(ctx, "GET", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.PagerDutyIntegration{} @@ -71,16 +64,13 @@ func (c *Client) GetPagerDutyIntegrationByName(ctx context.Context, name string) params.Add("name", name) resp, err := c.doRequest(ctx, "GET", IntegrationAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } integrationList := integration.PagerDutyIntegrationList{} @@ -109,16 +99,13 @@ func (c *Client) UpdatePagerDutyIntegration(ctx context.Context, id string, pdi } resp, err := c.doRequest(ctx, "PUT", IntegrationAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.PagerDutyIntegration{} @@ -132,16 +119,13 @@ func (c *Client) UpdatePagerDutyIntegration(ctx context.Context, id string, pdi // DeletePagerDutyIntegration deletes a PagerDuty integration. func (c *Client) DeletePagerDutyIntegration(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) diff --git a/sessiontoken.go b/sessiontoken.go index 55e02a2..f42d9f8 100644 --- a/sessiontoken.go +++ b/sessiontoken.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -25,16 +24,13 @@ func (c *Client) CreateSessionToken(ctx context.Context, tokenRequest *sessionto // we need to explicitly pass an empty token (which means it wont get set in the header) // the API accepts either no token or a valid token, but not an empty token. resp, err := c.doRequestWithToken(ctx, "POST", SessionTokenAPIURL, nil, bytes.NewReader(payload), "") - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } sessionToken := &sessiontoken.Token{} @@ -48,16 +44,13 @@ func (c *Client) CreateSessionToken(ctx context.Context, tokenRequest *sessionto // DeleteOrgToken deletes a token. func (c *Client) DeleteSessionToken(ctx context.Context, token string) error { resp, err := c.doRequestWithToken(ctx, "DELETE", SessionTokenAPIURL, nil, nil, token) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) diff --git a/slack_integration.go b/slack_integration.go index c165280..332e731 100644 --- a/slack_integration.go +++ b/slack_integration.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -20,16 +19,13 @@ func (c *Client) CreateSlackIntegration(ctx context.Context, si *integration.Sla } resp, err := c.doRequest(ctx, "POST", IntegrationAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.SlackIntegration{} @@ -43,16 +39,13 @@ func (c *Client) CreateSlackIntegration(ctx context.Context, si *integration.Sla // GetSlackIntegration retrieves a Slack integration. func (c *Client) GetSlackIntegration(ctx context.Context, id string) (*integration.SlackIntegration, error) { resp, err := c.doRequest(ctx, "GET", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.SlackIntegration{} @@ -71,16 +64,13 @@ func (c *Client) UpdateSlackIntegration(ctx context.Context, id string, si *inte } resp, err := c.doRequest(ctx, "PUT", IntegrationAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.SlackIntegration{} @@ -94,16 +84,13 @@ func (c *Client) UpdateSlackIntegration(ctx context.Context, id string, si *inte // DeleteSlackIntegration deletes a Slack integration. func (c *Client) DeleteSlackIntegration(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) diff --git a/slo.go b/slo.go index 1f763ef..e90bec9 100644 --- a/slo.go +++ b/slo.go @@ -4,10 +4,10 @@ import ( "bytes" "context" "encoding/json" - "fmt" - "github.com/signalfx/signalfx-go/slo" "io" "net/http" + + "github.com/signalfx/signalfx-go/slo" ) const SloAPIURL = "/v2/slo" @@ -47,17 +47,13 @@ func (c *Client) executeSloRequest(ctx context.Context, url string, method strin } resp, err := c.doRequest(ctx, method, url, nil, body) - if resp != nil { - defer resp.Body.Close() - } - if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != expectedValidStatus { - message, _ := io.ReadAll(resp.Body) - return nil, fmt.Errorf("Bad status %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, expectedValidStatus); err != nil { + return nil, err } if resp.Body != nil { diff --git a/team.go b/team.go index e8adcb7..9cd44dd 100644 --- a/team.go +++ b/team.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "errors" "fmt" "io" "io/ioutil" @@ -26,16 +25,13 @@ func (c *Client) CreateTeam(ctx context.Context, t *team.CreateUpdateTeamRequest } resp, err := c.doRequest(ctx, "POST", TeamAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalTeam := &team.Team{} @@ -49,15 +45,13 @@ func (c *Client) CreateTeam(ctx context.Context, t *team.CreateUpdateTeamRequest // DeleteTeam deletes a team. func (c *Client) DeleteTeam(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", TeamAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - return errors.New("Unexpected status code: " + resp.Status) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) @@ -67,15 +61,13 @@ func (c *Client) DeleteTeam(ctx context.Context, id string) error { // GetTeam gets a team. func (c *Client) GetTeam(ctx context.Context, id string) (*team.Team, error) { resp, err := c.doRequest(ctx, "GET", TeamAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + defer resp.Body.Close() + + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalTeam := &team.Team{} @@ -94,15 +86,13 @@ func (c *Client) UpdateTeam(ctx context.Context, id string, t *team.CreateUpdate } resp, err := c.doRequest(ctx, "PUT", TeamAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + defer resp.Body.Close() + + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalTeam := &team.Team{} @@ -122,16 +112,13 @@ func (c *Client) SearchTeam(ctx context.Context, limit int, name string, offset params.Add("tags", tags) resp, err := c.doRequest(ctx, "GET", TeamAPIURL, params, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalTeams := &team.SearchResults{} @@ -147,16 +134,13 @@ func (c *Client) LinkDetectorToTeam(ctx context.Context, id string, detectorID s targetURL := fmt.Sprintf("%s/%s/detector/%s", TeamAPIURL, id, detectorID) resp, err := c.doRequest(ctx, "POST", targetURL, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } return nil @@ -167,16 +151,13 @@ func (c *Client) UnlinkDetectorFromTeam(ctx context.Context, id string, detector targetURL := fmt.Sprintf("%s/%s/detector/%s", TeamAPIURL, id, detectorID) resp, err := c.doRequest(ctx, "DELETE", targetURL, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } return nil @@ -186,17 +167,13 @@ func (c *Client) UnlinkDetectorFromTeam(ctx context.Context, id string, detector func (c *Client) LinkDashboardGroupToTeam(ctx context.Context, id string, dashboardGroupID string) error { targetURL := fmt.Sprintf("%s/%s/dashboardgroup/%s", TeamAPIURL, id, dashboardGroupID) resp, err := c.doRequest(ctx, "POST", targetURL, nil, nil) - - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } return nil @@ -207,16 +184,13 @@ func (c *Client) UnlinkDashboardGroupFromTeam(ctx context.Context, id string, da targetURL := fmt.Sprintf("%s/%s/dashboardgroup/%s", TeamAPIURL, id, dashboardGroupID) resp, err := c.doRequest(ctx, "DELETE", targetURL, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } return nil diff --git a/victor_ops_integration.go b/victor_ops_integration.go index 76ae13e..9d1987c 100644 --- a/victor_ops_integration.go +++ b/victor_ops_integration.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -20,16 +19,13 @@ func (c *Client) CreateVictorOpsIntegration(ctx context.Context, oi *integration } resp, err := c.doRequest(ctx, "POST", IntegrationAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.VictorOpsIntegration{} @@ -43,16 +39,13 @@ func (c *Client) CreateVictorOpsIntegration(ctx context.Context, oi *integration // GetVictorOpsIntegration retrieves an VictorOps integration. func (c *Client) GetVictorOpsIntegration(ctx context.Context, id string) (*integration.VictorOpsIntegration, error) { resp, err := c.doRequest(ctx, "GET", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.VictorOpsIntegration{} @@ -71,16 +64,13 @@ func (c *Client) UpdateVictorOpsIntegration(ctx context.Context, id string, oi * } resp, err := c.doRequest(ctx, "PUT", IntegrationAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.VictorOpsIntegration{} @@ -94,16 +84,13 @@ func (c *Client) UpdateVictorOpsIntegration(ctx context.Context, id string, oi * // DeleteVictorOpsIntegration deletes an VictorOps integration. func (c *Client) DeleteVictorOpsIntegration(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body) diff --git a/webhook_integration.go b/webhook_integration.go index 8fbb250..84876a5 100644 --- a/webhook_integration.go +++ b/webhook_integration.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -20,16 +19,13 @@ func (c *Client) CreateWebhookIntegration(ctx context.Context, oi *integration.W } resp, err := c.doRequest(ctx, "POST", IntegrationAPIURL, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.WebhookIntegration{} @@ -43,16 +39,13 @@ func (c *Client) CreateWebhookIntegration(ctx context.Context, oi *integration.W // GetWebhookIntegration retrieves an Webhook integration. func (c *Client) GetWebhookIntegration(ctx context.Context, id string) (*integration.WebhookIntegration, error) { resp, err := c.doRequest(ctx, "GET", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.WebhookIntegration{} @@ -71,16 +64,13 @@ func (c *Client) UpdateWebhookIntegration(ctx context.Context, id string, oi *in } resp, err := c.doRequest(ctx, "PUT", IntegrationAPIURL+"/"+id, nil, bytes.NewReader(payload)) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return nil, err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - message, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusOK); err != nil { + return nil, err } finalIntegration := integration.WebhookIntegration{} @@ -94,16 +84,13 @@ func (c *Client) UpdateWebhookIntegration(ctx context.Context, id string, oi *in // DeleteWebhookIntegration deletes an Webhook integration. func (c *Client) DeleteWebhookIntegration(ctx context.Context, id string) error { resp, err := c.doRequest(ctx, "DELETE", IntegrationAPIURL+"/"+id, nil, nil) - if resp != nil { - defer resp.Body.Close() - } if err != nil { return err } + defer resp.Body.Close() - if resp.StatusCode != http.StatusNoContent { - message, _ := ioutil.ReadAll(resp.Body) - return fmt.Errorf("Unexpected status code: %d: %s", resp.StatusCode, message) + if err = newResponseError(resp, http.StatusNoContent); err != nil { + return err } _, _ = io.Copy(ioutil.Discard, resp.Body)