Skip to content

Commit

Permalink
add support for alerting API
Browse files Browse the repository at this point in the history
This addresses issue nytm#54.

It should be noted that it builds on top of PR nytm#51, which should probably
be reviewed and, ideally, merged first, assuming PR nytm#51 is approved.
  • Loading branch information
mdb committed Jun 7, 2020
1 parent 0f467ed commit 204577e
Show file tree
Hide file tree
Showing 4 changed files with 265 additions and 0 deletions.
22 changes: 22 additions & 0 deletions admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ import (
"fmt"
)

// PauseAllAlertsResponse represents the response body for a PauseAllAlerts request.
type PauseAllAlertsResponse struct {
AlertsAffected int64 `json:"alertsAffected,omitempty"`
State string `json:"state,omitempty"`
Message string `json:"message,omitempty"`
}

// CreateUser creates a Grafana user.
func (c *Client) CreateUser(user User) (int64, error) {
id := int64(0)
Expand All @@ -30,3 +37,18 @@ func (c *Client) CreateUser(user User) (int64, error) {
func (c *Client) DeleteUser(id int64) error {
return c.request("DELETE", fmt.Sprintf("/api/admin/users/%d", id), nil, nil, nil)
}

// PauseAllAlerts pauses all Grafana alerts.
func (c *Client) PauseAllAlerts() (PauseAllAlertsResponse, error) {
result := PauseAllAlertsResponse{}
data, err := json.Marshal(PauseAlertRequest{
Paused: true,
})
if err != nil {
return result, err
}

err = c.request("POST", "/api/admin/pause-all-alerts", nil, bytes.NewBuffer(data), &result)

return result, err
}
35 changes: 35 additions & 0 deletions admin_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
package gapi

import (
"strings"
"testing"

"github.com/gobs/pretty"
)

const (
createUserJSON = `{"id":1,"message":"User created"}`
deleteUserJSON = `{"message":"User deleted"}`

pauseAllAlertsJSON = `{
"alertsAffected": 1,
"state": "Paused",
"message": "alert paused"
}`
)

func TestCreateUser(t *testing.T) {
Expand Down Expand Up @@ -37,3 +46,29 @@ func TestDeleteUser(t *testing.T) {
t.Error(err)
}
}

func TestPauseAllAlerts(t *testing.T) {
server, client := gapiTestTools(200, pauseAllAlertsJSON)
defer server.Close()

res, err := client.PauseAllAlerts()
if err != nil {
t.Error(err)
}

t.Log(pretty.PrettyFormat(res))

if res.State != "Paused" {
t.Error("pause all alerts response should contain the correct response message")
}
}

func TestPauseAllAlerts_500(t *testing.T) {
server, client := gapiTestTools(500, pauseAllAlertsJSON)
defer server.Close()

_, err := client.PauseAllAlerts()
if !strings.Contains(err.Error(), "status: 500") {
t.Errorf("expected error to contain 'status: 500'; got: %s", err.Error())
}
}
77 changes: 77 additions & 0 deletions alert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
"net/url"
)

// Alert represents a Grafana API Alert
type Alert struct {
ID int64 `json:"id,omitempty"`
DashboardID int64 `json:"dashboardId,omitempty"`
DashboardUID string `json:"dashboardUid,omitempty"`
DashboardSlug string `json:"dashboardSlug,omitempty"`
PanelID int64 `json:"panelId,omitempty"`
Name string `json:"name,omitempty"`
State string `json:"state,omitempty"`
NewStateDate string `json:"newStateDate,omitempty"`
EvalDate string `json:"evalDate,omitempty"`
ExecutionError string `json:"executionError,omitempty"`
URL string `json:"url,omitempty"`
}

// PauseAlertRequest represents the request payload for a PauseAlert request.
type PauseAlertRequest struct {
Paused bool `json:"paused"`
}

// PauseAlertResponse represents the response body for a PauseAlert request.
type PauseAlertResponse struct {
AlertID int64 `json:"alertId,omitempty"`
State string `json:"state,omitempty"`
Message string `json:"message,omitempty"`
}

// Alerts fetches the annotations queried with the params it's passed.
func (c *Client) Alerts(params url.Values) ([]Alert, error) {
result := []Alert{}
err := c.request("GET", "/api/alerts", params, nil, &result)
if err != nil {
return nil, err
}

return result, err
}

// Alert fetches and returns an individual Grafana alert.
func (c *Client) Alert(id int64) (Alert, error) {
path := fmt.Sprintf("/api/alerts/%d", id)
result := Alert{}
err := c.request("GET", path, nil, nil, &result)
if err != nil {
return result, err
}

return result, err
}

// PauseAlert pauses the Grafana alert whose ID it's passed.
func (c *Client) PauseAlert(id int64) (PauseAlertResponse, error) {
path := fmt.Sprintf("/api/alerts/%d", id)
result := PauseAlertResponse{}
data, err := json.Marshal(PauseAlertRequest{
Paused: true,
})
if err != nil {
return result, err
}

err = c.request("POST", path, nil, bytes.NewBuffer(data), &result)
if err != nil {
return result, err
}

return result, err
}
131 changes: 131 additions & 0 deletions alert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package gapi

import (
"net/url"
"strings"
"testing"

"github.com/gobs/pretty"
)

const (
alertsJSON = `[{
"id": 1,
"dashboardId": 1,
"dashboardUId": "ABcdEFghij",
"dashboardSlug": "sensors",
"panelId": 1,
"name": "fire place sensor",
"state": "alerting",
"newStateDate": "2018-05-14T05:55:20+02:00",
"evalDate": "0001-01-01T00:00:00Z",
"evalData": null,
"executionError": "",
"url": "http://grafana.com/dashboard/db/sensors"
}]`

alertJSON = `{
"id": 1,
"dashboardId": 1,
"dashboardUId": "ABcdEFghij",
"dashboardSlug": "sensors",
"panelId": 1,
"name": "fire place sensor",
"state": "alerting",
"message": "Someone is trying to break in through the fire place",
"newStateDate": "2018-05-14T05:55:20+02:00",
"evalDate": "0001-01-01T00:00:00Z",
"executionError": "",
"url": "http://grafana.com/dashboard/db/sensors"
}`

pauseAlertJSON = `{
"alertId": 1,
"state": "Paused",
"message": "alert paused"
}`
)

func TestAlerts(t *testing.T) {
server, client := gapiTestTools(200, alertsJSON)
defer server.Close()

params := url.Values{}
params.Add("dashboardId", "123")

as, err := client.Alerts(params)
if err != nil {
t.Error(err)
}

t.Log(pretty.PrettyFormat(as))

if as[0].ID != 1 {
t.Error("alerts response should contain alerts with an ID")
}
}

func TestAlerts_500(t *testing.T) {
server, client := gapiTestTools(500, alertsJSON)
defer server.Close()

params := url.Values{}
params.Add("dashboardId", "123")

_, err := client.Alerts(params)
if !strings.Contains(err.Error(), "status: 500") {
t.Errorf("expected error to contain 'status: 500'; got: %s", err.Error())
}
}

func TestAlert(t *testing.T) {
server, client := gapiTestTools(200, alertJSON)
defer server.Close()

res, err := client.Alert(1)
if err != nil {
t.Error(err)
}

t.Log(pretty.PrettyFormat(res))

if res.ID != 1 {
t.Error("alert response should contain the ID of the queried alert")
}
}

func TestAlert_500(t *testing.T) {
server, client := gapiTestTools(500, alertJSON)
defer server.Close()

_, err := client.Alert(1)
if !strings.Contains(err.Error(), "status: 500") {
t.Errorf("expected error to contain 'status: 500'; got: %s", err.Error())
}
}

func TestPauseAlert(t *testing.T) {
server, client := gapiTestTools(200, pauseAlertJSON)
defer server.Close()

res, err := client.PauseAlert(1)
if err != nil {
t.Error(err)
}

t.Log(pretty.PrettyFormat(res))

if res.State != "Paused" {
t.Error("pause alert response should contain the correct response message")
}
}

func TestPauseAlert_500(t *testing.T) {
server, client := gapiTestTools(500, pauseAlertJSON)
defer server.Close()

_, err := client.PauseAlert(1)
if !strings.Contains(err.Error(), "status: 500") {
t.Errorf("expected error to contain 'status: 500'; got: %s", err.Error())
}
}

0 comments on commit 204577e

Please sign in to comment.